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

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.xml.XMLConstants;
import jakarta.xml.bind.SchemaOutputResolver;
import javax.xml.namespace.QName;

import org.eclipse.persistence.core.sessions.CoreProject;
import org.eclipse.persistence.internal.oxm.Constants;
import org.eclipse.persistence.internal.oxm.mappings.Descriptor;
import org.eclipse.persistence.internal.oxm.schema.SchemaModelProject;
import org.eclipse.persistence.internal.oxm.schema.model.Schema;
import org.eclipse.persistence.internal.oxm.schema.model.SchemaCompareByNamespace;
import org.eclipse.persistence.jaxb.TypeMappingInfo;
import org.eclipse.persistence.jaxb.javamodel.Helper;
import org.eclipse.persistence.jaxb.javamodel.JavaClass;
import org.eclipse.persistence.jaxb.javamodel.JavaModelInput;
import org.eclipse.persistence.jaxb.javamodel.reflection.JavaModelInputImpl;
import org.eclipse.persistence.jaxb.xmlmodel.XmlBindings;
import org.eclipse.persistence.logging.AbstractSessionLog;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.oxm.NamespaceResolver;
import org.eclipse.persistence.oxm.XMLContext;
import org.eclipse.persistence.oxm.XMLMarshaller;
import org.eclipse.persistence.sessions.Project;

/**
 * INTERNAL:
 *  <p><b>Purpose:</b>The purpose of this class is to act as an entry point into the
 *  TopLink JAXB 2.0 Generation framework
 *  <p><b>Responsibilities:</b><ul>
 *  <li>Run initial processing on a list of classes to create TypeInfo meta data</li>
 *  <li>Provide API to generate Schema Files</li>
 *  <li>Provide API to generate a TopLink Project</li>
 *  <li>Act as an integration point with WebServices</li>
 *  </ul>
 *  <p> This class acts as an entry point into JAXB 2.0 Generation. A Generator is created with a
 *  specific set of JAXB 2.0 Annotated classes and then performs actions on those, such as
 *  generating schema files, or generating TopLink Projects. Additional information is returned
 *  from the schema generation methods as a means of integration with WebServices.
 *
 *  @author  mmacivor
 *  @since   Oracle TopLink 11.1.1.0.0
 *  @see AnnotationsProcessor
 *  @see MappingsGenerator
 *  @see SchemaGenerator
 */
public class Generator {

    private AnnotationsProcessor annotationsProcessor;
    private SchemaGenerator schemaGenerator;
    private MappingsGenerator mappingsGenerator;
    private Helper helper;
    private Map<Type, TypeMappingInfo> typeToTypeMappingInfo;

    /**
     * This constructor creates a Helper using the JavaModelInput
     * instance's JavaModel. Annotations are processed here as well.
     *
     */
    public Generator(JavaModelInput jModelInput) {
        helper = new Helper(jModelInput.getJavaModel());
        configureFacetsGeneration(jModelInput);
        annotationsProcessor = new AnnotationsProcessor(helper);
        schemaGenerator = new SchemaGenerator(helper);
        mappingsGenerator = new MappingsGenerator(helper);
        annotationsProcessor.processClassesAndProperties(jModelInput.getJavaClasses(), null);
    }

    /**
     * This constructor will process and apply the given XmlBindings as appropriate.  Classes
     * declared in the bindings will be amalgamated with any classes in the JavaModelInput.
     *
     * If xmlBindings is null or empty, AnnotationsProcessor will be used to process
     * annotations as per usual.
     *
     * @param xmlBindings map of XmlBindings keyed on package name
     */
    public Generator(JavaModelInput jModelInput, Map<String, XmlBindings> xmlBindings, ClassLoader cLoader, String defaultTargetNamespace, boolean enableXmlAccessorFactory) {
        helper = new Helper(jModelInput.getJavaModel());
        configureFacetsGeneration(jModelInput);
        annotationsProcessor = new AnnotationsProcessor(helper);
        annotationsProcessor.setXmlAccessorFactorySupport(enableXmlAccessorFactory);
        annotationsProcessor.setDefaultTargetNamespace(defaultTargetNamespace);
        schemaGenerator = new SchemaGenerator(helper);
        mappingsGenerator = new MappingsGenerator(helper);
        if (xmlBindings != null && !xmlBindings.isEmpty()) {
            new XMLProcessor(xmlBindings).processXML(annotationsProcessor, jModelInput, null, null);
        } else {
            annotationsProcessor.processClassesAndProperties(jModelInput.getJavaClasses(), null);
        }
    }

    /**
     * This constructor creates a Helper using the JavaModelInput
     * instance's JavaModel and a map of javaclasses that were generated from Type objects.
     * Annotations are processed here as well.
     *
     */
    public Generator(JavaModelInput jModelInput, TypeMappingInfo[] typeMappingInfos, JavaClass[] javaClasses, Map<Type, TypeMappingInfo> typeToTypeMappingInfo, String defaultTargetNamespace) {
        helper = new Helper(jModelInput.getJavaModel());
        configureFacetsGeneration(jModelInput);
        annotationsProcessor = new AnnotationsProcessor(helper);
        annotationsProcessor.setDefaultTargetNamespace(defaultTargetNamespace);
        schemaGenerator = new SchemaGenerator(helper);
        mappingsGenerator = new MappingsGenerator(helper);
        this.typeToTypeMappingInfo = typeToTypeMappingInfo;
        annotationsProcessor.processClassesAndProperties(javaClasses, typeMappingInfos);
    }

