org.eclipse.persistence.internal.oxm.XMLDirectMappingNodeValue 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, 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.util.ArrayList;
import javax.xml.namespace.QName;
import org.eclipse.persistence.core.sessions.CoreSession;
import org.eclipse.persistence.internal.core.sessions.CoreAbstractSession;
import org.eclipse.persistence.internal.oxm.mappings.DirectMapping;
import org.eclipse.persistence.internal.oxm.mappings.Field;
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;
/**
* INTERNAL:
* Purpose: This is how the XML Direct Mapping is handled when used
* with the TreeObjectBuilder.
*/
public class XMLDirectMappingNodeValue extends MappingNodeValue implements NullCapableValue {
private DirectMapping xmlDirectMapping;
public XMLDirectMappingNodeValue(DirectMapping xmlDirectMapping) {
this.xmlDirectMapping = xmlDirectMapping;
}
@Override
public void setXPathNode(XPathNode xPathNode) {
super.setXPathNode(xPathNode);
xmlDirectMapping.getNullPolicy().xPathNode(xPathNode, this);
if(((Field) xmlDirectMapping.getField()).isTypedTextField()) {
XPathFragment typeAttributeXPathFragment = new XPathFragment();
typeAttributeXPathFragment.setAttribute(true);
typeAttributeXPathFragment.setLocalName(Constants.SCHEMA_TYPE_ATTRIBUTE);
typeAttributeXPathFragment.setNamespaceURI(javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI);
xPathNode.getParent().addChild(typeAttributeXPathFragment, new TypeNodeValue(), null);
}
}
@Override
public boolean isOwningNode(XPathFragment xPathFragment) {
return xPathFragment.hasAttribute || xPathFragment.nameIsText;
}
@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 (xmlDirectMapping.isReadOnly()) {
return false;
}
Object objectValue = marshalContext.getAttributeValue(object, xmlDirectMapping);
return this.marshalSingleValue(xPathFragment, marshalRecord, object, objectValue, session, namespaceResolver, marshalContext);
}
@Override
public boolean marshalSingleValue(XPathFragment xPathFragment, MarshalRecord marshalRecord, Object object, Object objectValue, CoreAbstractSession session, NamespaceResolver namespaceResolver, MarshalContext marshalContext) {
Object fieldValue = xmlDirectMapping.getFieldValue(objectValue, session, marshalRecord);
// Check for a null value
if (null == fieldValue) {
// Perform marshal operations based on the null policy
return xmlDirectMapping.getNullPolicy().directMarshal(xPathFragment, marshalRecord, object, session, namespaceResolver);
} else {
QName schemaType = ((Field) xmlDirectMapping.getField()).getSchemaTypeForValue(fieldValue, session);
XPathFragment groupingFragment = null;
boolean isQName = false;
if(Constants.QNAME_QNAME.equals(schemaType)) {
//if marshalling a QName, handle grouping elements here in case namespace adjustments need
//to happen
groupingFragment = openGroupingElementsForQName((QName)fieldValue, marshalRecord);
isQName = true;
}
if(groupingFragment == null) {
groupingFragment = marshalRecord.openStartGroupingElements(namespaceResolver);
}
if (xPathFragment.hasAttribute) {
marshalRecord.attribute(xPathFragment, namespaceResolver, fieldValue, schemaType);
marshalRecord.closeStartGroupingElements(groupingFragment);
} else {
if(((Field) xmlDirectMapping.getField()).getXPathFragment().nameIsText ){
XPathNode parentNode = xPathNode.getParent();
if(parentNode.getAttributeChildren() != null){
marshalRecord.forceValueWrapper();
}
}
Field xmlField = (Field) xmlDirectMapping.getField();
if (xmlField.isTypedTextField()) {
updateNamespaces(schemaType, marshalRecord, xmlField);
}
marshalRecord.closeStartGroupingElements(groupingFragment);
marshalRecord.characters(schemaType, fieldValue, null, xmlDirectMapping.isCDATA());
}
if(isQName) {
//check to see if the last grouping fragment was swapped
XPathFragment fragment = getLastGroupingFragment();
if(fragment != groupingFragment) {
marshalRecord.endElement(groupingFragment, namespaceResolver);
return false;
}
}
return true;
}
}
private XPathFragment getLastGroupingFragment() {
XPathFragment fragment = ((Field)this.getMapping().getField()).getXPathFragment();
if(fragment.hasAttribute || fragment.nameIsText) {
return null;
}
while(fragment.getNextFragment() != null) {
if(fragment.getNextFragment().nameIsText || fragment.getNextFragment().hasAttribute) {
return fragment;
}
fragment = fragment.getNextFragment();
}
return fragment;
}
private XPathFragment openGroupingElementsForQName(QName fieldValue, MarshalRecord marshalRecord) {
XPathFragment xPathFragment = null;
ArrayList groupingElements = marshalRecord.getGroupingElements();
NamespaceResolver namespaceResolver = marshalRecord.getNamespaceResolver();
if((fieldValue.getNamespaceURI() == null || fieldValue.getNamespaceURI().equals(Constants.EMPTY_STRING)) && marshalRecord.getNamespaceResolver().getDefaultNamespaceURI() != null) {
//In this case, the last grouping element may need to have a new prefix generated.
for (int x = 0, groupingElementsSize = groupingElements.size(); x < groupingElementsSize; x++) {
XPathNode xPathNode = groupingElements.get(x);
xPathFragment = xPathNode.getXPathFragment();
if(x == (groupingElements.size() - 1) && namespaceResolver.getDefaultNamespaceURI().equals(xPathFragment.getNamespaceURI()) && xPathFragment.getPrefix() == null) {
String prefix = namespaceResolver.generatePrefix();
String xPath = prefix + Constants.COLON + xPathFragment.getShortName();
XPathFragment newFragment = new XPathFragment(xPath);
newFragment.setNamespaceURI(namespaceResolver.getDefaultNamespaceURI());
marshalRecord.openStartElement(newFragment, namespaceResolver);
marshalRecord.namespaceDeclaration(prefix, namespaceResolver.getDefaultNamespaceURI());
marshalRecord.predicateAttribute(xPathFragment, namespaceResolver);
xPathFragment = newFragment;
} else {
marshalRecord.openStartElement(xPathFragment, namespaceResolver);
marshalRecord.predicateAttribute(xPathFragment, namespaceResolver);
marshalRecord.closeStartElement();
}
}
marshalRecord.setGroupingElement(null);
}
return xPathFragment;
}
@Override
public void attribute(UnmarshalRecord unmarshalRecord, String namespaceURI, String localName, String value) {
unmarshalRecord.removeNullCapableValue(this);
Field xmlField = (Field) xmlDirectMapping.getField();
CoreAbstractSession session = unmarshalRecord.getSession();
Object realValue = unmarshalRecord.getXMLReader().convertValueBasedOnSchemaType(xmlField, value, (ConversionManager) session.getDatasourcePlatform().getConversionManager(), unmarshalRecord);
// Perform operations on the object based on the null policy
Object convertedValue = xmlDirectMapping.getAttributeValue(realValue, session, unmarshalRecord);
xmlDirectMapping.setAttributeValueInObject(unmarshalRecord.getCurrentObject(), convertedValue);
}
@Override
public void endElement(XPathFragment xPathFragment, UnmarshalRecord unmarshalRecord) {
if(unmarshalRecord.isNil() && xmlDirectMapping.getNullPolicy().isNullRepresentedByXsiNil()){
Object convertedValue = xmlDirectMapping.getAttributeValue(org.eclipse.persistence.oxm.record.XMLRecord.NIL, unmarshalRecord.getSession(), unmarshalRecord);
unmarshalRecord.setAttributeValue(convertedValue, xmlDirectMapping);
unmarshalRecord.resetStringBuffer();
return;
}
unmarshalRecord.removeNullCapableValue(this);
Field xmlField = (Field) xmlDirectMapping.getField();
if (!xmlField.getLastXPathFragment().nameIsText) {
return;
}
Object value;
CharSequence unmarshalRecordCharacters = unmarshalRecord.getCharacters();
if (unmarshalRecordCharacters.length() == 0) {
value = xmlDirectMapping.getNullValue();
} else {
value = unmarshalRecordCharacters.toString();
}
unmarshalRecord.resetStringBuffer();
CoreAbstractSession session = unmarshalRecord.getSession();
ConversionManager conversionManager = (ConversionManager) session.getDatasourcePlatform().getConversionManager();
QName typeQName = unmarshalRecord.getTypeQName();
if (typeQName != null) {
Class> typeClass = xmlField.getJavaClass(typeQName, conversionManager);
value = conversionManager.convertObject(value, typeClass, typeQName);
} else {
value = unmarshalRecord.getXMLReader().convertValueBasedOnSchemaType(xmlField, value, conversionManager, unmarshalRecord);
}
Object convertedValue = xmlDirectMapping.getAttributeValue(value, session, unmarshalRecord);
unmarshalRecord.setAttributeValue(convertedValue, xmlDirectMapping);
}
@Override
public void setNullValue(Object object, CoreSession session) {
Object value = xmlDirectMapping.getObjectValue(null, session);
xmlDirectMapping.setAttributeValueInObject(object, value);
}
@Override
public boolean isNullCapableValue() {
if(xmlDirectMapping.getAttributeAccessor().isInstanceVariableAttributeAccessor() && !xmlDirectMapping.hasConverter() && xmlDirectMapping.getNullValue() == null) {
return false;
}
return xmlDirectMapping.getNullPolicy().getIsSetPerformedForAbsentNode();
}
@Override
public DirectMapping getMapping() {
return xmlDirectMapping;
}
@Override
public boolean isWhitespaceAware() {
return !xmlDirectMapping.getNullPolicy().isNullRepresentedByEmptyNode();
}
}