/*
 * 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:
//     Guy Pelletier - initial API and implementation from Oracle TopLink
//     05/16/2008-1.0M8 Guy Pelletier
//       - 218084: Implement metadata merging functionality between mapping files
//     05/23/2008-1.0M8 Guy Pelletier
//       - 211330: Add attributes-complete support to the EclipseLink-ORM.XML Schema
//     05/30/2008-1.0M8 Guy Pelletier
//       - 230213: ValidationException when mapping to attribute in MappedSuperClass
//     06/20/2008-1.0M9 Guy Pelletier
//       - 232975: Failure when attribute type is generic
//     07/15/2008-1.0.1 Guy Pelletier
//       - 240679: MappedSuperclass Id not picked when on get() method accessor
//     09/23/2008-1.1 Guy Pelletier
//       - 241651: JPA 2.0 Access Type support
//     10/01/2008-1.1 Guy Pelletier
//       - 249329: To remain JPA 1.0 compliant, any new JPA 2.0 annotations should be referenced by name
//     12/12/2008-1.1 Guy Pelletier
//       - 249860: Implement table per class inheritance 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/03/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
//     04/30/2009-2.0 Michael O'Brien
//       - 266912: JPA 2.0 Metamodel API (part of Criteria API)
//     06/16/2009-2.0 Guy Pelletier
//       - 277039: JPA 2.0 Cache Usage Settings
//     06/25/2009-2.0 Michael O'Brien
//       - 266912: change MappedSuperclass handling in stage2 to pre process accessors
//          in support of the custom descriptors holding mappings required by the Metamodel.
//          processAccessType() is now public and is overridden in the superclass
//     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
//     12/2/2009-2.1 Guy Pelletier
//       - 296289: Add current annotation metadata support on mapped superclasses to EclipseLink-ORM.XML Schema
//     12/18/2009-2.1 Guy Pelletier
//       - 211323: Add class extractor support to the EclipseLink-ORM.XML Schema
//     04/09/2010-2.1 Guy Pelletier
//       - 307050: Add defaults for access methods of a VIRTUAL access type
//     05/04/2010-2.1 Guy Pelletier
//       - 309373: Add parent class attribute to EclipseLink-ORM
//     05/14/2010-2.1 Guy Pelletier
//       - 253083: Add support for dynamic persistence using ORM.xml/eclipselink-orm.xml
//     06/01/2010-2.1 Guy Pelletier
//       - 315195: Add new property to avoid reading XML during the canonical model generation
//     06/09/2010-2.0.3 Guy Pelletier
//       - 313401: shared-cache-mode defaults to NONE when the element value is unrecognized
//     06/14/2010-2.2 Guy Pelletier
//       - 264417: Table generation is incorrect for JoinTables in AssociationOverrides
//     06/18/2010-2.2 Guy Pelletier
//       - 300458: EclispeLink should throw a more specific exception than NPE
//     06/22/2010-2.2 Guy Pelletier
//       - 308729: Persistent Unit deployment exception when mappedsuperclass has no annotations but has lifecycle callbacks
//     07/05/2010-2.1.1 Guy Pelletier
//       - 317708: Exception thrown when using LAZY fetch on VIRTUAL mapping
//     08/11/2010-2.2 Guy Pelletier
//       - 312123: JPA: Validation error during Id processing on parameterized generic OneToOne Entity relationship from MappedSuperclass
//     09/03/2010-2.2 Guy Pelletier
//       - 317286: DB column lenght not in sync between @Column and @JoinColumn
//     09/16/2010-2.2 Guy Pelletier
//       - 283028: Add support for letting an @Embeddable extend a @MappedSuperclass
//     12/01/2010-2.2 Guy Pelletier
//       - 331234: xml-mapping-metadata-complete overriden by metadata-complete specification
//     01/04/2011-2.3 Guy Pelletier
//       - 330628: @PrimaryKeyJoinColumn(...) is not working equivalently to @JoinColumn(..., insertable = false, updatable = false)
//     03/24/2011-2.3 Guy Pelletier
//       - 337323: Multi-tenant with shared schema support (part 1)
//     04/05/2011-2.3 Guy Pelletier
//       - 337323: Multi-tenant with shared schema support (part 3)
//     03/24/2011-2.3 Guy Pelletier
//       - 337323: Multi-tenant with shared schema support (part 8)
//     07/03/2011-2.3.1 Guy Pelletier
//       - 348756: m_cascadeOnDelete boolean should be changed to Boolean
//     10/09/2012-2.5 Guy Pelletier
//       - 374688: JPA 2.1 Converter support
//     10/25/2012-2.5 Guy Pelletier
//       - 3746888: 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
//     11/29/2012-2.5 Guy Pelletier
//       - 395406: Fix nightly static weave test errors
//     12/07/2012-2.5 Guy Pelletier
//       - 389090: JPA 2.1 DDL Generation Support (foreign key metadata support)
//     09 Jan 2013-2.5 Gordon Yorke
//       - 397772: JPA 2.1 Entity Graph Support
//     02/13/2013-2.5 Guy Pelletier
//       - 397772: JPA 2.1 Entity Graph Support (XML support)
//     02/20/2013-2.5 Guy Pelletier
//       - 389090: JPA 2.1 DDL Generation Support (foreign key metadata support)
//     05/19/2014-2.6 Tomas Kraus
//       - 437578: @Cacheable annotation value is passed to CachePolicy for ENABLE_SELECTIVE and DISABLE_SELECTIVE shared cache mode
package org.eclipse.persistence.internal.jpa.metadata.accessors.classes;

import static org.eclipse.persistence.internal.jpa.metadata.MetadataConstants.JPA_ACCESS_FIELD;
import static org.eclipse.persistence.internal.jpa.metadata.MetadataConstants.JPA_ACCESS_PROPERTY;
import static org.eclipse.persistence.internal.jpa.metadata.MetadataConstants.JPA_CONVERT;
import static org.eclipse.persistence.internal.jpa.metadata.MetadataConstants.JPA_CONVERTS;
import static org.eclipse.persistence.internal.jpa.metadata.MetadataConstants.JPA_DISCRIMINATOR_COLUMN;
import static org.eclipse.persistence.internal.jpa.metadata.MetadataConstants.JPA_DISCRIMINATOR_VALUE;
import static org.eclipse.persistence.internal.jpa.metadata.MetadataConstants.JPA_ENTITY;
import static org.eclipse.persistence.internal.jpa.metadata.MetadataConstants.JPA_ENTITY_GRAPH;
import static org.eclipse.persistence.internal.jpa.metadata.MetadataConstants.JPA_ENTITY_GRAPHS;
import static org.eclipse.persistence.internal.jpa.metadata.MetadataConstants.JPA_INHERITANCE;
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 static org.eclipse.persistence.internal.jpa.metadata.MetadataConstants.JPA_SECONDARY_TABLE;
import static org.eclipse.persistence.internal.jpa.metadata.MetadataConstants.JPA_SECONDARY_TABLES;
import static org.eclipse.persistence.internal.jpa.metadata.MetadataConstants.JPA_TABLE;

import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

import org.eclipse.persistence.annotations.CascadeOnDelete;
import org.eclipse.persistence.annotations.ClassExtractor;
import org.eclipse.persistence.annotations.Index;
import org.eclipse.persistence.annotations.Indexes;
import org.eclipse.persistence.annotations.VirtualAccessMethods;
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.helper.Helper;
import org.eclipse.persistence.internal.jpa.metadata.MetadataDescriptor;
import org.eclipse.persistence.internal.jpa.metadata.MetadataLogger;
import org.eclipse.persistence.internal.jpa.metadata.MetadataProject;
import org.eclipse.persistence.internal.jpa.metadata.ORMetadata;
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.accessors.objects.MetadataClass;
import org.eclipse.persistence.internal.jpa.metadata.columns.DiscriminatorColumnMetadata;
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.converters.ConvertMetadata;
import org.eclipse.persistence.internal.jpa.metadata.graphs.NamedEntityGraphMetadata;
import org.eclipse.persistence.internal.jpa.metadata.inheritance.InheritanceMetadata;
import org.eclipse.persistence.internal.jpa.metadata.listeners.EntityClassListenerMetadata;
import org.eclipse.persistence.internal.jpa.metadata.listeners.EntityListenerMetadata;
import org.eclipse.persistence.internal.jpa.metadata.mappings.AccessMethodsMetadata;
import org.eclipse.persistence.internal.jpa.metadata.tables.IndexMetadata;
import org.eclipse.persistence.internal.jpa.metadata.tables.SecondaryTableMetadata;
import org.eclipse.persistence.internal.jpa.metadata.tables.TableMetadata;
import org.eclipse.persistence.internal.jpa.metadata.xml.XMLEntityMappings;

/**
 * An entity 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 EclipseLink 1.0
 */
