All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.persistence.internal.oxm.XMLCompositeDirectCollectionMappingNodeValue Maven / Gradle / Ivy

There is a newer version: 5.0.0-B03
Show newest version
/*
 * 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.StringTokenizer;
import javax.xml.namespace.QName;

import org.eclipse.persistence.internal.core.helper.CoreClassConstants;
import org.eclipse.persistence.internal.core.queries.CoreContainerPolicy;
import org.eclipse.persistence.internal.core.sessions.CoreAbstractSession;
import org.eclipse.persistence.internal.oxm.mappings.DirectCollectionMapping;
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;

import org.eclipse.persistence.oxm.mappings.nullpolicy.AbstractNullPolicy;
import org.eclipse.persistence.oxm.mappings.nullpolicy.XMLNullRepresentationType;
import org.xml.sax.Attributes;

/**
 * INTERNAL:
 * 

Purpose: This is how the XML Composite Direct Collection Mapping is * handled when used with the TreeObjectBuilder.

*/ public class XMLCompositeDirectCollectionMappingNodeValue extends MappingNodeValue implements ContainerValue { private static final String SPACE = " "; private DirectCollectionMapping xmlCompositeDirectCollectionMapping; private int index = -1; public XMLCompositeDirectCollectionMappingNodeValue(DirectCollectionMapping xmlCompositeDirectCollectionMapping) { super(); this.xmlCompositeDirectCollectionMapping = xmlCompositeDirectCollectionMapping; } @Override public boolean isOwningNode(XPathFragment xPathFragment) { XPathFragment nextFragment = xPathFragment.getNextFragment(); if (nextFragment == null || xmlCompositeDirectCollectionMapping.usesSingleNode()) { return xPathFragment.isAttribute() || xPathFragment.nameIsText(); } else { return (nextFragment != null) && (nextFragment.nameIsText() || nextFragment.isAttribute()); } } /** * Override the method in XPathNode such that the marshaller can be set on the * marshalRecord - this is required for XMLConverter usage. */ @Override public boolean marshal(XPathFragment xPathFragment, MarshalRecord marshalRecord, Object object, CoreAbstractSession session, NamespaceResolver namespaceResolver) { if (xmlCompositeDirectCollectionMapping.isReadOnly()) { return false; } CoreContainerPolicy cp = getContainerPolicy(); Object collection = xmlCompositeDirectCollectionMapping.getAttributeAccessor().getAttributeValueFromObject(object); if (null == collection) { AbstractNullPolicy wrapperNP = xmlCompositeDirectCollectionMapping.getWrapperNullPolicy(); if (wrapperNP != null && wrapperNP.getMarshalNullRepresentation() == XMLNullRepresentationType.XSI_NIL) { marshalRecord.nilSimple(namespaceResolver); return true; } else { return false; } } Object iterator = cp.iteratorFor(collection); Field xmlField = (Field) xmlCompositeDirectCollectionMapping.getField(); if (null != iterator && cp.hasNext(iterator)) { XPathFragment groupingFragment = marshalRecord.openStartGroupingElements(namespaceResolver); marshalRecord.closeStartGroupingElements(groupingFragment); } else { if (xmlField.usesSingleNode() && !xmlCompositeDirectCollectionMapping.isDefaultEmptyContainer()) { XPathFragment groupingFragment = marshalRecord.openStartGroupingElements(namespaceResolver); marshalRecord.closeStartGroupingElements(groupingFragment); } else { return marshalRecord.emptyCollection(xPathFragment, namespaceResolver, xmlCompositeDirectCollectionMapping.getWrapperNullPolicy() != null); } } Object objectValue; if (xmlField.usesSingleNode()) { StringBuilder stringValueStringBuilder = new StringBuilder(); String newValue; QName schemaType = null; if (xPathFragment != null && !xPathFragment.isAttribute() && !xPathFragment.nameIsText) { marshalRecord.openStartElement(xPathFragment, namespaceResolver); } while (cp.hasNext(iterator)) { objectValue = cp.next(iterator, session); objectValue = xmlCompositeDirectCollectionMapping.convertObjectValueToDataValue(objectValue, session, marshalRecord.getMarshaller()); schemaType = xmlField.getSchemaTypeForValue(objectValue, session); newValue = marshalRecord.getValueToWrite(schemaType, objectValue, (ConversionManager) session.getDatasourcePlatform().getConversionManager()); if (null != newValue) { stringValueStringBuilder.append(newValue); if (cp.hasNext(iterator)) { stringValueStringBuilder.append(SPACE); } } } XPathFragment groupingFragment = marshalRecord.openStartGroupingElements(namespaceResolver); if (xPathFragment != null && xPathFragment.isAttribute()) { marshalRecord.attribute(xPathFragment, namespaceResolver, stringValueStringBuilder.toString()); marshalRecord.closeStartGroupingElements(groupingFragment); } else { marshalRecord.closeStartGroupingElements(groupingFragment); if (xmlCompositeDirectCollectionMapping.isCDATA()) { marshalRecord.cdata(stringValueStringBuilder.toString()); } else { marshalRecord.characters(stringValueStringBuilder.toString()); if (xPathFragment != null && !xPathFragment.isAttribute() && !xPathFragment.nameIsText) { marshalRecord.endElement(xPathFragment, namespaceResolver); } } } } else { int valueSize = cp.sizeFor(collection); if(marshalRecord.getMarshaller().isApplicationJSON() && (valueSize > 1 || !marshalRecord.getMarshaller().isReduceAnyArrays())) { marshalRecord.startCollection(); } while (cp.hasNext(iterator)) { objectValue = cp.next(iterator, session); marshalSingleValue(xPathFragment, marshalRecord, object, objectValue, session, namespaceResolver, ObjectMarshalContext.getInstance()); } if(marshalRecord.getMarshaller().isApplicationJSON() && (valueSize > 1 || !marshalRecord.getMarshaller().isReduceAnyArrays())) { marshalRecord.endCollection(); } } return true; } @Override public void attribute(UnmarshalRecord unmarshalRecord, String namespaceURI, String localName, String value) { Object collection = unmarshalRecord.getContainerInstance(this); if (xmlCompositeDirectCollectionMapping.usesSingleNode()) { StringTokenizer stringTokenizer = new StringTokenizer(value); while (stringTokenizer.hasMoreTokens()) { addUnmarshalValue(unmarshalRecord, stringTokenizer.nextToken(), collection); } } else { addUnmarshalValue(unmarshalRecord, value, collection); } } @Override public boolean startElement(XPathFragment xPathFragment, UnmarshalRecord unmarshalRecord, Attributes atts) { Field xmlField = (Field) xmlCompositeDirectCollectionMapping.getField(); XPathFragment lastXPathFragment = xmlField.getLastXPathFragment(); if (lastXPathFragment.nameIsText()) { String type = atts.getValue(javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, Constants.SCHEMA_TYPE_ATTRIBUTE); if (null != type) { String namespaceURI = null; int colonIndex = type.indexOf(Constants.COLON); if (colonIndex > -1) { String prefix = type.substring(0, colonIndex); namespaceURI = unmarshalRecord.resolveNamespacePrefix(prefix); type = type.substring(colonIndex + 1); } unmarshalRecord.setTypeQName(new QName(namespaceURI, type)); } } else if (lastXPathFragment.isAttribute()) { if (!xmlField.usesSingleNode()) { String namespaceURI = lastXPathFragment.getNamespaceURI(); if (namespaceURI == null) { namespaceURI = Constants.EMPTY_STRING; } String value = atts.getValue(namespaceURI, lastXPathFragment.getLocalName()); Object collection = unmarshalRecord.getContainerInstance(this); addUnmarshalValue(unmarshalRecord, value, collection); } } return true; } @Override public void endElement(XPathFragment xPathFragment, UnmarshalRecord unmarshalRecord) { Field xmlField = (Field) xmlCompositeDirectCollectionMapping.getField(); Object value = unmarshalRecord.getCharacters().toString(); if(((String)value).length() == 0 && !xmlField.usesSingleNode()){ if( xmlCompositeDirectCollectionMapping.getNullValue() != null){ value = xmlCompositeDirectCollectionMapping.getNullValue(); } } unmarshalRecord.resetStringBuffer(); XPathFragment lastXPathFragment = xmlField.getLastXPathFragment(); if (!lastXPathFragment.nameIsText()) { return; } if (xmlField.usesSingleNode() ) { Object collection = unmarshalRecord.getContainerInstance(this); StringTokenizer stringTokenizer = new StringTokenizer((String)value); while (stringTokenizer.hasMoreTokens()) { addUnmarshalValue(unmarshalRecord, stringTokenizer.nextToken(), collection); } } else { if(!unmarshalRecord.getXMLReader().isInCollection() && unmarshalRecord.isNil() ){ unmarshalRecord.setAttributeValueNull(this); }else{ Object collection = unmarshalRecord.getContainerInstance(this); addUnmarshalValue(unmarshalRecord, value, collection); } } } @Override public void endElement(XPathFragment xPathFragment, UnmarshalRecord unmarshalRecord, Object collection) { Field xmlField = (Field) xmlCompositeDirectCollectionMapping.getField(); Object value = unmarshalRecord.getCharacters().toString(); if(((String)value).length() == 0 && !xmlField.usesSingleNode()){ if( xmlCompositeDirectCollectionMapping.getNullValue() != null){ value = xmlCompositeDirectCollectionMapping.getNullValue(); } } unmarshalRecord.resetStringBuffer(); if (xmlField.usesSingleNode() && value instanceof String) { StringTokenizer stringTokenizer = new StringTokenizer((String)value); while (stringTokenizer.hasMoreTokens()) { addUnmarshalValue(unmarshalRecord, stringTokenizer.nextToken(), collection); } } else { if (xmlField.getLastXPathFragment().nameIsText()) { if(!unmarshalRecord.getXMLReader().isInCollection() && unmarshalRecord.isNil() ){ unmarshalRecord.setAttributeValueNull(this); } else{ addUnmarshalValue(unmarshalRecord, value, collection); } } } } private void addUnmarshalValue(UnmarshalRecord unmarshalRecord, Object value, Object collection) { if (unmarshalRecord.isNil() && unmarshalRecord.getXMLReader().isNullRepresentedByXsiNil(xmlCompositeDirectCollectionMapping.getNullPolicy())){ value = null; } else if (!isWhitespaceAware() && Constants.EMPTY_STRING.equals(value)) { value = null; } Field xmlField = (Field) xmlCompositeDirectCollectionMapping.getField(); ConversionManager conversionManager = unmarshalRecord.getConversionManager(); if (unmarshalRecord.getTypeQName() != null) { Class typeClass = xmlField.getJavaClass(unmarshalRecord.getTypeQName(), conversionManager); value = conversionManager.convertObject(value, typeClass, unmarshalRecord.getTypeQName()); } else { value = unmarshalRecord.getXMLReader().convertValueBasedOnSchemaType(xmlField, value, conversionManager, unmarshalRecord); } value = xmlCompositeDirectCollectionMapping.convertDataValueToObjectValue(value, unmarshalRecord.getSession(), unmarshalRecord.getUnmarshaller()); if (value != null && value.getClass() == CoreClassConstants.STRING) { if (xmlCompositeDirectCollectionMapping.isCollapsingStringValues()) { value = conversionManager.collapseStringValue((String)value); } else if (xmlCompositeDirectCollectionMapping.isNormalizingStringValues()) { value = conversionManager.normalizeStringValue((String)value); } } unmarshalRecord.addAttributeValue(this, value, collection); } @Override public Object getContainerInstance() { return getContainerPolicy().containerInstance(); } @Override public void setContainerInstance(Object object, Object containerInstance) { xmlCompositeDirectCollectionMapping.setAttributeValueInObject(object, containerInstance); } @Override public CoreContainerPolicy getContainerPolicy() { return xmlCompositeDirectCollectionMapping.getContainerPolicy(); } @Override public boolean isContainerValue() { return true; } @Override public boolean marshalSingleValue(XPathFragment xPathFragment, MarshalRecord marshalRecord, Object object, Object value, CoreAbstractSession session, NamespaceResolver namespaceResolver, MarshalContext marshalContext) { value = xmlCompositeDirectCollectionMapping.convertObjectValueToDataValue(value, session, marshalRecord.getMarshaller()); if (null != value) { Field xmlField = (Field) xmlCompositeDirectCollectionMapping.getField(); QName schemaType = xmlField.getSchemaTypeForValue(value, session); boolean isElementOpen = false; if (Constants.QNAME_QNAME.equals(schemaType)) { QName fieldValue = (QName) value; if ((fieldValue.getNamespaceURI() == null || fieldValue.getNamespaceURI().equals("")) && marshalRecord.getNamespaceResolver().getDefaultNamespaceURI() != null) { // In this case, an extra xmlns="" declaration is going to be added. This may // require adjusting the namespace of the current fragment. String defaultNamespaceURI = namespaceResolver.getDefaultNamespaceURI(); if (defaultNamespaceURI.equals(xPathFragment.getNamespaceURI()) && xPathFragment.getPrefix() == null) { String prefix = namespaceResolver.generatePrefix(); String xPath = prefix + Constants.COLON + xPathFragment.getShortName(); XPathFragment newFragment = new XPathFragment(xPath); newFragment.setNamespaceURI(defaultNamespaceURI); newFragment.setNextFragment(xPathFragment.getNextFragment()); marshalRecord.openStartElement(newFragment, namespaceResolver); isElementOpen = true; marshalRecord.namespaceDeclaration(prefix, defaultNamespaceURI); marshalRecord.predicateAttribute(xPathFragment, namespaceResolver); xPathFragment = newFragment; } } } if (!isElementOpen) { marshalRecord.openStartElement(xPathFragment, namespaceResolver); } XPathFragment nextFragment = xPathFragment.getNextFragment(); if (nextFragment != null && nextFragment.isAttribute()) { marshalRecord.predicateAttribute(xPathFragment, namespaceResolver); marshalRecord.attribute(nextFragment, namespaceResolver, value,schemaType); marshalRecord.closeStartElement(); } else { if (xmlField.isTypedTextField()) { updateNamespaces(schemaType, marshalRecord, xmlField); } marshalRecord.closeStartElement(); marshalRecord.predicateAttribute(xPathFragment, namespaceResolver); marshalRecord.characters(schemaType, value, null, xmlCompositeDirectCollectionMapping.isCDATA()); } marshalRecord.endElement(xPathFragment, namespaceResolver); return true; } else { AbstractNullPolicy nullPolicy = xmlCompositeDirectCollectionMapping.getNullPolicy(); if (nullPolicy.getMarshalNullRepresentation() != XMLNullRepresentationType.ABSENT_NODE) { marshalRecord.openStartElement(xPathFragment, namespaceResolver); XPathFragment nextFragment = xPathFragment.getNextFragment(); nullPolicy.directMarshal(nextFragment, marshalRecord, object, session, namespaceResolver); marshalRecord.endElement(xPathFragment, namespaceResolver); return true; } } return false; } @Override public DirectCollectionMapping getMapping() { return xmlCompositeDirectCollectionMapping; } @Override public boolean isWhitespaceAware() { return !xmlCompositeDirectCollectionMapping.getNullPolicy().isNullRepresentedByEmptyNode(); } @Override public boolean getReuseContainer() { return getMapping().getReuseContainer(); } /** * INTERNAL: * Used to track the index of the corresponding containerInstance in the containerInstances Object[] on UnmarshalRecord */ @Override public void setIndex(int index){ this.index = index; } /** * INTERNAL: * Set to track the index of the corresponding containerInstance in the containerInstances Object[] on UnmarshalRecord * Set during TreeObjectBuilder initialization */ @Override public int getIndex(){ return index; } /** * INTERNAL * Return true if an empty container should be set on the object if there * is no presence of the collection in the XML document. * @since EclipseLink 2.3.3 */ @Override public boolean isDefaultEmptyContainer() { return getMapping().isDefaultEmptyContainer(); } @Override public boolean isWrapperAllowedAsCollectionName() { return true; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy