| /* |
| * 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: |
| // Denise Smith - 2.5.1 - Initial Implementation |
| package org.eclipse.persistence.internal.oxm; |
| |
| import java.util.List; |
| |
| import javax.xml.namespace.QName; |
| |
| import org.eclipse.persistence.core.mappings.CoreAttributeAccessor; |
| import org.eclipse.persistence.exceptions.XMLMarshalException; |
| import org.eclipse.persistence.internal.core.helper.CoreClassConstants; |
| import org.eclipse.persistence.internal.core.sessions.CoreAbstractSession; |
| import org.eclipse.persistence.internal.oxm.mappings.CompositeObjectMapping; |
| import org.eclipse.persistence.internal.oxm.mappings.Descriptor; |
| 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.UnmarshalKeepAsElementPolicy; |
| import org.eclipse.persistence.internal.oxm.mappings.VariableXPathObjectMapping; |
| import org.eclipse.persistence.internal.oxm.record.MarshalContext; |
| import org.eclipse.persistence.internal.oxm.record.MarshalRecord; |
| import org.eclipse.persistence.internal.oxm.record.UnmarshalRecord; |
| import org.xml.sax.Attributes; |
| import org.xml.sax.SAXException; |
| |
| public abstract class XMLVariableXPathMappingNodeValue extends XMLRelationshipMappingNodeValue{ |
| |
| |
| /** |
| * INTERNAL: |
| */ |
| @Override |
| public boolean isOwningNode(XPathFragment xPathFragment) { |
| return null == xPathFragment; |
| } |
| |
| @Override |
| protected Descriptor findReferenceDescriptor(XPathFragment xPathFragment, UnmarshalRecord unmarshalRecord, Attributes atts, Mapping mapping, UnmarshalKeepAsElementPolicy policy) { |
| return (Descriptor)mapping.getReferenceDescriptor(); |
| } |
| |
| @Override |
| public void attribute(UnmarshalRecord unmarshalRecord, String namespaceURI, String localName, String value) { |
| Descriptor referenceDescriptor = (Descriptor) getMapping().getReferenceDescriptor(); |
| ObjectBuilder treeObjectBuilder = (ObjectBuilder) referenceDescriptor.getObjectBuilder(); |
| MappingNodeValue textMappingNodeValue = (MappingNodeValue) treeObjectBuilder.getRootXPathNode().getTextNode().getNodeValue(); |
| Mapping textMapping = textMappingNodeValue.getMapping(); |
| Object childObject = referenceDescriptor.getInstantiationPolicy().buildNewInstance(); |
| if(textMapping.isAbstractDirectMapping()) { |
| DirectMapping xmlDirectMapping = (DirectMapping) textMappingNodeValue.getMapping(); |
| Field xmlField = (Field) xmlDirectMapping.getField(); |
| Object realValue = unmarshalRecord.getXMLReader().convertValueBasedOnSchemaType(xmlField, value, (ConversionManager) unmarshalRecord.getSession().getDatasourcePlatform().getConversionManager(), unmarshalRecord); |
| Object convertedValue = xmlDirectMapping.getAttributeValue(realValue, unmarshalRecord.getSession(), unmarshalRecord); |
| xmlDirectMapping.setAttributeValueInObject(childObject, convertedValue); |
| } else { |
| Object oldChildObject = unmarshalRecord.getCurrentObject(); |
| CompositeObjectMapping nestedXMLCompositeObjectMapping = (CompositeObjectMapping) textMappingNodeValue.getMapping(); |
| unmarshalRecord.setCurrentObject(childObject); |
| textMappingNodeValue.attribute(unmarshalRecord, namespaceURI, localName, value); |
| unmarshalRecord.setCurrentObject(oldChildObject); |
| } |
| setXPathInObject(namespaceURI, localName, childObject); |
| setOrAddAttributeValue(unmarshalRecord, childObject, null, null); |
| } |
| |
| @Override |
| public boolean marshalSingleValue(XPathFragment xPathFragment, MarshalRecord marshalRecord, Object object, Object value, CoreAbstractSession session, NamespaceResolver namespaceResolver, MarshalContext marshalContext) { |
| if (null == value) { |
| return false; |
| } |
| |
| Object originalValue = value; |
| VariableXPathObjectMapping mapping = this.getMapping(); |
| Descriptor descriptor = (Descriptor)mapping.getReferenceDescriptor(); |
| |
| if(descriptor.hasInheritance()){ |
| Class<?> objectValueClass = value.getClass(); |
| if(!(objectValueClass == descriptor.getJavaClass())){ |
| descriptor = (Descriptor) session.getDescriptor(objectValueClass); |
| } |
| } |
| |
| Marshaller marshaller = marshalRecord.getMarshaller(); |
| ObjectBuilder objectBuilder = (ObjectBuilder)descriptor.getObjectBuilder(); |
| List extraNamespaces = objectBuilder.addExtraNamespacesToNamespaceResolver(descriptor, marshalRecord, session, true, true); |
| //Change to get the value from the object |
| String defaultRootElementString = descriptor.getDefaultRootElement(); |
| |
| marshalRecord.beforeContainmentMarshal(value); |
| XPathFragment rootFragment = mapping.getXPathFragmentForValue(value, marshalRecord.getNamespaceResolver(), marshalRecord.isNamespaceAware(), marshalRecord.getNamespaceSeparator()); |
| |
| XPathFragment groupingFragment = marshalRecord.openStartGroupingElements(namespaceResolver); |
| if(mapping.isAttribute()){ |
| ObjectBuilder tob = (ObjectBuilder) mapping.getReferenceDescriptor().getObjectBuilder(); |
| MappingNodeValue textMappingNodeValue = (MappingNodeValue) tob.getRootXPathNode().getTextNode().getMarshalNodeValue(); |
| Mapping textMapping = textMappingNodeValue.getMapping(); |
| if(textMapping.isAbstractDirectMapping()) { |
| DirectMapping xmlDirectMapping = (DirectMapping) textMapping; |
| Object fieldValue = xmlDirectMapping.getFieldValue(xmlDirectMapping.valueFromObject(value, xmlDirectMapping.getField(), session), session, marshalRecord); |
| QName schemaType = ((Field) xmlDirectMapping.getField()).getSchemaTypeForValue(fieldValue, session); |
| marshalRecord.attribute(rootFragment, namespaceResolver, fieldValue, schemaType); |
| //marshalRecord.closeStartGroupingElements(groupingFragment); |
| return true; |
| } else { |
| return textMappingNodeValue.marshalSingleValue(rootFragment, marshalRecord, value, textMapping.getAttributeValueFromObject(value), session, namespaceResolver, marshalContext); |
| } |
| }else{ |
| marshalRecord.closeStartGroupingElements(groupingFragment); |
| getXPathNode().startElement(marshalRecord, rootFragment, object, session, marshalRecord.getNamespaceResolver(), objectBuilder, value); |
| writeExtraNamespaces(extraNamespaces, marshalRecord, session); |
| |
| marshalRecord.addXsiTypeAndClassIndicatorIfRequired(descriptor, (Descriptor)mapping.getReferenceDescriptor(), (Field)mapping.getField(), originalValue, value, false, false); |
| objectBuilder.buildRow(marshalRecord, value, session, marshaller, null); |
| marshalRecord.afterContainmentMarshal(object, value); |
| marshalRecord.endElement(rootFragment, namespaceResolver); |
| marshalRecord.removeExtraNamespacesFromNamespaceResolver(extraNamespaces, session); |
| } |
| return true; |
| } |
| |
| @Override |
| public void endElement(XPathFragment xPathFragment, UnmarshalRecord unmarshalRecord) { |
| UnmarshalRecord childRecord = unmarshalRecord.getChildRecord(); |
| if(childRecord != null){ |
| Object childObject = childRecord.getCurrentObject(); |
| String localName = xPathFragment.getLocalName(); |
| |
| setXPathInObject(xPathFragment.getNamespaceURI(), localName, childObject); |
| |
| childObject = getMapping().convertDataValueToObjectValue(childObject, unmarshalRecord.getSession(), unmarshalRecord.getUnmarshaller()); |
| setOrAddAttributeValue(unmarshalRecord, childObject, xPathFragment, null); |
| unmarshalRecord.setChildRecord(null); |
| } else { |
| unmarshalRecord.resetStringBuffer(); |
| } |
| } |
| |
| @Override |
| public abstract VariableXPathObjectMapping getMapping(); |
| |
| public void setXPathInObject(String uri, String localName, Object childObject) { |
| CoreAttributeAccessor variableAttributeAccessor = this.getMapping().getVariableAttributeAccessor(); |
| if(!variableAttributeAccessor.isWriteOnly()){ |
| Object value = null; |
| if(getMapping().getVariableAttributeAccessor().getAttributeClass() == CoreClassConstants.QNAME){ |
| if(uri != null && uri.length() > 0) { |
| value = new QName(uri, localName); |
| }else{ |
| value = new QName( localName); |
| } |
| }else{ |
| value = localName; |
| } |
| |
| variableAttributeAccessor.setAttributeValueInObject(childObject, value); |
| } |
| } |
| |
| @Override |
| public boolean startElement(XPathFragment xPathFragment, UnmarshalRecord unmarshalRecord, Attributes atts) { |
| try { |
| processChild(xPathFragment, unmarshalRecord, atts, (Descriptor) getMapping().getReferenceDescriptor(), getMapping()); |
| } catch (SAXException e) { |
| throw XMLMarshalException.unmarshalException(e); |
| } |
| return true; |
| } |
| |
| @Override |
| public boolean isMixedContentNodeValue() { |
| return true; |
| } |
| |
| } |