/*
 * 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:
//     01/28/2009-2.0 Guy Pelletier
//       - 248293: JPA 2.0 Element Collections (part 1)
//     02/06/2009-2.0 Guy Pelletier
//       - 248293: JPA 2.0 Element Collections (part 2)
//     02/25/2009-2.0 Guy Pelletier
//       - 265359: JPA 2.0 Element Collections - Metadata processing portions
//     03/27/2009-2.0 Guy Pelletier
//       - 241413: JPA 2.0 Add EclipseLink support for Map type attributes
//     06/02/2009-2.0 Guy Pelletier
//       - 278768: JPA 2.0 Association Override Join Table
//     11/06/2009-2.0 Guy Pelletier
//       - 286317: UniqueConstraint xml element is changing (plus couple other fixes, see bug)
//     03/08/2010-2.1 Guy Pelletier
//       - 303632: Add attribute-type for mapping attributes to EclipseLink-ORM
//     03/29/2010-2.1 Guy Pelletier
//       - 267217: Add Named Access Type to EclipseLink-ORM
//     04/27/2010-2.1 Guy Pelletier
//       - 309856: MappedSuperclasses from XML are not being initialized properly
//     12/30/2010-2.3 Guy Pelletier
//       - 312253: Descriptor exception with Embeddable on DDL gen
//     03/24/2011-2.3 Guy Pelletier
//       - 337323: Multi-tenant with shared schema support (part 1)
//     07/03/2011-2.3.1 Guy Pelletier
//       - 348756: m_cascadeOnDelete boolean should be changed to Boolean
//      //     30/05/2012-2.4 Guy Pelletier
//       - 354678: Temp classloader is still being used during metadata processing
//     10/25/2012-2.5 Guy Pelletier
//       - 3746888: JPA 2.1 Converter support
//     11/28/2012-2.5 Guy Pelletier
//       - 374688: JPA 2.1 Converter support
//     07/16/2013-2.5.1 Guy Pelletier
//       - 412384: Applying Converter for parameterized basic-type for joda-time's DateTime does not work
package org.eclipse.persistence.internal.jpa.metadata.accessors.mappings;

import org.eclipse.persistence.annotations.BatchFetch;
import org.eclipse.persistence.annotations.CascadeOnDelete;
import org.eclipse.persistence.annotations.JoinFetch;
import org.eclipse.persistence.annotations.Noncacheable;
import org.eclipse.persistence.internal.helper.DatabaseTable;
import org.eclipse.persistence.internal.jpa.metadata.MetadataDescriptor;
import org.eclipse.persistence.internal.jpa.metadata.MetadataLogger;
import org.eclipse.persistence.internal.jpa.metadata.accessors.classes.ClassAccessor;
import org.eclipse.persistence.internal.jpa.metadata.accessors.objects.MetadataAccessibleObject;
import org.eclipse.persistence.internal.jpa.metadata.accessors.objects.MetadataAnnotation;
import org.eclipse.persistence.internal.jpa.metadata.mappings.BatchFetchMetadata;
import org.eclipse.persistence.internal.jpa.metadata.tables.CollectionTableMetadata;
import org.eclipse.persistence.internal.jpa.metadata.xml.XMLEntityMappings;

import org.eclipse.persistence.mappings.AggregateCollectionMapping;
import org.eclipse.persistence.mappings.AggregateMapping;
import org.eclipse.persistence.mappings.CollectionMapping;
import org.eclipse.persistence.mappings.ContainerMapping;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.DirectCollectionMapping;
import org.eclipse.persistence.mappings.DirectMapMapping;
import org.eclipse.persistence.mappings.ForeignReferenceMapping;
import org.eclipse.persistence.mappings.foundation.AbstractCompositeDirectCollectionMapping;

import static org.eclipse.persistence.internal.jpa.metadata.MetadataConstants.JPA_FETCH_LAZY;

/**
 * An abstract direct collection accessor.
 *
 * Used to support DirectCollection, DirectMap, AggregateCollection through
 * the ElementCollection, BasicCollection and BasicMap metadata.
 *
 * Key notes:
 * - any metadata mapped from XML to this class must be compared in the
 *   equals method.
 * - any metadata mapped from XML to this class must be handled in the merge
 *   method. (merging is done at the accessor/mapping level)
 * - any metadata mapped from XML to this class must be initialized in the
 *   initXMLObject  method.
 * - methods should be preserved in alphabetical order.
 *
 * @author Guy Pelletier
 * @since EclipseLink 1.2
 */
public abstract class DirectCollectionAccessor extends DirectAccessor {
    private BatchFetchMetadata m_batchFetch;
    private Boolean m_cascadeOnDelete;
    private Boolean m_nonCacheable;
    private String m_joinFetch;
    private CollectionTableMetadata m_collectionTable;

