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

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.lang.reflect.Type;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import jakarta.xml.bind.JAXBElement;
import jakarta.xml.bind.JAXBException;
import jakarta.xml.bind.Unmarshaller;
import jakarta.xml.bind.helpers.DefaultValidationEventHandler;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLStreamReader;
import javax.xml.transform.Source;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamSource;

import org.eclipse.persistence.jaxb.JAXBContext.JAXBContextInput;
import org.eclipse.persistence.jaxb.JAXBContext.ContextPathInput;
import org.eclipse.persistence.jaxb.JAXBContext.TypeMappingInfoInput;
import org.eclipse.persistence.jaxb.compiler.CompilerHelper;
import org.eclipse.persistence.jaxb.compiler.XMLProcessor;
import org.eclipse.persistence.jaxb.metadata.MetadataSource;
import org.eclipse.persistence.jaxb.xmlmodel.XmlBindings;
import org.eclipse.persistence.oxm.MediaType;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;

/**
 * <p>
 * <b>Purpose:</b>An EclipseLink specific JAXBContextFactory. This class can be specified in a
 * jaxb.properties file to make use of EclipseLink's JAXB 2.1 implementation.
 * <p>
 * <b>Responsibilities:</b>
 * <ul>
 * <li>Create a JAXBContext from an array of Classes and a Properties object</li>
 * <li>Create a JAXBContext from a context path and a classloader</li>
 * </ul>
 * <p>
 * This class is the entry point into in EclipseLink's JAXB 2.1 Runtime. It provides the required
 * factory methods and is invoked by jakarta.xml.bind.JAXBContext.newInstance() to create new
 * instances of JAXBContext. When creating a JAXBContext from a contextPath, the list of classes is
 * derived either from an ObjectFactory class (schema-to-java) or a jaxb.index file
 * (java-to-schema).
 *
 * @author mmacivor
 * @see jakarta.xml.bind.JAXBContext
 * @see org.eclipse.persistence.jaxb.JAXBContext
 * @see org.eclipse.persistence.jaxb.compiler.Generator
 */
public class JAXBContextFactory {

    /**
     * @deprecated As of release 2.4, replaced by JAXBContextProperties.OXM_METADATA_SOURCE
     * @see org.eclipse.persistence.jaxb.JAXBContextProperties#OXM_METADATA_SOURCE
     */
    @Deprecated
    public static final String ECLIPSELINK_OXM_XML_KEY = "eclipselink-oxm-xml";
    /**
     * @deprecated As of release 2.4, replaced by JAXBContextProperties.DEFAULT_TARGET_NAMESPACE
     * @see org.eclipse.persistence.jaxb.JAXBContextProperties#DEFAULT_TARGET_NAMESPACE
     */
    @Deprecated
    public static final String DEFAULT_TARGET_NAMESPACE_KEY = "defaultTargetNamespace";
    /**
     * @deprecated As of release 2.4, replaced by JAXBContextProperties.ANNOTATION_HELPER
     * @see org.eclipse.persistence.jaxb.JAXBContextProperties#ANNOTATION_HELPER
     */
    @Deprecated
    public static final String ANNOTATION_HELPER_KEY = "annotationHelper";
    public static final String PKG_SEPARATOR = ".";

    /**
     * Create a JAXBContext on the array of Class objects.  The JAXBContext will
     * also be aware of classes reachable from the classes in the array.
     */
    public static jakarta.xml.bind.JAXBContext createContext(Class<?>[] classesToBeBound, Map<String, Object> properties) throws JAXBException {
        ClassLoader loader = null;
        if (classesToBeBound.length > 0) {
            loader = classesToBeBound[0].getClassLoader();
        }
        return createContext(classesToBeBound, properties, loader);
    }

    /**
     * Create a JAXBContext on the array of Class objects.  The JAXBContext will
     * also be aware of classes reachable from the classes in the array.
     */
    public static jakarta.xml.bind.JAXBContext createContext(Class<?>[] classesToBeBound, Map<String, Object> properties, ClassLoader classLoader) throws JAXBException {
        Type[] types = new Type[classesToBeBound.length];
        System.arraycopy(classesToBeBound, 0, types, 0, classesToBeBound.length);
        return createContext(types, properties, classLoader);
    }

