/*
 * 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
package org.eclipse.persistence.oxm;

import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.dom.DOMSource;
import javax.xml.validation.Schema;
import javax.xml.validation.Validator;

import org.eclipse.persistence.exceptions.XMLMarshalException;
import org.eclipse.persistence.internal.oxm.Root;
import org.eclipse.persistence.internal.oxm.XMLObjectBuilder;
import org.eclipse.persistence.internal.oxm.documentpreservation.XMLBinderPolicy;
import org.eclipse.persistence.internal.oxm.record.DOMReader;
import org.eclipse.persistence.internal.oxm.record.SAXUnmarshaller;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.oxm.documentpreservation.DocumentPreservationPolicy;
import org.eclipse.persistence.oxm.record.DOMRecord;
import org.eclipse.persistence.platform.xml.XMLTransformer;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.ErrorHandler;

/**
 * PUBLIC:
 * <p><b>Purpose:</b>Provide a runtime public interface for preserving unmapped content from an
 * XML Document.
 * <p><b>Responsibilities:</b><ul>
 * <li>Unmarshal XML into JavaObjects and maintain the associations between nodes and objects</li>
 * <li>Update the cached XML based on changes to the object</li>
 * <li>Update the cached objects based on changes to the XML Document</li>
 * <li>Provide API to access the cached Node for a given object</li>
 * <li>Provide API to access the cached Object for a given XML Node</li>
 * </ul>
 *
 * <p>The XML Binder is a runtime class that allows an association to be maintained between the
 * original XML Document and the Java Objects built from the Document. It allows unmapped content
 * (such as comments, processing instructions or other unmapped elements and attributes) to be
 * preserved. The XMLBinder is created through an XMLContext.
 *
 *  @see org.eclipse.persistence.oxm.XMLContext
 *  @author mmacivor
 */

public class XMLBinder {

    SAXUnmarshaller saxUnmarshaller;
    XMLContext context;
    XMLMarshaller marshaller;
    XMLUnmarshaller unmarshaller;
    DocumentPreservationPolicy documentPreservationPolicy;
    DOMReader reader;

    public XMLBinder(XMLContext context) {
        this.context = new XMLContext(context.getXMLContextState());
        marshaller = this.context.createMarshaller();
        unmarshaller = this.context.createUnmarshaller();
        initialize();
    }

    public XMLBinder(XMLContext context, XMLMarshaller marshaller, XMLUnmarshaller unmarshaller) {
        this.context = new XMLContext(context.getXMLContextState());
        this.marshaller = marshaller;
        this.unmarshaller = unmarshaller;
        initialize();
    }

    private void initialize() {
        saxUnmarshaller = new SAXUnmarshaller(unmarshaller, null);
        documentPreservationPolicy = new XMLBinderPolicy();
        reader = new DOMReader(unmarshaller);
    }

    /**
     * This method will unmarshal the provided node into mapped java objects. The original node
     * will be cached rather than thrown away.
     * @param node
     * @return The root object unmarshalled from the provided node.
     */
    public Object unmarshal(org.w3c.dom.Node node) {
        validateNode(node);

        reader.setDocPresPolicy(documentPreservationPolicy);
        Object toReturn = saxUnmarshaller.unmarshal(reader, node);
        return toReturn;
    }

    private void validateNode(org.w3c.dom.Node node) {
        if (getSchema() != null) {
            Validator validator = getSchema().newValidator();
            validator.setErrorHandler(getErrorHandler());
            try {
                validator.validate(new DOMSource(node));
            } catch (Exception e) {
                throw XMLMarshalException.validateException(e);
            }
        }
    }

    public XMLRoot unmarshal(org.w3c.dom.Node node, Class javaClass) {
        validateNode(node);
        reader.setDocPresPolicy(documentPreservationPolicy);
        return buildXMLRootFromObject(saxUnmarshaller.unmarshal(reader, node, javaClass));
    }

    /**
     * This method will update the cached XML node for the provided object. If no node exists for this
     * object, then no operation is performed.
     * @param obj
     */
    public void updateXML(Object obj) {
        if(obj instanceof Root) {
            obj = ((Root)obj).getObject();
        }
        Node associatedNode = documentPreservationPolicy.getNodeForObject(obj);
        if(associatedNode == null) {
            return;
        }
        updateXML(obj, associatedNode);
    }

    public void marshal(Object obj, Node node) {
        XMLDescriptor desc = null;
        boolean isXMLRoot = obj instanceof Root;
        if (isXMLRoot) {
            Object o = ((Root) obj).getObject();
            desc = (XMLDescriptor) context.getSession(o).getDescriptor(o);
        } else {
            desc = (XMLDescriptor) context.getSession(obj).getDescriptor(obj);
        }

        DOMRecord domRecord = null;
        if (!isXMLRoot) {
            domRecord = new DOMRecord(desc.getDefaultRootElement(), desc.getNamespaceResolver());
            domRecord.setDocPresPolicy(getDocumentPreservationPolicy());
        }
        Node n = this.marshaller.objectToXML(obj, node, desc, domRecord, isXMLRoot, this.getDocumentPreservationPolicy());

        validateNode(n);

        DOMResult result = new DOMResult(node);
        XMLTransformer transformer = marshaller.getTransformer();
        if (isXMLRoot) {
            String oldEncoding = transformer.getEncoding();
            String oldVersion = transformer.getVersion();
            if (((Root) obj).getEncoding() != null) {
                transformer.setEncoding(((Root) obj).getEncoding());
            }
            if (((Root) obj).getXMLVersion() != null) {
                transformer.setVersion(((Root) obj).getXMLVersion());
            }
            transformer.transform(n, result);
            if(oldEncoding != null){
                transformer.setEncoding(oldEncoding);
            }
            if(oldVersion != null){
                transformer.setVersion(oldVersion);
            }
        } else {
            transformer.transform(n, result);

        }
    }

