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

import java.io.File;
import java.io.InputStream;

import java.lang.reflect.Method;

import java.net.URL;
import java.net.URLClassLoader;

import jakarta.xml.bind.JAXBContext;
import jakarta.xml.bind.PropertyException;
import jakarta.xml.bind.Unmarshaller;
import jakarta.xml.bind.UnmarshalException;
import jakarta.xml.bind.util.JAXBSource;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;

import junit.framework.TestCase;

import org.w3c.dom.Document;
import org.w3c.dom.Node;

import org.xml.sax.InputSource;

public class UnmarshallerTestCases extends TestCase  {

    private static final String SCHEMA_LANGUAGE = "http://java.sun.com/xml/jaxp/properties/schemaLanguage";
    private static final String XML_SCHEMA = "http://www.w3.org/2001/XMLSchema";

    private final static String CONTROL_XML_FILE_NAME = "org/eclipse/persistence/testing/oxm/jaxb/Employee.xml";
    private final static String CONTROL_EMPLOYEE_NAME = "Jane Doe";

    private JAXBContext jaxbContext;
    private Unmarshaller unmarshaller;
    private DocumentBuilder parser;
    private String contextPath;

    public UnmarshallerTestCases(String name) {
        super(name);
    }

    @Override
    public void setUp() throws Exception {
        contextPath = System.getProperty("jaxb.test.contextpath", JAXBSAXTestSuite.CONTEXT_PATH);

        jaxbContext = JAXBContext.newInstance(contextPath, getClass().getClassLoader());
        unmarshaller = jaxbContext.createUnmarshaller();
        DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
        builderFactory.setIgnoringElementContentWhitespace(true);
        parser = builderFactory.newDocumentBuilder();
    }

    /**
    * Since JAXB delegates all of its functionality to XMLMarshaller, there is no need to
    * re-test all of the various marshal/unmarshal methods.
    */
    public void testUnmarshalFile() throws Exception {
        File file = new File(ClassLoader.getSystemResource(CONTROL_XML_FILE_NAME).getFile());
        unmarshaller.setValidating(true);
        Object testObject = unmarshaller.unmarshal(file);
        assertEquals(getControlObject(), testObject);
    }

    public void testUnmarshalFileNotValidating() throws Exception {
        File file = new File(ClassLoader.getSystemResource(CONTROL_XML_FILE_NAME).getFile());
        unmarshaller.setValidating(false);
        Object testObject = unmarshaller.unmarshal(file);
        assertEquals(getControlObject(), testObject);
    }

    public void testUnmarshalFromJAXBSource() throws Exception {
        File file = new File(ClassLoader.getSystemResource(CONTROL_XML_FILE_NAME).getFile());
        Object unmarshalledObject = unmarshaller.unmarshal(file);

        JAXBSource jaxbSource = new JAXBSource(jaxbContext.createMarshaller(), unmarshalledObject);

        Object objectFromSource = unmarshaller.unmarshal(jaxbSource);
        assertEquals(getControlObject(), objectFromSource);
    }

    // Invalid sources tests=============================================================

    public void testUnmarshalFromInvalidFile() throws Exception {
        File file = new File("blah.txt");
        try {
            Object unmarshalledObject = unmarshaller.unmarshal(file);
        } catch (UnmarshalException e) {
            assertTrue(true);
            return;
        }
        assertTrue("An XMLValidation should have been caught but wasn't.", false);
    }

    public void testUnmarshalFromInvalidURL() throws Exception {
        URL url = new URL("http://");
        try {
            Object unmarshalledObject = unmarshaller.unmarshal(url);
        } catch (UnmarshalException e) {
            assertTrue(true);
            return;
        }
        assertTrue("An UnmarshalException should have been caught but wasn't.", false);
    }

    public void testUnmarshalFromInvalidNode()  throws Exception {
        Document doc = parser.newDocument();
        Node node = doc.createAttribute("aaa");
        try {
            Object unmarshalledObject = unmarshaller.unmarshal(node);
        } catch (UnmarshalException e) {
            assertTrue(true);
            return;
        }
        assertTrue("An UnmarshalException should have been caught but wasn't.", false);
    }

    public void testUnmarshalFromInvalidInputStream() throws Exception {
        InputStream stream = ClassLoader.getSystemResourceAsStream(CONTROL_XML_FILE_NAME);
        stream.close();
        try {
            Object unmarshalledObject = unmarshaller.unmarshal(stream);
        } catch (UnmarshalException e) {
            assertTrue(true);
            return;
        }
        assertTrue("An UnmarshalException should have been caught but wasn't.", false);
    }

    public void testUnmarshalFromInvalidSource() throws Exception {
        InputStream inputStream = ClassLoader.getSystemResourceAsStream(CONTROL_XML_FILE_NAME);
        StreamSource source = new StreamSource(inputStream);
        source.getInputStream().close();
        try {
            Object unmarshalledObject = unmarshaller.unmarshal(source);
        } catch (UnmarshalException e) {
            assertTrue(true);
            return;
        }
        assertTrue("An UnmarshalException should have been caught but wasn't.", false);
    }