    /**
     * Create a JAXBContext on context path.  The JAXBContext will
     * also be aware of classes reachable from the classes on the context path.
     */
    public static jakarta.xml.bind.JAXBContext createContext(String contextPath, ClassLoader classLoader) throws JAXBException {
        return createContext(contextPath, classLoader, null);
    }

    /**
     * Create a JAXBContext on context path.  The JAXBContext will
     * also be aware of classes reachable from the classes on the context path.
     */
    public static jakarta.xml.bind.JAXBContext createContext(String contextPath, ClassLoader classLoader, Map<String, Object> properties) throws JAXBException {
        JAXBContextInput contextInput = new ContextPathInput(contextPath, properties, classLoader);
        JAXBContext context = new JAXBContext(contextInput);
        if (context.isRefreshable()) {
            context.postInitialize();
        }
        return context;
    }

    /**
     * Create a JAXBContext on the array of Type objects.  The JAXBContext will
     * also be aware of classes reachable from the types in the array.  The
     * preferred means of creating a Type aware JAXBContext is to create the
     * JAXBContext with an array of TypeMappingInfo objects.
     */
    public static jakarta.xml.bind.JAXBContext createContext(Type[] typesToBeBound, Map<String, Object> properties, ClassLoader classLoader) throws JAXBException {
        Map<Type, TypeMappingInfo> typeToTypeMappingInfo = new HashMap<Type, TypeMappingInfo>();
        TypeMappingInfo[] typeMappingInfos = new TypeMappingInfo[typesToBeBound.length];
        for(int i = 0; i < typesToBeBound.length; i++) {
            TypeMappingInfo tmi = new TypeMappingInfo();
            tmi.setType(typesToBeBound[i]);
            typeToTypeMappingInfo.put(typesToBeBound[i], tmi);
            typeMappingInfos[i] = tmi;
        }

        JAXBContext context = (JAXBContext)createContext(typeMappingInfos, properties, classLoader);
        context.setTypeToTypeMappingInfo(typeToTypeMappingInfo);

        return context;
    }

    /**
     * Create a JAXBContext on the array of TypeMappingInfo objects.  The
     * JAXBContext will also be aware of classes reachable from the types in the
     * array.  This is the preferred means of creating a Type aware JAXBContext.
     */
    public static jakarta.xml.bind.JAXBContext createContext(TypeMappingInfo[] typesToBeBound, Map<String, Object> properties, ClassLoader classLoader) throws JAXBException {
        JAXBContextInput contextInput = new TypeMappingInfoInput(typesToBeBound, properties, classLoader);
        JAXBContext context = new JAXBContext(contextInput);
        if (context.isRefreshable()) {
            context.postInitialize();
        }
        return context;
    }

