/*
 * 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());
        }
    }

}
