| /* |
| * 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 |
| // 11/10/2011-2.4 Guy Pelletier |
| // - 357474: Address primaryKey option from tenant discriminator column |
| package org.eclipse.persistence.mappings.xdb; |
| |
| import org.eclipse.persistence.exceptions.ConversionException; |
| import org.eclipse.persistence.exceptions.DescriptorException; |
| import org.eclipse.persistence.internal.helper.ClassConstants; |
| import org.eclipse.persistence.internal.platform.database.XMLTypePlaceholder; |
| import org.eclipse.persistence.internal.sessions.AbstractSession; |
| import org.eclipse.persistence.mappings.DirectToFieldMapping; |
| import org.eclipse.persistence.platform.xml.XMLComparer; |
| import org.eclipse.persistence.platform.xml.XMLParser; |
| import org.eclipse.persistence.platform.xml.XMLPlatformFactory; |
| import org.eclipse.persistence.platform.xml.XMLTransformer; |
| import org.eclipse.persistence.sessions.Session; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Node; |
| |
| /** |
| * <b>Purpose</b>: Mapping used to map from a DOM (org.w3c.Document) or XML String into |
| * an Oracle XMLType field, in Oracle 9i XDB. |
| * |
| * @since Toplink 10.1.3 |
| */ |
| public class DirectToXMLTypeMapping extends DirectToFieldMapping { |
| /** |
| * Indicates if we should initialize the whole DOM on a read. |
| * This is only used if the user is mapping from an Oracle Document implementation. |
| */ |
| protected boolean shouldReadWholeDocument = false; |
| |
| /** |
| * Used to convert the DOM to a String. |
| */ |
| private XMLTransformer xmlTransformer; |
| |
| /** |
| * Used to determine if the XML document has been modified. |
| */ |
| private XMLComparer xmlComparer; |
| |
| /** |
| * Used to convert the String to a DOM |
| */ |
| private XMLParser xmlParser; |
| |
| /** |
| * INTERNAL: |
| * Default to mutable if mapped as a DOM. |
| */ |
| @Override |
| public void preInitialize(AbstractSession session) throws DescriptorException { |
| if (this.attributeClassification == null) { |
| this.attributeClassification = getAttributeAccessor().getAttributeClass(); |
| } |
| if ((this.isMutable == null) && (this.attributeClassification != ClassConstants.STRING)) { |
| setIsMutable(true); |
| } |
| super.preInitialize(session); |
| } |
| |
| /** |
| * INTERNAL: |
| * The mapping is initialized with the given session. This mapping is fully initialized |
| * after this. |
| */ |
| @Override |
| public void initialize(AbstractSession session) throws DescriptorException { |
| super.initialize(session); |
| setFieldClassification(XMLTypePlaceholder.class); |
| } |
| |
| public DirectToXMLTypeMapping() { |
| super(); |
| this.xmlTransformer = XMLPlatformFactory.getInstance().getXMLPlatform().newXMLTransformer(); |
| this.xmlTransformer.setFormattedOutput(false); |
| this.xmlParser = XMLPlatformFactory.getInstance().getXMLPlatform().newXMLParser(); |
| this.xmlComparer = new XMLComparer(); |
| } |
| |
| /** |
| * PUBLIC: |
| * @param readWholeDocument - determines if the Oracle XDB DOM should be fully initialized |
| * on a read. |
| */ |
| public void setShouldReadWholeDocument(boolean readWholeDocument) { |
| this.shouldReadWholeDocument = readWholeDocument; |
| } |
| |
| /** |
| * PUBLIC: |
| * @return boolean - returns true if currently initializing DOMs on reads. |
| */ |
| public boolean shouldReadWholeDocument() { |
| return shouldReadWholeDocument; |
| } |
| |
| /** |
| * INTERNAL: |
| * Get the attribute value for the given field value. If we're mapping to a |
| * Document, we need to check if we should return the Oracle DOM or build a |
| * new one. |
| */ |
| @Override |
| public Object getObjectValue(Object fieldValue, Session session) throws ConversionException { |
| Object attributeValue = fieldValue; |
| try { |
| if (attributeValue != null) { |
| if (this.attributeClassification != ClassConstants.STRING) { |
| String xml = (String)attributeValue; |
| java.io.StringReader reader = new java.io.StringReader(xml); |
| return this.xmlParser.parse(reader); |
| } |
| } |
| } catch (Exception ex) { |
| throw ConversionException.couldNotBeConverted(fieldValue, this.attributeClassification, ex); |
| } |
| |
| if ((attributeValue == null) && (this.nullValue != null)) {// Translate default null value |
| return this.nullValue; |
| } |
| |
| // Allow for user defined conversion to the object value. |
| if (this.converter != null) { |
| attributeValue = this.converter.convertDataValueToObjectValue(attributeValue, session); |
| } |
| return attributeValue; |
| } |
| |
| @Override |
| public boolean isDirectToXMLTypeMapping() { |
| return true; |
| } |
| |
| /** |
| * INTERNAL: |
| * Clone the DOM Document if required. |
| */ |
| @Override |
| protected Object buildCloneValue(Object attributeValue, AbstractSession session) { |
| Object newAttributeValue = attributeValue; |
| if (isMutable() && attributeValue != null) { |
| if ((getAttributeClassification() == ClassConstants.DOCUMENT) || (getAttributeClassification() == ClassConstants.NODE)) { |
| Document doc = (Document)attributeValue; |
| newAttributeValue = doc.cloneNode(true); |
| } |
| } |
| return newAttributeValue; |
| } |
| |
| /** |
| * INTERNAL: |
| * Compare the attribute values. |
| * Compare Nodes if mapped as a DOM. |
| */ |
| @Override |
| protected boolean compareObjectValues(Object firstValue, Object secondValue, AbstractSession session) { |
| // PERF: Check identity before conversion. |
| if (firstValue == secondValue) { |
| return true; |
| } |
| if ((firstValue == null) || (secondValue == null)) { |
| return false; |
| } |
| if (getAttributeClassification() == ClassConstants.STRING) { |
| return firstValue.equals(secondValue); |
| } else { |
| Object one = getFieldValue(firstValue, session); |
| Object two = getFieldValue(secondValue, session); |
| if (one instanceof Node && two instanceof Node) { |
| return this.xmlComparer.isNodeEqual((Node)one, (Node)two); |
| } |
| return one.equals(two); |
| } |
| } |
| } |