/*
 * Copyright (c) 2011, 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
//     05/26/2009-2.0  mobrien - 266912: Add implementation of IdentifiableType
//       as EntityType inherits here instead of ManagedType as of rev# 4265
//     09/23/2009-2.0  mobrien - 266912: Implement hasSingleIdAttribute() and
//       all other 6 remaining methods for Id and Version support.
//       DI 71 - 77 and 56
//       http://wiki.eclipse.org/EclipseLink/Development/JPA_2.0/metamodel_api#DI_74:_20090909:_Implement_IdentifiableType.hasSingleIdAttribute.28.29
//     10/21/2009-2.0 Guy Pelletier
//       - 290567: mappedbyid support incomplete
//     06/14/2010-2.1  mobrien - 314906: getJavaType should return the
//       collection javaType C in <X,C,V) of <X, List<V>, V> instead off the elementType V.
//       Because of this we switch to using getBindableJavaType() in getIdType()
//     08/06/2010-2.2 mobrien 322018 - reduce protected instance variables to private to enforce encapsulation
package org.eclipse.persistence.internal.jpa.metamodel;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import jakarta.persistence.metamodel.Attribute;
import jakarta.persistence.metamodel.Bindable;
import jakarta.persistence.metamodel.IdentifiableType;
import jakarta.persistence.metamodel.SingularAttribute;
import jakarta.persistence.metamodel.Type;

import org.eclipse.persistence.descriptors.CMPPolicy;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.localization.ExceptionLocalization;
import org.eclipse.persistence.mappings.DatabaseMapping;

/**
 * <p>
 * <b>Purpose</b>: Provides the implementation for the Entity interface
 *  of the JPA 2.0 Metamodel API (part of the JSR-317 EJB 3.1 Criteria API)
 * <p>
 * <b>Description</b>:
 *  Instances of the type IdentifiableType represent entity or
 *  mapped superclass types.
 *
 * @see jakarta.persistence.metamodel.EntityType
 *
 * @since EclipseLink 1.2 - JPA 2.0
 * @param <X> The represented entity or mapped superclass type.
 *
 */
public abstract class IdentifiableTypeImpl<X> extends ManagedTypeImpl<X> implements IdentifiableType<X> {

    /**
     * The supertype may be an entity or mappedSuperclass.<p>
     * For top-level inheritance root identifiable types with no superclass - return null (not Object)
     */
    private IdentifiableType<? super X> superType;

    /**
     * The collection of SingularAttributes that are Id attributes.
     */
    private Set<SingularAttribute<? super X, ?>> idAttributes;

    /**
     * The SingularAttribute if it exists that is a version attribute
     */
    private SingularAttribute<? super X, ?> versionAttribute;

    protected IdentifiableTypeImpl(MetamodelImpl metamodel, ClassDescriptor descriptor) {
        super(metamodel, descriptor);
        /* The superType field cannot be set until all ManagedType instances
         * have been instantiated for this metamodel.
         * This is required so that any references between attributes can be resolved.
         * This occurs later in MetamodelImpl.initialize()
         * The idAttributes field is computed at the end of MetamodelImpl.initialize()
         * The versionAttribute is lazy loaded.
         */
    }

    /**
     * INTERNAL:
     * The idAttributes collection is computed at the end of MetamodelImpl.initialize()
     */
    protected void initializeIdAttributes() {
        // initialize the set of id attributes directly from the mapping
        idAttributes = new HashSet<SingularAttribute<? super X, ?>>();
        for(Attribute attribute : this.getAttributes()) {
            if(!((AttributeImpl)attribute).isPlural()) {
                if(((SingularAttribute)attribute).isId()) {
                    idAttributes.add((SingularAttribute)attribute);
                }
            }
        }
    }