public class EntityAccessor extends MappedSuperclassAccessor {
    private Boolean m_cascadeOnDelete;

    private InheritanceMetadata m_inheritance;
    private DiscriminatorColumnMetadata m_discriminatorColumn;
    private PrimaryKeyForeignKeyMetadata m_primaryKeyForeignKey;

    private List<ConvertMetadata> m_converts = new ArrayList<ConvertMetadata>();
    private List<PrimaryKeyJoinColumnMetadata> m_primaryKeyJoinColumns = new ArrayList<PrimaryKeyJoinColumnMetadata>();
    private List<SecondaryTableMetadata> m_secondaryTables = new ArrayList<SecondaryTableMetadata>();
    private List<IndexMetadata> m_indexes = new ArrayList<IndexMetadata>();
    private List<NamedEntityGraphMetadata> m_namedEntityGraphs = new ArrayList<NamedEntityGraphMetadata>();

    private MetadataClass m_classExtractor;

    private String m_classExtractorName;
    private String m_discriminatorValue;
    private String m_entityName;

    private TableMetadata m_table;

    /**
     * INTERNAL:
     */
    public EntityAccessor() {
        super("<entity>");
    }

    /**
     * INTERNAL:
     */
    public EntityAccessor(MetadataAnnotation annotation, MetadataClass cls, MetadataProject project) {
        super(annotation, cls, project);
    }

    /**
     * INTERNAL:
     * Add multiple fields to the descriptor. Called from either Inheritance
     * or SecondaryTable context.
     */
    protected void addMultipleTableKeyFields(List<PrimaryKeyJoinColumnMetadata> primaryKeyJoinColumns, DatabaseTable targetTable, String PK_CTX, String FK_CTX) {
        // ProcessPrimaryKeyJoinColumns will validate the primary key join
        // columns passed in and will return a list of PrimaryKeyJoinColumnMetadata.
        for (PrimaryKeyJoinColumnMetadata primaryKeyJoinColumn : processPrimaryKeyJoinColumns(primaryKeyJoinColumns)) {
            // Look up the primary key field from the referenced column name.
            DatabaseField pkField = getReferencedField(primaryKeyJoinColumn.getReferencedColumnName(), getDescriptor(), PK_CTX);

            DatabaseField fkField = primaryKeyJoinColumn.getForeignKeyField(pkField);
            setFieldName(fkField, pkField.getName(), FK_CTX);
            fkField.setTable(targetTable);

            // Add the foreign key field to the descriptor.
            getDescriptor().addForeignKeyFieldForMultipleTable(fkField, pkField);
        }
    }

    /**
     * INTERNAL:
     * Build a list of classes that are decorated with a MappedSuperclass
     * annotation or that are tagged as a mapped-superclass in an XML document.
     *
     * This method will also do a couple other things as well since we are
     * traversing the parent classes:
     *  - Build a map of generic types specified and will be used to resolve
     *    actual class types for mappings.
     *  - Will discover and set the inheritance parent and root descriptors
     *    if this entity is part of an inheritance hierarchy.
     *  - save mapped-superclass descriptors on the project for later use
     *    by the Metamodel API
     *
     * Note: The list is rebuilt every time this method is called since
     * it is called both during pre-deploy and deploy where the class loader
     * dependencies change.
     */
    protected void discoverMappedSuperclassesAndInheritanceParents(boolean addMappedSuperclassAccessors) {
        // Clear any previous discovery.
        clearMappedSuperclassesAndInheritanceParents();

        EntityAccessor currentEntityAccessor = this;
        MetadataClass parentClass = getJavaClass().getSuperclass();
        List<String> genericTypes = getJavaClass().getGenericType();

        // We keep a list of potential subclass accessors to ensure they
        // have their root parent descriptor set correctly.
        List<EntityAccessor> subclassEntityAccessors = new ArrayList<EntityAccessor>();
        subclassEntityAccessors.add(currentEntityAccessor);

        if (! parentClass.isObject()) {
            while (parentClass != null && ! parentClass.isObject()) {
                if (getProject().hasEntity(parentClass)) {
                    // Our parent is an entity.
                    EntityAccessor parentEntityAccessor = getProject().getEntityAccessor(parentClass);

                    // Set the current entity's inheritance parent descriptor.
                    currentEntityAccessor.getDescriptor().setInheritanceParentDescriptor(parentEntityAccessor.getDescriptor());

                    // Update the current entity accessor.
                    currentEntityAccessor = parentEntityAccessor;

                    // Clear out any previous mapped superclasses and inheritance
                    // parents that were discovered. We're going to re-discover
                    // them now.
                    currentEntityAccessor.clearMappedSuperclassesAndInheritanceParents();

                    // If we found an entity with inheritance metadata, set the
                    // root descriptor on its subclasses.
                    if (currentEntityAccessor.hasInheritance()) {
                        for (EntityAccessor subclassEntityAccessor : subclassEntityAccessors) {
                            subclassEntityAccessor.getDescriptor().setInheritanceRootDescriptor(currentEntityAccessor.getDescriptor());
                        }

                        // Clear the subclass list, we'll keep looking but the
                        // inheritance strategy may have changed so we need to
                        // build a new list of subclasses.
                        subclassEntityAccessors.clear();
                    }

                    // Add the descriptor to the subclass list
                    subclassEntityAccessors.add(currentEntityAccessor);
                } else {
                    // Our parent might be a mapped superclass, check and add
                    // as needed.
                    currentEntityAccessor.addPotentialMappedSuperclass(parentClass, addMappedSuperclassAccessors);
                }

                // Resolve any generic types from the generic parent onto the
                // current entity accessor.
                currentEntityAccessor.resolveGenericTypes(genericTypes, parentClass);

                // Grab the generic types from the parent class.
                genericTypes = parentClass.getGenericType();

                // Finally, get the next parent and keep processing ...
                parentClass = parentClass.getSuperclass();
            }
        } else {
            // Resolve any generic types we have (we may be an inheritance root).
            currentEntityAccessor.resolveGenericTypes(genericTypes, parentClass);
        }

        // Set our root descriptor of the inheritance hierarchy on all the
        // subclass descriptors. The root may not have explicit inheritance
        // metadata therefore, make the current descriptor of the entity
        // hierarchy the root.
        if (! subclassEntityAccessors.isEmpty()) {
            for (EntityAccessor subclassEntityAccessor : subclassEntityAccessors) {
                if (subclassEntityAccessor != currentEntityAccessor) {
                    subclassEntityAccessor.getDescriptor().setInheritanceRootDescriptor(currentEntityAccessor.getDescriptor());
                }
            }
        }
    }


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

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

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