    /**
     * INTERNAL:
     */
    protected DirectCollectionAccessor(String xmlElement) {
        super(xmlElement);
    }

    /**
     * INTERNAL:
     */
    protected DirectCollectionAccessor(MetadataAnnotation annotation, MetadataAccessibleObject accessibleObject, ClassAccessor classAccessor) {
        super(annotation, accessibleObject, classAccessor);

        // Set the fetch type. A basic map may have no annotation (will default).
        if (annotation != null) {
            setFetch(annotation.getAttributeString("fetch"));
        }

        // Set the join fetch if one is present.
        if (isAnnotationPresent(JoinFetch.class)) {
            m_joinFetch = getAnnotation(JoinFetch.class).getAttributeString("value");
        }

        // Set the batch fetch if one is present.
        if (isAnnotationPresent(BatchFetch.class)) {
            m_batchFetch = new BatchFetchMetadata(getAnnotation(BatchFetch.class), this);
        }

        // Set the cascade on delete if specified.
        m_cascadeOnDelete = isAnnotationPresent(CascadeOnDelete.class);

        // Set the non cacheable if specified.
        m_nonCacheable = isAnnotationPresent(Noncacheable.class);

        // Since BasicCollection and ElementCollection look for different
        // collection tables, we will not initialize/look for one here. Those
        // accessors will be responsible for loading their collection table.
    }

    /**
     * INTERNAL:
     */
    @Override
    public boolean equals(Object objectToCompare) {
        if (super.equals(objectToCompare) && objectToCompare instanceof DirectCollectionAccessor) {
            DirectCollectionAccessor directCollectionAccessor = (DirectCollectionAccessor) objectToCompare;

            if (! valuesMatch(m_joinFetch, directCollectionAccessor.getJoinFetch())) {
                return false;
            }

            if (! valuesMatch(m_batchFetch, directCollectionAccessor.getBatchFetch())) {
                return false;
            }

            if (! valuesMatch(m_cascadeOnDelete, directCollectionAccessor.getCascadeOnDelete())) {
                return false;
            }

            if (! valuesMatch(m_nonCacheable, directCollectionAccessor.getNonCacheable())) {
                return false;
            }

            return valuesMatch(m_collectionTable, directCollectionAccessor.getCollectionTable());
        }

        return false;
    }

    @Override
    public int hashCode() {
        int result = super.hashCode();
        result = 31 * result + (m_batchFetch != null ? m_batchFetch.hashCode() : 0);
        result = 31 * result + (m_cascadeOnDelete != null ? m_cascadeOnDelete.hashCode() : 0);
        result = 31 * result + (m_nonCacheable != null ? m_nonCacheable.hashCode() : 0);
        result = 31 * result + (m_joinFetch != null ? m_joinFetch.hashCode() : 0);
        result = 31 * result + (m_collectionTable != null ? m_collectionTable.hashCode() : 0);
        return result;
    }

    /**
     * INTERNAL:
     * Used for OX mapping.
     */
    public BatchFetchMetadata getBatchFetch() {
        return m_batchFetch;
    }

    /**
     * INTERNAL:
     * Used for OX mapping.
     */
    public Boolean getCascadeOnDelete() {
        return m_cascadeOnDelete;
    }

    /**
     * INTERNAL:
     * Used for OX mapping.
     */
    public CollectionTableMetadata getCollectionTable() {
        return m_collectionTable;
    }

    /**
     * INTERNAL:
     */
    protected String getDefaultCollectionTableName() {
        return getOwningDescriptor().getAlias() + "_" + getDefaultAttributeName();
    }

    /**
     * INTERNAL:
     */
    @Override
    public String getDefaultFetchType() {
        return JPA_FETCH_LAZY;
    }

    /**
     * INTERNAL:
     * Used for OX mapping.
     */
    public String getJoinFetch() {
        return m_joinFetch;
    }

    /**
     * INTERNAL:
     * Used for OX mapping.
     */
    public String getPrivateOwned() {
        return null;
    }

    /**
     * INTERNAL:
     * The reference table in a direct collection case is the collection table.
     */
    @Override
    protected DatabaseTable getReferenceDatabaseTable() {
        if (m_collectionTable == null) {
            return null;
        }
        return m_collectionTable.getDatabaseTable();
    }

    /**
     * INTERNAL:
     * In a direct collection case, there is no notion of a reference
     * descriptor, therefore we return this accessors descriptor.
     */
    @Override
    public MetadataDescriptor getReferenceDescriptor() {
        return getDescriptor();
    }

    /**
     * INTERNAL:
     * Return the converter name for a map key.
     */
    protected abstract String getKeyConverter();

    /**
     * INTERNAL:
     * Used for OX mapping.
     */
    public Boolean getNonCacheable(){
        return m_nonCacheable;
    }

