/*
 * Copyright (c) 1998, 2020 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/16/2008-1.0M8 Guy Pelletier
//       - 218084: Implement metadata merging functionality between mapping files
//     09/23/2008-1.1 Guy Pelletier
//       - 241651: JPA 2.0 Access Type support
//     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)
//     03/27/2009-2.0 Guy Pelletier
//       - 241413: JPA 2.0 Add EclipseLink support for Map type attributes
//     04/24/2009-2.0 Guy Pelletier
//       - 270011: JPA 2.0 MappedById support
//     06/02/2009-2.0 Guy Pelletier
//       - 278768: JPA 2.0 Association Override Join Table
//     11/23/2009-2.0 Guy Pelletier
//       - 295790: JPA 2.0 adding @MapsId to one entity causes initialization errors in other entities
//     04/27/2010-2.1 Guy Pelletier
//       - 309856: MappedSuperclasses from XML are not being initialized properly
//     03/24/2011-2.3 Guy Pelletier
//       - 337323: Multi-tenant with shared schema support (part 1)
//     10/09/2012-2.5 Guy Pelletier
//       - 374688: JPA 2.1 Converter support
//     10/25/2012-2.5 Guy Pelletier
//       - 374688: JPA 2.1 Converter support
//     11/19/2012-2.5 Guy Pelletier
//       - 389090: JPA 2.1 DDL Generation Support (foreign key metadata support)
//     11/28/2012-2.5 Guy Pelletier
//       - 374688: JPA 2.1 Converter support
package org.eclipse.persistence.internal.jpa.metadata.accessors.mappings;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.persistence.internal.helper.DatabaseField;
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.columns.AssociationOverrideMetadata;
import org.eclipse.persistence.internal.jpa.metadata.columns.AttributeOverrideMetadata;
import org.eclipse.persistence.internal.jpa.metadata.converters.ConvertMetadata;
import org.eclipse.persistence.internal.jpa.metadata.xml.XMLEntityMappings;

import org.eclipse.persistence.mappings.AggregateMapping;
import org.eclipse.persistence.mappings.AggregateObjectMapping;
import org.eclipse.persistence.mappings.EmbeddableMapping;
import org.eclipse.persistence.mappings.foundation.AbstractCompositeObjectMapping;

import static org.eclipse.persistence.internal.jpa.metadata.MetadataConstants.JPA_ATTRIBUTE_OVERRIDE;
import static org.eclipse.persistence.internal.jpa.metadata.MetadataConstants.JPA_ATTRIBUTE_OVERRIDES;
import static org.eclipse.persistence.internal.jpa.metadata.MetadataConstants.JPA_ASSOCIATION_OVERRIDE;
import static org.eclipse.persistence.internal.jpa.metadata.MetadataConstants.JPA_ASSOCIATION_OVERRIDES;

/**
 * An embedded relationship accessor. It may define all the same attributes
 * as an entity, therefore, it also must handle nesting embedded's to the nth
 * level. An embedded owning descriptor is a reference back to the actual
 * owning entity's descriptor where the first embedded was discovered.
 *
 * 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 TopLink EJB 3.0 Reference Implementation
 */
public class EmbeddedAccessor extends MappingAccessor {
    private List<ConvertMetadata> m_converts;
    private List<AssociationOverrideMetadata> m_associationOverrides = new ArrayList<AssociationOverrideMetadata>();
    private List<AttributeOverrideMetadata> m_attributeOverrides = new ArrayList<AttributeOverrideMetadata>();

    /**
     * INTERNAL:
     * Used for OX mapping.
     */
    public EmbeddedAccessor() {
        super("<embedded>");
    }

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

    /**
     * INTERNAL:
     */
    public EmbeddedAccessor(MetadataAnnotation embedded, MetadataAccessibleObject accessibleObject, ClassAccessor classAccessor) {
        super(embedded, accessibleObject, classAccessor);

        // Set the attribute overrides if some are present.
        // Process the attribute overrides first.
        if (isAnnotationPresent(JPA_ATTRIBUTE_OVERRIDES)) {
            for (Object attributeOverride : getAnnotation(JPA_ATTRIBUTE_OVERRIDES).getAttributeArray("value")) {
                m_attributeOverrides.add(new AttributeOverrideMetadata((MetadataAnnotation) attributeOverride, this));
            }
        }

        // Process the single attribute override second.
        if (isAnnotationPresent(JPA_ATTRIBUTE_OVERRIDE)) {
            m_attributeOverrides.add(new AttributeOverrideMetadata(getAnnotation(JPA_ATTRIBUTE_OVERRIDE), this));
        }

        // Set the association overrides if some are present.
        // Process the attribute overrides first.
        if (isAnnotationPresent(JPA_ASSOCIATION_OVERRIDES)) {
            for (Object associationOverride : getAnnotation(JPA_ASSOCIATION_OVERRIDES).getAttributeArray("value")) {
                m_associationOverrides.add(new AssociationOverrideMetadata((MetadataAnnotation) associationOverride, this));
            }
        }

        // Process the single attribute override second.
        if (isAnnotationPresent(JPA_ASSOCIATION_OVERRIDE)) {
            m_associationOverrides.add(new AssociationOverrideMetadata(getAnnotation(JPA_ASSOCIATION_OVERRIDE), this));
        }
    }

