/*******************************************************************************
 * Copyright (c) 1998, 2013 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 v1.0 and Eclipse Distribution License v. 1.0 
 * which accompanies this distribution. 
 * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
 * and the Eclipse Distribution License is available at 
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * Contributors:
 *     Oracle - initial API and implementation from Oracle TopLink
 ******************************************************************************/
package org.eclipse.persistence.internal.oxm.record;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.Map;

import javax.xml.namespace.QName;
import javax.xml.transform.Source;
import javax.xml.validation.Schema;

import org.eclipse.persistence.exceptions.XMLMarshalException;
import org.eclipse.persistence.internal.core.helper.CoreClassConstants;
import org.eclipse.persistence.internal.core.sessions.CoreAbstractSession;
import org.eclipse.persistence.internal.oxm.Constants;
import org.eclipse.persistence.internal.oxm.Root;
import org.eclipse.persistence.internal.oxm.XMLConversionManager;
import org.eclipse.persistence.internal.oxm.XMLObjectBuilder;
import org.eclipse.persistence.internal.oxm.XPathFragment;
import org.eclipse.persistence.internal.oxm.mappings.Descriptor;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.oxm.XMLContext;
import org.eclipse.persistence.oxm.XMLRoot;
import org.eclipse.persistence.oxm.XMLUnmarshaller;
import org.eclipse.persistence.oxm.record.DOMRecord;
import org.eclipse.persistence.platform.xml.SAXDocumentBuilder;
import org.eclipse.persistence.platform.xml.XMLParser;
import org.eclipse.persistence.platform.xml.XMLPlatformException;
import org.eclipse.persistence.platform.xml.XMLPlatformFactory;
import org.eclipse.persistence.queries.ReadObjectQuery;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.Text;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;

/**
 * INTERNAL:
 * <p><b>Purpose:</b>Provide an implementation of PlatformUnmarshaller that makes use of the DOM
 * unmarshal code. Used by the DOMPlatform
 * <p><b>Responsibilities:</b><ul>
 * <li>Implement the required unmarshal methods from platform unmarshaller</li>
 * <li>Perform xml-to-object conversions</li>
 * </ul>
 * @author bdoughan
 * @see org.eclipse.persistence.oxm.platform.DOMPlatform
 *
 */
public class DOMUnmarshaller implements PlatformUnmarshaller {
    private XMLParser parser;
    private XMLUnmarshaller xmlUnmarshaller;
    private boolean isResultAlwaysXMLRoot;

    public DOMUnmarshaller(XMLUnmarshaller xmlUnmarshaller, Map<String, Boolean> parserFeatures) {
        super();
        if(null == parserFeatures) {
            parser = XMLPlatformFactory.getInstance().getXMLPlatform().newXMLParser();
        } else {
            parser = XMLPlatformFactory.getInstance().getXMLPlatform().newXMLParser(parserFeatures);
        }
        parser.setNamespaceAware(true);
        parser.setValidationMode(XMLParser.NONVALIDATING);
        this.xmlUnmarshaller = xmlUnmarshaller;
    }

    public EntityResolver getEntityResolver() {
        return parser.getEntityResolver();
    }

    public void setEntityResolver(EntityResolver entityResolver) {
        parser.setEntityResolver(entityResolver);
    }

    public ErrorHandler getErrorHandler() {
        return parser.getErrorHandler();
    }

    public void setErrorHandler(ErrorHandler errorHandler) {
        parser.setErrorHandler(errorHandler);
    }

    public int getValidationMode() {
        return parser.getValidationMode();
    }

    public void setValidationMode(int validationMode) {
        parser.setValidationMode(validationMode);
    }

    public void setWhitespacePreserving(boolean isWhitespacePreserving) {
        parser.setWhitespacePreserving(isWhitespacePreserving);
    }

    public void setSchemas(Object[] schemas) {
        try {
            parser.setXMLSchemas(schemas);
        } catch (XMLPlatformException e) {
            throw XMLMarshalException.errorSettingSchemas(e, schemas);
        }
    }
    
    public void setSchema(Schema schema) {
        parser.setXMLSchema(schema);
    }
    
    public Schema getSchema() {
        Schema schema = null;
        try {
            schema = parser.getXMLSchema();
        } catch(UnsupportedOperationException ex) {
            //if this parser doesn't support this API, just return null for the schema
        }
        return schema;
    }

