org.eclipse.persistence.internal.oxm.XMLAnyObjectMappingNodeValue Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of eclipselink Show documentation
Show all versions of eclipselink Show documentation
EclipseLink build based upon Git transaction f2b9fc5
/*
* Copyright (c) 1998, 2018 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.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.XMLMarshalException;
import org.eclipse.persistence.internal.core.sessions.CoreAbstractSession;
import org.eclipse.persistence.internal.oxm.mappings.AnyObjectMapping;
import org.eclipse.persistence.internal.oxm.mappings.Descriptor;
import org.eclipse.persistence.internal.oxm.mappings.Field;
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.AnyMappingContentHandler;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
/**
* INTERNAL:
* Purpose: This is how the XML Any Object Mapping is handled when
* used with the TreeObjectBuilder.
*/
public class XMLAnyObjectMappingNodeValue extends XMLRelationshipMappingNodeValue {
private AnyObjectMapping xmlAnyObjectMapping;
public XMLAnyObjectMappingNodeValue(AnyObjectMapping xmlAnyObjectMapping) {
super();
this.xmlAnyObjectMapping = xmlAnyObjectMapping;
}
public boolean isOwningNode(XPathFragment xPathFragment) {
return null == xPathFragment;
}
public boolean marshal(XPathFragment xPathFragment, MarshalRecord marshalRecord, Object object, CoreAbstractSession session, NamespaceResolver namespaceResolver) {
return marshal(xPathFragment, marshalRecord, object, session, namespaceResolver, ObjectMarshalContext.getInstance());
}
public boolean marshal(XPathFragment xPathFragment, MarshalRecord marshalRecord, Object object, CoreAbstractSession session, NamespaceResolver namespaceResolver, MarshalContext marshalContext) {
if (xmlAnyObjectMapping.isReadOnly()) {
return false;
}
Object objectValue = marshalContext.getAttributeValue(object, xmlAnyObjectMapping);
return this.marshalSingleValue(xPathFragment, marshalRecord, object, objectValue, session, namespaceResolver, marshalContext);
}
public boolean marshalSingleValue(XPathFragment xPathFragment, MarshalRecord marshalRecord, Object object, Object objectValue, CoreAbstractSession session, NamespaceResolver namespaceResolver, MarshalContext marshalContext) {
XPathFragment rootFragment = null;
Marshaller marshaller = marshalRecord.getMarshaller();
objectValue = xmlAnyObjectMapping.convertObjectValueToDataValue(objectValue, session, marshalRecord.getMarshaller());
if (null == objectValue) {
return false;
}
XPathFragment groupingFragment = marshalRecord.openStartGroupingElements(namespaceResolver);
marshalRecord.closeStartGroupingElements(groupingFragment);
boolean wasXMLRoot = false;
XPathFragment xmlRootFragment = null;
Object originalValue = objectValue;
if (xmlAnyObjectMapping.usesXMLRoot() && (objectValue instanceof Root)) {
xmlRootFragment = new XPathFragment();
xmlRootFragment.setNamespaceAware(marshalRecord.isNamespaceAware());
wasXMLRoot = true;
objectValue = ((Root) objectValue).getObject();
if(objectValue == null){
setupFragment(((Root) originalValue), xmlRootFragment, marshalRecord);
marshalRecord.nilComplex(xmlRootFragment, namespaceResolver);
return true;
}
}
if (objectValue instanceof String) {
marshalSimpleValue(xmlRootFragment, marshalRecord, originalValue, object, objectValue, session, namespaceResolver);
} else {
CoreSession childSession = null;
try {
childSession = marshaller.getContext().getSession(objectValue);
} catch (XMLMarshalException e) {
marshalSimpleValue(xmlRootFragment, marshalRecord, originalValue, object, objectValue, session, namespaceResolver);
return true;
}
Descriptor descriptor = (Descriptor) childSession.getDescriptor(objectValue);
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);
ObjectBuilder objectBuilder = (ObjectBuilder) descriptor.getObjectBuilder();
List extraNamespaces = objectBuilder.addExtraNamespacesToNamespaceResolver(descriptor, marshalRecord, session, true, true);
if(wasXMLRoot){
setupFragment(((Root) originalValue), xmlRootFragment, marshalRecord);
}
/*
* B5112171: 25 Apr 2006
* During marshalling - XML AnyObject and AnyCollection
* mappings throw a NullPointerException when the
* "document root element" on child object descriptors are not
* all defined. These nodes will be ignored with a warning.
*/
String defaultRootElementString = descriptor.getDefaultRootElement();
if (!wasXMLRoot && (defaultRootElementString == null)) {
throw XMLMarshalException.defaultRootElementNotSpecified(descriptor);
} else {
marshalRecord.beforeContainmentMarshal(objectValue);
if (xmlRootFragment != null) {
rootFragment = xmlRootFragment;
} else {
rootFragment = new XPathFragment(defaultRootElementString);
//resolve URI
if (rootFragment.getNamespaceURI() == null) {
if(rootFragment.getPrefix() != null) {
String uri = descriptor.getNonNullNamespaceResolver().resolveNamespacePrefix(rootFragment.getPrefix());
rootFragment.setNamespaceURI(uri);
} else {
rootFragment.setNamespaceURI(descriptor.getNonNullNamespaceResolver().getDefaultNamespaceURI());
}
}
}
if (!wasXMLRoot) {
marshalRecord.setLeafElementType(descriptor.getDefaultRootElementType());
}
getXPathNode().startElement(marshalRecord, rootFragment, object, session, descriptor.getNonNullNamespaceResolver(), objectBuilder, objectValue);
writeExtraNamespaces(extraNamespaces, marshalRecord, session);
marshalRecord.addXsiTypeAndClassIndicatorIfRequired(descriptor, descriptor, (Field)xmlAnyObjectMapping.getField(), originalValue, objectValue, wasXMLRoot, false);
objectBuilder.buildRow(marshalRecord, objectValue, (CoreAbstractSession) childSession, marshaller, null);
marshalRecord.afterContainmentMarshal(object, objectValue);
marshalRecord.endElement(rootFragment, namespaceResolver);
marshalRecord.removeExtraNamespacesFromNamespaceResolver(extraNamespaces, session);
}
}
return true;
}
public boolean startElement(XPathFragment xPathFragment, UnmarshalRecord unmarshalRecord, Attributes atts) {
try {
Descriptor workingDescriptor = findReferenceDescriptor(xPathFragment, unmarshalRecord, atts, xmlAnyObjectMapping, xmlAnyObjectMapping.getKeepAsElementPolicy());
UnmarshalKeepAsElementPolicy policy = xmlAnyObjectMapping.getKeepAsElementPolicy();
if (null != policy && ((workingDescriptor == null && policy.isKeepUnknownAsElement()) || policy.isKeepAllAsElement())) {
setupHandlerForKeepAsElementPolicy(unmarshalRecord, xPathFragment, atts);
}else if (workingDescriptor != null) {
processChild(xPathFragment, unmarshalRecord, atts, workingDescriptor, xmlAnyObjectMapping);
}else{
AnyMappingContentHandler handler = new AnyMappingContentHandler(unmarshalRecord, xmlAnyObjectMapping.usesXMLRoot());
String qnameString = xPathFragment.getLocalName();
if (xPathFragment.getPrefix() != null) {
qnameString = xPathFragment.getPrefix() + Constants.COLON + qnameString;
}
handler.startElement(xPathFragment.getNamespaceURI(), xPathFragment.getLocalName(), qnameString, atts);
XMLReader xmlReader = unmarshalRecord.getXMLReader();
xmlReader.setContentHandler(handler);
xmlReader.setLexicalHandler(handler);
return true;
}
} catch (SAXException e) {
throw XMLMarshalException.unmarshalException(e);
}
return true;
}
public void endElement(XPathFragment xPathFragment, UnmarshalRecord unmarshalRecord) {
UnmarshalRecord childRecord = unmarshalRecord.getChildRecord();
if (null != childRecord) {
Object childObject = childRecord.getCurrentObject();
// OBJECT VALUE
if (xmlAnyObjectMapping.usesXMLRoot()) {
Descriptor workingDescriptor = childRecord.getDescriptor();
if (workingDescriptor != null) {
String prefix = xPathFragment.getPrefix();
if ((prefix == null) && (xPathFragment.getNamespaceURI() != null)) {
prefix = unmarshalRecord.resolveNamespaceUri(xPathFragment.getNamespaceURI());
}
childObject = workingDescriptor.wrapObjectInXMLRoot(childObject, xPathFragment.getNamespaceURI(), xPathFragment.getLocalName(), prefix, false, unmarshalRecord.isNamespaceAware(), unmarshalRecord.getUnmarshaller());
workingDescriptor = null;
}
}
childObject = xmlAnyObjectMapping.convertDataValueToObjectValue(childObject, unmarshalRecord.getSession(), unmarshalRecord.getUnmarshaller());
unmarshalRecord.setAttributeValue(childObject, xmlAnyObjectMapping);
} else {
SAXFragmentBuilder builder = unmarshalRecord.getFragmentBuilder();
UnmarshalKeepAsElementPolicy keepAsElementPolicy = xmlAnyObjectMapping.getKeepAsElementPolicy();
if (null != keepAsElementPolicy && (keepAsElementPolicy.isKeepUnknownAsElement() || keepAsElementPolicy.isKeepAllAsElement()) && builder.getNodes().size() > 1) {
setOrAddAttributeValueForKeepAsElement(builder, xmlAnyObjectMapping, xmlAnyObjectMapping, unmarshalRecord, false, null);
} else {
// TEXT VALUE
if(xmlAnyObjectMapping.isMixedContent()) {
endElementProcessText(unmarshalRecord, xmlAnyObjectMapping, xPathFragment, null);
} else {
unmarshalRecord.resetStringBuffer();
}
}
}
}
protected void setOrAddAttributeValue(UnmarshalRecord unmarshalRecord, Object value, XPathFragment xPathFragment, Object collection){
if (!xmlAnyObjectMapping.usesXMLRoot()) {
unmarshalRecord.setAttributeValue(value, xmlAnyObjectMapping);
} else {
Root xmlRoot = unmarshalRecord.createRoot();
xmlRoot.setNamespaceURI(xPathFragment.getNamespaceURI());
xmlRoot.setSchemaType(unmarshalRecord.getTypeQName());
xmlRoot.setLocalName(xPathFragment.getLocalName());
xmlRoot.setObject(value);
// xmlRoot.setDeclaredType(type);
unmarshalRecord.setAttributeValue(xmlRoot, xmlAnyObjectMapping);
}
}
private Namespace setupFragment(Root originalValue, XPathFragment xmlRootFragment, MarshalRecord marshalRecord) {
Namespace generatedNamespace = null;
String xpath = originalValue.getLocalName();
if (originalValue.getNamespaceURI() != null) {
xmlRootFragment.setNamespaceURI((originalValue).getNamespaceURI());
String prefix = marshalRecord.getNamespaceResolver().resolveNamespaceURI((originalValue).getNamespaceURI());
if (prefix == null || prefix.length() == 0) {
prefix = marshalRecord.getNamespaceResolver().generatePrefix("ns0");
generatedNamespace = new Namespace(prefix, xmlRootFragment.getNamespaceURI());
xmlRootFragment.setGeneratedPrefix(true);
}
xpath = prefix + Constants.COLON + xpath;
}
xmlRootFragment.setXPath(xpath);
return generatedNamespace;
}
private void marshalSimpleValue(XPathFragment xmlRootFragment, MarshalRecord marshalRecord, Object originalValue, Object object, Object value, CoreAbstractSession session, NamespaceResolver namespaceResolver) {
QName qname = null;
if (xmlRootFragment != null) {
qname = ((Root) originalValue).getSchemaType();
setupFragment(((Root) originalValue), xmlRootFragment, marshalRecord);
getXPathNode().startElement(marshalRecord, xmlRootFragment, object, session, namespaceResolver, null, null);
updateNamespaces(qname, marshalRecord, null);
}
if (value instanceof org.w3c.dom.Node) {
marshalRecord.node((org.w3c.dom.Node) value, marshalRecord.getNamespaceResolver());
} else {
marshalRecord.characters(qname, value, null, false);
}
if (xmlRootFragment != null) {
marshalRecord.endElement(xmlRootFragment, namespaceResolver);
}
}
public AnyObjectMapping getMapping() {
return xmlAnyObjectMapping;
}
public boolean isWhitespaceAware() {
return false;
}
public boolean isAnyMappingNodeValue() {
return true;
}
@Override
public boolean isMixedContentNodeValue() {
return this.xmlAnyObjectMapping.isMixedContent();
}
@Override
protected Descriptor findReferenceDescriptor(XPathFragment xPathFragment, UnmarshalRecord unmarshalRecord, Attributes atts, Mapping mapping, UnmarshalKeepAsElementPolicy policy) {
Descriptor referenceDescriptor = super.findReferenceDescriptor(xPathFragment, unmarshalRecord, atts, mapping, policy);
if (referenceDescriptor == null) {
Context xmlContext = unmarshalRecord.getUnmarshaller().getContext();
XPathQName xpathQName = new XPathQName(xPathFragment.getNamespaceURI(), xPathFragment.getLocalName(), unmarshalRecord.isNamespaceAware());
referenceDescriptor = (Descriptor) xmlContext.getDescriptor(xpathQName);
// Check if descriptor is for a wrapper, if it is null it out and let continue
if (referenceDescriptor != null && referenceDescriptor.isWrapper()) {
referenceDescriptor = null;
}
}
return referenceDescriptor;
}
}