/******************************************************************************* * 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.ArrayList; import java.util.List; import java.util.Map; import javax.xml.namespace.QName; import org.eclipse.persistence.internal.core.queries.CoreContainerPolicy; import org.eclipse.persistence.internal.core.queries.CoreMappedKeyMapContainerPolicy; import org.eclipse.persistence.internal.core.sessions.CoreAbstractSession; import org.eclipse.persistence.internal.oxm.mappings.AnyAttributeMapping; import org.eclipse.persistence.internal.oxm.record.MarshalContext; import org.eclipse.persistence.internal.oxm.record.MarshalRecord; import org.eclipse.persistence.internal.oxm.record.UnmarshalRecord; /** * INTERNAL: * <p><b>Purpose</b>: This is how the XML Any Attribute Mapping is handled when * used with the TreeObjectBuilder.</p> */ public class XMLAnyAttributeMappingNodeValue extends MappingNodeValue implements ContainerValue { private AnyAttributeMapping xmlAnyAttributeMapping; private int index = -1; public XMLAnyAttributeMappingNodeValue(AnyAttributeMapping xmlAnyAttributeMapping) { super(); this.xmlAnyAttributeMapping = xmlAnyAttributeMapping; } public boolean isOwningNode(XPathFragment xPathFragment) { return xPathFragment == null; } @Override public boolean isWrapperAllowedAsCollectionName() { return false; } public boolean marshal(XPathFragment xPathFragment, MarshalRecord marshalRecord, Object object, CoreAbstractSession session, NamespaceResolver namespaceResolver) { if (xmlAnyAttributeMapping.isReadOnly()) { return false; } Object collection = xmlAnyAttributeMapping.getAttributeValueFromObject(object); if (collection == null) { return false; } CoreContainerPolicy cp = getContainerPolicy(); Object iter = cp.iteratorFor(collection); if (!cp.hasNext(iter)) { return false; } XPathFragment groupingElements = marshalRecord.openStartGroupingElements(namespaceResolver); List extraNamespaces = new ArrayList(); NamespaceResolver nr = marshalRecord.getNamespaceResolver(); while (cp.hasNext(iter)) { Map.Entry entry = (Map.Entry)cp.nextEntry(iter, session); Object key = entry.getKey(); if (key instanceof QName) { QName name = (QName) key; String value = entry.getValue().toString(); String qualifiedName = name.getLocalPart(); if (nr != null) { String prefix = nr.resolveNamespaceURI(name.getNamespaceURI()); if ((prefix != null) && prefix.length() > 0) { qualifiedName = prefix + Constants.COLON+ qualifiedName; } else if (name.getNamespaceURI() != null && name.getNamespaceURI().length() > 0) { String generatedPrefix = nr.generatePrefix(); if(marshalRecord.hasCustomNamespaceMapper()) { String customPrefix = marshalRecord.getMarshaller().getNamespacePrefixMapper().getPreferredPrefix(name.getNamespaceURI(), generatedPrefix, true); if(customPrefix != null && customPrefix.length() > 0) { generatedPrefix = customPrefix; } } qualifiedName = generatedPrefix + Constants.COLON + qualifiedName; nr.put(generatedPrefix, name.getNamespaceURI()); extraNamespaces.add(generatedPrefix); marshalRecord.namespaceDeclaration(generatedPrefix, name.getNamespaceURI()); } } if(javax.xml.XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(name.getNamespaceURI())){ marshalRecord.namespaceDeclaration(name.getLocalPart(), name.getNamespaceURI()); }else{ marshalRecord.attribute(name.getNamespaceURI(), name.getLocalPart(), qualifiedName, value); } } } for (int i = 0; i < extraNamespaces.size(); i++) { marshalRecord.getNamespaceResolver().removeNamespace((String) extraNamespaces.get(i)); } marshalRecord.closeStartGroupingElements(groupingElements); return true; } public void attribute(UnmarshalRecord unmarshalRecord, String namespaceURI, String localName, String value) { boolean includeAttribute = true; if(!xmlAnyAttributeMapping.isNamespaceDeclarationIncluded() && javax.xml.XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(namespaceURI)){ includeAttribute = false; }else if(!xmlAnyAttributeMapping.isSchemaInstanceIncluded() && javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI.equals(namespaceURI)){ includeAttribute = false; } if(includeAttribute){ CoreContainerPolicy cp = xmlAnyAttributeMapping.getContainerPolicy(); Object containerInstance = unmarshalRecord.getContainerInstance(this); QName key = new QName(namespaceURI, localName); cp.addInto(key, value, containerInstance, unmarshalRecord.getSession()); } } public Object getContainerInstance() { return xmlAnyAttributeMapping.getContainerPolicy().containerInstance(); } public void setContainerInstance(Object object, Object container) { xmlAnyAttributeMapping.setAttributeValueInObject(object, container); } public CoreMappedKeyMapContainerPolicy getContainerPolicy() { return (CoreMappedKeyMapContainerPolicy) xmlAnyAttributeMapping.getContainerPolicy(); } public boolean isContainerValue() { return true; } public boolean marshalSingleValue(XPathFragment xPathFragment, MarshalRecord marshalRecord, Object object, Object value, CoreAbstractSession session, NamespaceResolver namespaceResolver, MarshalContext marshalContext) { return true; } public AnyAttributeMapping getMapping() { return xmlAnyAttributeMapping; } public boolean getReuseContainer() { return getMapping().getReuseContainer(); } /** * 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(); } }