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

import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import org.eclipse.persistence.oxm.*;
import org.eclipse.persistence.exceptions.XMLMarshalException;
import org.eclipse.persistence.testing.oxm.OXTestCase;
import junit.textui.TestRunner;

import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

public class XMLMarshallerValidationModeTestCases extends OXTestCase {
    private static String NO_HEADER_RESOURCE = "org/eclipse/persistence/testing/oxm/xmlmarshaller/Car.xml";
    private static String DTD_VALIDATING_PASSES_RESOURCE = "org/eclipse/persistence/testing/oxm/xmlmarshaller/Car_DTD_passes.xml";
    private static String DTD_VALIDATING_FAILS_RESOURCE = "org/eclipse/persistence/testing/oxm/xmlmarshaller/Car_DTD_fails.xml";
    private static String SCHEMA_VALIDATING_PASSES_RESOURCE = "org/eclipse/persistence/testing/oxm/xmlmarshaller/Car_Valid.xml";
    private static String SCHEMA_VALIDATING_FAILS_RESOURCE = "org/eclipse/persistence/testing/oxm/xmlmarshaller/Car_Invalid.xml";
    private static String CONTROL_LICENSE = "123456";
    private static String CONTROL_LICENSE_INVALID = "123456789";
    private Object controlObject;
    private XMLContext context;
    private XMLUnmarshaller unmarshaller;
    private int originalMode;

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

    public static void main(String[] args) {
        String[] arguments = { "-c", "org.eclipse.persistence.testing.oxm.xmlmarshaller.XMLMarshallerValidationModeTestCases" };
        TestRunner.main(arguments);
    }

    @Override
    public void setUp() throws Exception {
        context = this.getXMLContext(new XMLMarshallerCarProject());
        unmarshaller = context.createUnmarshaller();
        originalMode = unmarshaller.getValidationMode();

        Car car = new Car();
        car.setLicense(CONTROL_LICENSE);
        controlObject = car;

    }

    @Override
    public void tearDown() throws Exception {
        unmarshaller.setValidationMode(originalMode);
    }

    //NON VALIDATING TESTS=========================================================================================

    /**
     * Set the validation mode to NONVALIDATING and try to unmarshal a file which is not valid against the DTD.
     * No Exception should occur
     */
    public void testNonValidatingDTD() {
        unmarshaller.setEntityResolver(new TestEntityResolver());
        unmarshaller.setValidationMode(XMLUnmarshaller.NONVALIDATING);
        InputStream streamToUnmarshal = ClassLoader.getSystemResourceAsStream(DTD_VALIDATING_FAILS_RESOURCE);
        Object unmarshalledObject = unmarshaller.unmarshal(streamToUnmarshal);

        assertEquals(controlObject, unmarshalledObject);

    }

    /**
     * Set the validation mode to NONVALIDATING and try to unmarshal a file which is not valid against the schema.
     * No Exception should occur
     */
    public void testNonValidatingSchema() {
        unmarshaller.setValidationMode(XMLUnmarshaller.NONVALIDATING);
        InputStream streamToUnmarshal = ClassLoader.getSystemResourceAsStream(SCHEMA_VALIDATING_FAILS_RESOURCE);
        Object unmarshalledObject = unmarshaller.unmarshal(streamToUnmarshal);

        Car car = new Car();
        car.setLicense(CONTROL_LICENSE_INVALID);

        assertEquals(car, unmarshalledObject);

    }

    /**
     * Set the validation mode to NONVALIDATING and try to unmarshal a file which does not have a DTD or schema set
     * No Exception should occur
     */
    public void testNonValidatingNoHeader() {
        unmarshaller.setValidationMode(XMLUnmarshaller.NONVALIDATING);
        InputStream streamToUnmarshal = ClassLoader.getSystemResourceAsStream(NO_HEADER_RESOURCE);
        Object unmarshalledObject = unmarshaller.unmarshal(streamToUnmarshal);

        assertEquals(controlObject, unmarshalledObject);

    }

    //DTD TESTS =========================================================================================

