/*
 * Copyright (c) 2017, 2020 Oracle and/or its affiliates. All rights reserved.
 */


/*
 *  @(#)JAXBContext.test.xml	1.7 07/01/24 Evgueni Rouban, Alexey Vishentsev
 * Generated from : api/jakarta_xml/bind/JAXBContext/JAXBContext.test.xml
 *
 * General tests of constructors and newInstance methods
 * General tests of constructors and newInstance methods.
 */

package javasoft.sqe.tests.api.jakarta.xml.bind.JAXBContext;

import jakarta.xml.bind.JAXBContext;
import jakarta.xml.bind.JAXBElement;
import jakarta.xml.bind.JAXBException;
import jakarta.xml.bind.Marshaller;
import jakarta.xml.bind.PropertyException;
import jakarta.xml.bind.SchemaOutputResolver;
import jakarta.xml.bind.Unmarshaller;
import jakarta.xml.bind.Validator;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.math.BigDecimal;
import java.net.URL;
import java.util.Collections;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Map;
import javasoft.sqe.javatest.Status;
import javasoft.sqe.javatest.lib.MultiTest;
import javax.xml.XMLConstants;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.namespace.QName;
import javax.xml.transform.Result;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;


public class JAXBContextTests extends MultiTest {

    public static final String testPackage = "javasoft.sqe.tests.api.jakarta.xml.bind.JAXBContext";

    /**
     * class loader that logs loading
     * and delegates to the current context class loader
     **/
    class CustomClassLoader extends ClassLoader {
        public StringBuffer log = new StringBuffer();
        public CustomClassLoader(ClassLoader parent) {
            super(parent);
        }
        public URL getResource(String name) {
            log.append("getResource(")
               .append(name)
               .append(");\n");
            return getParent().getResource(name);
        }
        public InputStream getResourceAsStream(String name) {
            log.append("getResourceAsStream(")
               .append(name)
               .append(");\n");
            return getParent().getResourceAsStream(name);
        }
        public Class loadClass(String name) throws ClassNotFoundException {
            log.append("loadClass(")
               .append(name)
               .append(");\n");
            return getParent().loadClass(name);
        }
    }

    javasoft.sqe.tests.api.jakarta.xml.bind.JAXBContext.package_with_jaxb_index.PurchaseOrderType
        createPurchaseOrder_packageWithJAXBIndex(){

        DatatypeFactory datatypeFactory;
        try {
            datatypeFactory = DatatypeFactory.newInstance();
        } catch (DatatypeConfigurationException e) {
            throw new Error("Invalid datatype factory configuration",e);
        }

        javasoft.sqe.tests.api.jakarta.xml.bind.JAXBContext.package_with_jaxb_index.Address address =
            new javasoft.sqe.tests.api.jakarta.xml.bind.JAXBContext.package_with_jaxb_index.Address();
        address.setName("Alice Smith");
        address.setStreet("123 Maple Street");
        address.setCity("Mill Valley");
        address.setState("CA");
        address.setCountry("USA");
        address.setZip(new BigDecimal(123456));

        javasoft.sqe.tests.api.jakarta.xml.bind.JAXBContext.package_with_jaxb_index.Items.Item item = new javasoft.sqe.tests.api.jakarta.xml.bind.JAXBContext.package_with_jaxb_index.Items.Item();
        item.setProductName("Lawnmower");
        item.setQuantity(1);
        item.setComment("Confirm this is electric");
        item.setPartNum("872-AA");
        item.setUSPrice(148.95f);

        javasoft.sqe.tests.api.jakarta.xml.bind.JAXBContext.package_with_jaxb_index.Items items =
            new javasoft.sqe.tests.api.jakarta.xml.bind.JAXBContext.package_with_jaxb_index.Items();
        items.getItem().add(item);

        javasoft.sqe.tests.api.jakarta.xml.bind.JAXBContext.package_with_jaxb_index.PurchaseOrderType po =
            new javasoft.sqe.tests.api.jakarta.xml.bind.JAXBContext.package_with_jaxb_index.PurchaseOrderType();

        po.setComment("Hurry, my lawn is going wild");
        po.setOrderDate(datatypeFactory.newXMLGregorianCalendar(new GregorianCalendar()));
        po.setShipTo(address);
        po.setBillTo(address);
        po.setItems(items);
        return po;
    }

    class JAXBContextChild extends JAXBContext {
        public final boolean flag;
        public JAXBContextChild() {
            super();
            flag = true;
        }
        public Marshaller createMarshaller() throws JAXBException {
            throw new JAXBException("unexpected call createMarshaller()");
        }
        public Validator createValidator() throws JAXBException {
            throw new JAXBException("unexpected call createValidator()");
        }
        public Unmarshaller createUnmarshaller() throws JAXBException {
            throw new JAXBException("unexpected call createUnmarshaller()");
        }
    }

