/******************************************************************************* * Copyright (c) 1998, 2015 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 v1.0 and Eclipse Distribution License v. 1.0 * which accompanies this distribution. * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html * and the Eclipse Distribution License is available at * http://www.eclipse.org/org/documents/edl-v10.php. * * 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(); } 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); } 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); } } public boolean startElement(XPathFragment xPathFragment, UnmarshalRecord unmarshalRecord, Attributes atts) { return this.choiceElementNodeValue.startElement(xPathFragment, unmarshalRecord, atts); } public void setXPathNode(XPathNode xPathNode) { super.setXPathNode(xPathNode); this.choiceElementNodeValue.setXPathNode(xPathNode); } public Object getContainerInstance() { return getContainerPolicy().containerInstance(); } public void setContainerInstance(Object object, Object containerInstance) { xmlChoiceCollectionMapping.setAttributeValueInObject(object, containerInstance); } public CoreContainerPolicy getContainerPolicy() { return xmlChoiceCollectionMapping.getContainerPolicy(); } public boolean isContainerValue() { return true; } 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; } 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; } public boolean isUnmarshalNodeValue() { return true; } public boolean isWrapperAllowedAsCollectionName() { return false; } public boolean isMarshalNodeValue() { return false; } public ChoiceCollectionMapping getMapping() { return xmlChoiceCollectionMapping; } 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. * */ 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. */ public boolean isMixedContentNodeValue() { return this.isMixedNodeValue; } /** * INTERNAL: * Used to track the index of the corresponding containerInstance in the containerInstances Object[] on UnmarshalRecord */ 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 */ 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 */ public boolean isDefaultEmptyContainer() { return getMapping().isDefaultEmptyContainer(); } }