/*
 * 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:
//     05/26/2009-2.0  mobrien - API update
//       - 266912: JPA 2.0 Metamodel API (part of the JSR-317 EJB 3.1 Criteria API)
//     06/30/2009-2.0  mobrien - finish JPA Metadata API modifications in support
//       of the Metamodel implementation for EclipseLink 2.0 release involving
//       Map, ElementCollection and Embeddable types on MappedSuperclass descriptors
//     08/06/2010-2.2 mobrien 322018 - reduce protected instance variables to private to enforce encapsulation
//     11/10/2011-2.4 Guy Pelletier
//       - 357474: Address primaryKey option from tenant discriminator column
package org.eclipse.persistence.internal.jpa.metamodel;

import java.lang.reflect.Field;

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

import org.eclipse.persistence.internal.descriptors.OptimisticLockingPolicy;
import org.eclipse.persistence.logging.AbstractSessionLog;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.mappings.AggregateMapping;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.ForeignReferenceMapping;
import org.eclipse.persistence.mappings.VariableOneToOneMapping;
import org.eclipse.persistence.mappings.foundation.AbstractDirectMapping;
import org.eclipse.persistence.mappings.structures.ReferenceMapping;

/**
 * <p>
 * <b>Purpose</b>: Provides the implementation for the SingularAttribute 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 SingularAttribute represents persistent
 * single-valued properties or fields.
 *
 * @author Michael O'Brien
 * @see jakarta.persistence.metamodel.SingularAttribute
 * @since EclipseLink 1.2 - JPA 2.0
 *
 * @param <X> The type containing the represented attribute
 * @param <T> The type of the represented attribute
 *
 */
public class SingularAttributeImpl<X, T> extends AttributeImpl<X, T> implements SingularAttribute<X, T> {

    /** Item 54: DI 89: explicit UID will avoid performance hit runtime generation of one */
    private static final long serialVersionUID = 3928292425281232234L;

    /** The Type representing this Entity or Basic type **/
    private Type<T> elementType;

    /**
     * Create an instance of the Attribute
     * @param managedType
     * @param mapping
     */
    protected SingularAttributeImpl(ManagedTypeImpl<X> managedType, DatabaseMapping mapping) {
        this(managedType, mapping, false);
    }
    /**
     * INTERNAL:
     * Create an Attribute instance with a passed in validation flag (usually set to true only during Metamodel initialization)
     * @param managedType
     * @param mapping
     * @param validationEnabled
     */
    protected SingularAttributeImpl(ManagedTypeImpl<X> managedType, DatabaseMapping mapping, boolean validationEnabled) {
        super(managedType, mapping);
        // Case: Handle primitive or java lang type (non-Entity) targets
        Class attributeClass = mapping.getAttributeClassification();
        /**
         * Case: Handle Entity targets
         * Process supported mappings by assigning their elementType.
         * For unsupported mappings we default to MetamodelImpl.DEFAULT_ELEMENT_TYPE.
         * If attribute is a primitive type (non-null) - we will wrap it in a BasicType automatically in getType below
         * The attribute classification is null for non-collection mappings such as embeddable keys.
         */
        if (null == attributeClass) {

            // We support @OneToOne but not EIS, Reference or VariableOneToOne
            // Note: OneToMany, ManyToMany are handled by PluralAttributeImpl
            if(mapping instanceof ForeignReferenceMapping) {// handles @ManyToOne
                attributeClass = ((ForeignReferenceMapping)mapping).getReferenceClass();
            } else if (mapping.isAbstractDirectMapping()) { // Also handles the keys of an EmbeddedId
                attributeClass = mapping.getField().getType();
                if(null == attributeClass) {
                    // lookup the attribute on the containing class
                    attributeClass = managedType.getTypeClassFromAttributeOrMethodLevelAccessor(mapping);
                }
            } else if (mapping.isAggregateObjectMapping()) { // IE: EmbeddedId
                attributeClass = ((AggregateMapping)mapping).getReferenceClass();
            } else if (mapping.isVariableOneToOneMapping()) { // interfaces are unsupported in the JPA 2.0 spec for the Metamodel API
                if(validationEnabled) {
                    AbstractSessionLog.getLog().log(SessionLog.FINEST, SessionLog.METAMODEL, "metamodel_mapping_type_is_unsupported", mapping, this);
                }
                // see JUnitCriteriaUnitTestSuite.testSelectPhoneNumberAreaCode() line: 246
                // VariableOneToOne mappings are unsupported - default to referenceClass (Interface) anyway
                // see interface org.eclipse.persistence.testing.models.jpa.relationships.Distributor
                attributeClass = ((VariableOneToOneMapping)mapping).getReferenceClass();
            } else if (mapping.isEISMapping() || mapping.isTransformationMapping()) { // unsupported in the JPA 2.0 spec for the Metamodel API
                if(validationEnabled) {
                    AbstractSessionLog.getLog().log(SessionLog.FINEST, SessionLog.METAMODEL, "metamodel_mapping_type_is_unsupported", mapping, this);
                }
            } else if ( mapping.isReferenceMapping()) { // unsupported in the JPA 2.0 spec for the Metamodel API
                if(validationEnabled) {
                    AbstractSessionLog.getLog().log(SessionLog.FINEST, SessionLog.METAMODEL, "metamodel_mapping_type_is_unsupported", mapping, this);
                }
                // Reference mappings are unsupported - default to referenceClass anyway
                attributeClass = ((ReferenceMapping)mapping).getReferenceClass();
            }
        }
        // All unsupported mappings such as TransformationMapping
        if(null == attributeClass && validationEnabled) {
            // TODO: refactor
            attributeClass = MetamodelImpl.DEFAULT_ELEMENT_TYPE_FOR_UNSUPPORTED_MAPPINGS;
            AbstractSessionLog.getLog().log(SessionLog.FINEST, SessionLog.METAMODEL, "metamodel_attribute_class_type_is_null", this);
        }
        elementType = getMetamodel().getType(attributeClass);
    }