    /**
     * Set the validation mode to DTDVALIDATION and try to unmarshal a file with no DTD specified
     * An XMLMarshalException should occur
     */
    public void testDTDValidatingDTDNotSet() {
        unmarshaller.setEntityResolver(new TestEntityResolver());
        unmarshaller.setValidationMode(XMLUnmarshaller.DTD_VALIDATION);
        ErrorHdlr err = new ErrorHdlr();
        unmarshaller.setErrorHandler(err);
        InputStream streamToUnmarshal = ClassLoader.getSystemResourceAsStream(NO_HEADER_RESOURCE);
        try {
            unmarshaller.unmarshal(streamToUnmarshal);
        } catch (XMLMarshalException exception) {
            StringWriter sw = new StringWriter();
            exception.printStackTrace(new PrintWriter(sw));
            assertTrue("An unexpected XMLMarshalException was caught\n" + sw.toString(), exception.getErrorCode() == XMLMarshalException.UNMARSHAL_EXCEPTION);
            return;
        }

        assertTrue("An exception should have been caught but wasn't.", false);
    }

    /**
     * Set the validation mode to DTDVALIDATION and try to unmarshal a file which is valid against the DTD
     * No Exception should occur
     */
    public void testDTDValidatingPasses() {
        unmarshaller.setEntityResolver(new TestEntityResolver());
        unmarshaller.setValidationMode(XMLUnmarshaller.DTD_VALIDATION);
        ErrorHdlr err = new ErrorHdlr();
        unmarshaller.setErrorHandler(err);
        InputStream streamToUnmarshal = ClassLoader.getSystemResourceAsStream(DTD_VALIDATING_PASSES_RESOURCE);
        Object unmarshalledObject;
        try {
            unmarshalledObject = unmarshaller.unmarshal(streamToUnmarshal);
        } catch (XMLMarshalException exception) {
            StringWriter sw = new StringWriter();
            exception.printStackTrace(new PrintWriter(sw));
            assertTrue("An XMLMarshalException was thrown unexpectedly\n" + sw.toString(), false);
            return;
        }
        assertEquals(controlObject, unmarshalledObject);
    }

    /**
     * Set the validation mode to DTDVALIDATION and try to unmarshal a file which is NOT valid against the DTD
     * An XMLMarshalException should occur
     */
    public void testDTDValidatingFails() {
        try {
            unmarshaller.setEntityResolver(new TestEntityResolver());
            unmarshaller.setValidationMode(XMLUnmarshaller.DTD_VALIDATION);
            ErrorHdlr err = new ErrorHdlr();
            unmarshaller.setErrorHandler(err);
            InputStream streamToUnmarshal = ClassLoader.getSystemResourceAsStream(DTD_VALIDATING_FAILS_RESOURCE);
            Object unmarshalledObject = unmarshaller.unmarshal(streamToUnmarshal);
            unmarshaller.setValidationMode(originalMode);
            assertEquals(controlObject, unmarshalledObject);
        } catch (XMLMarshalException exception) {
            StringWriter sw = new StringWriter();
            exception.printStackTrace(new PrintWriter(sw));
            assertTrue("An unexpected XMLMarshalException was caught\n" + sw.toString(), exception.getErrorCode() == XMLMarshalException.UNMARSHAL_EXCEPTION);
            return;
        }
        assertTrue(false);
    }

    //SCHEMA VALIDATING TEST=========================================================================================

    /**
     * Set the validation mode to SCHEMA_VALIDATION and try to unmarshal a file which does not have a schema specified
     * No exception should occur
     */
    public void testSchemaValidatingSchemaNotSet() {
        unmarshaller.setValidationMode(XMLUnmarshaller.SCHEMA_VALIDATION);
        ErrorHdlr err = new ErrorHdlr();
        unmarshaller.setErrorHandler(err);
        InputStream streamToUnmarshal = ClassLoader.getSystemResourceAsStream(NO_HEADER_RESOURCE);
        Object unmarshalledObject;
        try {
            unmarshalledObject = unmarshaller.unmarshal(streamToUnmarshal);
        } catch (XMLMarshalException exception) {
            StringWriter sw = new StringWriter();
            exception.printStackTrace(new PrintWriter(sw));
            assertTrue("An XMLMarshalException was thrown unexpectedly\n " + sw.toString(), false);
            return;
        }
        assertEquals(controlObject, unmarshalledObject);
    }

