org.eclipse.persistence.mappings.xdb.DirectToXMLTypeMapping Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of org.eclipse.persistence.core Show documentation
Show all versions of org.eclipse.persistence.core Show documentation
EclipseLink build based upon Git transaction ecdf3c32c4
/*
* Copyright (c) 1998, 2018 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;
/**
* Purpose: 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);
}
}
}