001: package org.jibx.binding.generator;
002:
003: import org.jibx.binding.model.MappingElement;
004: import org.jibx.runtime.QName;
005:
006: /**
007: * Holder for the details of how a mapping is to be represented in a schema.
008: * Each mapping is converted to a complex type, but the complex type may be
009: * either global or local to a containing global element. In the case of a
010: * mapping used as the base for one or more extension types, both a global
011: * complex type and a global element that references the type are required.
012: * This also tracks the content form for the complex type definition.
013: *
014: * Should the binding representation of polymorphism use both abstract mappings
015: * with type names, and concrete mappings with element names that reference the
016: * abstract mapping? Then use two complete separate hierarchies? But in order to
017: * do the
018: *
019: * book ----\
020: * -----item
021: * dvd -----/
022: *
023: * So the concrete <mapping> for book extends the concrete mapping for item, as
024: * does the concrete mapping for dvd. If book is not extended, there's no need
025: * to have a separate BookType. There is the need for a separate abstract
026: * mapping for ItemType, which the concrete mapping for item then uses. On the
027: * other hand, the way I've changed the code to work there's no need have any
028: * additional mappings - the book and dvd mappings can each just invoke the item
029: * mapping directly.
030: *
031: * Now what if I want to extend the book mapping? So I have an arts book type
032: * that adds more details, say the number of plates. Ideally, I'd like to have
033: * the artBook mapping extend the concrete book mapping. But then how do I
034: * distinguish between the artBook <struct map-as='book'/> and the reference to
035: * a book that's meant to be a <book> element? Here's the logical structure of
036: * what I want:
037: *
038: * book --\
039: * artBook ---------- BookType ---\
040: * ----- ItemType
041: * dvd -----/
042: *
043: * But the extends structure is:
044: *
045: * artBook ---------- book ---\
046: * ----- item
047: * dvd -----/
048: *
049: * Should the BookType abstract mapping in the top diagram extend ItemType? I
050: * don't think that's necessary, as long as the first component of the BookType
051: * definition is a structure reference to ItemType.
052: *
053: * So concrete <mapping>s can be extended to represent substitution groups. If
054: * the base of a <mapping> extension is an abstract <mapping>, I'll add an
055: * abstract element definition for that <mapping> just to serve as a base for
056: * the substitution group. Abstract <mapping> extensions in the future can be
057: * used for type substitution, but that requires named types for the whol
058: * hierarchy.
059: *
060: * If I do it this way, there's no need to allow for names on abstract mappings,
061: * and each abstract mapping corresponds directly to a complexType while each
062: * concrete mapping corresponds directly to an element. Note that the extends
063: * relationship between <mapping> elements may or may not carry over to the
064: * schema; if a <mapping> uses extends='...' but doesn't have the structure
065: * reference to the extended type as the first component, or if the reference
066: * uses a name, the extends relationship cannot go into the schema and the user
067: * should get a warning. On the other hand, if the first component is a
068: * structure reference to a <mapping> with no name, this should be reflected in
069: * the schame as an extends relationship for the complexTypes. <mapping>s which
070: * are used as groups of elements and/or attributes should be modeled in the
071: * schema as <group>s and <attributeGroup>s.
072: *
073: * What about customizations for schema generation? It seems like this would be
074: * very useful, but the issue here is that the structure doesn't match the form
075: * of the customizations used for going from Java (class-structured). I'd
076: * instead want to make schema customizations follow the structure of a binding
077: * definition.
078: *
079: * Can I just generate the schema components on-demand? That would mean a first
080: * pass to generate these details, and a second pass which actually triggered
081: * the generation process. But then I might also need a third pass, etc. I
082: * suppose the best is to do a sort of modified on-demand, where I generate the
083: * default equivalent directly
084: */
085: public class SchemaMappingDetail {
086: /** Mapping to be generated. */
087: private final MappingElement m_mapping;
088:
089: /** Schema type extension base mapping. */
090: private final MappingElement m_extensionBase;
091:
092: /** Has child element(s) flag. */
093: private final boolean m_hasChild;
094:
095: /** Has child text(s) flag. */
096: private final boolean m_hasText;
097:
098: /** Has attribute(s) flag. */
099: private final boolean m_hasAttribute;
100:
101: /** Type name (ignored if not generated as complex type). */
102: private final QName m_typeName;
103:
104: /** Element/group/attributeGroup name (ignored if not generated as any of
105: these). */
106: private final QName m_otherName;
107:
108: /** Substitution group base name. */
109: private QName m_substitutionName;
110:
111: /** Generate as complex type flag. */
112: private boolean m_isType;
113:
114: /** Generate as element flag. */
115: private boolean m_isElement;
116:
117: /** Generate as group/attributeGroup flag. If set, will be generated as
118: either a group (if elements defined), an attributeGroup (if attributes
119: defined), or both. */
120: private boolean m_isGroup;
121:
122: /**
123: * Constructor.
124: *
125: * @param map mapping definition
126: * @param haschild has child element(s) flag
127: * @param hastext has child text(s) flag
128: * @param base base mapping for schema type extension
129: * @param tname name as type
130: * @param oname name as element/group/attributeGroup
131: */
132: public SchemaMappingDetail(MappingElement map, boolean haschild,
133: boolean hastext, MappingElement base, QName tname,
134: QName oname) {
135: m_mapping = map;
136: m_extensionBase = base;
137: m_hasChild = haschild;
138: m_hasText = hastext;
139: m_hasAttribute = map.getAttributeComponents().size() > 0;
140: m_typeName = tname;
141: m_otherName = oname;
142: if (map.isAbstract() && map.getTypeName() != null) {
143: m_isType = true;
144: } else if (!map.isAbstract()) {
145: m_isElement = true;
146: }
147: }
148:
149: /**
150: * Check if generating as an element.
151: *
152: * @return flag
153: */
154: public boolean isElement() {
155: return m_isElement;
156: }
157:
158: /**
159: * Set generating as an element.
160: *
161: * @param gen
162: */
163: public void setElement(boolean gen) {
164: m_isElement = gen;
165: }
166:
167: /**
168: * Check if generating as a group.
169: *
170: * @return flag
171: */
172: public boolean isGroup() {
173: return m_isGroup;
174: }
175:
176: /**
177: * Set generating as a group.
178: *
179: * @param gen
180: */
181: public void setGroup(boolean gen) {
182: m_isGroup = gen;
183: }
184:
185: /**
186: * Check if generating as a group.
187: *
188: * @return flag
189: */
190: public boolean isType() {
191: return m_isType;
192: }
193:
194: /**
195: * Set generating as a type.
196: *
197: * @param gen
198: */
199: public void setType(boolean gen) {
200: m_isType = gen;
201: }
202:
203: /**
204: * Get base mapping for schema type extension.
205: *
206: * @return extension base
207: */
208: public MappingElement getExtensionBase() {
209: return m_extensionBase;
210: }
211:
212: /**
213: * Check if attribute component present.
214: *
215: * @return flag
216: */
217: public boolean hasAttribute() {
218: return m_hasAttribute;
219: }
220:
221: /**
222: * Check if child element component present.
223: *
224: * @return flag
225: */
226: public boolean hasChild() {
227: return m_hasChild;
228: }
229:
230: /**
231: * Check if text component present.
232: *
233: * @return flag
234: */
235: public boolean hasText() {
236: return m_hasText;
237: }
238:
239: /**
240: * Get mapping.
241: *
242: * @return mapping
243: */
244: public MappingElement getMapping() {
245: return m_mapping;
246: }
247:
248: /**
249: * Get name for type.
250: *
251: * @return name
252: */
253: public QName getTypeName() {
254: return m_typeName;
255: }
256:
257: /**
258: * Get element name.
259: *
260: * @return element name for concrete mapping (<code>null</code> if abstract)
261: */
262: public QName getOtherName() {
263: return m_otherName;
264: }
265:
266: /**
267: * Get substitution group base name.
268: *
269: * @return substitution group base name
270: */
271: public QName getSubstitution() {
272: return m_substitutionName;
273: }
274:
275: /**
276: * Set substitution group base name.
277: *
278: * @param qname
279: */
280: public void setSubstitution(QName qname) {
281: m_substitutionName = qname;
282: }
283: }
|