/*
 * 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:
//     Denise Smith  June 05, 2009 - Initial implementation
package org.eclipse.persistence.testing.jaxb.listofobjects;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;

import java.io.InputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

import java.util.Iterator;
import java.util.List;
import java.util.Map;

import jakarta.xml.bind.JAXBElement;
import jakarta.xml.bind.Marshaller;
import javax.xml.stream.XMLStreamReader;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;

import org.eclipse.persistence.internal.jaxb.JaxbClassLoader;
import org.eclipse.persistence.jaxb.*;
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.testing.jaxb.JAXBWithJSONTestCases;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;

public abstract class JAXBListOfObjectsTestCases extends JAXBWithJSONTestCases{

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

    @Override
    public void setClasses(Class[] newClasses) throws Exception {
        classLoader = new JaxbClassLoader(Thread.currentThread()
                .getContextClassLoader());
        JAXBContextFactory factory = new JAXBContextFactory();
        jaxbContext = JAXBContextFactory.createContext(newClasses, getProperties(), classLoader);
        jaxbMarshaller = jaxbContext.createMarshaller();
        jaxbUnmarshaller = jaxbContext.createUnmarshaller();
        this.classes = newClasses;
    }

    @Override
    public void setTypes(Type[] newTypes) throws Exception {
        classLoader = new JaxbClassLoader(Thread.currentThread()
                .getContextClassLoader());
        JAXBContextFactory factory = new JAXBContextFactory();

         Map props = getProperties();
                if(props != null){
            Map overrides = (Map) props.get(JAXBContextProperties.OXM_METADATA_SOURCE);
            if(overrides != null){
                Iterator valuesIter = overrides.values().iterator();
                while(valuesIter.hasNext()){
                    Source theSource = (Source) valuesIter.next();
                    validateBindingsFileAgainstSchema(theSource);
                }
            }
        }


        jaxbContext = JAXBContextFactory.createContext(newTypes, props, classLoader);
        jaxbMarshaller = jaxbContext.createMarshaller();
        jaxbUnmarshaller = jaxbContext.createUnmarshaller();
        types = newTypes;
    }

    @Override
    protected Object getControlObject() {
        return null;
    }

    @Override
    public void testXMLToObjectFromXMLStreamReader() throws Exception {
        if(null != XML_INPUT_FACTORY) {
            InputStream instream = ClassLoader.getSystemResourceAsStream(resourceName);
            XMLStreamReader xmlStreamReader = XML_INPUT_FACTORY.createXMLStreamReader(instream);
            Object testObject = jaxbUnmarshaller.unmarshal(xmlStreamReader);
            instream.close();
            xmlToObjectTest(testObject);
        }
    }

    public void testXMLToObjectFromXMLStreamReaderWithType() throws Exception {
        if(null != XML_INPUT_FACTORY) {
            InputStream instream = ClassLoader.getSystemResourceAsStream(resourceName);
            XMLStreamReader xmlStreamReader = XML_INPUT_FACTORY.createXMLStreamReader(instream);
            Object testObject = ((JAXBUnmarshaller)jaxbUnmarshaller).unmarshal(xmlStreamReader, getTypeToUnmarshalTo());
            instream.close();

            JAXBElement controlObj = (JAXBElement)getControlObject();
            JAXBElement newControlObj = new JAXBElement(controlObj.getName(), getClassForDeclaredTypeOnUnmarshal(), controlObj.getScope(), controlObj.getValue());
            xmlToObjectTest(testObject, newControlObj);
        }
    }
    /*
    public void testXMLToObjectFromXMLStreamReaderWithTypeMappingInfo() throws Exception {
        if(null != XML_INPUT_FACTORY) {
            InputStream instream = ClassLoader.getSystemResourceAsStream(resourceName);
            XMLStreamReader xmlStreamReader = XML_INPUT_FACTORY.createXMLStreamReader(instream);
            Object testObject = ((JAXBUnmarshaller)jaxbUnmarshaller).unmarshal(xmlStreamReader, getTypeMappingInfoToUnmarshalTo());
            instream.close();

            JAXBElement controlObj = (JAXBElement)getControlObject();
            JAXBElement newControlObj = new JAXBElement(controlObj.getName(), getClassForDeclaredTypeOnUnmarshal(), controlObj.getScope(), controlObj.getValue());
            xmlToObjectTest(testObject, newControlObj);
        }
    } */

    public void testXMLToObjectFromXMLStreamReaderWithClass() throws Exception {
        if(null != XML_INPUT_FACTORY) {
            InputStream instream = ClassLoader.getSystemResourceAsStream(resourceName);
            XMLStreamReader xmlStreamReader = XML_INPUT_FACTORY.createXMLStreamReader(instream);
            Object testObject = jaxbUnmarshaller.unmarshal(xmlStreamReader, getClassForDeclaredTypeOnUnmarshal());
            instream.close();

            JAXBElement controlObj = (JAXBElement)getControlObject();
            JAXBElement newControlObj = new JAXBElement(controlObj.getName(), getClassForDeclaredTypeOnUnmarshal(), controlObj.getScope(), controlObj.getValue());
            xmlToObjectTest(testObject, newControlObj);
        }
    }


    @Override
    public void testXMLToObjectFromXMLEventReader() throws Exception {
        if(null != XML_INPUT_FACTORY) {
            InputStream instream = ClassLoader.getSystemResourceAsStream(resourceName);
            javax.xml.stream.XMLEventReader reader = XML_INPUT_FACTORY.createXMLEventReader(instream);
            Object obj = jaxbUnmarshaller.unmarshal(reader);
            this.xmlToObjectTest(obj);
        }
    }

    public void testXMLToObjectFromXMLEventReaderWithType() throws Exception {
        if(null != XML_INPUT_FACTORY) {
            InputStream instream = ClassLoader.getSystemResourceAsStream(resourceName);
            javax.xml.stream.XMLEventReader reader = XML_INPUT_FACTORY.createXMLEventReader(instream);
            Object obj = ((JAXBUnmarshaller)jaxbUnmarshaller).unmarshal(reader, getTypeToUnmarshalTo());

            JAXBElement controlObj = (JAXBElement)getControlObject();
            JAXBElement newControlObj = new JAXBElement(controlObj.getName(), getClassForDeclaredTypeOnUnmarshal(), controlObj.getScope(), controlObj.getValue());
            xmlToObjectTest(obj, newControlObj);
        }
    }
    /*
    public void testXMLToObjectFromXMLEventReaderWithTypeMappingInfo() throws Exception {
        if(null != XML_INPUT_FACTORY) {
            InputStream instream = ClassLoader.getSystemResourceAsStream(resourceName);
            javax.xml.stream.XMLEventReader reader = XML_INPUT_FACTORY.createXMLEventReader(instream);
            Object obj = ((JAXBUnmarshaller)jaxbUnmarshaller).unmarshal(reader, getTypeMappingInfoToUnmarshalTo());

            JAXBElement controlObj = (JAXBElement)getControlObject();
            JAXBElement newControlObj = new JAXBElement(controlObj.getName(), getClassForDeclaredTypeOnUnmarshal(), controlObj.getScope(), controlObj.getValue());
            xmlToObjectTest(obj, newControlObj);
        }
    }
    */

    public void testXMLToObjectFromXMLEventReaderWithClass() throws Exception {
        if(null != XML_INPUT_FACTORY) {
            InputStream instream = ClassLoader.getSystemResourceAsStream(resourceName);
            javax.xml.stream.XMLEventReader reader = XML_INPUT_FACTORY.createXMLEventReader(instream);
            Object obj = jaxbUnmarshaller.unmarshal(reader, getClassForDeclaredTypeOnUnmarshal());

            JAXBElement controlObj = (JAXBElement)getControlObject();
            JAXBElement newControlObj = new JAXBElement(controlObj.getName(), getClassForDeclaredTypeOnUnmarshal(), controlObj.getScope(), controlObj.getValue());
            xmlToObjectTest(obj, newControlObj);
        }
    }

    @Override
    public void testXMLToObjectFromNode() throws Exception {
        if(isUnmarshalTest()) {
            InputStream instream = ClassLoader.getSystemResourceAsStream(resourceName);
            Node node  = parser.parse(instream);
            Object testObject = jaxbUnmarshaller.unmarshal(node);
            instream.close();
            xmlToObjectTest(testObject);
        }
    }


    public void testXMLToObjectFromNodeWithClass() throws Exception {
        if(isUnmarshalTest()) {
            InputStream instream = ClassLoader.getSystemResourceAsStream(resourceName);
            Node node  = parser.parse(instream);
            Object obj = jaxbUnmarshaller.unmarshal(node, getClassForDeclaredTypeOnUnmarshal());

            JAXBElement controlObj = (JAXBElement)getControlObject();
            JAXBElement newControlObj = new JAXBElement(controlObj.getName(), getClassForDeclaredTypeOnUnmarshal(), controlObj.getScope(), controlObj.getValue());
            xmlToObjectTest(obj, newControlObj);

            instream.close();
        }
    }

    @Override
    public void testObjectToXMLStreamWriter() throws Exception {
        StringWriter writer = new StringWriter();
        Object objectToWrite = getWriteControlObject();
        javax.xml.stream.XMLOutputFactory factory = javax.xml.stream.XMLOutputFactory.newInstance();
        javax.xml.stream.XMLStreamWriter streamWriter = factory.createXMLStreamWriter(writer);

        getJAXBMarshaller().marshal(objectToWrite, streamWriter);

        StringReader reader = new StringReader(writer.toString());
        InputSource inputSource = new InputSource(reader);
        Document testDocument = parser.parse(inputSource);
        writer.close();
        reader.close();

        objectToXMLDocumentTest(testDocument);
    }

    @Override
    public void testObjectToXMLStreamWriterRecord() throws Exception {
        StringWriter writer = new StringWriter();
        Object objectToWrite = getWriteControlObject();
        javax.xml.stream.XMLOutputFactory factory = javax.xml.stream.XMLOutputFactory.newInstance();
        javax.xml.stream.XMLStreamWriter streamWriter = factory.createXMLStreamWriter(writer);

        XMLStreamWriterRecord record = new XMLStreamWriterRecord(streamWriter);
        ((JAXBMarshaller) getJAXBMarshaller()).marshal(objectToWrite, record);

        StringReader reader = new StringReader(writer.toString());
        InputSource inputSource = new InputSource(reader);
        Document testDocument = parser.parse(inputSource);
        writer.close();
        reader.close();

        objectToXMLDocumentTest(testDocument);
    }

    @Override
    public void testObjectToXMLEventWriter() throws Exception {
        StringWriter writer = new StringWriter();
        Object objectToWrite = getWriteControlObject();
        javax.xml.stream.XMLOutputFactory factory = javax.xml.stream.XMLOutputFactory.newInstance();
        javax.xml.stream.XMLEventWriter eventWriter = factory.createXMLEventWriter(writer);

        getJAXBMarshaller().marshal(objectToWrite, eventWriter);

        StringReader reader = new StringReader(writer.toString());
        InputSource inputSource = new InputSource(reader);
        Document testDocument = parser.parse(inputSource);
        writer.close();
        reader.close();

        objectToXMLDocumentTest(testDocument);
    }

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

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

            Object objectToWrite = getWriteControlObject();

            ((JAXBMarshaller)jaxbMarshaller).marshal(objectToWrite, streamWriter, getTypeMappingInfoToUnmarshalTo());

            streamWriter.flush();

            StringReader reader = new StringReader(writer.toString());
            InputSource inputSource = new InputSource(reader);
            Document testDocument = parser.parse(inputSource);
            writer.close();
            reader.close();
            objectToXMLDocumentTest(testDocument);
        }
    }

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

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

            Object objectToWrite = getWriteControlObject();

            ((JAXBMarshaller)jaxbMarshaller).marshal(objectToWrite, eventWriter, getTypeMappingInfoToUnmarshalTo());

            eventWriter.flush();

            StringReader reader = new StringReader(writer.toString());
            InputSource inputSource = new InputSource(reader);
            Document testDocument = parser.parse(inputSource);
            writer.close();
            reader.close();
            objectToXMLDocumentTest(testDocument);
        }
    }
        */


    //Override and don't compare namespaceresolver size
    @Override
    public void testObjectToXMLStringWriter() throws Exception {
        StringWriter writer = new StringWriter();
        Object objectToWrite = getWriteControlObject();

        jaxbMarshaller.marshal(objectToWrite, writer);

        StringReader reader = new StringReader(writer.toString());
        InputSource inputSource = new InputSource(reader);
        Document testDocument = parser.parse(inputSource);
        writer.close();
        reader.close();

        objectToXMLDocumentTest(testDocument);
    }

     @Override
     public void testObjectToOutputStream() throws Exception {
            Object objectToWrite = getWriteControlObject();
            ByteArrayOutputStream stream = new ByteArrayOutputStream();

            jaxbMarshaller.marshal(objectToWrite, stream);

            InputStream is = new ByteArrayInputStream(stream.toByteArray());
            Document testDocument = parser.parse(is);
            stream.close();
            is.close();

            objectToXMLDocumentTest(testDocument);
        }

        @Override
        public void testObjectToOutputStreamASCIIEncoding() throws Exception {
            Object objectToWrite = getWriteControlObject();
            ByteArrayOutputStream stream = new ByteArrayOutputStream();

            String originalEncoding = (String)jaxbMarshaller.getProperty(Marshaller.JAXB_ENCODING);
            jaxbMarshaller.setProperty(Marshaller.JAXB_ENCODING, "US-ASCII");
            jaxbMarshaller.marshal(objectToWrite, stream);
            jaxbMarshaller.setProperty(Marshaller.JAXB_ENCODING, originalEncoding);

            InputStream is = new ByteArrayInputStream(stream.toByteArray());
            Document testDocument = parser.parse(is);
            stream.close();
            is.close();

            objectToXMLDocumentTest(testDocument);
        }


    @Override
    public void testRoundTrip() throws Exception {
        //This test is not applicable because to Marshal we need a specialized jaxbelement
    }


    //Override and don't compare namespaceresolver size
     @Override
     public void testObjectToContentHandler() throws Exception {
            SAXDocumentBuilder builder = new SAXDocumentBuilder();
            Object objectToWrite = getWriteControlObject();

            jaxbMarshaller.marshal(objectToWrite, builder);

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

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

            assertXMLIdentical(controlDocument, testDocument);
        }

        //Override and don't compare namespaceresolver size
        @Override
        public void testObjectToXMLDocument() throws Exception {
            Object objectToWrite = getWriteControlObject();

            Document testDocument = XMLPlatformFactory.getInstance().getXMLPlatform().createDocument();
            jaxbMarshaller.marshal(objectToWrite, testDocument);
            objectToXMLDocumentTest(testDocument);
        }


    public void testXMLToObjectFromStreamSource() throws Exception {
        InputStream instream = ClassLoader
                .getSystemResourceAsStream(resourceName);
        StreamSource source = new StreamSource();
        source.setInputStream(instream);
        Object obj = getJAXBUnmarshaller().unmarshal(source);
        this.xmlToObjectTest(obj);
    }

    public void testXMLToObjectFromStreamSourceWithClass() throws Exception {
        InputStream instream = ClassLoader.getSystemResourceAsStream(resourceName);
        StreamSource source = new StreamSource();
        source.setInputStream(instream);
        Object obj = getJAXBUnmarshaller().unmarshal(source, getClassForDeclaredTypeOnUnmarshal());
        JAXBElement controlObj = (JAXBElement)getControlObject();
        JAXBElement newControlObj = new JAXBElement(controlObj.getName(), getClassForDeclaredTypeOnUnmarshal(), controlObj.getScope(), controlObj.getValue());
                xmlToObjectTest(obj, newControlObj);
    }

    public abstract List<InputStream> getControlSchemaFiles();

    public void testSchemaGen() throws Exception {
        testSchemaGen(getControlSchemaFiles());
    }

    @Override
    public Object getWriteControlObject(){
        JAXBElement jaxbElement = (JAXBElement)getControlObject();

        try{
            Type typeToUse = getTypeToUnmarshalTo();
            if(typeToUse instanceof ParameterizedType){
                JAXBTypeElement typed = new JAXBTypeElement(jaxbElement.getName(), jaxbElement.getValue(), (ParameterizedType)typeToUse);
                return typed;
            }else if(typeToUse instanceof Class){
                JAXBTypeElement typed = new JAXBTypeElement(jaxbElement.getName(), jaxbElement.getValue(), (Class)typeToUse);
                return typed;
            }
        }catch(Exception e){
            fail(e.getMessage());
        }
        return null;

    }

    private Class getClassForDeclaredTypeOnUnmarshal() throws Exception{
        Type typeToUse = getTypeToUnmarshalTo();
        if(typeToUse instanceof Class){
            return (Class)typeToUse;
        }
        return Object.class;
    }

    protected abstract Type getTypeToUnmarshalTo() throws Exception;

    protected TypeMappingInfo getTypeMappingInfoToUnmarshalTo() throws Exception {
        TypeMappingInfo info = new TypeMappingInfo();
        info.setType(getTypeToUnmarshalTo());
        return info;
    }

    protected abstract String getNoXsiTypeControlResourceName();

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

            JAXBElement controlObj = (JAXBElement)controlObject;
            JAXBElement testObj = (JAXBElement)testObject;
            compareJAXBElementObjects(controlObj, testObj);
    }


}