    /**
     * INTERNAL:
     * Subclasses that support key converts need to override this method.
     */
    @Override
    protected void addConvert(ConvertMetadata convert) {
        if (m_converts == null) {
            m_converts = new ArrayList<ConvertMetadata>();
        }

        m_converts.add(convert);
    }

    /**
     * INTERNAL:
     */
    public void addMapsIdAccessor(MappingAccessor mapsIdAccessor) {
        ((AggregateObjectMapping) getMapping()).addMapsIdMapping(mapsIdAccessor.getMapping());
    }

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

            if (! valuesMatch(m_associationOverrides, embeddedAccessor.getAssociationOverrides())) {
                return false;
            }

            if (! valuesMatch(m_attributeOverrides, embeddedAccessor.getAttributeOverrides())) {
                return false;
            }

            return valuesMatch(m_converts, embeddedAccessor.getConverts());
        }

        return false;
    }

    @Override
    public int hashCode() {
        int result = super.hashCode();
        result = 31 * result + (m_converts != null ? m_converts.hashCode() : 0);
        result = 31 * result + (m_associationOverrides != null ? m_associationOverrides.hashCode() : 0);
        result = 31 * result + (m_attributeOverrides != null ? m_attributeOverrides.hashCode() : 0);
        return result;
    }

    /**
     * INTERNAL:
     * Used for OX mapping.
     */
    public List<AssociationOverrideMetadata> getAssociationOverrides() {
        return m_associationOverrides;
    }

    /**
     * INTERNAL:
     * Used for OX mapping.
     */
    public List<AttributeOverrideMetadata> getAttributeOverrides() {
        return m_attributeOverrides;
    }

    /**
     * INTERNAL:
     * Used for OX mapping.
     */
    public List<ConvertMetadata> getConverts() {
        return m_converts;
    }

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

        // Initialize lists of ORMetadata objects.
        initXMLObjects(m_attributeOverrides, accessibleObject);
        initXMLObjects(m_associationOverrides, accessibleObject);
        initXMLObjects(m_converts, accessibleObject);
    }

    /**
     * INTERNAL:
     */
    @Override
    public boolean isEmbedded() {
        return true;
    }

    /**
     * INTERNAL:
     * Process an embedded.
     */
    @Override
    public void process() {
        // Build and aggregate object mapping and add it to the descriptor.
        AggregateMapping mapping = getOwningDescriptor().getClassDescriptor().newAggregateMapping();
        setMapping(mapping);

        mapping.setReferenceClassName(getReferenceClassName());
        mapping.setAttributeName(getAttributeName());

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

        // EIS and ORDT mappings may not be aggregate object mappings.
        if (mapping.isAggregateObjectMapping()) {
            AggregateObjectMapping aggregateMapping = (AggregateObjectMapping) mapping;
            aggregateMapping.setIsNullAllowed(true);

            // Process attribute overrides.
            processAttributeOverrides(m_attributeOverrides, aggregateMapping, getReferenceDescriptor());

            // Process association overrides.
            processAssociationOverrides(m_associationOverrides, aggregateMapping, getReferenceDescriptor());

            // Process converts.
            processConverts(getConverts(m_converts), aggregateMapping, getReferenceClass(), false);
        } else if (mapping.isAbstractCompositeObjectMapping()) {
            ((AbstractCompositeObjectMapping)mapping).setField(getDatabaseField(getDescriptor().getPrimaryTable(), MetadataLogger.COLUMN));
        }

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

    /**
     * INTERNAL:
     * Used for OX mapping.
     */
    public void setAssociationOverrides(List<AssociationOverrideMetadata> associationOverrides) {
        m_associationOverrides = associationOverrides;
    }

    /**
     * INTERNAL:
     * Used for OX mapping.
     */
    public void setAttributeOverrides(List<AttributeOverrideMetadata> attributeOverrides) {
        m_attributeOverrides = attributeOverrides;
    }

    /**
     * INTERNAL:
     * Used for OX mapping.
     */
    public void setConverts(List<ConvertMetadata> converts) {
        m_converts = converts;
    }

    /**
     * INTERNAL:
     * Called when process the mapsId metadata. The id fields for this owning
     * descriptor must have it's id fields update to those from the one to one
     * accessor that maps them. We process embedded and embedded id mappings
     * first, so by default they get mapped and processed as they normally
     * would. When we go through the relationship accessors and discover a
     * mapsId we then need to make some updates to our list of primary key
     * fields.
     */
    protected void updateDerivedIdField(EmbeddableMapping embeddableMapping, String overrideName, DatabaseField overrideField, MappingAccessor mappingAccessor) {
       addFieldNameTranslation(embeddableMapping, overrideName, overrideField, mappingAccessor);

       // Update the primary key field.
       updatePrimaryKeyField(mappingAccessor, overrideField);
    }
}
