// set up for binding generation alternatives
ParentNode subparent = (ParentNode)child;
boolean empty = subparent.getChildren().size() == 0;
boolean recurse = true;
ContainerElementBase wrapcomp = bindcomp;
StructureElementBase newcomp = null;
QName newname = null;
boolean newopt = false;
if (subparent.isCollection() && !empty) {
// always create a new <collection> element for the binding to match a collection parent node
CollectionElement collect = newCollection(wrapname, wrapopt, holder, subparent);
wrapcomp.addChild(collect);
newcomp = collect;
newname = subparent.getQName();
} else {
// check for wrapper <structure> element needed (with nested name, or multiple values, or all)
boolean all = item.getSchemaComponent().type() == SchemaBase.ALL_TYPE;
boolean multi = subparent.getChildren().size() > 1;
if ((wrapname != null && (subparent.isNamed() || multi)) || (all && multi)) {
StructureElement struct = new StructureElement();
struct.setOrdered(!all);
setName(wrapname, holder, struct);
if (wrapopt) {
struct.setUsage(PropertyAttributes.OPTIONAL_USAGE);
}
wrapcomp.addChild(struct);
wrapcomp = struct;
if (!empty && bindcomp.type() == ElementBase.COLLECTION_ELEMENT &&
getSchemaCustom().getRepeatType() != SchemaRootBase.REPEAT_ARRAY) {
// dig into child node(s) to find the item type
DataNode nested = subparent;
String type = null;
while (((ParentNode)nested).getChildren().size() > 0) {
nested = (DataNode)((ParentNode)nested).getChildren().get(0);
if (nested.isCollection() || nested instanceof LeafNode) {
type = nested.getBindingType();
break;
}
}
struct.setDeclaredType(type);
}
} else {
newname = wrapname;
newopt = wrapopt;
}
// check for name associated with this node
if (subparent.isNamed()) {
// check if this is an attribute
AnnotatedBase comp = item.getSchemaComponent();
if (comp.type() == SchemaBase.ATTRIBUTE_TYPE) {
// handle attribute with embedded definition
ValueElement value = new ValueElement();
value.setEffectiveStyle(NestingAttributes.ATTRIBUTE_STYLE);
setName(subparent.getQName(), holder, value);
DataNode nested = subparent;
while ((nested = (DataNode)((ParentNode)nested).getChildren().get(0)).isInterior());
value.setGetName(((LeafNode)nested).getGetMethodName());
value.setSetName(((LeafNode)nested).getSetMethodName());
setValueHandlingOptions(item, value, holder);
wrapcomp.addChild(value);
if (SchemaUtils.isOptionalAttribute((AttributeElement)comp)) {
value.setUsage(PropertyAttributes.OPTIONAL_USAGE);
}
if (nested.isList()) {
String nestname = nested.getPropName();
value.setSerializerName(getBindingName() + '.' + LIST_SERIALIZE_PREFIX + nestname);
value.setDeserializerName(getBindingName() + '.' + LIST_DESERIALIZE_PREFIX + nestname);
} else if (getSchemaCustom().isForceTypes()) {
value.setDeclaredType(nested.getBindingType());
}
recurse = false;
} else if (subparent.getChildren().size() == 1) {
// wrapper for an embedded structure or value, just pass name
newname = subparent.getQName();
newopt = subparent.isOptional();
} else {
// create a <structure> element, using the name supplied
StructureElement struct = new StructureElement();
setName(subparent.getQName(), holder, struct);
wrapcomp.addChild(struct);
newcomp = struct;
newname = null;
newopt = false;
}
}
}
// set 'if' method and optional if inside a choice
if (parent.isSelectorNeeded()) {
if (newcomp == null) {
newcomp = new StructureElement();
setName(newname, holder, newcomp);
newname = null;
wrapcomp.addChild(newcomp);
}
newcomp.setTestName("if" + child.getSelectPropName());
newcomp.setUsage(PropertyAttributes.OPTIONAL_USAGE);
newopt = false;
}
// handle parent with no children as flag-only value
if (empty) {
// make sure there's a structure element
StructureElementBase struct = newcomp;
if (struct == null) {
// create a <structure> element, using the wrapping name supplied
if (newname == null) {
throw new IllegalStateException("Internal error - no wrapping name for empty structure");
} else {
struct = new StructureElement();
setName(newname, holder, struct);
wrapcomp.addChild(struct);
newcomp = struct;
}
}
// set flag and test methods on structure
struct.setFlagName(subparent.getFlagMethodName());
struct.setTestName(subparent.getTestMethodName());
setStructureOptional(subparent, newopt, struct);
} else {
// add choice handling for this structure
if (subparent.isSelectorNeeded()) {
if (newcomp == null) {
newcomp = new StructureElement();
setStructureOptional(subparent, false, newcomp);
wrapcomp.addChild(newcomp);
}
newcomp.setChoice(true);
newcomp.setOrdered(false);
}
// check for new binding component created for this node
if (recurse) {
if (newcomp == null) {
addToBinding(subparent, newname, newopt, single && children.size() == 1, wrapcomp, holder);
} else {
newcomp.setGetName(subparent.getGetMethodName());
newcomp.setSetName(subparent.getSetMethodName());
if (getSchemaCustom().isForceTypes()) {
newcomp.setDeclaredType(subparent.getBindingType());
}
addToBinding(subparent, newname, newopt, true, newcomp, holder);
}
}
}
} else {
LeafNode leaf = (LeafNode)child;
String gname = leaf.getGetMethodName();
String sname = leaf.getSetMethodName();
if (leaf.isAny()) {
// add structure binding with details determined by xs:any handling
int anytype = item.getComponentExtension().getAnyType();
StructureElementBase struct = (leaf.isCollection() && anytype != NestingCustomBase.ANY_DOM) ?
(StructureElementBase)new CollectionElement() : (StructureElementBase)new StructureElement();
String mapper;
switch (anytype) {
case NestingCustomBase.ANY_DISCARD:
// use discard mapper to skip past arbitrary element(s) when unmarshalling
mapper = leaf.isCollection() ? "org.jibx.extras.DiscardListMapper" :
"org.jibx.extras.DiscardElementMapper";
struct.setDeclaredType("java.lang.Object");
gname = sname = null;
break;
case NestingCustomBase.ANY_DOM:
// use DOM mapper to marshal/unmarshal arbitrary element(s)
mapper = leaf.isCollection() ? "org.jibx.extras.DomListMapper" :
"org.jibx.extras.DomElementMapper";
break;
case NestingCustomBase.ANY_MAPPED:
// create item <structure> child for case of list, otherwise just handle directly
mapper = null;
if (leaf.isCollection()) {
StructureElement itemstruct = new StructureElement();
itemstruct.setDeclaredType("java.lang.Object");
struct.addChild(itemstruct);
struct.setCreateType(m_listImplClass);
}
break;
default:
throw new IllegalStateException("Internal error - unknown xs:any handling");
}
if (leaf.isOptional()) {
struct.setUsage(PropertyAttributes.OPTIONAL_USAGE);
}
struct.setGetName(gname);
struct.setSetName(sname);
struct.setMarshallerName(mapper);
struct.setUnmarshallerName(mapper);
bindcomp.addChild(struct);
} else {
// set the names to be used for value
if (leaf.isCollection() || leaf.isList()) {
// process list and collection differently for binding
if (leaf.isCollection()) {
// create a new collection element
CollectionElement collect = newCollection(wrapname, wrapopt, holder, leaf);
bindcomp.addChild(collect);
// fill in the collection details
collect.setGetName(gname);
collect.setSetName(sname);
if (parent.isSelectorNeeded()) {
collect.setUsage(PropertyAttributes.OPTIONAL_USAGE);
collect.setTestName("if" + leaf.getSelectPropName());
}
int reptype = getSchemaCustom().getRepeatType();
if (reptype == SchemaRootBase.REPEAT_LIST || reptype == SchemaRootBase.REPEAT_TYPED) {
collect.setCreateType(m_listImplClass);
if (gname == null) {
collect.setDeclaredType(COLLECTION_VARIABLE_TYPE);
}
}
// check the content (if any) for <collection>
boolean usevalue = true;
String usetype = leaf.getType();
if (item instanceof ReferenceItem) {
DefinitionItem def = ((ReferenceItem)item).getDefinition();
TypeData defclas = def.getGenerateClass();
if (defclas.isSimpleValue()) {
usetype = defclas.getBindingName();
} else {
// reference to mapped class, configure <collection> to handle it properly
usevalue = false;
if (def.getSchemaComponent().type() == SchemaBase.ELEMENT_TYPE) {
// must be a non-abstract <mapping>, so use it directly
collect.setItemTypeName(defclas.getBindingName());
} else {
// abstract mapping reference, create child <structure> with map-as type
StructureElement struct = new StructureElement();
QName qname = def.getQName();
String uri = qname.getUri();
if (uri != null) {
holder.addTypeNameReference(uri, def.getSchemaComponent().getSchema());
}
struct.setMapAsQName(qname);
if (leaf.isNamed()) {
setName(leaf.getQName(), holder, struct);
}
collect.addChild(struct);
}
}
} else if (item instanceof GroupItem) {
// handle group directly if a structure class, else just as <value>
TypeData groupclas = ((GroupItem)item).getGenerateClass();
if (groupclas.isSimpleValue()) {
usetype = groupclas.getBindingName();
} else {
// add <structure> element to be filled in by inner class generation
usevalue = false;
StructureClassHolder classholder = ((StructureClassHolder)groupclas);
StructureElement struct = new StructureElement();
struct.setDeclaredType(classholder.getBindingName());
setName(leaf.getQName(), holder, struct);
// set component for dependent class generation
classholder.setBinding(struct);
collect.addChild(struct);
}
}
if (usevalue) {
// add <value> element to collection for simple (primitive or text) value
ValueElement value = new ValueElement();
value.setEffectiveStyle(NestingAttributes.ELEMENT_STYLE);
if (leaf.isNamed()) {
setName(leaf.getQName(), holder, value);
}
setValueHandlingOptions(item, value, holder);
value.setDeclaredType(usetype);
collect.addChild(value);
}
} else {
// handle list serialization and deserialization directly
ValueElement value = buildValueBinding(leaf, null, gname, sname, holder);
value.setSerializerName(getBindingName() + '.' + LIST_SERIALIZE_PREFIX + propname);
value.setDeserializerName(getBindingName() + '.' + LIST_DESERIALIZE_PREFIX + propname);
bindcomp.addChild(value);
}
} else {
// add <structure> wrapper if name passed in with name on value
ContainerElementBase contain = bindcomp;
boolean consing = single && children.size() == 1;
if (wrapname != null && (leaf.isNamed() || leaf.isReference())) {
StructureElement struct = new StructureElement();
setName(wrapname, holder, struct);
String type = leaf.getBindingType();
if (gname == null) {
struct.setDeclaredType(type);
} else if (!Types.isSimpleValue(type)) {
// apply access methods to wrapper only if this is a complex value
struct.setGetName(gname);
struct.setSetName(sname);
gname = sname = null;
if (getSchemaCustom().isForceTypes()) {
struct.setDeclaredType(type);
}
}
if (wrapopt) {
struct.setUsage(PropertyAttributes.OPTIONAL_USAGE);
}
contain.addChild(struct);
contain = struct;
consing = true;
wrapname = null;
wrapopt = false;
}
// build the appropriate binding representation
StructureElement struct = null;
if (item instanceof ReferenceItem) {
// handle reference directly if a structure class, else just as value
DefinitionItem def = ((ReferenceItem)item).getDefinition();
TypeData defclas = def.getGenerateClass();
if (!defclas.isSimpleValue()) {
struct = addReferenceStructure(leaf, def, consing, holder, contain);
}
} else if (item instanceof GroupItem) {
// handle group directly if a structure class, else just as value
TypeData groupclas = ((GroupItem)item).getGenerateClass();
if (!groupclas.isSimpleValue()) {
// create a new <structure> element for reference
struct = new StructureElement();
StructureClassHolder refclas = (StructureClassHolder)groupclas;
if (gname == null) {
struct.setDeclaredType(refclas.getBindingName());
}
// set the binding component to be filled in by inner class generation
refclas.setBinding(struct);
}
}
if (struct == null) {
// add simple <value> binding for field
ValueElement value = buildValueBinding(leaf, wrapname, gname, sname, holder);
if (getSchemaCustom().isForceTypes()) {
value.setDeclaredType(leaf.getBindingType());
}
if (wrapopt) {
value.setUsage(PropertyAttributes.OPTIONAL_USAGE);
}
contain.addChild(value);
} else {
// fill in structure attributes
struct.setGetName(gname);
struct.setSetName(sname);
if (getSchemaCustom().isForceTypes()) {
struct.setDeclaredType(leaf.getBindingType());
}
// set the name and optional status from wrapper or item
setName(wrapname == null ? leaf.getQName() : wrapname, holder, struct);
setStructureOptional(leaf, wrapopt, struct);
// common <choice> handling for structure
if (parent.isSelectorNeeded()) {
struct.setUsage(PropertyAttributes.OPTIONAL_USAGE);
struct.setTestName("if" + leaf.getSelectPropName());
}
// add to containing binding component
if (struct != contain) {
contain.addChild(struct);
}
}
}
}