/*
 * 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:
// dmccann - July 29/2009 - 2.0 - Initial implementation
package org.eclipse.persistence.testing.jaxb.externalizedmetadata.exceptions.contextfactory;

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

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

import org.eclipse.persistence.exceptions.JAXBException;
import org.eclipse.persistence.jaxb.JAXBContextFactory;
import org.eclipse.persistence.testing.oxm.OXTestCase;

/**
 * Tests externalized metadata processor exception handling.
 *
 */
public class ExceptionHandlingTestCases extends OXTestCase {

    private static final String CONTEXT_PATH = "org.eclipse.persistence.testing.jaxb.externalizedmetadata.exceptions.contextfactory";
    private static final String PATH = "org/eclipse/persistence/testing/jaxb/externalizedmetadata/exceptions/contextfactory/";

    /**
     * This is the preferred (and only) constructor.
     *
     * @param name
     */
    public ExceptionHandlingTestCases(String name) {
        super(name);
    }

    /**
     * Tests an invalid parameter type by setting a Key of type Class as opposed
     * to String.
     *
     * Negative test.
     */
    public void testInvalidMapParameterTypeBadKey() {
        Map<Class, Source> metadataSourceMap = new HashMap<Class, Source>();
        metadataSourceMap.put(JAXBContextFactory.class, new StreamSource());
        Map<String, Map<Class, Source>> properties = new HashMap<String, Map<Class, Source>>();
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, metadataSourceMap);

