/*
 * Copyright (c) 2011, 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:
// dmccann - August 5/2010 - 2.2 - Initial implementation
package org.eclipse.persistence.testing.jaxb.externalizedmetadata.mappings.xmltransformation;

import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

import jakarta.xml.bind.JAXBContext;
import jakarta.xml.bind.JAXBException;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;

import org.eclipse.persistence.internal.jaxb.JaxbClassLoader;
import org.eclipse.persistence.jaxb.JAXBContextFactory;
import org.eclipse.persistence.jaxb.JAXBContextProperties;
import org.eclipse.persistence.jaxb.compiler.Generator;
import org.eclipse.persistence.jaxb.javamodel.reflection.JavaModelImpl;
import org.eclipse.persistence.jaxb.javamodel.reflection.JavaModelInputImpl;
import org.eclipse.persistence.jaxb.xmlmodel.XmlBindings;

import junit.framework.TestCase;


public class JAXBContextTransformationMappingTestCases extends TestCase{
    private static final String PATH = "org/eclipse/persistence/testing/jaxb/externalizedmetadata/mappings/xmltransformation/";

    private static final String METADATA_FILE_NO_CLASS_OR_METHOD = PATH + "no-class-or-method.xml";
    private static final String METADATA_FILE_CLASS_AND_METHOD = PATH + "both-class-and-method.xml";
    private static final String METADATA_FILE_BAD_METHOD = PATH + "bad-method.xml";
    private static final String METADATA_FILE_BAD_CLASS = PATH + "bad-class.xml";

    /**
     * Test exception handling:  in this case both a transformer class and
     * method name have been set.  An exception should be thrown.
     *
     * Negative test.
     */
    public void testBothClassAndMethod() {
        InputStream inputStream = ClassLoader.getSystemResourceAsStream(METADATA_FILE_CLASS_AND_METHOD);

        HashMap<String, Source> metadataSourceMap = new HashMap<>();
        metadataSourceMap.put("org.eclipse.persistence.testing.jaxb.externalizedmetadata.mappings.xmltransformation", new StreamSource(inputStream));
        Map<String, Object> properties = new HashMap<>();
        properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, metadataSourceMap);

        try {
            JAXBContext jaxbContext = JAXBContextFactory.createContext(new Class<?>[]{Employee.class}, properties, Thread.currentThread().getContextClassLoader());
        } catch (JAXBException e) {
            return;
        }
        fail("The expected exception was never thrown.");
    }

    /**
     * Test exception handling:  in this case no transformer class or
     * method name has been set.  An exception should be thrown.
     *
     * Negative test.
     */
    public void testNoClassOrMethod() {
        InputStream inputStream = ClassLoader.getSystemResourceAsStream(METADATA_FILE_NO_CLASS_OR_METHOD);

        HashMap<String, Source> metadataSourceMap = new HashMap<>();
        metadataSourceMap.put("org.eclipse.persistence.testing.jaxb.externalizedmetadata.mappings.xmltransformation", new StreamSource(inputStream));
        Map<String, Object> properties = new HashMap<>();
        properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, metadataSourceMap);

       try {
            JAXBContext jaxbContext = JAXBContextFactory.createContext(new Class<?>[]{Employee.class}, properties, Thread.currentThread().getContextClassLoader());

        } catch (JAXBException e) {
            return;
        }
        fail("The expected exception was never thrown.");
    }

    /**
     * Test exception handling:  in this case the method name that has been
     * set is invalid (wrong number or type of params. An exception should
     * be thrown.
     *
     * Negative test.
     */

    public void testInvalidMethod() {
        InputStream inputStream = ClassLoader.getSystemResourceAsStream(METADATA_FILE_BAD_METHOD);

        HashMap<String, Source> metadataSourceMap = new HashMap<>();
        metadataSourceMap.put("org.eclipse.persistence.testing.jaxb.externalizedmetadata.mappings.xmltransformation", new StreamSource(inputStream));
        Map<String, Object> properties = new HashMap<>();
        properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, metadataSourceMap);

        int exceptionCount = 0;
        try {
            JAXBContext jaxbContext = JAXBContextFactory.createContext(new Class<?>[]{Employee.class}, properties, Thread.currentThread().getContextClassLoader());

        } catch (JAXBException e) {
            exceptionCount++;
        }
        assertTrue("The expected exception was never thrown.", exceptionCount > 0);
        exceptionCount--;
        // test exception from SchemaGenerator
        try {
            Map<String, XmlBindings> bindings = JAXBContextFactory.getXmlBindingsFromProperties(properties, Thread.currentThread().getContextClassLoader());
            JavaModelInputImpl jModelInput = new JavaModelInputImpl(new Class<?>[]{Employee.class}, new JavaModelImpl(new JaxbClassLoader(Thread.currentThread().getContextClassLoader(), new Class<?>[]{Employee.class})));
            Generator generator = new Generator(jModelInput, bindings, Thread.currentThread().getContextClassLoader(), "", false);
            generator.generateSchema();
        } catch (Exception e) {
            exceptionCount++;
        }
        assertTrue("The expected exception was never thrown.", exceptionCount > 0);
    }

    /**
     * Test exception handling:  in this case an invalid transformer class
     * has been set.  An exception should be thrown.
     *
     * Negative test.
     */

    public void testInvalidTransformerClass() {
        InputStream inputStream = ClassLoader.getSystemResourceAsStream(METADATA_FILE_BAD_CLASS);

        HashMap<String, Source> metadataSourceMap = new HashMap<>();
        metadataSourceMap.put("org.eclipse.persistence.testing.jaxb.externalizedmetadata.mappings.xmltransformation", new StreamSource(inputStream));
        Map<String, Object> properties = new HashMap<>();
        properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, metadataSourceMap);

        int exceptionCount = 0;
        // test exception from MappingsGenerator
        try {
            JAXBContext jaxbContext = JAXBContextFactory.createContext(new Class<?>[]{Employee.class}, properties, Thread.currentThread().getContextClassLoader());

        } catch (JAXBException e) {
            exceptionCount++;
        }
        assertTrue("The expected exception was never thrown.", exceptionCount > 0);
        exceptionCount--;
        // test exception from SchemaGenerator
        try {
            Map<String, XmlBindings> bindings = JAXBContextFactory.getXmlBindingsFromProperties(properties, Thread.currentThread().getContextClassLoader());
            JavaModelInputImpl jModelInput = new JavaModelInputImpl(new Class<?>[]{Employee.class}, new JavaModelImpl(new JaxbClassLoader(Thread.currentThread().getContextClassLoader(), new Class<?>[]{Employee.class})));
            Generator generator = new Generator(jModelInput, bindings, Thread.currentThread().getContextClassLoader(), "", false);
            generator.generateSchema();
        } catch (Exception e) {
            exceptionCount++;
        }
        assertTrue("The expected exception was never thrown.", exceptionCount > 0);
    }

}
