/*
 * 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 jakarta.xml.bind.PropertyException;
import jakarta.xml.bind.Unmarshaller;
import jakarta.xml.bind.ValidationException;

import java.io.File;

import junit.framework.TestCase;

import org.eclipse.persistence.jaxb.JAXBContext;
import org.eclipse.persistence.jaxb.JAXBValidator;
import org.eclipse.persistence.testing.jaxb.xmlmarshaller.Address;
import org.eclipse.persistence.testing.jaxb.xmlmarshaller.Badge;
import org.eclipse.persistence.testing.jaxb.xmlmarshaller.Employee;
import org.eclipse.persistence.testing.jaxb.xmlmarshaller.JAXBSAXTestSuite;
import org.eclipse.persistence.testing.jaxb.xmlmarshaller.Job;
import org.eclipse.persistence.testing.jaxb.xmlmarshaller.Job2;
import org.eclipse.persistence.testing.jaxb.xmlmarshaller.Phone;
import org.eclipse.persistence.testing.oxm.xmlmarshaller.Car;

public class ValidatorTestCases extends TestCase {
    private final static String CONTROL_XML_FILE_NAME = "org/eclipse/persistence/testing/oxm/jaxb/Employee_WithAddresses.xml";
    private final static String CONTROL_XML_ADDRESS_FAIL = "org/eclipse/persistence/testing/oxm/jaxb/Employee_WithAddresses_Fail.xml";
    private final static String CONTROL_XML_INHERITANCE_FILE_NAME = "org/eclipse/persistence/testing/oxm/jaxb/Employee_WithPOBoxAddress.xml";
    private final static String CONTROL_JOB_FILE_NAME = "org/eclipse/persistence/testing/oxm/jaxb/Job_Empty.xml";
    private JAXBContext jaxbContext;
    private JAXBValidator validator;
    private Unmarshaller unmarshaller;
    private String contextPath;

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

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

        jaxbContext = (JAXBContext) JAXBContext.newInstance(contextPath);
        validator = jaxbContext.createValidator();
        unmarshaller = jaxbContext.createUnmarshaller();
    }

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

        assertTrue("Object did not validate.", validator.validateRoot(testObject));
    }

    public void testValidateElement() throws Exception {
        boolean caughtException = false;
        File file = new File(ClassLoader.getSystemResource(CONTROL_XML_FILE_NAME).getFile());
        Employee employee = (Employee)unmarshaller.unmarshal(file);

        try {
            validator.validate(employee);
        } catch (ValidationException xmlpe) {
            caughtException = true;
        }
        assertFalse("Employee object did not validate.", caughtException);
    }

    public void testValidateComplexType() throws Exception {
        boolean caughtException = false;
        File file = new File(ClassLoader.getSystemResource(CONTROL_XML_FILE_NAME).getFile());
        Employee employee = (Employee)unmarshaller.unmarshal(file);

        try {
            validator.validate(employee.getHomeAddress());
        } catch (ValidationException xmlpe) {
            caughtException = true;
        }
        assertFalse("Address object did not validate.", caughtException);
    }

    public void testValidateInheritanceComplexType() throws Exception {
        boolean caughtException = false;
        File file = new File(ClassLoader.getSystemResource(CONTROL_XML_INHERITANCE_FILE_NAME).getFile());
        Employee employee = (Employee)unmarshaller.unmarshal(file);

        try {
            validator.validate(employee.getHomeAddress());
        } catch (org.eclipse.persistence.platform.xml.XMLPlatformException xmlpe) {
            caughtException = true;
        }
        assertFalse("Address object did not validate.", caughtException);
    }

    public void testValidateSimpleType() throws Exception {
        boolean caughtException = false;
        File file = new File(ClassLoader.getSystemResource(CONTROL_XML_FILE_NAME).getFile());
        Employee employee = (Employee)unmarshaller.unmarshal(file);

        try {
            validator.validate(employee.getPhone());
        } catch (ValidationException xmlpe) {
            caughtException = true;
        }
        assertFalse("Phone object did not validate.", caughtException);
    }

    public void testValidateSimpleTypeID() throws Exception {
        boolean caughtException = false;
        File file = new File(ClassLoader.getSystemResource(CONTROL_XML_FILE_NAME).getFile());
        Employee employee = (Employee)unmarshaller.unmarshal(file);

        try {
            validator.validate(employee.getBadge());
        } catch (ValidationException xmlpe) {
            caughtException = true;
        }
        assertFalse("Badge object did not validate.", caughtException);
    }

    public void testValidateElementException() throws Exception {
        boolean caughtException = false;

        try {
            Employee employee = new Employee();
            validator.validate(employee);
        } catch (ValidationException xmlpe) {
            caughtException = true;
        } catch (Exception ex) {
        }
        assertTrue("JAXBValidator did not throw ValidationException as expected.", caughtException);
    }

    public void testValidateAgainstWrongSchema() throws Exception {
        Job2 job = new Job2();

        try {
            validator.validate(job);
        } catch (ValidationException validationException) {
            assertTrue(true);
            return;
        } catch (Exception ex) {
            fail("An incorrect Exception was thrown");
            return;
        }
        fail("JAXBValidator did not throw ValidationException as expected.");
    }

    public void testValidateNestedComplexType() throws Exception {
        Job job = new Job();

        try {
            validator.validate(job);
        } catch (Exception exception) {
            fail("JAXBValidator threw an unexpected exception." + exception.getMessage());
            return;
        }
    }

    public void testValidateComplexTypeException() throws Exception {
        boolean caughtException = false;

        try {
            Address address = new Address();
            address.setStreet("613 Cedar Lane");
            address.setCity("Bangor");
            address.setState("Maine");
            validator.validate(address);
        } catch (ValidationException xmlpe) {
            caughtException = true;
        } catch (Exception ex) {
        }
        assertTrue("JAXBValidator did not throw ValidationException as expected.", caughtException);
    }

    public void testValidateSimpleTypeException() throws Exception {
        boolean caughtException = false;

        try {
            Phone phone = new Phone();
            phone.setNumber("12345678901");
            validator.validate(phone);
        } catch (ValidationException xmlpe) {
            caughtException = true;
        } catch (Exception ex) {
        }
        assertTrue("JAXBValidator did not throw ValidationException as expected.", caughtException);
    }

    public void testValidateSimpleTypeIDException() throws Exception {
        boolean caughtException = false;

        try {
            Badge badge = new Badge();
            badge.setNumber("11");
            validator.validate(badge);
        } catch (ValidationException xmlpe) {
            caughtException = true;
        } catch (Exception ex) {
        }
        assertTrue("JAXBValidator did not throw ValidationException as expected.", caughtException);
    }

    public void testValidationEventHandler() throws Exception {
        boolean caughtException = false;
        File file = new File(ClassLoader.getSystemResource(CONTROL_XML_ADDRESS_FAIL).getFile());
        Employee employee = (Employee)unmarshaller.unmarshal(file);

        try {
            validator.setEventHandler(new ValidationEventHandlerImpl());
            validator.validate(employee.getHomeAddress());
        } catch (ValidationException xmlpe) {
            caughtException = true;
        } catch (Exception ex) {
        }
        assertFalse("The event handler did not consume the exceptions as expected.", caughtException);
    }

    public void testValidateException() {
        boolean caughtException = false;
        try {
            validator.validate(null);
        } catch (IllegalArgumentException e) {
            caughtException = true;
        } catch (Exception e) {
        }
        assertTrue("JAXBValidator did not throw IllegalArgumentException as expected.", caughtException);
    }

    public void testValidateRootNull() {
        boolean caughtException = false;
        try {
            validator.validateRoot(null);
        } catch (IllegalArgumentException e) {
            caughtException = true;
        } catch (Exception e) {
        }
        assertTrue("JAXBValidator did not throw IllegalArgumentException as expected.", caughtException);
    }

    public void testValidateRootException() {
        boolean caughtException = false;
        try {
            Car car = new Car();
            validator.validateRoot(car);
        } catch (ValidationException e) {
            assertTrue(true);
            return;
        } catch (Exception e) {
            fail("JAXBValidator did not throw ValidationException as expected.");
            return;
        }
        assertTrue("JAXBValidator did not any exceptions, expected a ValidationException.", caughtException);
    }

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

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

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

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

    //=============================== Inner class for eventhandler test =================//
    class ValidationEventHandlerImpl implements jakarta.xml.bind.ValidationEventHandler {
        @Override
        public boolean handleEvent(jakarta.xml.bind.ValidationEvent param1) {
            return true;
        }
    }
}
