blob: 0a6c03cc01e04cf2e53e5aeedea2dc1bcde05bd7 [file] [log] [blame]
/*
* 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:
// Oracle - initial API and implementation from Oracle TopLink
package org.eclipse.persistence.oxm.record;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.Vector;
import javax.xml.namespace.QName;
import org.eclipse.persistence.internal.core.sessions.CoreAbstractSession;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.helper.Helper;
import org.eclipse.persistence.internal.oxm.ReferenceResolver;
import org.eclipse.persistence.internal.oxm.UnmarshalXPathEngine;
import org.eclipse.persistence.internal.oxm.XMLConversionManager;
import org.eclipse.persistence.oxm.IDResolver;
import org.eclipse.persistence.oxm.XMLField;
import org.eclipse.persistence.oxm.XMLConstants;
import org.eclipse.persistence.oxm.XMLLogin;
import org.eclipse.persistence.internal.oxm.XPathEngine;
import org.eclipse.persistence.internal.oxm.mappings.Field;
import org.eclipse.persistence.internal.oxm.record.TransformationRecord;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.oxm.NamespaceResolver;
import org.eclipse.persistence.oxm.mappings.nullpolicy.AbstractNullPolicy;
import org.eclipse.persistence.platform.xml.XMLParser;
import org.eclipse.persistence.platform.xml.XMLPlatform;
import org.eclipse.persistence.platform.xml.XMLPlatformFactory;
import org.eclipse.persistence.platform.xml.XMLTransformer;
import org.eclipse.persistence.exceptions.ValidationException;
import org.eclipse.persistence.exceptions.XMLMarshalException;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentFragment;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* PUBLIC:
* Provides a Record/Map API on an XML DOM element.
*/
public class DOMRecord extends XMLRecord implements TransformationRecord {
private Node dom;
private Node currentNode;
private XMLField lastUpdatedField;
private ReferenceResolver referenceResolver;
/**
* INTERNAL:
* Default constructor.
*/
public DOMRecord() {
super();
setNamespaceResolver(new NamespaceResolver());
referenceResolver = new ReferenceResolver();
// Required for subclasses.
}
/**
* INTERNAL:
* Create a record with the root element name.
*/
public DOMRecord(String rootElementName) {
this(rootElementName, (NamespaceResolver)null);
}
/**
* INTERNAL:
* Create a record with the root element name get the namespace URI from the namespaceResolver.
*/
public DOMRecord(String rootElementName, NamespaceResolver namespaceResolver) {
this();
String rootElementNamespaceURI = resolveNamespace(namespaceResolver, rootElementName);
setDOM(createNewDocument(rootElementName, rootElementNamespaceURI));
}
/**
* INTERNAL:
* Create a record with the root element name get the namespace URI from the namespaceResolver.
*/
public DOMRecord(String rootElementName, String rootElementNamespaceURI) {
this();
setDOM(createNewDocument(rootElementName, rootElementNamespaceURI));
}
/**
* INTERNAL:
* Create a record with the local root element name, that is a child of the parent.
*/
public DOMRecord(String localRootElementName, Node parent) {
this(localRootElementName, null, parent);
}
/**
* INTERNAL:
* Create a record with the local root element name, that is a child of the parent.
* Lookup the namespace URI from the namespaceResolver.
*/
public DOMRecord(String localRootElementName, NamespaceResolver namespaceResolver, Node parent) {
this();
Document document;
if (parent instanceof Document) {
document = (Document)parent;
} else {
document = parent.getOwnerDocument();
}
String localRootElementNamespaceURI = resolveNamespace(namespaceResolver, localRootElementName);
Element child = document.createElementNS(localRootElementNamespaceURI, localRootElementName);
parent.appendChild(child);
setDOM(child);
}
/**
* INTERNAL:
* Create a record with the element.
*/
public DOMRecord(Element element) {
this();
setDOM(element);
}
public DOMRecord(Node node) {
this();
setDOM(node);
}
/**
* INTERNAL:
* Create a record with the element.
*/
public DOMRecord(Document document) {
this();
setDOM(document.getDocumentElement());
}
/**
* PUBLIC:
* Get the local name of the context root element.
*/
@Override
public String getLocalName() {
String localName = getDOM().getLocalName();
if (null != localName) {
return localName;
}
return getDOM().getNodeName();
}
/**
* PUBLIC:
* Get the namespace URI for the context root element.
*/
@Override
public String getNamespaceURI() {
return getDOM().getNamespaceURI();
}
/**
* INTERNAL:
* The ReferenceResolver that is leveraged by key based mappings.
* @since EclipseLink 2.5.0
*/
public ReferenceResolver getReferenceResolver() {
if(null == referenceResolver) {
referenceResolver = new ReferenceResolver();
}
return referenceResolver;
}
/**
* INTERNAL:
* Set the ReferenceResolver that will be leveraged by key based mappings.
* @since EclipseLink 2.5.0
*/
public void setReferenceResolver(ReferenceResolver referenceResolver) {
this.referenceResolver = referenceResolver;
}
/**
* INTERNAL:
* Add the field-value pair to the document.
*/
@Override
public void add(DatabaseField key, Object value) {
// Value may be a direct value, nested record, or collection of values.
Object nodeValue = convertToNodeValue(value);
XPathEngine.getInstance().create(convertToXMLField(key), dom, nodeValue, session);
}
/**
* INTERNAL:
* Convert the value which may be a direct value, nested record, or set of nested records,
* to a node value usable with the XPathEngine.
*/
private Object convertToNodeValue(Object value) {
if (value instanceof List) {
List values = (List)value;
Vector nodeValues = new Vector(values.size());
for (int index = 0; index < values.size(); index++) {
Object nestedValue = values.get(index);
nodeValues.add(convertToNodeValue(nestedValue));
}
return nodeValues;
} else if (value instanceof DOMRecord) {
return ((DOMRecord)value).getDOM();
} else if (value != null && value.getClass() == XMLEntry.class) {
XMLEntry entry = (XMLEntry)value;
entry.setValue(convertToNodeValue(entry.getValue()));
return entry;
} else {
return value;
}
}
/**
* PUBLIC:
* Clear the sub-nodes of the DOM.
*/
@Override
public void clear() {
if(getDOM() instanceof Element) {
String domName = ((Element)getDOM()).getTagName();
this.dom = createNewDocument(domName, null);
this.currentNode = this.dom;
}
}
/**
* INTERNAL:
* Clone the row and its values.
*/
@Override
public DOMRecord clone() {
DOMRecord clone = (DOMRecord)super.clone();
if (clone != null) {
clone.setDOM((Element)dom.cloneNode(true));
}
return clone;
}
/**
* INTERNAL:
* Creates a new Document and returns the root element of that document
*/
public Node createNewDocument(String defaultRootElementName) {
return createNewDocument(defaultRootElementName, null);
}
/**
* INTERNAL:
* Creates a new Document and returns the root element of that document
*/
public Node createNewDocument(String defaultRootElementName, String namespaceURI) {
XMLPlatform xmlPlatform = XMLPlatformFactory.getInstance().getXMLPlatform();
Document document = xmlPlatform.createDocument();
if (defaultRootElementName == null || defaultRootElementName.length() == 0) {
DocumentFragment fragment = document.createDocumentFragment();
return fragment;
} else {
Node rootNode = document.createElementNS(namespaceURI, defaultRootElementName);
document.appendChild(rootNode);
return document.getDocumentElement();
}
}
/**
* PUBLIC:
* Return the document.
*/
@Override
public Document getDocument() {
return getDOM().getOwnerDocument();
}
/**
* INTERNAL:
* Check if the field is contained in the row.
*/
@Override
public boolean containsKey(DatabaseField key) {
XMLField xmlField = convertToXMLField(key);
NodeList nodeList = UnmarshalXPathEngine.getInstance().selectNodes(dom, xmlField, xmlField.getNamespaceResolver());
return nodeList.getLength() > 0;
}
/**
* PUBLIC:
* Check if the value is contained in the row.
*/
@Override
public boolean contains(Object value) {
return values().contains(value);
}
@Override
public Object get(DatabaseField key) {
Object value = getIndicatingNoEntry(key);
if(value == noEntry) {
return null;
}
return value;
}
/**
* INTERNAL:
* Given a DatabaseField return the corresponding value from the document
*/
@Override
public Object getIndicatingNoEntry(DatabaseField key) {
return getIndicatingNoEntry(key, false, false);
}
public Object getIndicatingNoEntry(DatabaseField key, boolean shouldReturnNode) {
return getIndicatingNoEntry(key, shouldReturnNode, false);
}
public Object getIndicatingNoEntry(DatabaseField key, boolean shouldReturnNode, boolean checkForXsiNil) {
XMLField field = convertToXMLField(key);
// handle 'self' xpath
if (field.isSelfField()) {
return this;
}
Object result = UnmarshalXPathEngine.getInstance().selectSingleNode(dom, field, field.getNamespaceResolver(), checkForXsiNil);
if(result == noEntry) {
if(shouldReturnNode) {
return null;
}
return noEntry;
}
if (result == NIL) {
return NIL;
}
Node node = (Node)result;
if(shouldReturnNode) {
return node;
}
// If a node was not found return null
if (null == node) {
return null;
}
// For Attributes and Text nodes return their value
if (Node.ELEMENT_NODE != node.getNodeType()) {
if (node.getNodeType() == Node.ATTRIBUTE_NODE) {
getValueFromAttribute((Attr)node, field);
}
// For Text, must handle typed elements
return getValueFromElement((Element)node.getParentNode(), node, field);
}
// If an element was found
return buildNestedRow((Element)node);
}
/**
* INTERNAL:
* Retrieve the value for the field name.
*/
@Override
public Object getValues(String key) {
Object value = getValuesIndicatingNoEntry(new XMLField(key));
if (value == AbstractRecord.noEntry) {
return null;
}
return value;
}
/**
* INTERNAL:
* Given a DatabaseField, return the corresponding values from the document
*/
@Override
public Object getValues(DatabaseField key) {
return this.getValues(key, null);
}
public Object getValues(DatabaseField key, AbstractNullPolicy nullPolicy) {
Object value = getValuesIndicatingNoEntry(key, nullPolicy);
if (value == AbstractRecord.noEntry) {
return null;
}
return value;
}
public Object getValuesIndicatingNoEntry(DatabaseField key) {
return this.getValuesIndicatingNoEntry(key, null);
}
public Object getValuesIndicatingNoEntry(DatabaseField key, AbstractNullPolicy nullPolicy) {
return getValuesIndicatingNoEntry(key, false, nullPolicy);
}
public List<XMLEntry> getValuesIndicatingNoEntry(List<DatabaseField> keys) {
return getValuesIndicatingNoEntry(keys, false);
}
public List<XMLEntry> getValuesIndicatingNoEntry(List<DatabaseField> keys, boolean shouldReturnNodes) {
List<XMLField> xmlFields = convertToXMLField(keys);
List<XMLEntry> values = UnmarshalXPathEngine.getInstance().selectNodes(dom, xmlFields, xmlFields.get(0).getNamespaceResolver());
if(shouldReturnNodes) {
return values;
}
for(XMLEntry next:values) {
Node nextNode = (Node)next.getValue();
if(!(nextNode.getNodeType() == Node.ELEMENT_NODE)) {
Object value = getValueFromElement((Element)nextNode.getParentNode(), nextNode, next.getXMLField());
next.setValue(value);
} else {
next.setValue(buildNestedRow((Element)nextNode));
}
}
return values;
}
/**
* INTERNAL:
* Given a DatabaseField, return the corresponding values from the document
*/
public Object getValuesIndicatingNoEntry(DatabaseField key, boolean shouldReturnNodes) {
return this.getValuesIndicatingNoEntry(key, shouldReturnNodes, null);
}
public Object getValuesIndicatingNoEntry(DatabaseField key, boolean shouldReturnNodes, AbstractNullPolicy nullPolicy) {
XMLField field = convertToXMLField(key);
NodeList nodeList = UnmarshalXPathEngine.getInstance().selectNodes(dom, field, field.getNamespaceResolver(), nullPolicy);
// If a node was not found return null
if (null == nodeList) {
return null;
}
int resultSize = nodeList.getLength();
Vector result = new Vector(resultSize);
if (resultSize == 0) {
return result;
}
if(shouldReturnNodes) {
//just copy all the nodes into the result vector and return it
for(int i = 0; i < resultSize; i++) {
result.add(nodeList.item(i));
}
return result;
}
// Assumption: NodeList contains nodes of the same type
Node firstNode = nodeList.item(0);
if ((firstNode == null) || (firstNode.getNodeType() != Node.ELEMENT_NODE)) {
if (field.usesSingleNode() && (resultSize == 1)) {
Node next = nodeList.item(0);
if (next == null) {
result.add(null);
} else {
Vector list = new Vector();
String sourceObject = next.getNodeValue();
StringTokenizer tokenizer = new StringTokenizer(sourceObject, " ");
while (tokenizer.hasMoreElements()) {
String token = tokenizer.nextToken();
Object nextItem = convertValue((Element)next.getParentNode(), field, token);
list.add(nextItem);
}
return list;
}
}
for (int x = 0; x < resultSize; x++) {
Node next = nodeList.item(x);
if (next == null) {
result.add(null);
} else {
result.add(getValueFromElement((Element)next.getParentNode(), next, field));
}
}
} else {
for (int x = 0; x < resultSize; x++) {
result.add(buildNestedRow((Element)nodeList.item(x)));
}
}
return result;
}
private Object getValueFromAttribute(Attr node, XMLField key) {
currentNode = node.getOwnerElement();
Object convertedValue = key.convertValueBasedOnSchemaType(node.getNodeValue(), (XMLConversionManager) session.getDatasourcePlatform().getConversionManager(), this);
currentNode = getDOM();
return convertedValue;
}
private Object getValueFromElement(Element node, Node textChild, Field key) {
Object value = textChild.getNodeValue();
return convertValue(node, key, value);
}
private Object convertValue(Element node, Field key, Object value) {
XMLConversionManager xmlCnvMgr = (XMLConversionManager) session.getDatasourcePlatform().getConversionManager();
if (key.isTypedTextField() && (node != null)) {
String schemaType = node.getAttributeNS(javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, XMLConstants.SCHEMA_TYPE_ATTRIBUTE);
if ((null != schemaType) && (schemaType.length() > 0)) {
QName qname = null;
int index = schemaType.indexOf(XMLConstants.COLON);
if (index == -1) {
qname = new QName(schemaType);
Class<?> convertClass = key.getJavaClass(qname, xmlCnvMgr);
return xmlCnvMgr.convertObject(value, convertClass);
} else {
String prefix = schemaType.substring(0, index);
String localPart = schemaType.substring(index + 1);
XMLPlatform xmlPlatform = XMLPlatformFactory.getInstance().getXMLPlatform();
String url = xmlPlatform.resolveNamespacePrefix(node, prefix);
qname = new QName(url, localPart);
Class<?> convertClass = key.getJavaClass(qname, xmlCnvMgr);
return xmlCnvMgr.convertObject(value, convertClass, qname);
}
}
}
currentNode = node;
Object convertedValue = key.convertValueBasedOnSchemaType(value, xmlCnvMgr, this);
currentNode = getDOM();
return convertedValue;
}
/**
* INTERNAL:
* Build the nested record, this can be overwriten by subclasses to use their subclass instance.
*/
public XMLRecord buildNestedRow(Element element) {
DOMRecord record = new DOMRecord(element);
record.setUnmarshaller(this.getUnmarshaller());
record.setOwningObject(this.getCurrentObject());
record.setDocPresPolicy(this.getDocPresPolicy());
record.setReferenceResolver(referenceResolver);
return record;
}
/**
* PUBLIC:
* Return the DOM.
*/
@Override
public Node getDOM() {
return dom;
}
/**
* INTERNAL:
* Set the field value into the DOM.
* The field name must be a valid simple XPath expression.
*/
@Override
public Object put(DatabaseField key, Object value) {
// Value may be a direct value, nested record, or collection of values.
XMLField field = convertToXMLField(key);
Object nodeValue = convertToNodeValue(value);
NodeList replaced = null;
boolean isEmptyCollection = false;
if (nodeValue instanceof Collection) {
isEmptyCollection = ((Collection)nodeValue).size() == 0;
replaced = XPathEngine.getInstance().replaceCollection(convertToXMLField(key), dom, (Collection)nodeValue, session);
} else {
replaced = XPathEngine.getInstance().replaceValue(convertToXMLField(key), dom, nodeValue, session);
}
if (replaced.getLength() == 0) {
// Replace does nothing if the node did not exist, return no nodes.
XPathEngine.getInstance().create(convertToXMLField(key), dom, nodeValue, lastUpdatedField, getDocPresPolicy(), session);
} else if (replaced.item(0) == getDOM()) {
// If the root element/record element was changed must update the record's reference.
setDOM(getDocument().getDocumentElement());
}
if(!field.getXPathFragment().isAttribute() && !field.getXPathFragment().nameIsText()) {
if(value != null && !isEmptyCollection) {
this.lastUpdatedField = field;
}
}
return replaced;
}
public Object put(List<XMLField> xmlFields, List<XMLEntry> values) {
Vector valuesToWrite = (Vector)convertToNodeValue(values);
List<XMLEntry> replaced = null;
replaced = XPathEngine.getInstance().replaceCollection(xmlFields, valuesToWrite, dom, getDocPresPolicy(), lastUpdatedField, session);
if(replaced.size() == 0) {
XPathEngine.getInstance().create(xmlFields, dom, valuesToWrite, lastUpdatedField, getDocPresPolicy(), session);
}
return replaced;
}
@Override
public Object put(Object key, Object value) throws ValidationException {
if (key instanceof String) {
return put((String)key, value);
} else if (key instanceof DatabaseField) {
return put((DatabaseField)key, value);
} else if (key instanceof List) {
return put((List<XMLField>)key, (List<XMLEntry>)value);
} else {
throw ValidationException.onlyFieldsAreValidKeysForDatabaseRows();
}
}
/**
* INTERNAL:
* Remove the field key from the row.
*/
@Override
public Object remove(DatabaseField key) {
return XPathEngine.getInstance().remove(convertToXMLField(key), dom, true);
}
/**
* INTERNAL:
* replaces the value at index with value
*/
@Override
public void replaceAt(Object value, int index) {
throw XMLMarshalException.operationNotSupported("replaceAt(Object value, int index)");
}
/**
* PUBLIC:
*/
@Override
public Set entrySet() {
int size = this.size();
Map tempMap = new HashMap(size);
Vector fields = getFields();
Vector values = getValues();
for (int i = 0; i < size; i++) {
tempMap.put(fields.elementAt(i), values.elementAt(i));
}
return tempMap.entrySet();
}
/**
* INTERNAL:
* Setting fields vector will not update the document so this is not supported
*/
@Override
protected void setFields(Vector fields) throws XMLMarshalException {
throw XMLMarshalException.operationNotSupported("setField(Vector fields)");
}
/**
* INTERNAL:
* This should not be used, but added some support for it as
* is called from some places such as sdk call used in the descriptor to define operation not supported,
* may also be called from toplin in some places.
*/
@Override
public Vector getFields() {
int length = getDOM().getChildNodes().getLength();
Node nextNode = null;
if(length > 0) {
nextNode = getDOM().getChildNodes().item(0);
}
Vector fields = new Vector(length);
while(nextNode != null) {
fields.add(new DatabaseField(nextNode.getNodeName()));
nextNode = nextNode.getNextSibling();
}
return fields;
}
/**
* INTERNAL:
* This should not be used, but added some support for it as
* is called from some places such as sdk call used in the descriptor to define operation not supported,
* may also be called from TopLink in some places.
*/
@Override
public Vector getValues() {
int length = getDOM().getChildNodes().getLength();
Node nextNode = null;
if(length > 0) {
nextNode = getDOM().getFirstChild();
}
Vector values = new Vector(length);
while(nextNode != null) {
values.add(nextNode);
nextNode = nextNode.getNextSibling();
}
return values;
}
/**
* INTERNAL:
* Setting values vector will not update the document so this is not supported
*/
@Override
protected void setValues(Vector values) throws XMLMarshalException {
throw XMLMarshalException.operationNotSupported("setValues(Vector values)");
}
/**
* INTERNAL:
* Sets the dom and updated document to be the owner document of the given element
*/
public void setDOM(Node element) {
this.dom = element;
this.currentNode = element;
this.getNamespaceResolver().setDOM(element);
}
public void setDOM(Element element) {
this.dom = element;
this.currentNode = element;
this.getNamespaceResolver().setDOM(element);
}
/**
* INTERNAL:
* Print the dom XML string.
*/
@Override
public String toString() {
StringWriter writer = new StringWriter();
writer.write(Helper.getShortClassName(getClass()));
writer.write("(");
transformToWriter(writer);
writer.write(")");
return writer.toString();
}
/**
* PUBLIC:
* Return the set of element names from the DOM.
*/
@Override
public Set keySet() {
int length = getDOM().getChildNodes().getLength();
HashSet keys = new HashSet(length);
for (int index = 0; index < length; index++) {
keys.add(getDOM().getChildNodes().item(index).getNodeName());
}
return keys;
}
/**
* PUBLIC:
* Return the collection of element values from the DOM.
*/
@Override
public Collection values() {
int length = getDOM().getChildNodes().getLength();
Vector values = new Vector(length);
for (int index = 0; index < length; index++) {
values.add(getDOM().getChildNodes().item(index));
}
return values;
}
/**
* Return the number of elements in the DOM.
*/
@Override
public int size() {
return getDOM().getAttributes().getLength() + getDOM().getChildNodes().getLength();
}
/**
* Set the XML from an XML string.
*/
public void transformFromXML(String xml) {
Reader reader = new StringReader(xml);
transformFromXML(reader);
}
/**
* INTERNAL:
* Return the namespace uri for the prefix of the given local name
*/
private String resolveNamespace(NamespaceResolver namespaceResolver, String localName) {
if(localName == null) {
return null;
}
int colonIndex = localName.indexOf(XMLConstants.COLON);
if (colonIndex < 0) {
// handle target/default namespace
if (namespaceResolver != null) {
return namespaceResolver.getDefaultNamespaceURI();
}
return null;
} else {
if (namespaceResolver == null) {
//throw an exception if the name has a : in it but the namespaceresolver is null
throw XMLMarshalException.namespaceResolverNotSpecified(localName);
}
String prefix = localName.substring(0, colonIndex);
String uri = namespaceResolver.resolveNamespacePrefix(prefix);
if (uri == null) {
//throw an exception if the prefix is not found in the namespaceresolver
throw XMLMarshalException.namespaceNotFound(prefix);
}
return uri;
}
}
@Override
public void setSession(AbstractSession session) {
this.session = session;
if (session != null && session.getDatasourceLogin() instanceof XMLLogin) {
this.equalNamespaceResolvers = ((XMLLogin) session.getDatasourceLogin()).hasEqualNamespaceResolvers();
}
}
/**
* Set the XML from an XML reader.
*/
public void transformFromXML(Reader reader) {
XMLParser parser = XMLPlatformFactory.getInstance().getXMLPlatform().newXMLParser();
Document document = parser.parse(reader);
setDOM(document.getDocumentElement());
}
/**
* Return the XML string representation of the DOM.
*/
@Override
public String transformToXML() {
StringWriter writer = new StringWriter();
transformToWriter(writer);
return writer.toString();
}
/**
* Write the XML string representation of the DOM.
*/
public void transformToWriter(Writer writer) {
XMLTransformer xmlTransformer = XMLPlatformFactory.getInstance().getXMLPlatform().newXMLTransformer();
xmlTransformer.transform(this.getDOM(), writer);
}
@Override
public String resolveNamespacePrefix(String prefix) {
XMLPlatform xmlPlatform = XMLPlatformFactory.getInstance().getXMLPlatform();
return xmlPlatform.resolveNamespacePrefix(currentNode, prefix);
}
/**
* INTERNAL:
* If the UnmarshalRecord has a ReferenceResolver, tell it to resolve its
* references.
* @since EclipseLink 2.5.0
*/
public void resolveReferences(CoreAbstractSession abstractSession, IDResolver idResolver) {
if(null != referenceResolver) {
referenceResolver.resolveReferences(abstractSession, idResolver, unmarshaller.getErrorHandler());
}
}
}