    public Object unmarshal(File file) {
    	if(!xmlUnmarshaller.getMediaType().isApplicationXML()){
    		throw XMLMarshalException.unsupportedMediaTypeForPlatform();
    	}
        try {
            Document document = null;
            document = parser.parse(file);
            return xmlToObject(new DOMRecord(document));
        } catch (XMLPlatformException e) {
            throw XMLMarshalException.unmarshalException(e);
        } finally {
        	xmlUnmarshaller.getStringBuffer().reset();
        }
    }

    public Object unmarshal(File file, Class clazz) {
    	if(!xmlUnmarshaller.getMediaType().isApplicationXML()){
    		throw XMLMarshalException.unsupportedMediaTypeForPlatform();
    	}
        try {
            Document document = null;
            document = parser.parse(file);
            return xmlToObject(new DOMRecord(document), clazz);
        } catch (XMLPlatformException e) {
            throw XMLMarshalException.unmarshalException(e);
        } finally {
        	xmlUnmarshaller.getStringBuffer().reset();
        }
    }

    public Object unmarshal(InputStream inputStream) {
    	if(!xmlUnmarshaller.getMediaType().isApplicationXML()){
    		throw XMLMarshalException.unsupportedMediaTypeForPlatform();
    	}
        try {
            Document document = null;
            document = parser.parse(inputStream);
            return xmlToObject(new DOMRecord(document));
        } catch (XMLPlatformException e) {
            throw XMLMarshalException.unmarshalException(e);
        } finally {
        	xmlUnmarshaller.getStringBuffer().reset();
        }
    }

    public Object unmarshal(InputStream inputStream, Class clazz) {
    	if(!xmlUnmarshaller.getMediaType().isApplicationXML()){
    		throw XMLMarshalException.unsupportedMediaTypeForPlatform();
    	}
        try {
            Document document = null;
            document = parser.parse(inputStream);
            return xmlToObject(new DOMRecord(document), clazz);
        } catch (XMLPlatformException e) {
            throw XMLMarshalException.unmarshalException(e);
        } finally {
        	xmlUnmarshaller.getStringBuffer().reset();
        }
    }

    public Object unmarshal(InputSource inputSource) {
    	if(!xmlUnmarshaller.getMediaType().isApplicationXML()){
    		throw XMLMarshalException.unsupportedMediaTypeForPlatform();
    	}
        try {
            Document document = null;
            document = parser.parse(inputSource);
            return xmlToObject(new DOMRecord(document));
        } catch (XMLPlatformException e) {
            throw XMLMarshalException.unmarshalException(e);
        } finally {
        	xmlUnmarshaller.getStringBuffer().reset();
        }
    }

    public Object unmarshal(InputSource inputSource, Class clazz) {
    	if(!xmlUnmarshaller.getMediaType().isApplicationXML()){
    		throw XMLMarshalException.unsupportedMediaTypeForPlatform();
    	}
        try {
            Document document = null;
            document = parser.parse(inputSource);
            return xmlToObject(new DOMRecord(document), clazz);
        } catch (XMLPlatformException e) {
            throw XMLMarshalException.unmarshalException(e);
        } finally {
        	xmlUnmarshaller.getStringBuffer().reset();
        }
    }

    public Object unmarshal(Node node) {
    	if(!xmlUnmarshaller.getMediaType().isApplicationXML()){
    		throw XMLMarshalException.unsupportedMediaTypeForPlatform();
    	}
        Element element = null;
        switch (node.getNodeType()) {
        case Node.DOCUMENT_NODE: {
            element = ((Document) node).getDocumentElement();
            break;
        }
        case Node.ELEMENT_NODE: {
            element = (Element) node;
            break;
        }
        default:
            throw XMLMarshalException.unmarshalException();
        }
        return xmlToObject(new DOMRecord(element));
    }

    public Object unmarshal(Node node, Class clazz) {
    	if(!xmlUnmarshaller.getMediaType().isApplicationXML()){
    		throw XMLMarshalException.unsupportedMediaTypeForPlatform();
    	}
        Element element = null;
        switch (node.getNodeType()) {
        case Node.DOCUMENT_NODE: {
            element = ((Document) node).getDocumentElement();
            break;
        }
        case Node.ELEMENT_NODE: {
            element = (Element) node;
            break;
        }
        default:
            throw XMLMarshalException.unmarshalException();
        }
        return xmlToObject(new DOMRecord(element), clazz);
    }

