| /*******************************************************************************
|
| * Copyright (c) 1998, 2013 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.HashMap;
|
| import java.util.List;
|
| import java.util.Map;
|
| import java.util.Map.Entry;
|
|
|
| import org.eclipse.persistence.internal.core.helper.CoreField;
|
| import org.eclipse.persistence.internal.core.sessions.CoreAbstractSession;
|
| import org.eclipse.persistence.internal.oxm.mappings.BinaryDataMapping;
|
| import org.eclipse.persistence.internal.oxm.mappings.ChoiceObjectMapping;
|
| import org.eclipse.persistence.internal.oxm.mappings.CompositeObjectMapping;
|
| import org.eclipse.persistence.internal.oxm.mappings.DirectMapping;
|
| import org.eclipse.persistence.internal.oxm.mappings.Field;
|
| import org.eclipse.persistence.internal.oxm.mappings.Mapping;
|
| import org.eclipse.persistence.internal.oxm.mappings.ObjectReferenceMapping;
|
| 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.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 XMLChoiceObjectMappingNodeValue extends MappingNodeValue {
|
|
|
| private NodeValue choiceElementNodeValue;
|
| private Map<Class, NodeValue> choiceElementNodeValues;
|
| private ChoiceObjectMapping xmlChoiceMapping;
|
| //The first node value of the choice will be registered as a null capable value. If any
|
| //of the choice elements get hit, this needs to be removed as a null value.
|
| private XMLChoiceObjectMappingNodeValue nullCapableNodeValue;
|
| private Field xmlField;
|
|
|
| public XMLChoiceObjectMappingNodeValue(ChoiceObjectMapping mapping, Field xmlField) {
|
| this.xmlChoiceMapping = mapping;
|
| this.xmlField = xmlField;
|
| initializeNodeValue();
|
| }
|
|
|
| public boolean isOwningNode(XPathFragment xPathFragment) {
|
| return choiceElementNodeValue.isOwningNode(xPathFragment);
|
| }
|
|
|
| public void initializeNodeValue() {
|
| Mapping xmlMapping = (Mapping) xmlChoiceMapping.getChoiceElementMappings().get(xmlField);
|
| choiceElementNodeValue = getNodeValueForMapping(xmlMapping);
|
| //check for mappings to other classes with the same field
|
| for(Entry<Class, Mapping> entry: ((Map<Class, Mapping>)xmlChoiceMapping.getChoiceElementMappingsByClass()).entrySet()) {
|
| Field field = (Field) xmlChoiceMapping.getClassToFieldMappings().get(entry.getKey());
|
| if(field != null && field.equals(this.xmlField)) {
|
| Mapping mappingForClass = entry.getValue();
|
| if(mappingForClass != xmlMapping) {
|
| if(this.choiceElementNodeValues == null) {
|
| choiceElementNodeValues = new HashMap<Class, NodeValue>();
|
| }
|
| choiceElementNodeValues.put(entry.getKey(), getNodeValueForMapping(mappingForClass));
|
| }
|
| }
|
| }
|
| }
|
|
|
| private NodeValue getNodeValueForMapping(Mapping xmlMapping) {
|
| if(xmlMapping instanceof BinaryDataMapping){
|
| return new XMLBinaryDataMappingNodeValue((BinaryDataMapping)xmlMapping);
|
| } else if(xmlMapping instanceof DirectMapping) {
|
| return new XMLDirectMappingNodeValue((DirectMapping)xmlMapping);
|
| } else if(xmlMapping instanceof ObjectReferenceMapping) {
|
| return new XMLObjectReferenceMappingNodeValue((ObjectReferenceMapping)xmlMapping, xmlField);
|
| } else {
|
| return new XMLCompositeObjectMappingNodeValue((CompositeObjectMapping)xmlMapping);
|
| }
|
| }
|
| public void setNullCapableNodeValue(XMLChoiceObjectMappingNodeValue nodeValue) {
|
| this.nullCapableNodeValue = nodeValue;
|
| }
|
|
|
| public boolean marshal(XPathFragment xPathFragment, MarshalRecord marshalRecord, Object object, CoreAbstractSession session, NamespaceResolver namespaceResolver) {
|
| return this.marshal(xPathFragment, marshalRecord, object, session, namespaceResolver, ObjectMarshalContext.getInstance());
|
| }
|
|
|
| public boolean marshal(XPathFragment xPathFragment, MarshalRecord marshalRecord, Object object, CoreAbstractSession session, NamespaceResolver namespaceResolver, MarshalContext marshalContext) {
|
| if(xmlChoiceMapping.isReadOnly()) {
|
| return false;
|
| }
|
| Object value = xmlChoiceMapping.getFieldValue(object, session, marshalRecord);
|
| return this.marshalSingleValue(xPathFragment, marshalRecord, object, value, session, namespaceResolver, marshalContext);
|
| }
|
|
|
| public boolean marshalSingleValue(XPathFragment xPathFragment, MarshalRecord marshalRecord, Object object, Object value, CoreAbstractSession session, NamespaceResolver namespaceResolver, MarshalContext marshalContext) {
|
| Class valueClass = null;
|
| if (value instanceof Root) {
|
| Root root = (Root)value;
|
| for(CoreField next: (List<CoreField>) this.xmlChoiceMapping.getFields()) {
|
| XPathFragment fragment = ((Field)next).getXPathFragment();
|
| while(fragment != null && !fragment.nameIsText) {
|
| if(fragment.getNextFragment() == null || fragment.getHasText()) {
|
| if(fragment.getLocalName().equals(root.getLocalName())) {
|
| String fragUri = fragment.getNamespaceURI();
|
| String namespaceUri = root.getNamespaceURI();
|
| if((namespaceUri == null && fragUri == null) || (namespaceUri != null && fragUri != null && namespaceUri.equals(fragUri))) {
|
| if(next == this.xmlField) {
|
| return this.choiceElementNodeValue.marshalSingleValue(xPathFragment, marshalRecord, object, value, session, namespaceResolver, marshalContext);
|
| } else {
|
| //If this root is associated with another field, then return and let that NodeValue handle it
|
| return false;
|
| }
|
| }
|
| }
|
| }
|
| fragment = fragment.getNextFragment();
|
| }
|
| }
|
| valueClass = root.getObject().getClass();
|
| }
|
| if (value != null) {
|
| if(valueClass == null) {
|
| valueClass = value.getClass();
|
| }
|
| Field fieldForClass = null;
|
| Class theClass = valueClass;
|
| while(theClass != null) {
|
| fieldForClass = (Field) xmlChoiceMapping.getClassToFieldMappings().get(valueClass);
|
| if(fieldForClass != null) {
|
| break;
|
| }
|
| theClass = theClass.getSuperclass();
|
| }
|
| if (fieldForClass != null && fieldForClass.equals(this.xmlField)) {
|
| if(this.choiceElementNodeValues != null) {
|
| NodeValue nodeValue = this.choiceElementNodeValues.get(theClass);
|
| if(nodeValue != null) {
|
| return nodeValue.marshalSingleValue(xPathFragment, marshalRecord, object, value, session, namespaceResolver, marshalContext);
|
| }
|
| }
|
| return this.choiceElementNodeValue.marshalSingleValue(xPathFragment, marshalRecord, object, value, session, namespaceResolver, marshalContext);
|
| }
|
| List<Field> sourceFields = null;
|
| theClass = valueClass;
|
| while(theClass != null) {
|
| sourceFields = (List<Field>) xmlChoiceMapping.getClassToSourceFieldsMappings().get(theClass);
|
| if(sourceFields != null) {
|
| break;
|
| }
|
| theClass = theClass.getSuperclass();
|
| }
|
| if (sourceFields != null && sourceFields.contains(this.xmlField)) {
|
| return this.choiceElementNodeValue.marshalSingleValue(xPathFragment, marshalRecord, object, value, session, namespaceResolver, marshalContext);
|
| }
|
| }
|
| return false;
|
| }
|
|
|
| public void endElement(XPathFragment xPathFragment, UnmarshalRecord unmarshalRecord) {
|
| if(null != xmlChoiceMapping.getConverter()) {
|
| UnmarshalContext unmarshalContext = unmarshalRecord.getUnmarshalContext();
|
| unmarshalRecord.setUnmarshalContext(new ChoiceUnmarshalContext(unmarshalContext, xmlChoiceMapping));
|
| this.choiceElementNodeValue.endElement(xPathFragment, unmarshalRecord);
|
| unmarshalRecord.setUnmarshalContext(unmarshalContext);
|
| } else {
|
| this.choiceElementNodeValue.endElement(xPathFragment, unmarshalRecord);
|
| }
|
| }
|
|
|
| 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);
|
| if(this.choiceElementNodeValues != null) {
|
| for(NodeValue next:choiceElementNodeValues.values()) {
|
| next.setXPathNode(xPathNode);
|
| }
|
| }
|
| }
|
|
|
| /**
|
| * 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);
|
| }
|
|
|
| @Override
|
| public Mapping getMapping() {
|
| return this.xmlChoiceMapping;
|
| }
|
|
|
| @Override
|
| public boolean isWhitespaceAware() {
|
| return choiceElementNodeValue.isWhitespaceAware();
|
| }
|
| } |