log.trace("Created BeanHandler for type=" + beanInfo.getName() + " factory=" + factory);
// Look through the properties
JBossXmlNoElements jbossXmlNoElements = typeInfo.getUnderlyingAnnotation(JBossXmlNoElements.class);
boolean noElements = jbossXmlNoElements != null;
PropertyInfo valueProperty = null;
PropertyInfo wildcardProperty = null;
boolean allBinding = propertyOrder.length == 0;
boolean determinePropertyOrder = allBinding || (propertyOrder.length == 1 && propertyOrder[0].length() == 0);
ArrayList<String> propertyNames = new ArrayList<String>();
Set<PropertyInfo> properties = beanInfo.getProperties();
if (properties != null && properties.isEmpty() == false)
{
boolean seenXmlAnyElement = false;
for (PropertyInfo property : properties)
{
push(typeInfo, property.getName());
if (trace)
log.trace("Checking property " + property.getName() + " for " + beanInfo.getName() + " type=" + property.getType().getName());
// Is this the value property?
XmlValue xmlValue = property.getUnderlyingAnnotation(XmlValue.class);
if (xmlValue != null)
{
if (trace)
log.trace("Seen @XmlValue for type=" + beanInfo.getName() + " property=" + property.getName());
if (valueProperty != null)
throw new RuntimeException("@XmlValue seen on two properties: " + property.getName() + " and " + valueProperty.getName());
valueProperty = property;
}
// Is this the wildcard property?
boolean ignoreXmlAnyElement = false;
XmlAnyElement xmlAnyElement = property.getUnderlyingAnnotation(XmlAnyElement.class);
if (xmlAnyElement != null)
{
if (trace)
log.trace("Seen @XmlAnyElement for type=" + beanInfo.getName() + " property=" + property.getName());
if (wildcardProperty != null && seenXmlAnyElement)
throw new RuntimeException("@XmlAnyElement seen on two properties: " + property.getName() + " and " + wildcardProperty.getName());
wildcardProperty = property;
seenXmlAnyElement = true;
// should we ignore it
if(property.getUnderlyingAnnotation(XmlElements.class) == null &&
property.getUnderlyingAnnotation(XmlElementRefs.class) == null)
ignoreXmlAnyElement = true;
}
else if (!seenXmlAnyElement && wildcardProperty == null && property.getType().getName().equals(org.w3c.dom.Element.class.getName()))
{
if (trace)
log.trace("Using type=" + beanInfo.getName() + " property=" + property.getName() + " as the base wildcard");
if (wildcardProperty != null)
throw new RuntimeException("@XmlAnyElement seen on two properties: " + property.getName() + " and " + wildcardProperty.getName());
wildcardProperty = property;
}
// Is this an attribute
XmlAttribute xmlAttribute = property.getUnderlyingAnnotation(XmlAttribute.class);
if (xmlAttribute != null)
{
JBossXmlAttribute jbossXmlAttribute = property.getUnderlyingAnnotation(JBossXmlAttribute.class);
// Determine the name
QName qName = generateXmlName(property.getName(), attributeForm, xmlAttribute.namespace(), xmlAttribute.name());
// Resolve the type
TypeInfo attributeTypeInfo = property.getType();
if (jbossXmlAttribute != null && jbossXmlAttribute.type() != Object.class)
attributeTypeInfo = attributeTypeInfo.getTypeInfoFactory().getTypeInfo(jbossXmlAttribute.type());
TypeBinding attributeType = resolveTypeBinding(attributeTypeInfo);
// Create the attribute handler
AttributeHandler attributeHandler = new PropertyHandler(property, attributeTypeInfo);
// Create the attributre and bind it to the type
AttributeBinding attribute = new AttributeBinding(schemaBinding, qName, attributeType, attributeHandler);
attribute.setRequired(xmlAttribute.required());
typeBinding.addAttribute(attribute);
if (trace)
log.trace("Bound attribute " + qName + " type=" + beanInfo.getName() + " property=" + property.getName() + " propertyType=" + attributeTypeInfo);
}
// Are we determining the property order?
if (determinePropertyOrder)
{
// Value property
if (xmlValue != null)
{
if (trace)
log.trace("Ignore not element @XmlValue for type=" + beanInfo.getName() + " property=" + property.getName());
pop();
continue;
}
// Wildcard property
if (ignoreXmlAnyElement)
{
if (trace)
log.trace("Ignore not element @XmlAnyElement for type=" + beanInfo.getName() + " property=" + property.getName());
pop();
continue;
}
// Ignore xml attribute
if (xmlAttribute != null)
{
if (trace)
log.trace("Ignore not element @XmlAttribute for type=" + beanInfo.getName() + " property=" + property.getName());
pop();
continue;
}
// Ignore xml tranient
XmlTransient xmlTransient = property.getUnderlyingAnnotation(XmlTransient.class);
if (xmlTransient != null)
{
if (trace)
log.trace("Ignore not element @XmlTransient for type=" + beanInfo.getName() + " property=" + property.getName());
pop();
continue;
}
// Ignore the class property
String name = property.getName();
if ("class".equals(name))
{
pop();
continue;
}
if (noElements)
{
pop();
continue;
}
if (trace)
log.trace("Element for type=" + beanInfo.getName() + " property=" + property.getName());
propertyNames.add(property.getName());
}
pop();
}
// Apply any access order
if (determinePropertyOrder)
{
if (accessOrder == XmlAccessOrder.ALPHABETICAL)
Collections.sort(propertyNames);
propertyOrder = propertyNames.toArray(new String[propertyNames.size()]);
}
}
// No value property, see if we have a default one
//if (valueProperty == null)
//{
// try
// {
// valueProperty = beanInfo.getProperty("value");
// }
// catch (Exception ignored)
// {
// Nope.
// }
//}
// Bind the value
if (valueProperty != null)
{
CharactersHandler charactersHandler = new ValueHandler(valueProperty);
typeBinding.setSimpleType(charactersHandler);
}
else if (trace)
log.trace("No value for type=" + beanInfo.getName());
if (trace)
log.trace("PropertyOrder " + Arrays.asList(propertyOrder) + " for type=" + beanInfo.getName());
// Determine the model
// TODO simple types/content when no properties other than @XmlValue and @XmlAttribute
typeBinding.setSimple(false);
ModelGroupBinding model = null;
if (allBinding)
{
if (trace)
log.trace("AllBinding for type=" + beanInfo.getName());
model = new AllBinding(schemaBinding);
}
else
{
if (trace)
log.trace("SequenceBinding for type=" + beanInfo.getName());
model = new SequenceBinding(schemaBinding);
}
model.setHandler(BuilderParticleHandler.INSTANCE);
ParticleBinding typeParticle = new ParticleBinding(model);
typeParticle.setMinOccurs(1);
typeParticle.setMaxOccurs(1);
typeBinding.setParticle(typeParticle);
if (typeInfo.isCollection())
{
typeParticle.setMinOccurs(0);
typeParticle.setMaxOccursUnbounded(true);
TypeInfo memberBaseType = typeInfo.getComponentType();
JBossXmlModelGroup xmlModelGroup = ((ClassInfo) memberBaseType)
.getUnderlyingAnnotation(JBossXmlModelGroup.class);
if (xmlModelGroup != null && xmlModelGroup.particles().length > 0)
{
if (trace)
log.trace("Item base type for " + typeInfo.getName() + " is " + memberBaseType.getName()
+ " and bound to repeatable choice");
// it's choice by default based on the idea that the
// type parameter is a base class for items
ModelGroupBinding choiceGroup = null;
QName choiceName = null;
if(!JBossXmlConstants.DEFAULT.equals(xmlModelGroup.name()))
{
choiceName = new QName(defaultNamespace, xmlModelGroup.name());
choiceGroup = schemaBinding.getGroup(choiceName);
}
if(choiceGroup == null)
{
choiceGroup = new ChoiceBinding(schemaBinding);
choiceGroup.setHandler(BuilderParticleHandler.INSTANCE);
if (choiceName != null)
{
choiceGroup.setQName(choiceName);
schemaBinding.addGroup(choiceGroup.getQName(), choiceGroup);
}
ParticleBinding choiceParticle = new ParticleBinding(choiceGroup, 0, 1, true);
model.addParticle(choiceParticle);
for (JBossXmlModelGroup.Particle member : xmlModelGroup.particles())
{
XmlElement element = member.element();
QName memberQName = generateXmlName(element.name(), XmlNsForm.QUALIFIED, element.namespace(), null);
TypeInfo memberTypeInfo = typeInfo.getTypeInfoFactory().getTypeInfo(member.type());
boolean isCol = false;
if (memberTypeInfo.isCollection())
{
memberTypeInfo = ((ClassInfo) memberTypeInfo).getComponentType();
isCol = true;
}
TypeBinding memberTypeBinding = resolveTypeBinding(memberTypeInfo);
ElementBinding memberElement = createElementBinding(memberTypeInfo, memberTypeBinding, memberQName, false);
memberElement.setNillable(true);
ParticleBinding memberParticle = new ParticleBinding(memberElement, 0, 1, isCol);
choiceGroup.addParticle(memberParticle);
typeBinding.pushInterceptor(memberQName, ChildCollectionInterceptor.SINGLETON);
}
}
else
{
ParticleBinding choiceParticle = new ParticleBinding(choiceGroup, 0, 1, true);
model.addParticle(choiceParticle);
}
if (trace)
log.trace("choices for " + typeBinding.getQName() + ": " + choiceGroup.getParticles());
}
}
// Determine the wildcard handler
AbstractPropertyHandler wildcardHandler = null;
if (wildcardProperty != null)
{
TypeInfo wildcardType = wildcardProperty.getType();
if (wildcardType.isCollection())
wildcardHandler = new CollectionPropertyWildcardHandler(wildcardProperty, wildcardType);
else
wildcardHandler = new PropertyWildcardHandler(wildcardProperty, wildcardType);
}
// Look through the properties
for (String name : propertyOrder)
{
// Setup the error stack
push(typeInfo, name);
// Get the property
PropertyInfo property = beanInfo.getProperty(name);
bindProperty(property, typeBinding, model, beanAdapterFactory, propertyOrder);
pop();
}
// Bind the children
JBossXmlChild[] children = null;
JBossXmlChildren jbossXmlChildren = typeInfo.getUnderlyingAnnotation(JBossXmlChildren.class);
if (jbossXmlChildren != null)
children = jbossXmlChildren.value();
else
{
JBossXmlChild jbossXmlChild = typeInfo.getUnderlyingAnnotation(JBossXmlChild.class);
if (jbossXmlChild != null)
children = new JBossXmlChild[] { jbossXmlChild };
}
if (children != null && children.length > 0)
{
for (JBossXmlChild child : children)
{
QName qName = generateXmlName(child.name(), elementForm, child.namespace(), child.name());
TypeInfo childType = JBossXBBuilder.configuration.getTypeInfo(child.type());
TypeBinding elementTypeBinding = resolveTypeBinding(childType);
ElementBinding elementBinding = createElementBinding(childType, elementTypeBinding, qName, false);
// Bind it to the model
ParticleBinding particle = new ParticleBinding(elementBinding, child.minOccurs(), child.maxOccurs(), child.unbounded());
model.addParticle(particle);
if(childType.isMap())
bindMapProperty(null, (ClassInfo) childType, elementTypeBinding.getQName(), (ModelGroupBinding) elementTypeBinding.getParticle().getTerm());
DefaultElementInterceptor interceptor = null;
if (typeInfo.isCollection())
interceptor = ChildCollectionInterceptor.SINGLETON;
else
{
// Expect a type with a value property to accept the child value
PropertyInfo property = beanInfo.getProperty("value");
if (property == null)
throw new UnsupportedOperationException("Expected a value property for non-collection type with JBossXmlChildren");
TypeInfo propertyType = property.getType();
interceptor = new PropertyInterceptor(property, propertyType);
}
typeBinding.pushInterceptor(qName, interceptor);
if (trace)
log.trace("Added interceptor " + qName + " for type=" + childType + " interceptor=" + interceptor);