    public Object unmarshal(Reader reader) {
    	if(!xmlUnmarshaller.getMediaType().isApplicationXML()){
    		throw XMLMarshalException.unsupportedMediaTypeForPlatform();
    	}
        try {
            Document document = null;
            document = parser.parse(reader);
            return xmlToObject(new DOMRecord(document));
        } catch (XMLPlatformException e) {
            throw XMLMarshalException.unmarshalException(e);
        } finally {
        	xmlUnmarshaller.getStringBuffer().reset();
        }
    }

    public Object unmarshal(Reader reader, Class clazz) {
    	if(!xmlUnmarshaller.getMediaType().isApplicationXML()){
    		throw XMLMarshalException.unsupportedMediaTypeForPlatform();
    	}
        try {
            Document document = null;
            document = parser.parse(reader);
            return xmlToObject(new DOMRecord(document), clazz);
        } catch (XMLPlatformException e) {
            throw XMLMarshalException.unmarshalException(e);
        } finally {
        	xmlUnmarshaller.getStringBuffer().reset();
        }
    }

    public Object unmarshal(Source source) {
    	if(!xmlUnmarshaller.getMediaType().isApplicationXML()){
    		throw XMLMarshalException.unsupportedMediaTypeForPlatform();
    	}
        try {
            Document document = null;
            document = parser.parse(source);
            return xmlToObject(new DOMRecord(document));
        } catch (XMLPlatformException e) {
            throw XMLMarshalException.unmarshalException(e);
        } finally {
        	xmlUnmarshaller.getStringBuffer().reset();
        }
    }

    public Object unmarshal(Source source, Class clazz) {
    	if(!xmlUnmarshaller.getMediaType().isApplicationXML()){
    		throw XMLMarshalException.unsupportedMediaTypeForPlatform();
    	}
        try {
            Document document = null;
            document = parser.parse(source);
            return xmlToObject(new DOMRecord(document), clazz);
        } catch (XMLPlatformException e) {
            throw XMLMarshalException.unmarshalException(e);
        } finally {
        	xmlUnmarshaller.getStringBuffer().reset();
        }
    }

    public Object unmarshal(URL url) {
    	if(!xmlUnmarshaller.getMediaType().isApplicationXML()){
    		throw XMLMarshalException.unsupportedMediaTypeForPlatform();
    	}
        try {
            Document document = null;
            document = parser.parse(url);
            return xmlToObject(new DOMRecord(document));
        } catch (XMLPlatformException e) {
            throw XMLMarshalException.unmarshalException(e);
        } finally {
        	xmlUnmarshaller.getStringBuffer().reset();
        }
    }

    public Object unmarshal(URL url, Class clazz) {
    	if(!xmlUnmarshaller.getMediaType().isApplicationXML()){
    		throw XMLMarshalException.unsupportedMediaTypeForPlatform();
    	}
        try {
            Document document = null;
            document = parser.parse(url);
            return xmlToObject(new DOMRecord(document), clazz);
        } catch (XMLPlatformException e) {
            throw XMLMarshalException.unmarshalException(e);
        } finally {
        	xmlUnmarshaller.getStringBuffer().reset();
        }
    }

    public Object unmarshal(XMLReader xmlReader, InputSource inputSource) {
    	if(!xmlUnmarshaller.getMediaType().isApplicationXML()){
    		throw XMLMarshalException.unsupportedMediaTypeForPlatform();
    	}
        try {
            SAXDocumentBuilder saxDocumentBuilder = new SAXDocumentBuilder();
            xmlReader.setContentHandler(saxDocumentBuilder);
            xmlReader.parse(inputSource);
            return xmlToObject(new DOMRecord(saxDocumentBuilder.getDocument()));
        } catch(IOException e) {
            throw XMLMarshalException.unmarshalException(e);
        } catch(SAXException e) {
            throw XMLMarshalException.unmarshalException(e);
        } finally {
        	xmlUnmarshaller.getStringBuffer().reset();
        }
    }

