/*
 * Copyright (c) 1998, 2020 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 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 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 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 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 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 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
     * @param classLoader
     * @return
     */
    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);
                }
            }
        }
    }
}