    /* standalone interface */
    public static void main(String argv[]) {
        JAXBContextTests test = new JAXBContextTests();
        test.run(argv, System.err, System.out).exit();
    }

    /**
     * Assertion testing
     * for protected JAXBContext(),
     * <br><b>pre-conditions</b>: called from within a constructor of the child class,
     * Default constructor throws no exceptions..
     * <br><b>Expected results</b>: no exceptions
     */
    public Status Ctor001() {
        if ((new JAXBContextChild()).flag) {
                return Status.passed("Ok");
        }
        return Status.failed("Failed.");
         }

    /**
     * Boundary value analysis
     * with input values orientation
     * for public static JAXBContext newInstance(java.lang.String contextPath) throws JAXBException,
     * <br><b>contextPath</b>: existent.
     * <br><b>Expected results</b>: no exceptions
     */
    public Status newInstance001() {
        ClassLoader oldCCL = Thread.currentThread().getContextClassLoader();

        try {
            Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());

            JAXBContext jc = JAXBContext.newInstance(testPackage);

            Thread.currentThread().setContextClassLoader(oldCCL);

            if (jc == null) {
                return Status.failed("jc is null");
            }

            if (! (jc instanceof CustomJAXBContext)) {
                return Status.failed("jc is not an instance of CustomJAXBContext"
                + ", jc.getClass().getName() = " + jc.getClass().getName()
                + ", jc.getClass().getClassLoader().getClass().getName() = " + jc.getClass().getClassLoader().getClass().getName()
                + ", CustomJAXBContext.class.getName() = " + CustomJAXBContext.class.getName()
                + ", CustomJAXBContext.class.getClassLoader().getClass().getName() = " + CustomJAXBContext.class.getClassLoader().getClass().getName());
            }

            return Status.passed("Ok");
        } catch (JAXBException e) {
            return Status.failed("unexpected exception " + e);
        } finally {
            Thread.currentThread().setContextClassLoader(oldCCL);
        }
         }

    /**
     * Assertion testing
     * for public static JAXBContext newInstance(java.lang.String contextPath) throws JAXBException,
     * <br><b>pre-conditions</b>: set current context class loader to the custom class loader,
     * Uses the context class loader of the current thread..
     * <br><b>Expected results</b>: the custom class loader is called to load the
     * jaxb.properties resource, the custom context factory class and the custom
     * JAXBContext class
     */
    public Status newInstance002() {
        ClassLoader oldCCL = Thread.currentThread().getContextClassLoader();

        try {
            CustomClassLoader cl = new CustomClassLoader(this.getClass().getClassLoader());
            Thread.currentThread().setContextClassLoader(cl);

            JAXBContext jc = JAXBContext.newInstance(testPackage);

            Thread.currentThread().setContextClassLoader(oldCCL);

            String result = "";

            if (cl.log.toString().indexOf("jaxb.properties);") == -1) {
                result += "; jaxb.properties was not loaded by the context class loader";
            }

            if (cl.log.toString().indexOf("loadClass(javasoft.sqe.tests.api.jakarta.xml.bind.JAXBContext.ContextFactory);") == -1 ) {
                result += "; context factory javasoft.sqe.tests.api.jakarta.xml.bind.JAXBContext.ContextFactory"
                        + " was not loaded by the context class loader";
            }

            if (cl.log.toString().indexOf("loadClass(javasoft.sqe.tests.api.jakarta.xml.bind.JAXBContext.CustomJAXBContext);") == -1 ) {
                result += "; custom JAXBContext javasoft.sqe.tests.api.jakarta.xml.bind.JAXBContext.CustomJAXBContext"
                        + " was not loaded by the context class loader";
            }

            if (result.length() > 0) {
                ref.println("newInstance002: " + cl.log);
                return Status.failed(result.substring(2));
            }

            return Status.passed("Ok");

        } catch (JAXBException e) {
            return Status.failed("unexpected exception " + e);
        } finally {
            Thread.currentThread().setContextClassLoader(oldCCL);
        }
         }

    /**
     * Boundary value analysis
     * with input values orientation
     * for public static JAXBContext newInstance(java.lang.String contextPath, java.lang.ClassLoader classLoader) throws JAXBException,
     * <br><b>contextPath</b>: existent
     * <br><b>classLoader</b>: test class loader.
     * <br><b>Expected results</b>: no exceptions
     */
    public Status newInstance003() {
        try {
            JAXBContext jc = JAXBContext.newInstance(testPackage
                                                    , this.getClass().getClassLoader());

            if (jc == null) {
                return Status.failed("jc is null");
            }

            if (! (jc instanceof CustomJAXBContext)) {
                return Status.failed("jc is not an instance of CustomJAXBContext"
                + ", jc.getClass().getName() = " + jc.getClass().getName()
                + ", jc.getClass().getClassLoader().getClass().getName() = " + jc.getClass().getClassLoader().getClass().getName()
                + ", CustomJAXBContext.class.getName() = " + CustomJAXBContext.class.getName()
                + ", CustomJAXBContext.class.getClassLoader().getClass().getName() = " + CustomJAXBContext.class.getClassLoader().getClass().getName());
            }

            return Status.passed("Ok");
        } catch (JAXBException e) {
            return Status.failed("unexpected exception " + e);
        }
         }

    /**
     * Assertion testing
     * for public static JAXBContext newInstance(java.lang.String contextPath, java.lang.ClassLoader classLoader) throws JAXBException,
     * <br><b>pre-conditions</b>: contextPath contains the package of the test,
     * class loader is the custom class loader,
     * Obtains a new instance of a JAXBContext class using the given class loader..
     * <br><b>Expected results</b>: no exceptions, the custom class loader is called to load the
     * jaxb.properties resource, the custom context factory class and the custom
     * JAXBContext class
     */
    public Status newInstance004() {
        try {
            CustomClassLoader cl = new CustomClassLoader(this.getClass().getClassLoader());

            JAXBContext jc = JAXBContext.newInstance(testPackage, cl);

            String result = "";

            if (cl.log.toString().indexOf("jaxb.properties);") == -1) {
                result += "; jaxb.properties was not loaded by the custom class loader";
            }

            if (cl.log.toString().indexOf("loadClass(javasoft.sqe.tests.api.jakarta.xml.bind.JAXBContext.ContextFactory);") == -1 ) {
                result += "; context factory javasoft.sqe.tests.api.jakarta.xml.bind.JAXBContext.ContextFactory"
                        + " was not loaded by the custom class loader";
            }

            if (cl.log.toString().indexOf("loadClass(javasoft.sqe.tests.api.jakarta.xml.bind.JAXBContext.CustomJAXBContext);") == -1 ) {
                result += "; custom JAXBContext javasoft.sqe.tests.api.jakarta.xml.bind.JAXBContext.CustomJAXBContext"
                        + " was not loaded by the custom class loader";
            }

            if (result.length() > 0) {
                ref.println("newInstance004: " + cl.log);
                return Status.failed(result.substring(2));
            }

            return Status.passed("Ok");
        } catch (JAXBException e) {
            return Status.failed("unexpected exception " + e);
        }
         }

    /**
     * Boundary value analysis
     * with input values orientation
     * for public static JAXBContext newInstance(java.lang.String contextPath, java.lang.ClassLoader classLoader) throws JAXBException,
     * <br><b>contextPath</b>: unexistent
     * <br><b>classLoader</b>: test class loader.
     * <br><b>Expected results</b>: JAXBException
     */
    public Status newInstance005() {
        try {
            JAXBContext jc = JAXBContext.newInstance(testPackage + ".unexistent"
                                                    , this.getClass().getClassLoader());

            return Status.failed("no exception is thrown");
        } catch (JAXBException e) {
            return Status.passed("Ok");
        }
         }

    /**
     * Boundary value analysis
     * with input values orientation
     * for public static JAXBContext newInstance(java.lang.String contextPath) throws JAXBException,
     * <br><b>contextPath</b>: unexistent.
     * <br><b>Expected results</b>: JAXBException
     */
    public Status newInstance006() {
        ClassLoader oldCCL = Thread.currentThread().getContextClassLoader();

        try {
            Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());

            JAXBContext jc = JAXBContext.newInstance(testPackage + ".unexistent");

            Thread.currentThread().setContextClassLoader(oldCCL);

            return Status.failed("no exception is thrown");
        } catch (JAXBException e) {
            return Status.passed("Ok");
        } finally {
            Thread.currentThread().setContextClassLoader(oldCCL);
        }
         }

    /**
     * Assertion testing
     * for public static JAXBContext newInstance( Class... classesToBeBound ) throws JAXBException,
     * newInstance(Class ...) creates a jaxbContext with no exception if valid classes are passed as a parameter.
     */
    public Status newInstance007() {
        JAXBContext jaxbContext;
            try {
                jaxbContext = JAXBContext.newInstance(
                        javasoft.sqe.tests.api.jakarta.xml.bind.JAXBContext.package_with_jaxb_index.PurchaseOrderType.class
                    );
            } catch (JAXBException e) {
                e.printStackTrace(ref);
                return Status.failed("Failed to create jaxb context using PurchaseOrderType.class"+e);
            }
            if(jaxbContext == null){
                return Status.failed("JAXBContext.newInstance(Class ...) returned null");
            }
            return Status.passed("Ok");
                }

    /**
     * Assertion testing
     * for public static JAXBContext newInstance( Class... classesToBeBound ) throws JAXBException,
     * IllegalArgumentException - if the parameter contains null (i.e., newInstance(null);).
     */
    public Status newInstance007a() {
        try {
                try {
                    JAXBContext jaxbContext = JAXBContext.newInstance(
                            javasoft.sqe.tests.api.jakarta.xml.bind.JAXBContext.package_with_jaxb_index.PurchaseOrderType.class, null );
                    return Status.failed( "Expected IllegalArgumentException wasn't thrown" );
                } catch( IllegalArgumentException x ){ /* expected */ }
            } catch (JAXBException e) {
                e.printStackTrace(ref);
                return Status.failed("Failed to create jaxb context using PurchaseOrderType.class"+e);
            }
            return Status.passed("Ok");
                }

    /**
     * Assertion testing
     * for public static JAXBContext newInstance( Class[] classesToBeBound, Map properties ) throws JAXBException,
     * newInstance(Class,Map) creates a jaxbContext with no exception if valid classes are passed as a parameter.
     */
    public Status newInstance008() {
        JAXBContext jaxbContext;
            try {
                Map<String, ?> props = new HashMap<String, Object>();
                jaxbContext = JAXBContext.newInstance(
                        new Class[] {javasoft.sqe.tests.api.jakarta.xml.bind.JAXBContext.package_with_jaxb_index.PurchaseOrderType.class},
                        props );
            } catch (JAXBException e) {
                e.printStackTrace(ref);
                return Status.failed("Failed to create jaxb context using PurchaseOrderType.class"+e);
            }
            if(jaxbContext == null){
                return Status.failed("JAXBContext.newInstance(Class ...) returned null");
            }
            return Status.passed("Ok");
                }

    /**
     * Assertion testing
     * for public static JAXBContext newInstance( Class... classesToBeBound ) throws JAXBException,
     * newInstance(Class..) throws JAXBException when class tree have colliding type names..
     */
    public Status newInstance009() {
        JAXBContext jaxbContext;
            try {
                jaxbContext = JAXBContext.newInstance(
                        javasoft.sqe.tests.api.jakarta.xml.bind.JAXBContext.colliding_type_names.PurchaseOrderType.class
                    );
            } catch (JAXBException e) {
                ref.println("JAXBException is thrown - ok");
                e.printStackTrace(ref);

                return Status.passed("Ok");
            }
            return Status.failed("Failed. PurchaseOrder and Address (referenced from PurchaseOrder) have colliding type names - but no exception is thrown");
                }

    /**
     * Assertion testing
     * for public static JAXBContext newInstance( Class... classesToBeBound ) throws JAXBException,
     * newInstance(Class...) with empty parameter list creates a new instance of JAXBContext that "knows" about spec-defined classes..
     */
    public Status newInstance010() {
        JAXBContext context;
            try {
                context = JAXBContext.newInstance();
            } catch (JAXBException e) {
                e.printStackTrace(ref);
                return Status.failed("JAXBContext.newInstance() failed. Should return an instance that only knows about spec-defined classes");
            }

            QName rootQName = new QName("jck-jaxb-test/JAXBContext/testDefaultNewInstance","root","jck");

            Marshaller marshaller;
            try {
                marshaller = context.createMarshaller();
            } catch (JAXBException e) {
                e.printStackTrace(ref);
                return Status.failed("jaxbContext.createMarshaller() failed: "+e);
            }
            StringWriter writer = new StringWriter();
            try {
                marshaller.setProperty("jaxb.formatted.output",Boolean.TRUE);
            } catch (PropertyException e1) {
                e1.printStackTrace(ref);
            }
            final String value = "String value";
            try {
                marshaller.marshal(new JAXBElement<String>(rootQName,String.class,value),writer);
            } catch (JAXBException e) {
                e.printStackTrace(ref);
                return Status.failed("Marshalling of String failed:"+e);
            }
            ref.println(" ---- newInstance010 : marshalled document ---- ");
            ref.println(writer.toString());
            ref.println(" ----------------------------------------------- ");
            Unmarshaller unmarshaller;
            try {
                unmarshaller = context.createUnmarshaller();
            } catch (JAXBException e) {
                e.printStackTrace(ref);
                return Status.failed("Failed to create Unmarshaller "+e);
            }

            JAXBElement<String> unmarshalled;
            try {
                unmarshalled = unmarshaller.unmarshal(new StreamSource(new StringReader(writer.toString())),String.class);
            } catch (JAXBException e) {
                e.printStackTrace(ref);
                return Status.failed("Unmarshalling failed. Cause"+e+"\n xml: \n"+writer.toString());
            }
            if(!value.equals(unmarshalled.getValue())){
                return Status.failed("Unmarshalled value is not equal to previously marshalled value.");
            }
            return Status.passed("Ok");
                }

    /**
     * Assertion testing
     * for public static JAXBContext newInstance(String contextPath) throws JAXBException,
     * newInstance(String) creates a jaxbContext with no exception if valid jaxb.index exists in the package, passed as a parameter. Package contains jaxb-annotated classes and a valid jaxb.index file..
     */
    public Status newInstance011() {
        JAXBContext jaxbContext;
            try {
                jaxbContext = JAXBContext.newInstance(
                        "javasoft.sqe.tests.api.jakarta.xml.bind.JAXBContext.package_with_jaxb_index"
                        );
            } catch (JAXBException e) {
                e.printStackTrace(ref);
                return Status.failed("Cannot create jaxb context - package contains a valid jaxb.index file.");
            }
            return Status.passed("Ok");
                }

    /**
     * Assertion testing
     * for public static JAXBContext newInstance(String contextPath) throws JAXBException,
     * newInstance(String) throws a JAXBException when package does not contain neither jaxb.index file nor ObjectFactory class..
     */
    public Status newInstance012() {
        JAXBContext jaxbContext;
            try {
                jaxbContext = JAXBContext.newInstance(
                        "javasoft.sqe.tests.api.jakarta.xml.bind.JAXBContext.package_without_jaxb_index"
                        );
            } catch (JAXBException e) {
                ref.println("JAXBException is thrown - ok");
                e.printStackTrace(ref);

                return Status.passed("Ok");
            }
            return Status.failed("Failed - no exception. newInstance(String contextPath) - package in contextPath contains jaxb-annotated classes but does not contain jaxb-index");
                }

    /**
     * Assertion testing
     * for public void generateSchema(SchemaOutputResolver outputResolver) throws IOException,
     * generateSchema(SchemaOutputResolver) generates schema for jaxb annotated classes.
     */
    public Status schemagen001() {
        class MySchemaOutputResolver extends SchemaOutputResolver{
                private String _nameSpaceURI;
                private String _suggestedFileName;
                private StringWriter _stringWriter;

                public MySchemaOutputResolver(StringWriter writer) {
                    super();
                    _stringWriter = writer;
                }

                public Result createOutput(String namespaceUri, String suggestedFileName) throws IOException {
                    _nameSpaceURI = namespaceUri;
                    _suggestedFileName = suggestedFileName;
                    StreamResult result = new StreamResult(_stringWriter);
                    result.setSystemId(new java.io.File(suggestedFileName));
                    return result;
                }

                public String getNameSpaceURI() {
                    return _nameSpaceURI;
                }

                public String getSuggestedFileName() {
                    return _suggestedFileName;
                }
            }

            StringWriter writer = new StringWriter();
            MySchemaOutputResolver resolver = new MySchemaOutputResolver(writer);

            JAXBContext jaxbContext;
            try {
                jaxbContext = JAXBContext.newInstance(
                        javasoft.sqe.tests.api.jakarta.xml.bind.JAXBContext.package_without_jaxb_index.PurchaseOrderType.class
                    );
            } catch (JAXBException e) {
                e.printStackTrace(ref);
                return Status.failed("Failed to create jaxb context using PurchaseOrderType.class"+e);
            }

            try {
                jaxbContext.generateSchema(resolver);
            } catch (IOException e) {
                e.printStackTrace(ref);
                return Status.failed("Exception while generated schema: "+e);
            }

            String schemaString = writer.toString();
            ref.println("Namespace URI: "+resolver.getNameSpaceURI());
            ref.println("Suggested file name: "+resolver.getSuggestedFileName());
            ref.println("Schema:");
            ref.println(schemaString);

            if(!"jck-jaxb-test/JAXBContext/package_without_jaxb_index".equals(resolver.getNameSpaceURI())){
                return Status.failed("Invalid namespace uri:"+resolver.getNameSpaceURI());
            }

            if(schemaString.length() == 0){
                return Status.failed("No schema is generated.");
            }

            return Status.passed("Ok");
                }
}
