/*
 * Copyright (c) 1998, 2020 Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 1998, 2018 IBM Corporation. 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
//     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
//     04/24/2009-2.0 Guy Pelletier
//       - 270011: JPA 2.0 MappedById support
//     05/1/2009-2.0 Guy Pelletier
//       - 249033: JPA 2.0 Orphan removal
//     06/02/2009-2.0 Guy Pelletier
//       - 278768: JPA 2.0 Association Override Join Table
//     06/09/2009-2.0 Guy Pelletier
//       - 249037: JPA 2.0 persisting list item index
//     09/29/2009-2.0 Guy Pelletier
//       - 282553: JPA 2.0 JoinTable support for OneToOne and ManyToOne
//     10/21/2009-2.0 Guy Pelletier
//       - 290567: mappedbyid support incomplete
//     11/23/2009-2.0 Guy Pelletier
//       - 295790: JPA 2.0 adding @MapsId to one entity causes initialization errors in other entities
//     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
//     06/14/2010-2.2 Guy Pelletier
//       - 264417: Table generation is incorrect for JoinTables in AssociationOverrides
//     07/05/2010-2.1.1 Guy Pelletier
//       - 317708: Exception thrown when using LAZY fetch on VIRTUAL mapping
//     08/04/2010-2.1.1 Guy Pelletier
//       - 315782: JPA2 derived identity metadata processing validation doesn't account for autoboxing
//     08/20/2010-2.2 Guy Pelletier
//       - 323252: Canonical model generator throws NPE on virtual 1-1 or M-1 mapping
//     08/25/2010-2.2 Guy Pelletier
//       - 309445: CanonicalModelProcessor process all files (minor correction to patch for bug above)
//     09/03/2010-2.2 Guy Pelletier
//       - 317286: DB column lenght not in sync between @Column and @JoinColumn
//     01/04/2011-2.3 Guy Pelletier
//       - 330628: @PrimaryKeyJoinColumn(...) is not working equivalently to @JoinColumn(..., insertable = false, updatable = false)
//     01/06/2011-2.3 Guy Pelletier
//       - 312244: can't map optional one-to-one relationship using @PrimaryKeyJoinColumn
//     03/24/2011-2.3 Guy Pelletier
//       - 337323: Multi-tenant with shared schema support (part 1)
//     11/19/2012-2.5 Guy Pelletier
//       - 389090: JPA 2.1 DDL Generation Support (foreign key metadata support)
//     12/07/2012-2.5 Guy Pelletier
//       - 389090: JPA 2.1 DDL Generation Support (foreign key metadata support)
//     02/20/2013-2.5 Guy Pelletier
//       - 389090: JPA 2.1 DDL Generation Support (foreign key metadata support)
//     07/09/2018-2.6 Jody Grassel
//       - 536853: MapsID processing sets up to fail validation

package org.eclipse.persistence.internal.jpa.metadata.accessors.mappings;

import static org.eclipse.persistence.internal.jpa.metadata.MetadataConstants.JPA_FETCH_EAGER;
import static org.eclipse.persistence.internal.jpa.metadata.MetadataConstants.JPA_ID;
import static org.eclipse.persistence.internal.jpa.metadata.MetadataConstants.JPA_MAPS_ID;
import static org.eclipse.persistence.internal.jpa.metadata.MetadataConstants.JPA_PRIMARY_KEY_JOIN_COLUMN;
import static org.eclipse.persistence.internal.jpa.metadata.MetadataConstants.JPA_PRIMARY_KEY_JOIN_COLUMNS;

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

import org.eclipse.persistence.exceptions.ValidationException;
import org.eclipse.persistence.internal.helper.DatabaseField;
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.MetadataAnnotatedElement;
import org.eclipse.persistence.internal.jpa.metadata.accessors.objects.MetadataAnnotation;
import org.eclipse.persistence.internal.jpa.metadata.accessors.objects.MetadataClass;
import org.eclipse.persistence.internal.jpa.metadata.columns.AssociationOverrideMetadata;
import org.eclipse.persistence.internal.jpa.metadata.columns.ForeignKeyMetadata;
import org.eclipse.persistence.internal.jpa.metadata.columns.JoinColumnMetadata;
import org.eclipse.persistence.internal.jpa.metadata.columns.PrimaryKeyForeignKeyMetadata;
import org.eclipse.persistence.internal.jpa.metadata.columns.PrimaryKeyJoinColumnMetadata;
import org.eclipse.persistence.internal.jpa.metadata.xml.XMLEntityMappings;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.EmbeddableMapping;
import org.eclipse.persistence.mappings.ObjectReferenceMapping;
import org.eclipse.persistence.mappings.OneToOneMapping;
import org.eclipse.persistence.mappings.RelationTableMechanism;
import org.eclipse.persistence.mappings.foundation.AbstractDirectMapping;

/**
 * INTERNAL:
 * A single object relationship accessor.
 *
 * 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 abstract class ObjectAccessor extends RelationshipAccessor {
    private Boolean m_id;
    private Boolean m_optional;
    private List<PrimaryKeyJoinColumnMetadata> m_primaryKeyJoinColumns = new ArrayList<PrimaryKeyJoinColumnMetadata>();
    private PrimaryKeyForeignKeyMetadata m_primaryKeyForeignKey;
    private String m_mapsId;

    /**
     * INTERNAL:
     * Used for OX mapping.
     */
    protected ObjectAccessor(String xmlElement) {
        super(xmlElement);
    }

    /**
     * INTERNAL:
     */
    protected ObjectAccessor(MetadataAnnotation annotation, MetadataAnnotatedElement annotatedElement, ClassAccessor classAccessor) {
        super(annotation, annotatedElement, classAccessor);

        if (annotation != null) {
            m_optional = annotation.getAttributeBooleanDefaultTrue("optional");
        }

        // Set the primary key join columns if some are present.
        // Process all the primary key join columns first.
        if (isAnnotationPresent(JPA_PRIMARY_KEY_JOIN_COLUMNS)) {
            MetadataAnnotation primaryKeyJoinColumns = getAnnotation(JPA_PRIMARY_KEY_JOIN_COLUMNS);
            for (Object primaryKeyJoinColumn : primaryKeyJoinColumns.getAttributeArray("value")) {
                m_primaryKeyJoinColumns.add(new PrimaryKeyJoinColumnMetadata((MetadataAnnotation) primaryKeyJoinColumn, this));
            }

            // Set the primary key foreign key metadata if one is specified.
            if (primaryKeyJoinColumns.hasAttribute("foreignKey")) {
                setPrimaryKeyForeignKey(new PrimaryKeyForeignKeyMetadata(primaryKeyJoinColumns.getAttributeAnnotation("foreignKey"), this));
            }
        }

        // Process the single primary key join column second.
        if (isAnnotationPresent(JPA_PRIMARY_KEY_JOIN_COLUMN)) {
            PrimaryKeyJoinColumnMetadata primaryKeyJoinColumn = new PrimaryKeyJoinColumnMetadata(getAnnotation(JPA_PRIMARY_KEY_JOIN_COLUMN), this);
            m_primaryKeyJoinColumns.add(primaryKeyJoinColumn);

            // Set the primary key foreign key metadata.
            if (primaryKeyJoinColumn.hasForeignKey()) {
                setPrimaryKeyForeignKey(new PrimaryKeyForeignKeyMetadata(primaryKeyJoinColumn.getForeignKey()));
            }
        }

        // Set the mapped by id if one is present.
        if (isAnnotationPresent(JPA_MAPS_ID)) {
            // Call getAttributeString with a default because we rely on the
            // mapsId not being null and its value of "" which means we need to
            // default. getAttributeString returns null which kills hasMapsId() logic.
            m_mapsId = getAnnotation(JPA_MAPS_ID).getAttributeString("value", "");
        }

        // Set the derived id if one is specified.
        m_id = isAnnotationPresent(JPA_ID);
    }

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

            if (! valuesMatch(m_id, objectAccessor.getId())) {
                return false;
            }

            if (! valuesMatch(m_optional, objectAccessor.getOptional())) {
                return false;
            }

            if (! valuesMatch(m_primaryKeyJoinColumns, objectAccessor.getPrimaryKeyJoinColumns())) {
                return false;
            }

            if (! valuesMatch(m_primaryKeyForeignKey, objectAccessor.getPrimaryKeyForeignKey())) {
                return false;
            }

            return valuesMatch(m_mapsId, objectAccessor.getMapsId());
        }

        return false;
    }

    @Override
    public int hashCode() {
        int result = super.hashCode();
        result = 31 * result + (m_id != null ? m_id.hashCode() : 0);
        result = 31 * result + (m_optional != null ? m_optional.hashCode() : 0);
        result = 31 * result + (m_primaryKeyJoinColumns != null ? m_primaryKeyJoinColumns.hashCode() : 0);
        result = 31 * result + (m_primaryKeyForeignKey != null ? m_primaryKeyForeignKey.hashCode() : 0);
        result = 31 * result + (m_mapsId != null ? m_mapsId.hashCode() : 0);
        return result;
    }

    /**
     * INTERNAL:
     * Return true is this accessor is a derived id accessor.
     */
    @Override
    public boolean derivesId() {
        return hasId() || hasMapsId();
    }

    /**
     * INTERNAL:
     * The attribute type for virtual object accessors is the target entity.
     */
    @Override
    public String getAttributeType() {
        return getTargetEntity().getName();
    }

    /**
     * INTERNAL:
     * Return the default fetch type for an object mapping.
     */
    @Override
    public String getDefaultFetchType() {
        return JPA_FETCH_EAGER;
    }

    /**
     * INTERNAL:
     */
    public Boolean getId(){
        return m_id;
    }

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

    /**
     * INTERNAL:
     * Used for OX mapping.
     */
    public PrimaryKeyForeignKeyMetadata getPrimaryKeyForeignKey() {
        return m_primaryKeyForeignKey;
    }

    /**
     * INTERNAL:
     * Used for OX mapping.
     */
    public List<PrimaryKeyJoinColumnMetadata> getPrimaryKeyJoinColumns() {
        return m_primaryKeyJoinColumns;
    }

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

    /**
     * INTERNAL:
     * If a target entity is specified in metadata, it will be set as the
     * reference class, otherwise we will use the raw class.
     */
    @Override
    public MetadataClass getReferenceClass() {
        if (m_referenceClass == null) {
            m_referenceClass = getTargetEntity();

            if (m_referenceClass.isVoid()) {
                // Get the reference class from the accessible object and
                // log the defaulting contextual reference class.
                m_referenceClass = super.getReferenceClass();
                getLogger().logConfigMessage(getLoggingContext(), getAnnotatedElement(), m_referenceClass);
            }
        }

        return m_referenceClass;
    }

    /**
     * INTERNAL:
     * Used to process primary keys and DerivedIds.
     */
    protected MetadataClass getSimplePKType(){
        MetadataDescriptor referenceDescriptor = getReferenceDescriptor();
        ClassAccessor referenceAccessor = referenceDescriptor.getClassAccessor();

        if (referenceAccessor.hasDerivedId()) {
            // Referenced object has a derived ID and must be a simple pk type.
            // Recurse through to get the simple type.
            return ((ObjectAccessor) referenceDescriptor.getMappingAccessor(referenceDescriptor.getIdAttributeName())).getSimplePKType();
        } else {
            // Validate on their basic mapping.
            return referenceDescriptor.getMappingAccessor(referenceDescriptor.getIdAttributeName()).getRawClass();
        }
    }

    /**
     * INTERNAL:
     * Object accessors don't require a separate attribute-type specification
     * in XML, instead they can use the reference class to determine the
     * attribute-type.
     */
    @Override
    public boolean hasAttributeType() {
        return getTargetEntity() != null && ! getTargetEntity().isVoid();
    }

    /**
     * INTERNAL:
     */
    protected boolean hasId() {
        return m_id != null && m_id;
    }

    /**
     * INTERNAL:
     */
    protected boolean hasMapsId() {
        return m_mapsId != null;
    }

    /**
     * INTERNAL:
     * Initialize a ManyToOneMapping.
     */
    protected ObjectReferenceMapping initManyToOneMapping() {
        // Allow for different descriptor types (EIS) to create different mapping types.
        ObjectReferenceMapping mapping = getDescriptor().getClassDescriptor().newManyToOneMapping();
        processRelationshipMapping(mapping);

        mapping.setIsOptional(isOptional());
        mapping.setDerivesId(derivesId());

        // Process the indirection.
        processIndirection(mapping);

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

        return mapping;
    }

    /**
     * INTERNAL:
     * Initialize a OneToOneMapping.
     */
    protected ObjectReferenceMapping initOneToOneMapping() {
        // Allow for different descriptor types (EIS) to create different mapping types.
        ObjectReferenceMapping mapping = getDescriptor().getClassDescriptor().newOneToOneMapping();
        processRelationshipMapping(mapping);

        mapping.setIsOptional(isOptional());
        mapping.setDerivesId(derivesId());

        // Process the indirection.
        processIndirection(mapping);

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

        return mapping;
    }

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

        // Initialize lists of ORMetadata objects.
        initXMLObjects(m_primaryKeyJoinColumns, accessibleObject);

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


    /**
     * INTERNAL:
     * Return true if this accessor represents a 1-1 primary key relationship.
     */
    public boolean isOneToOnePrimaryKeyRelationship() {
        return ! m_primaryKeyJoinColumns.isEmpty();
    }

    /**
     * INTERNAL:
     */
    public boolean isOptional() {
        return m_optional != null && m_optional;
    }

    /**
     * INTERNAL:
     * Process an association override for either an embedded object mapping,
     * or a map mapping (element-collection, 1-M and M-M) containing an
     * embeddable object as the value or key.
     */
    @Override
    protected void processAssociationOverride(AssociationOverrideMetadata associationOverride, EmbeddableMapping embeddableMapping, MetadataDescriptor owningDescriptor) {
        if (getMapping().isOneToOneMapping()) {
            processAssociationOverride(associationOverride, embeddableMapping, owningDescriptor.getPrimaryTable(), owningDescriptor);
        } else {
            super.processAssociationOverride(associationOverride, embeddableMapping, owningDescriptor);
        }
    }

    /**
     * INTERNAL:
     * Process an association override for either an embedded object mapping,
     * or a map mapping (element-collection, 1-M and M-M) containing an
     * embeddable object as the value or key.
     */
    protected void processAssociationOverride(AssociationOverrideMetadata associationOverride, EmbeddableMapping embeddableMapping, DatabaseTable defaultTable, MetadataDescriptor owningDescriptor) {
        // Process and use the association override's joinColumns. Avoid calling
        // getJoinColumns since, by default, that method looks for an association
        // override on the descriptor. In this case that has already been taken
        // care of for use before calling this method.
        for (JoinColumnMetadata joinColumn : getJoinColumnsAndValidate(associationOverride.getJoinColumns(), getReferenceDescriptor())) {
            // Look up the primary key field from the referenced column name.
            DatabaseField pkField = getReferencedField(joinColumn.getReferencedColumnName(), getReferenceDescriptor(), MetadataLogger.PK_COLUMN);

            DatabaseField fkField = ((OneToOneMapping) getMapping()).getTargetToSourceKeyFields().get(pkField);

            if (fkField == null) {
                throw ValidationException.invalidAssociationOverrideReferenceColumnName(pkField.getName(), associationOverride.getName(), embeddableMapping.getAttributeName(), owningDescriptor.getJavaClassName());
            } else {
                // Make sure we have a table set on the association override
                // field, otherwise use the default table provided.
                DatabaseField translationFKField = joinColumn.getForeignKeyField(pkField);
                if (! translationFKField.hasTableName()) {
                    translationFKField.setTable(defaultTable);
                }

                embeddableMapping.addFieldTranslation(translationFKField, fkField.getName());
            }
        }
    }

    /**
     * INTERNAL:
     * Used to process primary keys and DerivedIds.
     */
    protected void processId(OneToOneMapping mapping) {
        // If this entity has a pk class, we need to validate our ids.
        MetadataDescriptor referenceDescriptor = getReferenceDescriptor();
        String referencePKClassName = referenceDescriptor.getPKClassName();

        if (referencePKClassName != null) {
            // They have a pk class
            String pkClassName = getDescriptor().getPKClassName();
            if (pkClassName == null){
                throw ValidationException.invalidCompositePKSpecification(getJavaClass(), null);
            }

            if (pkClassName.equals(referencePKClassName)){
                // This pk is the reference pk, so all pk attributes are
                // accounted through this relationship.
                getOwningDescriptor().getPKClassIDs().clear();
            } else {
                // Validate our pk contains their pk.
                getOwningDescriptor().validateDerivedPKClassId(getAttributeName(), referencePKClassName, getReferenceClassName());
            }
        } else {
            MetadataClass type = null;
            if (referenceDescriptor.getClassAccessor().hasDerivedId()){
                // Referenced object has a derived ID but no PK class defined,
                // so it must be a simple pk type. Recurse through to get the
                // simple type
                type = ((ObjectAccessor) referenceDescriptor.getMappingAccessor(referenceDescriptor.getIdAttributeName())).getSimplePKType();
            } else {
                // Validate on their basic mapping.
                type = referenceDescriptor.getMappingAccessor(referenceDescriptor.getIdAttributeName()).getRawClass();
            }

            getOwningDescriptor().validateDerivedPKClassId(getAttributeName(), getBoxedType(type.getName()), getReferenceClassName());
        }

        // Store the Id attribute name. Used with validation and OrderBy.
        getOwningDescriptor().addIdAttributeName(getAttributeName());

        // Add the primary key fields to the descriptor.
        for (DatabaseField pkField : mapping.getForeignKeyFields()) {
            getOwningDescriptor().addPrimaryKeyField(pkField);
        }
    }

    /**
     * INTERNAL:
     * Process the mapping keys from the maps id value.
     */
    protected void processMapsId(OneToOneMapping oneToOneMapping) {
        EmbeddedIdAccessor embeddedIdAccessor = getDescriptor().getEmbeddedIdAccessor();

        if (embeddedIdAccessor == null) {
            // Case #4: a simple id association
            MappingAccessor idAccessor = getDescriptor().getMappingAccessor(getDescriptor().getIdAttributeName());
            DatabaseMapping idMapping = idAccessor.getMapping();

            // Grab the foreign key field and set it as the descriptor's id field.
            DatabaseField foreignKeyField = oneToOneMapping.getForeignKeyFields().elementAt(0);
            updatePrimaryKeyField(idAccessor, foreignKeyField);

            // Update the field on the mapping.
            ((AbstractDirectMapping) idMapping).setField(foreignKeyField);

            // Set the primary key mapping as read only.
            idMapping.setIsReadOnly(true);

            // Set the maps id mapping.
            oneToOneMapping.setDerivedIdMapping(idMapping);
        } else {
            if (embeddedIdAccessor.getReferenceClassName().equals(getReferenceDescriptor().getPKClassName())) {
                // Case #5: Parent's id class is the same as dependent's embedded id class
                // Case #6: Both parent and dependent use same embedded id class.
                processMapsIdFields(oneToOneMapping, embeddedIdAccessor, embeddedIdAccessor);
            } else {
                if (m_mapsId.equals("")) {
                    // User didn't specify a mapsId value. By default the attribute name from this object accessor is used.
                    m_mapsId = getAttributeName();
                }

                // Set the maps id value on the mapping.
                oneToOneMapping.setMapsIdValue(m_mapsId);
                MappingAccessor mappingAccessor = embeddedIdAccessor.getReferenceDescriptor().getMappingAccessor(m_mapsId);

                if (mappingAccessor == null) {
                    throw ValidationException.invalidMappedByIdValue(m_mapsId, getAnnotatedElementName(), embeddedIdAccessor.getReferenceClass());
                } else {
                    // Case #1: Dependent's embedded id maps a basic mapping to parent entity.
                    // Case #2: Dependent's embedded id maps the parent's id class
                    // Case #3: Dependent's embedded if maps the parent's embedded id class
                    processMapsIdFields(oneToOneMapping, embeddedIdAccessor, mappingAccessor);
                }
            }

            // Set the maps id mapping.
            oneToOneMapping.setDerivedIdMapping(embeddedIdAccessor.getMapping());
        }
    }

    /**
     * INTERNAL:
     * We're going to add field name translations where necessary. If the user
     * specified (erroneously that is) attribute overrides this will override
     * them.
     */
    protected void processMapsIdFields(OneToOneMapping oneToOneMapping, EmbeddedIdAccessor embeddedIdAccessor, MappingAccessor mapsIdAccessor) {
        // At this point we have a one to one mapping to the reference class
        // with specified join columns or defaulted ones. The foreign key
        // fields are the fields we want to use to map our id fields.
        for (DatabaseField fkField : oneToOneMapping.getForeignKeyFields()) {
            if (mapsIdAccessor.isBasic()) {
                // Case #1: Dependent's embedded id maps a basic mapping to parent entity.

                // Add the maps id accessor to the embedded id accessor's list
                // of mappings that need to be set to read only at initialize
                // time on the cloned aggregate descriptor.
                embeddedIdAccessor.addMapsIdAccessor(mapsIdAccessor);

                // Add a field name translation to the mapping.
                embeddedIdAccessor.updateDerivedIdField((EmbeddableMapping) embeddedIdAccessor.getMapping(), mapsIdAccessor.getAttributeName(), fkField, mapsIdAccessor);
            } else {
                if (mapsIdAccessor.isDerivedIdClass()) {
                    // Case #2: Dependent's embedded id maps the parent's id class
                    // Case #3: Dependent's embedded if maps the parent's embedded id class

                    // Add the maps id accessor to the embedded id accessor's
                    // list  of mappings that need to be set to read only at
                    // initialize time on the cloned aggregate descriptor.
                    embeddedIdAccessor.addMapsIdAccessor(mapsIdAccessor);
                } else {
                    // Case #5: Parent's id class is the same as dependent's embedded id class
                    // Case #6: Both parent and dependent use same embedded id class.

                    // Set the mapping to read only.
                    embeddedIdAccessor.getMapping().setIsReadOnly(true);
                }

                // For this foreign key relation, get the primary key accessor
                // from the reference descriptor.
                DatabaseField referencePKField = oneToOneMapping.getSourceToTargetKeyFields().get(fkField);
                MappingAccessor referencePKAccessor = getReferenceDescriptor().getPrimaryKeyAccessorForField(referencePKField);

                // If there is no primary key accessor then the user must have
                // specified an incorrect reference column name. Throw an exception.
                if (referencePKAccessor == null) {
                    throw ValidationException.invalidDerivedIdPrimaryKeyField(getReferenceClassName(), referencePKField.getQualifiedName(), getAttributeName(), getJavaClassName());
                } else {
                    // The reference primary key accessor will tell us which attribute
                    // accessor we need to map a field name translation for.
                    final Set<MappingAccessor> mappingAccessors = findAllFieldAccessors(mapsIdAccessor.getReferenceDescriptor());
                    final List<MappingAccessor> accessorsWithTargetAttributeName = new ArrayList<MappingAccessor>();
                    for (MappingAccessor ma : mappingAccessors) {
                        if (referencePKAccessor.getAttributeName().equals(ma.getAttributeName())) {
                            accessorsWithTargetAttributeName.add(ma);
                        }
                    }
                    MappingAccessor idAccessor = null;
                    if (accessorsWithTargetAttributeName.size() > 1 && accessorsWithTargetAttributeName.contains(referencePKAccessor)) {
                        // The MappingAccessor that is equal() to the referencePKAccessor may still be a different object.
                        idAccessor = accessorsWithTargetAttributeName.get(accessorsWithTargetAttributeName.indexOf(referencePKAccessor));
                    } else {
                        idAccessor = mapsIdAccessor.getReferenceDescriptor().getMappingAccessor(referencePKAccessor.getAttributeName());
                    }
                    
                    // Add a field name translation to the mapping.
                    ((EmbeddedAccessor) mapsIdAccessor).updateDerivedIdField((EmbeddableMapping) mapsIdAccessor.getMapping(), idAccessor.getAttributeName(), fkField, idAccessor);
                }
            }
        }
    }
    
    private Set<MappingAccessor> findAllFieldAccessors(MetadataDescriptor md) {
        final HashSet<MappingAccessor> retSet = new HashSet<MappingAccessor>();
        final Collection<MappingAccessor> mappingAccessors = md.getMappingAccessors();
        for (MappingAccessor ma : mappingAccessors) {
            if (ma instanceof EmbeddedAccessor) {
                retSet.addAll(findAllFieldAccessors(ma.getReferenceDescriptor()));
            } else {
                retSet.add(ma);
            }
        }
        
        return retSet;
    }

    /**
     * INTERNAL:
     * Process the join columns for the owning side of a one to one mapping.
     * The default pk and pk field names are used only with single primary key
     * entities. The processor should never get as far as to use them with
     * entities that have a composite primary key (validation exception will be
     * thrown).
     */
    protected void processForeignKeyRelationship(ObjectReferenceMapping mapping) {
        // If the fk field (name) is not specified, it defaults to the
        // concatenation of the following: the name of the referencing
        // relationship property or field of the referencing entity or
        // embeddable class; "_"; the name of the referenced primary key
        // column.
        String defaultFKFieldName = getDefaultAttributeName() + "_" + getReferenceDescriptor().getPrimaryKeyFieldName();

        // Get the join columns (directly or through an association override),
        // init them and validate.
        List<JoinColumnMetadata> joinColumns = getJoinColumns(getJoinColumns(), getReferenceDescriptor());

        // Get the foreign key (directly or through an association override) and
        // make sure it is initialized for processing.
        ForeignKeyMetadata foreignKey = getForeignKey(getForeignKey(), getReferenceDescriptor());

        // Now process the foreign key relationship metadata.
        processForeignKeyRelationship(mapping, joinColumns, foreignKey, getReferenceDescriptor(), defaultFKFieldName, getDescriptor().getPrimaryTable());
    }

    /**
     * INTERNAL:
     * Process the primary key join columns for the owning side of a one to one
     * mapping. The default pk and pk field names are used only with single
     * primary key entities. The processor should never get as far as to use
     * them with entities that have a composite primary key (validation
     * exception will be thrown).
     */
    protected void processOneToOnePrimaryKeyRelationship(OneToOneMapping mapping) {
        List<PrimaryKeyJoinColumnMetadata> pkJoinColumns = processPrimaryKeyJoinColumns(getPrimaryKeyJoinColumns());

        // Add the source foreign key fields to the mapping.
        for (PrimaryKeyJoinColumnMetadata primaryKeyJoinColumn : pkJoinColumns) {
            // Look up the primary key field from the referenced column name.
            DatabaseField pkField = getReferencedField(primaryKeyJoinColumn.getReferencedColumnName(), getReferenceDescriptor(), MetadataLogger.PK_COLUMN);

            // Look up the foreign key field from the name.
            DatabaseField fkField = getReferencedField(primaryKeyJoinColumn.getName(), getDescriptor(), MetadataLogger.FK_COLUMN);

            // Add a source foreign key to the mapping.
            mapping.addForeignKeyField(fkField, pkField);
        }

        // Mark the mapping read only
        mapping.setIsReadOnly(true);

        // Set the primary key join column flag. This will also set the mapping
        // to read only.
        mapping.setIsOneToOnePrimaryKeyRelationship(true);

        // Process the primary key foreign key metadata if specified for this
        // accessor.
        if (m_primaryKeyForeignKey != null) {
            m_primaryKeyForeignKey.process(getDescriptor().getPrimaryKeyTable());
        }
    }

    /**
     * INTERNAL:
     * Process the the correct metadata for the owning side of a one to one
     * mapping. Note, the order of checking is important, that is, check for
     * a mapsId first.
     */
    protected void processOwningMappingKeys(OneToOneMapping mapping) {
        if (derivesId()) {
            // We need to process the join columns as we normally would.
            // Then we must update the fields from our derived id accessor.
            processForeignKeyRelationship(mapping);

            if (hasMapsId()) {
                processMapsId(mapping);
            } else {
                processId(mapping);
            }
        } else if (isOneToOnePrimaryKeyRelationship()) {
            processOneToOnePrimaryKeyRelationship(mapping);
        } else if (hasJoinTable()) {
            mapping.setRelationTableMechanism(new RelationTableMechanism());
            processJoinTable(mapping, mapping.getRelationTableMechanism(), getJoinTableMetadata());
        } else {
            processForeignKeyRelationship(mapping);
        }
    }

    /**
     * INTERNAL:
     * Used for OX mapping.
     */
    public void setId(Boolean id){
        m_id = id;
    }

    /**
     * INTERNAL:
     * Used for OX mapping.
     */
    public void setMapsId(String mapsId){
        m_mapsId = mapsId;
    }

    /**
     * INTERNAL:
     * Used for OX mapping.
     */
    public void setOptional(Boolean isOptional) {
        m_optional = isOptional;
    }

    /**
     * INTERNAL:
     * Used for OX mapping.
     */
    public void setPrimaryKeyForeignKey(PrimaryKeyForeignKeyMetadata primaryKeyForeignKey) {
        m_primaryKeyForeignKey = primaryKeyForeignKey;
    }

    /**
     * INTERNAL:
     * Used for OX mapping.
     */
    public void setPrimaryKeyJoinColumns(List<PrimaryKeyJoinColumnMetadata> primaryKeyJoinColumns) {
        m_primaryKeyJoinColumns = primaryKeyJoinColumns;
    }
}
