propertyGroup.setSkip(Boolean.FALSE);
// handler for the model group members
BeanInfo propBeanInfo = JBossXBBuilder.configuration.getBeanInfo(propClassInfo);
BeanAdapterFactory propBeanAdapterFactory = createAdapterFactory(DefaultBeanAdapterBuilder.class, propBeanInfo, null);
BeanHandler propHandler = new BeanHandler(propBeanInfo.getName(), propBeanAdapterFactory);
propertyGroup.setHandler(propHandler);
String[] memberOrder = xmlModelGroup.propOrder();
if (memberOrder.length == 0 || memberOrder[0].length() == 0)
{
List<String> propNames = new ArrayList<String>();
for (PropertyInfo prop : propBeanInfo.getProperties())
{
propNames.add(prop.getName());
}
memberOrder = propNames.toArray(new String[propNames.size()]);
}
if (trace)
log.trace("Property order for " + xmlModelGroup.kind() + " property " + property.getName() + ": "
+ Arrays.asList(memberOrder));
// bind model group members
for (String memberPropName : memberOrder)
{
if ("class".equals(memberPropName))
{
continue;
}
PropertyInfo memberProp = propBeanInfo.getProperty(memberPropName);
TypeInfo memberTypeInfo = memberProp.getType();
String memberNamespace = null;
JBossXmlNsPrefix nsPrefix = memberProp.getUnderlyingAnnotation(JBossXmlNsPrefix.class);
if (nsPrefix != null)
{
memberNamespace = schemaBinding.getNamespace(nsPrefix.prefix());
if (memberNamespace == null && nsPrefix.schemaTargetIfNotMapped())
{
throw new IllegalStateException("Prefix '" + nsPrefix.prefix()
+ "' is not mapped to any namespace!");
}
}
String memberName = null;
XmlElement memberXmlElement = memberProp.getUnderlyingAnnotation(XmlElement.class);
if (memberXmlElement != null)
{
if (!XmlElement.DEFAULT.class.equals(memberXmlElement.type()))
{
memberTypeInfo = memberTypeInfo.getTypeInfoFactory().getTypeInfo(memberXmlElement.type());
}
if (memberNamespace == null)
memberNamespace = memberXmlElement.namespace();
memberName = memberXmlElement.name();
}
if (memberNamespace == null)
{
memberNamespace = defaultNamespace;
}
boolean isCol = false;
AbstractPropertyHandler memberPropertyHandler = null;
if (memberProp.getType().isCollection())
{
memberPropertyHandler = new CollectionPropertyHandler(memberProp, memberProp.getType());
isCol = true;
// if memberXmlElement is present then the collection item type is set explicitly
if (memberXmlElement == null || XmlElement.DEFAULT.class.equals(memberXmlElement.type()))
{
JBossXmlCollection jbossXmlCollection = memberProp
.getUnderlyingAnnotation(JBossXmlCollection.class);
if (jbossXmlCollection != null)
{
memberTypeInfo = memberTypeInfo.getTypeInfoFactory().getTypeInfo(jbossXmlCollection.type());
}
memberTypeInfo = ((ClassInfo) memberTypeInfo).getComponentType();
}
}
// if it is bound with XmlElement.type to a collection
else if (memberTypeInfo.isCollection())
{
memberPropertyHandler = new CollectionPropertyHandler(memberProp, memberTypeInfo);
isCol = true;
memberTypeInfo = ((ClassInfo) memberTypeInfo).getComponentType();
}
else
{
memberPropertyHandler = new PropertyHandler(memberProp, memberTypeInfo);
}
QName memberQName = generateXmlName(memberProp.getName(), elementForm, memberNamespace, memberName);
propBeanAdapterFactory.addProperty(memberQName, memberPropertyHandler);
XBValueAdapter valueAdapter = null;
XmlJavaTypeAdapter xmlTypeAdapter = memberProp.getUnderlyingAnnotation(XmlJavaTypeAdapter.class);
if (xmlTypeAdapter != null)
{
valueAdapter = new XBValueAdapter(xmlTypeAdapter.value(), memberTypeInfo.getTypeInfoFactory());
memberTypeInfo = valueAdapter.getAdaptedTypeInfo();
}
TypeBinding memberTypeBinding = resolveTypeBinding(memberTypeInfo);
ElementBinding memberElement = createElementBinding(memberTypeInfo, memberTypeBinding, memberQName,
false);
memberElement.setNillable(true);
memberElement.setValueAdapter(valueAdapter);
ParticleBinding memberParticle = new ParticleBinding(memberElement, 0, 1, isCol);
propertyGroup.addParticle(memberParticle);
if (trace)
log.trace("added " + memberParticle + " to " + xmlModelGroup.kind() + ", property "
+ property.getName());
}
}
model.addParticle(new ParticleBinding(propertyGroup));
// model group value handler based on the model group name
// TODO what if it doesn't have a name?
AbstractPropertyHandler propertyHandler = null;
if (propertyType.isCollection())
propertyHandler = new CollectionPropertyHandler(property, propClassInfo);
else
{
propertyHandler = new PropertyHandler(property, propClassInfo);
}
beanAdapterFactory.addProperty(propertyGroup.getQName(), propertyHandler);
return;
}
}
// So this is element(s)
XmlElement[] elements = null;
XmlElement xmlElement = property.getUnderlyingAnnotation(XmlElement.class);
if (xmlElement != null)
{
// A single element annotated
elements = new XmlElement[]
{xmlElement};
}
else
{
// Mutlple elements
XmlElements xmlElements = property.getUnderlyingAnnotation(XmlElements.class);
if (xmlElements != null)
elements = xmlElements.value();
}
// A single element not annotated
if (elements == null || elements.length == 0)
elements = new XmlElement[1];
// for now support just one JBossXmlNsPrefix
JBossXmlNsPrefix xmlNsPrefix = property.getUnderlyingAnnotation(JBossXmlNsPrefix.class);
// support for @XmlElementWrapper
// the wrapping element is ignored in this case
XmlElementWrapper xmlWrapper = property.getUnderlyingAnnotation(XmlElementWrapper.class);
if (xmlWrapper != null)
{
String wrapperNamespace = xmlWrapper.namespace();
String wrapperName = xmlWrapper.name();
QName wrapperQName = generateXmlName(property.getName(), elementForm, wrapperNamespace, wrapperName);
localModel = bindXmlElementWrapper(propertyType, localModel, xmlWrapper.nillable(), wrapperQName);
beanAdapterFactory.addProperty(wrapperQName, new PropertyHandler(property, propertyType));
if (trace)
log.trace("Added property " + wrapperQName + " for type=" + property.getBeanInfo().getName() + " property="
+ property.getName() + " as a wrapper element");
}
// Setup a choice
if (elements.length > 1)
{
ChoiceBinding choice = new ChoiceBinding(schemaBinding);
choice.setHandler(BuilderParticleHandler.INSTANCE);
ParticleBinding particleBinding = new ParticleBinding(choice);
particleBinding.setMinOccurs(0);
particleBinding.setMaxOccurs(1);
localModel.addParticle(particleBinding);
localModel = choice;
if (trace)
log.trace("XmlElements seen adding choice for type=" + property.getBeanInfo().getName() + " property="
+ property.getName());
}
for (int i = 0; i < elements.length; ++i)
{
XmlElement element = elements[i];
if (trace)
log.trace("Processing " + element + " for type=" + property.getBeanInfo().getName() + " property="
+ property.getName());
// Determine the parameters
String overrideNamespace = null;
String overrideName = null;
boolean nillable = false;
boolean required = false;
TypeInfo localPropertyType = propertyType;
if (element != null)
{
overrideNamespace = element.namespace();
overrideName = element.name();
nillable = element.nillable();
required = element.required();
Class<?> elementType = element.type();
if (elementType != XmlElement.DEFAULT.class)
localPropertyType = propertyType.getTypeInfoFactory().getTypeInfo(elementType);
}
if (xmlNsPrefix != null)
{
overrideNamespace = schemaBinding.getNamespace(xmlNsPrefix.prefix());
if (overrideNamespace == null)
{
if (xmlNsPrefix.schemaTargetIfNotMapped())
{
overrideNamespace = defaultNamespace;
}
else
{
throw new IllegalStateException("Prefix '" + xmlNsPrefix.prefix()
+ "' is not mapped to any namespace!");
}
}
}
// Determine the name
QName propertyQName = generateXmlName(property.getName(), elementForm, overrideNamespace, overrideName);
// Create the element
JBossXmlGroup jbossXmlGroup = null;
if (!propertyType.isPrimitive())
jbossXmlGroup = ((ClassInfo) propertyType).getUnderlyingAnnotation(JBossXmlGroup.class);
if (element == null && jbossXmlGroup != null)
{
if (trace)
log.trace("Processing group for property " + property.getName() + " in "
+ property.getBeanInfo().getName() + " " + jbossXmlGroup);
JBossXmlChild[] children = jbossXmlGroup.value();
if (children != null && children.length > 0)
{
TypeBinding elementTypeBinding = new TypeBinding();
JBossXmlGroupText groupText = ((ClassInfo) propertyType).getUnderlyingAnnotation(JBossXmlGroupText.class);
if (groupText != null && groupText.wrapper() != Object.class)
{
BeanInfo wrapperInfo = JBossXBBuilder.configuration.getBeanInfo(groupText.wrapper());
TypeBinding wrapperTypeBinding = resolveTypeBinding(wrapperInfo.getClassInfo());
// Steal the attributes
Collection<AttributeBinding> otherAttributes = wrapperTypeBinding.getAttributes();
if (otherAttributes != null)
{
for (AttributeBinding other : otherAttributes)
elementTypeBinding.addAttribute(other);
}
ParticleHandler particleHandler = wrapperTypeBinding.getHandler();
if (particleHandler instanceof BeanHandler == false)
throw new IllegalStateException("Cannot wrap " + wrapperInfo.getName() + " not a bean type " + particleHandler);
BeanHandler beanHandler = (BeanHandler) particleHandler;
WrapperBeanAdapterFactory wrapperFactory = new WrapperBeanAdapterFactory(beanHandler.getBeanAdapterFactory(), propertyType.getType());
elementTypeBinding.setHandler(new BeanHandler(wrapperInfo.getName(), wrapperFactory));
elementTypeBinding.setSimpleType(wrapperTypeBinding.getSimpleType());
}
else
{
elementTypeBinding.setHandler(BuilderParticleHandler.INSTANCE);
}
elementTypeBinding.setSchemaBinding(schemaBinding);
ElementBinding elementBinding = createElementBinding(localPropertyType, elementTypeBinding, propertyQName, false);
// Bind it to the model
ParticleBinding particle = new ParticleBinding(elementBinding, 1, 1, false);
if (required == false)
particle.setMinOccurs(0);
localModel.addParticle(particle);
// Setup the child model
ChoiceBinding childModel = new ChoiceBinding(schemaBinding);
childModel.setHandler(BuilderParticleHandler.INSTANCE);
ParticleBinding particleBinding = new ParticleBinding(childModel);
particleBinding.setMinOccurs(0);
particleBinding.setMaxOccurs(1);
elementTypeBinding.setParticle(particleBinding);
for (JBossXmlChild child : children)
{
QName childName = generateXmlName(child.name(), elementForm, child.namespace(), child.name());
TypeInfo childType = JBossXBBuilder.configuration.getTypeInfo(child.type());
TypeBinding childTypeBinding = resolveTypeBinding(childType);
ElementBinding childBinding = createElementBinding(childType, childTypeBinding, childName, false);
childBinding.setNillable(nillable);
// Bind it to the model
particle = new ParticleBinding(childBinding, child.minOccurs(), child.maxOccurs(), child.unbounded());
particle.setMinOccurs(0);
childModel.addParticle(particle);
if(childType.isMap())
bindMapProperty(property, (ClassInfo) childType, childName, (ModelGroupBinding) childTypeBinding.getParticle().getTerm());
DefaultElementInterceptor interceptor = new PropertyInterceptor(property, propertyType);
elementTypeBinding.pushInterceptor(childName, interceptor);
if (trace)
log.trace("Added interceptor " + childName + " for type=" + property.getBeanInfo().getName()
+ " property=" + property.getName() + " interceptor=" + interceptor + " " + childType.getName());
beanAdapterFactory.addProperty(propertyQName, new PropertyHandler(property, propertyType));
JBossXmlGroupWildcard groupWildcard = ((ClassInfo) propertyType)
.getUnderlyingAnnotation(JBossXmlGroupWildcard.class);
if (groupWildcard != null)
{
ChildWildcardHandler groupWildcardHandler;
if (groupWildcard.wrapper() != Object.class)
{
BeanInfo wrapperInfo = JBossXBBuilder.configuration.getBeanInfo(groupWildcard.wrapper());
groupWildcardHandler = new ChildWildcardHandler(property, wrapperInfo, groupWildcard.property());
}
else
groupWildcardHandler = new ChildWildcardHandler(property);
WildcardBinding wildcard = new WildcardBinding(schemaBinding);
if (groupWildcard.lax())
wildcard.setProcessContents((short) 3); // Lax
else
wildcard.setProcessContents((short) 1); // Strict
particleBinding = new ParticleBinding(wildcard);
particleBinding.setMinOccurs(0);
particleBinding.setMaxOccurs(1);
childModel.addParticle(particleBinding);
elementTypeBinding.getWildcard().setWildcardHandler(groupWildcardHandler);
}
}
}
}
else
{
XBValueAdapter valueAdapter = null;
XmlJavaTypeAdapter xmlTypeAdapter = property.getUnderlyingAnnotation(XmlJavaTypeAdapter.class);
if (xmlTypeAdapter != null)
{
valueAdapter = new XBValueAdapter(xmlTypeAdapter.value(), propertyType.getTypeInfoFactory());
localPropertyType = valueAdapter.getAdaptedTypeInfo();
}
ModelGroupBinding targetGroup = localModel;
boolean isCol = false;
boolean isMap = false;
AbstractPropertyHandler propertyHandler = null;
// a collection may be bound as a value of a complex type
// and this is checked with the XmlType annotation
if (propertyType.isCollection() && ((ClassInfo) propertyType).getUnderlyingAnnotation(XmlType.class) == null)
{
isCol = true;
propertyHandler = new CollectionPropertyHandler(property, propertyType);
// here we get the comp type based on the non-overriden property type...
// which feels like a weak point
TypeInfo typeArg = ((ClassInfo)property.getType()).getComponentType();
if (typeArg != null && ((ClassInfo)typeArg).getUnderlyingAnnotation(JBossXmlModelGroup.class) == null)
{// it may be a model group in which case we don't want to change the type
// TODO yes, this is another hack with collections
JBossXmlChild xmlChild = ((ClassInfo) propertyType).getUnderlyingAnnotation(JBossXmlChild.class);
if (xmlChild == null && localPropertyType.equals(propertyType))
{ // the localPropertyType was not overriden previously so use the collection parameter type
localPropertyType = typeArg;
}
}
}
// TODO this shouldn't be here (because localPropertyType should specify an item?)
// this is to support the Descriptions.class -> DescriptionsImpl.class
else if (localPropertyType.isCollection()
&& ((ClassInfo) localPropertyType).getUnderlyingAnnotation(XmlType.class) == null)
{
if (valueAdapter != null)
{
propertyHandler = new PropertyHandler(property, localPropertyType);
}
else
{
propertyHandler = new CollectionPropertyHandler(property, localPropertyType);
}
isCol = true;
localPropertyType = ((ClassInfo)localPropertyType).getComponentType();
}
else if (localPropertyType.isMap())
{
TypeBinding wrapperType = null;
if(elements.length > 1)
{
wrapperType = resolveTypeBinding(localPropertyType);
ElementBinding elementBinding = createElementBinding(localPropertyType, wrapperType, propertyQName, false);
elementBinding.setNillable(nillable);
elementBinding.setValueAdapter(valueAdapter);
// Bind it to the model
ParticleBinding particle = new ParticleBinding(elementBinding, 0, 1, isCol);
if (required == false)
particle.setMinOccurs(0);
targetGroup.addParticle(particle);
targetGroup = (ModelGroupBinding) wrapperType.getParticle().getTerm();
}
QName boundQName = bindMapProperty(property, (ClassInfo) localPropertyType, propertyQName, targetGroup);
if(boundQName != null)
{
if(wrapperType != null)
{
BeanAdapterFactory wrapperBeanFactory = ((BeanHandler)wrapperType.getHandler()).getBeanAdapterFactory();
Map<QName, AbstractPropertyHandler> properties = wrapperBeanFactory.getProperties();
if(!properties.containsKey(boundQName))
{
propertyHandler = new MapPropertyHandler(JBossXBBuilder.configuration, property, localPropertyType, true);
wrapperBeanFactory.addProperty(boundQName, propertyHandler);
}
propertyHandler = new PropertyHandler(property, localPropertyType);
}
else
{