    /**
     *  Return the attribute that corresponds to the id attribute
     *  declared by the entity or mapped superclass.
     *  @param type  the type of the represented declared id attribute
     *  @return declared id attribute
     *  @throws IllegalArgumentException if id attribute of the given
     *          type is not declared in the identifiable type or if
     *          the identifiable type has an id class
     */
    @Override
    public <Y> SingularAttribute<X, Y> getDeclaredId(Class<Y> type) {
        /**
         * We throw an IAE in 3 cases
         * 1) If the type is different from the javaType of the attribute
         * 2) If the id is not declared on (this) type
         * 3) If the id is not part of an IdClass (it is an EmbeddedId or just an Id)
         * 4) If the id does not exist on the hierarchy - never happens
         */
        // No need to check if an id exists - on an IdentifiableType - there is always at least one
        // This call will throw an IAE for 1) and 3)
        SingularAttribute<? super X, Y> anId = this.getId(type);
        // return the id only if it is declared on this IdentifableType
        // We know that the attribute exists - so the an IAE will be thrown for 2) for us
        return (SingularAttribute<X, Y>)getDeclaredAttribute(anId.getName(), true);
    }

    /**
     *  Return the attribute that corresponds to the version
     *  attribute declared by the entity or mapped superclass.
     *  @param type  the type of the represented declared version
     *               attribute
     *  @return declared version attribute
     *  @throws IllegalArgumentException if version attribute of the
     *          type is not declared in the identifiable type
     */
    @Override
    public <Y> SingularAttribute<X, Y> getDeclaredVersion(Class<Y> type) {
        /**
         * We throw an IAE in 3 cases
         * 1) If the type is different from the javaType of the attribute
         * 2) If the version is not declared on (this) type
         * 3) If the version does not exist on the hierarchy
         */
        // This call will throw an IAE for 1) and 3)
        SingularAttribute<? super X, Y> aVersion = this.getVersion(type);
        // return the version only if it is declared on this IdentifableType
        // We know that the attribute exists - so the an IAE will be thrown for 2) for us
        return (SingularAttribute<X, Y>)getDeclaredAttribute(aVersion.getName(), true);
    }

