Index: src/org/eclipse/persistence/internal/jaxb/DefaultElementConverter.java =================================================================== --- src/org/eclipse/persistence/internal/jaxb/DefaultElementConverter.java (revision 0) +++ src/org/eclipse/persistence/internal/jaxb/DefaultElementConverter.java (revision 0) @@ -0,0 +1,64 @@ +/******************************************************************************* +* Copyright (c) 1998, 2009 Oracle. All rights reserved. +* This program and the accompanying materials are made available under the +* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 +* which accompanies this distribution. +* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html +* and the Eclipse Distribution License is available at +* http://www.eclipse.org/org/documents/edl-v10.php. +* +* Contributors: +* bdoughan - July 30/2009 - 2.0 - Initial implementation +******************************************************************************/ +package org.eclipse.persistence.internal.jaxb; + +import org.eclipse.persistence.mappings.DatabaseMapping; +import org.eclipse.persistence.oxm.XMLMarshaller; +import org.eclipse.persistence.oxm.XMLUnmarshaller; +import org.eclipse.persistence.oxm.mappings.converters.XMLConverter; +import org.eclipse.persistence.sessions.Session; +import org.w3c.dom.Element; + +/** + * If there is no text node then apply the default value. + *
 @XmlElement(required = true, defaultValue = "default")
+ * protected Object a;
+ */ +public class DefaultElementConverter implements XMLConverter { + + private String defaultValue; + + public DefaultElementConverter(String defaultValue) { + this.defaultValue = defaultValue; + } + + public void initialize(DatabaseMapping mapping, Session session) { + } + + public Object convertDataValueToObjectValue(Object dataValue, Session session) { + if(dataValue instanceof Element) { + Element element = (Element) dataValue; + if(element.getTextContent().length() == 0) { + element.setTextContent(defaultValue); + } + } + return dataValue; + } + + public Object convertObjectValueToDataValue(Object objectValue, Session session) { + return objectValue; + } + + public boolean isMutable() { + return false; + } + + public Object convertDataValueToObjectValue(Object dataValue, Session session, XMLUnmarshaller unmarshaller) { + return convertDataValueToObjectValue(dataValue, session); + } + + public Object convertObjectValueToDataValue(Object objectValue, Session session, XMLMarshaller marshaller) { + return convertObjectValueToDataValue(objectValue, session); + } + +} \ No newline at end of file Index: src/org/eclipse/persistence/internal/jaxb/DomHandlerConverter.java =================================================================== --- src/org/eclipse/persistence/internal/jaxb/DomHandlerConverter.java (revision 4831) +++ src/org/eclipse/persistence/internal/jaxb/DomHandlerConverter.java (working copy) @@ -101,11 +101,11 @@ } public Object convertDataValueToObjectValue(Object dataValue, Session session) { - return null; + return convertDataValueToObjectValue(dataValue, session, null); } public Object convertObjectValueToDataValue(Object objectValue, Session session) { - return null; + return convertObjectValueToDataValue(objectValue, session, null); } -} +} \ No newline at end of file Index: src/org/eclipse/persistence/internal/jaxb/JAXBElementAttributeAccessor.java =================================================================== --- src/org/eclipse/persistence/internal/jaxb/JAXBElementAttributeAccessor.java (revision 4831) +++ src/org/eclipse/persistence/internal/jaxb/JAXBElementAttributeAccessor.java (working copy) @@ -1,143 +0,0 @@ -/******************************************************************************* -* Copyright (c) 1998, 2009 Oracle. All rights reserved. -* This program and the accompanying materials are made available under the -* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 -* which accompanies this distribution. -* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html -* and the Eclipse Distribution License is available at -* http://www.eclipse.org/org/documents/edl-v10.php. -* -* Contributors: -* mmacivor - June 05/2008 - 1.0 - Initial implementation -******************************************************************************/ -package org.eclipse.persistence.internal.jaxb; - -import java.util.HashMap; -import java.util.Map; - -import org.eclipse.persistence.mappings.AttributeAccessor; -import org.eclipse.persistence.exceptions.DescriptorException; -import org.eclipse.persistence.internal.helper.ClassConstants; -import org.eclipse.persistence.internal.queries.ContainerPolicy; -import org.eclipse.persistence.oxm.XMLRoot; -import javax.xml.bind.JAXBElement; -import javax.xml.namespace.QName; - -public class JAXBElementAttributeAccessor extends AttributeAccessor { - private AttributeAccessor nestedAccessor; - private ContainerPolicy containerPolicy; - private boolean isContainer; - private Map qNamesToScopes; - private Class declaredType; - - public JAXBElementAttributeAccessor(AttributeAccessor nestedAccessor) { - this.nestedAccessor = nestedAccessor; - this.isContainer = false; - qNamesToScopes = new HashMap(); - } - public JAXBElementAttributeAccessor(AttributeAccessor nestedAccessor, ContainerPolicy containerPolicy) { - this.nestedAccessor = nestedAccessor; - this.containerPolicy = containerPolicy; - this.isContainer = true; - qNamesToScopes = new HashMap(); - } - - public Object getAttributeValueFromObject(Object object) { - Object value = nestedAccessor.getAttributeValueFromObject(object); - //Swap JAXBElements for XMLRoots - //May need a better way to do this for perf. - if(isContainer) { - Object results = containerPolicy.containerInstance(containerPolicy.sizeFor(value)); - Object iterator = containerPolicy.iteratorFor(value); - while(containerPolicy.hasNext(iterator)) { - Object next = containerPolicy.next(iterator, null); - if(next instanceof JAXBElement) { - JAXBElement element = (JAXBElement)next; - XMLRoot root = new XMLRoot(); - root.setLocalName(element.getName().getLocalPart()); - root.setNamespaceURI(element.getName().getNamespaceURI()); - root.setObject(element.getValue()); - containerPolicy.addInto(root, results, null); - } else { - containerPolicy.addInto(next, results, null); - } - } - value = results; - } else if(value instanceof JAXBElement) { - JAXBElement element = (JAXBElement)value; - XMLRoot root = new XMLRoot(); - root.setLocalName(element.getName().getLocalPart()); - root.setNamespaceURI(element.getName().getNamespaceURI()); - root.setObject(element.getValue()); - value = root; - } - return value; - } - - public void setAttributeValueInObject(Object object, Object value) { - Object attributeValue = value; - if(isContainer) { - Object results = containerPolicy.containerInstance(containerPolicy.sizeFor(attributeValue)); - Object iterator = containerPolicy.iteratorFor(attributeValue); - while(containerPolicy.hasNext(iterator)) { - Object next = containerPolicy.next(iterator, null); - Object objectToAdd = unwrapObject(next); - containerPolicy.addInto(objectToAdd, results, null); - } - attributeValue = results; - } else { - attributeValue = unwrapObject(attributeValue); - - } - nestedAccessor.setAttributeValueInObject(object, attributeValue); - } - - public void initializeAttributes(Class theJavaClass) throws DescriptorException { - nestedAccessor.initializeAttributes(theJavaClass); - } - - private Object unwrapObject(Object originalObject){ - if(originalObject instanceof XMLRoot) { - XMLRoot root = (XMLRoot)originalObject; - QName name = new QName(root.getNamespaceURI(), root.getLocalName()); - Object value = root.getObject(); - if(value == null){ - return createJAXBElement(name, Object.class, value); - }else{ - return createJAXBElement(name, getDeclaredType(),value); - } - } else { - return originalObject; - } - } - - private JAXBElement createJAXBElement(QName qname, Class theClass, Object value){ - if(value != null && value instanceof JAXBElement){ - return (JAXBElement)value; - } - if(ClassConstants.XML_GREGORIAN_CALENDAR.isAssignableFrom(theClass)){ - theClass = ClassConstants.XML_GREGORIAN_CALENDAR; - }else if(ClassConstants.DURATION.isAssignableFrom(theClass)){ - theClass = ClassConstants.DURATION; - } - Class scopeClass = qNamesToScopes.get(qname); - if(scopeClass == javax.xml.bind.annotation.XmlElementDecl.GLOBAL.class){ - scopeClass = JAXBElement.GlobalScope.class; - } - return new JAXBElement(qname, theClass, scopeClass, value); - } - - public Map getQNamesToScopes() { - return qNamesToScopes; - } - public void setQNamesToScopes(Map namesToScopes) { - qNamesToScopes = namesToScopes; - } - - public void setDeclaredType(Class declaredType) { - this.declaredType = declaredType; - } - public Class getDeclaredType() { - return declaredType; - } -} Index: src/org/eclipse/persistence/internal/jaxb/JAXBElementConverter.java =================================================================== --- src/org/eclipse/persistence/internal/jaxb/JAXBElementConverter.java (revision 0) +++ src/org/eclipse/persistence/internal/jaxb/JAXBElementConverter.java (revision 0) @@ -0,0 +1,120 @@ +/******************************************************************************* +* Copyright (c) 1998, 2009 Oracle. All rights reserved. +* This program and the accompanying materials are made available under the +* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 +* which accompanies this distribution. +* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html +* and the Eclipse Distribution License is available at +* http://www.eclipse.org/org/documents/edl-v10.php. +* +* Contributors: +* bdoughan - July 29/2009 - 2.0 - Initial implementation +******************************************************************************/ +package org.eclipse.persistence.internal.jaxb; + +import javax.xml.bind.JAXBElement; +import javax.xml.namespace.QName; + +import org.eclipse.persistence.mappings.DatabaseMapping; +import org.eclipse.persistence.mappings.converters.Converter; +import org.eclipse.persistence.oxm.XMLMarshaller; +import org.eclipse.persistence.oxm.XMLRoot; +import org.eclipse.persistence.oxm.XMLUnmarshaller; +import org.eclipse.persistence.oxm.XMLField; +import org.eclipse.persistence.oxm.mappings.converters.XMLConverter; +import org.eclipse.persistence.exceptions.ConversionException; +import org.eclipse.persistence.internal.oxm.XPathFragment; +import org.eclipse.persistence.sessions.Session; + +public class JAXBElementConverter implements XMLConverter { + + private XPathFragment rootFragment; + private XMLField associatedField; + private DatabaseMapping mapping; + private Converter nestedConverter; + private Class declaredType; + private Class scope; + + public JAXBElementConverter(XMLField associatedField, Class declaredType, Class scope) { + this.associatedField = associatedField; + this.declaredType = declaredType; + this.scope = scope; + } + + public Converter getNestedConverter() { + return nestedConverter; + } + + public void setNestedConverter(Converter nestedConverter) { + this.nestedConverter = nestedConverter; + } + + public Object convertDataValueToObjectValue(Object dataValue, + Session session, XMLUnmarshaller unmarshaller) { + return convertDataValueToObjectValue(dataValue, session); + } + + public Object convertObjectValueToDataValue(Object objectValue, + Session session, XMLMarshaller marshaller) { + return convertObjectValueToDataValue(objectValue, session); + } + + public Object convertDataValueToObjectValue(Object dataValue, Session session) { + QName name = new QName(rootFragment.getNamespaceURI(), rootFragment.getLocalName()); + + if(mapping.isAbstractDirectMapping()){ + if ((dataValue == null) || (dataValue.getClass() != mapping.getAttributeClassification())) { + try { + dataValue = session.getDatasourcePlatform().convertObject(dataValue, mapping.getAttributeClassification()); + } catch (ConversionException e) { + throw ConversionException.couldNotBeConverted(this, mapping.getDescriptor(), e); + } + } + } + + if(null != nestedConverter) { + dataValue = nestedConverter.convertDataValueToObjectValue(dataValue, session); + } + if(dataValue instanceof JAXBElement) { + return dataValue; + } + if(null == declaredType) { + return new JAXBElement(name, Object.class, scope, dataValue); + } else { + return new JAXBElement(name, declaredType, scope, dataValue); + } + } + + public Object convertObjectValueToDataValue(Object objectValue, Session session) { + if(objectValue instanceof JAXBElement) { + objectValue = ((JAXBElement)objectValue).getValue(); + } else if(objectValue instanceof XMLRoot) { + objectValue = ((XMLRoot) objectValue).getObject(); + } + if(null != nestedConverter) { + objectValue = nestedConverter.convertObjectValueToDataValue(objectValue, session); + } + return objectValue; + } + + public void initialize(DatabaseMapping mapping, Session session) { + if(null != nestedConverter) { + nestedConverter.initialize(mapping, session); + } + XPathFragment fragment = associatedField.getXPathFragment(); + while(fragment.getNextFragment() != null && !(fragment.getNextFragment().nameIsText())) { + fragment = fragment.getNextFragment(); + } + if(fragment.hasNamespace() && associatedField.getNamespaceResolver() != null){ + String uri = associatedField.getNamespaceResolver().resolveNamespacePrefix(fragment.getPrefix()); + fragment.setNamespaceURI(uri); + } + this.rootFragment = fragment; + this.mapping = mapping; + } + + public boolean isMutable() { + return false; + } + +} \ No newline at end of file Index: src/org/eclipse/persistence/internal/jaxb/JAXBElementRootConverter.java =================================================================== --- src/org/eclipse/persistence/internal/jaxb/JAXBElementRootConverter.java (revision 0) +++ src/org/eclipse/persistence/internal/jaxb/JAXBElementRootConverter.java (revision 0) @@ -0,0 +1,111 @@ +/******************************************************************************* +* Copyright (c) 1998, 2009 Oracle. All rights reserved. +* This program and the accompanying materials are made available under the +* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 +* which accompanies this distribution. +* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html +* and the Eclipse Distribution License is available at +* http://www.eclipse.org/org/documents/edl-v10.php. +* +* Contributors: +* bdoughan - August 5/2009 - 2.0 - Initial implementation +******************************************************************************/ +package org.eclipse.persistence.internal.jaxb; + +import javax.xml.bind.JAXBElement; +import javax.xml.namespace.QName; + +import org.eclipse.persistence.internal.helper.ClassConstants; +import org.eclipse.persistence.mappings.DatabaseMapping; +import org.eclipse.persistence.mappings.converters.Converter; +import org.eclipse.persistence.oxm.XMLMarshaller; +import org.eclipse.persistence.oxm.XMLRoot; +import org.eclipse.persistence.oxm.XMLUnmarshaller; +import org.eclipse.persistence.oxm.mappings.converters.XMLConverter; +import org.eclipse.persistence.sessions.Session; + +/** + * Convert between instances of XMLRoot and JAXBElement + */ +public class JAXBElementRootConverter implements XMLConverter { + + private Class declaredType; + private XMLConverter nestedConverter; + + public JAXBElementRootConverter(Class declaredType) { + this.declaredType = declaredType; + } + + public Converter getNestedConverter() { + return nestedConverter; + } + + public void setNestedConverter(XMLConverter nestedConverter) { + this.nestedConverter = nestedConverter; + } + + public void initialize(DatabaseMapping mapping, Session session) { + if(null != nestedConverter) { + nestedConverter.initialize(mapping, session); + } + } + + public Object convertDataValueToObjectValue(Object dataValue, Session session) { + return this.convertDataValueToObjectValue(dataValue, session, null); + } + + public Object convertDataValueToObjectValue(Object dataValue, Session session, XMLUnmarshaller unmarshaller) { + if(null != nestedConverter) { + dataValue = nestedConverter.convertDataValueToObjectValue(dataValue, session, unmarshaller); + } + if(dataValue instanceof JAXBElement) { + return dataValue; + } else if(dataValue instanceof XMLRoot) { + XMLRoot root = (XMLRoot)dataValue; + QName name = new QName(root.getNamespaceURI(), root.getLocalName()); + dataValue = root.getObject(); + if(null == dataValue) { + return createJAXBElement(name, Object.class, dataValue); + }else{ + return createJAXBElement(name, declaredType, dataValue); + } + } + return dataValue; + } + + public Object convertObjectValueToDataValue(Object objectValue, Session session) { + return this.convertObjectValueToDataValue(objectValue, session, null); + } + + public Object convertObjectValueToDataValue(Object objectValue, Session session, XMLMarshaller marshaller) { + if(null != nestedConverter) { + objectValue = nestedConverter.convertObjectValueToDataValue(objectValue, session, marshaller); + } + if(objectValue instanceof JAXBElement && !(objectValue instanceof WrappedValue)) { + JAXBElement element = (JAXBElement) objectValue; + XMLRoot root = new XMLRoot(); + root.setLocalName(element.getName().getLocalPart()); + root.setNamespaceURI(element.getName().getNamespaceURI()); + root.setObject(element.getValue()); + return root; + } + return objectValue; + } + + public boolean isMutable() { + return false; + } + + private JAXBElement createJAXBElement(QName qname, Class theClass, Object value){ + if(value != null && value instanceof JAXBElement){ + return (JAXBElement)value; + } + if(ClassConstants.XML_GREGORIAN_CALENDAR.isAssignableFrom(theClass)){ + theClass = ClassConstants.XML_GREGORIAN_CALENDAR; + }else if(ClassConstants.DURATION.isAssignableFrom(theClass)){ + theClass = ClassConstants.DURATION; + } + return new JAXBElement(qname, theClass, value); + } + +} \ No newline at end of file Index: src/org/eclipse/persistence/internal/jaxb/many/MapValueAttributeAccessor.java =================================================================== --- src/org/eclipse/persistence/internal/jaxb/many/MapValueAttributeAccessor.java (revision 4831) +++ src/org/eclipse/persistence/internal/jaxb/many/MapValueAttributeAccessor.java (working copy) @@ -42,6 +42,9 @@ public Object getAttributeValueFromObject(Object object)throws DescriptorException { Object value = nestedAccessor.getAttributeValueFromObject(object); + if(null == value) { + return null; + } Object results = containerPolicy.containerInstance(((Map)value).size()); Iterator iter = ((Map)value).keySet().iterator(); Index: src/org/eclipse/persistence/jaxb/compiler/MappingsGenerator.java =================================================================== --- src/org/eclipse/persistence/jaxb/compiler/MappingsGenerator.java (revision 4831) +++ src/org/eclipse/persistence/jaxb/compiler/MappingsGenerator.java (working copy) @@ -34,19 +34,20 @@ import org.eclipse.persistence.jaxb.xmlmodel.XmlJavaTypeAdapter; import org.eclipse.persistence.jaxb.JAXBEnumTypeConverter; import org.eclipse.persistence.internal.helper.ClassConstants; +import org.eclipse.persistence.internal.jaxb.DefaultElementConverter; +import org.eclipse.persistence.internal.jaxb.JAXBElementConverter; +import org.eclipse.persistence.internal.jaxb.JAXBElementRootConverter; import org.eclipse.persistence.internal.jaxb.JAXBSetMethodAttributeAccessor; import org.eclipse.persistence.internal.jaxb.JaxbClassLoader; import org.eclipse.persistence.internal.jaxb.DomHandlerConverter; import org.eclipse.persistence.internal.jaxb.MultiArgInstantiationPolicy; import org.eclipse.persistence.internal.jaxb.WrappedValue; -import org.eclipse.persistence.internal.jaxb.JAXBElementAttributeAccessor; -import org.eclipse.persistence.mappings.AttributeAccessor; import org.eclipse.persistence.mappings.DatabaseMapping; +import org.eclipse.persistence.mappings.converters.Converter; import org.eclipse.persistence.oxm.*; import org.eclipse.persistence.oxm.mappings.*; import org.eclipse.persistence.oxm.mappings.converters.XMLListConverter; -import org.eclipse.persistence.oxm.mappings.converters.XMLRootConverter; import org.eclipse.persistence.oxm.mappings.nullpolicy.IsSetNullPolicy; import org.eclipse.persistence.oxm.mappings.nullpolicy.NullPolicy; import org.eclipse.persistence.oxm.mappings.nullpolicy.XMLNullRepresentationType; @@ -368,6 +369,7 @@ public XMLChoiceCollectionMapping generateChoiceCollectionMapping(Property property, XMLDescriptor descriptor, NamespaceInfo namespace) { ChoiceProperty prop = (ChoiceProperty)property; XMLChoiceCollectionMapping mapping = new XMLChoiceCollectionMapping(); + mapping.setReuseContainer(true); mapping.setAttributeName(property.getPropertyName()); if (property.isMethodProperty()) { if (property.getGetMethodName() == null) { @@ -413,8 +415,11 @@ DatabaseMapping mapping; if(isCollection) { mapping = new XMLChoiceCollectionMapping(); + ((XMLChoiceCollectionMapping) mapping).setReuseContainer(true); + ((XMLChoiceCollectionMapping) mapping).setConverter(new JAXBElementRootConverter(Object.class)); } else { mapping = new XMLChoiceObjectMapping(); + ((XMLChoiceObjectMapping) mapping).setConverter(new JAXBElementRootConverter(Object.class)); } mapping.setAttributeName(property.getPropertyName()); if (property.isMethodProperty()) { @@ -434,14 +439,11 @@ } List referencedElements = property.getReferencedElements(); - boolean hasJAXBElements = false; - AttributeAccessor mappingAccessor = mapping.getAttributeAccessor(); if(property.getType().isArray()) { - JAXBObjectArrayAttributeAccessor accessor = new JAXBObjectArrayAttributeAccessor(mappingAccessor, mapping.getContainerPolicy()); + JAXBObjectArrayAttributeAccessor accessor = new JAXBObjectArrayAttributeAccessor(mapping.getAttributeAccessor(), mapping.getContainerPolicy()); accessor.setComponentClassName(property.getType().getComponentType().getRawName()); - mappingAccessor = accessor; + mapping.setAttributeAccessor(accessor); } - Map qNamesToScopeClass = new HashMap(); for(ElementDeclaration element:referencedElements) { QName elementName = element.getElementName(); boolean isText = !(this.typeInfo.containsKey(element.getJavaTypeName())) && !(element.getJavaTypeName().equals(OBJECT_CLASS_NAME)); @@ -450,77 +452,58 @@ if(helper.getXMLToJavaTypeMap().get(element.getJavaType().getRawName()) == XMLConstants.BASE_64_BINARY_QNAME) { xmlField.setSchemaType(XMLConstants.BASE_64_BINARY_QNAME); } - XMLMapping nestedMapping; - JAXBElementAttributeAccessor nestedAccessor; + DatabaseMapping nestedMapping; if(isCollection){ - - nestedAccessor = new JAXBElementAttributeAccessor(mappingAccessor, mapping.getContainerPolicy()); - ((XMLChoiceCollectionMapping)mapping).addChoiceElement(xmlField, element.getJavaTypeName()); - nestedMapping = ((XMLChoiceCollectionMapping)mapping).getChoiceElementMappings().get(xmlField); - if(((DatabaseMapping)nestedMapping).isAbstractCompositeCollectionMapping()){ + XMLChoiceCollectionMapping xmlChoiceCollectionMapping = (XMLChoiceCollectionMapping) mapping; + xmlChoiceCollectionMapping.addChoiceElement(xmlField, element.getJavaTypeName()); + nestedMapping = (DatabaseMapping) xmlChoiceCollectionMapping.getChoiceElementMappings().get(xmlField); + if(nestedMapping.isAbstractCompositeCollectionMapping()){ ((XMLCompositeCollectionMapping)nestedMapping).setKeepAsElementPolicy(UnmarshalKeepAsElementPolicy.KEEP_UNKNOWN_AS_ELEMENT); } - if (((DatabaseMapping) nestedMapping).isAbstractCompositeDirectCollectionMapping()) { + if (nestedMapping.isAbstractCompositeDirectCollectionMapping()) { ((XMLCompositeDirectCollectionMapping) nestedMapping).getNullPolicy().setNullRepresentedByEmptyNode(false); } - if (element.isList() && ((DatabaseMapping)nestedMapping).isAbstractCompositeDirectCollectionMapping()) { + if (element.isList() && nestedMapping.isAbstractCompositeDirectCollectionMapping()) { XMLListConverter listConverter = new XMLListConverter(); listConverter.setObjectClassName(element.getJavaType().getQualifiedName()); ((XMLCompositeDirectCollectionMapping)nestedMapping).setValueConverter(listConverter); } }else{ - nestedAccessor = new JAXBElementAttributeAccessor(mappingAccessor); - ((XMLChoiceObjectMapping)mapping).addChoiceElement(xmlField, element.getJavaTypeName()); - nestedMapping = ((XMLChoiceObjectMapping)mapping).getChoiceElementMappings().get(xmlField); - if(((DatabaseMapping)nestedMapping).isAbstractCompositeObjectMapping()){ + XMLChoiceObjectMapping xmlChoiceObjectMapping = (XMLChoiceObjectMapping) mapping; + xmlChoiceObjectMapping.addChoiceElement(xmlField, element.getJavaTypeName()); + nestedMapping = (DatabaseMapping) xmlChoiceObjectMapping.getChoiceElementMappings().get(xmlField); + if(nestedMapping.isAbstractCompositeObjectMapping()){ ((XMLCompositeObjectMapping)nestedMapping).setKeepAsElementPolicy(UnmarshalKeepAsElementPolicy.KEEP_UNKNOWN_AS_ELEMENT); } } - + if(!element.isXmlRootElement()) { - XMLRootConverter converter = new XMLRootConverter(xmlField); + Class scopeClass = element.getScopeClass(); + if(scopeClass == javax.xml.bind.annotation.XmlElementDecl.GLOBAL.class){ + scopeClass = JAXBElement.GlobalScope.class; + } + Class declaredType = helper.getClassForJavaClass(element.getJavaType()); + JAXBElementConverter converter = new JAXBElementConverter(xmlField, declaredType, scopeClass); if(isCollection){ - ((XMLChoiceCollectionMapping)mapping).addConverter(xmlField, converter); + XMLChoiceCollectionMapping xmlChoiceCollectionMapping = (XMLChoiceCollectionMapping) mapping; + Converter originalConverter = xmlChoiceCollectionMapping.getConverter(xmlField); + converter.setNestedConverter(originalConverter); + xmlChoiceCollectionMapping.addConverter(xmlField, converter); }else{ - ((XMLChoiceObjectMapping)mapping).addConverter(xmlField, converter); + XMLChoiceObjectMapping xmlChoiceObjectMapping = (XMLChoiceObjectMapping) mapping; + Converter originalConverter = xmlChoiceObjectMapping.getConverter(xmlField); + converter.setNestedConverter(originalConverter); + xmlChoiceObjectMapping.addConverter(xmlField, converter); } - Class scopeClass = element.getScopeClass(); - if(scopeClass == javax.xml.bind.annotation.XmlElementDecl.GLOBAL.class){ - scopeClass = JAXBElement.GlobalScope.class; - } - qNamesToScopeClass.put(elementName, scopeClass); } - hasJAXBElements = hasJAXBElements || !element.isXmlRootElement(); - Class theClass; - theClass = helper.getClassForJavaClass(element.getJavaType()); - - nestedAccessor.setDeclaredType(theClass); - - nestedAccessor.setQNamesToScopes(qNamesToScopeClass); - ((DatabaseMapping)nestedMapping).setAttributeAccessor(nestedAccessor); } - if(hasJAXBElements) { - JAXBElementAttributeAccessor accessor; - if(isCollection){ - accessor = new JAXBElementAttributeAccessor(mappingAccessor, mapping.getContainerPolicy()); - }else{ - accessor = new JAXBElementAttributeAccessor(mappingAccessor); - } - - Class theClass = helper.getClassForJavaClass(property.getActualType()); - accessor.setDeclaredType(theClass); - - accessor.setQNamesToScopes(qNamesToScopeClass); - mapping.setAttributeAccessor(accessor); - } descriptor.addMapping(mapping); return (XMLMapping)mapping; } - - + public XMLAnyCollectionMapping generateAnyCollectionMapping(Property property, XMLDescriptor descriptor, NamespaceInfo namespaceInfo, boolean isMixed) { boolean isLax = false; Class domHandlerClass = null; @@ -532,6 +515,7 @@ } XMLAnyCollectionMapping mapping = new XMLAnyCollectionMapping(); mapping.setAttributeName(property.getPropertyName()); + mapping.setReuseContainer(true); if (property.isMethodProperty()) { if (property.getGetMethodName() == null) { // handle case of set with no get method @@ -550,19 +534,18 @@ if(!isMixed) { mapping.setUseXMLRoot(true); } - JAXBElementAttributeAccessor accessor = new JAXBElementAttributeAccessor(mapping.getAttributeAccessor(), mapping.getContainerPolicy()); - Class theClass = helper.getClassForJavaClass(property.getActualType()); - accessor.setDeclaredType(theClass); - mapping.setAttributeAccessor(accessor); + Class declaredType = helper.getClassForJavaClass(property.getActualType()); + JAXBElementRootConverter jaxbElementRootConverter = new JAXBElementRootConverter(declaredType); + mapping.setConverter(jaxbElementRootConverter); + if(isLax) { mapping.setKeepAsElementPolicy(UnmarshalKeepAsElementPolicy.KEEP_UNKNOWN_AS_ELEMENT); } else { mapping.setKeepAsElementPolicy(UnmarshalKeepAsElementPolicy.KEEP_ALL_AS_ELEMENT); } if(domHandlerClass != null) { - DomHandlerConverter converter = new DomHandlerConverter(domHandlerClass); - mapping.setConverter(converter); + jaxbElementRootConverter.setNestedConverter(new DomHandlerConverter(domHandlerClass)); } descriptor.addMapping(mapping); mapping.setMixedContent(isMixed); @@ -599,6 +582,10 @@ if(referenceClassName == null){ ((XMLField)mapping.getField()).setIsTypedTextField(true); ((XMLField)mapping.getField()).setSchemaType(XMLConstants.ANY_TYPE_QNAME); + String defaultValue = property.getDefaultValue(); + if(null != defaultValue) { + mapping.setConverter(new DefaultElementConverter(defaultValue)); + } }else{ mapping.setReferenceClassName(referenceClassName); } @@ -764,6 +751,7 @@ public void generateEnumCollectionMapping(Property property, XMLDescriptor descriptor, NamespaceInfo namespaceInfo, EnumTypeInfo info) { XMLCompositeDirectCollectionMapping mapping = new XMLCompositeDirectCollectionMapping(); mapping.setAttributeName(property.getPropertyName()); + mapping.setReuseContainer(true); if (property.isMethodProperty()) { if (property.getGetMethodName() == null) { // handle case of set with no get method @@ -801,6 +789,7 @@ public void generateAnyAttributeMapping(Property property, XMLDescriptor descriptor, NamespaceInfo namespaceInfo) { XMLAnyAttributeMapping mapping = new XMLAnyAttributeMapping(); mapping.setAttributeName(property.getPropertyName()); + mapping.setReuseContainer(true); if (property.isMethodProperty()) { if (property.getGetMethodName() == null) { // handle case of set with no get method @@ -846,10 +835,9 @@ mapping.setKeepAsElementPolicy(UnmarshalKeepAsElementPolicy.KEEP_UNKNOWN_AS_ELEMENT); } mapping.setUseXMLRoot(true); - JAXBElementAttributeAccessor accessor = new JAXBElementAttributeAccessor(mapping.getAttributeAccessor()); - Class theClass = helper.getClassForJavaClass(property.getActualType()); - accessor.setDeclaredType(theClass); - mapping.setAttributeAccessor(accessor); + Class declaredType = helper.getClassForJavaClass(property.getActualType()); + JAXBElementRootConverter jaxbElementRootConverter = new JAXBElementRootConverter(declaredType); + mapping.setConverter(jaxbElementRootConverter); descriptor.addMapping(mapping); } @@ -879,6 +867,7 @@ public XMLCompositeCollectionMapping generateMapMapping(Property property, XMLDescriptor descriptor, NamespaceInfo namespaceInfo) { XMLCompositeCollectionMapping mapping = new XMLCompositeCollectionMapping(); mapping.setAttributeName(property.getPropertyName()); + mapping.setReuseContainer(true); XMLField field = getXPathForField(property, namespaceInfo, false); JavaClass descriptorClass = helper.getJavaClass(descriptor.getJavaClassName()); JavaClass mapValueClass = helper.getJavaClass(MapValue.class); @@ -1058,6 +1047,7 @@ public XMLCompositeCollectionMapping generateCompositeCollectionMapping(Property property, XMLDescriptor descriptor, NamespaceInfo namespaceInfo, String referenceClassName) { XMLCompositeCollectionMapping mapping = new XMLCompositeCollectionMapping(); mapping.setAttributeName(property.getPropertyName()); + mapping.setReuseContainer(true); if (property.isMethodProperty()) { if (property.getGetMethodName() == null) { // handle case of set with no get method @@ -1120,6 +1110,7 @@ public XMLCompositeDirectCollectionMapping generateDirectCollectionMapping(Property property, XMLDescriptor descriptor, NamespaceInfo namespaceInfo) { XMLCompositeDirectCollectionMapping mapping = new XMLCompositeDirectCollectionMapping(); mapping.setAttributeName(property.getPropertyName()); + mapping.setReuseContainer(true); if (property.isMethodProperty()) { if (property.getGetMethodName() == null) { // handle case of set with no get method @@ -1367,6 +1358,7 @@ XMLField srcXPath = getXPathForField(property, namespaceInfo, true); XMLCollectionReferenceMapping mapping = new XMLCollectionReferenceMapping(); mapping.setAttributeName(property.getPropertyName()); + mapping.setReuseContainer(true); if (property.isMethodProperty()) { if (property.getGetMethodName() == null) { // handle case of set with no get method @@ -1673,6 +1665,7 @@ mapping.setAttributeName("value"); mapping.setXPath("text()"); mapping.setUsesSingleNode(true); + mapping.setReuseContainer(true); if(type != null && type.isEnumerationType()){ mapping.setValueConverter(buildJAXBEnumTypeConverter(mapping, (EnumTypeInfo)type)); Index: src/org/eclipse/persistence/jaxb/compiler/ReferenceProperty.java =================================================================== --- src/org/eclipse/persistence/jaxb/compiler/ReferenceProperty.java (revision 4831) +++ src/org/eclipse/persistence/jaxb/compiler/ReferenceProperty.java (working copy) @@ -27,7 +27,9 @@ if(referencedElements == null) { referencedElements = new ArrayList(); } - referencedElements.add(element); + if(!referencedElements.contains(element)) { + referencedElements.add(element); + } } public boolean isReference() {