    public void updateXML(Object obj, Node associatedNode) {
        if (obj instanceof Root) {
            obj = ((Root)obj).getObject();
        }

        Node objNode = this.getXMLNode(obj);

        AbstractSession session = context.getSession(obj);
        if (objNode == associatedNode) {
            DOMRecord root = new DOMRecord((Element)associatedNode);
            root.setMarshaller(marshaller);
            root.setDocPresPolicy(this.documentPreservationPolicy);
            XMLDescriptor rootDescriptor = (XMLDescriptor) session.getDescriptor(obj);
            ((XMLObjectBuilder)rootDescriptor.getObjectBuilder()).buildIntoNestedRow(root, obj, session);
        }
    }

    /**
     * Gets the XML Node associated with the provided object.
     * @param object
     * @return an XML Node used to construct the given object. Null if no node exists for this object.
     */
    public Node getXMLNode(Object object) {
        return documentPreservationPolicy.getNodeForObject(object);
    }

    /**
     * Gets the Java Object associated with the provided XML Node.
     * @param node
     * @return the Java Object associated with this node. If no object is associated then returns null
     */
    public Object getObject(Node node) {
        return documentPreservationPolicy.getObjectForNode(node);
    }

    /**
     * Updates the object associated with the provided node to reflect any changed made to that node.
     * If this Binder has no object associated with the given node, then no operation is performed.
     * @param node
     */
    public void updateObject(org.w3c.dom.Node node) {
        if (node.getNodeType() == Node.DOCUMENT_NODE) {
            node = ((Document) node).getDocumentElement();
        }

        Object cachedObject = documentPreservationPolicy.getObjectForNode(node);
        if (cachedObject != null) {
            unmarshal(node);
        } else {
            throw XMLMarshalException.objectNotFoundInCache(node.getNodeName());
        }
    }

    /**
     * Gets this XMLBinder's document preservation policy.
     * @return an instance of DocumentPreservationPolicy
     * @see org.eclipse.persistence.oxm.documentpreservation.DocumentPreservationPolicy
     */
    public DocumentPreservationPolicy getDocumentPreservationPolicy() {
        return documentPreservationPolicy;
    }

    public XMLMarshaller getMarshaller() {
        return marshaller;
    }

    public void setMarshaller(XMLMarshaller marshaller) {
        this.marshaller = marshaller;
    }

    public void setSchema(Schema aSchema) {
        this.unmarshaller.setSchema(aSchema);
        this.saxUnmarshaller.setSchema(aSchema);
    }

    public Schema getSchema() {
        return this.unmarshaller.getSchema();
    }

    public void setErrorHandler(ErrorHandler errorHandler) {
        this.unmarshaller.setErrorHandler(errorHandler);
        this.saxUnmarshaller.setErrorHandler(errorHandler);
    }

    public ErrorHandler getErrorHandler() {
        return this.unmarshaller.getErrorHandler();
    }

    /**
     * Create an XMLRoot instance.  If the object is an instance of XMLRoot
     * it will simply be returned.  Otherwise, we will create a new XMLRoot
     * using the object's descriptor default root element - any prefixes
     * will be resolved - and the given object
     *
     * @param obj
     * @return an XMLRoot instance encapsulating the given object
     */
    private XMLRoot buildXMLRootFromObject(Object obj) {
        if (obj instanceof XMLRoot) {
            return (XMLRoot) obj;
        }
        XMLRoot xmlRoot = new XMLRoot();
        xmlRoot.setObject(obj);

        // at this point, the default root element of the object being
        // marshalled to == the root element  - here we need to create
        // an XMLRoot instance using information from the returned
        // object
        org.eclipse.persistence.sessions.Session sess = this.unmarshaller.getXMLContext().getSession(obj);
        XMLDescriptor desc = (XMLDescriptor) sess.getClassDescriptor(obj);

        // here we are assuming that if we've gotten this far, there
        // must be a default root element set on the descriptor.  if
        // this is incorrect, we need to check for null and throw an
        // exception
        String rootName = desc.getDefaultRootElement();
        if (rootName == null) {
            return xmlRoot;
        }
        String rootNamespaceUri = null;
        int idx = rootName.indexOf(':');
        if (idx != -1) {
            rootNamespaceUri = desc.getNamespaceResolver().resolveNamespacePrefix(rootName.substring(0, idx));
            rootName = rootName.substring(idx + 1);
        }
        xmlRoot.setLocalName(rootName);
        xmlRoot.setNamespaceURI(rootNamespaceUri);
        return xmlRoot;
    }
}