    /**
     * <p>Convenience method for processing a properties map and creating a map of
     * package names to XmlBindings instances.</p>
     *
     * <p>It is assumed that the given map's key will be JAXBContextProperties.OXM_METADATA_SOURCE,
     * and the value will be:</p>
     * <pre>
     * 1)  {@literal Map<String, Object>}
     *     - Object is one of those listed in 3) below
     * 2)  {@literal List<Object>}
     *     - Object is one of those listed in 3) below
     *     - Bindings file must contain package-name attribute on
     *       xml-bindings element
     * 3)  One of:
     *     - java.io.File
     *     - java.io.InputStream
     *     - java.io.Reader
     *     - java.lang.String
     *     - java.net.URL
     *     - javax.xml.stream.XMLEventReader
     *     - javax.xml.stream.XMLStreamReader
     *     - javax.xml.transform.Source
     *     - org.eclipse.persistence.jaxb.metadata.MetadataSource
     *     - org.w3c.dom.Node
     *     - org.xml.sax.InputSource
     *
     *     - Bindings file must contain package-name attribute on
     *       xml-bindings element
     * </pre>
     */
    public static Map<String, XmlBindings> getXmlBindingsFromProperties(Map<String, Object> properties, ClassLoader classLoader) {
        Map<String, List<XmlBindings>> bindings = new HashMap<String, List<XmlBindings>>();
        Object value = null;
        if (properties != null) {
            if ((value = properties.get(JAXBContextProperties.OXM_METADATA_SOURCE)) == null) {
                // try looking up the 'old' metadata source key
                value = properties.get(ECLIPSELINK_OXM_XML_KEY);
            }
        }
        if (value != null) {
            // handle Map<String, Object>
            if (value instanceof Map) {
                Map<String, Object> metadataFiles = null;
                try {
                    metadataFiles = (Map<String, Object>) value;
                } catch (ClassCastException x) {
                    throw org.eclipse.persistence.exceptions.JAXBException.incorrectValueParameterTypeForOxmXmlKey();
                }
                for(Entry<String, Object> entry : metadataFiles.entrySet()) {
                    String key = null;
                    List<XmlBindings> xmlBindings = new ArrayList<XmlBindings>();
                    try {
                        key = entry.getKey();
                        if (key == null) {
                            throw org.eclipse.persistence.exceptions.JAXBException.nullMapKey();
                        }
                    } catch (ClassCastException cce) {
                        throw org.eclipse.persistence.exceptions.JAXBException.incorrectKeyParameterType();
                    }
                    Object metadataSource = entry.getValue();
                    if (metadataSource == null) {
                        throw org.eclipse.persistence.exceptions.JAXBException.nullMetadataSource(key);
                    }
                    if(metadataSource instanceof List) {
                        for(Object next: (List)metadataSource) {
                            XmlBindings binding = getXmlBindings(next, classLoader, properties);
                            if(binding != null) {
                                xmlBindings.add(binding);
                            }
                        }
                    } else {
                        XmlBindings binding = getXmlBindings(metadataSource, classLoader, properties);
                        if(binding != null) {
                            xmlBindings.add(binding);
                        }
                    }
                    if (xmlBindings != null) {
                        bindings.put(key, xmlBindings);
                    }
                }
                // handle List<Object>
            } else if (value instanceof List) {
                for (Object metadataSource : (List) value) {
                    if (metadataSource == null) {
                        throw org.eclipse.persistence.exceptions.JAXBException.nullMetadataSource();
                    }
                    bindings = processBindingFile(bindings, metadataSource, classLoader, properties);
                }
            // handle Object
            } else {
                bindings = processBindingFile(bindings, value, classLoader, properties);
            }
        }
        Map<String, XmlBindings> mergedBindings = new HashMap<String, XmlBindings>(bindings.size());
        for(Entry<String, List<XmlBindings>> next:bindings.entrySet()) {
            mergedBindings.put(next.getKey(), XMLProcessor.mergeXmlBindings(next.getValue()));
        }
        return mergedBindings;
    }

    /**
     * Processing a bindings file and add it to a given Map of package name to binding
     * files.
     *
     * @param originalBindings Map of bindings to be updated
     * @param bindingHandle handle to bindings file
     */
    private static Map<String, List<XmlBindings>> processBindingFile(Map<String, List<XmlBindings>> originalBindings, Object bindingHandle, ClassLoader classLoader, Map<String, Object> properties) {
        XmlBindings binding = getXmlBindings(bindingHandle, classLoader, properties);
        if (binding != null) {
            String key = binding.getPackageName();
            if (key.equals(XMLProcessor.DEFAULT)) {
                throw org.eclipse.persistence.exceptions.JAXBException.packageNotSetForBindingException();
            }
            List<XmlBindings> existingBindings = originalBindings.get(key);
            if(existingBindings != null) {
                existingBindings.add(binding);
            } else {
                existingBindings = new ArrayList<XmlBindings>();
                existingBindings.add(binding);
                originalBindings.put(key, existingBindings);
            }
        }
        return originalBindings;
    }

