/*
 * 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:
//     08/10/2009-2.0 Guy Pelletier
//       - 267391: JPA 2.0 implement/extend/use an APT tooling library for MetaModel API canonical classes
//     04/27/2010-2.1 Guy Pelletier
//       - 309856: MappedSuperclasses from XML are not being initialized properly
//     06/14/2010-2.2 Guy Pelletier
//       - 264417: Table generation is incorrect for JoinTables in AssociationOverrides
//     08/12/2010-2.2 Guy Pelletier
//       - 298118: canonical metamodel generation with untyped Map throws NPE
//     08/25/2010-2.2 Guy Pelletier
//       - 309445: CannonicalModelProcessor process all files
//     10/18/2010-2.2 Guy Pelletier
//       - 322921: OutOfMemory in annotation processor
//     11/23/2010-2.2 Guy Pelletier
//       - 330660: Canonical model generator throws ClassCastException when using package-info.java
package org.eclipse.persistence.internal.jpa.modelgen;

import java.io.IOException;
import java.io.Writer;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.PrimitiveType;
import jakarta.persistence.Embeddable;
import jakarta.persistence.Entity;
import jakarta.persistence.MappedSuperclass;
import javax.tools.JavaFileObject;

import org.eclipse.persistence.Version;
import org.eclipse.persistence.config.PersistenceUnitProperties;
import org.eclipse.persistence.internal.jpa.metadata.MetadataLogger;
import org.eclipse.persistence.internal.jpa.metadata.MetadataProject;
import org.eclipse.persistence.internal.jpa.metadata.accessors.classes.ClassAccessor;
import org.eclipse.persistence.internal.jpa.metadata.accessors.mappings.MappedKeyMapAccessor;
import org.eclipse.persistence.internal.jpa.metadata.accessors.mappings.MappingAccessor;
import org.eclipse.persistence.internal.jpa.metadata.accessors.objects.MetadataAnnotatedElement;
import org.eclipse.persistence.internal.jpa.metadata.accessors.objects.MetadataClass;
import org.eclipse.persistence.internal.jpa.modelgen.objects.PersistenceUnit;
import org.eclipse.persistence.internal.jpa.modelgen.objects.PersistenceUnitReader;
import org.eclipse.persistence.internal.jpa.modelgen.visitors.TypeVisitor;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.logging.AbstractSessionLog;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.sessions.DatabaseLogin;
import org.eclipse.persistence.sessions.Project;
import org.eclipse.persistence.sessions.server.ServerSession;

/**
 * The main APT processor to generate the JPA 2.0 Canonical model.
 *
 * @author Guy Pelletier
 * @since EclipseLink 1.2
 */
public class CanonicalModelProcessor extends AbstractProcessor {
    protected enum AttributeType {CollectionAttribute, ListAttribute, MapAttribute, SetAttribute, SingularAttribute }
    protected MetadataMirrorFactory nonStaticFactory;
    protected static MetadataMirrorFactory staticFactory;
    private SessionLog log;
    private boolean useStaticFactory;
    private boolean generateComments;
    private boolean generateTimestamp;
    private boolean generateGenerated;

    private static final Set<String> SUPPORTED_ANNOTATIONS = Collections.unmodifiableSet(new HashSet<String>() {{
        if (SourceVersion.latest().compareTo(SourceVersion.RELEASE_8) > 0) {
            add("java.persistence/jakarta.persistence.*");
        }
        add("jakarta.persistence.*");
        add("org.eclipse.persistence.annotations.*");
    }});

    private static final Set<String> SUPPORTED_OPTIONS = Collections.unmodifiableSet(new HashSet<String>() {{
        add(CanonicalModelProperties.CANONICAL_MODEL_PREFIX);
        add(CanonicalModelProperties.CANONICAL_MODEL_SUFFIX);
        add(CanonicalModelProperties.CANONICAL_MODEL_SUB_PACKAGE);
        add(CanonicalModelProperties.CANONICAL_MODEL_LOAD_XML);
        add(CanonicalModelProperties.CANONICAL_MODEL_USE_STATIC_FACTORY);
        add(CanonicalModelProperties.CANONICAL_MODEL_GENERATE_GENERATED);
        add(CanonicalModelProperties.CANONICAL_MODEL_GENERATE_TIMESTAMP);
        add(CanonicalModelProperties.CANONICAL_MODEL_GENERATE_COMMENTS);
        add(CanonicalModelProperties.CANONICAL_MODEL_PROCESSOR_LOG_LEVEL);
        add(CanonicalModelProperties.CANONICAL_MODEL_GLOBAL_LOG_LEVEL);
        add(PersistenceUnitProperties.ECLIPSELINK_PERSISTENCE_XML);
        add("verbose"); //shortcut to enable FINER logging
    }});