    public void testUnmarshalFromInvalidInputSource() throws Exception {
        InputStream stream = ClassLoader.getSystemResourceAsStream(CONTROL_XML_FILE_NAME);
        InputSource source = new InputSource(stream);
        source.getByteStream().close();
        try {
            Object unmarshalledObject = unmarshaller.unmarshal(source);
        } catch (UnmarshalException e) {
            assertTrue(true);
            return;
        }
        assertTrue("An UnmarshalException should have been caught but wasn't.", false);
    }

    public void testUnmarshalFileException() {
        boolean caughtException = false;
        try {
            unmarshaller.unmarshal((File) null);
        } catch (IllegalArgumentException e) {
            caughtException = true;
        } catch (Exception e) {
        }
        assertTrue("JAXBUnmarshaller did not throw IllegalArgumentException as expected.", caughtException);
    }

    public void testUnmarshalInputStreamException() {
        boolean caughtException = false;
        try {
            unmarshaller.unmarshal((InputStream) null);
        } catch (IllegalArgumentException e) {
            caughtException = true;
        } catch (Exception e) {
        }
        assertTrue("JAXBUnmarshaller did not throw IllegalArgumentException as expected.", caughtException);
    }

    public void testUnmarshalInputSourceException() {
        boolean caughtException = false;
        try {
            unmarshaller.unmarshal((InputSource) null);
        } catch (IllegalArgumentException e) {
            caughtException = true;
        } catch (Exception e) {
        }
        assertTrue("JAXBUnmarshaller did not throw IllegalArgumentException as expected.", caughtException);
    }

    public void testUnmarshalSourceException() {
        boolean caughtException = false;
        try {
            unmarshaller.unmarshal((Source) null);
        } catch (IllegalArgumentException e) {
            caughtException = true;
        } catch (Exception e) {
        }
        assertTrue("JAXBUnmarshaller did not throw IllegalArgumentException as expected.", caughtException);
    }

    public void testUnmarshalURLException() {
        boolean caughtException = false;
        try {
            unmarshaller.unmarshal((URL) null);
        } catch (IllegalArgumentException e) {
            caughtException = true;
        } catch (Exception e) {
        }
        assertTrue("JAXBUnmarshaller did not throw IllegalArgumentException as expected.", caughtException);
    }

    public void testUnmarshalNodeException() {
        boolean caughtException = false;
        try {
            unmarshaller.unmarshal((Node) null);
        } catch (IllegalArgumentException e) {
            caughtException = true;
        } catch (Exception e) {
        }
        assertTrue("JAXBUnmarshaller did not throw IllegalArgumentException as expected.", caughtException);
    }

    public void testJAXBClassLoader() throws Exception {
        // Determine the directory that Employee.class is in
        URL classURL = ClassLoader.getSystemClassLoader().getResource("org/eclipse/persistence/testing/jaxb/xmlmarshaller/Employee.class");
        URL directoryURL = new File(classURL.getFile()).getParentFile().getParentFile().getParentFile().getParentFile().getParentFile().getParentFile().toURI().toURL();

        // Create a URLClassLoader specifically for this class
        URLClassLoader classLoader = new URLClassLoader(new URL[] { directoryURL });

        // Set up a control object using this ClassLoader
        Object controlObject = Class.forName("org.eclipse.persistence.testing.jaxb.xmlmarshaller.Employee", true, classLoader).getConstructor().newInstance();
        Method setMethod = controlObject.getClass().getMethod("setName", new Class[] { String.class });
        setMethod.invoke(controlObject, new Object[] { CONTROL_EMPLOYEE_NAME });

        // Unmarshall the control file, passing JAXB this classLoader
        JAXBContext jaxbContext = JAXBContext.newInstance(contextPath, classLoader);
        Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
        File file = new File(ClassLoader.getSystemResource(CONTROL_XML_FILE_NAME).getFile());
        Object testObject = unmarshaller.unmarshal(file);

        assertEquals(controlObject, testObject);
    }

    public void testSetNullPropertyException() {
        boolean caughtException = false;
        try {
            unmarshaller.setProperty(null, null);
        } catch (IllegalArgumentException e) {
            caughtException = true;
        } catch (Exception e) {
        }
        assertTrue("JAXBUnmarshaller did not throw IllegalArgumentException as expected.", caughtException);
    }

    public void testGetNullPropertyException() {
        boolean caughtException = false;
        try {
            unmarshaller.getProperty(null);
        } catch (IllegalArgumentException e) {
            caughtException = true;
        } catch (Exception e) {
        }
        assertTrue("JAXBUnmarshaller did not throw IllegalArgumentException as expected.", caughtException);
    }

    public void testSetInvalidPropertyException() {
        boolean caughtException = false;
        try {
            unmarshaller.setProperty("thisIsAnInvalidProperty", "thisIsAnInvalidValue");
        } catch (PropertyException e) {
            caughtException = true;
        } catch (Exception e) {
        }
        assertTrue("JAXBUnmarshaller did not throw PropertyException as expected.", caughtException);
    }

    public void testGetInvalidPropertyException() {
        boolean caughtException = false;
        try {
            unmarshaller.getProperty("thisIsAnInvalidProperty");
        } catch (PropertyException e) {
            caughtException = true;
        } catch (Exception e) {
        }
        assertTrue("JAXBUnmarshaller did not throw PropertyException as expected.", caughtException);
    }

    // =============================================================

    private Object getControlObject() {
        Employee employee = new Employee();
        employee.setName(CONTROL_EMPLOYEE_NAME);
        return employee;
    }

}