    /**
     * INTERNAL:
     * Used for OX mapping.
     */
    public DiscriminatorColumnMetadata getDiscriminatorColumn() {
        return m_discriminatorColumn;
    }

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

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

    /**
     * INTERNAL:
     * Used for OX mapping.
     */
    public List<IndexMetadata> getIndexes() {
        return m_indexes;
    }

    /**
     * INTERNAL:
     * Used for OX mapping.
     */
    public InheritanceMetadata getInheritance() {
        return m_inheritance;
    }

    /**
     * INTERNAL:
     * Used for OX mapping.
     */
    public List<NamedEntityGraphMetadata> getNamedEntityGraphs() {
        return m_namedEntityGraphs;
    }

    /**
     * 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 List<SecondaryTableMetadata> getSecondaryTables() {
        return m_secondaryTables;
    }

    /**
     * INTERNAL:
     * Used for OX mapping.
     */
    public TableMetadata getTable() {
        return m_table;
    }

    /**
     * INTERNAL:
     * This method is a little involved since a class extractor is mutually
     * exclusive with a discriminator column.
     *
     * Within one xml file it is impossible to have both specified since they
     * are within a choice tag. However, if one is specified in the orm.xml
     * and the other in the eclipselink-orm.xml, after the merge both will be
     * set on this accessor, so we need to check which came from the
     * eclipselink-orm.xml because it is the one we need to use.
     */
    public boolean hasClassExtractor() {
        if (m_classExtractorName != null && m_discriminatorColumn != null) {
            // If we have both a classExtractorName and a discriminatorColumn
            // then the only way this is possible is if the user has both an
            // orm.xml and an eclipselink-orm.xml and one specifies the
            // discriminator column and the other specifies the class extractor.
            // We must use the one from the eclipselink-orm.xml.
            return ! m_discriminatorColumn.loadedFromEclipseLinkXML();
        } else if (m_classExtractorName != null) {
            // We have a class extractor name and we don't care where it came
            // from. It must be used and override any annotations.
            return true;
        } else if (m_discriminatorColumn != null) {
            // We have a discriminator column and we don't care where it came
            // from. It must be used and override any annotations.
            return false;
        } else {
            // Nothing was specified in XML. Must look at the annotations now.
            if (isAnnotationPresent(ClassExtractor.class) && (isAnnotationPresent(JPA_DISCRIMINATOR_COLUMN) || isAnnotationPresent(JPA_DISCRIMINATOR_VALUE))) {
                throw ValidationException.classExtractorCanNotBeSpecifiedWithDiscriminatorMetadata(getJavaClassName());
            }

            return isAnnotationPresent(ClassExtractor.class);
        }
    }

    /**
     * INTERNAL:
     * Return true if this class has an inheritance specifications.
     */
    public boolean hasInheritance() {
        if (m_inheritance == null) {
            return isAnnotationPresent(JPA_INHERITANCE);
        } else {
            return true;
        }
    }

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

        // Initialize simple class objects.
        m_classExtractor = initXMLClassName(m_classExtractorName);

        // Initialize single objects.
        initXMLObject(m_inheritance, accessibleObject);
        initXMLObject(m_discriminatorColumn, accessibleObject);
        initXMLObject(m_table, accessibleObject);
        initXMLObject(m_primaryKeyForeignKey, accessibleObject);