    /**
     * Default constructor.
     */
    public CanonicalModelProcessor() {
    }

    @Override
    public Set<String> getSupportedAnnotationTypes() {
        return SUPPORTED_ANNOTATIONS;
    }

    @Override
    public Set<String> getSupportedOptions() {
        return SUPPORTED_OPTIONS;
    }

    @Override
    public SourceVersion getSupportedSourceVersion() {
        return SourceVersion.latest();
    }

    @Override
    public synchronized void init(ProcessingEnvironment processingEnv) {
        super.init(processingEnv);
        Map<String, String> options = processingEnv.getOptions();

        log = new MessagerLog(processingEnv.getMessager(), options);
        if (Boolean.valueOf(options.get("verbose")) && log.getLevel() > SessionLog.FINER) {
            log.setLevel(SessionLog.FINER);
        }
        AbstractSessionLog.setLog(log);

        // Log processing environment options
        for (Map.Entry<String, String> option : options.entrySet()) {
            log(SessionLog.CONFIG, "Found Option: {0}, with value: {1}",
                    new Object[]{option.getKey(), option.getValue()});
        }

        useStaticFactory = Boolean.valueOf(CanonicalModelProperties.getOption(
                CanonicalModelProperties.CANONICAL_MODEL_USE_STATIC_FACTORY,
                CanonicalModelProperties.CANONICAL_MODEL_USE_STATIC_FACTORY_DEFAULT,
                options));
        generateGenerated = Boolean.valueOf(CanonicalModelProperties.getOption(
                CanonicalModelProperties.CANONICAL_MODEL_GENERATE_GENERATED,
                CanonicalModelProperties.CANONICAL_MODEL_GENERATE_GENERATED_DEFAULT,
                options));
        if (generateGenerated) {
            generateTimestamp = Boolean.valueOf(CanonicalModelProperties.getOption(
                CanonicalModelProperties.CANONICAL_MODEL_GENERATE_TIMESTAMP,
                CanonicalModelProperties.CANONICAL_MODEL_GENERATE_TIMESTAMP_DEFAULT,
                options));
            generateComments = Boolean.valueOf(CanonicalModelProperties.getOption(
                CanonicalModelProperties.CANONICAL_MODEL_GENERATE_COMMENTS,
                CanonicalModelProperties.CANONICAL_MODEL_GENERATE_COMMENTS_DEFAULT,
                options));
        }
    }

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        if (! roundEnv.processingOver() && ! roundEnv.errorRaised()) {
            MetadataMirrorFactory factory = null;
            try {
                if (useStaticFactory) {
                    if (staticFactory == null) {
                        // We must remember some state from one round to another.
                        // In some rounds, the user may only change one class
                        // meaning we only have one root element from the round.
                        // If it is a child class to an existing already generated
                        // parent class we need to know about this class, so the
                        // factory will also hang onto static projects for each
                        // persistence unit. Doing this is going to need careful
                        // cleanup thoughts though. Adding classes ok, but what
                        // about removing some?
                        AbstractSession session = new ServerSession(new Project(new DatabaseLogin()));
                        session.setSessionLog(log);
                        final MetadataLogger logger = new MetadataLogger(session);
                        staticFactory = new MetadataMirrorFactory(logger,
                                Thread.currentThread().getContextClassLoader());
                        log(SessionLog.INFO, "Creating static metadata factory ...");
                    }

                    factory = staticFactory;
                } else {
                    if (nonStaticFactory == null) {
                        AbstractSession session = new ServerSession(new Project(new DatabaseLogin()));
                        session.setSessionLog(log);
                        final MetadataLogger logger = new MetadataLogger(session);
                        nonStaticFactory = new MetadataMirrorFactory(logger,
                                Thread.currentThread().getContextClassLoader());
                        log(SessionLog.INFO, "Creating non-static metadata factory ...");
                    }

                    factory = nonStaticFactory;
                }

                final MetadataLogger logger = factory.getLogger();

                // Step 1 - The factory is passed around so those who want the
                // processing or round env can get it off the factory. This
                // saves us from having to pass around multiple objects.
                factory.setEnvironments(processingEnv, roundEnv);

                // Step 2 - read the persistence xml classes (gives us extra
                // classes and mapping files. From them we get transients and
                // access). Metadata read from XML causes new accessors to be
                // created and override existing ones (causing them to be un-
                // pre-processed. We can never tell what changes in XML so we
                // have to do this.
                final PersistenceUnitReader puReader = new PersistenceUnitReader(logger, processingEnv);
                puReader.initPersistenceUnits(factory);

                // Step 3 - iterate over all the persistence units and generate
                // their canonical model classes.
                for (PersistenceUnit persistenceUnit : factory.getPersistenceUnits()) {

                    // Step 3a - add the Entities not defined in XML that are
                    // being compiled.
                    for (Element element : roundEnv.getElementsAnnotatedWith(Entity.class)) {
                        persistenceUnit.addEntityAccessor(element);
                    }

                    // Step 3b - add the Embeddables not defined in XML that are
                    // being compiled.
                    for (Element element : roundEnv.getElementsAnnotatedWith(Embeddable.class)) {
                        persistenceUnit.addEmbeddableAccessor(element);
                    }

                    // Step 3c - add the MappedSuperclasses not defined in XML
                    // that are being compiled.
                    for (Element element : roundEnv.getElementsAnnotatedWith(MappedSuperclass.class)) {
                        persistenceUnit.addMappedSuperclassAccessor(element);
                    }

                    // Step 3d - tell the persistence unit to pre-process itself.
                    persistenceUnit.preProcessForCanonicalModel();

                    // Step 3e - We're set, generate the canonical model classes.
                    generateCanonicalModelClasses(factory, persistenceUnit);
                }
            } catch (Exception e) {
                log.logThrowable(SessionLog.SEVERE, SessionLog.PROCESSOR, e);
                throw new RuntimeException(e);
            }
        }

