if (property.isXmlList()) {
firstVar = nullCond._then().decl(context.toJType(boolean.class), builder.getWriteVariableManager().createId(property.getName() + "First"), JExpr.TRUE);
}
String itemName = builder.getWriteVariableManager().createId(property.getName() + "Item");
JForEach each = nullCond._then().forEach(itemType, itemName, outerVar);
// write wraper element closing tag
if (wrapperElement != null) {
if (property.isRequired() || property.isNillable()) {
outerBlock.add(builder.getXSW().invoke("writeEndElement"));
} else {
nullCond._then().add(builder.getXSW().invoke("writeEndElement"));
}
}
outerBlock = each.body();
outerVar = each.var();
}
Class propertyType = toClass(property.getComponentType());
// process value through adapter
outerVar = writeAdapterConversion(builder, outerBlock, property, outerVar);
if (property.getAdapterType() != null) {
propertyType = property.getComponentAdaptedType();
}
// determine types that may be substuited for this value
Map<Class, ElementMapping> expectedTypes = new TreeMap<Class, ElementMapping>(new ClassComparator());
for (ElementMapping mapping : property.getElementMappings()) {
if (mapping.getComponentType() != null) {
expectedTypes.put(toClass(mapping.getComponentType()), mapping);
} else {
expectedTypes.put(toClass(property.getType()), mapping);
}
}
if (expectedTypes.size() == 1 && !property.isMixed()) {
ElementMapping mapping = property.getElementMappings().iterator().next();
// null check for non-nillable elements
JBlock block = outerBlock;
JConditional nullCond = null;
if (!mapping.isNillable() && !propertyType.isPrimitive()) {
nullCond = outerBlock._if(outerVar.ne(JExpr._null()));
block = nullCond._then();
}
// add space (' ') separator for XmlList
if (property.isXmlList()) {
// if (fooFirst) {
// writer.writeCharacters(" ");
// }
// fooFirst = false;
block._if(firstVar.not())._then().add(builder.getXSW().invoke("writeCharacters").arg(" "));
block.assign(firstVar, JExpr.FALSE);
}
// write element
writeElement(builder, block, mapping, outerVar, propertyType, mapping.isNillable(), property.isXmlList());
// property is required and does not support nill, then an error is reported if the value was null
if (property.isRequired() && !mapping.isNillable() && nullCond != null) {
nullCond._else().invoke(builder.getWriteContextVar(), "unexpectedNullValue").arg(builder.getWriteObject()).arg(property.getName());
}
} else {
JIfElseBlock conditional = new JIfElseBlock();
outerBlock.add(conditional);
if (property.isMixed()) {
// add instance of check
JExpression isInstance = outerVar._instanceof(context.toJClass(String.class));
JBlock block = conditional.addCondition(isInstance);
// declare item variable
JVar itemVar;
if (toClass(property.getComponentType()) == String.class) {
itemVar = outerVar;
} else {
String itemName = builder.getWriteVariableManager().createId("string");
itemVar = block.decl(context.toJClass(String.class), itemName, JExpr.cast(context.toJClass(String.class), outerVar));
}
writeSimpleTypeElement(builder, itemVar, String.class, block);
}
ElementMapping nilMapping = null;
for (Map.Entry<Class, ElementMapping> entry : expectedTypes.entrySet()) {
Class itemType = entry.getKey();
ElementMapping mapping = entry.getValue();
if (mapping.isNillable()) {
if (nilMapping != null && nilMapping != mapping) {
throw new BuildException("Property " + property + " mappings " + mapping.getXmlName() + " and " + nilMapping + " are both nillable. Only one mapping may of an property may be nilable");
}
nilMapping = mapping;
}
// add instance of check
JExpression isInstance = outerVar._instanceof(context.toJClass(itemType));
JBlock block = conditional.addCondition(isInstance);
// add space (' ') separator for XmlList
if (property.isXmlList()) {
// if (fooFirst) {
// writer.writeCharacters(" ");
// }
// fooFirst = false;
block._if(firstVar.not())._then().add(builder.getXSW().invoke("writeCharacters").arg(" "));
block.assign(firstVar, JExpr.FALSE);
}
// declare item variable
JVar itemVar;
if (toClass(property.getComponentType()) == itemType) {
itemVar = outerVar;
} else {
String itemName = builder.getWriteVariableManager().createId(itemType.getSimpleName());
itemVar = block.decl(context.toJClass(itemType), itemName, JExpr.cast(context.toJClass(itemType), outerVar));
}
writeElement(builder, block, mapping, itemVar, itemType, false, property.isXmlList());
}
// if item was null, write xsi:nil or report an error
JBlock nullBlock = conditional.addCondition(outerVar.eq(JExpr._null()));
if (nilMapping != null) {
// write start element
QName name = nilMapping.getXmlName();
nullBlock.add(builder.getWriteStartElement(name));
// write xsi:nil
nullBlock.add(builder.getXSW().invoke("writeXsiNil"));
// close element
nullBlock.add(builder.getXSW().invoke("writeEndElement"));
} else {
nullBlock.invoke(builder.getWriteContextVar(), "unexpectedNullValue").arg(builder.getWriteObject()).arg(property.getName());
}
// if not a recogonized type or null, report unknown type error
JInvocation unexpected = conditional._else().invoke(builder.getWriteContextVar(), "unexpectedElementType").arg(builder.getXSW()).arg(builder.getWriteObject()).arg(property.getName()).arg(outerVar);
for (Class expectedType : expectedTypes.keySet()) {
unexpected.arg(context.dotclass(expectedType));
}
}
break;
case ELEMENT_REF:
JBlock block = builder.getWriteMethod().body();
JVar itemVar = propertyVar;
if (property.isCollection()) {
JBlock collectionNotNull = block._if(propertyVar.ne(JExpr._null()))._then();
JType itemType;
if (!toClass(property.getComponentType()).isPrimitive()) {
itemType = context.getGenericType(property.getComponentType());
} else {
itemType = context.toJType((Class<?>) toClass(property.getComponentType()));
}
String itemName = builder.getWriteVariableManager().createId( property.getName() + "Item");
JForEach each = collectionNotNull.forEach(itemType, itemName, propertyVar);
JBlock newBody = each.body();
block = newBody;
itemVar = each.var();
}
// process value through adapter
itemVar = writeAdapterConversion(builder, block, property, itemVar);
if (property.isMixed()) {
// add instance of check
JExpression isInstance = itemVar._instanceof(context.toJClass(String.class));
JConditional conditional = block._if(isInstance);
// declare item variable
JVar stringVar;
if (toClass(property.getComponentType()) == String.class) {
stringVar = itemVar;
} else {
String itemName = builder.getWriteVariableManager().createId("string");
stringVar = conditional._then().decl(context.toJClass(String.class), itemName, JExpr.cast(context.toJClass(String.class), itemVar));
}
writeSimpleTypeElement(builder, stringVar, String.class, conditional._then());
block = conditional._else();
}
if (!property.isXmlAny()) {
block.invoke(builder.getWriteContextVar(), "unexpectedElementRef").arg(builder.getXSW()).arg(builder.getWriteObject()).arg(property.getName()).arg(itemVar);
} else {
block.invoke(builder.getWriteContextVar(), "writeXmlAny").arg(builder.getXSW()).arg(builder.getWriteObject()).arg(property.getName()).arg(itemVar);
}
break;
case VALUE:
block = builder.getWriteMethod().body();
itemVar = propertyVar;
firstVar = null;
if (property.isCollection()) {
JBlock collectionNotNull = block._if(propertyVar.ne(JExpr._null()))._then();
JType itemType;
if (!toClass(property.getComponentType()).isPrimitive()) {
itemType = context.getGenericType(property.getComponentType());
} else {
itemType = context.toJType((Class<?>) toClass(property.getComponentType()));
}
firstVar = collectionNotNull.decl(context.toJType(boolean.class), builder.getWriteVariableManager().createId(property.getName() + "First"), JExpr.TRUE);
String itemName = builder.getWriteVariableManager().createId( property.getName() + "Item");
JForEach each = collectionNotNull.forEach(itemType, itemName, propertyVar);
JBlock newBody = each.body();
block = newBody;
itemVar = each.var();
}
// add space (' ') separator for XmlList
if (property.isCollection()) {
// if (fooFirst) {