    public Object unmarshal(XMLReader xmlReader, InputSource inputSource, Class clazz) {
    	if(!xmlUnmarshaller.getMediaType().isApplicationXML()){
    		throw XMLMarshalException.unsupportedMediaTypeForPlatform();
    	}
        try {
            SAXDocumentBuilder saxDocumentBuilder = new SAXDocumentBuilder();
            xmlReader.setContentHandler(saxDocumentBuilder);
            xmlReader.parse(inputSource);
            return xmlToObject(new DOMRecord(saxDocumentBuilder.getDocument()), clazz);
        } catch(IOException e) {
            throw XMLMarshalException.unmarshalException(e);
        } catch(SAXException e) {
            throw XMLMarshalException.unmarshalException(e);
        } finally {
        	xmlUnmarshaller.getStringBuffer().reset();
        }
    }

    /**
     * INTERNAL: Find the Descriptor corresponding to the context node of the
     * XMLRecord, and then convert the XMLRecord to an instance of the
     * corresponding object.
     * 
     * @param xmlRecord
     *            The XMLRecord to unmarshal from
     * @return the object which resulted from unmarshalling the given XMLRecord
     * @throws XMLMarshalException
     *             if an error occurred during unmarshalling
     */
    public Object xmlToObject(DOMRecord xmlRecord) throws XMLMarshalException {   
    	 return xmlToObject(xmlRecord, null);
    }