        return false; // Don't claim any annotations
    }

    /**
     * INTERNAL:
     */
    protected void generateCanonicalModelClass(MetadataClass metadataClass, Element element, PersistenceUnit persistenceUnit) throws IOException {
        Writer writer = null;

        try {
            ClassAccessor accessor = persistenceUnit.getClassAccessor(metadataClass);
            String qualifiedName = accessor.getAccessibleObjectName();
            String className = getName(qualifiedName);
            String classPackage = getPackage(qualifiedName);

            String qualifiedCanonicalName = persistenceUnit.getQualifiedCanonicalName(qualifiedName);
            String canonicalName = getName(qualifiedCanonicalName);
            String canonicalpackage = getPackage(qualifiedCanonicalName);

            boolean isNewJava = SourceVersion.RELEASE_8.compareTo(processingEnv.getSourceVersion()) < 0;
            JavaFileObject file = processingEnv.getFiler().createSourceFile(qualifiedCanonicalName, element);
            writer = file.openWriter();

            // Print the package if we have one.
            if (! canonicalpackage.equals("")) {
                writer.append("package " + canonicalpackage + ";\n\n");
            }

            // Go through the accessor list, ignoring any transient accessors
            // to build our attributes and import list.
            ArrayList<String> attributes = new ArrayList<>();
            HashMap<String, String> imports = new HashMap<>();

            if (generateGenerated) {
                if (isNewJava) {
                    imports.put("Generated", "javax.annotation.processing.Generated");
                } else {
                    imports.put("Generated", "jakarta.annotation.Generated");
                }
            }

            // Import the model class if the canonical class is generated elsewhere.
            if (! classPackage.equals(canonicalpackage)) {
                imports.put(className, qualifiedName);
            }

            for (MappingAccessor mappingAccessor : accessor.getDescriptor().getMappingAccessors()) {
                if (! mappingAccessor.isTransient()) {
                    MetadataAnnotatedElement annotatedElement = mappingAccessor.getAnnotatedElement();
                    // Must go through the mapping accessor for the raw class
                    // since it may be a virtual mapping accessor with an
                    // attribute type.
                    MetadataClass rawClass = mappingAccessor.getRawClass();

                    // NOTE: order of checking is important.
                    String attributeType;
                    String types = className;

                    if (mappingAccessor.isBasic()) {
                        types = types + ", " + getUnqualifiedType(getBoxedType(annotatedElement, rawClass), imports);
                        attributeType = AttributeType.SingularAttribute.name();
                        imports.put(attributeType, "jakarta.persistence.metamodel.SingularAttribute");
                    } else {
                        if (rawClass.isList()) {
                            attributeType = AttributeType.ListAttribute.name();
                            imports.put(attributeType, "jakarta.persistence.metamodel.ListAttribute");
                        } else if (rawClass.isSet()) {
                            attributeType = AttributeType.SetAttribute.name();
                            imports.put(attributeType, "jakarta.persistence.metamodel.SetAttribute");
                        } else if (rawClass.isMap()) {
                            attributeType = AttributeType.MapAttribute.name();
                            imports.put(attributeType, "jakarta.persistence.metamodel.MapAttribute");
                        } else if (rawClass.isCollection()) {
                            attributeType = AttributeType.CollectionAttribute.name();
                            imports.put(attributeType, "jakarta.persistence.metamodel.CollectionAttribute");
                        } else {
                            attributeType = AttributeType.SingularAttribute.name();
                            imports.put(attributeType, "jakarta.persistence.metamodel.SingularAttribute");
                        }

                        if (mappingAccessor.isMapAccessor()) {
                            if (mappingAccessor.isMappedKeyMapAccessor()) {
                                MetadataClass mapKeyClass = ((MappedKeyMapAccessor) mappingAccessor).getMapKeyClass();
                                types = types + ", " + getUnqualifiedType(mapKeyClass.getName(), imports) + ", " + getUnqualifiedType(mappingAccessor.getReferenceClassName(), imports);
                            } else {
                                String mapKeyType;
                                if (annotatedElement.isGenericCollectionType()) {
                                    // Grab the map key class from the generic.
                                    mapKeyType = annotatedElement.getGenericType().get(1);
                                } else {
                                    if (mappingAccessor.getReferenceDescriptor().hasIdAccessor()) {
                                        // Grab the id type from the reference descriptor, now there's a handle!
                                        MappingAccessor idAccessor = mappingAccessor.getReferenceDescriptor().getIdAccessors().values().iterator().next();
                                        mapKeyType = idAccessor.getReferenceClassName();
                                    } else {
                                        // We don't know at this point so just use the catch all default.
                                        mapKeyType = TypeVisitor.GENERIC_TYPE;
                                    }
                                }

                                types = types + ", " + getUnqualifiedType(mapKeyType, imports) + ", " + getUnqualifiedType(mappingAccessor.getReferenceClassName(), imports);
                            }
                        } else {
                            types = types + ", " + getUnqualifiedType(mappingAccessor.getReferenceClassName(), imports);
                        }
                    }

                    // Add the mapping attribute to the list of attributes for this class.
                    attributes.add("    public static volatile " + attributeType + "<" + types + "> " + annotatedElement.getAttributeName() + ";\n");
                }
            }

            // Will import the parent as well if needed.
            String parent = writeImportStatements(imports, accessor, writer, persistenceUnit, canonicalpackage);

            if (generateGenerated) {
                // Write out the generation annotations.
                String elVersion = "EclipseLink-" + Version.getVersion() + ".v" + Version.getBuildDate() + "-r" + Version.getBuildRevision();
                writer.append("@Generated(value=\"");
                if (isNewJava) {
                    writer.append(CanonicalModelProcessor.class.getName());
                } else {
                    writer.append(elVersion);
                }
                writer.append("\"");
                if (generateTimestamp) {
                    Date date = new Date();
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
                    writer.append(", date=\"" +  sdf.format(date) + "\"");
                }
                if (isNewJava && generateComments) {
                    writer.append(", comments=\"");
                    writer.append(elVersion);
                    writer.append("\"");
                }
                writer.append(")\n");
            }
            writer.append("@StaticMetamodel(" + className + ".class)\n");

            int modifier = accessor.getAccessibleObject().getModifiers();
            writer.append(java.lang.reflect.Modifier.toString(modifier) + " class " + canonicalName);

            if (parent == null) {
                writer.append(" { \n\n");
            } else {
                writer.append(" extends " + parent + " {\n\n");
            }

            // Go through the attributes and write them out.
            for (String str : attributes) {
                writer.append(str);
            }

            writer.append("\n}");
        } finally {
            if (writer != null) {
                writer.flush();
                writer.close();
                writer = null;
            }
        }
    }

    /**
     * INTERNAL:
     */
    protected void generateCanonicalModelClasses(MetadataMirrorFactory factory, PersistenceUnit persistenceUnit) throws IOException {
        Map<Element, MetadataClass> roundElements = factory.getRoundElements();

        for (Element roundElement : roundElements.keySet()) {
            MetadataClass roundClass = roundElements.get(roundElement);

            if (persistenceUnit.containsClass(roundClass)) {
                log(SessionLog.FINEST, "Generating class: {0}", roundClass.getName());
                generateCanonicalModelClass(roundClass, roundElement, persistenceUnit);
            }
        }
    }

    /**
     * INTERNAL:
     */
    protected String getBoxedType(MetadataAnnotatedElement annotatedElement, MetadataClass rawClass) {
        PrimitiveType primitiveType = (PrimitiveType) annotatedElement.getPrimitiveType();
        if (primitiveType != null) {
            return processingEnv.getTypeUtils().boxedClass(primitiveType).toString();
        }

        String type = annotatedElement.getType();
        return (type == null) ? rawClass.getType() : type;
    }

    /**
     * INTERNAL:
     */
    protected String getName(String qualifiedName) {
        if (qualifiedName.indexOf('.') > -1) {
            return qualifiedName.substring(qualifiedName.lastIndexOf('.') + 1);
        }

        return qualifiedName;
    }

    /**
     * INTERNAL:
     */
    protected String getPackage(String qualifiedName) {
        if (qualifiedName.indexOf('.') > -1) {
            return qualifiedName.substring(0, qualifiedName.lastIndexOf('.'));
        }

        return "";
    }

    /**
     * INTERNAL: This method will hack off any package qualification. It will
     * add that type to the import list unless it is a known JDK type that does
     * not need to be imported (java.lang). This method also trims the type
     * from leading and trailing white spaces.
     */
    protected String getUnqualifiedType(String type, HashMap<String, String> imports) {
        // Remove any leading and trailing white spaces.
        type = type.trim();

        // Convert any $ (enums, inner classes to valid dot notation for import statement)
        // org.eclipse.persistence.testing.models.jpa.xml.advanced.ShovelSections$MaterialType
        type = type.replace("$", ".");

        if (type.contains("void")) {
            // This case hits when the user defines something like:
            // @BasicCollection public Collection responsibilities;
            return TypeVisitor.GENERIC_TYPE;
        } else if (type.startsWith("java.lang")) {
            return type.substring(type.lastIndexOf('.') + 1);
        } else {
            if (type.indexOf('<') > -1) {
                String raw = type.substring(0, type.indexOf('>'));
                String generic = type.substring(type.indexOf('<') + 1, type.length() - 1);

                if (raw.contains("Map")) {
                    String key = generic.substring(0, generic.indexOf(','));
                    String value = generic.substring(generic.indexOf(',') + 1);
                    return getUnqualifiedType(raw, imports) + "<" + getUnqualifiedType(key, imports) + ", " + getUnqualifiedType(value, imports) + ">";
                }

                return getUnqualifiedType(raw, imports) + "<" + getUnqualifiedType(generic, imports) + ">";
            } else if (type.indexOf('.') > -1) {
                String shortClassName = type.substring(type.lastIndexOf('.') + 1);

                // We already have an import for this class, look at it further.
                if (imports.containsKey(shortClassName)) {
                    if (imports.get(shortClassName).equals(type)) {
                        // We're hitting the same class from the same package,
                        // return the short name for this class.
                        return type.substring(type.lastIndexOf('.') + 1);
                    } else {
                        // Same class name different package. Don't hack off the
                        // qualification and don't add it to the import list.
                        return type;
                    }
                } else {
                    // Add it to the import list. If the type is used in an array
                    // hack off the [].
                    if (shortClassName.indexOf('[') > 1) {
                        imports.put(shortClassName, type.substring(0, type.indexOf('[')));
                    } else {
                        imports.put(shortClassName, type);
                    }

                    return shortClassName;
                }
            } else {
                return type;
            }
        }
    }

    /**
     * INTERNAL:
     */
    protected String writeImportStatements(HashMap<String, String> typeImports, ClassAccessor accessor, Writer writer, PersistenceUnit persistenceUnit, String childCanonicalpackage) throws IOException {
        String parentCanonicalName = null;

        // Get the import list ready to be sorted.
        ArrayList<String> imps = new ArrayList<>();
        imps.addAll(typeImports.values());

        // Add the standard canonical model generator imports.
        imps.add("jakarta.persistence.metamodel.StaticMetamodel");

        // Import the parent canonical class if need be.
        MetadataClass parentCls = accessor.getJavaClass().getSuperclass();
        MetadataProject project = accessor.getProject();

        if (project.hasEntity(parentCls) || project.hasEmbeddable(parentCls) || project.hasMappedSuperclass(parentCls)) {
            String qualifiedParentCanonicalName = persistenceUnit.getQualifiedCanonicalName(parentCls.getName());
            parentCanonicalName = getName(qualifiedParentCanonicalName);
            String parentCanonicalPackage = getPackage(qualifiedParentCanonicalName);

            if (! parentCanonicalPackage.equals(childCanonicalpackage)) {
                imps.add(qualifiedParentCanonicalName);
            }
        }

        // Sort the list of imports before writing them.
        Collections.sort(imps);

        // Write out the imports.
        for (String typeImport : imps) {
            writer.append("import " + typeImport + ";\n");
        }

        writer.append("\n");
        return parentCanonicalName;
    }

    private void log(int level, String msg, Object... args) {
        log.log(level, SessionLog.PROCESSOR, msg, args, false);
    }
}