        // Initialize lists of ORMetadata objects.
        initXMLObjects(m_secondaryTables, accessibleObject);
        initXMLObjects(m_primaryKeyJoinColumns, accessibleObject);
        initXMLObjects(m_indexes, accessibleObject);
        initXMLObjects(m_converts, accessibleObject);
        initXMLObjects(m_namedEntityGraphs, accessibleObject);
    }

    /**
     * INTERNAL:
     */
    public boolean isCascadeOnDelete() {
        return (m_cascadeOnDelete == null) ? isAnnotationPresent(CascadeOnDelete.class) : m_cascadeOnDelete;
    }

    /**
     * INTERNAL:
     * Return true if this accessor represents an entity class.
     */
    @Override
    public boolean isEntityAccessor() {
        return true;
    }

    /**
     * INTERNAL:
     */
    @Override
    public boolean isMappedSuperclass() {
        return false;
    }

    /**
     * INTERNAL:
     * Entity level merging details.
     */
    @Override
    public void merge(ORMetadata metadata) {
        super.merge(metadata);

        EntityAccessor accessor = (EntityAccessor) metadata;

        // Simple object merging.
        m_cascadeOnDelete = (Boolean) mergeSimpleObjects(m_cascadeOnDelete, accessor.getCascadeOnDelete(), accessor, "<cascade-on-delete>");
        m_entityName = (String) mergeSimpleObjects(m_entityName, accessor.getEntityName(), accessor, "@name");
        m_discriminatorValue = (String) mergeSimpleObjects(m_discriminatorValue, accessor.getDiscriminatorValue(), accessor, "<discriminator-value>");
        m_classExtractorName = (String) mergeSimpleObjects(m_classExtractorName, accessor.getClassExtractorName(), accessor, "<class-extractor>");

        // ORMetadata object merging.
        m_discriminatorColumn = (DiscriminatorColumnMetadata) mergeORObjects(m_discriminatorColumn, accessor.getDiscriminatorColumn());
        m_inheritance = (InheritanceMetadata) mergeORObjects(m_inheritance, accessor.getInheritance());
        m_table = (TableMetadata) mergeORObjects(m_table, accessor.getTable());
        m_primaryKeyForeignKey = (PrimaryKeyForeignKeyMetadata) mergeORObjects(m_primaryKeyForeignKey, accessor.getPrimaryKeyForeignKey());

        // ORMetadata list merging.
        m_secondaryTables = mergeORObjectLists(m_secondaryTables, accessor.getSecondaryTables());
        m_primaryKeyJoinColumns = mergeORObjectLists(m_primaryKeyJoinColumns, accessor.getPrimaryKeyJoinColumns());
        m_indexes = mergeORObjectLists(m_indexes, accessor.getIndexes());
        m_converts = mergeORObjectLists(m_converts, accessor.getConverts());
        m_namedEntityGraphs = mergeORObjectLists(m_namedEntityGraphs, accessor.getNamedEntityGraphs());
    }

    /**
     * INTERNAL:
     * The pre-process method is called during regular deployment and metadata
     * processing and will pre-process the items of interest on an entity class.
     *
     * The order of processing is important, care must be taken if changes must
     * be made.
     */
    @Override
    public void preProcess() {
        // If we are not already an inheritance subclass (meaning we were not
        // discovered through a subclass entity discovery) then perform the
        // discovery process before processing any further. We traverse the
        // chain upwards and we can not guarantee which entity will be processed
        // first in an inheritance hierarchy.
        if (! getDescriptor().isInheritanceSubclass()) {
            discoverMappedSuperclassesAndInheritanceParents(true);
        }

        // If we are an inheritance subclass process out root first.
        if (getDescriptor().isInheritanceSubclass()) {
            // Ensure our parent accessors are processed first. Top->down.
            // An inheritance subclass can no longer blindly inherit a default
            // access type from the root of the inheritance hierarchy since
            // that root may explicitly set an access type which applies only
            // to itself. The first entity in the hierarchy (going down) that
            // does not specify an explicit type will be used to determine
            // the default access type.
            EntityAccessor parentAccessor = (EntityAccessor) getDescriptor().getInheritanceParentDescriptor().getClassAccessor();
            if (! parentAccessor.isPreProcessed()) {
                parentAccessor.preProcess();
            }
        }

        // Process the correct access type before any other processing.
        processAccessType();

        // Process a virtual class specification after determining access type.
        processVirtualClass();

        // Process the default access methods after determining access type.
        processAccessMethods();

        // Process a @Struct and @EIS annotation to create the correct type of descriptor.
        processStruct();
        processNoSql();

        // Process our parents metadata after processing our own.
        super.preProcess();
    }

    /**
     * INTERNAL:
     * The pre-process for canonical model method is called (and only called)
     * during the canonical model generation. The use of this pre-process allows
     * us to remove some items from the regular pre-process that do not apply
     * to the canonical model generation.
     *
     * The order of processing is important, care must be taken if changes must
     * be made.
     */
    @Override
    public void preProcessForCanonicalModel() {
        setIsPreProcessed();

        // If we are not already an inheritance subclass (meaning we were not
        // discovered through a subclass entity discovery) then perform
        // the discovery process before processing any further. We traverse
        // the chain upwards and we can not guarantee which entity will be
        // processed first in an inheritance hierarchy.
        if (! getDescriptor().isInheritanceSubclass()) {
            discoverMappedSuperclassesAndInheritanceParents(false);
        }

        // If we are an inheritance subclass process out root first.
        if (getDescriptor().isInheritanceSubclass()) {
            // Ensure our parent accessors are processed first. Top->down.
            // An inheritance subclass can no longer blindly inherit a default
            // access type from the root of the inheritance hierarchy since
            // that root may explicitly set an access type which applies only
            // to itself. The first entity in the hierarchy (going down) that
            // does not specify an explicit type will be used to determine
            // the default access type.
            EntityAccessor parentAccessor = (EntityAccessor) getDescriptor().getInheritanceParentDescriptor().getClassAccessor();
            if (! parentAccessor.isPreProcessed()) {
                parentAccessor.preProcessForCanonicalModel();
            }
        }

        // Process our parents metadata after processing our own.
        super.preProcessForCanonicalModel();
    }

    /**
     * INTERNAL:
     * Process the items of interest on an entity class. The order of processing
     * is important, care must be taken if changes must be made.
     */
    @Override
    public void process() {
        // Process the entity annotation.
        processEntity();

        // If we are an inheritance subclass process our root first.
        if (getDescriptor().isInheritanceSubclass()) {
            ClassAccessor parentAccessor = getDescriptor().getInheritanceParentDescriptor().getClassAccessor();
            if (! parentAccessor.isProcessed()) {
                parentAccessor.process();
            }
        }

        // Process the Table and Inheritance metadata.
        processTableAndInheritance();

        // Process the indices metadata.
        processIndexes();

        // Process the cascade on delete metadata.
        processCascadeOnDelete();

        // Process the JPA converts metadata.
        processConverts();

        // Process our parents metadata after processing our own.
        super.process();

        // Finally, process the mapping accessors on this entity (and all those
        // from super classes that apply to us).
        processMappingAccessors();

        // Process the entity graph metadata.
        processEntityGraphs();
    }

    /**
     * INTERNAL:
     * For VIRTUAL access we need to look for default access methods that we
     * need to use with our mapping attributes.
     */
    public void processAccessMethods() {
        // If we use virtual access and do not have any access methods
        // specified then go look for access methods on a mapped superclass
        // or inheritance parent.
        if (hasAccessMethods()) {
            getDescriptor().setDefaultAccessMethods(getAccessMethods());
        } else {
            MetadataAnnotation virtualAccessMethods = getAnnotation(VirtualAccessMethods.class);
            if (virtualAccessMethods != null){
                getDescriptor().setDefaultAccessMethods(new AccessMethodsMetadata(virtualAccessMethods, this));
                return;
            }
            // Go through the mapped superclasses.
            for (MappedSuperclassAccessor mappedSuperclass : getMappedSuperclasses()) {
                if (mappedSuperclass.hasAccessMethods()) {
                    getDescriptor().setDefaultAccessMethods(mappedSuperclass.getAccessMethods());
                    return;
                }
                virtualAccessMethods = mappedSuperclass.getAnnotation(VirtualAccessMethods.class);
                if (virtualAccessMethods != null){
                    getDescriptor().setDefaultAccessMethods(new AccessMethodsMetadata(virtualAccessMethods, this));
                    return;
                }
            }

            // Go through the inheritance parents.
            if (getDescriptor().isInheritanceSubclass()) {
                MetadataDescriptor parentDescriptor = getDescriptor().getInheritanceParentDescriptor();
                while (parentDescriptor.isInheritanceSubclass()) {
                    if (parentDescriptor.getClassAccessor().hasAccessMethods()) {
                        getDescriptor().setDefaultAccessMethods(parentDescriptor.getClassAccessor().getAccessMethods());
                        return;
                    }
                    virtualAccessMethods = parentDescriptor.getClassAccessor().getAnnotation(VirtualAccessMethods.class);
                    if (virtualAccessMethods != null){
                        getDescriptor().setDefaultAccessMethods(new AccessMethodsMetadata(virtualAccessMethods, this));
                        return;
                    }
                    parentDescriptor = parentDescriptor.getInheritanceParentDescriptor();
                }
            }

        }
    }

    /**
     * INTERNAL:
     * Figure out the access type for this entity. It works as follows:
     * 1 - check for an explicit access type specification
     * 2 - check our inheritance parents (ignoring explicit specifications)
     * 3 - check our mapped superclasses (ignoring explicit specifications) for
     *     the location of annotations
     * 4 - check the entity itself for the location of annotations
     * 5 - check for an xml default from a persistence-unit-metadata-defaults or
     *     entity-mappings setting.
     * 6 - we have exhausted our search, default to FIELD.
     */
    @Override
    public void processAccessType() {
        // This function has been overridden in the MappedSuperclassAccessor
        // parent. Do not call this superclass method.

        // Step 1 - Check for an explicit setting.
        String explicitAccessType = getAccess();

        // Step 2, regardless if there is an explicit access type we still
        // want to determine the default access type for this entity since
        // any embeddable, mapped superclass or id class that depends on it
        // will have it available.
        String defaultAccessType = null;

        // 1 - Check the access types from our parents if we are an inheritance
        // sub-class. Inheritance hierarchies are processed top->down so our
        // first parent that does not define an explicit access type will have
        // the type we would want to default to.
        if (getDescriptor().isInheritanceSubclass()) {
            MetadataDescriptor parent = getDescriptor().getInheritanceParentDescriptor();
            while (parent != null) {
                if (! parent.getClassAccessor().hasAccess()) {
                    defaultAccessType = parent.getDefaultAccess();
                    break;
                }

                parent = parent.getInheritanceParentDescriptor();
            }
        }

        // 2 - If there is no inheritance or no inheritance parent that does not
        // explicitly define an access type. Let's check this entities mapped
        // superclasses now.
        if (defaultAccessType == null) {
            for (MappedSuperclassAccessor mappedSuperclass : getMappedSuperclasses()) {
                if (! mappedSuperclass.hasAccess()) {
                    if (mappedSuperclass.hasObjectRelationalFieldMappingAnnotationsDefined()) {
                        defaultAccessType = JPA_ACCESS_FIELD;
                    } else if (mappedSuperclass.hasObjectRelationalMethodMappingAnnotationsDefined()) {
                        defaultAccessType = JPA_ACCESS_PROPERTY;
                    }

                    break;
                }
            }

            // 3 - If there are no mapped superclasses or no mapped superclasses
            // without an explicit access type. Check where the annotations are
            // defined on this entity class.
            if (defaultAccessType == null) {
                if (hasObjectRelationalFieldMappingAnnotationsDefined()) {
                    defaultAccessType = JPA_ACCESS_FIELD;
                } else if (hasObjectRelationalMethodMappingAnnotationsDefined()) {
                    defaultAccessType = JPA_ACCESS_PROPERTY;
                } else {
                    // 4 - If there are no annotations defined on either the
                    // fields or properties, check for an xml default from
                    // persistence-unit-metadata-defaults or entity-mappings.
                    if (getDescriptor().getDefaultAccess() != null) {
                        defaultAccessType = getDescriptor().getDefaultAccess();
                    } else {
                        // 5 - We've exhausted our search, set the access type
                        // to FIELD.
                        defaultAccessType = JPA_ACCESS_FIELD;
                    }
                }
            }
        }

        // Finally set the default access type on the descriptor and log a
        // message to the user if we are defaulting the access type for this
        // entity to use that default.
        getDescriptor().setDefaultAccess(defaultAccessType);

        if (explicitAccessType == null) {
            getLogger().logConfigMessage(MetadataLogger.ACCESS_TYPE, defaultAccessType, getJavaClass());
        }

        // This access type setting on the class descriptor will be used to
        // weave the class properly.
        getDescriptor().setAccessTypeOnClassDescriptor(getAccessType());
    }

    /**
     * INTERNAL:
     * Process a caching metadata for this entity accessor logging ignore
     * warnings where necessary.
     */
    @Override
    protected void processCaching() {
        if (getProject().isSharedCacheModeAll()) {
           if (getDescriptor().isCacheableFalse()) {
               // The persistence unit has an ALL caching type and the user
               // specified Cacheable(false). Log a warning message that it is
               // being ignored. If Cacheable(true) was specified then it is
               // redundant and we just carry on.
               getLogger().logConfigMessage(MetadataLogger.IGNORE_CACHEABLE_FALSE, getJavaClass());
           }

           // Process the cache metadata.
           processCachingMetadata();
        } else if (getProject().isSharedCacheModeNone()) {
            if (getDescriptor().isCacheableTrue()) {
                // The persistence unit has a NONE caching type and the the user
                // specified Cacheable(true). Log a warning message that it is being
                // ignored. If Cacheable(false) was specified then it is redundant
                // and we just carry on.
                getLogger().logConfigMessage(MetadataLogger.IGNORE_CACHEABLE_TRUE, getJavaClass());
            }

            // Turn off the cache.
            getDescriptor().useNoCache();
        } else if (getProject().isSharedCacheModeEnableSelective()) {
            if (!getDescriptor().isCacheableTrue()) {
                // ENABLE_SELECTIVE and Cacheable(false) or no setting, turn off the cache.
                getDescriptor().useNoCache();
            }
            // Cacheable annotation in current class can override default or inherited settings.
            getDescriptor().setCacheableInDescriptor();
            // ENABLE_SELECTIVE and Cacheable(true), process the cache metadata.
            processCachingMetadata();
        } else if (getProject().isSharedCacheModeDisableSelective() || getProject().isSharedCacheModeUnspecified()) {
            if (getDescriptor().isCacheableFalse()) {
                // DISABLE_SELECTIVE and Cacheable(false), turn off cache.
                getDescriptor().useNoCache();
            }
            // Cacheable annotation in current class can override default or inherited settings.
            getDescriptor().setCacheableInDescriptor();
            // DISABLE_SELECTIVE and Cacheable(true) or no setting, process the cache metadata.
            processCachingMetadata();
        }
    }

    /**
     * INTERNAL:
     * Check if CascadeOnDelete was set on the Entity.
     */
    protected void processCascadeOnDelete() {
        getDescriptor().getClassDescriptor().setIsCascadeOnDeleteSetOnDatabaseOnSecondaryTables(isCascadeOnDelete());
    }

    /**
     * INTERNAL:
     * Return the user defined class extractor class for this entity. Assumes
     * hasClassExtractor has been called beforehand (meaning we either have
     * an annotation or XML definition.
     */
    public String processClassExtractor() {
        MetadataAnnotation classExtractor = getAnnotation(ClassExtractor.class);

        if (m_classExtractor == null) {
            m_classExtractor = getMetadataClass(classExtractor.getAttributeString("value"));
        } else {
            getLogger().logConfigMessage(MetadataLogger.OVERRIDE_ANNOTATION_WITH_XML, classExtractor, getJavaClassName(), getLocation());
        }

        return m_classExtractor.getName();
    }

    /**
     * INTERNAL:
     * Add a convert metadata to the descriptor convert map.
     */
    public void processConvert(ConvertMetadata convert) {
        if (convert.hasAttributeName()) {
            if (convert.getAttributeName().indexOf('.') > -1) {
                // We have a dot notation name.
                String dotNotationName = convert.getAttributeName();
                int dotIndex = dotNotationName.indexOf('.');
                String attributeName = dotNotationName.substring(0, dotIndex);
                String remainder = dotNotationName.substring(dotIndex + 1);
                // Update the convert attribute name for correct convert processing.
                convert.setAttributeName(remainder);
                getDescriptor().addConvert(attributeName, convert);
            } else {
                // Simple single name.
                String attributeName = convert.getAttributeName();
                convert.setAttributeName("");
                getDescriptor().addConvert(attributeName, convert);
            }
        } else {
            throw ValidationException.missingConvertAttributeName(getJavaClassName());
        }
    }

    /**
     * INTERNAL:
     * Process the convert metadata for this entity accessor logging ignore
     * warnings where necessary.
     */
    public void processConverts() {
        if (m_converts.isEmpty()) {
            // Look for a Converts annotation.
            if (isAnnotationPresent(JPA_CONVERTS)) {
                for (Object convert : getAnnotation(JPA_CONVERTS).getAttributeArray("value")) {
                    processConvert(new ConvertMetadata((MetadataAnnotation) convert, this));
                }
            } else {
                // Look for a Convert annotation
                if (isAnnotationPresent(JPA_CONVERT)) {
                    processConvert(new ConvertMetadata(getAnnotation(JPA_CONVERT), this));
                }
            }
        } else {
            if (isAnnotationPresent(JPA_CONVERT)) {
                getLogger().logConfigMessage(MetadataLogger.OVERRIDE_ANNOTATION_WITH_XML, getAnnotation(JPA_CONVERT), getJavaClassName(), getLocation());
            }

            if (isAnnotationPresent(JPA_CONVERTS)) {
                getLogger().logConfigMessage(MetadataLogger.OVERRIDE_ANNOTATION_WITH_XML, getAnnotation(JPA_CONVERTS), getJavaClassName(), getLocation());
            }

            for (ConvertMetadata convert : m_converts) {
                processConvert(convert);
            }
        }
    }

    /**
     * INTERNAL:
     * Allows for processing DerivedIds.  All referenced accessors are processed
     * first to ensure the necessary fields are set before this derivedId is processed
     */
    @Override
    public void processDerivedId(HashSet<ClassAccessor> processing, HashSet<ClassAccessor> processed) {
        if (! processed.contains(this)) {
            super.processDerivedId(processing, processed);

            // Validate we found a primary key.
            validatePrimaryKey();

            // Primary key has been validated, let's process those items that
            // depend on it now.

            // Process the SecondaryTable(s) metadata.
            processSecondaryTables();
        }
    }

    /**
     * INTERNAL:
     * Process the discriminator column metadata (defaulting if necessary),
     * and return the EclipseLink database field.
     */
    public DatabaseField processDiscriminatorColumn() {
        MetadataAnnotation discriminatorColumn = getAnnotation(JPA_DISCRIMINATOR_COLUMN);

        if (m_discriminatorColumn == null) {
            m_discriminatorColumn = new DiscriminatorColumnMetadata(discriminatorColumn, this);
        } else {
            if (isAnnotationPresent(JPA_DISCRIMINATOR_COLUMN)) {
                getLogger().logConfigMessage(MetadataLogger.OVERRIDE_ANNOTATION_WITH_XML, discriminatorColumn, getJavaClassName(), getLocation());
            }
        }

        return m_discriminatorColumn.process(getDescriptor(), MetadataLogger.INHERITANCE_DISCRIMINATOR_COLUMN);
    }

    /**
     * INTERNAL:
     * Process a discriminator value to set the class indicator on the root
     * descriptor of the inheritance hierarchy.
     *
     * If there is no discriminator value, the class indicator defaults to
     * the class name.
     */
    public String processDiscriminatorValue() {
        if (! Modifier.isAbstract(getJavaClass().getModifiers())) {
            // Add the indicator to the inheritance root class' descriptor. The
            // default is the short class name.
            if (m_discriminatorValue == null) {
                MetadataAnnotation discriminatorValue = getAnnotation(JPA_DISCRIMINATOR_VALUE);

                if (discriminatorValue == null) {
                    // By default return the alias (i.e. entity name if provided
                    // otherwise the short java class name)
                    return getDescriptor().getAlias();
                } else {
                    return discriminatorValue.getAttributeString("value");
                }
            } else {
                return m_discriminatorValue;
            }
        }

        return null;
    }

    /**
     * INTERNAL:
     * Process the entity metadata.
     */
    protected void processEntity() {
        // Process the entity name (alias) and default if necessary.
        if (m_entityName == null) {
            m_entityName = (getAnnotation(JPA_ENTITY) == null) ? "" : getAnnotation(JPA_ENTITY).getAttributeString("name");
        }

        if (m_entityName == null || m_entityName.equals("")) {
            m_entityName = Helper.getShortClassName(getJavaClassName());
            getLogger().logConfigMessage(MetadataLogger.ALIAS, getDescriptor(), m_entityName);
        }

        getProject().addAlias(m_entityName, getDescriptor());
    }

    /**
     * INTERNAL:
     * Process the entity graph metadata on this entity accessor.
     */
    protected void processEntityGraphs() {
        if (m_namedEntityGraphs.isEmpty()) {
            // Look for an NamedEntityGraphs annotation.
            if (isAnnotationPresent(JPA_ENTITY_GRAPHS)) {
                for (Object entityGraph : getAnnotation(JPA_ENTITY_GRAPHS).getAttributeArray("value")) {
                    new NamedEntityGraphMetadata((MetadataAnnotation) entityGraph, this).process(this);
                }
            } else {
                // Look for a NamedEntityGraph annotation
                if (isAnnotationPresent(JPA_ENTITY_GRAPH)) {
                    new NamedEntityGraphMetadata(getAnnotation(JPA_ENTITY_GRAPH), this).process(this);
                }
            }
        } else {
            // Process the named entity graphs from XML.
            if (isAnnotationPresent(JPA_ENTITY_GRAPH)) {
                getLogger().logConfigMessage(MetadataLogger.OVERRIDE_ANNOTATION_WITH_XML, getAnnotation(JPA_ENTITY_GRAPH), getJavaClassName(), getLocation());
            }

            if (isAnnotationPresent(JPA_ENTITY_GRAPHS)) {
                getLogger().logConfigMessage(MetadataLogger.OVERRIDE_ANNOTATION_WITH_XML, getAnnotation(JPA_ENTITY_GRAPHS), getJavaClassName(), getLocation());
            }

            for (NamedEntityGraphMetadata entityGraph : m_namedEntityGraphs) {
                entityGraph.process(this);
            }
        }
    }

    /**
     * INTERNAL:
     * Process index information for the given metadata descriptor.
     */
    protected void processIndexes() {
        // TODO: This method is adding annotation metadata to XML metadata. This
        // is wrong and does not follow the spec ideology. XML metadata should
        // override not merge with annotations.
        if (isAnnotationPresent(Index.class)) {
            m_indexes.add(new IndexMetadata(getAnnotation(Index.class), this));
        }

        if (isAnnotationPresent(Indexes.class)) {
            for (Object index : getAnnotation(Indexes.class).getAttributeArray("value")) {
                m_indexes.add(new IndexMetadata((MetadataAnnotation) index, this));
            }
        }

        for (IndexMetadata indexMetadata : m_indexes) {
            indexMetadata.process(getDescriptor(), null);
        }
    }

    /**
     * INTERNAL:
     * Process the Inheritance metadata for a root of an inheritance
     * hierarchy. One may or may not be specified for the entity class that is
     * the root of the entity class hierarchy, so we need to default in this
     * case. This method should only be called on the root of the inheritance
     * hierarchy.
     */
    protected void processInheritance() {
        // Process the inheritance metadata first. Create one if one does not
        // exist.
        if (m_inheritance == null) {
            m_inheritance = new InheritanceMetadata(getAnnotation(JPA_INHERITANCE), this);
        }

        m_inheritance.process(getDescriptor());
    }

    /**
     * INTERNAL:
     * Process the inheritance metadata for an inheritance subclass. The
     * parent descriptor must be provided.
     */
    public void processInheritancePrimaryKeyJoinColumns() {
        // If there are no primary key join columns specified in XML, look for
        // some defined through annotations.
        if (m_primaryKeyJoinColumns.isEmpty()) {
            // 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 specified.
                if (primaryKeyJoinColumn.hasForeignKey()) {
                    setPrimaryKeyForeignKey(new PrimaryKeyForeignKeyMetadata(primaryKeyJoinColumn.getForeignKey()));
                }
            }
        }

        // Process the primary key join columns into multiple table key fields.
        addMultipleTableKeyFields(m_primaryKeyJoinColumns, getDescriptor().getPrimaryTable(), MetadataLogger.INHERITANCE_PK_COLUMN, MetadataLogger.INHERITANCE_FK_COLUMN);

        // Process the primary key foreign key.
        if (m_primaryKeyForeignKey != null) {
            m_primaryKeyForeignKey.process(getDescriptor().getPrimaryTable());
        }
    }

    /**
     * INTERNAL:
     * Process the listeners for this entity.
     */
    public void processListeners(ClassLoader loader) {
        // Step 1 - process the default listeners that were defined in XML.
        // Default listeners process the class for additional lifecycle
        // callback methods that are decorated with annotations.
        // NOTE: We add the default listeners regardless if the exclude default
        // listeners flag is set. This allows the user to change the exclude
        // flag at runtime and have the default listeners available to them.
        for (EntityListenerMetadata defaultListener : getProject().getDefaultListeners()) {
            // We need to clone the default listeners. Can't re-use the
            // same one for all the entities in the persistence unit.
            ((EntityListenerMetadata) defaultListener.clone()).process(this, loader, true);
        }

        // Step 2 - process the entity listeners that are defined on the entity
        // class and mapped superclasses (taking metadata-complete into
        // consideration). Go through the mapped superclasses first, top->down
        // only if the exclude superclass listeners flag is not set.
        discoverMappedSuperclassesAndInheritanceParents(true);

        if (! getDescriptor().excludeSuperclassListeners()) {
            int mappedSuperclassesSize = getMappedSuperclasses().size();

            for (int i = mappedSuperclassesSize - 1; i >= 0; i--) {
                getMappedSuperclasses().get(i).processEntityListeners(loader);
            }
        }

        processEntityListeners(loader);

        // Step 3 - process the entity class for lifecycle callback methods. Go
        // through the mapped superclasses as well.
        new EntityClassListenerMetadata(this).process(getMappedSuperclasses(), loader);
    }

    /**
     * INTERNAL:
     * Process the accessors for the given class.
     * If we are within a TABLE_PER_CLASS inheritance hierarchy, our parent
     * accessors will already have been added at this point.
     * @see InheritanceMetadata process()
     */
    @Override
    public void processMappingAccessors() {
        // Process our mapping accessors, and then perform the necessary
        // validation checks for this entity.
        super.processMappingAccessors();

        // Validate the optimistic locking setting.
        validateOptimisticLocking();

        // Check that we have a simple pk. If it is a derived id, this will be
        // run in a second pass
        if (! hasDerivedId()){
            // Validate we found a primary key.
            validatePrimaryKey();

            // Primary key has been validated, let's process those items that
            // depend on it now.

            // Process the SecondaryTable(s) metadata.
            processSecondaryTables();
        }
    }

    /**
     * INTERNAL:
     * Process a MetadataSecondaryTable. Do all the table name defaulting and
     * set the correct, fully qualified name on the TopLink DatabaseTable.
     */
    protected void processSecondaryTable(SecondaryTableMetadata secondaryTable) {
        // Process any table defaults and log warning messages.
        processTable(secondaryTable, secondaryTable.getName());

        // Add the table to the descriptor.
        getDescriptor().addTable(secondaryTable.getDatabaseTable());

        // Get the primary key join column(s) and add the multiple table key fields.
        addMultipleTableKeyFields(secondaryTable.getPrimaryKeyJoinColumns(), secondaryTable.getDatabaseTable(), MetadataLogger.SECONDARY_TABLE_PK_COLUMN, MetadataLogger.SECONDARY_TABLE_FK_COLUMN);
    }

    /**
     * INTERNAL:
     * Process secondary-table(s) for a given entity.
     */
    protected void processSecondaryTables() {
        // Ignore secondary tables when the descriptor is an EIS descriptor.
        if (! getDescriptor().getClassDescriptor().isEISDescriptor()) {
            MetadataAnnotation secondaryTable = getAnnotation(JPA_SECONDARY_TABLE);
            MetadataAnnotation secondaryTables = getAnnotation(JPA_SECONDARY_TABLES);

            if (m_secondaryTables.isEmpty()) {
                // Look for a SecondaryTables annotation.
                if (secondaryTables != null) {
                    for (Object table : secondaryTables.getAttributeArray("value")) {
                        processSecondaryTable(new SecondaryTableMetadata((MetadataAnnotation)table, this));
                    }
                } else {
                    // Look for a SecondaryTable annotation
                    if (secondaryTable != null) {
                        processSecondaryTable(new SecondaryTableMetadata(secondaryTable, this));
                    }
                }
            } else {
                if (secondaryTable != null) {
                    getLogger().logConfigMessage(MetadataLogger.OVERRIDE_ANNOTATION_WITH_XML, secondaryTable, getJavaClassName(), getLocation());
                }

                if (secondaryTables != null) {
                    getLogger().logConfigMessage(MetadataLogger.OVERRIDE_ANNOTATION_WITH_XML, secondaryTables, getJavaClassName(), getLocation());
                }

                for (SecondaryTableMetadata table : m_secondaryTables) {
                    processSecondaryTable(table);
                }
            }
        }
    }

    /**
     * INTERNAL:
     * Process table information for the given metadata descriptor.
     */
    protected void processTable() {
        MetadataAnnotation table = getAnnotation(JPA_TABLE);

        if (m_table == null) {
            // Check for a table annotation. If no annotation is defined, the
            // table will default.
            processTable(new TableMetadata(table, this));
        } else {
            if (table != null) {
                getLogger().logConfigMessage(MetadataLogger.OVERRIDE_ANNOTATION_WITH_XML, table, getJavaClassName(), getLocation());
            }

            processTable(m_table);
        }
    }

    /**
     * INTERNAL:
     * Process a MetadataTable. Do all the table name defaulting and set the
     * correct, fully qualified name on the TopLink DatabaseTable.
     */
    protected void processTable(TableMetadata table) {
        // Ignore secondary tables when the descriptor is an EIS descriptor.
        if (! getDescriptor().getClassDescriptor().isEISDescriptor()) {
            // Process any table defaults and log warning messages.
            processTable(table, getDescriptor().getDefaultTableName());

            // Set the table on the descriptor.
            getDescriptor().setPrimaryTable(table.getDatabaseTable());
        }
    }

    /**
     * INTERNAL:
     * Process any inheritance specifics. NOTE: Inheritance hierarchies are
     * always processed from the top down so it is safe to assume that all
     * our parents have already been processed fully. The only exception being
     * when a root accessor doesn't know they are a root (defaulting case). In
     * this case we'll tell the root accessor to process the inheritance
     * metadata before continuing with our own processing.
     */
    protected void processTableAndInheritance() {
        // If we are an inheritance subclass, ensure our root is processed
        // first since it has information its subclasses depend on.
        if (getDescriptor().isInheritanceSubclass()) {
            MetadataDescriptor rootDescriptor = getDescriptor().getInheritanceRootDescriptor();
            EntityAccessor rootAccessor = (EntityAccessor) rootDescriptor.getClassAccessor();

            // An entity who didn't know they were the root of an inheritance
            // hierarchy (that is, does not define inheritance metadata) must
            // process and default the inheritance metadata.
            if (! rootAccessor.hasInheritance()) {
                rootAccessor.processInheritance();
            }

            // Process the table metadata for this descriptor if either there
            // is an inheritance specification (we're a new root) or if we are
            // part of a joined or table per class inheritance strategy.
            if (hasInheritance() || ! rootDescriptor.usesSingleTableInheritanceStrategy()) {
                processTable();
            }

            // If this entity has inheritance metadata as well, then the
            // inheritance strategy is mixed and we need to process the
            // inheritance metadata to ensure this entity's subclasses process
            // correctly.
            if (hasInheritance()) {
                // Process the inheritance metadata.
                processInheritance();
            } else {
                // Process the inheritance details using the inheritance
                // metadata from our parent. This will put the right
                // inheritance policy on our descriptor.
                rootAccessor.getInheritance().process(getDescriptor());
            }
        } else {
            // Process the table metadata if there is some, otherwise default.
            processTable();

            // If we have inheritance metadata, then process it now. If we are
            // an inheritance root class that doesn't know it, a subclass will
            // force this processing to occur.
            if (hasInheritance()) {
                processInheritance();
            }
        }
    }

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

    /**
     * INTERNAL:
     * Used for OX mapping.
     */
    public void setClassExtractorName(String classExtractorName) {
        m_classExtractorName = classExtractorName;
    }

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

    /**
     * INTERNAL:
     * Used for OX mapping.
     */
    public void setDiscriminatorColumn(DiscriminatorColumnMetadata discriminatorColumn) {
        m_discriminatorColumn = discriminatorColumn;
    }

    /**
     * INTERNAL:
     * Used for OX mapping.
     */
    public void setDiscriminatorValue(String discriminatorValue) {
        m_discriminatorValue = discriminatorValue;
    }

    /**
     * INTERNAL:
     * Used for OX mapping.
     */
    public void setEntityName(String entityName) {
        m_entityName = entityName;
    }

    /**
     * INTERNAL:
     * Used for OX mapping.
     */
    public void setIndexes(List<IndexMetadata> indexes) {
        m_indexes = indexes;
    }

    /**
     * INTERNAL:
     * Used for OX mapping.
     */
    public void setInheritance(InheritanceMetadata inheritance) {
        m_inheritance = inheritance;
    }

    /**
     * INTERNAL:
     * Used for OX mapping.
     */
    public void setNamedEntityGraphs(List<NamedEntityGraphMetadata> namedEntityGraphs) {
        m_namedEntityGraphs = namedEntityGraphs;
    }

    /**
     * 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;
    }

    /**
     * INTERNAL:
     * Used for OX mapping.
     */
    public void setSecondaryTables(List<SecondaryTableMetadata> secondaryTables) {
        m_secondaryTables = secondaryTables;
    }

    /**
     * INTERNAL:
     * Used for OX mapping.
     */
    public void setTable(TableMetadata table) {
        m_table = table;
    }

    /**
     * INTERNAL:
     * Validate a OptimisticLocking(type=VERSION_COLUMN) setting. That is,
     * validate that we found a version field. If not, throw an exception.
     */
    protected void validateOptimisticLocking() {
        if (getDescriptor().usesVersionColumnOptimisticLocking() && ! getDescriptor().usesOptimisticLocking()) {
            throw ValidationException.optimisticLockingVersionElementNotSpecified(getJavaClass());
        }
    }

    /**
     * INTERNAL:
     * Call this method after a primary key should have been found.
     */
    protected void validatePrimaryKey() {
        // If this descriptor has a composite primary key, check that all
        // our composite primary key attributes were validated.
        if (getDescriptor().hasCompositePrimaryKey()) {
            if (getDescriptor().pkClassWasNotValidated()) {
                throw ValidationException.invalidCompositePKSpecification(getJavaClass(), getDescriptor().getPKClassName());
            }

            // Log a warning to the user that they have specified multiple id
            // fields without an id class specification. If they are using a
            // @PrimaryKey specification don't issue the warning.
            if (! getDescriptor().hasPKClass() && ! getDescriptor().hasPrimaryKey()) {
                getLogger().logWarningMessage(MetadataLogger.MULTIPLE_ID_FIELDS_WITHOUT_ID_CLASS, getJavaClassName());
            }
        } else {
            // Descriptor has a single primary key. Validate an id attribute was
            // found, unless we are an inheritance subclass or an aggregate descriptor.
            if (! getDescriptor().hasPrimaryKeyFields() && ! getDescriptor().isInheritanceSubclass()) {
                throw ValidationException.noPrimaryKeyAnnotationsFound(getJavaClass());
            }
        }
    }
}
