| /* |
| * Copyright (c) 1998, 2020 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.Collection; |
| import java.util.Map; |
| |
| import org.eclipse.persistence.core.sessions.CoreSession; |
| import org.eclipse.persistence.internal.core.queries.CoreContainerPolicy; |
| import org.eclipse.persistence.internal.core.sessions.CoreAbstractSession; |
| import org.eclipse.persistence.internal.oxm.mappings.AnyCollectionMapping; |
| import org.eclipse.persistence.internal.oxm.mappings.BinaryDataCollectionMapping; |
| import org.eclipse.persistence.internal.oxm.mappings.ChoiceCollectionMapping; |
| import org.eclipse.persistence.internal.oxm.mappings.CollectionReferenceMapping; |
| import org.eclipse.persistence.internal.oxm.mappings.CompositeCollectionMapping; |
| import org.eclipse.persistence.internal.oxm.mappings.DirectCollectionMapping; |
| import org.eclipse.persistence.internal.oxm.mappings.Field; |
| import org.eclipse.persistence.internal.oxm.mappings.Mapping; |
| import org.eclipse.persistence.internal.oxm.record.MarshalContext; |
| import org.eclipse.persistence.internal.oxm.record.MarshalRecord; |
| import org.eclipse.persistence.internal.oxm.record.UnmarshalContext; |
| import org.eclipse.persistence.internal.oxm.record.UnmarshalRecord; |
| |
| import org.xml.sax.Attributes; |
| |
| /** |
| * INTERNAL: |
| * <p><b>Purpose</b>: This is how the XML Choice Collection Mapping is |
| * handled when used with the TreeObjectBuilder.</p> |
| * @author mmacivor |
| */ |
| public class XMLChoiceCollectionMappingUnmarshalNodeValue extends MappingNodeValue implements ContainerValue { |
| private NodeValue choiceElementNodeValue; |
| private NodeValue choiceElementMarshalNodeValue; |
| private ChoiceCollectionMapping xmlChoiceCollectionMapping; |
| private Mapping nestedMapping; |
| private Map<Field, NodeValue> fieldToNodeValues; |
| private Field xmlField; |
| private ContainerValue containerNodeValue; |
| private boolean isMixedNodeValue; |
| private boolean isAny; |
| private int index = -1; |
| |
| public XMLChoiceCollectionMappingUnmarshalNodeValue(ChoiceCollectionMapping mapping, Field xmlField) { |
| this.xmlChoiceCollectionMapping = mapping; |
| this.xmlField = xmlField; |
| if(xmlField == null && mapping.isAny()){ |
| isAny = true; |
| }else{ |
| this.nestedMapping = (Mapping)mapping.getChoiceElementMappings().get(xmlField); |
| } |
| initializeNodeValue(); |
| } |
| |
| public XMLChoiceCollectionMappingUnmarshalNodeValue(ChoiceCollectionMapping mapping, Field xmlField, Mapping nestedMapping) { |
| this.xmlChoiceCollectionMapping = mapping; |
| this.xmlField = xmlField; |
| this.nestedMapping = nestedMapping; |
| initializeNodeValue(); |
| } |
| |
| @Override |
| public boolean isOwningNode(XPathFragment xPathFragment) { |
| if(isMixedNodeValue) { |
| if(xPathFragment.nameIsText()) { |
| return true; |
| } else { |
| return false; |
| } |
| } |
| return choiceElementNodeValue.isOwningNode(xPathFragment); |
| } |
| |
| private void initializeNodeValue() { |
| if(nestedMapping == null && isAny){ |
| nestedMapping = xmlChoiceCollectionMapping.getAnyMapping(); |
| } |
| Mapping xmlMapping = this.nestedMapping; |
| if(xmlMapping instanceof BinaryDataCollectionMapping) { |
| choiceElementNodeValue = new XMLBinaryDataCollectionMappingNodeValue((BinaryDataCollectionMapping)xmlMapping); |
| choiceElementMarshalNodeValue = choiceElementNodeValue; |
| } else if(xmlMapping instanceof DirectCollectionMapping) { |
| choiceElementNodeValue = new XMLCompositeDirectCollectionMappingNodeValue((DirectCollectionMapping)xmlMapping); |
| choiceElementMarshalNodeValue = choiceElementNodeValue; |
| } else if(xmlMapping instanceof CompositeCollectionMapping){ |
| choiceElementNodeValue = new XMLCompositeCollectionMappingNodeValue((CompositeCollectionMapping)xmlMapping); |
| choiceElementMarshalNodeValue = choiceElementNodeValue; |
| }else if(xmlMapping instanceof AnyCollectionMapping){ |
| choiceElementNodeValue = new XMLAnyCollectionMappingNodeValue((AnyCollectionMapping)xmlMapping); |
| choiceElementMarshalNodeValue = choiceElementNodeValue; |
| } else { |
| choiceElementNodeValue = new XMLCollectionReferenceMappingNodeValue((CollectionReferenceMapping)xmlMapping, xmlField); |
| CollectionReferenceMapping refMapping = ((CollectionReferenceMapping)xmlMapping); |
| if(refMapping.usesSingleNode() || refMapping.getFields().size() == 1) { |
| choiceElementMarshalNodeValue = new XMLCollectionReferenceMappingNodeValue(refMapping, xmlField); |
| |
| } else { |
| choiceElementMarshalNodeValue = new XMLCollectionReferenceMappingMarshalNodeValue((CollectionReferenceMapping)xmlMapping); |
| } |
| } |
| } |
| |
| public void setContainerNodeValue(XMLChoiceCollectionMappingUnmarshalNodeValue nodeValue) { |
| this.containerNodeValue = nodeValue; |
| } |
| |
| public void setNullValue(Object object, CoreSession session) { |
| xmlChoiceCollectionMapping.setAttributeValueInObject(object, null); |
| } |
| |
| @Override |
| public void endElement(XPathFragment xPathFragment, UnmarshalRecord unmarshalRecord) { |
| Object collection = unmarshalRecord.getContainerInstance(this.containerNodeValue); |
| |
| if(null != xmlChoiceCollectionMapping.getConverter()) { |
| UnmarshalContext unmarshalContext = unmarshalRecord.getUnmarshalContext(); |
| unmarshalRecord.setUnmarshalContext(new ChoiceUnmarshalContext(unmarshalContext, xmlChoiceCollectionMapping)); |
| this.choiceElementNodeValue.endElement(xPathFragment, unmarshalRecord, collection); |
| unmarshalRecord.setUnmarshalContext(unmarshalContext); |
| } else { |
| this.choiceElementNodeValue.endElement(xPathFragment, unmarshalRecord, collection); |
| } |
| } |
| |
| @Override |
| public boolean startElement(XPathFragment xPathFragment, UnmarshalRecord unmarshalRecord, Attributes atts) { |
| return this.choiceElementNodeValue.startElement(xPathFragment, unmarshalRecord, atts); |
| } |
| |
| @Override |
| public void setXPathNode(XPathNode xPathNode) { |
| super.setXPathNode(xPathNode); |
| this.choiceElementNodeValue.setXPathNode(xPathNode); |
| } |
| |
| @Override |
| public Object getContainerInstance() { |
| return getContainerPolicy().containerInstance(); |
| } |
| |
| @Override |
| public void setContainerInstance(Object object, Object containerInstance) { |
| xmlChoiceCollectionMapping.setAttributeValueInObject(object, containerInstance); |
| } |
| |
| @Override |
| public CoreContainerPolicy getContainerPolicy() { |
| return xmlChoiceCollectionMapping.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) { |
| //empty impl in the unmarshal node value |
| return false; |
| } |
| |
| @Override |
| public boolean marshal(XPathFragment xPathFragment, MarshalRecord marshalRecord, Object object, CoreAbstractSession session, NamespaceResolver namespaceResolver) { |
| //dummy impl in the unmarshal node value |
| return false; |
| } |
| |
| public NodeValue getChoiceElementNodeValue() { |
| return this.choiceElementNodeValue; |
| } |
| |
| public NodeValue getChoiceElementMarshalNodeValue() { |
| return this.choiceElementMarshalNodeValue; |
| } |
| |
| @Override |
| public boolean isUnmarshalNodeValue() { |
| return true; |
| } |
| |
| @Override |
| public boolean isWrapperAllowedAsCollectionName() { |
| return false; |
| } |
| |
| @Override |
| public boolean isMarshalNodeValue() { |
| return false; |
| } |
| |
| @Override |
| public ChoiceCollectionMapping getMapping() { |
| return xmlChoiceCollectionMapping; |
| } |
| |
| @Override |
| public boolean getReuseContainer() { |
| return getMapping().getReuseContainer(); |
| } |
| |
| public void setFieldToNodeValues(Map<Field, NodeValue> fieldToNodeValues) { |
| this.fieldToNodeValues = fieldToNodeValues; |
| } |
| |
| public Collection<NodeValue> getAllNodeValues() { |
| return this.fieldToNodeValues.values(); |
| } |
| |
| /** |
| * The underlying choice element node value will handle attributes. |
| * |
| */ |
| @Override |
| public void attribute(UnmarshalRecord unmarshalRecord, String URI, String localName, String value) { |
| this.choiceElementNodeValue.attribute(unmarshalRecord, URI, localName, value); |
| } |
| |
| /** |
| * INTERNAL: |
| * Indicates that this is the choice mapping node value that represents the mixed content. |
| */ |
| public void setIsMixedNodeValue(boolean isMixed) { |
| this.isMixedNodeValue = isMixed; |
| } |
| |
| /** |
| * INTERNAL: |
| * Return true if this is the node value representing mixed content. |
| */ |
| @Override |
| public boolean isMixedContentNodeValue() { |
| return this.isMixedNodeValue; |
| } |
| |
| /** |
| * 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(); |
| } |
| |
| } |