    /**
     * This constructor will process and apply the given XmlBindings as appropriate.  Classes
     * declared in the bindings will be amalgamated with any classes in the JavaModelInput.
     *
     * If xmlBindings is null or empty, AnnotationsProcessor will be used to process
     * annotations as per usual.
     *
     * @param xmlBindings map of XmlBindings keyed on package name
     */
    public Generator(JavaModelInput jModelInput, TypeMappingInfo[] typeMappingInfos, JavaClass[] javaClasses, Map<Type, TypeMappingInfo> typeToTypeMappingInfo, Map<String, XmlBindings> xmlBindings, ClassLoader cLoader, String defaultTargetNamespace, boolean enableXmlAccessorFactory) {
        helper = new Helper(jModelInput.getJavaModel());
        configureFacetsGeneration(jModelInput);
        annotationsProcessor = new AnnotationsProcessor(helper);
        annotationsProcessor.setXmlAccessorFactorySupport(enableXmlAccessorFactory);
        annotationsProcessor.setDefaultTargetNamespace(defaultTargetNamespace);
        schemaGenerator = new SchemaGenerator(helper);
        mappingsGenerator = new MappingsGenerator(helper);
        this.typeToTypeMappingInfo = typeToTypeMappingInfo;
        if (xmlBindings != null && !xmlBindings.isEmpty()) {
            new XMLProcessor(xmlBindings).processXML(annotationsProcessor, jModelInput, typeMappingInfos, javaClasses);
        } else {
        annotationsProcessor.processClassesAndProperties(javaClasses, typeMappingInfos);
        }
    }

    /**
     * This event is called when mappings generation is completed,
     * and provides a chance to deference anything that is no longer
     * needed (to reduce the memory footprint of this object).
     */
    public void postInitialize() {
        mappingsGenerator = null;
        annotationsProcessor.postInitialize();
        schemaGenerator = null;
    }

    /**
     *
     */
    public boolean hasMarshalCallbacks() {
        return getMarshalCallbacks()!=null && !getMarshalCallbacks().isEmpty();
    }

    public boolean hasUnmarshalCallbacks() {
        return getUnmarshalCallbacks()!=null && !getUnmarshalCallbacks().isEmpty();
    }

    public CoreProject generateProject() throws Exception {
        mappingsGenerator.getClassToGeneratedClasses().putAll(annotationsProcessor.getArrayClassesToGeneratedClasses());
        CoreProject p = mappingsGenerator.generateProject(annotationsProcessor.getTypeInfoClasses(), annotationsProcessor.getTypeInfos(), annotationsProcessor.getUserDefinedSchemaTypes(), annotationsProcessor.getPackageToPackageInfoMappings(), annotationsProcessor.getGlobalElements(), annotationsProcessor.getLocalElements(), annotationsProcessor.getTypeMappingInfosToGeneratedClasses(), annotationsProcessor.getTypeMappingInfoToAdapterClasses(),annotationsProcessor.isDefaultNamespaceAllowed());
        annotationsProcessor.getArrayClassesToGeneratedClasses().putAll(mappingsGenerator.getClassToGeneratedClasses());
        return p;
    }

    public java.util.Collection<Schema> generateSchema() {
        schemaGenerator.generateSchema(annotationsProcessor.getTypeInfoClasses(), annotationsProcessor.getTypeInfos(), annotationsProcessor.getUserDefinedSchemaTypes(), annotationsProcessor.getPackageToPackageInfoMappings(), null, annotationsProcessor.getArrayClassesToGeneratedClasses());
        return schemaGenerator.getAllSchemas();
    }

    public Map<String, SchemaTypeInfo> generateSchemaFiles(String schemaPath, Map<QName, Type> additionalGlobalElements) throws FileNotFoundException {
        // process any additional global elements
        processAdditionalElements(additionalGlobalElements, annotationsProcessor);

        schemaGenerator.generateSchema(annotationsProcessor.getTypeInfoClasses(), annotationsProcessor.getTypeInfos(), annotationsProcessor.getUserDefinedSchemaTypes(), annotationsProcessor.getPackageToPackageInfoMappings(), annotationsProcessor.getGlobalElements(), annotationsProcessor.getArrayClassesToGeneratedClasses());
        Project proj = new SchemaModelProject();
        XMLContext context = new XMLContext(proj);
        XMLMarshaller marshaller = context.createMarshaller();
        Descriptor schemaDescriptor = (Descriptor)proj.getDescriptor(Schema.class);

        java.util.Collection<Schema> schemas = schemaGenerator.getAllSchemas();
        for(Schema schema : schemas) {
            File file = new File(schemaPath + "/" + schema.getName());
            NamespaceResolver schemaNamespaces = schema.getNamespaceResolver();
            schemaNamespaces.put(Constants.SCHEMA_PREFIX, XMLConstants.W3C_XML_SCHEMA_NS_URI);
            schemaDescriptor.setNamespaceResolver(schemaNamespaces);
            marshaller.marshal(schema, new FileOutputStream(file));
        }
        return schemaGenerator.getSchemaTypeInfo();
    }

