/*
 * 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.testing.jaxb;

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.Type;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import jakarta.xml.bind.JAXBContext;
import jakarta.xml.bind.JAXBElement;
import jakarta.xml.bind.JAXBException;
import jakarta.xml.bind.Marshaller;
import jakarta.xml.bind.SchemaOutputResolver;
import jakarta.xml.bind.Unmarshaller;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;

import org.eclipse.persistence.internal.oxm.record.XMLStreamReaderInputSource;
import org.eclipse.persistence.internal.oxm.record.XMLStreamReaderReader;
import org.eclipse.persistence.jaxb.JAXBContextFactory;
import org.eclipse.persistence.jaxb.JAXBUnmarshaller;
import org.eclipse.persistence.jaxb.JAXBUnmarshallerHandler;
import org.eclipse.persistence.jaxb.MarshallerProperties;
import org.eclipse.persistence.jaxb.UnmarshallerProperties;
import org.eclipse.persistence.jaxb.compiler.CompilerHelper;
import org.eclipse.persistence.jaxb.xmlmodel.XmlBindings;
import org.eclipse.persistence.oxm.MediaType;
import org.eclipse.persistence.oxm.XMLContext;
import org.eclipse.persistence.oxm.XMLDescriptor;
import org.eclipse.persistence.oxm.XMLRoot;
import org.eclipse.persistence.oxm.record.XMLStreamWriterRecord;
import org.eclipse.persistence.platform.xml.SAXDocumentBuilder;
import org.eclipse.persistence.platform.xml.XMLPlatformFactory;
import org.eclipse.persistence.sessions.Project;
import org.eclipse.persistence.testing.oxm.mappings.XMLMappingTestCases;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.ls.LSInput;
import org.w3c.dom.ls.LSResourceResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;

public abstract class JAXBTestCases extends XMLMappingTestCases {

    public static final String ECLIPSELINK_OXM_XSD = "eclipselink_oxm_2_6.xsd";
    protected JAXBContext jaxbContext;
    protected Marshaller jaxbMarshaller;
    protected Unmarshaller jaxbUnmarshaller;
    protected Class[] classes;
    protected Type[] types;
    protected String contextPath;

    protected ClassLoader classLoader;
    protected Source bindingsFileXSDSource;

    public JAXBTestCases(String name) throws Exception {
        super(name);
    }

    @Override
    public XMLContext getXMLContext(Project project) {
        return new XMLContext(project, classLoader);
    }

    @Override
    public void setUp() throws Exception {
        setupParser();
        setupControlDocs();

        InputStream bindingsFileXSDInputStream = getClass().getClassLoader().getResourceAsStream(ECLIPSELINK_OXM_XSD);
        if(bindingsFileXSDInputStream == null){
            bindingsFileXSDInputStream = getClass().getClassLoader().getResourceAsStream("org/eclipse/persistence/jaxb/" + ECLIPSELINK_OXM_XSD);
        }
        if(bindingsFileXSDInputStream == null){
            fail("ERROR LOADING " + ECLIPSELINK_OXM_XSD);
        }
        bindingsFileXSDSource = new StreamSource(bindingsFileXSDInputStream);
    }

    @Override
    public void tearDown() {
        super.tearDown();
        jaxbContext = null;
        jaxbMarshaller = null;
        jaxbUnmarshaller = null;
        classLoader = null;
        bindingsFileXSDSource = null;
    }

    @Override
    protected void setProject(Project project) {
        this.project = project;
    }

    public void setClasses(Class[] newClasses) throws Exception {

        classLoader = Thread.currentThread().getContextClassLoader();
        jaxbContext = JAXBContextFactory.createContext(newClasses, getProperties(), classLoader);
        classes = newClasses;

        xmlContext = ((org.eclipse.persistence.jaxb.JAXBContext)jaxbContext).getXMLContext();
        setProject(xmlContext.getSession(0).getProject());
        jaxbMarshaller = jaxbContext.createMarshaller();
        jaxbUnmarshaller = jaxbContext.createUnmarshaller();

    }

    public void setContextPath(String contextPath) throws Exception {
         classLoader = Thread.currentThread().getContextClassLoader();
         this.contextPath = contextPath;
         Map props = getProperties();
         if(props != null){
             Map overrides = (Map) props.get(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY);
             if(overrides != null){
                 Iterator valuesIter = overrides.values().iterator();
                 while(valuesIter.hasNext()){
                     Object next = valuesIter.next();
                     validateBindingsFileAgainstSchema(next);
                 }
             }
         }
         jaxbContext = JAXBContextFactory.createContext(contextPath, classLoader, getProperties());

         xmlContext = ((org.eclipse.persistence.jaxb.JAXBContext)jaxbContext).getXMLContext();
         setProject(xmlContext.getSession(0).getProject());
         jaxbMarshaller = jaxbContext.createMarshaller();
         jaxbUnmarshaller = jaxbContext.createUnmarshaller();
    }


    public void setTypes(Type[] newTypes) throws Exception {

        types = newTypes;
        classLoader = Thread.currentThread().getContextClassLoader();

        Map props = getProperties();
        if(props != null){
            Map overrides = (Map) props.get(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY);
            if(overrides != null){
                Iterator valuesIter = overrides.values().iterator();
                while(valuesIter.hasNext()){
                    Object next = valuesIter.next();
                    validateBindingsFileAgainstSchema(next);
                }
            }
        }

        jaxbContext = JAXBContextFactory.createContext(newTypes, getProperties(), classLoader);

        xmlContext = ((org.eclipse.persistence.jaxb.JAXBContext)jaxbContext).getXMLContext();
        setProject(xmlContext.getSession(0).getProject());
        jaxbMarshaller = jaxbContext.createMarshaller();
        jaxbUnmarshaller = jaxbContext.createUnmarshaller();
    }

    protected Map getProperties() throws JAXBException{
        return null;
    }

    private Map getPropertiesFromJSON() throws JAXBException{
        Map props = new HashMap(getProperties());

        if(props !=null){

            Object bindingFilesObject = props.get(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY);
            if(bindingFilesObject != null){
                JAXBContext jaxbContext = CompilerHelper.getXmlBindingsModelContext();
                //unmarshal XML
                Unmarshaller u =jaxbContext.createUnmarshaller();
                Marshaller jsonMarshaller = jaxbContext.createMarshaller();
                //Marshal bindings to JSON (with no root)
                jsonMarshaller.setProperty(MarshallerProperties.MEDIA_TYPE, "application/json");
                jsonMarshaller.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, false);
                if(bindingFilesObject instanceof Map){
                    Map<String, Object> bindingFiles = (Map<String, Object>) bindingFilesObject;

                    Iterator<String> keyIter = bindingFiles.keySet().iterator();
                    while(keyIter.hasNext()){
                        String nextKey = keyIter.next();
                        Object nextBindings = bindingFiles.get(nextKey);;
                        if(nextBindings instanceof List){
                            List nextList = (List) bindingFiles.get(nextKey);
                            for(int i=0;i< nextList.size();i++){
                                Object o = nextList.get(i);
                                if(o instanceof Source){
                                    Source nextSource = (Source)o;
                                    if(nextSource instanceof StreamSource){
                                        StreamSource ss= (StreamSource)nextSource;
                                        StreamSource ss2= new StreamSource(ss.getInputStream());
                                        Object unmarshalledFromXML = u.unmarshal(ss2);
                                        StringWriter sw = new StringWriter();
                                        StreamResult newResult = new StreamResult(sw);
                                        jsonMarshaller.marshal(unmarshalledFromXML, newResult);
                                        StreamSource newSource = new StreamSource(new StringReader(sw.toString()));
                                        nextList.set(i, newSource);
                                    }
                                }
                            }
                        }else if(nextBindings instanceof Source){
                            Object unmarshalledFromXML = u.unmarshal((Source)nextBindings);

                            StringWriter sw = new StringWriter();
                            StreamResult newResult = new StreamResult(sw);
                            jsonMarshaller.marshal(unmarshalledFromXML, newResult);
                            StreamSource newSource = new StreamSource(new StringReader(sw.toString()));
                            bindingFiles.put(nextKey, newSource);
                        }
                    }
                }else if(bindingFilesObject instanceof List){
                    List bindingFilesList = (List) bindingFilesObject;
                    for(int i=0; i<bindingFilesList.size(); i++){
                        Object next = bindingFilesList.get(i);
                        Object unmarshalledFromXML = getXmlBindings(next);
                        StringWriter sw = new StringWriter();
                        StreamResult newResult = new StreamResult(sw);
                        jsonMarshaller.marshal(unmarshalledFromXML, newResult);
                        StreamSource newSource = new StreamSource(new StringReader(sw.toString()));
                        bindingFilesList.set(i, newSource);
                    }
                    props.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, bindingFilesList);
                }else{
                    Object unmarshalledFromXML = getXmlBindings(bindingFilesObject);
                    StringWriter sw = new StringWriter();
                    StreamResult newResult = new StreamResult(sw);
                    jsonMarshaller.marshal(unmarshalledFromXML, newResult);
                    StreamSource newSource = new StreamSource(new StringReader(sw.toString()));
                    props.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, newSource);

                }

            }
        }
        return props;

    }

    private static XmlBindings getXmlBindings(Object metadata) {
        XmlBindings xmlBindings = null;
        Unmarshaller unmarshaller;
        // only create the JAXBContext for our XmlModel once
        JAXBContext jaxbContext = CompilerHelper.getXmlBindingsModelContext();
        try {
            unmarshaller = jaxbContext.createUnmarshaller();
            if (metadata instanceof File) {
                xmlBindings = (XmlBindings) unmarshaller.unmarshal((File) metadata);
            } else if (metadata instanceof InputSource) {
                xmlBindings = (XmlBindings) unmarshaller.unmarshal((InputSource) metadata);
            } else if (metadata instanceof BufferedInputStream) {
                   xmlBindings = (XmlBindings) unmarshaller.unmarshal((BufferedInputStream) metadata);
            } else if (metadata instanceof InputStream) {
                xmlBindings = (XmlBindings) unmarshaller.unmarshal((InputStream) metadata);
            } else if (metadata instanceof Node) {
                xmlBindings = (XmlBindings) unmarshaller.unmarshal((Node) metadata);
            } else if (metadata instanceof Reader) {
                xmlBindings = (XmlBindings) unmarshaller.unmarshal((Reader) metadata);
            } else if (metadata instanceof Source) {
                xmlBindings = (XmlBindings) unmarshaller.unmarshal((Source) metadata);
            } else if (metadata instanceof URL) {
                xmlBindings = (XmlBindings) unmarshaller.unmarshal((URL) metadata);
            } else if (metadata instanceof XMLEventReader) {
                xmlBindings = (XmlBindings) unmarshaller.unmarshal((XMLEventReader) metadata);
            } else if (metadata instanceof XMLStreamReader) {
                xmlBindings = (XmlBindings) unmarshaller.unmarshal((XMLStreamReader) metadata);
            } else if (metadata instanceof String) {
                if(((String)metadata).length() == 0) {
                    throw org.eclipse.persistence.exceptions.JAXBException.unableToLoadMetadataFromLocation((String)metadata);
                }
                URL url = null;
                try {
                    url = new URL((String)metadata);
                } catch(MalformedURLException ex) {
                    url = Thread.currentThread().getContextClassLoader().getResource((String)metadata);
                }
                if(url != null) {
                    xmlBindings = (XmlBindings)unmarshaller.unmarshal(url);
                } else {
                    //throw exception
                    throw org.eclipse.persistence.exceptions.JAXBException.unableToLoadMetadataFromLocation((String)metadata);
                }
            } else {
                throw org.eclipse.persistence.exceptions.JAXBException.incorrectValueParameterTypeForOxmXmlKey();
            }
        } catch (JAXBException jaxbEx) {
            throw org.eclipse.persistence.exceptions.JAXBException.couldNotUnmarshalMetadata(jaxbEx);
        }
        return xmlBindings;
    }




    public JAXBContext getJAXBContext() {
        return jaxbContext;
    }

    public Marshaller getJAXBMarshaller() {
        return jaxbMarshaller;
    }

    public Unmarshaller getJAXBUnmarshaller() {
        return jaxbUnmarshaller;
    }

    public Class getUnmarshalClass(){
        return null;
    }

    @Override
    public void testXMLToObjectFromInputStream() throws Exception {

        if(isUnmarshalTest()) {
            InputStream instream = ClassLoader.getSystemResourceAsStream(resourceName);
            jaxbUnmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, getXMLUnmarshalMediaType());
            Object testObject = null;
            if(getUnmarshalClass() != null){
               testObject = jaxbUnmarshaller.unmarshal(new StreamSource(instream), getUnmarshalClass());
            }else{
               testObject = jaxbUnmarshaller.unmarshal(instream);
            }

            instream.close();
            xmlToObjectTest(testObject);

            if(getProperties() != null){
                JAXBContext jaxbContextFromJSONBindings = createJaxbContextFromJSONBindings();
                   Unmarshaller jaxbUnmarshallerFromJSONBindings = jaxbContextFromJSONBindings.createUnmarshaller();
                   jaxbUnmarshallerFromJSONBindings.setAttachmentUnmarshaller(jaxbUnmarshaller.getAttachmentUnmarshaller());
                   jaxbUnmarshallerFromJSONBindings.setProperty(UnmarshallerProperties.OBJECT_GRAPH, jaxbUnmarshaller.getProperty(UnmarshallerProperties.OBJECT_GRAPH));
                   jaxbUnmarshallerFromJSONBindings.setProperty(UnmarshallerProperties.JSON_NAMESPACE_PREFIX_MAPPER, jaxbMarshaller.getProperty(UnmarshallerProperties.JSON_NAMESPACE_PREFIX_MAPPER));
                Object testObject2 = null;
                    log("************test with JSON bindings*********");
                    InputStream instream2 = ClassLoader.getSystemResourceAsStream(resourceName);
                    if(getUnmarshalClass() != null){
                     testObject2 = jaxbUnmarshallerFromJSONBindings.unmarshal(new StreamSource(instream2), getUnmarshalClass());
                 }else{
                     testObject2 = jaxbUnmarshallerFromJSONBindings.unmarshal(instream2);
                 }
                 instream2.close();
                 xmlToObjectTest(testObject2);
            }
        }
    }

    protected JAXBContext createJaxbContextFromJSONBindings() throws JAXBException{
        if(classes != null){
            return JAXBContextFactory.createContext(classes, getPropertiesFromJSON(), classLoader);
        }else if (types != null){
            return JAXBContextFactory.createContext(types, getPropertiesFromJSON(), classLoader);
        }else if(contextPath != null){
            return JAXBContextFactory.createContext(contextPath, classLoader, getPropertiesFromJSON());
        }
        return null;
    }

    public MediaType getXMLUnmarshalMediaType(){
        return MediaType.APPLICATION_XML;
    }

    public void testRoundTrip() throws Exception{
        if(isUnmarshalTest()) {
            jaxbUnmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, getXMLUnmarshalMediaType());
            InputStream instream = null;
            if(writeControlDocumentLocation !=null){
                instream = ClassLoader.getSystemResourceAsStream(writeControlDocumentLocation);
            }else{
                instream = ClassLoader.getSystemResourceAsStream(resourceName);
            }
            jaxbUnmarshaller.setProperty(MarshallerProperties.MEDIA_TYPE, "application/xml");
            Object testObject = null;
            if(getUnmarshalClass() != null){
                testObject = jaxbUnmarshaller.unmarshal(new StreamSource(instream), getUnmarshalClass());
            }else{
                testObject = jaxbUnmarshaller.unmarshal(instream);
            }

                instream.close();
                xmlToObjectTest(testObject);

                objectToXMLStringWriter(testObject);
        }
    }

    @Override
    public void testObjectToOutputStream() throws Exception {
        Object objectToWrite = getWriteControlObject();
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        XMLDescriptor desc = null;
        if (objectToWrite instanceof XMLRoot) {
            desc = (XMLDescriptor)xmlContext.getSession(0).getProject().getDescriptor(((XMLRoot)objectToWrite).getObject().getClass());
        } else {
            desc = (XMLDescriptor)xmlContext.getSession(0).getProject().getDescriptor(objectToWrite.getClass());
        }

        int sizeBefore = getNamespaceResolverSize(desc);
        jaxbMarshaller.setProperty(MarshallerProperties.MEDIA_TYPE, "application/xml");
        try {
            jaxbMarshaller.marshal(objectToWrite, stream);
        } catch(Exception e) {
            assertMarshalException(e);
            return;
        }
        if(expectsMarshalException){
            fail("An exception should have occurred but didn't.");
            return;
           }

        int sizeAfter = getNamespaceResolverSize(desc);

        assertEquals(sizeBefore, sizeAfter);

        InputStream is = new ByteArrayInputStream(stream.toByteArray());

        Document testDocument = getTestDocument(is);

        stream.close();
        is.close();

        objectToXMLDocumentTest(testDocument);

        if(getProperties() != null){
             log("************test with JSON bindings*********");
             ByteArrayOutputStream stream2 = new ByteArrayOutputStream();
             JAXBContext jaxbContextFromJSONBindings = createJaxbContextFromJSONBindings();
             Marshaller jaxbMarshallerFromJSONBindings = jaxbContextFromJSONBindings.createMarshaller();
             jaxbMarshallerFromJSONBindings.setAttachmentMarshaller(jaxbMarshaller.getAttachmentMarshaller());


              jaxbMarshallerFromJSONBindings.setProperty(MarshallerProperties.NAMESPACE_PREFIX_MAPPER, jaxbMarshaller.getProperty(MarshallerProperties.NAMESPACE_PREFIX_MAPPER));
             jaxbMarshallerFromJSONBindings.setProperty(MarshallerProperties.OBJECT_GRAPH, jaxbMarshaller.getProperty(MarshallerProperties.OBJECT_GRAPH));


             jaxbMarshallerFromJSONBindings.marshal(objectToWrite, stream2);
             InputStream is2 = new ByteArrayInputStream(stream2.toByteArray());
             Document testDocument2 = parser.parse(is2);
             stream2.close();
             is2.close();

             objectToXMLDocumentTest(testDocument2);

        }
    }

    @Override
    public void testObjectToOutputStreamASCIIEncoding() throws Exception {
        Object objectToWrite = getWriteControlObject();
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        XMLDescriptor desc = null;
        if (objectToWrite instanceof XMLRoot) {
            desc = (XMLDescriptor)xmlContext.getSession(0).getProject().getDescriptor(((XMLRoot)objectToWrite).getObject().getClass());
        } else {
            desc = (XMLDescriptor)xmlContext.getSession(0).getProject().getDescriptor(objectToWrite.getClass());
        }
        jaxbMarshaller.setProperty(MarshallerProperties.MEDIA_TYPE, "application/xml");

        int sizeBefore = getNamespaceResolverSize(desc);
        String originalEncoding = (String)jaxbMarshaller.getProperty(Marshaller.JAXB_ENCODING);
        jaxbMarshaller.setProperty(Marshaller.JAXB_ENCODING, "US-ASCII");
        try {
            jaxbMarshaller.marshal(objectToWrite, stream);
        } catch(Exception e) {
            assertMarshalException(e);
            return;
        }
        if(expectsMarshalException){
            fail("An exception should have occurred but didn't.");
            return;
        }

        jaxbMarshaller.setProperty(Marshaller.JAXB_ENCODING, originalEncoding);
        int sizeAfter = getNamespaceResolverSize(desc);

        assertEquals(sizeBefore, sizeAfter);

        InputStream is = new ByteArrayInputStream(stream.toByteArray());
        Document testDocument = getTestDocument(is);

        stream.close();
        is.close();

        objectToXMLDocumentTest(testDocument);
    }

    public Document getTestDocument(InputStream is) throws Exception{
       return parser.parse(is);
    }

    public Document getTestDocument(String s) throws Exception{
        StringReader reader = new StringReader(s);
        InputSource inputSource = new InputSource(reader);
        Document doc = parser.parse(inputSource);
        reader.close();
        return doc;
    }

    @Override
    public void testObjectToXMLStringWriter() throws Exception {
        objectToXMLStringWriter(getWriteControlObject());
    }

    @Override
    public void testValidatingMarshal() {
    }

    public void objectToXMLStringWriter(Object objectToWrite) throws Exception {
        StringWriter writer = new StringWriter();

        XMLDescriptor desc = null;
        if (objectToWrite instanceof XMLRoot) {
            desc = (XMLDescriptor)xmlContext.getSession(0).getProject().getDescriptor(((XMLRoot)objectToWrite).getObject().getClass());
        } else {
            desc = (XMLDescriptor)xmlContext.getSession(0).getProject().getDescriptor(objectToWrite.getClass());
        }

        int sizeBefore = getNamespaceResolverSize(desc);
        jaxbMarshaller.setProperty(MarshallerProperties.MEDIA_TYPE, "application/xml");

        try {
            jaxbMarshaller.marshal(objectToWrite, writer);
        } catch(Exception e) {
            assertMarshalException(e);
            return;
        }
        if(expectsMarshalException){
            fail("An exception should have occurred but didn't.");
            return;
        }

        int sizeAfter = getNamespaceResolverSize(desc);

        assertEquals(sizeBefore, sizeAfter);

        Document testDocument = getTestDocument(writer.toString());

        writer.close();

        objectToXMLDocumentTest(testDocument);
    }

    @Override
    public void testObjectToXMLStreamWriter() throws Exception {
        if(XML_OUTPUT_FACTORY != null) {
            StringWriter writer = new StringWriter();

            XMLOutputFactory factory = XMLOutputFactory.newInstance();
            factory.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, Boolean.valueOf(false));
            XMLStreamWriter streamWriter= factory.createXMLStreamWriter(writer);

            Object objectToWrite = getWriteControlObject();
            XMLDescriptor desc = null;
            if (objectToWrite instanceof XMLRoot) {
                desc = (XMLDescriptor)xmlContext.getSession(0).getProject().getDescriptor(((XMLRoot)objectToWrite).getObject().getClass());
            } else {
                desc = (XMLDescriptor)xmlContext.getSession(0).getProject().getDescriptor(objectToWrite.getClass());
            }
            jaxbMarshaller.setProperty(MarshallerProperties.MEDIA_TYPE, "application/xml");

            int sizeBefore = getNamespaceResolverSize(desc);
            try {
                jaxbMarshaller.marshal(objectToWrite, streamWriter);
            } catch(Exception e) {
                assertMarshalException(e);
                return;
            }
            if(expectsMarshalException){
                fail("An exception should have occurred but didn't.");
                return;
            }

            streamWriter.flush();
            int sizeAfter = getNamespaceResolverSize(desc);

            assertEquals(sizeBefore, sizeAfter);
            Document testDocument = getTestDocument(writer.toString());

            writer.close();
            objectToXMLDocumentTest(testDocument);
        }
    }

    public void testObjectToXMLStreamWriterRecord() throws Exception {
        if(XML_OUTPUT_FACTORY != null) {
            StringWriter writer = new StringWriter();

            XMLOutputFactory factory = XMLOutputFactory.newInstance();
            factory.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, Boolean.valueOf(false));
            XMLStreamWriter streamWriter= factory.createXMLStreamWriter(writer);

            Object objectToWrite = getWriteControlObject();
            XMLDescriptor desc = null;
            if (objectToWrite instanceof XMLRoot) {
                desc = (XMLDescriptor)xmlContext.getSession(0).getProject().getDescriptor(((XMLRoot)objectToWrite).getObject().getClass());
            } else {
                desc = (XMLDescriptor)xmlContext.getSession(0).getProject().getDescriptor(objectToWrite.getClass());
            }
            jaxbMarshaller.setProperty(MarshallerProperties.MEDIA_TYPE, "application/xml");

            int sizeBefore = getNamespaceResolverSize(desc);
            XMLStreamWriterRecord record = new XMLStreamWriterRecord(streamWriter);
            try {
                ((org.eclipse.persistence.jaxb.JAXBMarshaller)jaxbMarshaller).marshal(objectToWrite, record);
            } catch(Exception e) {
                assertMarshalException(e);
                return;
            }
            if(expectsMarshalException){
                fail("An exception should have occurred but didn't.");
                return;
            }

            streamWriter.flush();
            int sizeAfter = getNamespaceResolverSize(desc);

            assertEquals(sizeBefore, sizeAfter);

            Document testDocument = getTestDocument(writer.toString());
            writer.close();
            objectToXMLDocumentTest(testDocument);
        }
    }


    @Override
    public void testObjectToXMLEventWriter() throws Exception {
        if(XML_OUTPUT_FACTORY != null) {
            StringWriter writer = new StringWriter();

            XMLOutputFactory factory = XMLOutputFactory.newInstance();
            factory.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, Boolean.valueOf(false));
            XMLEventWriter eventWriter= factory.createXMLEventWriter(writer);

            Object objectToWrite = getWriteControlObject();
            XMLDescriptor desc = null;
            if (objectToWrite instanceof XMLRoot) {
                desc = (XMLDescriptor)xmlContext.getSession(0).getProject().getDescriptor(((XMLRoot)objectToWrite).getObject().getClass());
            } else {
                desc = (XMLDescriptor)xmlContext.getSession(0).getProject().getDescriptor(objectToWrite.getClass());
            }
            jaxbMarshaller.setProperty(MarshallerProperties.MEDIA_TYPE, "application/xml");

            int sizeBefore = getNamespaceResolverSize(desc);
            try {
                jaxbMarshaller.marshal(objectToWrite, eventWriter);
            } catch(Exception e) {
                assertMarshalException(e);
                return;
            }
            if(expectsMarshalException){
                fail("An exception should have occurred but didn't.");
                return;
            }

            eventWriter.flush();
            int sizeAfter = getNamespaceResolverSize(desc);

            assertEquals(sizeBefore, sizeAfter);
            Document testDocument = getTestDocument(writer.toString());
            writer.close();
            objectToXMLDocumentTest(testDocument);
        }
    }

    @Override
    public void testObjectToContentHandler() throws Exception {
        SAXDocumentBuilder builder = new SAXDocumentBuilder();
        Object objectToWrite = getWriteControlObject();
        XMLDescriptor desc = null;
        if (objectToWrite instanceof XMLRoot) {
            desc = (XMLDescriptor)xmlContext.getSession(0).getProject().getDescriptor(((XMLRoot)objectToWrite).getObject().getClass());
        } else {
            desc = (XMLDescriptor)xmlContext.getSession(0).getProject().getDescriptor(objectToWrite.getClass());
        }
        int sizeBefore = getNamespaceResolverSize(desc);
        jaxbMarshaller.setProperty(MarshallerProperties.MEDIA_TYPE, "application/xml");

        try {
            jaxbMarshaller.marshal(objectToWrite, builder);
        } catch(Exception e) {
            assertMarshalException(e);
            return;
        }
        if(expectsMarshalException){
            fail("An exception should have occurred but didn't.");
            return;
        }

        int sizeAfter = getNamespaceResolverSize(desc);

        assertEquals(sizeBefore, sizeAfter);

        Document controlDocument = getWriteControlDocument();
        Document testDocument = builder.getDocument();

        log("**testObjectToContentHandler**");
        log("Expected:");
        log(controlDocument);
        log("\nActual:");
        log(testDocument);

        //Diff diff = new Diff(controlDocument, testDocument);
        //this.assertXMLEqual(diff, true);
        assertXMLIdentical(controlDocument, testDocument);
    }

    @Override
    public void testXMLToObjectFromURL() throws Exception {
        if(isUnmarshalTest()) {
            java.net.URL url = ClassLoader.getSystemResource(resourceName);
            jaxbUnmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, getXMLUnmarshalMediaType());

            Object testObject = null;
            if(getUnmarshalClass() != null){
               testObject = jaxbUnmarshaller.unmarshal(new StreamSource(url.openStream()), getUnmarshalClass());
            }else{
                testObject = jaxbUnmarshaller.unmarshal(url);
            }
            xmlToObjectTest(testObject);
        }
    }

    @Override
    public void testXMLToObjectFromXMLStreamReader() throws Exception {
        if(null != XML_INPUT_FACTORY && isUnmarshalTest()) {
            InputStream instream = ClassLoader.getSystemResourceAsStream(resourceName);
            XMLStreamReader xmlStreamReader = XML_INPUT_FACTORY.createXMLStreamReader(instream);
            jaxbUnmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, getXMLUnmarshalMediaType());

            Object testObject = null;
            if(getUnmarshalClass() != null){
                testObject = getJAXBUnmarshaller().unmarshal(xmlStreamReader, getUnmarshalClass());
            }else{
                testObject = jaxbUnmarshaller.unmarshal(xmlStreamReader);
            }
            instream.close();
            xmlToObjectTest(testObject);
        }
    }
    @Override
    public void testXMLToObjectFromNode() throws Exception {
        if(isUnmarshalTest()) {
            InputStream instream = ClassLoader.getSystemResourceAsStream(resourceName);
            Node node  = parser.parse(instream);
            jaxbUnmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, getXMLUnmarshalMediaType());
            Object testObject = null;
            if(getUnmarshalClass() != null){
               testObject = jaxbUnmarshaller.unmarshal(node, getUnmarshalClass());
            }else{
                testObject = jaxbUnmarshaller.unmarshal(node);
            }
            instream.close();
            xmlToObjectTest(testObject);
        }
    }


    public void testXMLToObjectFromXMLStreamReaderEx() throws Exception {
        if(null != XML_INPUT_FACTORY && isUnmarshalTest()) {
            InputStream instream = ClassLoader.getSystemResourceAsStream(resourceName);
            XMLStreamReader xmlStreamReader = XML_INPUT_FACTORY.createXMLStreamReader(instream);

            ExtendedXMLStreamReaderReader xmlStreamReaderReaderEx = new ExtendedXMLStreamReaderReader();
            xmlStreamReaderReaderEx.setErrorHandler(((JAXBUnmarshaller) jaxbUnmarshaller).getXMLUnmarshaller().getErrorHandler());
            XMLStreamReaderInputSource xmlStreamReaderInputSource = new XMLStreamReaderInputSource(xmlStreamReader);
            SAXSource saxSource = new SAXSource(xmlStreamReaderReaderEx, xmlStreamReaderInputSource);
            jaxbUnmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, getXMLUnmarshalMediaType());
            Object testObject = null;
            if(getUnmarshalClass() != null){
                 testObject = jaxbUnmarshaller.unmarshal(saxSource, getUnmarshalClass());
            }else{
                 testObject = jaxbUnmarshaller.unmarshal(saxSource);
            }

            instream.close();
            xmlToObjectTest(testObject);
        }
    }

    @Override
    public void testXMLToObjectFromXMLEventReader() throws Exception {
        if(null != XML_INPUT_FACTORY && isUnmarshalTest()) {
            InputStream instream = ClassLoader.getSystemResourceAsStream(resourceName);
            XMLEventReader xmlEventReader = XML_INPUT_FACTORY.createXMLEventReader(instream);
            jaxbUnmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, getXMLUnmarshalMediaType());
            Object testObject = null;
            if(getUnmarshalClass() != null){
               testObject = jaxbUnmarshaller.unmarshal(xmlEventReader, getUnmarshalClass());
            }else{
                testObject = jaxbUnmarshaller.unmarshal(xmlEventReader);
            }
            instream.close();
            xmlToObjectTest(testObject);
        }
    }

    @Override
    public void testObjectToXMLDocument() throws Exception {
        Object objectToWrite = getWriteControlObject();
        XMLDescriptor desc = null;
        if (objectToWrite instanceof XMLRoot) {
            desc = (XMLDescriptor)xmlContext.getSession(0).getProject().getDescriptor(((XMLRoot)objectToWrite).getObject().getClass());
        } else {
            desc = (XMLDescriptor)xmlContext.getSession(0).getProject().getDescriptor(objectToWrite.getClass());
        }
        jaxbMarshaller.setProperty(MarshallerProperties.MEDIA_TYPE, "application/xml");

        int sizeBefore = getNamespaceResolverSize(desc);
        Document testDocument = XMLPlatformFactory.getInstance().getXMLPlatform().createDocument();
        try {
            jaxbMarshaller.marshal(objectToWrite, testDocument);
        } catch(Exception e) {
            assertMarshalException(e);
            return;
        }
        if(expectsMarshalException){
            fail("An exception should have occurred but didn't.");
            return;
        }

        int sizeAfter = getNamespaceResolverSize(desc);
        assertEquals(sizeBefore, sizeAfter);
        objectToXMLDocumentTest(testDocument);
    }


    @Override
    public void xmlToObjectTest(Object testObject) throws Exception {
        xmlToObjectTest(testObject, getReadControlObject());
    }

    public void xmlToObjectTest(Object testObject, Object controlObject) throws Exception {
        log("\n**xmlToObjectTest**");
        log("Expected:");
        log(controlObject.toString());
        log("Actual:");
        log(testObject.toString());

        if ((controlObject instanceof JAXBElement) && (testObject instanceof JAXBElement)) {
            JAXBElement controlObj = (JAXBElement)controlObject;
            JAXBElement testObj = (JAXBElement)testObject;
            compareJAXBElementObjects(controlObj, testObj);
        } else {
            super.xmlToObjectTest(testObject);
        }
    }
    @Override
    public void testUnmarshallerHandler() throws Exception {
        if(isUnmarshalTest()) {
            SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
            saxParserFactory.setNamespaceAware(true);
            SAXParser saxParser = saxParserFactory.newSAXParser();
            XMLReader xmlReader = saxParser.getXMLReader();
            jaxbUnmarshaller.setProperty(MarshallerProperties.MEDIA_TYPE, "application/xml");

            JAXBUnmarshallerHandler jaxbUnmarshallerHandler = (JAXBUnmarshallerHandler)jaxbUnmarshaller.getUnmarshallerHandler();
            xmlReader.setContentHandler(jaxbUnmarshallerHandler);
            InputStream inputStream = ClassLoader.getSystemResourceAsStream(resourceName);
            InputSource inputSource = new InputSource(inputStream);
            xmlReader.parse(inputSource);

            xmlToObjectTest(jaxbUnmarshallerHandler.getResult());
        }
    }

    public void testSchemaGen(List<InputStream> controlSchemas) throws Exception {
        MyStreamSchemaOutputResolver outputResolver = new MyStreamSchemaOutputResolver();
        getJAXBContext().generateSchema(outputResolver);

        List<Writer> generatedSchemas = outputResolver.getSchemaFiles();
        compareSchemas(controlSchemas, generatedSchemas);
    }

    public void compareSchemas(List<InputStream> controlSchemas, List<Writer> generatedSchemas) throws Exception {
        assertEquals(controlSchemas.size(), generatedSchemas.size());

        for(int i=0;i<controlSchemas.size(); i++){
            InputStream nextControlValue = controlSchemas.get(i);

            Writer sw = generatedSchemas.get(i);
            InputSource nextGeneratedValue = new InputSource(new StringReader(sw.toString()));

            assertNotNull("Generated Schema not found.", nextGeneratedValue);

            Document control = parser.parse(nextControlValue);
            Document test = parser.parse(nextGeneratedValue);

            JAXBXMLComparer xmlComparer = new JAXBXMLComparer();
            boolean isEqual = xmlComparer.isSchemaEqual(control, test);
            if(!isEqual){
                logDocument(control);
                logDocument(test);
            }
            assertTrue("generated schema did not match control schema", isEqual);
        }
    }

    protected String validateAgainstSchema(InputStream src, Source schemaSource) {
        return validateAgainstSchema(src, schemaSource, null);
    }
    protected String validateAgainstSchema(InputStream src, Source schemaSource, MyMapStreamSchemaOutputResolver outputResolver) {
        SchemaFactory sFact = SchemaFactory.newInstance(javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI);
        sFact.setResourceResolver(new ResourceResolver(outputResolver));

        Schema theSchema;
        try {
            theSchema = sFact.newSchema(schemaSource);
            Validator validator = theSchema.newValidator();
            StreamSource ss = new StreamSource(src);
            validator.validate(ss);
        } catch (Exception e) {
            if (e.getMessage() == null) {
                return "An unknown exception occurred.";
            }
            return e.getMessage();
        }
        return null;
    }

    public class MySchemaOutputResolver extends SchemaOutputResolver {
        // keep a list of processed schemas for the validation phase of the
        // test(s)
        public List<File> schemaFiles;

        public MySchemaOutputResolver() {
            schemaFiles = new ArrayList<File>();
        }

        @Override
        public Result createOutput(String namespaceURI, String suggestedFileName)throws IOException {
            File schemaFile = new File(suggestedFileName);
            if(namespaceURI == null){
                namespaceURI ="";
            }
            schemaFiles.add(schemaFile);
            return new StreamResult(schemaFile);
        }

        public List<File> getSchemaFiles() {
            return schemaFiles;
        }
    }

    /**
     * SchemaOutputResolver for writing out the generated schema.  Returns a StreamResult
     * wrapping a StringWriter.
     *
     */
    public static class MyStreamSchemaOutputResolver extends SchemaOutputResolver {
        // keep a list of processed schemas for the validation phase of the test(s)
        private List<Writer> schemaFiles;

        public MyStreamSchemaOutputResolver() {
            schemaFiles = new ArrayList<Writer>();
        }

        @Override
        public Result createOutput(String namespaceURI, String suggestedFileName) throws IOException {
            if (namespaceURI == null) {
                namespaceURI = "";
            }

            StringWriter sw = new StringWriter();
            schemaFiles.add(sw);
            Result res = new StreamResult(sw);
            res.setSystemId(suggestedFileName);
            return res;
        }

        public List<Writer> getSchemaFiles() {
            return schemaFiles;
        }
    }

    public static class MyMapStreamSchemaOutputResolver extends SchemaOutputResolver {
        // keep a list of processed schemas for the validation phase of the test(s)
        public Map<String, Writer> schemaFiles;

        public MyMapStreamSchemaOutputResolver() {
            schemaFiles = new HashMap<String, Writer>();
        }

        @Override
        public Result createOutput(String namespaceURI, String suggestedFileName) throws IOException {
            //return new StreamResult(System.out);
            if (namespaceURI == null) {
                namespaceURI = "";
            }

            StringWriter sw = new StringWriter();
            schemaFiles.put(namespaceURI, sw);
            Result res = new StreamResult(sw);
            res.setSystemId(suggestedFileName);
            return res;
        }
    }

    protected void logDocument(Document document){
       try {
              TransformerFactory transformerFactory = TransformerFactory.newInstance();
              Transformer transformer = transformerFactory.newTransformer();
              DOMSource source = new DOMSource(document);
              StreamResult result = new StreamResult(System.out);
              transformer.transform(source, result);
          } catch (Exception e) {
              e.printStackTrace();
          }
   }


    protected void validateBindingsFileAgainstSchema(Object obj) {
        if(obj instanceof List){
            List theList = (List)obj;
            for(int i=0; i<theList.size(); i++){
                Object next = theList.get(i);
                if(next instanceof Source) {
                    Source src = (Source)theList.get(i);
                    validateBindingsFileAgainstSchema(src);
                }
            }
        }
    }

    protected void validateBindingsFileAgainstSchema(Source src) {
        String result = null;
        SchemaFactory sFact = SchemaFactory.newInstance(javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI);
        Schema theSchema;
        try {
            InputStream bindingsFileXSDInputStream = getClass().getClassLoader().getResourceAsStream(ECLIPSELINK_OXM_XSD);
            if (bindingsFileXSDInputStream == null){
                bindingsFileXSDInputStream = getClass().getClassLoader().getResourceAsStream("org/eclipse/persistence/jaxb/" + ECLIPSELINK_OXM_XSD);
            }
            if (bindingsFileXSDInputStream == null){
                fail("ERROR LOADING " + ECLIPSELINK_OXM_XSD);
            }
            Source bindingsFileXSDSource = new StreamSource(bindingsFileXSDInputStream);
            theSchema = sFact.newSchema(bindingsFileXSDSource);
            Validator validator = theSchema.newValidator();

            validator.validate(src);
        } catch (Exception e) {
            e.printStackTrace();
            if (e.getMessage() == null) {
                result = "An unknown exception occurred.";
            }
            result = e.getMessage();
        }
        assertTrue("Schema validation failed unxepectedly: " + result, result == null);
    }

    public static class ExtendedXMLStreamReaderReader extends XMLStreamReaderReader {

        @Override
        protected void parseCharactersEvent(XMLStreamReader xmlStreamReader) throws SAXException {
            try {
                contentHandler.characters(xmlStreamReader.getElementText());
            } catch(XMLStreamException e) {
                super.parseCharactersEvent(xmlStreamReader);
            }
        }

    }

    /**
     * Class responsible from resolving schema imports during schema
     * validation.
     *
     */
    class ResourceResolver implements LSResourceResolver {
        private MyMapStreamSchemaOutputResolver oResolver;

        public ResourceResolver(MyMapStreamSchemaOutputResolver resolver) {
            oResolver = resolver;
        }
        @Override
        public LSInput resolveResource(String type, String namespaceURI, String publicId, String systemId, String baseUri) {
            return new MyLSInput(namespaceURI, oResolver);
        }
    }

    /**
     * Class which will be returned to from resolveResource() call in
     * ResourceResolver.
     *
     */
    class MyLSInput implements LSInput {
        private String sValue;
        private MyMapStreamSchemaOutputResolver oResolver;

        public MyLSInput(String value, MyMapStreamSchemaOutputResolver resolver) {
            sValue = value;
            oResolver = resolver;
        }
        @Override
        public void setSystemId(String arg0) {}
        @Override
        public void setStringData(String arg0) {}
        @Override
        public void setPublicId(String arg0) {}
        @Override
        public void setEncoding(String arg0) {}
        @Override
        public void setCharacterStream(Reader arg0) {}
        @Override
        public void setCertifiedText(boolean arg0) {}
        @Override
        public void setByteStream(InputStream arg0) {}
        @Override
        public void setBaseURI(String arg0) {}
        @Override
        public String getSystemId() {return null;}
        @Override
        public String getStringData() {
            return oResolver.schemaFiles.get(sValue).toString();
        }
        @Override
        public String getPublicId() {return null;}
        @Override
        public String getEncoding() {return null;}
        @Override
        public Reader getCharacterStream() {return null;}
        @Override
        public boolean getCertifiedText() {return false;}
        @Override
        public InputStream getByteStream() {return null;}
        @Override
        public String getBaseURI() {return null;}
    }

}