    /**
     * Convenience method for creating an XmlBindings object based on a given Object. The method
     * will load the eclipselink metadata model and unmarshal the Object. This assumes that the
     * Object represents the eclipselink-oxm.xml metadata file to be unmarshalled.
     *
     * @param metadata assumed to be one of:  File, InputSource, InputStream, Reader, Source
     */
    private static XmlBindings getXmlBindings(Object metadata, ClassLoader classLoader, Map<String, Object> properties) {
    JAXBContext jaxbContext = CompilerHelper.getXmlBindingsModelContext();
        InputStream openedStream = null;

    try {
            Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
            unmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, MediaType.APPLICATION_XML);
            unmarshaller.setProperty(UnmarshallerProperties.AUTO_DETECT_MEDIA_TYPE, true);
            unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, false);
            unmarshaller.setEventHandler(new DefaultValidationEventHandler());
            if (metadata instanceof MetadataSource){
                return ((MetadataSource)metadata).getXmlBindings(properties, classLoader);
            }
            JAXBElement<XmlBindings> bindingsJaxbElement = null;
            if (metadata instanceof XMLEventReader) {
                bindingsJaxbElement=  unmarshaller.unmarshal((XMLEventReader) metadata, XmlBindings.class);
            } else if (metadata instanceof XMLStreamReader) {
                bindingsJaxbElement =  unmarshaller.unmarshal((XMLStreamReader) metadata, XmlBindings.class);
            } else {
                Source source = null;
                if(metadata instanceof File){
                    source = new StreamSource(new FileInputStream((File) metadata));
                } else if(metadata instanceof InputSource){
                    if(((InputSource)metadata).getByteStream() != null){
                        source = new StreamSource(((InputSource) metadata).getByteStream());
                    }else if(((InputSource)metadata).getCharacterStream() != null){
                        source = new StreamSource(((InputSource) metadata).getCharacterStream());
                    }
                }else if(metadata instanceof InputStream){
                    source = new StreamSource((InputStream) metadata);
                } else if (metadata instanceof Node) {
                    source = new DOMSource((Node) metadata);
                } else if(metadata instanceof Reader){
                    source = new StreamSource((Reader) metadata);
                } else if(metadata instanceof Source){
                    source = (Source)metadata;
                } else if (metadata instanceof URL) {
                    openedStream = ((URL) metadata).openStream();
                    source = new StreamSource(openedStream);
                } else if (metadata instanceof String) {
                    StreamSource streamSource = new StreamSource((String)metadata);
                    try{
                           bindingsJaxbElement = unmarshaller.unmarshal(streamSource, XmlBindings.class);
                    }catch(JAXBException e){
                        openedStream = classLoader.getResourceAsStream((String)metadata);
                        if(openedStream != null){
                            bindingsJaxbElement = unmarshaller.unmarshal(new StreamSource(openedStream), XmlBindings.class);
                        }else{
                            throw org.eclipse.persistence.exceptions.JAXBException.couldNotUnmarshalMetadata(e);
                        }
                    }
                } else{
                    throw org.eclipse.persistence.exceptions.JAXBException.incorrectValueParameterTypeForOxmXmlKey();
                }
                if(bindingsJaxbElement == null){
                    if(source == null){
                        throw org.eclipse.persistence.exceptions.JAXBException.incorrectValueParameterTypeForOxmXmlKey();
                    }else{
                        bindingsJaxbElement = unmarshaller.unmarshal(source, XmlBindings.class);
                    }
                }
            }
            if(bindingsJaxbElement != null){
                return bindingsJaxbElement.getValue();
            }
            throw org.eclipse.persistence.exceptions.JAXBException.incorrectValueParameterTypeForOxmXmlKey();
        }catch(jakarta.xml.bind.JAXBException ex){
            throw org.eclipse.persistence.exceptions.JAXBException.couldNotUnmarshalMetadata(ex);
        }catch(IOException ioException){
             throw org.eclipse.persistence.exceptions.JAXBException.couldNotUnmarshalMetadata(ioException);
        }finally{
            if(openedStream != null){
                try {
                    openedStream.close();
                } catch (IOException e) {
                    throw org.eclipse.persistence.exceptions.JAXBException.couldNotUnmarshalMetadata(e);
                }
            }
        }
    }
}