    /**
     * INTERNAL:
     * Return the converter name for a collection value.
     * @see BasicMapAccessor for override details. An EclipseLink
     * BasicMapAccessor can specify a value converter within the BasicMap
     * metadata. Otherwise for all other cases, BasicCollectionAccessor and
     * ElementCollectionAccessor, the value converter is returned from a Convert
     * metadata specification.
     */
    protected String getValueConverter() {
        return getConvert();
    }

    /**
     * INTERNAL:
     * Return true if this accessor has a map key class specified.
     * @see ElementCollectionAccessor
     */
    protected boolean hasMapKeyClass() {
        return false;
    }

    /**
     * INTERNAL:
     */
    @Override
    public void initXMLObject(MetadataAccessibleObject accessibleObject, XMLEntityMappings entityMappings) {
        super.initXMLObject(accessibleObject, entityMappings);

        // Initialize single objects.
        initXMLObject(m_collectionTable, accessibleObject);
    }

    /**
     * INTERNAL:
     */
    public Boolean isCascadeOnDelete() {
        return m_cascadeOnDelete != null && m_cascadeOnDelete;
    }

    /**
     * INTERNAL:
     * Return true if this accessor represents a direct collection mapping,
     * which include basic collection, basic map and element collection
     * accessors.
     */
    @Override
    public boolean isDirectCollection() {
        return true;
    }

    /**
     * INTERNAL:
     * Used for OX mapping.
     */
    public boolean isNonCacheable() {
        return m_nonCacheable != null && m_nonCacheable;
    }

    /**
     * INTERNAL:
     * Returns true if the given class is a valid basic collection type.
     */
    protected boolean isValidDirectCollectionType() {
        return getAccessibleObject().isSupportedCollectionClass(getRawClass());
    }

    /**
     * INTERNAL:
     * Returns true if the given class is a valid basic map type.
     */
    protected boolean isValidDirectMapType() {
        return getAccessibleObject().isSupportedMapClass(getRawClass());
    }

    /**
     * INTERNAL:
     */
    protected void process(DatabaseMapping mapping) {
        // Add the mapping to the descriptor.
        setMapping(mapping);

        // Set the attribute name.
        mapping.setAttributeName(getAttributeName());

        // Will check for PROPERTY access
        setAccessorMethods(mapping);

        if (mapping instanceof CollectionMapping) {
            CollectionMapping collectionMapping = (CollectionMapping)mapping;

            // Set the reference class name.
            collectionMapping.setReferenceClassName(getReferenceClassName());

            // Process join fetch type.
            processJoinFetch(getJoinFetch(), collectionMapping);

            // Process the batch fetch if specified.
            processBatchFetch(collectionMapping);

            // Process the collection table.
            processCollectionTable(collectionMapping);

            // The spec. requires pessimistic lock to be extend-able to CollectionTable
            collectionMapping.setShouldExtendPessimisticLockScope(true);

            // Set the cascade on delete if specified.
            collectionMapping.setIsCascadeOnDeleteSetOnDatabase(isCascadeOnDelete());
        } else if (mapping instanceof AggregateMapping) {
            AggregateMapping aggregateMapping = (AggregateMapping)mapping;

            // Set the reference class name.
            aggregateMapping.setReferenceClassName(getReferenceClassName());
        }

        // Set the non cacheable if specified.
        mapping.setIsCacheable(!isNonCacheable());

        // Process a @ReturnInsert and @ReturnUpdate (to log a warning message)
        processReturnInsertAndUpdate();

        // Process any partitioning policies.
        processPartitioning();
    }

    /**
     * INTERNAL:
     * Set the batch fetch type on the foreign reference mapping.
     */
    protected void processBatchFetch(ForeignReferenceMapping mapping) {
        if (m_batchFetch != null) {
            m_batchFetch.process(mapping);
        }
    }

    /**
     * INTERNAL:
     * Process a MetadataCollectionTable. Sub classes should call this to
     * ensure a table is defaulted.
     */
    protected void processCollectionTable(CollectionMapping mapping) {
        // Check that we loaded a collection table otherwise default one.
        if (m_collectionTable == null) {
            m_collectionTable = new CollectionTableMetadata(this);
        }

        // Process any table defaults and log warning messages.
        processTable(m_collectionTable, getDefaultCollectionTableName());

        // Set the reference table on the mapping.
        if (isDirectEmbeddableCollection()) {
            ((AggregateCollectionMapping) mapping).setDefaultSourceTable(m_collectionTable.getDatabaseTable());
        } else {
            ((DirectCollectionMapping) mapping).setReferenceTable(m_collectionTable.getDatabaseTable());
        }
    }