    /**
     * Set the validation mode to SCHEMA_VALIDATION and try to unmarshal a file which is NOT valid against its schema
     * An XMLMarshalException should occur
     */
    public void testSchemaURLValidatingFails() {
        unmarshaller.setValidationMode(XMLUnmarshaller.SCHEMA_VALIDATION);
        ErrorHdlr err = new ErrorHdlr();
        unmarshaller.setErrorHandler(err);
        InputStream streamToUnmarshal = ClassLoader.getSystemResourceAsStream(SCHEMA_VALIDATING_FAILS_RESOURCE);
        try {
            unmarshaller.unmarshal(streamToUnmarshal);
        } catch (XMLMarshalException exception) {
            StringWriter sw = new StringWriter();
            exception.printStackTrace(new PrintWriter(sw));
            assertTrue("An unexpected XMLMarshalException was caught\n" + sw.toString(), exception.getErrorCode() == XMLMarshalException.UNMARSHAL_EXCEPTION);
            return;
        }
        assertTrue("An XMLMarshalException should have been caught but wasn't.", false);
    }

    /**
     * Set the validation mode to SCHEMA_VALIDATION and try to unmarshal a file which is valid against its schema
     * No exception should occur
     */
    public void testSchemaURLValidatingPasses() {
        unmarshaller.setValidationMode(XMLUnmarshaller.SCHEMA_VALIDATION);
        ErrorHdlr err = new ErrorHdlr();
        unmarshaller.setErrorHandler(err);
        InputStream streamToUnmarshal = ClassLoader.getSystemResourceAsStream(SCHEMA_VALIDATING_PASSES_RESOURCE);
        Object unmarshalledObject;
        try {
            unmarshalledObject = unmarshaller.unmarshal(streamToUnmarshal);
        } catch (XMLMarshalException exception) {
            StringWriter sw = new StringWriter();
            exception.printStackTrace(new PrintWriter(sw));
            assertTrue("An XMLMarshalException was thrown unexpectedly\n" + sw.toString(), false);
            return;
        }
        assertEquals(controlObject, unmarshalledObject);
    }

    //=========================================================================================
    public class TestEntityResolver implements org.xml.sax.EntityResolver {
        private final String DTD_NAME = "org/eclipse/persistence/testing/oxm/xmlmarshaller/Car.dtd";

        public TestEntityResolver() {
        }

        @Override
        public InputSource resolveEntity(String publicId, String systemId) {
            InputStream localDtdStream = ClassLoader.getSystemResourceAsStream(DTD_NAME);
            if (localDtdStream != null) {
                return new InputSource(localDtdStream);
            }
            return null;
        }
    }

    /**
     * Error handler implementation to capture DTD/Schema validation
     * errors/warnings.
     */
    class ErrorHdlr implements ErrorHandler {
        private boolean errorHasOccurred;
        private boolean fatalErrorHasOccurred;
        private boolean warningHasOccurred;
        ErrorHdlr() {
            errorHasOccurred = false;
            fatalErrorHasOccurred = false;
            warningHasOccurred = false;
        }
        @Override
        public void error(SAXParseException arg0) throws SAXException {
            errorHasOccurred = true;
            throw arg0;
        }
        @Override
        public void fatalError(SAXParseException arg0) throws SAXException {
            fatalErrorHasOccurred = true;
            throw arg0;
        }
        @Override
        public void warning(SAXParseException arg0) throws SAXException {
            warningHasOccurred = true;
            throw arg0;
        }
        boolean validationErrorsOccurred() {
            return errorHasOccurred || fatalErrorHasOccurred || warningHasOccurred;
        }
    }
}
