/*
 * 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  January 2012
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.JAXBTestCases;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;

public abstract class JAXBListOfObjectsNoJSONTestCases extends JAXBTestCases{

    public JAXBListOfObjectsNoJSONTestCases(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, null, classLoader);
        jaxbMarshaller = jaxbContext.createMarshaller();
        jaxbUnmarshaller = jaxbContext.createUnmarshaller();
    }

    @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);
                }
            }
        }

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

    @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);
    }


}

