org.eclipse.persistence.internal.oxm.XMLCompositeCollectionMappingNodeValue 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.List;
import javax.xml.namespace.QName;
import org.eclipse.persistence.core.queries.CoreAttributeGroup;
import org.eclipse.persistence.core.queries.CoreAttributeItem;
import org.eclipse.persistence.exceptions.XMLMarshalException;
import org.eclipse.persistence.internal.core.queries.CoreContainerPolicy;
import org.eclipse.persistence.internal.core.sessions.CoreAbstractSession;
import org.eclipse.persistence.internal.oxm.mappings.CompositeCollectionMapping;
import org.eclipse.persistence.internal.oxm.mappings.Descriptor;
import org.eclipse.persistence.internal.oxm.mappings.Field;
import org.eclipse.persistence.internal.oxm.mappings.InverseReferenceMapping;
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.CompositeCollectionMappingContentHandler;
import org.eclipse.persistence.oxm.mappings.nullpolicy.AbstractNullPolicy;
import org.eclipse.persistence.oxm.mappings.nullpolicy.XMLNullRepresentationType;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
/**
* INTERNAL:
* Purpose: This is how the XML Composite Collection Mapping is handled when used with the TreeObjectBuilder.
*
*/
public class XMLCompositeCollectionMappingNodeValue extends XMLRelationshipMappingNodeValue implements ContainerValue {
private CompositeCollectionMapping xmlCompositeCollectionMapping;
private int index = -1;
private boolean isInverseReference;
public XMLCompositeCollectionMappingNodeValue(CompositeCollectionMapping xmlCompositeCollectionMapping) {
super();
this.xmlCompositeCollectionMapping = xmlCompositeCollectionMapping;
}
public XMLCompositeCollectionMappingNodeValue(CompositeCollectionMapping xmlCompositeCollectionMapping, boolean isInverse) {
this(xmlCompositeCollectionMapping);
this.isInverseReference = isInverse;
}
@Override
public boolean marshal(XPathFragment xPathFragment, MarshalRecord marshalRecord, Object object, CoreAbstractSession session, NamespaceResolver namespaceResolver) {
if (xmlCompositeCollectionMapping.isReadOnly()) {
return false;
}
Object collection = xmlCompositeCollectionMapping.getAttributeAccessor().getAttributeValueFromObject(object);
if (null == collection) {
AbstractNullPolicy wrapperNP = xmlCompositeCollectionMapping.getWrapperNullPolicy();
if (wrapperNP != null && wrapperNP.getMarshalNullRepresentation() == XMLNullRepresentationType.XSI_NIL) {
marshalRecord.nilSimple(namespaceResolver);
return true;
} else {
return false;
}
}
CoreContainerPolicy cp = getContainerPolicy();
int size = marshalRecord.getCycleDetectionStack().size();
// when writing the collection need to see if any of the objects we are
// writing are in the parent collection inverse ref
if ((isInverseReference || xmlCompositeCollectionMapping.getInverseReferenceMapping() != null) && size >= 2) {
Object owner = marshalRecord.getCycleDetectionStack().get(size - 2);
try {
if (cp.contains(owner, collection, session)) {
return false;
}
} catch (ClassCastException e) {
// For Bug #416875
}
}
Object iterator = cp.iteratorFor(collection);
if (null != iterator && cp.hasNext(iterator)) {
XPathFragment groupingFragment = marshalRecord.openStartGroupingElements(namespaceResolver);
marshalRecord.closeStartGroupingElements(groupingFragment);
int valueSize = cp.sizeFor(collection);
if(marshalRecord.getMarshaller().isApplicationJSON() && (valueSize > 1 || !marshalRecord.getMarshaller().isReduceAnyArrays())) {
marshalRecord.startCollection();
}
do {
Object objectValue = cp.next(iterator, session);
marshalSingleValue(xPathFragment, marshalRecord, object, objectValue, session, namespaceResolver, ObjectMarshalContext.getInstance());
} while (cp.hasNext(iterator));
if(marshalRecord.getMarshaller().isApplicationJSON() && (valueSize > 1 || !marshalRecord.getMarshaller().isReduceAnyArrays())) {
marshalRecord.endCollection();
}
return true;
}
return marshalRecord.emptyCollection(xPathFragment, namespaceResolver, xmlCompositeCollectionMapping.getWrapperNullPolicy() != null);
}
@Override
public boolean startElement(XPathFragment xPathFragment, UnmarshalRecord unmarshalRecord, Attributes atts) {
try {
Descriptor xmlDescriptor = (Descriptor) xmlCompositeCollectionMapping.getReferenceDescriptor();
if (xmlDescriptor == null) {
xmlDescriptor = findReferenceDescriptor(xPathFragment, unmarshalRecord, atts, xmlCompositeCollectionMapping, xmlCompositeCollectionMapping.getKeepAsElementPolicy());
if (xmlDescriptor == null) {
if (unmarshalRecord.getXMLReader().isNullRepresentedByXsiNil(xmlCompositeCollectionMapping.getNullPolicy())) {
if (unmarshalRecord.isNil()) {
return true;
}
} else if (xmlCompositeCollectionMapping.getNullPolicy().valueIsNull(atts)) {
getContainerPolicy().addInto(null, unmarshalRecord.getContainerInstance(this), unmarshalRecord.getSession());
return true;
}
if (xmlCompositeCollectionMapping.getField() != null) {
//try leaf element type
QName leafType = ((Field) xmlCompositeCollectionMapping.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) xmlCompositeCollectionMapping.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 = xmlCompositeCollectionMapping.getKeepAsElementPolicy();
if (policy != null && ((xmlDescriptor == null && policy.isKeepUnknownAsElement()) || policy.isKeepAllAsElement())) {
if (unmarshalRecord.getTypeQName() != null) {
Class