    /**
     *  Return the attributes corresponding to the id class of the
     *  identifiable type.
     *  @return id attributes
     *  @throws IllegalArgumentException if the identifiable type
     *          does not have an id class
     */
    @Override
    public Set<SingularAttribute<? super X, ?>> getIdClassAttributes() {
        // Get the list of IdClass attributes previously stored on the core project during metadata processing
        List<String> idClassNamesList = getMetamodel().getProject().getMetamodelIdClassMap()
            .get(getJavaType().getCanonicalName());
        // Check for IdClass existence
        if(null != idClassNamesList) {
            // All Id attributes are part of an IdClass
            return this.idAttributes;
        } else {
            // No IdClass attributes found - the IdentifiableType may still have a single @Id or an @EmbeddedId in this case
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage(
                    "metamodel_identifiable_type_has_no_idclass_attribute",
                    new Object[] {this}));
        }
    }

    /**
     *  Return the attribute that corresponds to the id attribute of
     *  the entity or mapped superclass.
     *  @param type  the type of the represented id attribute
     *  @return id attribute
     *  @throws IllegalArgumentException if id attribute of the given
     *          type is not present in the identifiable type or if
     *          the identifiable type has an id class
     */
    @Override
    public <Y> SingularAttribute<? super X, Y> getId(Class<Y> type) {
        // We assume that there is at most a single EmbeddedId
        SingularAttribute<? super X, Y> idAttribute = null;
        if(!hasSingleIdAttribute()) {
            // Id is part of an IdClass
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage(
                    "metamodel_identifiable_id_attribute_is_incorrect_idclass",
                    new Object[] { this }));
        } else {
            List<String> anAttributesMsg = new ArrayList<>();
            List<String> anAttributesJavaTypeMsg = new ArrayList<>();
            // verify single id attribute type
            for(SingularAttribute<? super X, ?> anAttribute : idAttributes) {
                // Verify type is correct - relax restriction on null and Object.class (from same classLoader)
                if(null == type || Object.class == type ||
                        type.getCanonicalName().equals(anAttribute.getJavaType().getCanonicalName())) {
                    idAttribute = (SingularAttribute<? super X, Y>) anAttribute;
                } else {
                    anAttributesMsg.add(anAttribute.toString());
                    anAttributesJavaTypeMsg.add(anAttribute.getJavaType().toString());
                }
            }
            if (idAttribute == null) {
                throw new IllegalArgumentException(ExceptionLocalization.buildMessage(
                        "metamodel_identifiable_id_attribute_type_incorrect",
                        new Object[] { anAttributesMsg, this, type, anAttributesJavaTypeMsg }));
            }
        }
        return idAttribute;
    }

    /**
     *  Return the type that represents the type of the id.
     *  @return type of id
     */
    @Override
    public Type<?> getIdType() {
        // NOTE: This code is another good reason to abstract out a PKPolicy on the descriptor
        CMPPolicy cmpPolicy = getDescriptor().getCMPPolicy();
        if (null == cmpPolicy) {
            // Composite key support (IE: @EmbeddedId)
            List<DatabaseMapping> pkMappings = getDescriptor().getObjectBuilder().getPrimaryKeyMappings();
            // Check the primaryKeyFields on the descriptor - for MappedSuperclass pseudo-Descriptors
            if(pkMappings.isEmpty()) {
                // Search the mappings for Id mappings
                for(DatabaseMapping aMapping : getDescriptor().getMappings()) {
                    if(aMapping.isJPAId()) {
                        // get the attribute Id (declared or not)
                        Attribute<X, ?> anAttribute = this.getAttribute(aMapping.getAttributeName());
                        if(anAttribute != null) {
                            return this.getMetamodel().getType(((Bindable)anAttribute).getBindableJavaType()); // all Attributes are Bindable
                        }
                    }
                }
            }

            if (pkMappings.size() == 1) {
                Class<?> aClass = pkMappings.get(0).getAttributeClassification(); // null for OneToOneMapping
                // lookup class in our types map
                return this.getMetamodel().getType(aClass);
            }
        }

        // Single Key support using any Java class - built in or user defined
        // There already is an instance of the PKclass on the policy
        if (cmpPolicy != null && cmpPolicy.isCMP3Policy()) {
            // BasicType, EntityType or IdentifiableType are handled here, lookup the class in the types map and create a wrapper if it does not exist yet
            return this.getMetamodel().getType(cmpPolicy.getPKClass());
        }
        // Non-specification mandated exception
        throw new IllegalArgumentException(ExceptionLocalization.buildMessage(
                "metamodel_incompatible_persistence_config_for_getIdType",
                new Object[] { this }));
    }

    /**
     *  Return the identifiable type that corresponds to the most
     *  specific mapped superclass or entity extended by the entity
     *  or mapped superclass.
     *  @return supertype of identifiable type or null if no such supertype
     */
    @Override
    public IdentifiableType<? super X> getSupertype() {
        return this.superType;
    }

    /**
     *  Return the attribute that corresponds to the version
     *    attribute of the entity or mapped superclass.
     *  @param type  the type of the represented version attribute
     *  @return version attribute
     *  @throws IllegalArgumentException if version attribute of the
     *          given type is not present in the identifiable type
     */
    @Override
    public <Y> SingularAttribute<? super X, Y> getVersion(Class<Y> type) {
        // Lazy load the version attribute if it exists
        if(null == getVersion()) {
            // No version exists - throw IAE
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage(
                "metamodel_identifiable_no_version_attribute_present",
                new Object[] { this }));
        } else {
            // Verify the type (Note: ClassLoaders do not have to be the same)
            // Relax restriction on null and Object.class (from same classLoader)
            if(null == type || Object.class == type ||
                    type.getCanonicalName().equals(versionAttribute.getJavaType().getCanonicalName())) {
                return (SingularAttribute<? super X, Y>)versionAttribute;
            } else {
                throw new IllegalArgumentException(ExceptionLocalization.buildMessage(
                    "metamodel_identifiable_version_attribute_type_incorrect",
                    new Object[] { versionAttribute, this, type, versionAttribute.getJavaType()}));
            }
        }
    }

    /**
     * INTERNAL:
     * Return the version attribute on this type.
     * If no version attribute exists - return null.
     */
    private <Y> SingularAttribute<? super X, ?> getVersion() {
        if(hasVersionAttribute()) {
            return versionAttribute;
        } else {
            return null;
        }
    }

    /**
     *  Whether or not the identifiable type has an id attribute.
     *  Returns true for a simple id or embedded id; returns false
     *  for an idclass.
     *  @return boolean indicating whether or not the identifiable
     *           type has a single id attribute
     */
    @Override
    public boolean hasSingleIdAttribute() {
        // The following section will return false for any multiple EmbeddableId as well as multiple Ids as part of an IdClass
        // Note: there will always be at least 1 Id for an IdentifiableType

        /**
         * Since we are in IdentifiableType which involves only Entities and MappedSuperclasses,
         * we are safe to assume that there will always be an Id of some sort - we are not in
         * Basic, Embeddable or transient types.
         * Check the core API project for any IdClass matching this IdentifiableType
         * after we check directly on the descriptor for an Id.
         *  References: SubQueryImpl.select()
         */

        // Note: this function will return false only if an IdClass is present
        List<DatabaseField> pkFields = this.getDescriptor().getPrimaryKeyFields();
        // return false for no Id field types
        if(pkFields.isEmpty()) {
            return false;
        } else {
            // Optional: Verify the mapping on the each field and whether it is an IdClass
            Class<?> pkClass = null;
            if(this.getDescriptor().hasCMPPolicy()) {
                pkClass = this.getDescriptor().getCMPPolicy().getPKClass();
                if(null == pkClass) {
                    return false;
                }
            } else {
                // MappedSuperclass descriptors do not have a CMP policy yet because the are not initialized
                return pkFields.size() < 2;
            }

            // 288792: Search the values of the list of IdClass attribute names stored on the project
            for (List<String> idClassNamesList : getMetamodel().getProject().getMetamodelIdClassMap().values()) {
                for(String idClassName : idClassNamesList) {
                    if(idClassName.equals(pkClass.getCanonicalName())) {
                        return false;
                    }
                }
            }
        }
        return true;
    }

    /**
     *  Whether or not the identifiable type has a version attribute.
     *  @return boolean indicating whether or not the identifiable
     *           type has a version attribute
     */
    @Override
    public boolean hasVersionAttribute() {
        // The versionAttribute is lazy loaded
        if(null != versionAttribute) {
            return true;
        } else {
            for(Attribute attribute : this.getAttributes()) {
                if(!((AttributeImpl)attribute).isPlural() && ((SingularAttribute)attribute).isVersion()) {
                    versionAttribute = (SingularAttribute)attribute;
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * INTERNAL:
     * Return whether this type is identifiable.
     * This would be EntityType and MappedSuperclassType
     */
    @Override
    protected boolean isIdentifiableType() {
        return true;
    }

    /**
     * INTERNAL:
     * Set the superType for this IdentifiableType - only after all ManagedTypes
     * have been instantiated for this Metamodel.<p>
     * Top-level identifiable types have their supertype set to null.
     *
     * @param superType - the entity or mappedSuperclass superType
     */
    protected void setSupertype(IdentifiableType<? super X> superType) {
        // See design issue #42 - we return null for top-level types (with no superclass) as well as unset supertypes
        // http://wiki.eclipse.org/EclipseLink/Development/JPA_2.0/metamodel_api#DI_42:_20090709:_IdentifiableType.supertype_-_what_do_top-level_types_set_it_to
        this.superType = superType;
    }
}