        try {
            JAXBContextFactory.createContext(CONTEXT_PATH, getClass().getClassLoader(), properties);
        } catch (JAXBException e) {
            return;
        } catch (Exception x) {
        }
        fail("The expected JAXBException was not thrown.");
    }

    /**
     * Tests an invalid parameter type by setting a null Key.
     *
     * Negative test.
     */
    public void testInvalidMapParameterTypeNullKey() {
        Map<Class, Source> metadataSourceMap = new HashMap<Class, Source>();
        metadataSourceMap.put(null, new StreamSource());
        Map<String, Map<Class, Source>> properties = new HashMap<String, Map<Class, Source>>();
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, metadataSourceMap);

        try {
            JAXBContextFactory.createContext(CONTEXT_PATH, getClass().getClassLoader(), properties);
        } catch (JAXBException e) {
            return;
        } catch (Exception x) {
        }
        fail("The expected JAXBException was not thrown.");
    }

    /**
     * Tests an invalid parameter type by setting {@code Map<String, Class>} instead
     * of {@code Map<String, Source>}.
     *
     * Negative test.
     */
    public void testInvalidParameterTypeBadValue() {
        Map<String, Class> metadataSourceMap = new HashMap<String, Class>();
        metadataSourceMap.put(CONTEXT_PATH, this.getClass());
        Map<String, Map<String, Class>> properties = new HashMap<String, Map<String, Class>>();
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, metadataSourceMap);

        try {
            JAXBContextFactory.createContext(CONTEXT_PATH, getClass().getClassLoader(), properties);
        } catch (JAXBException e) {
            return;
        } catch (Exception x) {
        }
        fail("The expected JAXBException was not thrown.");
    }

    /**
     * Tests setting the metadata Source in the Map to null.
     *
     * Negative test.
     */
    public void testInvalidMapParameterTypeNullValue() {
        Map<String, Source> metadataSourceMap = new HashMap<String, Source>();
        metadataSourceMap.put(CONTEXT_PATH, null);
        Map<String, Map<String, Source>> properties = new HashMap<String, Map<String, Source>>();
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, metadataSourceMap);

        try {
            JAXBContextFactory.createContext(CONTEXT_PATH, getClass().getClassLoader(), properties);
        } catch (JAXBException e) {
            return;
        } catch (Exception x) {
        }
        fail("The expected JAXBException was not thrown.");
    }

    /**
     * Tests associating something other than {@code Map<String, Source>} with the key
     * 'eclipselink-oxm-xml' in the properties map.
     *
     * Negative test.
     */
    public void testInvalidParameterTypeBadOxmXmlValue() {
        Map<String, List<Integer>> properties = new HashMap<String, List<Integer>>();
        ArrayList<Integer> ints = new ArrayList<Integer>();
        ints.add(666);
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, ints);
        try {
            JAXBContextFactory.createContext(CONTEXT_PATH, getClass().getClassLoader(), properties);
        } catch (JAXBException e) {
            return;
        } catch (Exception x) {
        }
        fail("The expected JAXBException was not thrown.");
    }

    /**
     * Tests declaration of a non-existent class via eclipselink-oxm.xml
     *
     * Negative test.
     */
    public void testInvalidClassName() {
        String metadataFile = PATH + "eclipselink-oxm.xml";
        InputStream iStream = getClass().getClassLoader().getResourceAsStream(metadataFile);
        if (iStream == null) {
            fail("Couldn't load metadata file [" + metadataFile + "]");
        }

        HashMap<String, Source> metadataSourceMap = new HashMap<String, Source>();
        metadataSourceMap.put(CONTEXT_PATH, new StreamSource(iStream));
        Map<String, Map<String, Source>> properties = new HashMap<String, Map<String, Source>>();
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, metadataSourceMap);

        try {
            JAXBContextFactory.createContext(CONTEXT_PATH, getClass().getClassLoader(), properties);
        } catch (JAXBException e) {
            return;
        } catch (Exception x) {
        }
        fail("The expected JAXBException was not thrown.");
    }

    /**
     * Tests invalid eclipselink-oxm.xml exception handling.
     *
     * Negative test.
     */
    public void testInvalidMetadataFile() {
        String metadataFile = PATH + "eclipselink-oxm-invalid.xml";
        InputStream iStream = getClass().getClassLoader().getResourceAsStream(metadataFile);
        if (iStream == null) {
            fail("Couldn't load metadata file [" + metadataFile + "]");
        }

        HashMap<String, Source> metadataSourceMap = new HashMap<String, Source>();
        metadataSourceMap.put(CONTEXT_PATH, new StreamSource(iStream));
        Map<String, Map<String, Source>> properties = new HashMap<String, Map<String, Source>>();
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, metadataSourceMap);

        try {
            JAXBContextFactory.createContext(CONTEXT_PATH, getClass().getClassLoader(), properties);
        } catch (JAXBException e) {
            return;
        } catch (Exception x) {
            x.printStackTrace();
        }
        fail("The expected JAXBException was not thrown.");
    }

    /**
     * Tests declaration of a non-existent package
     *
     * Negative test.
     */
    public void testInvalidPackageAsKey() {
        String validPath = "org/eclipse/persistence/testing/jaxb/externalizedmetadata/jaxbcontextfactory/";
        String contextPath = "org.eclipse.persistence.testing.jaxb.externalizedmetadata.jaxbcontextfactory";
        String metadataFile = validPath + "eclipselink-oxm.xml";
        InputStream iStream = getClass().getClassLoader().getResourceAsStream(metadataFile);
        if (iStream == null) {
            fail("Couldn't load metadata file [" + metadataFile + "]");
        }

        HashMap<String, Source> metadataSourceMap = new HashMap<String, Source>();
        metadataSourceMap.put("java.util", new StreamSource(iStream));
        Map<String, Map<String, Source>> properties = new HashMap<String, Map<String, Source>>();
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, metadataSourceMap);

        try {
            JAXBContext ctx = JAXBContextFactory.createContext(contextPath, getClass().getClassLoader(), properties);
        } catch (jakarta.xml.bind.JAXBException e) {
            assertTrue(e.getLinkedException() instanceof JAXBException);
            assertEquals(JAXBException.JAVATYPE_NOT_ALLOWED_IN_BINDINGS_FILE, ((JAXBException)e.getLinkedException()).getErrorCode());
            return;
        }
        fail("The expected JAXBException was not thrown.");
    }

    /**
     * Tests declaration of a non-existent class via eclipselink-oxm.xml
     *
     * Negative test.
     */
    public void testInvalidLocation() {
        String metadataFile = PATH + "eclipselink_doesnt_exist-oxm.xml";
        InputStream iStream = getClass().getClassLoader().getResourceAsStream(metadataFile);

        HashMap<String, Source> metadataSourceMap = new HashMap<String, Source>();
        metadataSourceMap.put(CONTEXT_PATH, new StreamSource(iStream));
        Map<String, Map<String, Source>> properties = new HashMap<String, Map<String, Source>>();
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, metadataSourceMap);

        try {
            JAXBContextFactory.createContext(CONTEXT_PATH, getClass().getClassLoader(), properties);
        } catch (JAXBException e) {
            return;
        } catch (Exception x) {
            x.printStackTrace();
        }
        fail("The expected JAXBException was not thrown.");
    }

    /**
     * Tests declaration of a non-existent class via eclipselink-oxm.xml
     *
     * Negative test.
     */
    public void testInvalidLocation2() {
        String metadataFile = PATH + "eclipselink_doesnt_exist-oxm.xml";

        HashMap<String, Source> metadataSourceMap = new HashMap<String, Source>();
        metadataSourceMap.put(CONTEXT_PATH, new StreamSource(metadataFile));
        Map<String, Map<String, Source>> properties = new HashMap<String, Map<String, Source>>();
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, metadataSourceMap);

        try {
            JAXBContextFactory.createContext(CONTEXT_PATH, getClass().getClassLoader(), properties);
        } catch (JAXBException e) {
            return;
        } catch (Exception x) {
            x.printStackTrace();
        }
        fail("The expected JAXBException was not thrown.");
    }
}
