blob: aad770849d1cba2206426ed252dc8c46793011f7 [file] [log] [blame]
/*
* Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
// Contributors:
// Oracle - initial API and implementation from Oracle TopLink
package org.eclipse.persistence.internal.oxm;
import java.lang.reflect.Modifier;
import java.util.List;
import javax.xml.namespace.QName;
import org.eclipse.persistence.core.queries.CoreAttributeGroup;
import org.eclipse.persistence.core.queries.CoreAttributeItem;
import org.eclipse.persistence.core.sessions.CoreSession;
import org.eclipse.persistence.exceptions.DescriptorException;
import org.eclipse.persistence.exceptions.XMLMarshalException;
import org.eclipse.persistence.internal.core.sessions.CoreAbstractSession;
import org.eclipse.persistence.internal.oxm.mappings.CompositeObjectMapping;
import org.eclipse.persistence.internal.oxm.mappings.Descriptor;
import org.eclipse.persistence.internal.oxm.mappings.DirectMapping;
import org.eclipse.persistence.internal.oxm.mappings.Field;
import org.eclipse.persistence.internal.oxm.mappings.InverseReferenceMapping;
import org.eclipse.persistence.internal.oxm.mappings.Mapping;
import org.eclipse.persistence.internal.oxm.mappings.UnmarshalKeepAsElementPolicy;
import org.eclipse.persistence.internal.oxm.record.MarshalContext;
import org.eclipse.persistence.internal.oxm.record.MarshalRecord;
import org.eclipse.persistence.internal.oxm.record.ObjectMarshalContext;
import org.eclipse.persistence.internal.oxm.record.UnmarshalRecord;
import org.eclipse.persistence.internal.oxm.record.XMLReader;
import org.eclipse.persistence.internal.oxm.record.XMLRecord;
import org.eclipse.persistence.internal.oxm.record.deferred.CompositeObjectMappingContentHandler;
import org.eclipse.persistence.oxm.XMLRoot;
import org.eclipse.persistence.oxm.mappings.nullpolicy.AbstractNullPolicy;
import org.eclipse.persistence.platform.xml.XMLPlatformFactory;
import org.w3c.dom.Attr;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
/**
* INTERNAL:
* <p><b>Purpose</b>: This is how the XML Composite Object Mapping is handled
* when used with the TreeObjectBuilder.</p>
*/
public class XMLCompositeObjectMappingNodeValue extends XMLRelationshipMappingNodeValue implements NullCapableValue {
private CompositeObjectMapping xmlCompositeObjectMapping;
private boolean isInverseReference;
public XMLCompositeObjectMappingNodeValue(CompositeObjectMapping xmlCompositeObjectMapping) {
this.xmlCompositeObjectMapping = xmlCompositeObjectMapping;
}
public XMLCompositeObjectMappingNodeValue(CompositeObjectMapping xmlCompositeObjectMapping, boolean isInverse) {
this(xmlCompositeObjectMapping);
isInverseReference = isInverse;
}
@Override
public void attribute(UnmarshalRecord unmarshalRecord, String namespaceURI, String localName, String value) {
unmarshalRecord.removeNullCapableValue(this);
Descriptor referenceDescriptor = (Descriptor) getMapping().getReferenceDescriptor();
ObjectBuilder treeObjectBuilder = (ObjectBuilder) referenceDescriptor.getObjectBuilder();
MappingNodeValue textMappingNodeValue = (MappingNodeValue) treeObjectBuilder.getRootXPathNode().getTextNode().getNodeValue();
Mapping textMapping = textMappingNodeValue.getMapping();
Object childObject = referenceDescriptor.getInstantiationPolicy().buildNewInstance();
if(textMapping.isAbstractDirectMapping()) {
DirectMapping xmlDirectMapping = (DirectMapping) textMappingNodeValue.getMapping();
Field xmlField = (Field) xmlDirectMapping.getField();
Object realValue = unmarshalRecord.getXMLReader().convertValueBasedOnSchemaType(xmlField, value, (ConversionManager) unmarshalRecord.getSession().getDatasourcePlatform().getConversionManager(), unmarshalRecord);
Object convertedValue = xmlDirectMapping.getAttributeValue(realValue, unmarshalRecord.getSession(), unmarshalRecord);
xmlDirectMapping.setAttributeValueInObject(childObject, convertedValue);
} else {
Object oldChildObject = unmarshalRecord.getCurrentObject();
CompositeObjectMapping nestedXMLCompositeObjectMapping = (CompositeObjectMapping) textMappingNodeValue.getMapping();
unmarshalRecord.setCurrentObject(childObject);
textMappingNodeValue.attribute(unmarshalRecord, namespaceURI, localName, value);
unmarshalRecord.setCurrentObject(oldChildObject);
}
setAttributeValue(childObject, unmarshalRecord);
}
/**
* Marshal any 'self' mapped attributes.
*
*/
@Override
public boolean marshalSelfAttributes(XPathFragment xPathFragment, MarshalRecord marshalRecord, Object object, CoreAbstractSession session, NamespaceResolver namespaceResolver, Marshaller marshaller) {
Object objectValue = xmlCompositeObjectMapping.getAttributeValueFromObject(object);
objectValue = xmlCompositeObjectMapping.convertObjectValueToDataValue(objectValue, session, marshaller);
Descriptor descriptor = (Descriptor)session.getDescriptor(objectValue);
if(descriptor != null){
ObjectBuilder objectBuilder = (ObjectBuilder)descriptor.getObjectBuilder();
return objectBuilder.marshalAttributes(marshalRecord, objectValue, session);
} else {
UnmarshalKeepAsElementPolicy keepAsElementPolicy = getMapping().getKeepAsElementPolicy();
if(null != keepAsElementPolicy && (keepAsElementPolicy.isKeepAllAsElement() || keepAsElementPolicy.isKeepUnknownAsElement())) {
if(objectValue instanceof Node) {
Node rootNode = (Node)objectValue;
NamedNodeMap attributes = rootNode.getAttributes();
for(int i = 0; i < attributes.getLength(); i++) {
Attr next = (Attr)attributes.item(i);
if(!(javax.xml.XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(next.getNamespaceURI()))) {
marshalRecord.node(next, namespaceResolver);
}
}
}
}
}
return false;
}
@Override
public boolean marshal(XPathFragment xPathFragment, MarshalRecord marshalRecord, Object object, CoreAbstractSession session, NamespaceResolver namespaceResolver) {
return marshal(xPathFragment, marshalRecord, object, session, namespaceResolver, ObjectMarshalContext.getInstance());
}
@Override
public boolean marshal(XPathFragment xPathFragment, MarshalRecord marshalRecord, Object object, CoreAbstractSession session, NamespaceResolver namespaceResolver, MarshalContext marshalContext) {
if (xmlCompositeObjectMapping.isReadOnly()) {
return false;
}
int size =marshalRecord.getCycleDetectionStack().size();
Object objectValue = marshalContext.getAttributeValue(object, xmlCompositeObjectMapping);
if ((isInverseReference || xmlCompositeObjectMapping.getInverseReferenceMapping() != null) && objectValue != null && size >= 2) {
Object owner = marshalRecord.getCycleDetectionStack().get(size - 2);
if (objectValue.equals(owner)) {
return false;
}
}
return this.marshalSingleValue(xPathFragment, marshalRecord, object, objectValue, session, namespaceResolver, marshalContext);
}
private boolean isNil(Object value) {
if (value instanceof XMLRoot) {
return ((XMLRoot)value).isNil();
}
return false;
}
@Override
public boolean marshalSingleValue(XPathFragment xPathFragment, MarshalRecord marshalRecord, Object object, Object objectValue, CoreAbstractSession session, NamespaceResolver namespaceResolver, MarshalContext marshalContext) {
boolean isNilFlag = isNil(objectValue);
objectValue = xmlCompositeObjectMapping.convertObjectValueToDataValue(objectValue, session, marshalRecord.getMarshaller());
if (null == objectValue) {
return xmlCompositeObjectMapping.getNullPolicy().compositeObjectMarshal(xPathFragment, marshalRecord, object, session, namespaceResolver);
}
XPathFragment groupingFragment = marshalRecord.openStartGroupingElements(namespaceResolver);
if(xPathFragment.hasAttribute) {
ObjectBuilder tob = (ObjectBuilder) xmlCompositeObjectMapping.getReferenceDescriptor().getObjectBuilder();
MappingNodeValue textMappingNodeValue = (MappingNodeValue) tob.getRootXPathNode().getTextNode().getMarshalNodeValue();
Mapping textMapping = textMappingNodeValue.getMapping();
if(textMapping.isAbstractDirectMapping()) {
DirectMapping xmlDirectMapping = (DirectMapping) textMapping;
Object fieldValue = xmlDirectMapping.getFieldValue(xmlDirectMapping.valueFromObject(objectValue, xmlDirectMapping.getField(), session), session, marshalRecord);
QName schemaType = ((Field) xmlDirectMapping.getField()).getSchemaTypeForValue(fieldValue, session);
if(fieldValue != null) {
marshalRecord.attribute(xPathFragment, namespaceResolver, fieldValue, schemaType);
} else {
XMLMarshalException ex = XMLMarshalException.nullValueNotAllowed(this.xmlCompositeObjectMapping.getAttributeName(), this.xmlCompositeObjectMapping.getDescriptor().getJavaClass().getName());
try {
marshalRecord.getMarshaller().getErrorHandler().warning(new SAXParseException(null, null, ex));
} catch(Exception saxException) {
throw ex;
}
}
marshalRecord.closeStartGroupingElements(groupingFragment);
return true;
} else {
return textMappingNodeValue.marshalSingleValue(xPathFragment, marshalRecord, objectValue, textMapping.getAttributeValueFromObject(objectValue), session, namespaceResolver, marshalContext);
}
}
boolean isSelfFragment = xPathFragment.isSelfFragment;
marshalRecord.closeStartGroupingElements(groupingFragment);
UnmarshalKeepAsElementPolicy keepAsElementPolicy = xmlCompositeObjectMapping.getKeepAsElementPolicy();
if (null != keepAsElementPolicy && (keepAsElementPolicy.isKeepUnknownAsElement() || keepAsElementPolicy.isKeepAllAsElement()) && objectValue instanceof Node) {
if (isSelfFragment) {
NodeList children = ((org.w3c.dom.Element) objectValue).getChildNodes();
for (int i = 0, childrenLength = children.getLength(); i < childrenLength ; i++) {
Node next = children.item(i);
short nodeType = next.getNodeType();
if (nodeType == Node.ELEMENT_NODE) {
marshalRecord.node(next, marshalRecord.getNamespaceResolver());
return true;
} else if (nodeType == Node.TEXT_NODE) {
marshalRecord.characters(next.getNodeValue());
return true;
}
}
return false;
} else {
marshalRecord.node((Node) objectValue, marshalRecord.getNamespaceResolver());
return true;
}
}
Descriptor descriptor = (Descriptor)xmlCompositeObjectMapping.getReferenceDescriptor();
if(descriptor == null){
descriptor = (Descriptor) session.getDescriptor(objectValue.getClass());
}else if(descriptor.hasInheritance()){
Class objectValueClass = objectValue.getClass();
if(!(objectValueClass == descriptor.getJavaClass())){
descriptor = (Descriptor) session.getDescriptor(objectValueClass);
}
}
if(descriptor != null){
marshalRecord.beforeContainmentMarshal(objectValue);
ObjectBuilder objectBuilder = (ObjectBuilder)descriptor.getObjectBuilder();
CoreAttributeGroup group = marshalRecord.getCurrentAttributeGroup();
CoreAttributeItem item = group.getItem(getMapping().getAttributeName());
CoreAttributeGroup nestedGroup = XMLRecord.DEFAULT_ATTRIBUTE_GROUP;
if(item != null) {
if(item.getGroups() != null) {
nestedGroup = item.getGroup(descriptor.getJavaClass());
}
if(nestedGroup == null) {
nestedGroup = item.getGroup() == null?XMLRecord.DEFAULT_ATTRIBUTE_GROUP:item.getGroup();
}
}
marshalRecord.pushAttributeGroup(nestedGroup);
if (!(isSelfFragment || xPathFragment.nameIsText)) {
xPathNode.startElement(marshalRecord, xPathFragment, object, session, namespaceResolver, objectBuilder, objectValue);
if (isNilFlag) {
marshalRecord.nilSimple(namespaceResolver);
}
}
List extraNamespaces = null;
if (marshalRecord.getNamespaceResolver() != null && descriptor.getNamespaceResolver() != null) {
for (String prefix: descriptor.getNamespaceResolver().getPrefixesToNamespaces().keySet()) {
if (!marshalRecord.getNamespaceResolver().hasPrefix(prefix)) {
marshalRecord.setEqualNamespaceResolvers(false);
break;
}
}
}
if (!marshalRecord.hasEqualNamespaceResolvers()) {
extraNamespaces = objectBuilder.addExtraNamespacesToNamespaceResolver(descriptor, marshalRecord, session, true, false);
writeExtraNamespaces(extraNamespaces, marshalRecord, session);
}
if(!isSelfFragment) {
marshalRecord.addXsiTypeAndClassIndicatorIfRequired(descriptor, (Descriptor) xmlCompositeObjectMapping.getReferenceDescriptor(), (Field)xmlCompositeObjectMapping.getField(), false);
}
objectBuilder.buildRow(marshalRecord, objectValue, session, marshalRecord.getMarshaller(), xPathFragment);
marshalRecord.afterContainmentMarshal(object, objectValue);
marshalRecord.popAttributeGroup();
if (!(isSelfFragment || xPathFragment.nameIsText())) {
marshalRecord.endElement(xPathFragment, namespaceResolver);
}
marshalRecord.removeExtraNamespacesFromNamespaceResolver(extraNamespaces, session);
} else {
if(Constants.UNKNOWN_OR_TRANSIENT_CLASS.equals(xmlCompositeObjectMapping.getReferenceClassName())){
throw XMLMarshalException.descriptorNotFoundInProject(objectValue.getClass().getName());
}
if (!(isSelfFragment || xPathFragment.nameIsText())) {
xPathNode.startElement(marshalRecord, xPathFragment, object, session, namespaceResolver, null, objectValue);
}
QName schemaType = ((Field) xmlCompositeObjectMapping.getField()).getSchemaTypeForValue(objectValue,session);
updateNamespaces(schemaType, marshalRecord,((Field)xmlCompositeObjectMapping.getField()));
marshalRecord.characters(schemaType, objectValue, null, false);
if (!(isSelfFragment || xPathFragment.nameIsText())) {
marshalRecord.endElement(xPathFragment, namespaceResolver);
}
}
return true;
}
@Override
public boolean startElement(XPathFragment xPathFragment, UnmarshalRecord unmarshalRecord, Attributes atts) {
try {
unmarshalRecord.removeNullCapableValue(this);
Descriptor xmlDescriptor = (Descriptor)xmlCompositeObjectMapping.getReferenceDescriptor();
if (null == xmlDescriptor) {
xmlDescriptor = findReferenceDescriptor(xPathFragment, unmarshalRecord, atts, xmlCompositeObjectMapping,xmlCompositeObjectMapping.getKeepAsElementPolicy());
if(xmlDescriptor == null){
if(xmlCompositeObjectMapping.getField() != null){
//try leaf element type
QName leafType = ((Field)xmlCompositeObjectMapping.getField()).getLastXPathFragment().getLeafElementType();
if (leafType != null) {
XPathFragment frag = new XPathFragment();
frag.setNamespaceAware(unmarshalRecord.isNamespaceAware());
String xpath = leafType.getLocalPart();
String uri = leafType.getNamespaceURI();
if (uri != null && uri.length() > 0) {
frag.setNamespaceURI(uri);
String prefix = ((Descriptor)xmlCompositeObjectMapping.getDescriptor()).getNonNullNamespaceResolver().resolveNamespaceURI(uri);
if (prefix != null && prefix.length() > 0) {
xpath = prefix + Constants.COLON + xpath;
}
}
frag.setXPath(xpath);
Context xmlContext = unmarshalRecord.getUnmarshaller().getContext();
xmlDescriptor = xmlContext.getDescriptorByGlobalType(frag);
}
}
}
UnmarshalKeepAsElementPolicy policy = xmlCompositeObjectMapping.getKeepAsElementPolicy();
if (null != policy && ((xmlDescriptor == null && policy.isKeepUnknownAsElement()) || policy.isKeepAllAsElement())) {
QName schemaType = unmarshalRecord.getTypeQName();
if(schemaType == null){
schemaType = ((Field)xmlCompositeObjectMapping.getField()).getSchemaType();
unmarshalRecord.setTypeQName(schemaType);
}
if(schemaType != null){
Class theClass = unmarshalRecord.getConversionManager().javaType(schemaType);
if(theClass == null){
setupHandlerForKeepAsElementPolicy(unmarshalRecord, xPathFragment, atts);
return true;
}
}else{
setupHandlerForKeepAsElementPolicy(unmarshalRecord, xPathFragment, atts);
return true;
}
}
}
//
// Null Composite Objects are marshalled in 2 ways when the input XML node is empty.
// (1) as null
// - isNullRepresentedByEmptyNode = true
// (2) as empty object
// - isNullRepresentedByEmptyNode = false
// A deferred contentHandler is used to queue events until we are able to determine
// whether we are in one of empty/simple/complex state.
// Control is returned to the UnmarshalHandler after creation of (1) or (2) above is started.
// Object creation was deferred to the DeferredContentHandler
//
// Check if we need to create the DeferredContentHandler based on policy state
AbstractNullPolicy nullPolicy = xmlCompositeObjectMapping.getNullPolicy();
if(nullPolicy.isNullRepresentedByEmptyNode()) {
String qnameString = xPathFragment.getLocalName();
if(xPathFragment.getPrefix() != null) {
qnameString = xPathFragment.getPrefix() + Constants.COLON + qnameString;
}
if(null != xmlDescriptor) {
// Process null capable value
CompositeObjectMappingContentHandler aHandler = new CompositeObjectMappingContentHandler(//
unmarshalRecord, this, xmlCompositeObjectMapping, atts, xPathFragment, xmlDescriptor);
// Send control to the handler
aHandler.startElement(xPathFragment.getNamespaceURI(), xPathFragment.getLocalName(), qnameString, atts);
XMLReader xmlReader = unmarshalRecord.getXMLReader();
xmlReader.setContentHandler(aHandler);
xmlReader.setLexicalHandler(aHandler);
}
} else {
if(unmarshalRecord.getXMLReader().isNullRecord(nullPolicy, atts, unmarshalRecord) && nullPolicy.ignoreAttributesForNil()){
xmlCompositeObjectMapping.setAttributeValueInObject(unmarshalRecord.getCurrentObject(), null);
} else {
Field xmlFld = (Field)this.xmlCompositeObjectMapping.getField();
if (xmlFld.hasLastXPathFragment()) {
unmarshalRecord.setLeafElementType(xmlFld.getLastXPathFragment().getLeafElementType());
}
processChild(xPathFragment, unmarshalRecord, atts, xmlDescriptor, xmlCompositeObjectMapping);
}
}
} catch (SAXException e) {
throw XMLMarshalException.unmarshalException(e);
}
return true;
}
@Override
public void endElement(XPathFragment xPathFragment, UnmarshalRecord unmarshalRecord) {
if(unmarshalRecord.isNil() && xmlCompositeObjectMapping.getNullPolicy().isNullRepresentedByXsiNil() && (unmarshalRecord.getChildRecord() == null)){
unmarshalRecord.resetStringBuffer();
return;
}
if (null == unmarshalRecord.getChildRecord()) {
SAXFragmentBuilder builder = unmarshalRecord.getFragmentBuilder();
UnmarshalKeepAsElementPolicy keepAsElementPolicy = xmlCompositeObjectMapping.getKeepAsElementPolicy();
if (null != keepAsElementPolicy && (keepAsElementPolicy.isKeepUnknownAsElement() || keepAsElementPolicy.isKeepAllAsElement()) && builder.getNodes().size() != 0) {
if(unmarshalRecord.getTypeQName() != null){
Class theClass = unmarshalRecord.getConversionManager().javaType(unmarshalRecord.getTypeQName());
if(theClass != null){
//handle simple text
endElementProcessText(unmarshalRecord, xmlCompositeObjectMapping, xPathFragment, null);
return;
}
}
if (builder.getDocument() != null) {
setOrAddAttributeValueForKeepAsElement(builder, xmlCompositeObjectMapping, xmlCompositeObjectMapping, unmarshalRecord, false, null);
return;
}
}else{
//handle simple text
endElementProcessText(unmarshalRecord, xmlCompositeObjectMapping, xPathFragment, null);
return;
}
} else {
Object object = unmarshalRecord.getChildRecord().getCurrentObject();
setAttributeValue(object, unmarshalRecord);
unmarshalRecord.setChildRecord(null);
}
}
private void setAttributeValue(Object object, UnmarshalRecord unmarshalRecord) {
InverseReferenceMapping inverseReferenceMapping = xmlCompositeObjectMapping.getInverseReferenceMapping();
//If isInverseReference then this mapping is an inlineMapping of an InverseReference
if(null != inverseReferenceMapping){
if(inverseReferenceMapping.getContainerPolicy() == null) {
Object currentValue = inverseReferenceMapping.getAttributeAccessor().getAttributeValueFromObject(object);
if( !isInverseReference || (currentValue == null && isInverseReference)) {
inverseReferenceMapping.getAttributeAccessor().setAttributeValueInObject(object, unmarshalRecord.getCurrentObject());
}
} else {
Object backpointerContainer = inverseReferenceMapping.getAttributeAccessor().getAttributeValueFromObject(object);
if(backpointerContainer == null) {
backpointerContainer = inverseReferenceMapping.getContainerPolicy().containerInstance();
inverseReferenceMapping.getAttributeAccessor().setAttributeValueInObject(object, backpointerContainer);
}
inverseReferenceMapping.getContainerPolicy().addInto(unmarshalRecord.getCurrentObject(), backpointerContainer, unmarshalRecord.getSession());
}
}
object = xmlCompositeObjectMapping.convertDataValueToObjectValue(object, unmarshalRecord.getSession(), unmarshalRecord.getUnmarshaller());
// Set the child object on the parent
unmarshalRecord.setAttributeValue(object, xmlCompositeObjectMapping);
}
@Override
public void endSelfNodeValue(UnmarshalRecord unmarshalRecord, UnmarshalRecord selfRecord, Attributes attributes) {
if(xmlCompositeObjectMapping.getNullPolicy().valueIsNull(attributes)){
xmlCompositeObjectMapping.setAttributeValueInObject(unmarshalRecord.getCurrentObject(), null);
return;
}
unmarshalRecord.removeNullCapableValue(this);
if (unmarshalRecord.getFragmentBuilder().getDocument() != null) {
UnmarshalKeepAsElementPolicy keepAsElementPolicy = xmlCompositeObjectMapping.getKeepAsElementPolicy();
SAXFragmentBuilder builder = unmarshalRecord.getFragmentBuilder();
if ((((keepAsElementPolicy.isKeepUnknownAsElement()) || (keepAsElementPolicy.isKeepAllAsElement())))&& (builder.getNodes().size() != 0) ) {
if(unmarshalRecord.getTypeQName() != null){
Class theClass = unmarshalRecord.getConversionManager().javaType(unmarshalRecord.getTypeQName());
if(theClass != null){
//handle simple text
endElementProcessText(unmarshalRecord, xmlCompositeObjectMapping, null, null);
return;
}
}
Element element = (Element) builder.getNodes().remove(builder.getNodes().size() -1);
String xsiType = null;
if(null != element) {
if(unmarshalRecord.isNamespaceAware()){
xsiType = element.getAttributeNS(javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, Constants.SCHEMA_TYPE_ATTRIBUTE);
}else{
xsiType = element.getAttribute(Constants.SCHEMA_TYPE_ATTRIBUTE);
}
}
if(null != xsiType) {
xsiType = xsiType.trim();
Object value = element;
String namespace = null;
int colonIndex = xsiType.indexOf(unmarshalRecord.getNamespaceSeparator());
if (colonIndex > -1) {
String prefix = xsiType.substring(0, colonIndex);
namespace = unmarshalRecord.resolveNamespacePrefix(prefix);
if(null == namespace) {
namespace = XMLPlatformFactory.getInstance().getXMLPlatform().resolveNamespacePrefix(element, prefix);
}
QName qName = new QName(namespace, xsiType.substring(colonIndex + 1));
ConversionManager conversionManager = unmarshalRecord.getConversionManager();
Class theClass = conversionManager.javaType(qName);
if (theClass != null) {
value = conversionManager.convertObject(element.getTextContent(), theClass, qName);
}
}else{
if(!unmarshalRecord.isNamespaceAware() || !unmarshalRecord.getUnmarshaller().getJsonTypeConfiguration().useXsdTypesWithPrefix()){
QName qName = new QName(javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI, xsiType);
ConversionManager conversionManager = unmarshalRecord.getConversionManager();
Class theClass = conversionManager.javaType(qName);
if (theClass != null) {
value = conversionManager.convertObject(element.getTextContent(), theClass, qName);
}
}
}
xmlCompositeObjectMapping.setAttributeValueInObject(unmarshalRecord.getCurrentObject(), value);
} else {
xmlCompositeObjectMapping.setAttributeValueInObject(unmarshalRecord.getCurrentObject(), element);
}
}
} else {
Object valueToSet = selfRecord.getCurrentObject();
valueToSet = xmlCompositeObjectMapping.convertDataValueToObjectValue(valueToSet, unmarshalRecord.getSession(), unmarshalRecord.getUnmarshaller());
xmlCompositeObjectMapping.setAttributeValueInObject(unmarshalRecord.getCurrentObject(), valueToSet);
InverseReferenceMapping inverseReferenceMapping = xmlCompositeObjectMapping.getInverseReferenceMapping();
if (null != inverseReferenceMapping) {
inverseReferenceMapping.getAttributeAccessor().setAttributeValueInObject(valueToSet, unmarshalRecord.getCurrentObject());
}
}
}
@Override
public UnmarshalRecord buildSelfRecord(UnmarshalRecord unmarshalRecord, Attributes atts) {
try {
Descriptor xmlDescriptor = (Descriptor)xmlCompositeObjectMapping.getReferenceDescriptor();
if (null == xmlDescriptor) {
xmlDescriptor = findReferenceDescriptor(null, unmarshalRecord, atts, xmlCompositeObjectMapping,xmlCompositeObjectMapping.getKeepAsElementPolicy());
}
if(xmlDescriptor != null){
if (xmlDescriptor.hasInheritance()) {
unmarshalRecord.setAttributes(atts);
Class clazz = ((ObjectBuilder)xmlDescriptor.getObjectBuilder()).classFromRow(unmarshalRecord, unmarshalRecord.getSession());
if (clazz == null) {
// no xsi:type attribute - look for type indicator on the default root element
XPathQName leafElementType = unmarshalRecord.getLeafElementType();
// if we have a user-set type, try to get the class from the inheritance policy
if (leafElementType != null) {
Object indicator = xmlDescriptor.getInheritancePolicy().getClassIndicatorMapping().get(leafElementType);
if(indicator != null) {
clazz = (Class)indicator;
}
}
}
if (clazz != null) {
xmlDescriptor = (Descriptor)unmarshalRecord.getSession().getDescriptor(clazz);
} else {
// since there is no xsi:type attribute, use the reference descriptor set
// on the mapping - make sure it is non-abstract
if (Modifier.isAbstract(xmlDescriptor.getJavaClass().getModifiers())) {
// need to throw an exception here
throw DescriptorException.missingClassIndicatorField(unmarshalRecord, (org.eclipse.persistence.oxm.XMLDescriptor)xmlDescriptor.getInheritancePolicy().getDescriptor());
}
}
}
UnmarshalRecord childRecord = unmarshalRecord.getChildUnmarshalRecord((ObjectBuilder) xmlDescriptor.getObjectBuilder());
childRecord.setSelfRecord(true);
unmarshalRecord.setChildRecord(childRecord);
childRecord.startDocument();
childRecord.initializeRecord(this.xmlCompositeObjectMapping);
return childRecord;
} else{
return null;
}
} catch (SAXException e) {
throw XMLMarshalException.unmarshalException(e);
}
}
@Override
public void setNullValue(Object object, CoreSession session) {
xmlCompositeObjectMapping.setAttributeValueInObject(object, null);
}
@Override
public boolean isNullCapableValue() {
if(xmlCompositeObjectMapping.getAttributeAccessor().isInstanceVariableAttributeAccessor() && !xmlCompositeObjectMapping.hasConverter()) {
return false;
}
Field xmlField = (Field)xmlCompositeObjectMapping.getField();
if (xmlField.getLastXPathFragment().isSelfFragment) {
return false;
}
return xmlCompositeObjectMapping.getNullPolicy().getIsSetPerformedForAbsentNode();
}
@Override
public CompositeObjectMapping getMapping() {
return xmlCompositeObjectMapping;
}
@Override
protected void setOrAddAttributeValue(UnmarshalRecord unmarshalRecord, Object value, XPathFragment xPathFragment, Object collection){
unmarshalRecord.setAttributeValue(value, xmlCompositeObjectMapping);
}
}