    /**
     * Return the Java type of the represented object.
     * If the bindable type of the object is <code>PLURAL_ATTRIBUTE</code>,
     * the Java element type is returned. If the bindable type is
     * <code>SINGULAR_ATTRIBUTE</code> or <code>ENTITY_TYPE</code>,
     * the Java type of the
     * represented entity or attribute is returned.
     * @return Java type
     */
    @Override
    public Class<T> getBindableJavaType() {
        // In SingularAttribute our BindableType is SINGLE_ATTRIBUTE - return the java type of the represented entity
        return this.elementType.getJavaType();
    }

    /**
     *  Is the attribute an id attribute.
     *  @return boolean indicating whether or not attribute is an id
     */
    @Override
    public boolean isId() {
        if(this.getManagedTypeImpl().isMappedSuperclass()) {
            // The field on the mapping is the same field in the pkFields list on the descriptor
            // 288792: We can use the new isJPAId field here
            return (this.getDescriptor().getPrimaryKeyFields().contains(this.getMapping().getField()));
        } else {
            // 288792: Some id mappings will return false for isPrimaryKeyMapping but true for isJPAId
            return getMapping().isPrimaryKeyMapping() || getMapping().isJPAId();
        }
    }

    /**
     *  Can the attribute be null.
     *  @return boolean indicating whether or not the attribute can
     *          be null
     */
    @Override
    public boolean isOptional() {
        return getMapping().isOptional();
    }


    /**
     * INTERNAL:
     * Return whether the attribute is plural or singular
     * @return
     */
    @Override
    public boolean isPlural() {
        return false;
    }

    /**
     *  Is the attribute a version attribute.
     *  @return boolean indicating whether or not attribute is
     *          a version attribute
     */
    @Override
    public boolean isVersion() {
        if (getDescriptor().usesOptimisticLocking() && getMapping().isDirectToFieldMapping()) {
            OptimisticLockingPolicy policy = getDescriptor().getOptimisticLockingPolicy();

            return policy.getWriteLockField().equals(getMapping().getField());
        }
        return false;
    }

    @Override
    public Bindable.BindableType getBindableType() {
        return Bindable.BindableType.SINGULAR_ATTRIBUTE;
    }

    /**
     *  Return the Java type of the represented attribute.
     *  @return Java type
     */
    @Override
    public Class<T> getJavaType() {
        if(null == elementType) {
            Class aJavaType = getMapping().getAttributeClassification();
            if(null == aJavaType) {
                aJavaType = getMapping().getField().getType();
                if(null == aJavaType) {
                    // lookup the attribute on the containing class
                    Class containingClass = getMapping().getDescriptor().getJavaClass();
                    Field aField = null;
                    try {
                        aField = containingClass.getDeclaredField(getMapping().getAttributeName());
                        aJavaType = aField.getType();
                        return aJavaType;
                    } catch (NoSuchFieldException nsfe) {
                        // This exception will be warned about below
                        if(null == aJavaType) {
                            AbstractSessionLog.getLog().log(SessionLog.FINEST, SessionLog.METAMODEL, "metamodel_attribute_class_type_is_null", this);
                            return MetamodelImpl.DEFAULT_ELEMENT_TYPE_FOR_UNSUPPORTED_MAPPINGS;
                        }
                    }
                }
            }
            return aJavaType;
        } else {
            return this.elementType.getJavaType();
        }
    }

    /**
     * Return the type that represents the type of the attribute.
     * @return type of attribute
     */
    @Override
    public Type<T> getType() {
        return elementType;
    }

    /**
     * Return the String representation of the receiver.
     */
    @Override
    public String toString() {
        StringBuffer aBuffer = new StringBuffer("SingularAttributeImpl[");
        aBuffer.append(getType());
        aBuffer.append(",");
        aBuffer.append(getMapping());
        aBuffer.append("]");
        return aBuffer.toString();
    }
}