    /**
     * INTERNAL: Convert the Oracle XMLDocument to the reference-class.
     */
    public Object xmlToObject(DOMRecord xmlRow, Class referenceClass) throws XMLMarshalException {
    	try{
	        //Try to get the Encoding and Version from DOM3 APIs if available
	        String xmlEncoding = "UTF-8";
	        String xmlVersion = "1.0";
	
	        try {
	            Method getEncoding = PrivilegedAccessHelper.getMethod(xmlRow.getDocument().getClass(), "getXmlEncoding", new Class[] {}, true);
	            Method getVersion = PrivilegedAccessHelper.getMethod(xmlRow.getDocument().getClass(), "getXmlVersion", new Class[] {}, true);
	            xmlEncoding = (String) PrivilegedAccessHelper.invokeMethod(getEncoding, xmlRow.getDocument(), new Object[] {});
	            xmlVersion = (String) PrivilegedAccessHelper.invokeMethod(getVersion, xmlRow.getDocument(), new Object[] {});
	        } catch (Exception ex) {
	            //if the methods aren't available, then just use the default values
	        }
	
	        XMLContext xmlContext = xmlUnmarshaller.getXMLContext();
	
	        // handle case where the reference class is a primitive wrapper - in
	        // this case, we need to use the conversion manager to convert the 
	        // node's value to the primitive wrapper class, then create, 
	        // populate and return an XMLRoot
	        if (referenceClass != null && (XMLConversionManager.getDefaultJavaTypes().get(referenceClass) != null ||CoreClassConstants.XML_GREGORIAN_CALENDAR.isAssignableFrom(referenceClass)
	        	    ||CoreClassConstants.DURATION.isAssignableFrom(referenceClass))){
	            // we're assuming that since we're unmarshalling to a primitive
	            // wrapper, the root element has a single text node
	            Object nodeVal;
	            try {
	                Text rootTxt = (Text) xmlRow.getDOM().getFirstChild();
	                nodeVal = rootTxt.getNodeValue();
	            } catch (Exception ex) {
	                // here, either the root element doesn't have a text node as a
	                // first child, or there is no first child at all - in any case,
	                // try converting null
	                nodeVal = null;
	            }
	  
	            Object obj = ((XMLConversionManager) xmlContext.getSession().getDatasourcePlatform().getConversionManager()).convertObject(nodeVal, referenceClass);
	            Root xmlRoot = new XMLRoot();
	            xmlRoot.setObject(obj);
	            String lName = xmlRow.getDOM().getLocalName();
	            if (lName == null) {
	                lName = xmlRow.getDOM().getNodeName();
	            }
	            xmlRoot.setLocalName(lName);
	            xmlRoot.setNamespaceURI(xmlRow.getDOM().getNamespaceURI());
	            xmlRoot.setEncoding(xmlEncoding);
	            xmlRoot.setVersion(xmlVersion);
	            return xmlRoot;
	        }
            Descriptor descriptor = null;
            CoreAbstractSession readSession = null;
            boolean shouldWrap = true;            
            if(referenceClass == null){
                QName rootQName = new QName(xmlRow.getNamespaceURI(), xmlRow.getLocalName());
                descriptor = xmlContext.getDescriptor(rootQName);   
                if (null == descriptor) {
                    String type = ((Element) xmlRow.getDOM()).getAttributeNS(javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "type");
                    if (null != type) {
     	                XPathFragment typeFragment = new XPathFragment(type);
     	                String namespaceURI = xmlRow.resolveNamespacePrefix(typeFragment.getPrefix());
     	                typeFragment.setNamespaceURI(namespaceURI);
     	                descriptor = xmlContext.getDescriptorByGlobalType(typeFragment);    	               
     	            }
                 }else{
                	 if(null != descriptor.getDefaultRootElementField() && !descriptor.isResultAlwaysXMLRoot() && !xmlUnmarshaller.isResultAlwaysXMLRoot()){
                 	    String descLocalName = descriptor.getDefaultRootElementField().getXPathFragment().getLocalName();
                 	    String localName = xmlRow.getDOM().getLocalName();
                 	    if (localName == null) {
                 		  localName = xmlRow.getDOM().getNodeName();
       	                }
                 	String namespaceURI = xmlRow.getDOM().getNamespaceURI();
                     	if( descLocalName != null && descLocalName.equals(localName) ){
                     	    String descUri = descriptor.getDefaultRootElementField().getXPathFragment().getNamespaceURI();
                         	if((namespaceURI == null && descUri == null ) || (namespaceURI !=null &&namespaceURI.length() == 0 && descUri == null ) || (namespaceURI != null && namespaceURI.equals(descUri))){
                      	       //found a descriptor based on root element then know we won't need to wrap in an XMLRoot
                     	       shouldWrap = false;
                     	    }
                         }
                 	}
                 }          
                
                 if (null == descriptor) {
                     throw XMLMarshalException.noDescriptorWithMatchingRootElement(rootQName.toString());
                 }else{
                     readSession = xmlContext.getSession(descriptor.getJavaClass());
                 }
            } else {
                // for XMLObjectReferenceMappings we need a non-shared cache, so
                // try and get a Unit Of Work from the XMLContext
                readSession = xmlContext.getSession(referenceClass);
                descriptor = (Descriptor)readSession.getDescriptor(referenceClass);
                if (descriptor == null) {
                    throw XMLMarshalException.descriptorNotFoundInProject(referenceClass.getName());
                } 
            }
	    		
	        Object object = null;
	        if(null == xmlRow.getDOM().getAttributes().getNamedItemNS(javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, Constants.SCHEMA_NIL_ATTRIBUTE)) {
	            xmlRow.setUnmarshaller(xmlUnmarshaller);
	            xmlRow.setDocPresPolicy(xmlContext.getDocumentPreservationPolicy((AbstractSession) readSession));
	            XMLObjectBuilder objectBuilder = (XMLObjectBuilder) descriptor.getObjectBuilder();
	
	            ReadObjectQuery query = new ReadObjectQuery();
	            query.setReferenceClass(referenceClass);
	            query.setSession((AbstractSession) readSession);
	            object = objectBuilder.buildObject(query, xmlRow, null);
	
	            // resolve mapping references
	            xmlRow.resolveReferences(readSession, xmlUnmarshaller.getIDResolver());
	        }
	
	        String elementNamespaceUri = xmlRow.getDOM().getNamespaceURI();
	        String elementLocalName = xmlRow.getDOM().getLocalName();
	        if (elementLocalName == null) {
	            elementLocalName = xmlRow.getDOM().getNodeName();
	        }
	        String elementPrefix = xmlRow.getDOM().getPrefix();
	        if(shouldWrap || descriptor.isResultAlwaysXMLRoot() || isResultAlwaysXMLRoot){	        
	            return descriptor.wrapObjectInXMLRoot(object, elementNamespaceUri, elementLocalName, elementPrefix, xmlEncoding, xmlVersion, this.isResultAlwaysXMLRoot, true, xmlUnmarshaller);
	        }else{
	        	return object;
	        }
    	}finally{    		
            xmlUnmarshaller.getStringBuffer().reset();           
    	}
    }

    public boolean isResultAlwaysXMLRoot() {
        return this.isResultAlwaysXMLRoot;
    }

    public void setResultAlwaysXMLRoot(boolean alwaysReturnRoot) {
        this.isResultAlwaysXMLRoot = alwaysReturnRoot;
    }

    @Override
    public void mediaTypeChanged() {
       //do nothing
    }
}