    /**
     * INTERNAL:
     */
    protected void processDirectCollectionMapping() {
        // Initialize our mapping.
        DatabaseMapping mapping = getOwningDescriptor().getClassDescriptor().newDirectCollectionMapping();

        // Process common direct collection metadata. This must be done
        // before any field processing since field processing requires that
        // the collection table be processed before hand.
        process(mapping);

        processContainerPolicyAndIndirection((ContainerMapping) mapping);

        if (mapping instanceof DirectCollectionMapping) {
            DirectCollectionMapping directCollectionMapping = (DirectCollectionMapping) mapping;
            // Process the container and indirection policies.

            // Process the value column (we must process this field before the
            // call to processConverter, since it may set a field classification)
            directCollectionMapping.setDirectField(getDatabaseField(getReferenceDatabaseTable(), MetadataLogger.VALUE_COLUMN));

            // To resolve any generic types (or respect an attribute type
            // specification) we need to set the attribute classification on the
            // mapping to ensure we do the right conversions.
            if (hasAttributeType() || getAccessibleObject().isGenericCollectionType()) {
                directCollectionMapping.setDirectFieldClassificationName(getJavaClassName(getReferenceClass()));
            }
        } else if (mapping.isAbstractCompositeDirectCollectionMapping()) {
            ((AbstractCompositeDirectCollectionMapping) mapping).setField(getDatabaseField(getDescriptor().getPrimaryTable(), MetadataLogger.COLUMN));
        }

        // Process a converter for this mapping. We will look for a convert
        // value. If none is found then we'll look for a JPA converter, that
        // is, Enumerated, Lob and Temporal. With everything falling into
        // a serialized mapping if no converter whatsoever is found.
        processMappingValueConverter(mapping, getValueConverter(), getConverts(), getReferenceClass(), getReferenceClassWithGenerics());
    }

    /**
     * INTERNAL:
     */
    protected void processDirectMapMapping() {
        // Initialize and process common direct collection metadata. This must
        // be done before any field processing since field processing requires
        // that the collection table be processed before hand.
        DirectMapMapping mapping = new DirectMapMapping();
        process(mapping);

        // Process the container and indirection policies.
        processContainerPolicyAndIndirection(mapping);

        // Process the key column (we must process this field before the
        // call to processConverter, since it may set a field classification)
        mapping.setDirectKeyField(getDatabaseField(getReferenceDatabaseTable(), MetadataLogger.MAP_KEY_COLUMN));

        // Only process the key converter if this is a basic map accessor. The
        // key converter for an element collection case will be taken care of
        // in the processContainerPolicyAndIndirection call above.
        if (isBasicMap()) {
            // To resolve any generic types (or respect an attribute type
            // specification) we need to set the attribute classification on the
            // mapping to ensure we do the right conversions.
            if (hasAttributeType() || getAccessibleObject().isGenericCollectionType()) {
                mapping.setDirectKeyFieldClassificationName(getJavaClassName(getMapKeyReferenceClass()));
            }

            // Process a converter for the key column of this mapping.
            processMappingKeyConverter(mapping, getKeyConverter(), null, getMapKeyReferenceClass(), getMapKeyReferenceClassWithGenerics());
        }

        // Process the value column (we must process this field before the call
        // to processConverter, since it may set a field classification)
        mapping.setDirectField(getDatabaseField(getReferenceDatabaseTable(), MetadataLogger.VALUE_COLUMN));

        // To resolve any generic types (or respect an attribute type
        // specification) we need to set the attribute classification on the
        // mapping to ensure we do the right conversions.
        if (hasAttributeType() || getAccessibleObject().isGenericCollectionType()) {
            mapping.setDirectFieldClassificationName(getJavaClassName(getReferenceClass()));
        }

        // Process a converter for value column of this mapping.
        processMappingValueConverter(mapping, getValueConverter(), getConverts(), getReferenceClass(), getReferenceClassWithGenerics());
    }

    /**
     * INTERNAL:
     * Used for OX mapping.
     */
    public void setBatchFetch(BatchFetchMetadata batchFetch) {
        m_batchFetch = batchFetch;
    }

    /**
     * INTERNAL:
     * Used for OX mapping.
     */
    public void setCascadeOnDelete(Boolean cascadeOnDelete) {
        m_cascadeOnDelete = cascadeOnDelete;
    }

    /**
     * INTERNAL:
     * Used for OX mapping.
     */
    public void setCollectionTable(CollectionTableMetadata collectionTable) {
        m_collectionTable = collectionTable;
    }

    /**
     * INTERNAL:
     * Used for OX mapping.
     */
    public void setNonCacheable(Boolean nonCacheable){
        m_nonCacheable = nonCacheable;
    }

    /**
     * INTERNAL:
     * Used for OX mapping.
     */
    public void setJoinFetch(String joinFetch) {
        m_joinFetch = joinFetch;
    }
}