    public Map<String, SchemaTypeInfo> generateSchemaFiles(SchemaOutputResolver outputResolver, Map<QName, Type> additionalGlobalElements) {
        // process any additional global elements
        processAdditionalElements(additionalGlobalElements, annotationsProcessor);

        schemaGenerator.generateSchema(annotationsProcessor.getTypeInfoClasses(), annotationsProcessor.getTypeInfos(), annotationsProcessor.getUserDefinedSchemaTypes(), annotationsProcessor.getPackageToPackageInfoMappings(), annotationsProcessor.getGlobalElements(), annotationsProcessor.getArrayClassesToGeneratedClasses(), outputResolver);
        Project proj = new SchemaModelProject();
        XMLContext context = new XMLContext(proj);
        XMLMarshaller marshaller = context.createMarshaller();

        Descriptor schemaDescriptor = (Descriptor)proj.getDescriptor(Schema.class);

        java.util.Collection<Schema> schemas = schemaGenerator.getAllSchemas();
        // make sure that schemas will be passed to the output in specified order
        if (schemas instanceof List) {
            ((List<Schema>)schemas).sort(new SchemaCompareByNamespace());
        }
        for(Schema schema : schemas) {
            try {
                NamespaceResolver schemaNamespaces = schema.getNamespaceResolver();
                schemaNamespaces.put(Constants.SCHEMA_PREFIX, XMLConstants.W3C_XML_SCHEMA_NS_URI);
                schemaDescriptor.setNamespaceResolver(schemaNamespaces);
                // make sure we don't call into the provided output resolver more than once
                javax.xml.transform.Result target;
                if (schema.hasResult()) {
                    target = schema.getResult();
                } else {
                    target = outputResolver.createOutput(schema.getTargetNamespace(), schema.getName());
                }
                marshaller.marshal(schema, target);
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        return schemaGenerator.getSchemaTypeInfo();
    }

    /**
     * Convenience method that processes a given map of QName-Type entries.  For each an ElementDeclaration
     * is created and added to the given AnnotationsProcessor instance's map of global elements.
     *
     * It is assumed that the map of QName-Type entries contains Type instances that are either a Class or
     * a ParameterizedType.
     *
     */
    private void processAdditionalElements(Map<QName, Type> additionalGlobalElements, AnnotationsProcessor annotationsProcessor) {
        if (additionalGlobalElements != null) {
            ElementDeclaration declaration;
            for(Entry<QName, Type> entry : additionalGlobalElements.entrySet()) {
                QName key = entry.getKey();
                Type type = entry.getValue();
                TypeMappingInfo tmi = null;
                if(this.typeToTypeMappingInfo != null) {
                    tmi = this.typeToTypeMappingInfo.get(type);
                }

                if(tmi != null) {
                    if(annotationsProcessor.getTypeMappingInfosToGeneratedClasses().get(tmi) != null) {
                        type =  annotationsProcessor.getTypeMappingInfosToGeneratedClasses().get(tmi);
                    }
                }
                JavaClass jClass = null;
                if (type instanceof Class) {
                    Class<?> tClass = (Class<?>) type;
                    jClass = helper.getJavaClass(tClass);
                }
                // if no type is available don't do anything
                if (jClass != null) {
                    declaration = new ElementDeclaration(key, jClass, jClass.getQualifiedName(), false);
                    annotationsProcessor.getGlobalElements().put(key, declaration);
                }
            }
        }
    }

    public Map<String, UnmarshalCallback> getUnmarshalCallbacks() {
        return annotationsProcessor.getUnmarshalCallbacks();
    }

    public Map<String, MarshalCallback> getMarshalCallbacks() {
        return annotationsProcessor.getMarshalCallbacks();
    }

    public MappingsGenerator getMappingsGenerator() {
        return this.mappingsGenerator;
    }

    public AnnotationsProcessor getAnnotationsProcessor() {
        return annotationsProcessor;
    }

    public void setTypeToTypeMappingInfo(Map<Type, TypeMappingInfo> typesToTypeMapping) {
        this.typeToTypeMappingInfo = typesToTypeMapping;
    }

    public Map<Type, TypeMappingInfo> getTypeToTypeMappingInfo() {
        return this.typeToTypeMappingInfo;
    }

    private void configureFacetsGeneration(JavaModelInput jModelInput) {
        if (jModelInput instanceof JavaModelInputImpl) {
            helper.setFacets(((JavaModelInputImpl) jModelInput).isFacets());
        } else {
            String msg = "MOXy BV: Facets generation could not be configured. EclipseLink''s JavaModelInputImpl was " +
                    "not detected, instead JavaModelInput is of class: {0}";
            AbstractSessionLog.getLog().log(SessionLog.WARNING, SessionLog.MOXY, msg, new Object[] {jModelInput.getClass()}, false);
        }
    }

}
