/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 1998, 2021 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
//     stardif - updates for Cascaded locking and inheritance
//     02/20/2009-1.1 Guy Pelletier
//       - 259829: TABLE_PER_CLASS with abstract classes does not work
//     10/15/2010-2.2 Guy Pelletier
//       - 322008: Improve usability of additional criteria applied to queries at the session/EM
//     04/01/2011-2.3 Guy Pelletier
//       - 337323: Multi-tenant with shared schema support (part 2)
//     04/05/2011-2.3 Guy Pelletier
//       - 337323: Multi-tenant with shared schema support (part 3)
//     04/21/2011-2.3 Guy Pelletier
//       - 337323: Multi-tenant with shared schema support (part 5)
//     09/09/2011-2.3.1 Guy Pelletier
//       - 356197: Add new VPD type to MultitenantType
//     11/10/2011-2.4 Guy Pelletier
//       - 357474: Address primaryKey option from tenant discriminator column
//     14/05/2012-2.4 Guy Pelletier
//       - 376603: Provide for table per tenant support for multitenant applications
//     30/05/2012-2.4 Guy Pelletier
//       - 354678: Temp classloader is still being used during metadata processing
//     09 Jan 2013-2.5 Gordon Yorke
//       - 397772: JPA 2.1 Entity Graph Support
//     06/25/2014-2.5.2 Rick Curtis
//       - 438177: Support M2M map with jointable
//     08/12/2015-2.6 Mythily Parthasarathy
//       - 474752: Address NPE for Embeddable with 1-M association
//     07/09/2018-2.6 Jody Grassel
//       - 536853: MapsID processing sets up to fail validation
package org.eclipse.persistence.descriptors;

import java.io.Serializable;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;

import org.eclipse.persistence.annotations.CacheKeyType;
import org.eclipse.persistence.annotations.IdValidation;
import org.eclipse.persistence.config.CacheIsolationType;
import org.eclipse.persistence.core.descriptors.CoreDescriptor;
import org.eclipse.persistence.descriptors.changetracking.AttributeChangeTrackingPolicy;
import org.eclipse.persistence.descriptors.changetracking.ChangeTracker;
import org.eclipse.persistence.descriptors.changetracking.DeferredChangeDetectionPolicy;
import org.eclipse.persistence.descriptors.changetracking.ObjectChangePolicy;
import org.eclipse.persistence.descriptors.copying.CloneCopyPolicy;
import org.eclipse.persistence.descriptors.copying.CopyPolicy;
import org.eclipse.persistence.descriptors.copying.InstantiationCopyPolicy;
import org.eclipse.persistence.descriptors.copying.PersistenceEntityCopyPolicy;
import org.eclipse.persistence.descriptors.invalidation.CacheInvalidationPolicy;
import org.eclipse.persistence.descriptors.invalidation.NoExpiryCacheInvalidationPolicy;
import org.eclipse.persistence.descriptors.partitioning.PartitioningPolicy;
import org.eclipse.persistence.exceptions.DatabaseException;
import org.eclipse.persistence.exceptions.DescriptorException;
import org.eclipse.persistence.exceptions.ValidationException;
import org.eclipse.persistence.expressions.Expression;
import org.eclipse.persistence.expressions.ExpressionBuilder;
import org.eclipse.persistence.history.HistoryPolicy;
import org.eclipse.persistence.internal.databaseaccess.DatabaseCall;
import org.eclipse.persistence.internal.databaseaccess.DatasourceCall;
import org.eclipse.persistence.internal.databaseaccess.Platform;
import org.eclipse.persistence.internal.descriptors.CascadeLockingPolicy;
import org.eclipse.persistence.internal.descriptors.InstantiationPolicy;
import org.eclipse.persistence.internal.descriptors.ObjectBuilder;
import org.eclipse.persistence.internal.descriptors.OptimisticLockingPolicy;
import org.eclipse.persistence.internal.descriptors.PersistenceObject;
import org.eclipse.persistence.internal.descriptors.PersistenceObjectAttributeAccessor;
import org.eclipse.persistence.internal.descriptors.PersistenceObjectInstantiationPolicy;
import org.eclipse.persistence.internal.descriptors.SerializedObjectPolicyWrapper;
import org.eclipse.persistence.internal.descriptors.VirtualAttributeMethodInfo;
import org.eclipse.persistence.internal.dynamic.DynamicEntityImpl;
import org.eclipse.persistence.internal.expressions.SQLSelectStatement;
import org.eclipse.persistence.internal.expressions.SQLStatement;
import org.eclipse.persistence.internal.helper.ClassConstants;
import org.eclipse.persistence.internal.helper.ConversionManager;
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.helper.MappingCompare;
import org.eclipse.persistence.internal.helper.NonSynchronizedVector;
import org.eclipse.persistence.internal.identitymaps.IdentityMap;
import org.eclipse.persistence.internal.indirection.ProxyIndirectionPolicy;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.internal.security.PrivilegedClassForName;
import org.eclipse.persistence.internal.security.PrivilegedMethodInvoker;
import org.eclipse.persistence.internal.security.PrivilegedNewInstanceFromClass;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.internal.weaving.PersistenceWeavedChangeTracking;
import org.eclipse.persistence.mappings.AggregateCollectionMapping;
import org.eclipse.persistence.mappings.AggregateMapping;
import org.eclipse.persistence.mappings.AggregateObjectMapping;
import org.eclipse.persistence.mappings.Association;
import org.eclipse.persistence.mappings.AttributeAccessor;
import org.eclipse.persistence.mappings.CollectionMapping;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.DirectCollectionMapping;
import org.eclipse.persistence.mappings.DirectToFieldMapping;
import org.eclipse.persistence.mappings.ForeignReferenceMapping;
import org.eclipse.persistence.mappings.ManyToManyMapping;
import org.eclipse.persistence.mappings.ManyToOneMapping;
import org.eclipse.persistence.mappings.ObjectReferenceMapping;
import org.eclipse.persistence.mappings.OneToManyMapping;
import org.eclipse.persistence.mappings.OneToOneMapping;
import org.eclipse.persistence.mappings.UnidirectionalOneToManyMapping;
import org.eclipse.persistence.mappings.foundation.AbstractDirectMapping;
import org.eclipse.persistence.mappings.querykeys.DirectQueryKey;
import org.eclipse.persistence.mappings.querykeys.QueryKey;
import org.eclipse.persistence.queries.AttributeGroup;
import org.eclipse.persistence.queries.DatabaseQuery;
import org.eclipse.persistence.queries.DeleteObjectQuery;
import org.eclipse.persistence.queries.FetchGroup;
import org.eclipse.persistence.queries.FetchGroupTracker;
import org.eclipse.persistence.queries.InsertObjectQuery;
import org.eclipse.persistence.queries.ObjectLevelReadQuery;
import org.eclipse.persistence.queries.QueryRedirector;
import org.eclipse.persistence.queries.ReadObjectQuery;
import org.eclipse.persistence.sequencing.Sequence;
import org.eclipse.persistence.sessions.DatabaseRecord;
import org.eclipse.persistence.sessions.Project;
import org.eclipse.persistence.sessions.interceptors.CacheInterceptor;
import org.eclipse.persistence.sessions.remote.DistributedSession;

/**
 * <p><b>Purpose</b>:
 * Abstract descriptor class for defining persistence information on a class.
 * This class provides the data independent behavior and is subclassed,
 * for relational, object-relational, EIS, XML, etc.
 *
 * @see RelationalDescriptor
 * @see org.eclipse.persistence.mappings.structures.ObjectRelationalDataTypeDescriptor
 * @see org.eclipse.persistence.eis.EISDescriptor
 * @see org.eclipse.persistence.oxm.XMLDescriptor
 */
public class ClassDescriptor extends CoreDescriptor<AttributeGroup, DescriptorEventManager, DatabaseField, InheritancePolicy, InstantiationPolicy, Vector, ObjectBuilder> implements Cloneable, Serializable {
    protected Class<?> javaClass;
    protected String javaClassName;
    protected Vector<DatabaseTable> tables;
    protected transient DatabaseTable defaultTable;
    protected List<DatabaseField> primaryKeyFields;
    protected Map<DatabaseTable, Map<DatabaseField, DatabaseField>> additionalTablePrimaryKeyFields;
    protected transient List<DatabaseTable> multipleTableInsertOrder;
    protected Map<DatabaseTable, Set<DatabaseTable>> multipleTableForeignKeys;
    /** Support delete cascading on the database for multiple and inheritance tables. */
    protected boolean isCascadeOnDeleteSetOnDatabaseOnSecondaryTables;

    protected transient Vector<DatabaseField> fields;
    protected transient Vector<DatabaseField> allFields;
    protected transient List<DatabaseField> selectionFields;
    protected transient List<DatabaseField> allSelectionFields;
    protected transient Vector<DatabaseField> returnFieldsToGenerateInsert;
    protected transient Vector<DatabaseField> returnFieldsToGenerateUpdate;
    protected transient List<DatabaseField> returnFieldsToMergeInsert;
    protected transient List<DatabaseField> returnFieldsToMergeUpdate;

    protected Vector<DatabaseMapping> mappings;

    //Used to track which other classes reference this class in cases where
    // the referencing classes need to be notified of something.
    protected Set<ClassDescriptor> referencingClasses;

    //used by the lock on clone process.  This will contain the foreign reference
    //mapping without indirection
    protected List<DatabaseMapping> lockableMappings;
    protected Map<String, QueryKey> queryKeys;

    // Additional properties.
    protected String sequenceNumberName;
    protected DatabaseField sequenceNumberField;
    protected transient String sessionName;
    protected transient Vector constraintDependencies;
    protected transient String amendmentMethodName;
    protected transient Class<?> amendmentClass;
    protected String amendmentClassName;
    protected String alias;
    protected boolean shouldBeReadOnly;
    protected boolean shouldAlwaysConformResultsInUnitOfWork;

    // for bug 2612601 allow ability not to register results in UOW.
    protected boolean shouldRegisterResultsInUnitOfWork = true;

    // Delegation objects, these perform most of the behavior.
    protected DescriptorQueryManager queryManager;
    protected CopyPolicy copyPolicy;
    protected String copyPolicyClassName;
    protected InterfacePolicy interfacePolicy;
    protected OptimisticLockingPolicy optimisticLockingPolicy;
    protected transient List<CascadeLockingPolicy> cascadeLockingPolicies;
    protected WrapperPolicy wrapperPolicy;
    protected ObjectChangePolicy changePolicy;
    protected ReturningPolicy returningPolicy;
    protected List<ReturningPolicy> returningPolicies;
    protected HistoryPolicy historyPolicy;
    protected String partitioningPolicyName;
    protected PartitioningPolicy partitioningPolicy;
    protected CMPPolicy cmpPolicy;
    protected CachePolicy cachePolicy;
    protected MultitenantPolicy multitenantPolicy;
    protected SerializedObjectPolicy serializedObjectPolicy;

    //manage fetch group behaviors and operations
    protected FetchGroupManager fetchGroupManager;

    /** Additional properties may be added. */
    protected Map properties;
    /** Allow the user to defined un-converted properties which will be initialized at runtime. */
    protected Map<String, List<String>> unconvertedProperties;

    protected transient int initializationStage;
    protected transient int interfaceInitializationStage;
    /** The following are the [initializationStage] states the descriptor passes through during the initialization. */
    protected static final int UNINITIALIZED = 0;
    protected static final int PREINITIALIZED = 1;
    protected static final int INITIALIZED = 2; // this state represents a fully initialized descriptor
    protected static final int POST_INITIALIZED = 3; // however this value is used by the public function isFullyInitialized()
    protected static final int ERROR = -1;

    protected int descriptorType;
    /** Define valid descriptor types. */
    protected static final int NORMAL = 0;
    protected static final int INTERFACE = 1;
    protected static final int AGGREGATE = 2;
    protected static final int AGGREGATE_COLLECTION = 3;

    protected boolean shouldOrderMappings;
    protected CacheInvalidationPolicy cacheInvalidationPolicy = null;

    /** PERF: Used to optimize cache locking to only acquire deferred locks when required (no-indirection). */
    protected boolean shouldAcquireCascadedLocks = false;
    /** INTERNAL: flag to indicate the initialization state of cascade locking for this descriptor */
    protected boolean cascadedLockingInitialized = false;

    /** PERF: Compute and store if the primary key is simple (direct-mapped) to allow fast extraction. */
    protected boolean hasSimplePrimaryKey = false;

    /**
     * Defines if any mapping reference a field in a secondary table.
     * This is used to disable deferring multiple table writes.
     */
    protected boolean hasMultipleTableConstraintDependecy = false;

    public static final int UNDEFINED_OBJECT_CHANGE_BEHAVIOR = CachePolicy.UNDEFINED_OBJECT_CHANGE_BEHAVIOR;
    public static final int SEND_OBJECT_CHANGES = CachePolicy.SEND_OBJECT_CHANGES;
    public static final int INVALIDATE_CHANGED_OBJECTS = CachePolicy.INVALIDATE_CHANGED_OBJECTS;
    public static final int SEND_NEW_OBJECTS_WITH_CHANGES = CachePolicy.SEND_NEW_OBJECTS_WITH_CHANGES;
    public static final int DO_NOT_SEND_CHANGES = CachePolicy.DO_NOT_SEND_CHANGES;

    public static final int UNDEFINED_ISOLATATION = CachePolicy.UNDEFINED_ISOLATATION;
    public static final int USE_SESSION_CACHE_AFTER_TRANSACTION = CachePolicy.USE_SESSION_CACHE_AFTER_TRANSACTION;
    public static final int ISOLATE_NEW_DATA_AFTER_TRANSACTION = CachePolicy.ISOLATE_NEW_DATA_AFTER_TRANSACTION; // this is the default behaviour even when undefined.
    public static final int ISOLATE_CACHE_AFTER_TRANSACTION = CachePolicy.ISOLATE_CACHE_AFTER_TRANSACTION;
    public static final int ISOLATE_FROM_CLIENT_SESSION = CachePolicy.ISOLATE_FROM_CLIENT_SESSION;  // Entity Instances only exist in UOW and shared cache.
    public static final int ISOLATE_CACHE_ALWAYS = CachePolicy.ISOLATE_CACHE_ALWAYS;

    /** INTERNAL: Backdoor for using changes sets for new objects. */
    public static boolean shouldUseFullChangeSetsForNewObjects = false;

    /** Allow connection unwrapping to be configured. */
    protected boolean isNativeConnectionRequired;

    /** Allow zero primary key validation to be configured. */
    protected IdValidation idValidation;

    /** Allow zero primary key validation to be configured per field. */
    protected List<IdValidation> primaryKeyIdValidations;

    // JPA 2.0 Derived identities - map of mappings that act as derived ids
    protected Map<String, DatabaseMapping> derivesIdMappings;

    //Added for default Redirectors
    protected QueryRedirector defaultQueryRedirector;
    protected QueryRedirector defaultReadAllQueryRedirector;
    protected QueryRedirector defaultReadObjectQueryRedirector;
    protected QueryRedirector defaultReportQueryRedirector;
    protected QueryRedirector defaultUpdateObjectQueryRedirector;
    protected QueryRedirector defaultInsertObjectQueryRedirector;
    protected QueryRedirector defaultDeleteObjectQueryRedirector;

    //Added for default Redirectors
    protected String defaultQueryRedirectorClassName;
    protected String defaultReadAllQueryRedirectorClassName;
    protected String defaultReadObjectQueryRedirectorClassName;
    protected String defaultReportQueryRedirectorClassName;
    protected String defaultUpdateObjectQueryRedirectorClassName;
    protected String defaultInsertObjectQueryRedirectorClassName;
    protected String defaultDeleteObjectQueryRedirectorClassName;

    /** Store the Sequence used for the descriptor. */
    protected Sequence sequence;

    /** Mappings that require postCalculateChanges method to be called */
    protected List<DatabaseMapping> mappingsPostCalculateChanges;
    /** Mappings that require postCalculateChangesOnDeleted method to be called */
    protected List<DatabaseMapping> mappingsPostCalculateChangesOnDeleted;

    /** used by aggregate descriptors to hold additional fields needed when they are stored in an AggregatateCollection
     *  These fields are generally foreign key fields that are required in addition to the fields in the descriptor's
     *  mappings to uniquely identify the Aggregate*/
    protected transient List<DatabaseField> additionalAggregateCollectionKeyFields;

    /** stores a list of mappings that require preDelete as a group prior to the delete individually */
    protected List<DatabaseMapping> preDeleteMappings;

    /** stores fields that are written by Map key mappings so they can be checked for multiple writable mappings */
    protected transient List<DatabaseField> additionalWritableMapKeyFields;

    /** whether this descriptor has any relationships through its mappings, through inheritance, or through aggregates */
    protected boolean hasRelationships = false;

    /** Stores a set of FK fields that will be cached to later retrieve noncacheable mappings */
    protected Set<DatabaseField> foreignKeyValuesForCaching;

    /** caches if this descriptor has any non cacheable mappings */
    protected boolean hasNoncacheableMappings = false;

    /** This flag stores whether this descriptor is using Property access based on JPA semantics.  It is used to modify
     * the behavior of our weaving functionality as it pertains to adding annotations to fields
     */
    protected boolean weavingUsesPropertyAccess = false;

    /** A list of methods that are used by virtual mappings.  This list is used to control weaving of methods
     * used for virtual access*/
    protected List<VirtualAttributeMethodInfo> virtualAttributeMethods = null;

    /**
     * A list of AttributeAccessors in order of access from root to leaf to arrive at current AggregateDescriptor.
     * Only application for Aggregate Descriptors.
     */
    protected List<AttributeAccessor> accessorTree;

    /**
     * JPA DescriptorCustomizer list stored here to preserve it when caching the project
     */
    protected String descriptorCustomizerClassName;

    /**
     * This flag controls if a UOW should acquire locks for clone or simple clone the instance passed to registerExistingObject.  If the IdentityMap type does not
     * have concurrent access this can save a return to the identity map for cloning.
     */
    protected boolean shouldLockForClone = true;

    /**
     * PUBLIC:
     * Return a new descriptor.
     */
    public ClassDescriptor() {
        // Properties
        this.tables = NonSynchronizedVector.newInstance(3);
        this.mappings = NonSynchronizedVector.newInstance();
        this.primaryKeyFields = new ArrayList<>(2);
        this.fields = NonSynchronizedVector.newInstance();
        this.allFields = NonSynchronizedVector.newInstance();
        this.constraintDependencies = NonSynchronizedVector.newInstance(2);
        this.multipleTableForeignKeys = new HashMap<>(5);
        this.queryKeys = new HashMap<>(5);
        this.initializationStage = UNINITIALIZED;
        this.interfaceInitializationStage = UNINITIALIZED;
        this.descriptorType = NORMAL;
        this.shouldOrderMappings = true;
        this.shouldBeReadOnly = false;
        this.shouldAlwaysConformResultsInUnitOfWork = false;
        this.shouldAcquireCascadedLocks = false;
        this.hasSimplePrimaryKey = false;
        this.derivesIdMappings = new HashMap<>(5);

        this.referencingClasses = new HashSet<>();

        // Policies
        this.objectBuilder = new ObjectBuilder(this);
        this.cachePolicy = new CachePolicy();

        this.additionalWritableMapKeyFields = new ArrayList<>(2);
        this.foreignKeyValuesForCaching = new HashSet<>();
    }

    /**
     * PUBLIC:
     * This method should only be used for interface descriptors.  It
     * adds an abstract query key to the interface descriptor.  Any
     * implementors of that interface must define the query key
     * defined by this abstract query key.
     */
    public void addAbstractQueryKey(String queryKeyName) {
        QueryKey queryKey = new QueryKey();
        queryKey.setName(queryKeyName);
        addQueryKey(queryKey);
    }

    /**
     * INTERNAL:
     * Add the cascade locking policy to all children that have a relationship to this descriptor
     * either by inheritance or by encapsulation/aggregation.
     * @param policy - the CascadeLockingPolicy
     */
    public void addCascadeLockingPolicy(CascadeLockingPolicy policy) {
        getCascadeLockingPolicies().add(policy);
        // 232608: propagate later version changes up to the locking policy on a parent branch by setting the policy on all children here
        if (hasInheritance()) {
            // InOrder traverse the entire [deep] tree, not just the next level
            for (ClassDescriptor parent : getInheritancePolicy().getAllChildDescriptors()) {
                // Set the same cascade locking policy on all descriptors that inherit from this descriptor.
                parent.addCascadeLockingPolicy(policy);
            }
        }

        // do not propagate an extra locking policy to other mappings, if this descriptor already
        // has a cascaded optimistic locking policy that will be cascaded
        if (!this.cascadedLockingInitialized) {
            // never cascade locking until descriptor is initialized
            if (isInitialized(INITIALIZED)) {
                // Set cascade locking policies on privately owned children mappings.
                for (DatabaseMapping mapping : getMappings()) {
                    prepareCascadeLockingPolicy(mapping);
                }
                this.cascadedLockingInitialized = true;
            }
        }
    }

    /**
     * ADVANCED:
     * EclipseLink automatically orders database access through the foreign key information provided in 1:1 and 1:m mappings.
     * In some case when 1:1 are not defined it may be required to tell the descriptor about a constraint,
     * this defines that this descriptor has a foreign key constraint to another class and must be inserted after
     * instances of the other class.
     */
    public void addConstraintDependencies(Class<?> dependencies) {
        addConstraintDependency(dependencies);
    }

    /**
     * ADVANCED:
     * EclipseLink automatically orders database access through the foreign key information provided in 1:1 and 1:m mappings.
     * In some case when 1:1 are not defined it may be required to tell the descriptor about a constraint,
     * this defines that this descriptor has a foreign key constraint to another class and must be inserted after
     * instances of the other class.
     */
    public void addConstraintDependency(Class<?> dependencies) {
        getConstraintDependencies().add(dependencies);
    }

    /**
     * Return a new direct/basic mapping for this type of descriptor.
     */
    public AbstractDirectMapping newDirectMapping() {
        return new DirectToFieldMapping();
    }

    /**
     * Return a new aggregate/embedded mapping for this type of descriptor.
     */
    public AggregateMapping newAggregateMapping() {
        return new AggregateObjectMapping();
    }

    /**
     * Return a new aggregate collection/element collection mapping for this type of descriptor.
     */
    public DatabaseMapping newAggregateCollectionMapping() {
        return new AggregateCollectionMapping();
    }

    /**
     * Return a new direct collection/element collection mapping for this type of descriptor.
     */
    public DatabaseMapping newDirectCollectionMapping() {
        return new DirectCollectionMapping();
    }

    /**
     * Return a new one to one mapping for this type of descriptor.
     */
    public ObjectReferenceMapping newOneToOneMapping() {
        OneToOneMapping mapping = new OneToOneMapping();
        mapping.setIsOneToOneRelationship(true);
        return mapping;
    }

    /**
     * Return a new many to one mapping for this type of descriptor.
     */
    public ObjectReferenceMapping newManyToOneMapping() {
        return new ManyToOneMapping();
    }

    /**
     * Return a new one to many mapping for this type of descriptor.
     */
    public CollectionMapping newOneToManyMapping() {
        return new OneToManyMapping();
    }

    /**
     * Return a new one to many mapping for this type of descriptor.
     */
    public CollectionMapping newUnidirectionalOneToManyMapping() {
        return new UnidirectionalOneToManyMapping();
    }

    /**
     * Return a new one to many mapping for this type of descriptor.
     */
    public CollectionMapping newManyToManyMapping() {
        return new ManyToManyMapping();
    }

    /**
     * PUBLIC:
     * Add a direct to field mapping to the receiver. The new mapping specifies that
     * an instance variable of the class of objects which the receiver describes maps in
     * the default manner for its type to the indicated database field.
     *
     * @param attributeName is the name of an instance variable of the
     * class which the receiver describes.
     * @param fieldName is the name of the database column which corresponds
     * with the designated instance variable.
     * @return The newly created DatabaseMapping is returned.
     */
    public DatabaseMapping addDirectMapping(String attributeName, String fieldName) {
        AbstractDirectMapping mapping = newDirectMapping();

        mapping.setAttributeName(attributeName);
        mapping.setField(new DatabaseField(fieldName));

        return addMapping(mapping);
    }

    /**
     * PUBLIC:
     * Add a direct to field mapping to the receiver. The new mapping specifies that
     * a variable accessed by the get and set methods of the class of objects which
     * the receiver describes maps in  the default manner for its type to the indicated
     * database field.
     */
    public DatabaseMapping addDirectMapping(String attributeName, String getMethodName, String setMethodName, String fieldName) {
        AbstractDirectMapping mapping = (AbstractDirectMapping)addDirectMapping(attributeName, fieldName);

        mapping.setSetMethodName(setMethodName);
        mapping.setGetMethodName(getMethodName);

        return mapping;
    }

    /**
     * PUBLIC:
     * Add a query key to the descriptor. Query keys define Java aliases to database fields.
     */
    public void addDirectQueryKey(String queryKeyName, String fieldName) {
        DirectQueryKey queryKey = new DirectQueryKey();
        DatabaseField field = new DatabaseField(fieldName);

        queryKey.setName(queryKeyName);
        queryKey.setField(field);
        getQueryKeys().put(queryKeyName, queryKey);
    }

    /**
     * PUBLIC:
     * This protocol can be used to associate multiple tables with foreign key
     * information. Use this method to associate secondary tables to a
     * primary table. Specify the source foreign key field to the target
     * primary key field. The join criteria will be generated based on the
     * fields provided. Unless the customary insert order is specified by the user
     * (using setMultipleTableInsertOrder method)
     * the (automatically generated) table insert order will ensure that
     * insert into target table happens before insert into the source table
     * (there may be a foreign key constraint in the database that requires
     * target table to be inserted before the source table).
     */
    public void addForeignKeyFieldNameForMultipleTable(String sourceForeignKeyFieldName, String targetPrimaryKeyFieldName) throws DescriptorException {
        addForeignKeyFieldForMultipleTable(new DatabaseField(sourceForeignKeyFieldName), new DatabaseField(targetPrimaryKeyFieldName));
    }

    /**
     * PUBLIC:
     * This protocol can be used to associate multiple tables with foreign key
     * information. Use this method to associate secondary tables to a
     * primary table. Specify the source foreign key field to the target
     * primary key field. The join criteria will be generated based on the
     * fields provided.
     */
    public void addForeignKeyFieldForMultipleTable(DatabaseField sourceForeignKeyField, DatabaseField targetPrimaryKeyField) throws DescriptorException {
        // Make sure that the table is fully qualified.
        if ((!sourceForeignKeyField.hasTableName()) || (!targetPrimaryKeyField.hasTableName())) {
            throw DescriptorException.multipleTablePrimaryKeyMustBeFullyQualified(this);
        }

        setAdditionalTablePrimaryKeyFields(sourceForeignKeyField.getTable(), targetPrimaryKeyField, sourceForeignKeyField);
        Set<DatabaseTable> sourceTables = getMultipleTableForeignKeys().get(targetPrimaryKeyField.getTable());
        if(sourceTables == null) {
            sourceTables = new HashSet<>(3);
            getMultipleTableForeignKeys().put(targetPrimaryKeyField.getTable(), sourceTables);
        }
        sourceTables.add(sourceForeignKeyField.getTable());
    }

    /**
     * PUBLIC:
     * Add a database mapping to the receiver. Perform any required
     * initialization of both the mapping and the receiving descriptor
     * as a result of adding the new mapping.
     */
    public DatabaseMapping addMapping(DatabaseMapping mapping) {
        // For CR#2646, if the mapping already points to the parent descriptor then leave it.
        if (mapping.getDescriptor() == null) {
            mapping.setDescriptor(this);
        }
        getMappings().add(mapping);
        return mapping;
    }

    protected void validateMappingType(DatabaseMapping mapping) {
        if (!(mapping.isRelationalMapping())) {
            throw DescriptorException.invalidMappingType(mapping);
        }
    }

    /**
     * PUBLIC:
     * Specify the primary key field of the descriptors table.
     * This should be called for each field that makes up the primary key of the table.
     * If the descriptor has many tables, this must be the primary key in the first table,
     * if the other tables have the same primary key nothing else is required, otherwise
     * a primary key/foreign key field mapping must be provided for each of the other tables.
     * @see #addForeignKeyFieldNameForMultipleTable(String, String)
     */
    public void addPrimaryKeyFieldName(String fieldName) {
        addPrimaryKeyField(new DatabaseField(fieldName));
    }

    /**
     * ADVANCED:
     * Specify the primary key field of the descriptors table.
     * This should be called for each field that makes up the primary key of the table.
     * This can be used for advanced field types, such as XML nodes, or to set the field type.
     */
    public void addPrimaryKeyField(DatabaseField field) {
        // Check if the pkFields List already contains a DatabaseField that is equal to the
        // field we want to add, in order to avoid duplicates which will fail validation later.
        List<DatabaseField> pkFields = getPrimaryKeyFields();
        if (!pkFields.contains(field)) {
            pkFields.add(field);
        }
    }

    /**
     * PUBLIC:
     * Add a query key to the descriptor. Query keys define Java aliases to database fields.
     */
    public void addQueryKey(QueryKey queryKey) {
        getQueryKeys().put(queryKey.getName(), queryKey);
    }

    /**
     * PUBLIC:
     * Specify the table for the class of objects the receiver describes.
     * This method is used if there is more than one table.
     */
    public void addTable(DatabaseTable table) {
        getTables().add(table);
    }

    /**
     * PUBLIC:
     * Specify the table name for the class of objects the receiver describes.
     * If the table has a qualifier it should be specified using the dot notation,
     * (i.e. "userid.employee"). This method is used if there is more than one table.
     */
    public void addTableName(String tableName) {
        addTable(new DatabaseTable(tableName));
    }

    /**
     * PUBLIC:
     * Add an unconverted property (to be initialiazed at runtime)
     */
    public void addUnconvertedProperty(String propertyName, String propertyValue, String propertyType) {
        List<String> valuePair = new ArrayList<>(2);
        valuePair.add(propertyValue);
        valuePair.add(propertyType);
        getUnconvertedProperties().put(propertyName, valuePair);
    }

    /**
     * INTERNAL:
     * Adjust the order of the tables in the multipleTableInsertOrder Vector according to the FK
     * relationship if one (or more) were previously specified. I.e. target of FK relationship should be inserted
     * before source.
     * If the multipleTableInsertOrder has been specified (presumably by the user) then do not change it.
     */
    public void adjustMultipleTableInsertOrder() {
        // Check if a user defined insert order was given.
        if ((getMultipleTableInsertOrder() == null) || getMultipleTableInsertOrder().isEmpty()) {
            createMultipleTableInsertOrder();
        } else {
            verifyMultipleTableInsertOrder();
        }
        toggleAdditionalTablePrimaryKeyFields();
    }

    /**
     * PUBLIC:
     * Used to set the descriptor to always conform in any unit of work query.
     *
     */
    public void alwaysConformResultsInUnitOfWork() {
        setShouldAlwaysConformResultsInUnitOfWork(true);
    }

    /**
     * PUBLIC:
     * This method is the equivalent of calling {@link #setShouldAlwaysRefreshCache} with an argument of <CODE>true</CODE>:
     * it configures a <CODE>ClassDescriptor</CODE> to always refresh the cache if data is received from the database by any query.<P>
     *
     * However, if a query hits the cache, data is not refreshed regardless of how this setting is configured. For example, by
     * default, when a query for a single object based on its primary key is executed, OracleAS TopLink will first look in the
     * cache for the object. If the object is in the cache, the cached object is returned and data is not refreshed. To avoid
     * cache hits, use the {@link #disableCacheHits} method.<P>
     *
     * Also note that the {@link org.eclipse.persistence.sessions.UnitOfWork} will not refresh its registered objects.<P>
     *
     * Use this property with caution because it can lead to poor performance and may refresh on queries when it is not desired. Normally,
     * if you require fresh data, it is better to configure a query with {@link org.eclipse.persistence.queries.ObjectLevelReadQuery#refreshIdentityMapResult}.
     * To ensure that refreshes are only done when required, use this method in conjunction with {@link #onlyRefreshCacheIfNewerVersion}.
     *
     * @see #dontAlwaysRefreshCache
     */
    public void alwaysRefreshCache() {
        setShouldAlwaysRefreshCache(true);
    }

    /**
     * PUBLIC:
     * This method is the equivalent of calling {@link #setShouldAlwaysRefreshCacheOnRemote} with an argument of <CODE>true</CODE>:
     * it configures a <CODE>ClassDescriptor</CODE> to always remotely refresh the cache if data is received from the database by any
     * query in a {@link org.eclipse.persistence.sessions.remote.RemoteSession}.<P>
     *
     * However, if a query hits the cache, data is not refreshed regardless of how this setting is configured. For example, by
     * default, when a query for a single object based on its primary key is executed, OracleAS TopLink will first look in the
     * cache for the object. If the object is in the cache, the cached object is returned and data is not refreshed. To avoid
     * cache hits, use the {@link #disableCacheHitsOnRemote} method.<P>
     *
     * Also note that the {@link org.eclipse.persistence.sessions.UnitOfWork} will not refresh its registered objects.<P>
     *
     * Use this property with caution because it can lead to poor performance and may refresh on queries when it is not desired.
     * Normally, if you require fresh data, it is better to configure a query with {@link org.eclipse.persistence.queries.ObjectLevelReadQuery#refreshIdentityMapResult}.
     * To ensure that refreshes are only done when required, use this method in conjunction with {@link #onlyRefreshCacheIfNewerVersion}.
     *
     * @see #dontAlwaysRefreshCacheOnRemote
     */
    public void alwaysRefreshCacheOnRemote() {
        setShouldAlwaysRefreshCacheOnRemote(true);
    }

    /**
     * ADVANCED:
     * Call the descriptor amendment method.
     * This is called while loading or creating a descriptor that has an amendment method defined.
     */
    public void applyAmendmentMethod() {
        applyAmendmentMethod(null);
    }

    /**
     * INTERNAL:
     * Call the descriptor amendment method.
     * This is called while loading or creating a descriptor that has an amendment method defined.
     */
    public void applyAmendmentMethod(DescriptorEvent event) {
        if ((getAmendmentClass() == null) || (getAmendmentMethodName() == null)) {
            return;
        }

        Method method = null;
        Class<?>[] argTypes = new Class<?>[1];

        // BUG#2669585
        // Class argument type must be consistent, descriptor, i.e. instance may be a subclass.
        argTypes[0] = ClassDescriptor.class;
        try {
            method = Helper.getDeclaredMethod(getAmendmentClass(), getAmendmentMethodName(), argTypes);
        } catch (Exception ignore) {
            // Return type should now be ClassDescriptor.
            argTypes[0] = ClassDescriptor.class;
            try {
                method = Helper.getDeclaredMethod(getAmendmentClass(), getAmendmentMethodName(), argTypes);
            } catch (Exception exception) {
                throw DescriptorException.invalidAmendmentMethod(getAmendmentClass(), getAmendmentMethodName(), exception, this);
            }
        }

        Object[] args = new Object[1];
        args[0] = this;

        try {
            if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()) {
                AccessController.doPrivileged(new PrivilegedMethodInvoker(method, null, args));
            } else {
                PrivilegedAccessHelper.invokeMethod(method, null, args);
            }
        } catch (Exception exception) {
            throw DescriptorException.errorOccuredInAmendmentMethod(getAmendmentClass(), getAmendmentMethodName(), exception, this);
        }
    }

    /**
     * INTERNAL:
     * Used to determine if a foreign key references the primary key.
     */
    public boolean arePrimaryKeyFields(Vector fields) {
        if (!(fields.size() == (getPrimaryKeyFields().size()))) {
            return false;
        }

        for (Enumeration enumFields = fields.elements(); enumFields.hasMoreElements();) {
            DatabaseField field = (DatabaseField)enumFields.nextElement();

            if (!getPrimaryKeyFields().contains(field)) {
                return false;
            }
        }

        return true;
    }

    /**
     * INTERNAL:
     * Some attributes have default values defined in Project.
     * If such the value for the attribute hasn't been set then the default value is assigned.
     */
    protected void assignDefaultValues(AbstractSession session) {
        if (this.idValidation == null) {
            this.idValidation = session.getProject().getDefaultIdValidation();
        }
        getCachePolicy().assignDefaultValues(session);
    }

    /**
     * INTERNAL:
     * Return the selection criteria used to IN batch fetching.
     */
    public Expression buildBatchCriteriaByPK(ExpressionBuilder builder, ObjectLevelReadQuery query) {
        int size = getPrimaryKeyFields().size();
        if (size > 1) {
            // Support composite keys using nested IN.
            List<Expression> fields = new ArrayList<>(size);
            for (DatabaseField targetForeignKeyField : primaryKeyFields) {
                fields.add(builder.getField(targetForeignKeyField));
            }
            return query.getSession().getPlatform().buildBatchCriteriaForComplexId(builder, fields);
        } else {
            return query.getSession().getPlatform().buildBatchCriteria(builder, builder.getField(primaryKeyFields.get(0)));
        }

    }
    /**
     * INTERNAL:
     * Return a call built from a statement. Subclasses may throw an exception
     * if the statement is not appropriate.
     */
    public DatasourceCall buildCallFromStatement(SQLStatement statement, DatabaseQuery query, AbstractSession session) {
        DatabaseCall call = statement.buildCall(session);
        if (isNativeConnectionRequired()) {
            call.setIsNativeConnectionRequired(true);
        }
        return call;
    }

    /**
     * INTERNAL:
     * Extract the direct values from the specified field value.
     * Return them in a vector.
     */
    public Vector buildDirectValuesFromFieldValue(Object fieldValue) throws DatabaseException {
        throw DescriptorException.normalDescriptorsDoNotSupportNonRelationalExtensions(this);
    }

    /**
     * INTERNAL:
     * A DatabaseField is built from the given field name.
     */

    // * added 9/7/00 by Les Davis
    // * bug fix for null pointer in initialization of mappings in remote session
    public DatabaseField buildField(String fieldName) {
        DatabaseField field = new DatabaseField(fieldName);
        DatabaseTable table;

        if (field.hasTableName()) {
            table = getTable(field.getTableName());
        } else if (getDefaultTable() != null) {
            table = getDefaultTable();
        } else {
            table = getTable(getTableName());
        }

        field.setTable(table);
        return field;
    }

    /**
     * INTERNAL:
     * The table of the field is ensured to be unique from the descriptor's tables.
     * If the field has no table the default table is assigned.
     * This is used only in initialization.
     * Fields are ensured to be unique so if the field has already been built it is returned.
     */
    public DatabaseField buildField(DatabaseField field) {
        return buildField(field, null);
    }

    public DatabaseField buildField(DatabaseField field, DatabaseTable relationTable) {
        DatabaseField builtField = getObjectBuilder().getFieldsMap().get(field);
        if (builtField == null) {
            builtField = field;
            DatabaseTable table;
            if (relationTable != null && field.hasTableName() && field.getTableName().equals(relationTable.getName())){
                table = relationTable;
            } else if (relationTable != null && !field.hasTableName()) {
                table = relationTable;
            } else if (field.hasTableName()) {
                table = getTable(field.getTableName());
            } else {
                table = getDefaultTable();
            }
            builtField.setTable(table);
            getObjectBuilder().getFieldsMap().put(builtField, builtField);
        }
        return builtField;
    }

    /**
     * INTERNAL:
     * Build the appropriate field value for the specified
     * set of direct values.
     */
    public Object buildFieldValueFromDirectValues(Vector directValues, String elementDataTypeName, AbstractSession session) throws DatabaseException {
        throw DescriptorException.normalDescriptorsDoNotSupportNonRelationalExtensions(this);
    }

    /**
     * INTERNAL:
     * Build and return the appropriate field value for the specified
     * set of foreign keys (i.e. each row has the fields that
     * make up a foreign key).
     */
    public Object buildFieldValueFromForeignKeys(Vector foreignKeys, String referenceDataTypeName, AbstractSession session) throws DatabaseException {
        throw DescriptorException.normalDescriptorsDoNotSupportNonRelationalExtensions(this);
    }

    /**
     * INTERNAL:
     * Build and return the field value from the specified nested database row.
     */
    public Object buildFieldValueFromNestedRow(AbstractRecord nestedRow, AbstractSession session) throws DatabaseException {
        throw DescriptorException.normalDescriptorsDoNotSupportNonRelationalExtensions(this);
    }

    /**
     * INTERNAL:
     * Build and return the appropriate field value for the specified
     * set of nested rows.
     */
    public Object buildFieldValueFromNestedRows(Vector nestedRows, String structureName, AbstractSession session) throws DatabaseException {
        throw DescriptorException.normalDescriptorsDoNotSupportNonRelationalExtensions(this);
    }

    /**
     * INTERNAL:
     * Build and return the nested database row from the specified field value.
     */
    public AbstractRecord buildNestedRowFromFieldValue(Object fieldValue) throws DatabaseException {
        throw DescriptorException.normalDescriptorsDoNotSupportNonRelationalExtensions(this);
    }

    /**
     * INTERNAL:
     * Build and return the nested rows from the specified field value.
     */
    public Vector buildNestedRowsFromFieldValue(Object fieldValue, AbstractSession session) throws DatabaseException {
        throw DescriptorException.normalDescriptorsDoNotSupportNonRelationalExtensions(this);
    }

    /**
     *  To check that tables and fields are present in database
     */
    protected void checkDatabase(AbstractSession session) {
        if (session.getIntegrityChecker().shouldCheckDatabase()) {
            for (Iterator<DatabaseTable> iterator = getTables().iterator(); iterator.hasNext();) {
                DatabaseTable table = iterator.next();
                if (session.getIntegrityChecker().checkTable(table, session)) {
                    // To load the fields of database into a vector
                    List databaseFields = new ArrayList();
                    List<AbstractRecord> result = session.getAccessor().getColumnInfo(null, null, table.getName(), null, session);
                    // Table name may need to be lowercase.
                    if (result.isEmpty() && session.getPlatform().shouldForceFieldNamesToUpperCase()) {
                        result = session.getAccessor().getColumnInfo(null, null, table.getName().toLowerCase(), null, session);
                    }
                    for (Iterator<AbstractRecord> resultIterator = result.iterator(); resultIterator.hasNext();) {
                        AbstractRecord row = resultIterator.next();
                        if (session.getPlatform().shouldForceFieldNamesToUpperCase()) {
                            databaseFields.add(((String)row.get("COLUMN_NAME")).toUpperCase());
                        } else {
                            databaseFields.add(row.get("COLUMN_NAME"));
                        }
                    }

                    // To check that the fields of descriptor are present in the database.
                    for (DatabaseField field : getFields()) {
                        if (field.getTable().equals(table) && (!databaseFields.contains(field.getName()))) {
                            session.getIntegrityChecker().handleError(DescriptorException.fieldIsNotPresentInDatabase(this, table.getName(), field.getName()));
                        }
                    }
                } else {
                    session.getIntegrityChecker().handleError(DescriptorException.tableIsNotPresentInDatabase(this));
                }
            }
        }
    }

    /**
     * INTERNAL:
     * Verify that an aggregate descriptor's inheritance tree
     * is full of aggregate descriptors.
     */
    public void checkInheritanceTreeAggregateSettings(AbstractSession session, AggregateMapping mapping) throws DescriptorException {
        if (!this.hasInheritance()) {
            return;
        }

        if (this.isChildDescriptor()) {
            Class<?> parentClass = this.getInheritancePolicy().getParentClass();
            if (parentClass == this.getJavaClass()) {
                throw DescriptorException.parentClassIsSelf(this);
            }

            // recurse up the inheritance tree to the root descriptor
            session.getDescriptor(parentClass).checkInheritanceTreeAggregateSettings(session, mapping);
        } else {
            // we have a root descriptor, now verify it and all its children, grandchildren, etc.
            this.checkInheritanceTreeAggregateSettingsForChildren(session, mapping);
        }
    }

    /**
     * Verify that an aggregate descriptor's inheritance tree
     * is full of aggregate descriptors, cont.
     */
    private void checkInheritanceTreeAggregateSettingsForChildren(AbstractSession session, AggregateMapping mapping) throws DescriptorException {
        if (!this.isAggregateDescriptor()) {
            session.getIntegrityChecker().handleError(DescriptorException.referenceDescriptorIsNotAggregate(this.getJavaClass().getName(), mapping));
        }
        for (ClassDescriptor childDescriptor : this.getInheritancePolicy().getChildDescriptors()) {
            // recurse down the inheritance tree to its leaves
            childDescriptor.checkInheritanceTreeAggregateSettingsForChildren(session, mapping);
        }
    }

    /**
     * INTERNAL:
     * Create multiple table insert order.
     * If its a child descriptor then insert order starts
     * with the same insert order as in the parent.
     * Non-inherited tables ordered to adhere to
     * multipleTableForeignKeys:
     * the target table (the key in multipleTableForeignKeys map)
     * should stand in insert order before any of the source tables
     * (members of the corresponding value in multipleTableForeignKeys).
     */
    protected void createMultipleTableInsertOrder() {
        int nParentTables = 0;
        if (isChildDescriptor()) {
            nParentTables = getInheritancePolicy().getParentDescriptor().getTables().size();
            setMultipleTableInsertOrder(new ArrayList(getInheritancePolicy().getParentDescriptor().getMultipleTableInsertOrder()));

            if(nParentTables == getTables().size()) {
                // all the tables mapped by the parent - nothing to do.
                return;
            }
        }

        if(getMultipleTableForeignKeys().isEmpty()) {
            if(nParentTables == 0) {
                // no multipleTableForeignKeys specified - keep getTables() order.
                setMultipleTableInsertOrder((Vector)getTables().clone());
            } else {
                // insert order for parent-defined tables has been already copied from parent descriptor,
                // add the remaining tables keeping the same order as in getTables()
                for(int k = nParentTables; k < getTables().size(); k++) {
                    getMultipleTableInsertOrder().add(getTables().get(k));
                }
            }
            return;
        }

        verifyMultipleTablesForeignKeysTables();

        // tableComparison[i][j] indicates the order between i and j tables:
        // -1 i table before j table;
        // +1 i table after j table;
        //  0 - not defined (could be either before or after)
        int[][] tableComparison = createTableComparison(getTables(), nParentTables);

        // Now create insert order of the tables:
        // getTables.get(i) table should be
        //  before getTable.get(j) in insert order if tableComparison[i][j]==-1;
        //  after getTable.get(j) in insert order if tableComparison[i][j]== 1;
        //  doesn't matter if tableComparison[i][j]== 0.
        createMultipleTableInsertOrderFromComparison(tableComparison, nParentTables);
    }

    /**
     * INTERNAL:
     * Verify multiple table insert order provided by the user.
     * If its a child descriptor then insert order starts
     * with the same insert order as in the parent.
     * Non-inherited tables ordered to adhere to
     * multipleTableForeignKeys:
     * the target table (the key in multipleTableForeignKeys map)
     * should stand in insert order before any of the source tables
     * (members of the corresponding value in multipleTableForeignKeys).
     */
    protected void verifyMultipleTableInsertOrder() {
        int nParentTables = 0;
        if (isChildDescriptor()) {
            nParentTables = getInheritancePolicy().getParentDescriptor().getTables().size();

            if(nParentTables + getMultipleTableInsertOrder().size() == getTables().size()) {
                // the user specified insert order only for the tables directly mapped by the descriptor,
                // the inherited tables order must be the same as in parent descriptor
                List<DatabaseTable> childMultipleTableInsertOrder = getMultipleTableInsertOrder();
                setMultipleTableInsertOrder(new ArrayList(getInheritancePolicy().getParentDescriptor().getMultipleTableInsertOrder()));
                getMultipleTableInsertOrder().addAll(childMultipleTableInsertOrder);
            }

        }

        if (getMultipleTableInsertOrder().size() != getTables().size()) {
            throw DescriptorException.multipleTableInsertOrderMismatch(this);
        }

        if(nParentTables == getTables().size()) {
            // all the tables mapped by the parent - nothing to do.
            return;
        }

        if(getMultipleTableForeignKeys().isEmpty()) {
            // nothing to do
            return;
        }

        verifyMultipleTablesForeignKeysTables();

        // tableComparison[i][j] indicates the order between i and j tables:
        // -1 i table before j table;
        // +1 i table after j table;
        //  0 - not defined (could be either before or after)
        int[][] tableComparison = createTableComparison(getMultipleTableInsertOrder(), nParentTables);

        for(int i = nParentTables; i < getMultipleTableInsertOrder().size(); i++) {
            for(int j = i + 1; j < getTables().size(); j++) {
                if(tableComparison[i - nParentTables][j - nParentTables] > 0) {
                    throw DescriptorException.insertOrderConflictsWithMultipleTableForeignKeys(this, getMultipleTableInsertOrder().get(i), getMultipleTableInsertOrder().get(j));
                }
            }
        }
    }

    /**
     * INTERNAL:
     * Verify that the tables specified in multipleTablesForeignKeysTables are valid.
     */
    protected void verifyMultipleTablesForeignKeysTables() {
        Iterator<Map.Entry<DatabaseTable, Set<DatabaseTable>>> itTargetTables = getMultipleTableForeignKeys().entrySet().iterator();
        while(itTargetTables.hasNext()) {
            Map.Entry<DatabaseTable, Set<DatabaseTable>> entry = itTargetTables.next();
            DatabaseTable targetTable = entry.getKey();
            if (getTables().indexOf(targetTable) == -1) {
                throw DescriptorException.illegalTableNameInMultipleTableForeignKeyField(this, targetTable);
            }
            Iterator<DatabaseTable> itSourceTables = entry.getValue().iterator();
            while(itSourceTables.hasNext()) {
                DatabaseTable sourceTable = itSourceTables.next();
                if (getTables().indexOf(sourceTable) == -1) {
                    throw DescriptorException.illegalTableNameInMultipleTableForeignKeyField(this, targetTable);
                }
            }
        }
    }

    /**
     * INTERNAL:
     * This helper method creates a matrix that contains insertion order comparison for the tables.
     * Comparison is done for indexes from nStart to tables.size()-1.
     */
    protected int[][] createTableComparison(List<DatabaseTable> tables, int nStart) {
        int nTables = tables.size();
        // tableComparison[i][j] indicates the order between i and j tables:
        // -1 i table before j table;
        // +1 i table after j table;
        //  0 - not defined (could be either before or after)
        int[][] tableComparison = new int[nTables - nStart][nTables - nStart];

        Iterator<Map.Entry<DatabaseTable, Set<DatabaseTable>>> itTargetTables = getMultipleTableForeignKeys().entrySet().iterator();
        // loop through all pairs of target and source tables and insert either +1 or -1 into tableComparison for each pair.
        while(itTargetTables.hasNext()) {
            Map.Entry<DatabaseTable, Set<DatabaseTable>> entry = itTargetTables.next();
            DatabaseTable targetTable = entry.getKey();
            int targetIndex = tables.indexOf(targetTable) - nStart;
            if(targetIndex >= 0) {
                Set<DatabaseTable> sourceTables = entry.getValue();
                Iterator<DatabaseTable> itSourceTables = sourceTables.iterator();
                while(itSourceTables.hasNext()) {
                    DatabaseTable sourceTable = itSourceTables.next();
                    int sourceIndex = tables.indexOf(sourceTable) - nStart;
                    if(sourceIndex >= 0) {
                        // targetTable should be before sourceTable: tableComparison[sourceIndex, targetIndex] = 1; tableComparison[targetIndex, sourceIndex] =-1.
                        if(tableComparison[targetIndex][sourceIndex] == 1) {
                            throw DescriptorException.insertOrderCyclicalDependencyBetweenTwoTables(this, sourceTable, targetTable);
                        } else {
                            tableComparison[targetIndex][sourceIndex] =-1;
                            tableComparison[sourceIndex][targetIndex] = 1;
                        }
                    } else {
                        throw DescriptorException.insertOrderChildBeforeParent(this, sourceTable, targetTable);
                    }
                }
            }
        }
        return tableComparison;
    }

    /**
     * INTERNAL:
     * This helper method creates multipleTableInsertOrderFromComparison using comparison matrix
     * created by createTableComparison(getTables()) method call.
     */
    protected void createMultipleTableInsertOrderFromComparison(int[][] tableComparison, int nStart) {
        int nTables = getTables().size();
        int[] tableOrder = new int[nTables - nStart];
        boolean bOk = createTableOrder(0, nTables - nStart, tableOrder, tableComparison);
        if(bOk) {
            if(nStart == 0) {
                setMultipleTableInsertOrder(NonSynchronizedVector.newInstance(nTables));
            }
            for(int k=0; k < nTables - nStart; k++) {
                getMultipleTableInsertOrder().add(getTables().get(tableOrder[k] + nStart));
            }
        } else {
            throw DescriptorException.insertOrderCyclicalDependencyBetweenThreeOrMoreTables(this);
        }
    }

    /**
     * INTERNAL:
     * This helper method recursively puts indexes from 0 to nTables-1 into tableOrder according to tableComparison 2 dim array.
     * k is index in tableOrder that currently the method is working on - the method should be called with k = 0.
     */
    protected boolean createTableOrder(int k, int nTables, int[] tableOrder, int[][] tableComparison) {
        if(k == nTables) {
            return true;
        }

        // array of indexes not yet ordered
        int[] iAvailable = new int[nTables-k];
        int l = 0;
        for(int i=0; i < nTables; i++) {
            boolean isUsed = false;
            for(int j=0; j<k && !isUsed; j++) {
                if(i == tableOrder[j]) {
                    isUsed = true;
                }
            }
            if(!isUsed) {
                iAvailable[l] = i;
                l++;
            }
        }

        boolean bOk = false;
        for(int i=0; (i < nTables-k)  && !bOk; i++) {
            boolean isSmallest = true;
            for(int j=0; (j < nTables-k) && isSmallest; j++) {
                if(i != j) {
                    if(tableComparison[iAvailable[i]][iAvailable[j]] > 0) {
                        isSmallest = false;
                    }
                }
            }
            if(isSmallest) {
                // iAvailable[i] is less or equal according to tableComparison to all other remaining indexes - let's try to use it as tableOrder[k]
                tableOrder[k] = iAvailable[i];
                // now try to fill out the last remaining n - k - 1 elements of tableOrder
                bOk = createTableOrder(k + 1, nTables, tableOrder, tableComparison);
            }
        }
        return bOk;
    }

    /**
     * INTERNAL:
     * Clones the descriptor
     */
    @Override
    public Object clone() {
        ClassDescriptor clonedDescriptor = null;

        // clones itself
        try {
            clonedDescriptor = (ClassDescriptor)super.clone();
        } catch (Exception exception) {
            throw new AssertionError(exception);
        }

        Vector mappingsVector = NonSynchronizedVector.newInstance();

        // All the mappings
        for (Enumeration<DatabaseMapping> mappingsEnum = getMappings().elements(); mappingsEnum.hasMoreElements();) {
            DatabaseMapping mapping;

            mapping = (DatabaseMapping) mappingsEnum.nextElement().clone();
            mapping.setDescriptor(clonedDescriptor);
            mappingsVector.addElement(mapping);
        }
        clonedDescriptor.setMappings(mappingsVector);

        Map queryKeys = new HashMap(getQueryKeys().size() + 2);

        // All the query keys
        for (QueryKey queryKey : getQueryKeys().values()) {
            queryKey = (QueryKey)queryKey.clone();
            queryKey.setDescriptor(clonedDescriptor);
            queryKeys.put(queryKey.getName(), queryKey);
        }
        clonedDescriptor.setQueryKeys(queryKeys);

        // PrimaryKeyFields
        List primaryKeyVector = new ArrayList(getPrimaryKeyFields().size());
        List<DatabaseField> primaryKeyFields = getPrimaryKeyFields();
        for (int index = 0; index < primaryKeyFields.size(); index++) {
            DatabaseField primaryKey = primaryKeyFields.get(index).clone();
            primaryKeyVector.add(primaryKey);
        }
        clonedDescriptor.setPrimaryKeyFields(primaryKeyVector);

        // fields.
        clonedDescriptor.setFields(NonSynchronizedVector.newInstance());

        // Referencing classes
        clonedDescriptor.referencingClasses = new HashSet<>(referencingClasses);

        // Post-calculate changes
        if (this.mappingsPostCalculateChanges != null) {
            clonedDescriptor.mappingsPostCalculateChanges = new ArrayList<>();
            for (DatabaseMapping databaseMapping : this.mappingsPostCalculateChanges) {
                clonedDescriptor.mappingsPostCalculateChanges.add((DatabaseMapping)databaseMapping.clone());
            }
        }

        // Post-calculate on delete
        if (this.mappingsPostCalculateChangesOnDeleted != null) {
            clonedDescriptor.mappingsPostCalculateChangesOnDeleted = new ArrayList<>();
            for (DatabaseMapping databaseMapping : this.mappingsPostCalculateChangesOnDeleted) {
                clonedDescriptor.mappingsPostCalculateChangesOnDeleted.add((DatabaseMapping)databaseMapping.clone());
            }
        }

        // The inheritance policy
        if (clonedDescriptor.hasInheritance()) {
            clonedDescriptor.setInheritancePolicy((InheritancePolicy)getInheritancePolicy().clone());
            clonedDescriptor.getInheritancePolicy().setDescriptor(clonedDescriptor);
        }

        if (clonedDescriptor.hasSerializedObjectPolicy()) {
            clonedDescriptor.setSerializedObjectPolicy(getSerializedObjectPolicy().clone());
        }

        // The returning policy
        if (clonedDescriptor.hasReturningPolicy()) {
            clonedDescriptor.setReturningPolicy((ReturningPolicy)getReturningPolicy().clone());
            clonedDescriptor.getReturningPolicy().setDescriptor(clonedDescriptor);
        }
        if (clonedDescriptor.hasReturningPolicies()) {
            clonedDescriptor.returningPolicies = new ArrayList<>();
            for (ReturningPolicy returningPolicy : this.returningPolicies) {
                clonedDescriptor.returningPolicies.add((ReturningPolicy)returningPolicy.clone());
            }
            clonedDescriptor.prepareReturnFields(clonedDescriptor.returningPolicies);
        }

        // The Object builder
        clonedDescriptor.setObjectBuilder((ObjectBuilder)getObjectBuilder().clone());
        clonedDescriptor.getObjectBuilder().setDescriptor(clonedDescriptor);

        clonedDescriptor.setEventManager((DescriptorEventManager)getEventManager().clone());
        clonedDescriptor.getEventManager().setDescriptor(clonedDescriptor);

        // The Query manager
        clonedDescriptor.setQueryManager((DescriptorQueryManager)getQueryManager().clone());
        clonedDescriptor.getQueryManager().setDescriptor(clonedDescriptor);

        //fetch group
        if (hasFetchGroupManager()) {
            clonedDescriptor.setFetchGroupManager((FetchGroupManager)getFetchGroupManager().clone());
        }

        if (this.cachePolicy != null) {
            clonedDescriptor.setCachePolicy(this.cachePolicy.clone());
        }

        // Bug 3037701 - clone several more elements
        if (this.instantiationPolicy != null) {
            clonedDescriptor.setInstantiationPolicy((InstantiationPolicy)getInstantiationPolicy().clone());
        }
        if (this.copyPolicy != null) {
            clonedDescriptor.setCopyPolicy((CopyPolicy)getCopyPolicy().clone());
        }
        if (getOptimisticLockingPolicy() != null) {
            clonedDescriptor.setOptimisticLockingPolicy((OptimisticLockingPolicy)getOptimisticLockingPolicy().clone());
        }
        //bug 5171059 clone change tracking policies as well
        clonedDescriptor.setObjectChangePolicy(this.getObjectChangePolicyInternal());

        // Clone the tables
        Vector<DatabaseTable> tables = NonSynchronizedVector.newInstance(3);
        for (DatabaseTable table : getTables()) {
            tables.add(table.clone());
        }
        clonedDescriptor.setTables(tables);

        // Clone the default table
        if (getDefaultTable() != null) {
            clonedDescriptor.setDefaultTable(getDefaultTable().clone());
        }

        // Clone the CMPPolicy
        if (getCMPPolicy() != null) {
            clonedDescriptor.setCMPPolicy(getCMPPolicy().clone());
            clonedDescriptor.getCMPPolicy().setDescriptor(clonedDescriptor);
        }

        // Clone the sequence number field.
        if (getSequenceNumberField() != null) {
            clonedDescriptor.setSequenceNumberField(getSequenceNumberField().clone());
        }

        // Clone the multitenant policy.
        if (hasMultitenantPolicy()) {
            clonedDescriptor.setMultitenantPolicy(getMultitenantPolicy().clone(clonedDescriptor));
        }

        return clonedDescriptor;
    }

    /**
     * INTERNAL:
     * Convert all the class-name-based settings in this Descriptor to actual class-based
     * settings. This method is used when converting a project that has been built
     * with class names to a project with classes.
     */
    public void convertClassNamesToClasses(ClassLoader classLoader){
        Class<?> redirectorClass = null;

        if (getJavaClassName() != null){
            Class<?> descriptorClass = null;
            try{
                if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
                    try {
                        descriptorClass = AccessController.doPrivileged(new PrivilegedClassForName<>(getJavaClassName(), true, classLoader));
                    } catch (PrivilegedActionException exception) {
                        throw ValidationException.classNotFoundWhileConvertingClassNames(getJavaClassName(), exception.getException());
                    }
                } else {
                    descriptorClass = org.eclipse.persistence.internal.security.PrivilegedAccessHelper.getClassForName(getJavaClassName(), true, classLoader);
                }
            } catch (ClassNotFoundException exc){
                throw ValidationException.classNotFoundWhileConvertingClassNames(getJavaClassName(), exc);
            }
            setJavaClass(descriptorClass);
        }

        if (getAmendmentClassName() != null) {
            Class<?> amendmentClass = null;
            try{
                if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
                    try {
                        amendmentClass = AccessController.doPrivileged(new PrivilegedClassForName<>(getAmendmentClassName(), true, classLoader));
                    } catch (PrivilegedActionException exception) {
                        throw ValidationException.classNotFoundWhileConvertingClassNames(getAmendmentClassName(), exception.getException());
                    }
                } else {
                    amendmentClass = org.eclipse.persistence.internal.security.PrivilegedAccessHelper.getClassForName(getAmendmentClassName(), true, classLoader);
                }
            } catch (ClassNotFoundException exc){
                throw ValidationException.classNotFoundWhileConvertingClassNames(getAmendmentClassName(), exc);
            }
            setAmendmentClass(amendmentClass);
        }

        if (copyPolicy == null && getCopyPolicyClassName() != null){
            Class<?> copyPolicyClass = null;
            CopyPolicy newCopyPolicy = null;
            try{
                if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
                    try {
                        copyPolicyClass = AccessController.doPrivileged(new PrivilegedClassForName<>(getCopyPolicyClassName(), true, classLoader));
                    } catch (PrivilegedActionException exception) {
                        throw ValidationException.classNotFoundWhileConvertingClassNames(getCopyPolicyClassName(), exception.getException());
                    }
                    try {
                        newCopyPolicy = (CopyPolicy)AccessController.doPrivileged(new PrivilegedNewInstanceFromClass<>(copyPolicyClass));
                    } catch (PrivilegedActionException exception) {
                        throw ValidationException.reflectiveExceptionWhileCreatingClassInstance(getCopyPolicyClassName(), exception.getException());
                    }
                } else {
                    copyPolicyClass = org.eclipse.persistence.internal.security.PrivilegedAccessHelper.getClassForName(getCopyPolicyClassName(), true, classLoader);
                    newCopyPolicy = (CopyPolicy)org.eclipse.persistence.internal.security.PrivilegedAccessHelper.newInstanceFromClass(copyPolicyClass);
                }
            } catch (ClassNotFoundException exc) {
                throw ValidationException.classNotFoundWhileConvertingClassNames(getCopyPolicyClassName(), exc);
            } catch (ReflectiveOperationException ex){
                throw ValidationException.reflectiveExceptionWhileCreatingClassInstance(getCopyPolicyClassName(), ex);
            }
            setCopyPolicy(newCopyPolicy);
        }

        if (this.serializedObjectPolicy != null && this.serializedObjectPolicy instanceof SerializedObjectPolicyWrapper) {
            String serializedObjectPolicyClassName = ((SerializedObjectPolicyWrapper)this.serializedObjectPolicy).getSerializedObjectPolicyClassName();
            Class<?> serializedObjectPolicyClass = null;
            SerializedObjectPolicy newSerializedObjectPolicy = null;
            try{
                if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
                    try {
                        serializedObjectPolicyClass = AccessController.doPrivileged(new PrivilegedClassForName<>(serializedObjectPolicyClassName, true, classLoader));
                    } catch (PrivilegedActionException exception) {
                        throw ValidationException.classNotFoundWhileConvertingClassNames(serializedObjectPolicyClassName, exception.getException());
                    }
                    try {
                        newSerializedObjectPolicy = (SerializedObjectPolicy)AccessController.doPrivileged(new PrivilegedNewInstanceFromClass<>(serializedObjectPolicyClass));
                    } catch (PrivilegedActionException exception) {
                        throw ValidationException.reflectiveExceptionWhileCreatingClassInstance(serializedObjectPolicyClassName, exception.getException());
                    }
                } else {
                    serializedObjectPolicyClass = org.eclipse.persistence.internal.security.PrivilegedAccessHelper.getClassForName(serializedObjectPolicyClassName, true, classLoader);
                    newSerializedObjectPolicy = (SerializedObjectPolicy)org.eclipse.persistence.internal.security.PrivilegedAccessHelper.newInstanceFromClass(serializedObjectPolicyClass);
                }
            } catch (ClassNotFoundException exc) {
                throw ValidationException.classNotFoundWhileConvertingClassNames(serializedObjectPolicyClassName, exc);
            } catch (IllegalAccessException ex){
                throw ValidationException.reflectiveExceptionWhileCreatingClassInstance(serializedObjectPolicyClassName, ex);
            } catch (InstantiationException e){
                throw ValidationException.reflectiveExceptionWhileCreatingClassInstance(serializedObjectPolicyClassName, e);
            }
            newSerializedObjectPolicy.setField(this.serializedObjectPolicy.getField());
            setSerializedObjectPolicy(newSerializedObjectPolicy);
        }

        //Create and set default QueryRedirector instances
        if (this.defaultQueryRedirectorClassName != null){
            try{
                if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
                    try {
                        redirectorClass = AccessController.doPrivileged(new PrivilegedClassForName<>(defaultQueryRedirectorClassName, true, classLoader));
                    } catch (PrivilegedActionException exception) {
                        throw ValidationException.classNotFoundWhileConvertingClassNames(defaultQueryRedirectorClassName, exception.getException());
                    }
                    try {
                        setDefaultQueryRedirector((QueryRedirector) AccessController.doPrivileged(new PrivilegedNewInstanceFromClass<>(redirectorClass)));
                    } catch (PrivilegedActionException exception) {
                        throw ValidationException.classNotFoundWhileConvertingClassNames(defaultQueryRedirectorClassName, exception.getException());
                    }
                } else {
                    redirectorClass = org.eclipse.persistence.internal.security.PrivilegedAccessHelper.getClassForName(defaultQueryRedirectorClassName, true, classLoader);
                    setDefaultQueryRedirector((QueryRedirector) org.eclipse.persistence.internal.security.PrivilegedAccessHelper.newInstanceFromClass(redirectorClass));
                }
            } catch (ClassNotFoundException exc) {
                throw ValidationException.classNotFoundWhileConvertingClassNames(defaultQueryRedirectorClassName, exc);
            } catch (Exception e) {
                // Catches IllegalAccessException and InstantiationException
                throw ValidationException.classNotFoundWhileConvertingClassNames(defaultQueryRedirectorClassName, e);
            }
        }

        if (this.defaultReadObjectQueryRedirectorClassName != null){
            try{
                if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
                    try {
                        redirectorClass = AccessController.doPrivileged(new PrivilegedClassForName<>(defaultReadObjectQueryRedirectorClassName, true, classLoader));
                    } catch (PrivilegedActionException exception) {
                        throw ValidationException.classNotFoundWhileConvertingClassNames(defaultReadObjectQueryRedirectorClassName, exception.getException());
                    }
                    try {
                        setDefaultReadObjectQueryRedirector((QueryRedirector) AccessController.doPrivileged(new PrivilegedNewInstanceFromClass<>(redirectorClass)));
                    } catch (PrivilegedActionException exception) {
                        throw ValidationException.classNotFoundWhileConvertingClassNames(defaultReadObjectQueryRedirectorClassName, exception.getException());
                    }
                } else {
                    redirectorClass = org.eclipse.persistence.internal.security.PrivilegedAccessHelper.getClassForName(defaultReadObjectQueryRedirectorClassName, true, classLoader);
                    setDefaultReadObjectQueryRedirector((QueryRedirector) org.eclipse.persistence.internal.security.PrivilegedAccessHelper.newInstanceFromClass(redirectorClass));
                }
            } catch (ClassNotFoundException exc) {
                throw ValidationException.classNotFoundWhileConvertingClassNames(defaultReadObjectQueryRedirectorClassName, exc);
            } catch (Exception e) {
                // Catches IllegalAccessException and InstantiationException
                throw ValidationException.classNotFoundWhileConvertingClassNames(defaultReadObjectQueryRedirectorClassName, e);
            }
        }
        if (this.defaultReadAllQueryRedirectorClassName != null){
            try{
                if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
                    try {
                        redirectorClass = AccessController.doPrivileged(new PrivilegedClassForName<>(defaultReadAllQueryRedirectorClassName, true, classLoader));
                    } catch (PrivilegedActionException exception) {
                        throw ValidationException.classNotFoundWhileConvertingClassNames(defaultReadAllQueryRedirectorClassName, exception.getException());
                    }
                    try {
                        setDefaultReadAllQueryRedirector((QueryRedirector) AccessController.doPrivileged(new PrivilegedNewInstanceFromClass<>(redirectorClass)));
                    } catch (PrivilegedActionException exception) {
                        throw ValidationException.classNotFoundWhileConvertingClassNames(defaultReadAllQueryRedirectorClassName, exception.getException());
                    }
                } else {
                    redirectorClass = org.eclipse.persistence.internal.security.PrivilegedAccessHelper.getClassForName(defaultReadAllQueryRedirectorClassName, true, classLoader);
                    setDefaultReadAllQueryRedirector((QueryRedirector) org.eclipse.persistence.internal.security.PrivilegedAccessHelper.newInstanceFromClass(redirectorClass));
                }
            } catch (ClassNotFoundException exc) {
                throw ValidationException.classNotFoundWhileConvertingClassNames(defaultReadAllQueryRedirectorClassName, exc);
            } catch (Exception e) {
                // Catches IllegalAccessException and InstantiationException
                throw ValidationException.classNotFoundWhileConvertingClassNames(defaultReadAllQueryRedirectorClassName, e);
            }
        }
        if (this.defaultReportQueryRedirectorClassName != null){
            try{
                if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
                    try {
                        redirectorClass = AccessController.doPrivileged(new PrivilegedClassForName<>(defaultReportQueryRedirectorClassName, true, classLoader));
                    } catch (PrivilegedActionException exception) {
                        throw ValidationException.classNotFoundWhileConvertingClassNames(defaultReportQueryRedirectorClassName, exception.getException());
                    }
                    try {
                        setDefaultReportQueryRedirector((QueryRedirector) AccessController.doPrivileged(new PrivilegedNewInstanceFromClass<>(redirectorClass)));
                    } catch (PrivilegedActionException exception) {
                        throw ValidationException.classNotFoundWhileConvertingClassNames(defaultReportQueryRedirectorClassName, exception.getException());
                    }
                } else {
                    redirectorClass = org.eclipse.persistence.internal.security.PrivilegedAccessHelper.getClassForName(defaultReportQueryRedirectorClassName, true, classLoader);
                    setDefaultReportQueryRedirector((QueryRedirector) org.eclipse.persistence.internal.security.PrivilegedAccessHelper.newInstanceFromClass(redirectorClass));
                }
            } catch (ClassNotFoundException exc) {
                throw ValidationException.classNotFoundWhileConvertingClassNames(defaultReportQueryRedirectorClassName, exc);
            } catch (Exception e) {
                // Catches IllegalAccessException and InstantiationException
                throw ValidationException.classNotFoundWhileConvertingClassNames(defaultReportQueryRedirectorClassName, e);
            }
        }
        if (this.defaultInsertObjectQueryRedirectorClassName != null){
            try{
                if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
                    try {
                        redirectorClass = AccessController.doPrivileged(new PrivilegedClassForName<>(defaultInsertObjectQueryRedirectorClassName, true, classLoader));
                    } catch (PrivilegedActionException exception) {
                        throw ValidationException.classNotFoundWhileConvertingClassNames(defaultInsertObjectQueryRedirectorClassName, exception.getException());
                    }
                    try {
                        setDefaultInsertObjectQueryRedirector((QueryRedirector) AccessController.doPrivileged(new PrivilegedNewInstanceFromClass<>(redirectorClass)));
                    } catch (PrivilegedActionException exception) {
                        throw ValidationException.classNotFoundWhileConvertingClassNames(defaultInsertObjectQueryRedirectorClassName, exception.getException());
                    }
                } else {
                    redirectorClass = org.eclipse.persistence.internal.security.PrivilegedAccessHelper.getClassForName(defaultInsertObjectQueryRedirectorClassName, true, classLoader);
                    setDefaultInsertObjectQueryRedirector((QueryRedirector) org.eclipse.persistence.internal.security.PrivilegedAccessHelper.newInstanceFromClass(redirectorClass));
                }
            } catch (ClassNotFoundException exc) {
                throw ValidationException.classNotFoundWhileConvertingClassNames(defaultInsertObjectQueryRedirectorClassName, exc);
            } catch (Exception e) {
                // Catches IllegalAccessException and InstantiationException
                throw ValidationException.classNotFoundWhileConvertingClassNames(defaultInsertObjectQueryRedirectorClassName, e);
            }
        }
        if (this.defaultUpdateObjectQueryRedirectorClassName != null){
            try{
                if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
                    try {
                        redirectorClass = AccessController.doPrivileged(new PrivilegedClassForName<>(defaultUpdateObjectQueryRedirectorClassName, true, classLoader));
                    } catch (PrivilegedActionException exception) {
                        throw ValidationException.classNotFoundWhileConvertingClassNames(defaultUpdateObjectQueryRedirectorClassName, exception.getException());
                    }
                    try {
                        setDefaultUpdateObjectQueryRedirector((QueryRedirector) AccessController.doPrivileged(new PrivilegedNewInstanceFromClass<>(redirectorClass)));
                    } catch (PrivilegedActionException exception) {
                        throw ValidationException.classNotFoundWhileConvertingClassNames(defaultUpdateObjectQueryRedirectorClassName, exception.getException());
                    }
                } else {
                    redirectorClass = org.eclipse.persistence.internal.security.PrivilegedAccessHelper.getClassForName(defaultUpdateObjectQueryRedirectorClassName, true, classLoader);
                    setDefaultUpdateObjectQueryRedirector((QueryRedirector) org.eclipse.persistence.internal.security.PrivilegedAccessHelper.newInstanceFromClass(redirectorClass));
                }
            } catch (ClassNotFoundException exc) {
                throw ValidationException.classNotFoundWhileConvertingClassNames(defaultUpdateObjectQueryRedirectorClassName, exc);
            } catch (Exception e) {
                // Catches IllegalAccessException and InstantiationException
                throw ValidationException.classNotFoundWhileConvertingClassNames(defaultUpdateObjectQueryRedirectorClassName, e);
            }
        }
        if (this.defaultDeleteObjectQueryRedirectorClassName != null){
            try{
                if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
                    try {
                        redirectorClass = AccessController.doPrivileged(new PrivilegedClassForName<>(defaultDeleteObjectQueryRedirectorClassName, true, classLoader));
                    } catch (PrivilegedActionException exception) {
                        throw ValidationException.classNotFoundWhileConvertingClassNames(defaultDeleteObjectQueryRedirectorClassName, exception.getException());
                    }
                    try {
                        setDefaultDeleteObjectQueryRedirector((QueryRedirector) AccessController.doPrivileged(new PrivilegedNewInstanceFromClass<>(redirectorClass)));
                    } catch (PrivilegedActionException exception) {
                        throw ValidationException.classNotFoundWhileConvertingClassNames(defaultDeleteObjectQueryRedirectorClassName, exception.getException());
                    }
                } else {
                    redirectorClass = org.eclipse.persistence.internal.security.PrivilegedAccessHelper.getClassForName(defaultDeleteObjectQueryRedirectorClassName, true, classLoader);
                    setDefaultDeleteObjectQueryRedirector((QueryRedirector) org.eclipse.persistence.internal.security.PrivilegedAccessHelper.newInstanceFromClass(redirectorClass));
                }
            } catch (ClassNotFoundException exc) {
                throw ValidationException.classNotFoundWhileConvertingClassNames(defaultDeleteObjectQueryRedirectorClassName, exc);
            } catch (Exception e) {
                // Catches IllegalAccessException and InstantiationException
                throw ValidationException.classNotFoundWhileConvertingClassNames(defaultDeleteObjectQueryRedirectorClassName, e);
            }
        }
        Iterator<DatabaseMapping> mappings = getMappings().iterator();
        while (mappings.hasNext()){
            mappings.next().convertClassNamesToClasses(classLoader);
        }
        if (this.inheritancePolicy != null){
            this.inheritancePolicy.convertClassNamesToClasses(classLoader);
        }
        if (this.interfacePolicy != null){
            this.interfacePolicy.convertClassNamesToClasses(classLoader);
        }
        if (this.instantiationPolicy != null){
            this.instantiationPolicy.convertClassNamesToClasses(classLoader);
        }
        if (hasCMPPolicy()) {
            getCMPPolicy().convertClassNamesToClasses(classLoader);
        }
        if(this.queryManager != null) {
            this.queryManager.convertClassNamesToClasses(classLoader);
        }
        if(this.cachePolicy != null) {
            this.cachePolicy.convertClassNamesToClasses(classLoader);
        }

        if (hasUnconvertedProperties()) {
            for (String propertyName : getUnconvertedProperties().keySet()) {
                List<String> valuePair = getUnconvertedProperties().get(propertyName);
                String value = valuePair.get(0);
                String valueTypeName = valuePair.get(1);
                Class<String> valueType = String.class;

                if (valueTypeName != null) {
                    // Have to initialize the valueType now
                    try {
                        if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()) {
                            try {
                                valueType = AccessController.doPrivileged(new PrivilegedClassForName<>(valueTypeName, true, classLoader));
                            } catch (PrivilegedActionException exception) {
                                throw ValidationException.classNotFoundWhileConvertingClassNames(valueTypeName, exception.getException());
                            }
                        } else {
                            valueType = org.eclipse.persistence.internal.security.PrivilegedAccessHelper.getClassForName(valueTypeName, true, classLoader);
                        }
                    } catch (ClassNotFoundException exc){
                        throw ValidationException.classNotFoundWhileConvertingClassNames(valueTypeName, exc);
                    }
                }

                // Add the converted property. If the value type is the same
                // as the source (value) type, no conversion is made.
                getProperties().put(propertyName, ConversionManager.getDefaultManager().convertObject(value, valueType));
            }
        }
    }

    /**
     * PUBLIC:
     * Create a copy policy of the type passed in as a string.
     */
    public void createCopyPolicy(String policyType) {
        if (policyType.equals("clone")) {
            useCloneCopyPolicy();
            return;
        }
        if (policyType.equals("constructor")) {
            useInstantiationCopyPolicy();
            return;
        }
    }

    /**
     * PUBLIC:
     * Create a instantiation policy of the type passed in as a string.
     */
    public void createInstantiationPolicy(String policyType) {
        if (policyType.equals("static method")) {
            //do nothing for now
            return;
        }
        if (policyType.equals("constructor")) {
            useDefaultConstructorInstantiationPolicy();
            return;
        }
        if (policyType.equals("factory")) {
            //do nothing for now
            return;
        }
    }

    /**
     * PUBLIC:
     * Sets the descriptor to be an aggregate.
     * An aggregate descriptor is contained within another descriptor's table.
     * Aggregate descriptors are insert/updated/deleted with their owner and cannot exist without their owner as they share the same row.
     * Aggregates are not cached (they are cached as part of their owner) and cannot be read/written/deleted/registered.
     * All aggregate descriptors must call this.
     */
    public void descriptorIsAggregate() {
        setDescriptorType(AGGREGATE);
    }

    /**
     * PUBLIC:
     * Sets the descriptor to be part of an aggregate collection.
     * An aggregate collection descriptor stored in a separate table but some of the fields (the primary key) comes from its owner.
     * Aggregate collection descriptors are insert/updated/deleted with their owner and cannot exist without their owner as they share the primary key.
     * Aggregate collections are not cached (they are cached as part of their owner) and cannot be read/written/deleted/registered.
     * All aggregate collection descriptors must call this.
     */
    public void descriptorIsAggregateCollection() {
        setDescriptorType(AGGREGATE_COLLECTION);
    }

    /**
     * PUBLIC:
     * Sets the descriptor to be for an interface.
     * An interface descriptor allows for other classes to reference an interface or one of several other classes.
     * The implementor classes can be completely unrelated in term of the database stored in distinct tables.
     * Queries can also be done for the interface which will query each of the implementor classes.
     * An interface descriptor cannot define any mappings as an interface is just API and not state,
     * a interface descriptor should define the common query key of its implementors to allow querying.
     * An interface descriptor also does not define a primary key or table or other settings.
     * If an interface only has a single implementor (i.e. a classes public interface or remote) then an interface
     * descriptor should not be defined for it and relationships should be to the implementor class not the interface,
     * in this case the implementor class can add the interface through its interface policy to map queries on the interface to it.
     */
    public void descriptorIsForInterface() {
        setDescriptorType(INTERFACE);
    }

    /**
     * PUBLIC:
     * Sets the descriptor to be normal.
     * This is the default and means the descriptor is not aggregate or for an interface.
     */
    public void descriptorIsNormal() {
        setDescriptorType(NORMAL);
    }

    /**
     * PUBLIC:
     * Allow for cache hits on primary key read object queries to be disabled.
     * This can be used with {@link #alwaysRefreshCache} or {@link #alwaysRefreshCacheOnRemote} to ensure queries always go to the database.
     */
    public void disableCacheHits() {
        setShouldDisableCacheHits(true);
    }

    /**
     * PUBLIC:
     * Allow for remote session cache hits on primary key read object queries to be disabled.
     * This can be used with alwaysRefreshCacheOnRemote() to ensure queries always go to the server session cache.
     *
     * @see #alwaysRefreshCacheOnRemote()
     */
    public void disableCacheHitsOnRemote() {
        setShouldDisableCacheHitsOnRemote(true);
    }

    /**
     * PUBLIC:
     * The descriptor is defined to not conform the results in unit of work in read query. Default.
     *
     */
    public void dontAlwaysConformResultsInUnitOfWork() {
        setShouldAlwaysConformResultsInUnitOfWork(false);
    }

    /**
     * PUBLIC:
     * This method is the equivalent of calling {@link #setShouldAlwaysRefreshCache} with an argument of <CODE>false</CODE>:
     * it ensures that a <CODE>ClassDescriptor</CODE> is not configured to always refresh the cache if data is received from the database by any query.
     *
     * @see #alwaysRefreshCache
     */
    public void dontAlwaysRefreshCache() {
        setShouldAlwaysRefreshCache(false);
    }

    /**
     * PUBLIC:
     * This method is the equivalent of calling {@link #setShouldAlwaysRefreshCacheOnRemote} with an argument of <CODE>false</CODE>:
     * it ensures that a <CODE>ClassDescriptor</CODE> is not configured to always remotely refresh the cache if data is received from the
     * database by any query in a {@link org.eclipse.persistence.sessions.remote.RemoteSession}.
     *
     * @see #alwaysRefreshCacheOnRemote
     */
    public void dontAlwaysRefreshCacheOnRemote() {
        setShouldAlwaysRefreshCacheOnRemote(false);
    }

    /**
     * PUBLIC:
     * Allow for cache hits on primary key read object queries.
     *
     * @see #disableCacheHits()
     */
    public void dontDisableCacheHits() {
        setShouldDisableCacheHits(false);
    }

    /**
     * PUBLIC:
     * Allow for remote session cache hits on primary key read object queries.
     *
     * @see #disableCacheHitsOnRemote()
     */
    public void dontDisableCacheHitsOnRemote() {
        setShouldDisableCacheHitsOnRemote(false);
    }

    /**
     * PUBLIC:
     * This method is the equivalent of calling {@link #setShouldOnlyRefreshCacheIfNewerVersion} with an argument of <CODE>false</CODE>:
     * it ensures that a <CODE>ClassDescriptor</CODE> is not configured to only refresh the cache if the data received from the database by
     * a query is newer than the data in the cache (as determined by the optimistic locking field).
     *
     * @see #onlyRefreshCacheIfNewerVersion
     */
    public void dontOnlyRefreshCacheIfNewerVersion() {
        setShouldOnlyRefreshCacheIfNewerVersion(false);
    }

    /**
     * INTERNAL:
     * The first table in the tables is always treated as default.
     */
    protected DatabaseTable extractDefaultTable() {
        if (getTables().isEmpty()) {
            if (isChildDescriptor()) {
                return getInheritancePolicy().getParentDescriptor().extractDefaultTable();
            } else {
                return null;
            }
        }

        return getTables().get(0);
    }

    /**
     * INTERNAL:
     * additionalAggregateCollectionKeyFields are used by aggregate descriptors to hold additional fields needed when they are stored in an AggregatateCollection
     * These fields are generally foreign key fields that are required in addition to the fields in the descriptor's
     *  mappings to uniquely identify the Aggregate
     */
    public List<DatabaseField> getAdditionalAggregateCollectionKeyFields(){
        if (additionalAggregateCollectionKeyFields == null){
            additionalAggregateCollectionKeyFields = new ArrayList<>();
        }
        return additionalAggregateCollectionKeyFields;
    }

    /**
     * INTERNAL:
     * This is used to map the primary key field names in a multiple table descriptor.
     */
    public Map<DatabaseTable, Map<DatabaseField, DatabaseField>> getAdditionalTablePrimaryKeyFields() {
        if (additionalTablePrimaryKeyFields == null) {
            additionalTablePrimaryKeyFields = new HashMap(5);
        }
        return additionalTablePrimaryKeyFields;
    }

    /**
     * INTERNAL:
     * Return a list of fields that are written by map keys
     * Used to determine if there is a multiple writable mappings issue
     */
    public List<DatabaseField> getAdditionalWritableMapKeyFields() {
        if (additionalWritableMapKeyFields == null) {
            additionalWritableMapKeyFields = new ArrayList(2);
        }
        return additionalWritableMapKeyFields;
    }

    /**
     * PUBLIC:
     * Get the alias
     */
    public String getAlias() {

        /* CR3310: Steven Vo
         *   Default alias to the Java class name if the alias is not set
         */
        if ((alias == null) && (getJavaClassName() != null)) {
            alias = org.eclipse.persistence.internal.helper.Helper.getShortClassName(getJavaClassName());
        }
        return alias;
    }

    /**
     * INTERNAL:
     * Return all the fields which include all child class fields.
     * By default it is initialized to the fields for the current descriptor.
     */
    public Vector<DatabaseField> getAllFields() {
        return allFields;
    }

    /**
     * INTERNAL:
     * Return all selection fields which include all child class fields.
     * By default it is initialized to selection fields for the current descriptor.
     */
    public List<DatabaseField> getAllSelectionFields() {
        return allSelectionFields;
    }

    /**
     * INTERNAL:
     * Return all selection fields which include all child class fields.
     * By default it is initialized to selection fields for the current descriptor.
     */
    public List<DatabaseField> getAllSelectionFields(ObjectLevelReadQuery query) {
        if (hasSerializedObjectPolicy() && query.shouldUseSerializedObjectPolicy()) {
            return this.serializedObjectPolicy.getAllSelectionFields();
        } else {
            return allSelectionFields;
        }
    }

    /**
     * INTERNAL:
     * Return fields used to build insert statement.
     */
    public Vector<DatabaseField> getReturnFieldsToGenerateInsert() {
        return this.returnFieldsToGenerateInsert;
    }

    /**
     * INTERNAL:
     * Return fields used to build update statement.
     */
    public Vector<DatabaseField> getReturnFieldsToGenerateUpdate() {
        return this.returnFieldsToGenerateUpdate;
    }

    /**
     * INTERNAL:
     * Return fields used in to map into entity for insert.
     */
    public List<DatabaseField> getReturnFieldsToMergeInsert() {
        return this.returnFieldsToMergeInsert;
    }

    /**
     * INTERNAL:
     * Return fields used in to map into entity for update.
     */
    public List<DatabaseField> getReturnFieldsToMergeUpdate() {
        return this.returnFieldsToMergeUpdate;
    }

    /**
     * PUBLIC:
     * Return the amendment class.
     * The amendment method will be called on the class before initialization to allow for it to initialize the descriptor.
     * The method must be a public static method on the class.
     */
    public Class<?> getAmendmentClass() {
        return amendmentClass;
    }

    /**
     * INTERNAL:
     * Return amendment class name, used by the MW.
     */
    public String getAmendmentClassName() {
        if ((amendmentClassName == null) && (amendmentClass != null)) {
            amendmentClassName = amendmentClass.getName();
        }
        return amendmentClassName;
    }

    /**
     * PUBLIC:
     * Return the amendment method.
     * This will be called on the amendment class before initialization to allow for it to initialize the descriptor.
     * The method must be a public static method on the class.
     */
    public String getAmendmentMethodName() {
        return amendmentMethodName;
    }

    /**
     * @return the accessorTree
     */
    public List<AttributeAccessor> getAccessorTree() {
        return accessorTree;
    }


    /**
     * PUBLIC:
     * Return this objects ObjectChangePolicy.
     */
    public ObjectChangePolicy getObjectChangePolicy() {
        // part of fix for 4410581: project xml must save change policy
        // if no change-policy XML element, field is null: lazy-init to default
        if (changePolicy == null) {
            changePolicy = new DeferredChangeDetectionPolicy();
        }
        return changePolicy;
    }

    /**
     * INTERNAL:
     * Return this objects ObjectChangePolicy and do not lazy initialize
     */
    public ObjectChangePolicy getObjectChangePolicyInternal() {
        return changePolicy;
    }

    /**
     * PUBLIC:
     * Return this descriptor's HistoryPolicy.
     */
    public HistoryPolicy getHistoryPolicy() {
        return historyPolicy;
    }

    /**
     * PUBLIC:
     * Return the descriptor's partitioning policy.
     */
    public PartitioningPolicy getPartitioningPolicy() {
        return partitioningPolicy;
    }

    /**
     * PUBLIC:
     * Set the descriptor's partitioning policy.
     * A PartitioningPolicy is used to partition the data for a class across multiple difference databases
     * or across a database cluster such as Oracle RAC.
     * Partitioning can provide improved scalability by allowing multiple database machines to service requests.
     */
    public void setPartitioningPolicy(PartitioningPolicy partitioningPolicy) {
        this.partitioningPolicy = partitioningPolicy;
    }

    /**
     * PUBLIC:
     * Return the name of the descriptor's partitioning policy.
     * A PartitioningPolicy with the same name must be defined on the Project.
     * A PartitioningPolicy is used to partition the data for a class across multiple difference databases
     * or across a database cluster such as Oracle RAC.
     * Partitioning can provide improved scalability by allowing multiple database machines to service requests.
     */
    public String getPartitioningPolicyName() {
        return partitioningPolicyName;
    }

    /**
     * PUBLIC:
     * Set the name of the descriptor's partitioning policy.
     * A PartitioningPolicy with the same name must be defined on the Project.
     * A PartitioningPolicy is used to partition the data for a class across multiple difference databases
     * or across a database cluster such as Oracle RAC.
     * Partitioning can provide improved scalability by allowing multiple database machines to service requests.
     */
    public void setPartitioningPolicyName(String partitioningPolicyName) {
        this.partitioningPolicyName = partitioningPolicyName;
    }

    /**
     * A CacheInterceptor is an adaptor that when overridden and assigned to a Descriptor all interaction
     * between EclipseLink and the internal cache for that class will pass through the Interceptor.
     * Advanced users could use this interceptor to audit, profile or log cache access.  This Interceptor
     * could also be used to redirect or augment the TopLink cache with an alternate cache mechanism.
     * EclipseLink's configurated IdentityMaps will be passed to the Interceptor constructor.
     *
     * As with IdentityMaps an entire class inheritance hierarchy will share the same interceptor.
     * @see org.eclipse.persistence.sessions.interceptors.CacheInterceptor
     */
    public Class<? extends CacheInterceptor> getCacheInterceptorClass() {
        return getCachePolicy().getCacheInterceptorClass();
    }

    /**
     * A CacheInterceptor is an adaptor that when overridden and assigned to a Descriptor all interaction
     * between EclipseLink and the internal cache for that class will pass through the Interceptor.
     * Advanced users could use this interceptor to audit, profile or log cache access.  This Interceptor
     * could also be used to redirect or augment the TopLink cache with an alternate cache mechanism.
     * EclipseLink's configurated IdentityMaps will be passed to the Interceptor constructor.
     *
     * As with IdentityMaps an entire class inheritance hierarchy will share the same interceptor.
     * @see org.eclipse.persistence.sessions.interceptors.CacheInterceptor
     */
    public String getCacheInterceptorClassName() {
        return getCachePolicy().getCacheInterceptorClassName();
    }

    /**
     * PUBLIC:
     * Return the CacheInvalidationPolicy for this descriptor
     * For uninitialized cache invalidation policies, this will return a NoExpiryCacheInvalidationPolicy
     * @return CacheInvalidationPolicy
     * @see org.eclipse.persistence.descriptors.invalidation.CacheInvalidationPolicy
     */
    public CacheInvalidationPolicy getCacheInvalidationPolicy() {
        if (cacheInvalidationPolicy == null) {
            cacheInvalidationPolicy = new NoExpiryCacheInvalidationPolicy();
        }
        return cacheInvalidationPolicy;
    }

    /**
     * PUBLIC:
     * Get a value indicating the type of cache synchronization that will be used on objects of
     * this type. Possible values are:
     * SEND_OBJECT_CHANGES
     * INVALIDATE_CHANGED_OBJECTS
     * SEND_NEW_OBJECTS+WITH_CHANGES
     * DO_NOT_SEND_CHANGES
     */
    public int getCacheSynchronizationType() {
        return getCachePolicy().getCacheSynchronizationType();
    }

    /**
     * INTERNAL:
     */
    public List<CascadeLockingPolicy> getCascadeLockingPolicies() {
        if (this.cascadeLockingPolicies == null) {
            this.cascadeLockingPolicies = new ArrayList();
        }
        return cascadeLockingPolicies;
    }

    /**
     * ADVANCED:
     *  automatically orders database access through the foreign key information provided in 1:1 and 1:m mappings.
     * In some case when 1:1 are not defined it may be required to tell the descriptor about a constraint,
     * this defines that this descriptor has a foreign key constraint to another class and must be inserted after
     * instances of the other class.
     */
    public Vector getConstraintDependencies() {
        if (constraintDependencies == null) {
            constraintDependencies = NonSynchronizedVector.newInstance(1);
        }
        return constraintDependencies;
    }

    /**
     * INTERNAL:
     * Returns the copy policy.
     */
    public CopyPolicy getCopyPolicy() {
        // Lazy initialize for XML deployment.
        if (copyPolicy == null) {
            setCopyPolicy(new InstantiationCopyPolicy());
        }
        return copyPolicy;
    }

    /**
     * INTERNAL:
     * Returns the name of a Class that implements CopyPolicy
     * Will be instantiated as a copy policy at initialization times
     * using the no-args constructor
     */
    public String getCopyPolicyClassName(){
        return copyPolicyClassName;
    }

    /**
     * INTERNAL:
     * The first table in the tables is always treated as default.
     */
    public DatabaseTable getDefaultTable() {
        return defaultTable;
    }

    /**
     * ADVANCED:
     * return the descriptor type (NORMAL by default, others include INTERFACE, AGGREGATE, AGGREGATE COLLECTION)
     */
    public int getDescriptorType() {
        return descriptorType;
    }

    /**
     * INTERNAL:
     * This method is explicitly used by the XML reader.
     */
    public String getDescriptorTypeValue() {
        if (isAggregateCollectionDescriptor()) {
            return "Aggregate collection";
        } else if (isAggregateDescriptor()) {
            return "Aggregate";
        } else if (isDescriptorForInterface()) {
            return "Interface";
        } else {
            // Default.
            return "Normal";
        }
    }

    /**
     * ADVANCED:
     * Return the derives id mappings.
     */
    public Collection<DatabaseMapping> getDerivesIdMappinps() {
        return derivesIdMappings.values();
    }

    /**
     * INTERNAL:
     * DescriptorCustomizer is the JPA equivalent of an amendment method.
     */
    public String getDescriptorCustomizerClassName(){
        return descriptorCustomizerClassName;
    }

    /**
     * PUBLIC:
     * Get the event manager for the descriptor.  The event manager is responsible
     * for managing the pre/post selectors.
     */
    public DescriptorEventManager getDescriptorEventManager() {
        return getEventManager();
    }

    /**
     * PUBLIC:
     * Get the event manager for the descriptor.  The event manager is responsible
     * for managing the pre/post selectors.
     */
    @Override
    public DescriptorEventManager getEventManager() {
        // Lazy initialize for XML deployment.
        if (eventManager == null) {
            setEventManager(new org.eclipse.persistence.descriptors.DescriptorEventManager());
        }
        return eventManager;
    }

    /**
     * INTERNAL:
     * Return all the fields
     */
    public Vector<DatabaseField> getFields() {
        if (fields == null) {
            fields = NonSynchronizedVector.newInstance();
        }
        return fields;
    }

    /**
     * INTERNAL:
     * Return all selection fields
     */
    public List<DatabaseField> getSelectionFields() {
        return selectionFields;
    }

    /**
     * INTERNAL:
     * Return all selection fields
     */
    public List<DatabaseField> getSelectionFields(ObjectLevelReadQuery query) {
        if (hasSerializedObjectPolicy() && query.shouldUseSerializedObjectPolicy()) {
            return this.serializedObjectPolicy.getSelectionFields();
        } else {
            return selectionFields;
        }
    }

    /**
     * INTERNAL:
     */
    public Set<DatabaseField> getForeignKeyValuesForCaching() {
        return foreignKeyValuesForCaching;
    }

    /**
     * INTERNAL:
     * Return the class of identity map to be used by this descriptor.
     * The default is the "SoftCacheWeakIdentityMap".
     */
    public <T extends IdentityMap> Class<T> getIdentityMapClass() {
        return getCachePolicy().getIdentityMapClass();
    }

    /**
     * PUBLIC:
     * Return the size of the identity map.
     */
    public int getIdentityMapSize() {
        return getCachePolicy().getIdentityMapSize();
    }

    /**
     * PUBLIC:
     * The inheritance policy is used to define how a descriptor takes part in inheritance.
     * All inheritance properties for both child and parent classes is configured in inheritance policy.
     * Caution must be used in using this method as it lazy initializes an inheritance policy.
     * Calling this on a descriptor that does not use inheritance will cause problems, #hasInheritance() must always first be called.
     */
    public InheritancePolicy getDescriptorInheritancePolicy() {
        return getInheritancePolicy();
    }

    /**
     * PUBLIC:
     * The inheritance policy is used to define how a descriptor takes part in inheritance.
     * All inheritance properties for both child and parent classes is configured in inheritance policy.
     * Caution must be used in using this method as it lazy initializes an inheritance policy.
     * Calling this on a descriptor that does not use inheritance will cause problems, #hasInheritance() must always first be called.
     */
    @Override
    public InheritancePolicy getInheritancePolicy() {
        if (inheritancePolicy == null) {
            // Lazy initialize to conserve space in non-inherited classes.
            setInheritancePolicy(new org.eclipse.persistence.descriptors.InheritancePolicy(this));
        }
        return inheritancePolicy;
    }

    /**
     * INTERNAL:
     * Return the inheritance policy.
     */
    public InheritancePolicy getInheritancePolicyOrNull() {
        return inheritancePolicy;
    }

    /**
     * INTERNAL:
     * Returns the instantiation policy.
     */
    @Override
    public InstantiationPolicy getInstantiationPolicy() {
        // Lazy initialize for XML deployment.
        if (instantiationPolicy == null) {
            setInstantiationPolicy(new InstantiationPolicy());
        }
        return instantiationPolicy;
    }

    /**
     * PUBLIC:
     * Returns the InterfacePolicy.
     * The interface policy allows for a descriptor's public and variable interfaces to be defined.
     * Caution must be used in using this method as it lazy initializes an interface policy.
     * Calling this on a descriptor that does not use interfaces will cause problems, #hasInterfacePolicy() must always first be called.
     */
    public InterfacePolicy getInterfacePolicy() {
        if (interfacePolicy == null) {
            // Lazy initialize to conserve space in non-inherited classes.
            setInterfacePolicy(new InterfacePolicy(this));
        }
        return interfacePolicy;
    }

    /**
     * INTERNAL:
     * Returns the InterfacePolicy.
     */
    public InterfacePolicy getInterfacePolicyOrNull() {
        return interfacePolicy;
    }

    /**
     * PUBLIC:
     * Return the java class.
     */
    @Override
    @SuppressWarnings({"unchecked"})
    public <T> Class<T> getJavaClass() {
        return (Class<T>) javaClass;
    }

    /**
     * Return the class name, used by the MW.
     */
    public String getJavaClassName() {
        if ((javaClassName == null) && (javaClass != null)) {
            javaClassName = javaClass.getName();
        }
        return javaClassName;
    }

    /**
     * INTERNAL:
     * Returns a reference to the mappings that must be traverse when locking
     */
    public List<DatabaseMapping> getLockableMappings() {
        if (this.lockableMappings == null) {
            this.lockableMappings = new ArrayList<>();
        }
        return this.lockableMappings;
    }

    /**
     * PUBLIC:
     * Returns the mapping associated with a given attribute name.
     * This can be used to find a descriptors mapping in a amendment method before the descriptor has been initialized.
     */
    public DatabaseMapping getMappingForAttributeName(String attributeName) {
        // ** Don't use this internally, just for amendments, see getMappingForAttributeName on ObjectBuilder.
        for (Enumeration<DatabaseMapping> mappingsNum = mappings.elements(); mappingsNum.hasMoreElements();) {
            DatabaseMapping mapping = mappingsNum.nextElement();
            if ((mapping.getAttributeName() != null) && mapping.getAttributeName().equals(attributeName)) {
                return mapping;
            }
        }
        return null;
    }

    /**
     * ADVANCED:
     * Removes the locally defined mapping associated with a given attribute name.
     * This can be used in a amendment method before the descriptor has been initialized.
     */
    public DatabaseMapping removeMappingForAttributeName(String attributeName) {
        DatabaseMapping mapping = getMappingForAttributeName(attributeName);
        getMappings().remove(mapping);
        return mapping;
    }

    /**
     * PUBLIC:
     * Returns mappings
     */
    public Vector<DatabaseMapping> getMappings() {
        return mappings;
    }

    /**
     * INTERNAL:
     * Returns the foreign key relationships used for multiple tables which were specified by the user. Used
     * by the Project XML writer to output these associations
     *
     * @see #adjustMultipleTableInsertOrder()
     */
    public Vector getMultipleTableForeignKeyAssociations() {
        Vector associations = new Vector(getAdditionalTablePrimaryKeyFields().size() * 2);
        Iterator<Map<DatabaseField, DatabaseField>> tablesHashtable = getAdditionalTablePrimaryKeyFields().values().iterator();
        while (tablesHashtable.hasNext()) {
            Map<DatabaseField, DatabaseField> tableHash = tablesHashtable.next();
            Iterator<DatabaseField> fieldEnumeration = tableHash.keySet().iterator();
            while (fieldEnumeration.hasNext()) {
                DatabaseField keyField = fieldEnumeration.next();

                //PRS#36802(CR#2057) contains() is changed to containsKey()
                if (getMultipleTableForeignKeys().containsKey(keyField.getTable())) {
                    Association association = new Association(keyField.getQualifiedName(), tableHash.get(keyField).getQualifiedName());
                    associations.addElement(association);
                }
            }
        }
        return associations;
    }

    /**
     * INTERNAL:
     * Returns the foreign key relationships used for multiple tables which were specified by the user. The key
     * of the Map is the field in the source table of the foreign key relationship. The value is the field
     * name of the target table.
     *
     * @see #adjustMultipleTableInsertOrder()
     */
    public Map<DatabaseTable, Set<DatabaseTable>> getMultipleTableForeignKeys() {
        if (multipleTableForeignKeys == null) {
            multipleTableForeignKeys = new HashMap<>(5);
        }
        return multipleTableForeignKeys;
    }

    /**
     * INTERNAL:
     * Returns the List of DatabaseTables in the order which INSERTS should take place. This order is
     * determined by the foreign key fields which are specified by the user.
     */
    public List<DatabaseTable> getMultipleTableInsertOrder() throws DescriptorException {
        return multipleTableInsertOrder;
    }

    /**
     * INTERNAL:
     * Returns the foreign key relationships used for multiple tables which were specified by the user. Used
     * by the Project XML writer to output these associations
     *
     * @see #adjustMultipleTableInsertOrder()
     */
    public Vector getMultipleTablePrimaryKeyAssociations() {
        Vector associations = new Vector(getAdditionalTablePrimaryKeyFields().size() * 2);
        Iterator<Map<DatabaseField, DatabaseField>> tablesHashtable = getAdditionalTablePrimaryKeyFields().values().iterator();
        while (tablesHashtable.hasNext()) {
            Map<DatabaseField, DatabaseField> tableHash = tablesHashtable.next();
            Iterator<DatabaseField> fieldEnumeration = tableHash.keySet().iterator();
            while (fieldEnumeration.hasNext()) {
                DatabaseField keyField = fieldEnumeration.next();

                //PRS#36802(CR#2057) contains() is changed to containsKey()
                if (!getMultipleTableForeignKeys().containsKey(keyField.getTable())) {
                    Association association = new Association(keyField.getQualifiedName(), tableHash.get(keyField).getQualifiedName());
                    associations.addElement(association);
                }
            }
        }
        return associations;
    }

    /**
     * INTERNAL:
     * Retun the multitenant policy
     */
    public MultitenantPolicy getMultitenantPolicy() {
        return multitenantPolicy;
    }

    /**
     * INTERNAL:
     * Return the object builder
     */
    @Override
    public ObjectBuilder getObjectBuilder() {
        return objectBuilder;
    }

    /**
     * PUBLIC:
     * Returns the OptimisticLockingPolicy. By default this is an instance of VersionLockingPolicy.
     */
    public OptimisticLockingPolicy getOptimisticLockingPolicy() {
        return optimisticLockingPolicy;
    }

    /**
     * INTERNAL:
     * Set of mappings that require early delete behavior.
     * This is used to handle deletion constraints.
     */
    public List<DatabaseMapping> getPreDeleteMappings() {
        if (this.preDeleteMappings == null) {
            this.preDeleteMappings = new ArrayList<>();
        }
        return this.preDeleteMappings;
    }

    /**
     * INTERNAL:
     * Add the mapping to be notified before deletion.
     * Must also be added to child descriptors.
     */
    public void addPreDeleteMapping(DatabaseMapping mapping) {
        getPreDeleteMappings().add(mapping);
    }

    /**
     * PUBLIC:
     * Return the names of all the primary keys.
     */
    @Override
    public Vector<String> getPrimaryKeyFieldNames() {
        Vector<String> result = new Vector(getPrimaryKeyFields().size());
        List<DatabaseField> primaryKeyFields = getPrimaryKeyFields();
        for (int index = 0; index < primaryKeyFields.size(); index++) {
            result.addElement(primaryKeyFields.get(index).getQualifiedName());
        }

        return result;
    }

    /**
     * INTERNAL:
     * Return all the primary key fields
     */
    @Override
    public List<DatabaseField> getPrimaryKeyFields() {
        return primaryKeyFields;
    }

    /**
     * PUBLIC:
     * Returns the user defined properties.
     */
    public Map getProperties() {
        if (properties == null) {
            properties = new HashMap(5);
        }
        return properties;
    }

    /**
     * PUBLIC:
     * Returns the descriptor property associated the given String.
     */
    public Object getProperty(String name) {
        return getProperties().get(name);
    }

    /**
     * INTERNAL:
     * Return the query key with the specified name
     */
    public QueryKey getQueryKeyNamed(String queryKeyName) {
        return this.getQueryKeys().get(queryKeyName);
    }

    /**
     * PUBLIC:
     * Return the query keys.
     */
    public Map<String, QueryKey> getQueryKeys() {
        return queryKeys;
    }

    /**
     * PUBLIC:
     * Return the queryManager.
     * The query manager can be used to specify customization of the SQL
     * that  generates for this descriptor.
     */
    public DescriptorQueryManager getDescriptorQueryManager() {
        return this.getQueryManager();
    }

    /**
     * PUBLIC:
     * Return the queryManager.
     * The query manager can be used to specify customization of the SQL
     * that  generates for this descriptor.
     */
    public DescriptorQueryManager getQueryManager() {
        // Lazy initialize for XML deployment.
        if (queryManager == null) {
            setQueryManager(new org.eclipse.persistence.descriptors.DescriptorQueryManager());
        }
        return queryManager;
    }

    /**
     * INTERNAL:
     * Return the class of identity map to be used by this descriptor.
     * The default is the "SoftCacheWeakIdentityMap".
     */
    public <T extends IdentityMap> Class<T> getRemoteIdentityMapClass() {
        return getCachePolicy().getRemoteIdentityMapClass();
    }

    /**
     * PUBLIC:
     * This method returns the root descriptor for for this descriptor's class heirarchy.
     * If the user is not using inheritance then the root class will be this class.
     */
    public ClassDescriptor getRootDescriptor(){
        if (this.hasInheritance()){
            return this.getInheritancePolicy().getRootParentDescriptor();
        }
        return this;
    }

    /**
     * PUBLIC:
     * Return the size of the remote identity map.
     */
    public int getRemoteIdentityMapSize() {
        return getCachePolicy().getRemoteIdentityMapSize();
    }

    /**
     * PUBLIC:
     * Return returning policy.
     */
    public ReturningPolicy getReturningPolicy() {
        return returningPolicy;
    }

    /**
     * PUBLIC:
     * Return returning policy from current descriptor and from mappings
     */
    public List<ReturningPolicy> getReturningPolicies() {
        return returningPolicies;
    }

    /**
     * INTERNAL:
     * Get sequence number field
     */
    public DatabaseField getSequenceNumberField() {
        return sequenceNumberField;
    }

    /**
     * PUBLIC:
     * Get sequence number field name
     */
    public String getSequenceNumberFieldName() {
        if (getSequenceNumberField() == null) {
            return null;
        }
        return getSequenceNumberField().getQualifiedName();
    }

    /**
     * PUBLIC:
     * Get sequence number name
     */
    public String getSequenceNumberName() {
        return sequenceNumberName;
    }

    /**
     * INTERNAL:
     * Return the name of the session local to this descriptor.
     * This is used by the session broker.
     */
    public String getSessionName() {
        return sessionName;
    }

    /**
     * INTERNAL:
     * Checks if table name exists with the current descriptor or not.
     */
    public DatabaseTable getTable(String tableName) throws DescriptorException {
        if (hasTablePerMultitenantPolicy()) {
            DatabaseTable table =  ((TablePerMultitenantPolicy) getMultitenantPolicy()).getTable(tableName);

            if (table != null) {
                return table;
            }
        }

        if (getTables().isEmpty()) {
            return null;// Assume aggregate descriptor.
        }

        for (Enumeration<DatabaseTable> tables = getTables().elements(); tables.hasMoreElements();) {
            DatabaseTable table = tables.nextElement();

            if(tableName.indexOf(' ') != -1) {
                //if looking for a table with a ' ' character, the name will have
                //been quoted internally. Check for match without quotes.
                String currentTableName = table.getName();
                if(currentTableName.substring(1, currentTableName.length() - 1).equals(tableName)) {
                    return table;
                }
            }
            if (table.getName().equals(tableName)) {
                return table;
            }
        }

        if (isAggregateDescriptor()) {
            return getDefaultTable();
        }
        throw DescriptorException.tableNotPresent(tableName, this);
    }

    /**
     * PUBLIC:
     * Return the name of the descriptor's first table.
     * This method must only be called on single table descriptors.
     */
    public String getTableName() {
        if (getTables().isEmpty()) {
            return null;
        } else {
            return getTables().get(0).getName();
        }
    }

    /**
     * PUBLIC:
     * Return the table names.
     */
    public Vector getTableNames() {
        Vector tableNames = new Vector(getTables().size());
        for (Enumeration<DatabaseTable> fieldsEnum = getTables().elements(); fieldsEnum.hasMoreElements();) {
            tableNames.addElement(fieldsEnum.nextElement().getQualifiedName());
        }

        return tableNames;
    }

    /**
     * PUBLIC:
     * Returns the TablePerClassPolicy.
     * The table per class policy allows JPA users to configure the
     * TABLE_PER_CLASS inheritance strategy. Calling this on a descriptor that
     * does not use table per class will cause problems,
     * #hasTablePerClassPolicy() must always first be called.
     * @see #setTablePerClassPolicy
     */
    public TablePerClassPolicy getTablePerClassPolicy() {
        return (TablePerClassPolicy) interfacePolicy;
    }

    /**
     * INTERNAL:
     * Return all the tables.
     */
    public Vector<DatabaseTable> getTables() {
        return tables;
    }

    /**
     * INTERNAL:
     * searches first descriptor than its ReturningPolicy for an equal field
     */
    @Override
    public DatabaseField getTypedField(DatabaseField field) {
        boolean mayBeMoreThanOne = hasMultipleTables() && !field.hasTableName();
        DatabaseField foundField = null;
        for (int index = 0; index < getFields().size(); index++) {
            DatabaseField descField = getFields().get(index);
            if (field.equals(descField)) {
                if (descField.getType() != null) {
                    foundField = descField;
                    if (!mayBeMoreThanOne || descField.getTable().equals(getDefaultTable())) {
                        break;
                    }
                }
            }
        }
        if ((foundField == null) && hasReturningPolicy()) {
            DatabaseField returnField = getReturningPolicy().getField(field);
            if ((returnField != null) && (returnField.getType() != null)) {
                foundField = returnField;
            }
        }
        if (foundField != null) {
            foundField = foundField.clone();
            if (!field.hasTableName()) {
                foundField.setTableName("");
            }
        }

        return foundField;
    }

    /**
     * ADVANCED:
     * Return the WrapperPolicy for this descriptor.
     * This advanced feature can be used to wrap objects with other classes such as CORBA TIE objects or EJBs.
     */
    public WrapperPolicy getWrapperPolicy() {
        return wrapperPolicy;
    }

    /**
     * INTERNAL:
     * Checks if the class has any private owned parts or other dependencies, (i.e. M:M join table).
     */
    public boolean hasDependencyOnParts() {
        for (DatabaseMapping mapping : getMappings()) {
            if (mapping.hasDependency()) {
                return true;
            }
        }

        return false;
    }

    /**
     * INTERNAL:
     * returns true if users have designated one or more mappings as IDs. Used
     * for CMP3Policy primary key class processing.
     */
    public boolean hasDerivedId() {
        return ! derivesIdMappings.isEmpty();
    }

    /**
     * INTERNAL:
     * returns true if a DescriptorEventManager has been set.
     */
    @Override
    public boolean hasEventManager() {
        return null != eventManager;
    }

    /**
     * INTERNAL:
     * Return if this descriptor is involved in inheritance, (is child or parent).
     * Note: If this class is part of table per class inheritance strategy this
     * method will return false.
     * @see #hasTablePerClassPolicy()
     */
    @Override
    public boolean hasInheritance() {
        return (inheritancePolicy != null);
    }

    /**
     * INTERNAL:
     * Return if this descriptor is involved in interface, (is child or parent).
     */
    public boolean hasInterfacePolicy() {
        return (interfacePolicy != null);
    }

    /**
     * INTERNAL:
     * Check if descriptor has multiple tables
     */
    public boolean hasMultipleTables() {
        return (getTables().size() > 1);
    }

    /**
     * INTERNAL:
     * Calculates whether descriptor references an entity (directly or through a nested mapping).
     */
    public boolean hasNestedIdentityReference(boolean withChildren) {
        if (withChildren && hasInheritance() && getInheritancePolicy().hasChildren()) {
            for (ClassDescriptor childDescriptor : getInheritancePolicy().getAllChildDescriptors()) {
                // leaf children have all the mappings
                if (!childDescriptor.getInheritancePolicy().hasChildren()) {
                    if (childDescriptor.hasNestedIdentityReference(false)) {
                        return true;
                    }
                }
            }
        } else {
            for (DatabaseMapping mapping : getMappings()) {
                if (mapping.hasNestedIdentityReference()) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * @return the hasNoncacheableMappings
     */
    public boolean hasNoncacheableMappings() {
        return hasNoncacheableMappings;
    }

    /**
     * @return the preDeleteMappings
     */
    public boolean hasPreDeleteMappings() {
        return preDeleteMappings != null;
    }

    /**
     * INTERNAL:
     * Checks if the class has any private owned parts are not
     */
    public boolean hasPrivatelyOwnedParts() {
        for (Enumeration<DatabaseMapping> mappings = getMappings().elements(); mappings.hasMoreElements();) {
            DatabaseMapping mapping = mappings.nextElement();
            if (mapping.isPrivateOwned()) {
                return true;
            }
        }

        return false;
    }

    /**
     * INTERNAL:
     * Checks to see if it has a query key or mapping with the specified name or not.
     */
    public boolean hasQueryKeyOrMapping(String attributeName) {
        return (getQueryKeys().containsKey(attributeName) || (getObjectBuilder().getMappingForAttributeName(attributeName) != null));
    }

    /**
     * INTERNAL:
     *  return whether this descriptor has any relationships through its mappings, through inheritance, or through aggregates
     */
    public boolean hasRelationships() {
        return hasRelationships;
    }

    /**
     * INTERNAL:
     * This method returns true if this descriptor has either a ForeignReferenceMapping to
     * an object aside from the one described by descriptor or more than one ForeignReferenceMapping
     * to descriptor.  (i.e. It determines if there is any mapping aside from a backpointer to a mapping
     * defined in descriptor)
     */
    public boolean hasRelationshipsExceptBackpointer(ClassDescriptor descriptor){
        Iterator<DatabaseMapping> i = mappings.iterator();
        boolean foundRelationship = false;
        while (i.hasNext()){
            DatabaseMapping mapping = i.next();
            if (mapping.isForeignReferenceMapping()){
                ForeignReferenceMapping frMapping = (ForeignReferenceMapping)mapping;
                if (frMapping.getReferenceDescriptor().equals(descriptor)){
                    if (foundRelationship){
                        return true;
                    } else {
                        foundRelationship = true;
                    }
                } else {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * INTERNAL:
     * Return if this descriptor has Returning policy.
     */
    public boolean hasReturningPolicy() {
        return (returningPolicy != null);
    }

    /**
     * INTERNAL:
     * Return if this descriptor or descriptors from mappings has Returning policy.
     */
    public boolean hasReturningPolicies() {
        return (returningPolicies != null);
    }

    /**
     * INTERNAL:
     */
    public boolean hasSerializedObjectPolicy() {
        return this.serializedObjectPolicy != null;
    }

    /**
     * INTERNAL:
     */
    public SerializedObjectPolicy getSerializedObjectPolicy() {
        return this.serializedObjectPolicy;
    }

    /**
     * INTERNAL:
     */
    public void setSerializedObjectPolicy(SerializedObjectPolicy serializedObjectPolicy) {
        this.serializedObjectPolicy = serializedObjectPolicy;
        if (serializedObjectPolicy != null) {
            serializedObjectPolicy.setDescriptor(this);
        }
    }

    /**
     * INTERNAL:
     * Return if a wrapper policy is used.
     */
    public boolean hasWrapperPolicy() {
        return this.wrapperPolicy != null;
    }

    /**
     * INTERNAL:
     * Initialize the mappings as a separate step.
     * This is done as a separate step to ensure that inheritance has been first resolved.
     */
    public void initialize(AbstractSession session) throws DescriptorException {
        // Avoid repetitive initialization (this does not solve loops)
        if (isInitialized(INITIALIZED) || isInvalid()) {
            return;
        }

        setInitializationStage(INITIALIZED);

        // make sure that parent mappings are initialized?
        if (isChildDescriptor()) {
            ClassDescriptor parentDescriptor = getInheritancePolicy().getParentDescriptor();
            parentDescriptor.initialize(session);
            getCachePolicy().initializeFromParent(parentDescriptor.getCachePolicy(), this,
                    parentDescriptor, session);
            // Setup this early before useOptimisticLocking is called so that subclass
            // versioned by superclass are also covered
            getInheritancePolicy().initializeOptimisticLocking();
            // EL bug 336486
            getInheritancePolicy().initializeCacheInvalidationPolicy();
            if (parentDescriptor.hasSerializedObjectPolicy()) {
                if (!hasSerializedObjectPolicy()) {
                    // If SerializedObjectPolicy set on parent descriptor then should be set on children, too
                    setSerializedObjectPolicy(parentDescriptor.getSerializedObjectPolicy().instantiateChild());
                }
            }
        }

        // Mappings must be sorted before field are collected in the order of the mapping for indexes to work.
        // Sorting the mappings to ensure that all DirectToFields get merged before all other mappings
        // This prevents null key errors when merging maps
        if (shouldOrderMappings()) {
            Vector<DatabaseMapping> mappings = getMappings();
            DatabaseMapping[] mappingsArray = new DatabaseMapping[mappings.size()];
            for (int index = 0; index < mappings.size(); index++) {
                mappingsArray[index] = mappings.get(index);
            }
            Arrays.sort(mappingsArray, new MappingCompare());
            mappings = NonSynchronizedVector.newInstance(mappingsArray.length);
            for (int index = 0; index < mappingsArray.length; index++) {
                mappings.add(mappingsArray[index]);
            }
            setMappings(mappings);
        }

        boolean initializeCascadeLocking = (usesOptimisticLocking() && getOptimisticLockingPolicy().isCascaded()) || hasCascadeLockingPolicies();
        for (DatabaseMapping mapping : getMappings()) {
            validateMappingType(mapping);
            mapping.initialize(session);
            if (!mapping.isCacheable()){
                this.hasNoncacheableMappings = true;
            }

            if (mapping.isForeignReferenceMapping()){
                if(((ForeignReferenceMapping)mapping).getIndirectionPolicy() instanceof ProxyIndirectionPolicy) {
                    session.getProject().setHasProxyIndirection(true);
                }
                ClassDescriptor referencedDescriptor = mapping.getReferenceDescriptor();
                if (referencedDescriptor!= null){
                    referencedDescriptor.referencingClasses.add(this);
                }
            }

            if (mapping.isAggregateObjectMapping()) {
                ClassDescriptor referencedDescriptor = mapping.getReferenceDescriptor();
                if (referencedDescriptor!= null){
                    referencedDescriptor.referencingClasses.add(this);
                }
            }
            // If this descriptor uses a cascaded version optimistic locking
            // or has cascade locking policies set then prepare check the
            // mappings.
            if (initializeCascadeLocking) {
                prepareCascadeLockingPolicy(mapping);
            }

            // JPA 2.0 Derived identities - build a map of derived id mappings.
            if (mapping.derivesId()) {
                this.derivesIdMappings.put(mapping.getAttributeName(), mapping);
            }

            // Add all the fields in the mapping to myself.
            Helper.addAllUniqueToVector(getFields(), mapping.getFields());
        }
        if (initializeCascadeLocking) {
            this.cascadedLockingInitialized = true;
        }

        if (hasMappingsPostCalculateChangesOnDeleted()) {
            session.getProject().setHasMappingsPostCalculateChangesOnDeleted(true);
        }

        // PERF: Don't initialize locking until after fields have been computed so
        // field is in correct position.
        if (!isAggregateDescriptor()) {
            if (!isChildDescriptor()) {
                // Add write lock field to getFields
                if (usesOptimisticLocking()) {
                    getOptimisticLockingPolicy().initializeProperties();
                }
            }
            if (hasSerializedObjectPolicy()) {
                getSerializedObjectPolicy().initializeField(session);
            }
        }

        // All the query keys should be initialized.
        for (Iterator<QueryKey> queryKeys = getQueryKeys().values().iterator(); queryKeys.hasNext();) {
            QueryKey queryKey = queryKeys.next();
            queryKey.initialize(this);
        }

        if (getPartitioningPolicyName() != null) {
            PartitioningPolicy policy = session.getProject().getPartitioningPolicy(getPartitioningPolicyName());
            if (policy == null) {
                session.getIntegrityChecker().handleError(DescriptorException.missingPartitioningPolicy(getPartitioningPolicyName(), this, null));
            }
            setPartitioningPolicy(policy);
        }

        // If this descriptor has inheritance then it needs to be initialized before all fields is set.
        if (hasInheritance()) {
            getInheritancePolicy().initialize(session);
            if (getInheritancePolicy().isChildDescriptor()) {
                ClassDescriptor parentDescriptor = getInheritancePolicy().getParentDescriptor();
                for (DatabaseMapping mapping : parentDescriptor.getMappings()) {
                    if (mapping.isAggregateObjectMapping() || ((mapping.isForeignReferenceMapping() && (!mapping.isDirectCollectionMapping())) && (!((ForeignReferenceMapping)mapping).usesIndirection()))) {
                        getLockableMappings().add(mapping);// add those mappings from the parent.
                    }
                    // JPA 2.0 Derived identities - build a map of derived id mappings.
                    if (mapping.derivesId()) {
                        this.derivesIdMappings.put(mapping.getAttributeName(), mapping);
                    }
                }
                if (parentDescriptor.hasPreDeleteMappings()) {
                    getPreDeleteMappings().addAll(parentDescriptor.getPreDeleteMappings());
                }
                if (parentDescriptor.hasMappingsPostCalculateChanges()) {
                    getMappingsPostCalculateChanges().addAll(parentDescriptor.getMappingsPostCalculateChanges());
                }
                if (parentDescriptor.hasMappingsPostCalculateChangesOnDeleted()) {
                    getMappingsPostCalculateChangesOnDeleted().addAll(parentDescriptor.getMappingsPostCalculateChangesOnDeleted());
                }
            }
        }

        // cr 4097  Ensure that the mappings are ordered after the superclasses mappings have been added.
        // This ensures that the mappings in the child class are ordered correctly
        // I am sorting the mappings to ensure that all DirectToFields get merged before all other mappings
        // This prevents null key errors when merging maps
        // This resort will change the previous sort order, only do it if has inheritance.
        if (hasInheritance() && shouldOrderMappings()) {
            Vector<DatabaseMapping> mappings = getMappings();
            DatabaseMapping[] mappingsArray = new DatabaseMapping[mappings.size()];
            for (int index = 0; index < mappings.size(); index++) {
                mappingsArray[index] = mappings.get(index);
            }
            Arrays.sort(mappingsArray, new MappingCompare());
            mappings = NonSynchronizedVector.newInstance(mappingsArray.length);
            for (int index = 0; index < mappingsArray.length; index++) {
                mappings.add(mappingsArray[index]);
            }
            setMappings(mappings);
        }

        // Initialize the allFields to its fields, this can be done now because the fields have been computed.
        setAllFields((Vector)getFields().clone());

        getObjectBuilder().initialize(session);

        // Initialize the multitenant policy only after the mappings have been
        // initialized.
        if (hasMultitenantPolicy()) {
            getMultitenantPolicy().initialize(session);
        }

        if (shouldOrderMappings()) {
            // PERF: Ensure direct primary key mappings are first.
            for (int index = getObjectBuilder().getPrimaryKeyMappings().size() - 1; index >= 0; index--) {
                DatabaseMapping mapping = getObjectBuilder().getPrimaryKeyMappings().get(index);
                if ((mapping != null) && mapping.isAbstractColumnMapping()) {
                    getMappings().remove(mapping);
                    getMappings().add(0, mapping);
                    DatabaseField field = mapping.getField();
                    getFields().remove(field);
                    getFields().add(0, field);
                    getAllFields().remove(field);
                    getAllFields().add(0, field);
                }
            }
        }

        if (usesOptimisticLocking() && (!isChildDescriptor())) {
            getOptimisticLockingPolicy().initialize(session);
        }
        if (hasInterfacePolicy() || isDescriptorForInterface()) {
            interfaceInitialization(session);
        }
        if (hasWrapperPolicy()) {
            getWrapperPolicy().initialize(session);
        }
        if (hasReturningPolicy()) {
            getReturningPolicy().initialize(session);
        }
        if (hasSerializedObjectPolicy()) {
            getSerializedObjectPolicy().initialize(session);
        }
        getQueryManager().initialize(session);
        getEventManager().initialize(session);
        getCopyPolicy().initialize(session);
        getInstantiationPolicy().initialize(session);
        getCachePolicy().initialize(this, session);

        if (getHistoryPolicy() != null) {
            getHistoryPolicy().initialize(session);
        } else if (hasInheritance()) {
            // Only one level of inheritance needs to be checked as parent descriptors
            // are initialized before children are
            ClassDescriptor parentDescriptor = getInheritancePolicy().getParentDescriptor();
            if ((parentDescriptor != null) && (parentDescriptor.getHistoryPolicy() != null)) {
                setHistoryPolicy((HistoryPolicy)parentDescriptor.getHistoryPolicy().clone());
            }
        }

        if (getCMPPolicy() != null) {
            getCMPPolicy().initialize(this, session);
        }

        // Validate the fetch group setting during descriptor initialization.
        if (hasFetchGroupManager()) {
            getFetchGroupManager().initialize(session);
        }

        // By default if change policy is not configured set to attribute change tracking if weaved.
        if ((getObjectChangePolicyInternal() == null) && (ChangeTracker.class.isAssignableFrom(getJavaClass()))) {
            // Only auto init if this class "itself" was weaved for change tracking, i.e. not just a superclass.
            if (Arrays.asList(getJavaClass().getInterfaces()).contains(PersistenceWeavedChangeTracking.class)
                    || (DynamicEntityImpl.class.isAssignableFrom(getJavaClass()))) {
                // Must double check that this descriptor support change tracking,
                // when it was weaved it was not initialized, and may now know that it does not support change tracking.
                if (supportsChangeTracking(session.getProject())) {
                    setObjectChangePolicy(new AttributeChangeTrackingPolicy());
                }
            }
        }
        // 3934266 move validation to the policy allowing for this to be done in the sub policies.
        getObjectChangePolicy().initialize(session, this);

        // Setup default redirectors.  Any redirector that is not set will get assigned the
        // default redirector.
        if (this.defaultReadAllQueryRedirector == null){
            this.defaultReadAllQueryRedirector = this.defaultQueryRedirector;
        }
        if (this.defaultReadObjectQueryRedirector == null){
            this.defaultReadObjectQueryRedirector = this.defaultQueryRedirector;
        }
        if (this.defaultReportQueryRedirector == null){
            this.defaultReportQueryRedirector = this.defaultQueryRedirector;
        }
        if (this.defaultInsertObjectQueryRedirector == null){
            this.defaultInsertObjectQueryRedirector = this.defaultQueryRedirector;
        }

        if (this.defaultUpdateObjectQueryRedirector == null){
            this.defaultUpdateObjectQueryRedirector = this.defaultQueryRedirector;
        }
    }

    /**
     * INTERNAL:
     * Initialize the query manager specific to the descriptor type.
     */
    public void initialize(DescriptorQueryManager queryManager, AbstractSession session) {
        //PERF: set read-object query to cache generated SQL.
        if (!queryManager.hasReadObjectQuery()) {
            // Prepare static read object query always.
            ReadObjectQuery readObjectQuery = new ReadObjectQuery();
            readObjectQuery.setSelectionCriteria(getObjectBuilder().getPrimaryKeyExpression());
            queryManager.setReadObjectQuery(readObjectQuery);
        }
        queryManager.getReadObjectQuery().setName("read" + getJavaClass().getSimpleName());

        if (!queryManager.hasInsertQuery()) {
            // Prepare insert query always.
            queryManager.setInsertQuery(new InsertObjectQuery());
        }
        queryManager.getInsertQuery().setModifyRow(getObjectBuilder().buildTemplateInsertRow(session));

        if (!usesFieldLocking()) {
            //do not reset the query if we are using field locking
            if (!queryManager.hasDeleteQuery()) {
                // Prepare delete query always.
                queryManager.setDeleteQuery(new DeleteObjectQuery());
            }
            queryManager.getDeleteQuery().setModifyRow(new DatabaseRecord());
        }

        if (queryManager.hasUpdateQuery()) {
            // Do not prepare to update by default to allow minimal update.
            queryManager.getUpdateQuery().setModifyRow(getObjectBuilder().buildTemplateUpdateRow(session));
        }
    }

    /**
     * INTERNAL:
     * This initialized method is used exclusively for inheritance.  It passes in
     * true if the child descriptor is isolated.
     *
     * This is needed by regular aggregate descriptors (because they require review);
     * but not by SDK aggregate descriptors.
     */
    public void initializeAggregateInheritancePolicy(AbstractSession session) {
        ClassDescriptor parentDescriptor = session.getDescriptor(getInheritancePolicy().getParentClass());
        parentDescriptor.getInheritancePolicy().addChildDescriptor(this);
    }

    /**
     * INTERNAL:
     * Rebuild the multiple table primary key map.
     */
    public void initializeMultipleTablePrimaryKeyFields() {
        int tableSize = getTables().size();
        int additionalTablesSize = tableSize - 1;
        boolean isChild = hasInheritance() && getInheritancePolicy().isChildDescriptor();
        if (isChild) {
            additionalTablesSize = tableSize - getInheritancePolicy().getParentDescriptor().getTables().size();
        }
        if (tableSize <= 1) {
            return;
        }
        ExpressionBuilder builder = new ExpressionBuilder();
        Expression joinExpression = getQueryManager().getMultipleTableJoinExpression();
        for (int index = 1; index < tableSize; index++) {
            DatabaseTable table = getTables().get(index);
            Map<DatabaseField, DatabaseField> oldKeyMapping = getAdditionalTablePrimaryKeyFields().get(table);
            if (oldKeyMapping != null) {
                if (!getQueryManager().hasCustomMultipleTableJoinExpression()) {
                    Expression keyJoinExpression = null;
                    // Build the multiple table join expression resulting from the fk relationships.
                    for (Map.Entry<DatabaseField, DatabaseField> entry : oldKeyMapping.entrySet()) {
                        DatabaseField sourceTableField = entry.getKey();
                        DatabaseField targetTableField = entry.getValue();
                        // Must add this field to read, so translations work on database row, this could be either.
                        if (!getFields().contains(sourceTableField)) {
                            getFields().add(sourceTableField);
                        }
                        if (!getFields().contains(targetTableField)) {
                            getFields().add(targetTableField);
                        }
                        keyJoinExpression = builder.getField(targetTableField).equal(builder.getField(sourceTableField)).and(keyJoinExpression);
                    }
                    if (keyJoinExpression != null) {
                        joinExpression = keyJoinExpression.and(joinExpression);
                    }
                    getQueryManager().getTablesJoinExpressions().put(table, keyJoinExpression);
                }
            } else {
                // If the user has specified a custom multiple table join then we do not assume that the secondary tables have identically named pk as the primary table.
                // No additional fk info was specified so assume the pk field(s) are the named the same in the additional table.
                Map newKeyMapping = new HashMap(getPrimaryKeyFields().size());
                getAdditionalTablePrimaryKeyFields().put(table, newKeyMapping);

                Expression keyJoinExpression = null;
                // For each primary key field in the primary table, add a pk relationship from the primary table's pk field to the assumed identically named secondary pk field.
                for (DatabaseField primaryKeyField : getPrimaryKeyFields()) {
                    DatabaseField secondaryKeyField = primaryKeyField.clone();
                    secondaryKeyField.setTable(table);
                    newKeyMapping.put(primaryKeyField, secondaryKeyField);
                    // Must add this field to read, so translations work on database row.
                    getFields().add(buildField(secondaryKeyField));

                    if (!getQueryManager().hasCustomMultipleTableJoinExpression()) {
                        keyJoinExpression = builder.getField(secondaryKeyField).equal(builder.getField(primaryKeyField)).and(keyJoinExpression);
                    }
                }
                if (keyJoinExpression != null) {
                    joinExpression = keyJoinExpression.and(joinExpression);
                }
                getQueryManager().getTablesJoinExpressions().put(table, keyJoinExpression);
            }
        }
        if (joinExpression != null) {
            getQueryManager().setInternalMultipleTableJoinExpression(joinExpression);
        }
        if (getQueryManager().hasCustomMultipleTableJoinExpression()) {
            Map tablesJoinExpressions = SQLSelectStatement.mapTableToExpression(joinExpression, getTables());
            getQueryManager().getTablesJoinExpressions().putAll(tablesJoinExpressions);
        }
        if (isChild && (additionalTablesSize > 0)) {
            for (int index = tableSize - additionalTablesSize; index < tableSize; index++) {
                DatabaseTable table = getTables().get(index);
                getInheritancePolicy().addChildTableJoinExpressionToAllParents(table, getQueryManager().getTablesJoinExpressions().get(table));
            }
        }
    }

    /**
     * INTERNAL:
     * Initialize the descriptor properties such as write lock and sequencing.
     */
    protected void initializeProperties(AbstractSession session) throws DescriptorException {
        if (!isAggregateDescriptor()) {
            if (!isChildDescriptor()) {
                // Initialize the primary key fields
                for (int index = 0; index < getPrimaryKeyFields().size(); index++) {
                    DatabaseField primaryKey = getPrimaryKeyFields().get(index);
                    primaryKey = buildField(primaryKey);
                    primaryKey.setPrimaryKey(true);
                    getPrimaryKeyFields().set(index, primaryKey);
                }
                List primaryKeyFields = (List)((ArrayList)getPrimaryKeyFields()).clone();
                // Remove non-default table primary key (MW used to set these as pk).
                for (int index = 0; index < primaryKeyFields.size(); index++) {
                    DatabaseField primaryKey = (DatabaseField)primaryKeyFields.get(index);
                    if (!primaryKey.getTable().equals(getDefaultTable())) {
                        getPrimaryKeyFields().remove(primaryKey);
                    }
                }
            }

            // build sequence number field
            if (getSequenceNumberField() != null) {
                setSequenceNumberField(buildField(getSequenceNumberField()));
            }
        }

        // Set the local session name for the session broker.
        setSessionName(session.getName());
    }

    /**
     * INTERNAL:
     * Allow the descriptor to initialize any dependencies on this session.
     */
    public void interfaceInitialization(AbstractSession session) throws DescriptorException {
        if (isInterfaceInitialized(INITIALIZED)) {
            return;
        }

        setInterfaceInitializationStage(INITIALIZED);

        if (isInterfaceChildDescriptor()) {
            for (Iterator<Class<?>> interfaces = getInterfacePolicy().getParentInterfaces().iterator();
                     interfaces.hasNext();) {
                Class<?> parentInterface = interfaces.next();
                ClassDescriptor parentDescriptor = session.getDescriptor(parentInterface);
                parentDescriptor.interfaceInitialization(session);

                if (isDescriptorForInterface()) {
                    setQueryKeys(Helper.concatenateMaps(getQueryKeys(), parentDescriptor.getQueryKeys()));
                } else {
                    //ClassDescriptor is a class, not an interface
                    for (Iterator<String> parentKeys = parentDescriptor.getQueryKeys().keySet().iterator();
                         parentKeys.hasNext();) {
                        String queryKeyName = parentKeys.next();
                        if (!hasQueryKeyOrMapping(queryKeyName)) {
                            //the parent descriptor has a query key not defined in the child
                            session.getIntegrityChecker().handleError(DescriptorException.childDoesNotDefineAbstractQueryKeyOfParent(this, parentDescriptor, queryKeyName));
                        }
                    }
                }

                if (parentDescriptor == this) {
                    return;
                }
            }
        }

        getInterfacePolicy().initialize(session);
    }

    /**
     * INTERNAL:
     * Convenience method to return true if the java class from this descriptor is abstract.
     */
    public boolean isAbstract() {
        return java.lang.reflect.Modifier.isAbstract(getJavaClass().getModifiers());
    }

    /**
     * PUBLIC:
     * Return true if this descriptor is an aggregate collection descriptor
     */
    public boolean isAggregateCollectionDescriptor() {
        return this.descriptorType == AGGREGATE_COLLECTION;
    }

    /**
     * PUBLIC:
     * Return true if this descriptor is an aggregate descriptor
     */
    public boolean isAggregateDescriptor() {
        return this.descriptorType == AGGREGATE;
    }

    /**
     * PUBLIC:
     * Return if the descriptor defines inheritance and is a child.
     */
    public boolean isChildDescriptor() {
        return hasInheritance() && getInheritancePolicy().isChildDescriptor();
    }

    /**
     * PUBLIC:
     * Return if the descriptor maps to an EIS or NoSQL datasource.
     */
    public boolean isEISDescriptor() {
        return false;
    }

    /**
     * PUBLIC:
     * Return if the descriptor maps to an object-relational structured type.
     */
    public boolean isObjectRelationalDataTypeDescriptor() {
        return false;
    }

    /**
     * PUBLIC:
     * Return if the descriptor maps to XML.
     */
    public boolean isXMLDescriptor() {
        return false;
    }

    /**
     * PUBLIC:
     * Return if the descriptor maps to a relational table.
     */
    public boolean isRelationalDescriptor() {
        return false;
    }

    /**
     * PUBLIC:
     * Return if the java class is an interface.
     */
    public boolean isDescriptorForInterface() {
        return this.descriptorType == INTERFACE;
    }

    /**
     * PUBLIC
     * return true if this descriptor is any type of aggregate descriptor.
     */
    public boolean isDescriptorTypeAggregate(){
        return this.descriptorType == AGGREGATE_COLLECTION || this.descriptorType == AGGREGATE;
    }

    /**
     * INTERNAL:
     * return true if this descriptor is an entity.
     * (The descriptor may be a  mappedSuperclass - only in the internal case during metamodel processing)
     */
    public boolean isDescriptorTypeNormal(){
        return this.descriptorType == NORMAL;
    }

    /**
     * INTERNAL:
     * Check if the descriptor is finished initialization.
     */
    public boolean isFullyInitialized() {
        return this.initializationStage == POST_INITIALIZED;
    }

    /**
     * INTERNAL:
     * Check if descriptor is already initialized for the level of initialization.
     * 1 = pre
     * 2 = mapping
     * 3 = post
     */
    protected boolean isInitialized(int initializationStage) {
        return this.initializationStage >= initializationStage;
    }

    /**
     * INTERNAL:
     * Return if the descriptor defines inheritance and is a child.
     */
    public boolean isInterfaceChildDescriptor() {
        return hasInterfacePolicy() && getInterfacePolicy().isInterfaceChildDescriptor();
    }

    /**
     * INTERNAL:
     * Check if interface descriptor is already initialized for the level of initialization.
     * 1 = pre
     * 2 = mapping
     * 3 = post
     */
    protected boolean isInterfaceInitialized(int interfaceInitializationStage) {
        return this.interfaceInitializationStage >= interfaceInitializationStage;
    }

    /**
     * INTERNAL:
     * Return if an error occurred during initialization which should abort any further initialization.
     */
    public boolean isInvalid() {
        return this.initializationStage == ERROR;
    }

    /**
     * PUBLIC:
     * Returns true if the descriptor represents an isolated class
     */
    public boolean isIsolated() {
        return getCachePolicy().isIsolated();
    }

    /**
     * PUBLIC:
     * Returns true if the descriptor represents an isolated class
     */
    public boolean isProtectedIsolation() {
        return getCachePolicy().isProtectedIsolation();
    }

    /**
     * PUBLIC:
     * Returns true if the descriptor represents an isolated class
     */
    public boolean isSharedIsolation() {
        return getCachePolicy().isSharedIsolation();
    }

    /**
     * INTERNAL:
     * Return if this descriptor has more than one table.
     */
    public boolean isMultipleTableDescriptor() {
        return getTables().size() > 1;
    }

    /**
     * INTERNAL:
     * Indicates whether pk or some of its components
     * set after insert into the database.
     * Shouldn't be called before ClassDescriptor has been initialized.
     */
    public boolean isPrimaryKeySetAfterInsert(AbstractSession session) {
        return (usesSequenceNumbers() && getSequence().shouldAcquireValueAfterInsert()) || (hasReturningPolicy() && getReturningPolicy().isUsedToSetPrimaryKey());
    }

    /**
     * ADVANCED:
     * When set to false, this setting will allow the UOW to avoid locking the shared cache instance in order to perform a clone.
     * Caution should be taken as setting this to false may allow cloning of partial updates
     */
    public boolean shouldLockForClone() {
        return this.shouldLockForClone;
    }

    /**
     * INTERNAL:
     * Return if change sets are required for new objects.
     */
    public boolean shouldUseFullChangeSetsForNewObjects() {
        return getCachePolicy().getCacheSynchronizationType() == CachePolicy.SEND_NEW_OBJECTS_WITH_CHANGES || shouldUseFullChangeSetsForNewObjects;
    }

    /**
     * PUBLIC:
     * This method is the equivalent of calling {@link #setShouldOnlyRefreshCacheIfNewerVersion} with an argument of <CODE>true</CODE>:
     * it configures a <CODE>ClassDescriptor</CODE> to only refresh the cache if the data received from the database by a query is newer than
     * the data in the cache (as determined by the optimistic locking field) and as long as one of the following is true:
     *
     * <UL>
     * <LI>the <CODE>ClassDescriptor</CODE> was configured by calling {@link #alwaysRefreshCache} or {@link #alwaysRefreshCacheOnRemote},</LI>
     * <LI>the query was configured by calling {@link org.eclipse.persistence.queries.ObjectLevelReadQuery#refreshIdentityMapResult}, or</LI>
     * <LI>the query was a call to {@link org.eclipse.persistence.sessions.Session#refreshObject}</LI>
     * </UL>
     * <P>
     *
     * However, if a query hits the cache, data is not refreshed regardless of how this setting is configured. For example, by default,
     * when a query for a single object based on its primary key is executed, EclipseLink will first look in the cache for the object.
     * If the object is in the cache, the cached object is returned and data is not refreshed. To avoid cache hits, use
     * the {@link #disableCacheHits} method.<P>
     *
     * Also note that the {@link org.eclipse.persistence.sessions.UnitOfWork} will not refresh its registered objects.
     *
     * @see #dontOnlyRefreshCacheIfNewerVersion
     */
    public void onlyRefreshCacheIfNewerVersion() {
        setShouldOnlyRefreshCacheIfNewerVersion(true);
    }

    /**
     * INTERNAL:
     * Post initializations after mappings are initialized.
     */
    public void postInitialize(AbstractSession session) throws DescriptorException {
        // These cached settings on the project must be set even if descriptor is initialized.
        if (getHistoryPolicy() != null) {
            session.getProject().setHasGenericHistorySupport(true);
        }

        // Avoid repetitive initialization (this does not solve loops)
        if (isInitialized(POST_INITIALIZED) || isInvalid()) {
            return;
        }

        setInitializationStage(POST_INITIALIZED);

        // Make sure that child is post initialized,
        // this initialize bottom up, unlike the two other phases that to top down.
        if (hasInheritance()) {
            for (ClassDescriptor child : getInheritancePolicy().getChildDescriptors()) {
                child.postInitialize(session);
            }
        }

        // Allow mapping to perform post initialization.
        for (DatabaseMapping mapping : getMappings()) {
            // This causes post init to be called multiple times in inheritance.
            mapping.postInitialize(session);
            // PERF: computed if deferred locking is required.
            if (!shouldAcquireCascadedLocks()) {
                if (mapping.isForeignReferenceMapping()){
                    if (!((ForeignReferenceMapping)mapping).usesIndirection()){
                        setShouldAcquireCascadedLocks(true);
                    }
                    hasRelationships = true;
                }
                if ((mapping instanceof AggregateObjectMapping)){
                    if (mapping.getReferenceDescriptor().shouldAcquireCascadedLocks()) {
                        setShouldAcquireCascadedLocks(true);
                    }
                    if (mapping.getReferenceDescriptor().hasRelationships()){
                        hasRelationships = true;
                    }
                }
            }
            if (getCachePolicy().isProtectedIsolation() &&
                    ((mapping.isForeignReferenceMapping() && !mapping.isCacheable())
                    || (mapping.isAggregateObjectMapping() && mapping.getReferenceDescriptor().hasNoncacheableMappings()))) {
                mapping.collectQueryParameters(this.foreignKeyValuesForCaching);
            }
            if (mapping.isLockableMapping()){
                getLockableMappings().add(mapping);
            }


        }

        if (hasInheritance()) {
            getInheritancePolicy().postInitialize(session);
        }

        //PERF: Ensure that the identical primary key fields are used to avoid equals.
        for (int index = (getPrimaryKeyFields().size() - 1); index >= 0; index--) {
            DatabaseField primaryKeyField = getPrimaryKeyFields().get(index);
            int fieldIndex = getFields().indexOf(primaryKeyField);

            // Aggregate/agg-collections may not have a mapping for pk field.
            if (fieldIndex != -1) {
                primaryKeyField = getFields().get(fieldIndex);
                getPrimaryKeyFields().set(index, primaryKeyField);
                primaryKeyField.setPrimaryKey(true);
            }
        }

        // List of fields selected by a query that uses SOP when descriptor has SOP. Used to index these fields.
        List<DatabaseField> sopSelectionFields = null;
        if (hasSerializedObjectPolicy()) {
            getSerializedObjectPolicy().postInitialize(session);
            this.selectionFields = (List<DatabaseField>)getFields().clone();
            this.selectionFields.remove(getSerializedObjectPolicy().getField());
            this.allSelectionFields = (List<DatabaseField>)getAllFields().clone();
            this.allSelectionFields.remove(getSerializedObjectPolicy().getField());
            sopSelectionFields = getSerializedObjectPolicy().getSelectionFields();
            if (sopSelectionFields.size() == getFields().size()) {
                // no need for sop field indexes - SOP uses all the field in the descriptor
                sopSelectionFields = null;
            }
        } else {
            this.selectionFields = getFields();
            this.allSelectionFields = getAllFields();
        }

        // Index and classify fields and primary key.
        // This is in post because it needs field classification defined in initializeMapping
        // this can come through a 1:1 so requires all descriptors to be initialized (mappings).
        // May 02, 2000 - Jon D.
        for (int index = 0; index < getFields().size(); index++) {
            DatabaseField field = getFields().elementAt(index);
            if (field.getType() == null){
                DatabaseMapping mapping = getObjectBuilder().getMappingForField(field);
                if (mapping != null) {
                    field.setType(mapping.getFieldClassification(field));
                }
            }
            // LOB may require lob writer which needs full row to fetch LOB.
            if ((field.getType() == ClassConstants.BLOB) || (field.getType() == ClassConstants.CLOB)) {
                setHasMultipleTableConstraintDependecy(true);
            }
            field.setIndex(index);
            if (sopSelectionFields != null) {
                int sopFieldIndex = sopSelectionFields.indexOf(field);
                if (sopFieldIndex != -1) {
                    field.setIndex(sopFieldIndex);
                }
            }
        }

        // EL Bug 426500 - When a mapping has built its selection criteria early with partially
        // initialized fields, post-initialize any source and target Expression fields.
        for (DatabaseMapping mapping : getMappings()) {
            mapping.postInitializeSourceAndTargetExpressions();
        }

        // Set cache key type.
        if (getCachePolicy().getCacheKeyType() == null || (getCachePolicy().getCacheKeyType() == CacheKeyType.AUTO)) {
            if ((getPrimaryKeyFields().size() > 1) || getObjectBuilder().isXMLObjectBuilder()) {
                setCacheKeyType(CacheKeyType.CACHE_ID);
            } else if ((getPrimaryKeyFields().size() == 1) && (getObjectBuilder().getPrimaryKeyClassifications().size() == 1)) {
                Class<?> type = getObjectBuilder().getPrimaryKeyClassifications().get(0);
                if ((type == null) || type.isArray()) {
                    getCachePolicy().setCacheKeyType(CacheKeyType.CACHE_ID);
                } else {
                    getCachePolicy().setCacheKeyType(CacheKeyType.ID_VALUE);
                }
            } else {
                getCachePolicy().setCacheKeyType(CacheKeyType.CACHE_ID);
            }
        } else if ((getCachePolicy().getCacheKeyType() == CacheKeyType.ID_VALUE) && (getPrimaryKeyFields().size() > 1)) {
            session.getIntegrityChecker().handleError(DescriptorException.cannotUseIdValueForCompositeId(this));
        }
        if (hasFetchGroupManager()) {
            getFetchGroupManager().postInitialize(session);
        }
        getObjectBuilder().postInitialize(session);
        getQueryManager().postInitialize(session);

        // Post initialize the multitenant policy after the query manager.
        if (hasMultitenantPolicy()) {
            getMultitenantPolicy().postInitialize(session);
        }

        getCachePolicy().postInitialize(this, session);

        postInitializeReturningPolicies();

        validateAfterInitialization(session);

        checkDatabase(session);
    }

    private void postInitializeReturningPolicies() {
        //Initialize ReturningPolicies
        List<ReturningPolicy> returningPolicies = new ArrayList<>();
        if (this.hasReturningPolicy()) {
            returningPolicies.add(this.getReturningPolicy());
        }
        browseReturningPolicies(returningPolicies, this.getMappings());
        if (returningPolicies.size() > 0) {
            this.returningPolicies = returningPolicies;
            prepareReturnFields(returningPolicies);
        }
    }

    private void browseReturningPolicies(List<ReturningPolicy> returningPolicies, Vector<DatabaseMapping> mappings) {
        for (DatabaseMapping databaseMapping :mappings) {
            if (databaseMapping instanceof AggregateObjectMapping) {
                ClassDescriptor referenceDescriptor = databaseMapping.getReferenceDescriptor();
                if (referenceDescriptor != null) {
                    browseReturningPolicies(returningPolicies, referenceDescriptor.getMappings());
                    if (referenceDescriptor.hasReturningPolicy()) {
                        returningPolicies.add(referenceDescriptor.getReturningPolicy());
                    }
                }
            }
        }
    }

    private void prepareReturnFields(List<ReturningPolicy> returningPolicies) {
        Vector<DatabaseField> returnFieldsInsert = new NonSynchronizedVector<>();
        Vector<DatabaseField> returnFieldsUpdate = new NonSynchronizedVector<>();
        List<DatabaseField> returnFieldsToMergeInsert = new ArrayList<>();
        List<DatabaseField> returnFieldsToMergeUpdate = new ArrayList<>();
        Collection<DatabaseField> tmpFields;
        for (ReturningPolicy returningPolicy: returningPolicies) {
            tmpFields = returningPolicy.getFieldsToGenerateInsert(this.defaultTable);
            if (tmpFields != null) {
                returnFieldsInsert.addAll(tmpFields);
            }
            tmpFields = returningPolicy.getFieldsToGenerateUpdate(this.defaultTable);
            if (tmpFields != null) {
                returnFieldsUpdate.addAll(tmpFields);
            }
            tmpFields = returningPolicy.getFieldsToMergeInsert();
            if (tmpFields != null) {
                returnFieldsToMergeInsert.addAll(tmpFields);
            }
            tmpFields = returningPolicy.getFieldsToMergeUpdate();
            if (tmpFields != null) {
                returnFieldsToMergeUpdate.addAll(tmpFields);
            }
        }
        this.returnFieldsToGenerateInsert = (returnFieldsInsert.isEmpty()) ? null : returnFieldsInsert;
        this.returnFieldsToGenerateUpdate = (returnFieldsUpdate.isEmpty()) ? null : returnFieldsUpdate;
        this.returnFieldsToMergeInsert = (returnFieldsToMergeInsert.isEmpty()) ? null : returnFieldsToMergeInsert;
        this.returnFieldsToMergeUpdate = (returnFieldsToMergeUpdate.isEmpty()) ? null : returnFieldsToMergeUpdate;
    }

    /**
     * INTERNAL:
     * Configure all descriptors referencing this class to be protected and update their cache settings.
     */
    public void notifyReferencingDescriptorsOfIsolation(AbstractSession session) {
        for (ClassDescriptor descriptor : this.referencingClasses){
            if (descriptor.getCachePolicy().getCacheIsolation() == null || descriptor.getCachePolicy().getCacheIsolation() == CacheIsolationType.SHARED) {
                descriptor.getCachePolicy().setCacheIsolation(CacheIsolationType.PROTECTED);
                descriptor.getCachePolicy().postInitialize(descriptor, session);
                for (DatabaseMapping mapping : descriptor.getMappings()) {
                    if (mapping.isAggregateMapping() && (mapping.getReferenceDescriptor() != null)) {
                        mapping.getReferenceDescriptor().getCachePolicy().setCacheIsolation(CacheIsolationType.PROTECTED);
                    }
                }
            }
        }
    }

    /**
     * INTERNAL:
     * Allow the descriptor to initialize any dependencies on this session.
     */
    public void preInitialize(AbstractSession session) throws DescriptorException {
        // Avoid repetitive initialization (this does not solve loops)
        if (isInitialized(PREINITIALIZED)) {
            return;
        }
        setInitializationStage(PREINITIALIZED);

        assignDefaultValues(session);

        if (this.isCascadeOnDeleteSetOnDatabaseOnSecondaryTables && !session.getPlatform().supportsDeleteOnCascade()) {
            this.isCascadeOnDeleteSetOnDatabaseOnSecondaryTables = false;
        }
        // Set the fetchgroup manager is the class implements the tracking interface.
        if (FetchGroupTracker.class.isAssignableFrom(getJavaClass())) {
            if (getFetchGroupManager() == null && !isAggregateDescriptor()) {
                //aggregate descriptors will set fetchgroupmanager during mapping init.
                setFetchGroupManager(new FetchGroupManager());
            }
        }
        // PERF: Check if the class "itself" was weaved.
        // If weaved avoid reflection, use clone copy and empty new.
        if (Arrays.asList(getJavaClass().getInterfaces()).contains(PersistenceObject.class)) {
            // Cloning is only auto set for field access, as method access
            // may not have simple fields, same with empty new and reflection get/set.
            boolean isMethodAccess = false;
            for (Iterator<DatabaseMapping> iterator = getMappings().iterator(); iterator.hasNext(); ) {
                DatabaseMapping mapping = iterator.next();
                if (mapping.isUsingMethodAccess()) {
                    // Ok for lazy 1-1s
                    if (!mapping.isOneToOneMapping() || !((ForeignReferenceMapping)mapping).usesIndirection()) {
                        isMethodAccess = true;
                    }
                } else if (!mapping.isWriteOnly()) {
                    // Avoid reflection.
                    mapping.setAttributeAccessor(new PersistenceObjectAttributeAccessor(mapping.getAttributeName()));
                }
            }
            if (!isMethodAccess) {
                if (this.copyPolicy == null) {
                    setCopyPolicy(new PersistenceEntityCopyPolicy());
                }
                if (!isAbstract()) {
                    try {
                        if (this.instantiationPolicy == null) {
                            setInstantiationPolicy(new PersistenceObjectInstantiationPolicy((PersistenceObject)getJavaClass().getConstructor().newInstance()));
                        }
                    } catch (Exception ignore) { }
                }
            }
        }

        // 4924665 Check for spaces in table names, and add the appropriate quote character
        Iterator<DatabaseTable> tables = this.getTables().iterator();
        while(tables.hasNext()) {
            DatabaseTable next = tables.next();
            if(next.getName().indexOf(' ') != -1) {
                // EL Bug 382420 - set use delimiters to true if table name contains a space
                next.setUseDelimiters(true);
            }
        }

        // Allow mapping pre init, must be done before validate.
        for (DatabaseMapping mapping : getMappings()) {
            try {
                mapping.preInitialize(session);
            } catch (DescriptorException exception) {
                session.getIntegrityChecker().handleError(exception);
            }
        }

        validateBeforeInitialization(session);

        preInitializeInheritancePolicy(session);

        // Make sure that parent is already preinitialized
        if (hasInheritance()) {
            // The default table will be set in this call once the duplicate
            // tables have been removed.
            getInheritancePolicy().preInitialize(session);
        } else {
            // This must be done now, after validate, before init anything else.
            setInternalDefaultTable();
        }

        // Once the table and mapping information has been settled, we'll need
        // to set tenant id fields on the descriptor for each table. These are
        // at least used for DDL generation. Doesn't seem to interfere or
        // duplicate anything else we have done to support tenant id fields.
        if (hasMultitenantPolicy()) {
            getMultitenantPolicy().preInitialize(session);
        }

        verifyTableQualifiers(session.getDatasourcePlatform());
        initializeProperties(session);
        if (!isAggregateDescriptor()) {
            // Adjust before you initialize ...
            adjustMultipleTableInsertOrder();
            initializeMultipleTablePrimaryKeyFields();
        }

        if (hasInterfacePolicy()) {
            preInterfaceInitialization(session);
        }

        getQueryManager().preInitialize(session);

    }

    /**
     * INTERNAL:
     */
    protected void prepareCascadeLockingPolicy(DatabaseMapping mapping) {
        if (mapping.isPrivateOwned() && mapping.isForeignReferenceMapping()) {
            if (mapping.isCascadedLockingSupported()) {
                // Even if the mapping says it is supported in general, there
                // may be conditions where it is not. Need the following checks.
                if (((ForeignReferenceMapping)mapping).hasCustomSelectionQuery()) {
                    throw ValidationException.unsupportedCascadeLockingMappingWithCustomQuery(mapping);
                } else if (isDescriptorTypeAggregate()) {
                    throw ValidationException.unsupportedCascadeLockingDescriptor(this);
                } else {
                    mapping.prepareCascadeLockingPolicy();
                }
            } else {
                throw ValidationException.unsupportedCascadeLockingMapping(mapping);
            }
        }
    }

    /**
     * Hook together the inheritance policy tree.
     */
    protected void preInitializeInheritancePolicy(AbstractSession session) throws DescriptorException {
        if (isChildDescriptor() && (requiresInitialization(session))) {
            if (getInheritancePolicy().getParentClass().equals(getJavaClass())) {
                setInterfaceInitializationStage(ERROR);
                throw DescriptorException.parentClassIsSelf(this);
            }
            ClassDescriptor parentDescriptor = session.getDescriptor(getInheritancePolicy().getParentClass());
            parentDescriptor.getInheritancePolicy().addChildDescriptor(this);
            getInheritancePolicy().setParentDescriptor(parentDescriptor);
            parentDescriptor.preInitialize(session);
        }
    }

    /**
     * INTERNAL:
     * Allow the descriptor to initialize any dependencies on this session.
     */
    public void preInterfaceInitialization(AbstractSession session) throws DescriptorException {
        if (isInterfaceInitialized(PREINITIALIZED)) {
            return;
        }

        setInterfaceInitializationStage(PREINITIALIZED);

        assignDefaultValues(session);

        if (isInterfaceChildDescriptor()) {
            for (Iterator<Class<?>> interfaces = getInterfacePolicy().getParentInterfaces().iterator();
                     interfaces.hasNext();) {
                Class<?> parentInterface = interfaces.next();
                ClassDescriptor parentDescriptor = session.getDescriptor(parentInterface);
                if ((parentDescriptor == null) || (parentDescriptor.getJavaClass() == getJavaClass()) || parentDescriptor.getInterfacePolicy().usesImplementorDescriptor()) {
                    session.getProject().getDescriptors().put(parentInterface, this);
                    session.clearLastDescriptorAccessed();
                } else if (!parentDescriptor.isDescriptorForInterface()) {
                    throw DescriptorException.descriptorForInterfaceIsMissing(parentInterface.getName());
                } else {
                    parentDescriptor.preInterfaceInitialization(session);
                    parentDescriptor.getInterfacePolicy().addChildDescriptor(this);
                    getInterfacePolicy().addParentDescriptor(parentDescriptor);
                }
            }
        }
    }

    /**
     * INTERNAL:
     * Rehash any hashtables based on fields.
     * This is used to clone descriptors for aggregates, which hammer field names,
     * it is probably better not to hammer the field name and this should be refactored.
     */
    public void rehashFieldDependancies(AbstractSession session) {
        getObjectBuilder().rehashFieldDependancies(session);

        for (Enumeration<DatabaseMapping> enumtr = getMappings().elements(); enumtr.hasMoreElements();) {
            enumtr.nextElement().rehashFieldDependancies(session);
        }
    }

    /**
     * INTERNAL:
     * A user should not be setting which attributes to join or not to join
     * after descriptor initialization; provided only for backwards compatibility.
     */
    public void reInitializeJoinedAttributes() {
        if (!isInitialized(POST_INITIALIZED)) {
            // wait until the descriptor gets initialized first
            return;
        }
        getObjectBuilder().initializeJoinedAttributes();
        if (hasInheritance()) {
            for (ClassDescriptor child : getInheritancePolicy().getChildDescriptors()) {
                child.reInitializeJoinedAttributes();
            }
        }
    }

    /**
     * INTERNAL:
     * Used to initialize a remote descriptor.
     */
    public void remoteInitialization(DistributedSession session) {
        // These cached settings on the project must be set even if descriptor is initialized.
        if (getHistoryPolicy() != null) {
            session.getProject().setHasGenericHistorySupport(true);
        }

        // Record that there is an isolated class in the project.
        if (!getCachePolicy().isSharedIsolation()) {
            session.getProject().setHasIsolatedClasses(true);
        }
        if (!getCachePolicy().shouldIsolateObjectsInUnitOfWork() && !shouldBeReadOnly()) {
            session.getProject().setHasNonIsolatedUOWClasses(true);
        }

        for (DatabaseMapping mapping : getMappings()) {
            mapping.remoteInitialization(session);
        }

        getEventManager().remoteInitialization(session);
        getInstantiationPolicy().initialize(session);
        getCopyPolicy().initialize(session);

        if (hasInheritance()) {
            getInheritancePolicy().remoteInitialization(session);
        }

        if (getCMPPolicy() != null) {
            getCMPPolicy().remoteInitialize(this, session);
        }
    }

    /**
     * PUBLIC:
     * Remove the user defined property.
     */
    public void removeProperty(String property) {
        getProperties().remove(property);
    }

    /**
     * INTERNAL:
     * Aggregate and Interface descriptors do not require initialization as they are cloned and
     * initialized by each mapping. Descriptors with table per tenant policies are cloned per
     * client session (per tenant) so do not initialize the original descriptor.
     */
    public boolean requiresInitialization(AbstractSession session) {
        // If we are an aggregate or interface descriptor we do not require initialization.
        if (isDescriptorTypeAggregate() || isDescriptorForInterface()) {
            return false;
        }

        // If we have a table per tenant policy then check for our tenant
        // context property. If it is available from the session, set it and
        // return true to initialize. Otherwise do not initialize the
        // descriptor (it will be initialized per client session).
        if (hasTablePerMultitenantPolicy()) {
            return ((TablePerMultitenantPolicy) getMultitenantPolicy()).shouldInitialize(session);
        }

        // By default it should be initialized.
        return true;
    }

    /**
     * INTERNAL:
     * Validate that the descriptor was defined correctly.
     * This allows for checks to be done that require the descriptor initialization to be completed.
     */
    protected void selfValidationAfterInitialization(AbstractSession session) throws DescriptorException {
        // This has to be done after, because read subclasses must be initialized.
        if ( (hasInheritance() && (getInheritancePolicy().shouldReadSubclasses() || isAbstract())) || hasTablePerClassPolicy() && isAbstract() ) {
            // Avoid building a new instance if the inheritance class is abstract.
            // There is an empty statement here, and this was done if anything for the
            // readability sake of the statement logic.
        } else if (session.getIntegrityChecker().shouldCheckInstantiationPolicy()) {
            getInstantiationPolicy().buildNewInstance();
        }

        if (hasReturningPolicy()) {
            getReturningPolicy().validationAfterDescriptorInitialization(session);
        }
        getObjectBuilder().validate(session);
    }

    /**
     * INTERNAL:
     * Validate that the descriptor's non-mapping attribute are defined correctly.
     */
    protected void selfValidationBeforeInitialization(AbstractSession session) throws DescriptorException {
        if (isChildDescriptor()) {
            ClassDescriptor parentDescriptor = session.getDescriptor(getInheritancePolicy().getParentClass());

            if (parentDescriptor == null) {
                session.getIntegrityChecker().handleError(DescriptorException.parentDescriptorNotSpecified(getInheritancePolicy().getParentClass().getName(), this));
            }
        } else {
            if (getTables().isEmpty() && (!isAggregateDescriptor())) {
                session.getIntegrityChecker().handleError(DescriptorException.tableNotSpecified(this));
            }
        }

        if (!isChildDescriptor() && !isDescriptorTypeAggregate()) {
            if (getPrimaryKeyFieldNames().isEmpty()) {
                session.getIntegrityChecker().handleError(DescriptorException.primaryKeyFieldsNotSepcified(this));
            }
        }

        if ((ClassConstants.NoIdentityMap_Class.equals(getIdentityMapClass())) && (getQueryManager().getDoesExistQuery().shouldCheckCacheForDoesExist())) {
            session.getIntegrityChecker().handleError(DescriptorException.identityMapNotSpecified(this));
        }

        if (((getSequenceNumberName() != null) && (getSequenceNumberField() == null)) || ((getSequenceNumberName() == null) && (getSequenceNumberField() != null))) {
            session.getIntegrityChecker().handleError(DescriptorException.sequenceNumberPropertyNotSpecified(this));
        }
    }

    /**
     * INTERNAL:
     * This is used to map the primary key field names in a multiple table
     * descriptor.
     */
    protected void setAdditionalTablePrimaryKeyFields(DatabaseTable table, DatabaseField field1, DatabaseField field2) {
        Map<DatabaseField, DatabaseField> tableAdditionalPKFields = getAdditionalTablePrimaryKeyFields().get(table);

        if (tableAdditionalPKFields == null) {
            tableAdditionalPKFields = new HashMap(2);
            getAdditionalTablePrimaryKeyFields().put(table, tableAdditionalPKFields);
        }

        tableAdditionalPKFields.put(field1, field2);
    }

    /**
     * INTERNAL:
     * Eclipselink needs additionalTablePKFields entries to be associated with tables other than the main (getTables.get(0)) one.
     * Also in case of two non-main tables additionalTablePKFields entry should be associated with the one
     * father down insert order.
     */
    protected void toggleAdditionalTablePrimaryKeyFields() {
        if(additionalTablePrimaryKeyFields == null) {
            // nothing to do
            return;
        }

        // nProcessedTables is a number of tables (first in egtTables() order) that don't require toggle - to, but may be toggled - from
        // (meaning by "toggle - to" table:    setAdditionalTablePrimaryKeyFields(table, .., ..);)
        // "Processed" tables always include the main table (getTables().get(0)) plus all the inherited tables.
        // Don't toggle between processed tables (that has been already done by the parent);
        // always toggle from processed to non-processed;
        // toggle between two non-processed to the one that is father down insert order.
        int nProcessedTables = 1;
        if (isChildDescriptor()) {
            nProcessedTables = getInheritancePolicy().getParentDescriptor().getTables().size();
            // if this is multiple table inheritance, we should include the table for this child in the processed tables
            if (getTables().size() > nProcessedTables){
                nProcessedTables++;
            }
        }

        // cache the original map in a new variable
        Map<DatabaseTable, Map<DatabaseField, DatabaseField>> additionalTablePrimaryKeyFieldsOld = additionalTablePrimaryKeyFields;
        // nullify the original map variable - it will be re-created from scratch
        additionalTablePrimaryKeyFields = null;
        Iterator<Map.Entry<DatabaseTable, Map<DatabaseField, DatabaseField>>> itTable = additionalTablePrimaryKeyFieldsOld.entrySet().iterator();
        // loop through the cached original map and add all its entries (either toggled or unchanged) to the re-created map
        while(itTable.hasNext()) {
            Map.Entry<DatabaseTable, Map<DatabaseField, DatabaseField>> entryTable = itTable.next();
            DatabaseTable sourceTable = entryTable.getKey();
            boolean isSourceProcessed = getTables().indexOf(sourceTable) < nProcessedTables;
            int sourceInsertOrderIndex = getMultipleTableInsertOrder().indexOf(sourceTable);
            Map<DatabaseField, DatabaseField> targetTableAdditionalPKFields = entryTable.getValue();
            Iterator<Map.Entry<DatabaseField, DatabaseField>> itField = targetTableAdditionalPKFields.entrySet().iterator();
            while(itField.hasNext()) {
                Map.Entry<DatabaseField, DatabaseField> entryField = itField.next();
                DatabaseField targetField = entryField.getKey();
                DatabaseField sourceField = entryField.getValue();
                DatabaseTable targetTable = targetField.getTable();
                boolean isTargetProcessed = getTables().indexOf(targetTable) < nProcessedTables;
                int targetInsertOrderIndex = getMultipleTableInsertOrder().indexOf(targetTable);
                // add the entry to the map
                if(!isTargetProcessed && (isSourceProcessed || (sourceInsertOrderIndex > targetInsertOrderIndex))) {
                    // source and target toggled
                    setAdditionalTablePrimaryKeyFields(targetTable, sourceField, targetField);
                } else {
                    // exactly the same as in the original map
                    setAdditionalTablePrimaryKeyFields(sourceTable, targetField, sourceField);
                }
            }
        }
    }

    /**
     * INTERNAL:
     * This is used to map the primary key field names in a multiple table
     * descriptor.
     */
    public void setAdditionalTablePrimaryKeyFields(Map<DatabaseTable, Map<DatabaseField, DatabaseField>> additionalTablePrimaryKeyFields) {
        this.additionalTablePrimaryKeyFields = additionalTablePrimaryKeyFields;
    }

    /**
     * PUBLIC:
     * Set the alias
     */
    public void setAlias(String alias) {
        this.alias = alias;
    }

    /**
     * INTERNAL:
     * Set all the fields.
     */
    protected void setAllFields(Vector<DatabaseField> allFields) {
        this.allFields = allFields;
    }

    /**
     * PUBLIC:
     * Set the amendment class.
     * The amendment method will be called on the class before initialization to allow for it to initialize the descriptor.
     * The method must be a public static method on the class.
     */
    public void setAmendmentClass(Class<?> amendmentClass) {
        this.amendmentClass = amendmentClass;
    }

    /**
     * INTERNAL:
     * Return the amendment class name, used by the MW.
     */
    public void setAmendmentClassName(String amendmentClassName) {
        this.amendmentClassName = amendmentClassName;
    }

    /**
     * PUBLIC:
     * Set the amendment method.
     * This will be called on the amendment class before initialization to allow for it to initialize the descriptor.
     * The method must be a public static method on the class.
     */
    public void setAmendmentMethodName(String amendmentMethodName) {
        this.amendmentMethodName = amendmentMethodName;
    }

    /**
     * @param accessorTree the accessorTree to set
     */
    public void setAccessorTree(List<AttributeAccessor> accessorTree) {
        this.accessorTree = accessorTree;
    }

    /**
     * PUBLIC:
     * Set the type of cache synchronization that will be used on objects of this type.  Possible values
     * are:
     * SEND_OBJECT_CHANGES
     * INVALIDATE_CHANGED_OBJECTS
     * SEND_NEW_OBJECTS_WITH_CHANGES
     * DO_NOT_SEND_CHANGES
     * Note: Cache Synchronization type cannot be altered for descriptors that are set as isolated using
     * the setIsIsolated method.
     * @param type int  The synchronization type for this descriptor
     *
     */
    public void setCacheSynchronizationType(int type) {
        getCachePolicy().setCacheSynchronizationType(type);
    }

    /**
     * PUBLIC:
     * Set the ObjectChangePolicy for this descriptor.
     */
    public void setObjectChangePolicy(ObjectChangePolicy policy) {
        this.changePolicy = policy;
    }

    /**
     * PUBLIC:
     * Set the HistoryPolicy for this descriptor.
     */
    public void setHistoryPolicy(HistoryPolicy policy) {
        this.historyPolicy = policy;
        if (policy != null) {
            policy.setDescriptor(this);
        }
    }

    /**
     * PUBLIC:
     * A CacheInterceptor is an adaptor that when overridden and assigned to a Descriptor all interaction
     * between EclipseLink and the internal cache for that class will pass through the Interceptor.
     * Advanced users could use this interceptor to audit, profile or log cache access.  This Interceptor
     * could also be used to redirect or augment the TopLink cache with an alternate cache mechanism.
     * EclipseLink's configurated IdentityMaps will be passed to the Interceptor constructor.

     * As with IdentityMaps an entire class inheritance hierarchy will share the same interceptor.
     * @see org.eclipse.persistence.sessions.interceptors.CacheInterceptor
     */
    public void setCacheInterceptorClass(Class<? extends CacheInterceptor> cacheInterceptorClass) {
        getCachePolicy().setCacheInterceptorClass(cacheInterceptorClass);
    }

    /**
     * PUBLIC:
     * A CacheInterceptor is an adaptor that when overridden and assigned to a Descriptor all interaction
     * between EclipseLink and the internal cache for that class will pass through the Interceptor.
     * Advanced users could use this interceptor to audit, profile or log cache access.  This Interceptor
     * could also be used to redirect or augment the TopLink cache with an alternate cache mechanism.
     * EclipseLink's configurated IdentityMaps will be passed to the Interceptor constructor.

     * As with IdentityMaps an entire class inheritance hierarchy will share the same interceptor.
     * @see org.eclipse.persistence.sessions.interceptors.CacheInterceptor
     */
    public void setCacheInterceptorClassName(String cacheInterceptorClassName) {
        getCachePolicy().setCacheInterceptorClassName(cacheInterceptorClassName);
    }

    /**
     * PUBLIC:
     * Set the Cache Invalidation Policy for this descriptor.
     * @see org.eclipse.persistence.descriptors.invalidation.CacheInvalidationPolicy
     */
    public void setCacheInvalidationPolicy(CacheInvalidationPolicy policy) {
        cacheInvalidationPolicy = policy;
    }

    /**
     * ADVANCED:
     *  automatically orders database access through the foreign key information provided in 1:1 and 1:m mappings.
     * In some case when 1:1 are not defined it may be required to tell the descriptor about a constraint,
     * this defines that this descriptor has a foreign key constraint to another class and must be inserted after
     * instances of the other class.
     */
    public void setConstraintDependencies(Vector constraintDependencies) {
        this.constraintDependencies = constraintDependencies;
    }

    /**
     * INTERNAL:
     * Set the copy policy.
     * This would be 'protected' but the EJB stuff in another
     * package needs it to be public
     */
    public void setCopyPolicy(CopyPolicy policy) {
        copyPolicy = policy;
        if (policy != null) {
            policy.setDescriptor(this);
        }
    }

    /**
     * INTERNAL:
     * Sets the name of a Class that implements CopyPolicy
     * Will be instantiatied as a copy policy at initialization times
     * using the no-args constructor
     */
    public void setCopyPolicyClassName(String className) {
        copyPolicyClassName = className;
    }

    /**
     * INTERNAL:
     * The descriptors default table can be configured if the first table is not desired.
     */
    public void setDefaultTable(DatabaseTable defaultTable) {
        this.defaultTable = defaultTable;
    }

    /**
     * PUBLIC:
     * The descriptors default table can be configured if the first table is not desired.
     */
    public void setDefaultTableName(String defaultTableName) {
        setDefaultTable(new DatabaseTable(defaultTableName));
    }

    /**
     * INTERNAL:
     * Sets the JPA DescriptorCustomizer class name.
     * DescriptorCustomizer is the JPA equivalent of an amendment method.
     */
    public void setDescriptorCustomizerClassName(String descriptorCustomizerClassName) {
        this.descriptorCustomizerClassName = descriptorCustomizerClassName;
    }

    /**
     * ADVANCED:
     * set the descriptor type (NORMAL by default, others include INTERFACE, AGGREGATE, AGGREGATE COLLECTION)
     */
    public void setDescriptorType(int descriptorType) {
        this.descriptorType = descriptorType;
    }

    /**
     * INTERNAL:
     * This method is explicitly used by the XML reader.
     */
    public void setDescriptorTypeValue(String value) {
        if (value.equals("Aggregate collection")) {
            descriptorIsAggregateCollection();
        } else if (value.equals("Aggregate")) {
            descriptorIsAggregate();
        } else if (value.equals("Interface")) {
            descriptorIsForInterface();
        } else {
            descriptorIsNormal();
        }
    }


    /**
     * INTERNAL:
     * Set the event manager for the descriptor.  The event manager is responsible
     * for managing the pre/post selectors.
     */
    @Override
    public void setEventManager(DescriptorEventManager eventManager) {
        this.eventManager = eventManager;
        if (eventManager != null) {
            eventManager.setDescriptor(this);
        }
    }

    /**
     * INTERNAL:
     * OBSOLETE - old reader.
     * This method is explicitly used by the Builder only.
     */
    public void setExistenceChecking(String token) throws DescriptorException {
        getQueryManager().setExistenceCheck(token);
    }

    /**
     * INTERNAL:
     * Set the fields used by this descriptor.
     */
    public void setFields(Vector<DatabaseField> fields) {
        this.fields = fields;
    }

    /**
     * INTERNAL:
     * This method is used by the  XML Deployment ClassDescriptor to read and write these mappings
     */
    public void setForeignKeyFieldNamesForMultipleTable(List<Association> associations) throws DescriptorException {
        for (Association association: associations) {
            addForeignKeyFieldNameForMultipleTable((String) association.getKey(), (String) association.getValue());
        }
    }

    /**
     * @param fullyMergeEntity the fullyMergeEntity to set
     */
    public void setFullyMergeEntity(boolean fullyMergeEntity) {
        getCachePolicy().setFullyMergeEntity(fullyMergeEntity);
    }

    /**
     * PUBLIC:
     * Set the class of identity map to be used by this descriptor.
     * The default is the "FullIdentityMap".
     */
    public void setIdentityMapClass(Class<? extends IdentityMap> theIdentityMapClass) {
        getCachePolicy().setIdentityMapClass(theIdentityMapClass);
    }

    /**
     * PUBLIC:
     * Set the size of the identity map to be used by this descriptor.
     * The default is the 100.
     */
    public void setIdentityMapSize(int identityMapSize) {
        getCachePolicy().setIdentityMapSize(identityMapSize);
    }

    /**
     * INTERNAL:
     * Sets the inheritance policy.
     */
    @Override
    public void setInheritancePolicy(InheritancePolicy inheritancePolicy) {
        this.inheritancePolicy = inheritancePolicy;
        if (inheritancePolicy != null) {
            inheritancePolicy.setDescriptor(this);
        }
    }

    /**
     * PUBLIC:
     * Sets the returning policy.
     */
    public void setReturningPolicy(ReturningPolicy returningPolicy) {
        this.returningPolicy = returningPolicy;
        if (returningPolicy != null) {
            returningPolicy.setDescriptor(this);
        }
    }

    /**
     * INTERNAL:
     */
    protected void setInitializationStage(int initializationStage) {
        this.initializationStage = initializationStage;
    }

    /**
     * INTERNAL:
     * Sets the instantiation policy.
     */
    @Override
    public void setInstantiationPolicy(InstantiationPolicy instantiationPolicy) {
        this.instantiationPolicy = instantiationPolicy;
        if (instantiationPolicy != null) {
            instantiationPolicy.setDescriptor(this);
        }
    }

    /**
     * INTERNAL:
     */
    protected void setInterfaceInitializationStage(int interfaceInitializationStage) {
        this.interfaceInitializationStage = interfaceInitializationStage;
    }

    /**
     * INTERNAL:
     * Sets the interface policy.
     */
    public void setInterfacePolicy(InterfacePolicy interfacePolicy) {
        this.interfacePolicy = interfacePolicy;
        if (interfacePolicy != null) {
            interfacePolicy.setDescriptor(this);
        }
    }

    /**
     * INTERNAL:
     * Set the default table if one if not already set. This method will
     * extract the default table.
     */
    public void setInternalDefaultTable() {
        if (getDefaultTable() == null) {
            setDefaultTable(extractDefaultTable());
        }
    }

    /**
     * INTERNAL:
     * Set the default table if one if not already set. This method will set
     * the table that is provided as the default.
     */
    public void setInternalDefaultTable(DatabaseTable defaultTable) {
        if (getDefaultTable() == null) {
            setDefaultTable(defaultTable);
        }
    }

    /**
     * INTERNAL:
     * Set entity @Cacheable annotation value in cache configuration object.
     * @param cacheable Entity @Cacheable annotation value for current class
     *        or <code>null</code> if @Cacheable annotation is not set. Parent
     *        values are ignored, value shall refer to current class only.
     *        This value should be set only when SharedCacheMode allows
     *        to override caching on entity level (DISABLE_SELECTIVE
     *        or ENABLE_SELECTIVE).
     */
    public void setCacheable(Boolean cacheable) {
        getCachePolicy().setCacheable(cacheable);
    }

    /**
     * PUBLIC:
     * Controls how the Entity instances will be cached.  See the CacheIsolationType for details on the options.
     * @return the isolationType
     */
    public CacheIsolationType getCacheIsolation() {
        return getCachePolicy().getCacheIsolation();
    }

    /**
     * PUBLIC:
     * Controls how the Entity instances and data will be cached.  See the CacheIsolationType for details on the options.
     * To disable all second level caching simply set CacheIsolationType.ISOLATED.  Note that setting the isolation
     * will automatically set the corresponding cacheSynchronizationType.
     * ISOLATED = DO_NOT_SEND_CHANGES, PROTECTED and SHARED = SEND_OBJECT_CHANGES
     */
    public void setCacheIsolation(CacheIsolationType isolationType) {
        getCachePolicy().setCacheIsolation(isolationType);
    }

    /**
     * INTERNAL:
     * Return if the unit of work should by-pass the session cache.
     * Objects will be built in the unit of work, and never merged into the session cache.
     */
    public boolean shouldIsolateObjectsInUnitOfWork() {
        return getCachePolicy().shouldIsolateObjectsInUnitOfWork();
    }

    /**
     * INTERNAL:
     * Return if the unit of work should by-pass the IsolatedSession cache.
     * Objects will be built/merged into the unit of work and into the session cache.
     * but not built/merge into the IsolatedClientSession cache.
     */
    public boolean shouldIsolateProtectedObjectsInUnitOfWork() {
        return getCachePolicy().shouldIsolateProtectedObjectsInUnitOfWork();
    }

    /**
     * INTERNAL:
     * Return if the unit of work should by-pass the session cache after an early transaction.
     */
    public boolean shouldIsolateObjectsInUnitOfWorkEarlyTransaction() {
        return getCachePolicy().shouldIsolateObjectsInUnitOfWorkEarlyTransaction();
    }

    /**
     * INTERNAL:
     * Return if the unit of work should use the session cache after an early transaction.
     */
    public boolean shouldUseSessionCacheInUnitOfWorkEarlyTransaction() {
        return getCachePolicy().shouldUseSessionCacheInUnitOfWorkEarlyTransaction();
    }

    /**
     * INTERNAL:
     * Used to store un-converted properties, which are subsequenctly converted
     * at runtime (through the convertClassNamesToClasses method.
     */
    public Map<String, List<String>> getUnconvertedProperties() {
        if (unconvertedProperties == null) {
            unconvertedProperties = new HashMap<>(5);
        }

        return unconvertedProperties;
    }

    /**
     * ADVANCED:
     * Return the unit of work cache isolation setting.
     * This setting configures how the session cache will be used in a unit of work.
     * @see #setUnitOfWorkCacheIsolationLevel(int)
     */
    public int getUnitOfWorkCacheIsolationLevel() {
        return getCachePolicy().getUnitOfWorkCacheIsolationLevel();
    }

    /**
     * ADVANCED:
     * This setting configures how the session cache will be used in a unit of work.
     * Most of the options only apply to a unit of work in an early transaction,
     * such as a unit of work that was flushed (writeChanges), issued a modify query, or acquired a pessimistic lock.
     * <p> USE_SESSION_CACHE_AFTER_TRANSACTION - Objects built from new data accessed after a unit of work early transaction are stored in the session cache.
     * This options is the most efficient as it allows the cache to be used after an early transaction.
     * This should only be used if it is known that this class is not modified in the transaction,
     * otherwise this could cause uncommitted data to be loaded into the session cache.
     * ISOLATE_NEW_DATA_AFTER_TRANSACTION - Default (when using caching): Objects built from new data accessed after a unit of work early transaction are only stored in the unit of work.
     * This still allows previously cached objects to be accessed in the unit of work after an early transaction,
     * but ensures uncommitted data will never be put in the session cache by storing any object built from new data only in the unit of work.
     * ISOLATE_CACHE_AFTER_TRANSACTION - After a unit of work early transaction the session cache is no longer used for this class.
     * Objects will be directly built from the database data and only stored in the unit of work, even if previously cached.
     * Note that this may lead to poor performance as the session cache is bypassed after an early transaction.
     * ISOLATE_CACHE_ALWAYS - Default (when using isolated cache): The session cache will never be used for this class.
     * Objects will be directly built from the database data and only stored in the unit of work.
     * New objects and changes will also never be merged into the session cache.
     * Note that this may lead to poor performance as the session cache is bypassed,
     * however if this class is isolated or pessimistic locked and always accessed in a transaction, this can avoid having to build two copies of the object.
     */
    public void setUnitOfWorkCacheIsolationLevel(int unitOfWorkCacheIsolationLevel) {
        getCachePolicy().setUnitOfWorkCacheIsolationLevel(unitOfWorkCacheIsolationLevel);
    }

    /**
     * INTERNAL:
     * set whether this descriptor has any relationships through its mappings, through inheritance, or through aggregates
     */
    public void setHasRelationships(boolean hasRelationships) {
        this.hasRelationships = hasRelationships;
    }

    /**
    * PUBLIC:
    * Set the Java class that this descriptor maps.
    * Every descriptor maps one and only one class.
    */
    @Override
    public void setJavaClass(Class<?> theJavaClass) {
        javaClass = theJavaClass;
    }

    /**
     * INTERNAL:
     * Return the java class name, used by the MW.
     */
    public void setJavaClassName(String theJavaClassName) {
        javaClassName = theJavaClassName;
    }

    /**
     * PUBLIC:
     * Sets the descriptor to be for an interface.
     * An interface descriptor allows for other classes to reference an interface or one of several other classes.
     * The implementor classes can be completely unrelated in term of the database stored in distinct tables.
     * Queries can also be done for the interface which will query each of the implementor classes.
     * An interface descriptor cannot define any mappings as an interface is just API and not state,
     * a interface descriptor should define the common query key of its implementors to allow querying.
     * An interface descriptor also does not define a primary key or table or other settings.
     * If an interface only has a single implementor (i.e. a classes public interface or remote) then an interface
     * descriptor should not be defined for it and relationships should be to the implementor class not the interface,
     * in this case the implementor class can add the interface through its interface policy to map queries on the interface to it.
     */
    public void setJavaInterface(Class<?> theJavaInterface) {
        javaClass = theJavaInterface;
        descriptorIsForInterface();
    }

    /**
     * INTERNAL:
     * Return the java interface name, used by the MW.
     */
    public void setJavaInterfaceName(String theJavaInterfaceName) {
        javaClassName = theJavaInterfaceName;
        descriptorIsForInterface();
    }

    /**
     * INTERNAL:
     * Set the list of lockable mappings for this project
     * This method is provided for CMP use.  Normally, the lockable mappings are initialized
     * at descriptor initialization time.
     */
    public void setLockableMappings(List<DatabaseMapping> lockableMappings) {
        this.lockableMappings = lockableMappings;
    }

    /**
     * INTERNAL:
     * Set the mappings.
     */
    public void setMappings(Vector<DatabaseMapping> mappings) {
        // This is used from XML reader so must ensure that all mapping's descriptor has been set.
        for (Enumeration<DatabaseMapping> mappingsEnum = mappings.elements(); mappingsEnum.hasMoreElements();) {
            DatabaseMapping mapping = mappingsEnum.nextElement();

            // For CR#2646, if the mapping already points to the parent descriptor then leave it.
            if (mapping.getDescriptor() == null) {
                mapping.setDescriptor(this);
            }
        }
        this.mappings = mappings;
    }

    /**
     * INTERNAL:
     *
     * @see #getMultipleTableForeignKeys
     */
    protected void setMultipleTableForeignKeys(Map<DatabaseTable, Set<DatabaseTable>> newValue) {
        this.multipleTableForeignKeys = newValue;
    }

    /**
     * ADVANCED:
     * Sets the List of DatabaseTables in the order which INSERTS should take place.
     * This is normally computed correctly by , however in advanced cases in it may be overridden.
     */
    public void setMultipleTableInsertOrder(List<DatabaseTable> newValue) {
        this.multipleTableInsertOrder = newValue;
    }

    /**
     * INTERNAL:
     * Set a multitenant policy on the descriptor.
     */
    public void setMultitenantPolicy(MultitenantPolicy multitenantPolicy) {
        this.multitenantPolicy = multitenantPolicy;
    }

    /**
     * ADVANCED:
     * Return if delete cascading has been set on the database for the descriptor's
     * multiple tables.
     */
    public boolean isCascadeOnDeleteSetOnDatabaseOnSecondaryTables() {
        return isCascadeOnDeleteSetOnDatabaseOnSecondaryTables;
    }

    /**
     * ADVANCED:
     * Set if delete cascading has been set on the database for the descriptor's
     * multiple tables.
     * This will avoid the delete SQL being generated for those tables.
     */
    public void setIsCascadeOnDeleteSetOnDatabaseOnSecondaryTables(boolean isCascadeOnDeleteSetOnDatabaseOnSecondaryTables) {
        this.isCascadeOnDeleteSetOnDatabaseOnSecondaryTables = isCascadeOnDeleteSetOnDatabaseOnSecondaryTables;
    }

    /**
     * INTERNAL:
     * Set the ObjectBuilder.
     */
    @Override
    protected void setObjectBuilder(ObjectBuilder builder) {
        objectBuilder = builder;
    }

    /**
     * PUBLIC:
     * Set the OptimisticLockingPolicy.
     * This can be one of the provided locking policies or a user defined policy.
     * @see VersionLockingPolicy
     * @see TimestampLockingPolicy
     * @see FieldsLockingPolicy
     */
    public void setOptimisticLockingPolicy(OptimisticLockingPolicy optimisticLockingPolicy) {
        this.optimisticLockingPolicy = optimisticLockingPolicy;
        if (optimisticLockingPolicy != null) {
            optimisticLockingPolicy.setDescriptor(this);
        }
    }

    /**
     * PUBLIC:
     * Specify the primary key field of the descriptors table.
     * This should only be called if it is a singlton primary key field,
     * otherwise addPrimaryKeyFieldName should be called.
     * If the descriptor has many tables, this must be the primary key in all of the tables.
     *
     * @see #addPrimaryKeyFieldName(String)
     */
    public void setPrimaryKeyFieldName(String fieldName) {
        addPrimaryKeyFieldName(fieldName);
    }

    /**
     * PUBLIC:
     * User can specify a vector of all the primary key field names if primary key is composite.
     *
     * @see #addPrimaryKeyFieldName(String)
     */
    @Override
    public void setPrimaryKeyFieldNames(Vector primaryKeyFieldsName) {
        setPrimaryKeyFields(new ArrayList(primaryKeyFieldsName.size()));
        for (Enumeration keyEnum = primaryKeyFieldsName.elements(); keyEnum.hasMoreElements();) {
            addPrimaryKeyFieldName((String)keyEnum.nextElement());
        }
    }

    /**
     * INTERNAL:
     * Set the primary key fields
     */
    @Override
    public void setPrimaryKeyFields(List<DatabaseField> thePrimaryKeyFields) {
        primaryKeyFields = thePrimaryKeyFields;
    }

    /**
     * INTERNAL:
     * Set the user defined properties.
     */
    public void setProperties(Map properties) {
        this.properties = properties;
    }

    /**
     * PUBLIC:
     * Set the user defined property.
     */
    public void setProperty(String name, Object value) {
        getProperties().put(name, value);
    }

    /**
     * INTERNAL:
     * Set the query keys.
     */
    public void setQueryKeys(Map<String, QueryKey> queryKeys) {
        this.queryKeys = queryKeys;
    }

    /**
     * INTERNAL:
     * Set the query manager.
     */
    public void setQueryManager(DescriptorQueryManager queryManager) {
        this.queryManager = queryManager;
        if (queryManager != null) {
            queryManager.setDescriptor(this);
        }
    }

    /**
     * PUBLIC:
     * Set the class of identity map to be used by this descriptor.
     * The default is the "FullIdentityMap".
     */
    public void setRemoteIdentityMapClass(Class<? extends IdentityMap> theIdentityMapClass) {
        getCachePolicy().setRemoteIdentityMapClass(theIdentityMapClass);
    }

    /**
     * PUBLIC:
     * Set the size of the identity map to be used by this descriptor.
     * The default is the 100.
     */
    public void setRemoteIdentityMapSize(int identityMapSize) {
        getCachePolicy().setRemoteIdentityMapSize(identityMapSize);
    }

    /**
     * INTERNAL:
     * Set the sequence number field.
     */
    public void setSequenceNumberField(DatabaseField sequenceNumberField) {
        this.sequenceNumberField = sequenceNumberField;
    }

    /**
     * PUBLIC:
     * Set the sequence number field name.
     * This is the field in the descriptors table that needs its value to be generated.
     * This is normally the primary key field of the descriptor.
     */
    public void setSequenceNumberFieldName(String fieldName) {
        if (fieldName == null) {
            setSequenceNumberField(null);
        } else {
            setSequenceNumberField(new DatabaseField(fieldName));
        }
    }

    /**
     * PUBLIC:
     * Set the sequence number name.
     * This is the seq_name part of the row stored in the sequence table for this descriptor.
     * If using Oracle native sequencing this is the name of the Oracle sequence object.
     * If using Sybase native sequencing this name has no meaning, but should still be set for compatibility.
     * The name does not have to be unique among descriptors, as having descriptors share sequences can
     * improve pre-allocation performance.
     */
    public void setSequenceNumberName(String name) {
        sequenceNumberName = name;
    }

    /**
     * INTERNAL:
     * Set the name of the session local to this descriptor.
     * This is used by the session broker.
     */
    protected void setSessionName(String sessionName) {
        this.sessionName = sessionName;
    }

    /**
     * PUBLIC:
     * set if the descriptor is defined to always conform the results in unit of work in read query.
     *
     */
    public void setShouldAlwaysConformResultsInUnitOfWork(boolean shouldAlwaysConformResultsInUnitOfWork) {
        this.shouldAlwaysConformResultsInUnitOfWork = shouldAlwaysConformResultsInUnitOfWork;
    }

    /**
     * PUBLIC:
     * When the <CODE>shouldAlwaysRefreshCache</CODE> argument passed into this method is <CODE>true</CODE>,
     * this method configures a <CODE>ClassDescriptor</CODE> to always refresh the cache if data is received from
     * the database by any query.<P>
     *
     * However, if a query hits the cache, data is not refreshed regardless of how this setting is configured.
     * For example, by default, when a query for a single object based on its primary key is executed, OracleAS TopLink
     * will first look in the cache for the object. If the object is in the cache, the cached object is returned and
     * data is not refreshed. To avoid cache hits, use the {@link #disableCacheHits} method.<P>
     *
     * Also note that the {@link org.eclipse.persistence.sessions.UnitOfWork} will not refresh its registered objects.<P>
     *
     * Use this property with caution because it can lead to poor performance and may refresh on queries when it is not desired.
     * Normally, if you require fresh data, it is better to configure a query with {@link org.eclipse.persistence.queries.ObjectLevelReadQuery#refreshIdentityMapResult}.
     * To ensure that refreshes are only done when required, use this method in conjunction with {@link #onlyRefreshCacheIfNewerVersion}.<P>
     *
     * When the <CODE>shouldAlwaysRefreshCache</CODE> argument passed into this method is <CODE>false</CODE>, this method
     * ensures that a <CODE>ClassDescriptor</CODE> is not configured to always refresh the cache if data is received from the database by any query.
     *
     * @see #alwaysRefreshCache
     * @see #dontAlwaysRefreshCache
     */
    public void setShouldAlwaysRefreshCache(boolean shouldAlwaysRefreshCache) {
        getCachePolicy().setShouldAlwaysRefreshCache(shouldAlwaysRefreshCache);
    }

    /**
     * PUBLIC:
     * When the <CODE>shouldAlwaysRefreshCacheOnRemote</CODE> argument passed into this method is <CODE>true</CODE>,
     * this method configures a <CODE>ClassDescriptor</CODE> to always remotely refresh the cache if data is received from
     * the database by any query in a {@link org.eclipse.persistence.sessions.remote.RemoteSession}.
     *
     * However, if a query hits the cache, data is not refreshed regardless of how this setting is configured. For
     * example, by default, when a query for a single object based on its primary key is executed, OracleAS TopLink
     * will first look in the cache for the object. If the object is in the cache, the cached object is returned and
     * data is not refreshed. To avoid cache hits, use the {@link #disableCacheHitsOnRemote} method.<P>
     *
     * Also note that the {@link org.eclipse.persistence.sessions.UnitOfWork} will not refresh its registered objects.<P>
     *
     * Use this property with caution because it can lead to poor performance and may refresh on queries when it is
     * not desired. Normally, if you require fresh data, it is better to configure a query with {@link org.eclipse.persistence.queries.ObjectLevelReadQuery#refreshIdentityMapResult}.
     * To ensure that refreshes are only done when required, use this method in conjunction with {@link #onlyRefreshCacheIfNewerVersion}.<P>
     *
     * When the <CODE>shouldAlwaysRefreshCacheOnRemote</CODE> argument passed into this method is <CODE>false</CODE>,
     * this method ensures that a <CODE>ClassDescriptor</CODE> is not configured to always remotely refresh the cache if data
     * is received from the database by any query in a {@link org.eclipse.persistence.sessions.remote.RemoteSession}.
     *
     * @see #alwaysRefreshCacheOnRemote
     * @see #dontAlwaysRefreshCacheOnRemote
     */
    public void setShouldAlwaysRefreshCacheOnRemote(boolean shouldAlwaysRefreshCacheOnRemote) {
        getCachePolicy().setShouldAlwaysRefreshCacheOnRemote(shouldAlwaysRefreshCacheOnRemote);
    }

    /**
     * PUBLIC:
     * Define if the descriptor reference class is read-only
     */
    public void setShouldBeReadOnly(boolean shouldBeReadOnly) {
        this.shouldBeReadOnly = shouldBeReadOnly;
    }

    /**
     * PUBLIC:
     * Set the descriptor to be read-only.
     * Declaring a descriptor is read-only means that instances of the reference class will never be modified.
     * Read-only descriptor is usually used in the unit of work to gain performance as there is no need for
     * the registration, clone and merge for the read-only classes.
     */
    public void setReadOnly() {
        setShouldBeReadOnly(true);
    }

    /**
     * PUBLIC:
     * Set if cache hits on primary key read object queries should be disabled.
     *
     * @see #alwaysRefreshCache()
     */
    public void setShouldDisableCacheHits(boolean shouldDisableCacheHits) {
        getCachePolicy().setShouldDisableCacheHits(shouldDisableCacheHits);
    }

    /**
     * PUBLIC:
     * Set if the remote session cache hits on primary key read object queries is allowed or not.
     *
     * @see #disableCacheHitsOnRemote()
     */
    public void setShouldDisableCacheHitsOnRemote(boolean shouldDisableCacheHitsOnRemote) {
        getCachePolicy().setShouldDisableCacheHitsOnRemote(shouldDisableCacheHitsOnRemote);
    }

    /**
     * ADVANCED:
     * When set to false, this setting will allow the UOW to avoid locking the shared cache instance in order to perform a clone.
     * Caution should be taken as setting this to false may allow cloning of partial updates
     */
     public void setShouldLockForClone(boolean shouldLockForClone) {
        this.shouldLockForClone = shouldLockForClone;
    }

    /**
     * PUBLIC:
     * When the <CODE>shouldOnlyRefreshCacheIfNewerVersion</CODE> argument passed into this method is <CODE>true</CODE>,
     * this method configures a <CODE>ClassDescriptor</CODE> to only refresh the cache if the data received from the database
     * by a query is newer than the data in the cache (as determined by the optimistic locking field) and as long as one of the following is true:
     *
     * <UL>
     * <LI>the <CODE>ClassDescriptor</CODE> was configured by calling {@link #alwaysRefreshCache} or {@link #alwaysRefreshCacheOnRemote},</LI>
     * <LI>the query was configured by calling {@link org.eclipse.persistence.queries.ObjectLevelReadQuery#refreshIdentityMapResult}, or</LI>
     * <LI>the query was a call to {@link org.eclipse.persistence.sessions.Session#refreshObject}</LI>
     * </UL>
     * <P>
     *
     * However, if a query hits the cache, data is not refreshed regardless of how this setting is configured. For example, by default,
     * when a query for a single object based on its primary key is executed, OracleAS TopLink will first look in the cache for the object.
     * If the object is in the cache, the cached object is returned and data is not refreshed. To avoid cache hits, use
     * the {@link #disableCacheHits} method.<P>
     *
     * Also note that the {@link org.eclipse.persistence.sessions.UnitOfWork} will not refresh its registered objects.<P>
     *
     * When the <CODE>shouldOnlyRefreshCacheIfNewerVersion</CODE> argument passed into this method is <CODE>false</CODE>, this method
     * ensures that a <CODE>ClassDescriptor</CODE> is not configured to only refresh the cache if the data received from the database by a
     * query is newer than the data in the cache (as determined by the optimistic locking field).
     *
     * @see #onlyRefreshCacheIfNewerVersion
     * @see #dontOnlyRefreshCacheIfNewerVersion
     */
    public void setShouldOnlyRefreshCacheIfNewerVersion(boolean shouldOnlyRefreshCacheIfNewerVersion) {
        getCachePolicy().setShouldOnlyRefreshCacheIfNewerVersion(shouldOnlyRefreshCacheIfNewerVersion);
    }

    /**
     * PUBLIC:
     * This is set to turn off the ordering of mappings.  By Default this is set to true.
     * By ordering the mappings  insures that object are merged in the right order.
     * If the order of the mappings needs to be specified by the developer then set this to
     * false and  will use the order that the mappings were added to the descriptor
     */
    public void setShouldOrderMappings(boolean shouldOrderMappings) {
        this.shouldOrderMappings = shouldOrderMappings;
    }

    /**
     * INTERNAL:
     * Set to false to have queries conform to a UnitOfWork without registering
     * any additional objects not already in that UnitOfWork.
     * @see #shouldRegisterResultsInUnitOfWork
     */
    public void setShouldRegisterResultsInUnitOfWork(boolean shouldRegisterResultsInUnitOfWork) {
        //bug 2612601
        this.shouldRegisterResultsInUnitOfWork = shouldRegisterResultsInUnitOfWork;
    }

    /**
     * PUBLIC:
     * Specify the table name for the class of objects the receiver describes.
     * If the table has a qualifier it should be specified using the dot notation,
     * (i.e. "userid.employee"). This method is used for single table.
     */
    public void setTableName(String tableName) throws DescriptorException {
        if (getTables().isEmpty()) {
            addTableName(tableName);
        } else {
            getTables().get(0).setPossiblyQualifiedName(tableName);
        }
    }

    /**
     * PUBLIC:
     * Specify the all table names for the class of objects the receiver describes.
     * If the table has a qualifier it should be specified using the dot notation,
     * (i.e. "userid.employee"). This method is used for multiple tables
     */
    public void setTableNames(Vector tableNames) {
        setTables(NonSynchronizedVector.newInstance(tableNames.size()));
        for (Enumeration tableEnum = tableNames.elements(); tableEnum.hasMoreElements();) {
            addTableName((String)tableEnum.nextElement());
        }
    }

    /**
     * INTERNAL:
     * Sets the table per class policy.
     */
    public void setTablePerClassPolicy(TablePerClassPolicy tablePerClassPolicy) {
        interfacePolicy = tablePerClassPolicy;
        if (interfacePolicy != null) {
            interfacePolicy.setDescriptor(this);
        }
    }

    /**
     * PUBLIC: Set the table Qualifier for this descriptor.  This table creator will be used for
     * all tables in this descriptor
     */
    public void setTableQualifier(String tableQualifier) {
        for (Enumeration<DatabaseTable> enumtr = getTables().elements(); enumtr.hasMoreElements();) {
            DatabaseTable table = enumtr.nextElement();
            table.setTableQualifier(tableQualifier);
        }
    }

    /**
     * INTERNAL:
     * Sets the tables
     */
    public void setTables(Vector<DatabaseTable> theTables) {
        tables = theTables;
    }

    /**
     * ADVANCED:
     * Sets the WrapperPolicy for this descriptor.
     * This advanced feature can be used to wrap objects with other classes such as CORBA TIE objects or EJBs.
     */
    public void setWrapperPolicy(WrapperPolicy wrapperPolicy) {
        this.wrapperPolicy = wrapperPolicy;

        // For bug 2766379 must be able to set the wrapper policy back to default
        // which is null.
        if (wrapperPolicy != null) {
            wrapperPolicy.setDescriptor(this);
        }
        getObjectBuilder().setHasWrapperPolicy(wrapperPolicy != null);
    }

    /**
     * PUBLIC:
     * Return if the descriptor is defined to always conform the results in unit of work in read query.
     *
     */
    public boolean shouldAlwaysConformResultsInUnitOfWork() {
        return shouldAlwaysConformResultsInUnitOfWork;
    }

    /**
     * PUBLIC:
     * This method returns <CODE>true</CODE> if the <CODE>ClassDescriptor</CODE> is configured to always refresh
     * the cache if data is received from the database by any query. Otherwise, it returns <CODE>false</CODE>.
     *
     * @see #setShouldAlwaysRefreshCache
     */
    public boolean shouldAlwaysRefreshCache() {
        return getCachePolicy().shouldAlwaysRefreshCache();
    }

    /**
     * PUBLIC:
     * This method returns <CODE>true</CODE> if the <CODE>ClassDescriptor</CODE> is configured to always remotely
     * refresh the cache if data is received from the database by any query in a {@link org.eclipse.persistence.sessions.remote.RemoteSession}.
     * Otherwise, it returns <CODE>false</CODE>.
     *
     * @see #setShouldAlwaysRefreshCacheOnRemote
     */
    public boolean shouldAlwaysRefreshCacheOnRemote() {
        return getCachePolicy().shouldAlwaysRefreshCacheOnRemote();
    }

    /**
     * PUBLIC:
     * Return if the descriptor reference class is defined as read-only
     *
     */
    public boolean shouldBeReadOnly() {
        return shouldBeReadOnly;
    }

    /**
     * PUBLIC:
     * Return if for cache hits on primary key read object queries to be disabled.
     *
     * @see #disableCacheHits()
     */
    public boolean shouldDisableCacheHits() {
        return getCachePolicy().shouldDisableCacheHits();
    }

    /**
     * PUBLIC:
     * Return if the remote server session cache hits on primary key read object queries is aloowed or not.
     *
     * @see #disableCacheHitsOnRemote()
     */
    public boolean shouldDisableCacheHitsOnRemote() {
        return getCachePolicy().shouldDisableCacheHitsOnRemote();
    }

    /**
     * PUBLIC:
     * This method returns <CODE>true</CODE> if the <CODE>ClassDescriptor</CODE> is configured to only refresh the cache
     * if the data received from the database by a query is newer than the data in the cache (as determined by the
     * optimistic locking field). Otherwise, it returns <CODE>false</CODE>.
     *
     * @see #setShouldOnlyRefreshCacheIfNewerVersion
     */
    public boolean shouldOnlyRefreshCacheIfNewerVersion() {
        return getCachePolicy().shouldOnlyRefreshCacheIfNewerVersion();
    }

    /**
     * INTERNAL:
     * Return if mappings should be ordered or not.  By default this is set to true
     * to prevent attributes from being merged in the wrong order
     *
     */
    public boolean shouldOrderMappings() {
        return shouldOrderMappings;
    }

    /**
     * INTERNAL:
     * PERF: Return if the primary key is simple (direct-mapped) to allow fast extraction.
     */
    public boolean hasSimplePrimaryKey() {
        return hasSimplePrimaryKey;
    }

    /**
     * INTERNAL:
     * Return if this descriptor is involved in a table per class inheritance.
     */
    public boolean hasTablePerClassPolicy() {
        return hasInterfacePolicy() && interfacePolicy.isTablePerClassPolicy();
    }

    /**
     * INTERNAL:
     * PERF: Set if the primary key is simple (direct-mapped) to allow fast extraction.
     */
    public void setHasSimplePrimaryKey(boolean hasSimplePrimaryKey) {
        this.hasSimplePrimaryKey = hasSimplePrimaryKey;
    }

    /**
     * INTERNAL:
     * PERF: Return if deferred locks should be used.
     * Used to optimize read locking.
     * This is determined based on if any relationships do not use indirection.
     */
    public boolean shouldAcquireCascadedLocks() {
        return shouldAcquireCascadedLocks;
    }

    /**
     * INTERNAL:
     * PERF: Set if deferred locks should be used.
     * This is determined based on if any relationships do not use indirection,
     * but this provides a backdoor hook to force on if require because of events usage etc.
     */
    public void setShouldAcquireCascadedLocks(boolean shouldAcquireCascadedLocks) {
        this.shouldAcquireCascadedLocks = shouldAcquireCascadedLocks;
    }

    /**
     * PUBLIC:
     * Return true if this descriptor should using an additional join expresison.
     */
    public boolean shouldUseAdditionalJoinExpression() {
        // Return true, if the query manager has an additional join expression
        // and this descriptor is not part of an inheritance hierarchy using a
        // view (CR#3701077)
        return ((getQueryManager().getAdditionalJoinExpression() != null) && ! (hasInheritance() && getInheritancePolicy().hasView()));
    }

    /**
     * PUBLIC:
     * Return true if this descriptor is using CacheIdentityMap
     */
    public boolean shouldUseCacheIdentityMap() {
        return ClassConstants.CacheIdentityMap_Class.equals(getIdentityMapClass());
    }

    /**
     * PUBLIC:
     * Return true if this descriptor is using FullIdentityMap
     */
    public boolean shouldUseFullIdentityMap() {
        return ClassConstants.FullIdentityMap_Class.equals(getIdentityMapClass());
    }

    /**
     * PUBLIC:
     * Return true if this descriptor is using SoftIdentityMap
     */
    public boolean shouldUseSoftIdentityMap() {
        return ClassConstants.SoftIdentityMap_Class.equals(getIdentityMapClass());
    }

    /**
     * PUBLIC:
     * Return true if this descriptor is using SoftIdentityMap
     */
    public boolean shouldUseRemoteSoftIdentityMap() {
        return ClassConstants.SoftIdentityMap_Class.equals(getRemoteIdentityMapClass());
    }

    /**
     * PUBLIC:
     * Return true if this descriptor is using HardCacheWeakIdentityMap.
     */
    public boolean shouldUseHardCacheWeakIdentityMap() {
        return ClassConstants.HardCacheWeakIdentityMap_Class.equals(getIdentityMapClass());
    }

    /**
     * PUBLIC:
     * Return true if this descriptor is using NoIdentityMap
     */
    public boolean shouldUseNoIdentityMap() {
        return ClassConstants.NoIdentityMap_Class.equals(getIdentityMapClass());
    }

    /**
     * INTERNAL:
     * Allows one to do conforming in a UnitOfWork without registering.
     * Queries executed on a UnitOfWork will only return working copies for objects
     * that have already been registered.
     * <p>Extreme care should be taken in using this feature, for a user will
     * get back a mix of registered and original (unregistered) objects.
     * <p>Best used with a WrapperPolicy where invoking on an object will trigger
     * its registration (CMP).  Without a WrapperPolicy {@link org.eclipse.persistence.sessions.UnitOfWork#registerExistingObject registerExistingObject}
     * should be called on any object that you intend to change.
     * @return true by default.
     * @see #setShouldRegisterResultsInUnitOfWork
     * @see org.eclipse.persistence.queries.ObjectLevelReadQuery#shouldRegisterResultsInUnitOfWork
     */
    public boolean shouldRegisterResultsInUnitOfWork() {
        // bug 2612601
        return shouldRegisterResultsInUnitOfWork;
    }

    /**
     * PUBLIC:
     * Return true if this descriptor is using CacheIdentityMap
     */
    public boolean shouldUseRemoteCacheIdentityMap() {
        return ClassConstants.CacheIdentityMap_Class.equals(getRemoteIdentityMapClass());
    }

    /**
     * PUBLIC:
     * Return true if this descriptor is using FullIdentityMap
     */
    public boolean shouldUseRemoteFullIdentityMap() {
        return ClassConstants.FullIdentityMap_Class.equals(getRemoteIdentityMapClass());
    }

    /**
     * PUBLIC:
     * Return true if this descriptor is using HardCacheWeakIdentityMap
     */
    public boolean shouldUseRemoteHardCacheWeakIdentityMap() {
        return ClassConstants.HardCacheWeakIdentityMap_Class.equals(getRemoteIdentityMapClass());
    }

    /**
     * PUBLIC:
     * Return true if this descriptor is using NoIdentityMap
     */
    public boolean shouldUseRemoteNoIdentityMap() {
        return ClassConstants.NoIdentityMap_Class.equals(getRemoteIdentityMapClass());
    }

    /**
     * PUBLIC:
     * Return true if this descriptor is using SoftCacheWeakIdentityMap
     */
    public boolean shouldUseRemoteSoftCacheWeakIdentityMap() {
        return ClassConstants.SoftCacheWeakIdentityMap_Class.equals(getRemoteIdentityMapClass());
    }

    /**
     * PUBLIC:
     * Return true if this descriptor is using WeakIdentityMap
     */
    public boolean shouldUseRemoteWeakIdentityMap() {
        return ClassConstants.WeakIdentityMap_Class.equals(getRemoteIdentityMapClass());
    }

    /**
     * PUBLIC:
     * Return true if this descriptor is using SoftCacheWeakIdentityMap.
     */
    public boolean shouldUseSoftCacheWeakIdentityMap() {
        return ClassConstants.SoftCacheWeakIdentityMap_Class.equals(getIdentityMapClass());
    }

    /**
     * PUBLIC:
     * Return true if this descriptor is using WeakIdentityMap
     */
    public boolean shouldUseWeakIdentityMap() {
        return ClassConstants.WeakIdentityMap_Class.equals(getIdentityMapClass());
    }

    /**
     * INTERNAL:
     * Returns whether this descriptor is capable of supporting weaved change tracking.
     * This method is used before the project is initialized.
     */
    public boolean supportsChangeTracking(Project project){
        // Check the descriptor: if field-locking is used, cannot do
        // change tracking because field-locking requires backup clone.
        OptimisticLockingPolicy lockingPolicy = getOptimisticLockingPolicy();
        if (lockingPolicy instanceof FieldsLockingPolicy) {
            return false;
        }
        Vector<DatabaseMapping> mappings = getMappings();
        for (Iterator<DatabaseMapping> iterator = mappings.iterator(); iterator.hasNext();) {
            DatabaseMapping mapping = iterator.next();
            if (!mapping.isChangeTrackingSupported(project) ) {
                return false;
            }
        }
        return true;
    }

    /**
     * PUBLIC:
     * Returns a brief string representation of the receiver.
     */
    @Override
    public String toString() {
        return Helper.getShortClassName(getClass()) + "(" + getJavaClassName() + " --> " + getTables() + ")";
    }

    /**
     * PUBLIC:
     * Set the locking policy an all fields locking policy.
     * A field locking policy is base on locking on all fields by comparing with their previous values to detect field-level collisions.
     * Note: the unit of work must be used for all updates when using field locking.
     * @see AllFieldsLockingPolicy
     */
    public void useAllFieldsLocking() {
        setOptimisticLockingPolicy(new AllFieldsLockingPolicy());
    }

    /**
     * PUBLIC:
     * Set the class of identity map to be the cache identity map.
     * This map caches the LRU instances read from the database.
     * Note: This map does not guarantee object identity.
     * The default is the "SoftCacheWeakIdentityMap".
     */
    public void useCacheIdentityMap() {
        setIdentityMapClass(ClassConstants.CacheIdentityMap_Class);
    }

    /**
     * PUBLIC:
     * Set the locking policy a changed fields locking policy.
     * A field locking policy is base on locking on all changed fields by comparing with their previous values to detect field-level collisions.
     * Note: the unit of work must be used for all updates when using field locking.
     * @see ChangedFieldsLockingPolicy
     */
    public void useChangedFieldsLocking() {
        setOptimisticLockingPolicy(new ChangedFieldsLockingPolicy());
    }

    /**
     * PUBLIC:
     * Specifies that the creation of clones within a unit of work is done by
     * sending the #clone() method to the original object. The #clone() method
     * must return a logical shallow copy of the original object.
     * This can be used if the default mechanism of creating a new instance
     * does not handle the object's non-persistent attributes correctly.
     *
     * @see #useCloneCopyPolicy(String)
     */
    public void useCloneCopyPolicy() {
        useCloneCopyPolicy("clone");
    }

    /**
     * PUBLIC:
     * Specifies that the creation of clones within a unit of work is done by
     * sending the cloneMethodName method to the original object. This method
     * must return a logical shallow copy of the original object.
     * This can be used if the default mechanism of creating a new instance
     * does not handle the object's non-persistent attributes correctly.
     *
     * @see #useCloneCopyPolicy()
     */
    public void useCloneCopyPolicy(String cloneMethodName) {
        CloneCopyPolicy policy = new CloneCopyPolicy();
        policy.setMethodName(cloneMethodName);
        setCopyPolicy(policy);
    }

    /**
     * PUBLIC:
     * Specifies that the creation of clones within a unit of work is done by building
     * a new instance using the
     * technique indicated by the descriptor's instantiation policy
     * (which by default is to use the
     * the default constructor). This new instance is then populated by using the
     * descriptor's mappings to copy attributes from the original to the clone.
     * This is the default.
     * If another mechanism is desired the copy policy allows for a clone method to be called.
     *
     * @see #useCloneCopyPolicy()
     * @see #useCloneCopyPolicy(String)
     * @see #useDefaultConstructorInstantiationPolicy()
     * @see #useMethodInstantiationPolicy(String)
     * @see #useFactoryInstantiationPolicy(Class, String)
     * @see #useFactoryInstantiationPolicy(Class, String, String)
     * @see #useFactoryInstantiationPolicy(Object, String)
     */
    public void useInstantiationCopyPolicy() {
        setCopyPolicy(new InstantiationCopyPolicy());
    }

    /**
     * PUBLIC:
     * Use the default constructor to create new instances of objects built from the database.
     * This is the default.
     * The descriptor's class must either define a default constructor or define
     * no constructors at all.
     *
     * @see #useMethodInstantiationPolicy(String)
     * @see #useFactoryInstantiationPolicy(Class, String)
     * @see #useFactoryInstantiationPolicy(Class, String, String)
     * @see #useFactoryInstantiationPolicy(Object, String)
     */
    public void useDefaultConstructorInstantiationPolicy() {
        getInstantiationPolicy().useDefaultConstructorInstantiationPolicy();
    }

    /**
     * PUBLIC:
     * Use an object factory to create new instances of objects built from the database.
     * The methodName is the name of the
     * method that will be invoked on the factory. When invoked, it must return a new instance
     * of the descriptor's class.
     * The factory will be created by invoking the factoryClass's default constructor.
     *
     * @see #useDefaultConstructorInstantiationPolicy()
     * @see #useMethodInstantiationPolicy(String)
     * @see #useFactoryInstantiationPolicy(Class, String, String)
     * @see #useFactoryInstantiationPolicy(Object, String)
     */
    public void useFactoryInstantiationPolicy(Class<?> factoryClass, String methodName) {
        getInstantiationPolicy().useFactoryInstantiationPolicy(factoryClass, methodName);
    }

    /**
     * INTERNAL:
     * Set the factory class name, used by the MW.
     */
    public void useFactoryInstantiationPolicy(String factoryClassName, String methodName) {
        getInstantiationPolicy().useFactoryInstantiationPolicy(factoryClassName, methodName);
    }

    /**
     * PUBLIC:
     * Use an object factory to create new instances of objects built from the database.
     * The factoryMethodName is a static method declared by the factoryClass.
     * When invoked, it must return an instance of the factory. The methodName is the name of the
     * method that will be invoked on the factory. When invoked, it must return a new instance
     * of the descriptor's class.
     *
     * @see #useDefaultConstructorInstantiationPolicy()
     * @see #useFactoryInstantiationPolicy(Class, String)
     * @see #useFactoryInstantiationPolicy(Object, String)
     * @see #useMethodInstantiationPolicy(String)
     */
    public void useFactoryInstantiationPolicy(Class<?> factoryClass, String methodName, String factoryMethodName) {
        getInstantiationPolicy().useFactoryInstantiationPolicy(factoryClass, methodName, factoryMethodName);
    }

    /**
     * INTERNAL:
     * Set the factory class name, used by the MW.
     */
    public void useFactoryInstantiationPolicy(String factoryClassName, String methodName, String factoryMethodName) {
        getInstantiationPolicy().useFactoryInstantiationPolicy(factoryClassName, methodName, factoryMethodName);
    }

    /**
     * PUBLIC:
     * Use an object factory to create new instances of objects built from the database.
     * The methodName is the name of the
     * method that will be invoked on the factory. When invoked, it must return a new instance
     * of the descriptor's class.
     *
     * @see #useDefaultConstructorInstantiationPolicy()
     * @see #useMethodInstantiationPolicy(String)
     * @see #useFactoryInstantiationPolicy(Class, String)
     * @see #useFactoryInstantiationPolicy(Class, String, String)
     */
    public void useFactoryInstantiationPolicy(Object factory, String methodName) {
        getInstantiationPolicy().useFactoryInstantiationPolicy(factory, methodName);
    }

    /**
     * PUBLIC:
     * Set the class of identity map to be the full identity map.
     * This map caches all instances read and grows to accomodate them.
     * The default is the "SoftCacheWeakIdentityMap".
     */
    public void useFullIdentityMap() {
        getCachePolicy().useFullIdentityMap();
    }

    /**
     * PUBLIC:
     * Set the class of identity map to be the hard cache weak identity map.
     * This map uses weak references to only cache object in-memory.
     * It also includes a secondary fixed sized hard cache to improve caching performance.
     * This is provided because some Java VM's implement soft references differently.
     * The default is the "SoftCacheWeakIdentityMap".
     */
    public void useHardCacheWeakIdentityMap() {
        getCachePolicy().useHardCacheWeakIdentityMap();
    }

    /**
     * PUBLIC:
     * Set the class of identity map to be the soft identity map.
     * This map uses soft references to only cache all object in-memory, until memory is low.
     * Note that "low" is interpreted differently by different JVM's.
     * The default is the "SoftCacheWeakIdentityMap".
     */
    public void useSoftIdentityMap() {
        getCachePolicy().useSoftIdentityMap();
    }

    /**
     * PUBLIC:
     * Set the class of identity map to be the soft identity map.
     * This map uses soft references to only cache all object in-memory, until memory is low.
     * Note that "low" is interpreted differently by different JVM's.
     * The default is the "SoftCacheWeakIdentityMap".
     */
    public void useRemoteSoftIdentityMap() {
        getCachePolicy().setRemoteIdentityMapClass(ClassConstants.SoftIdentityMap_Class);
    }

    /**
     * PUBLIC:
     * Use the specified static method to create new instances of objects built from the database.
     * This method must be statically declared by the descriptor's class, and it must
     * return a new instance of the descriptor's class.
     *
     * @see #useDefaultConstructorInstantiationPolicy()
     * @see #useFactoryInstantiationPolicy(Class, String)
     * @see #useFactoryInstantiationPolicy(Class, String, String)
     * @see #useFactoryInstantiationPolicy(Object, String)
     */
    public void useMethodInstantiationPolicy(String staticMethodName) {
        getInstantiationPolicy().useMethodInstantiationPolicy(staticMethodName);
    }

    /**
     * PUBLIC:
     * Set the class of identity map to be the no identity map.
     * This map does no caching.
     * Note: This map does not maintain object identity.
     * In general if caching is not desired a WeakIdentityMap should be used with an isolated descriptor.
     * The default is the "SoftCacheWeakIdentityMap".
     * @see #setCacheIsolation(CacheIsolationType)
     */
    public void useNoIdentityMap() {
        getCachePolicy().useNoIdentityMap();
    }

    /**
     * PUBLIC:
     * Set the class of identity map to be the cache identity map.
     * This map caches the LRU instances read from the database.
     * The default is the "SoftCacheWeakIdentityMap".
     */
    public void useRemoteCacheIdentityMap() {
        getCachePolicy().setRemoteIdentityMapClass(ClassConstants.CacheIdentityMap_Class);
    }

    /**
     * PUBLIC:
     * Set the class of identity map to be the full identity map.
     * This map caches all instances read and grows to accomodate them.
     * The default is the "SoftCacheWeakIdentityMap".
     */
    public void useRemoteFullIdentityMap() {
        getCachePolicy().setRemoteIdentityMapClass(ClassConstants.FullIdentityMap_Class);
    }

    /**
     * PUBLIC:
     * Set the class of identity map to be the hard cache weak identity map.
     * This map uses weak references to only cache object in-memory.
     * It also includes a secondary fixed sized soft cache to improve caching performance.
     * This is provided because some Java VM's do not implement soft references correctly.
     * The default is the "SoftCacheWeakIdentityMap".
     */
    public void useRemoteHardCacheWeakIdentityMap() {
        getCachePolicy().setRemoteIdentityMapClass(ClassConstants.HardCacheWeakIdentityMap_Class);
    }

    /**
     * PUBLIC:
     * Set the class of identity map to be the no identity map.
     * This map does no caching.
     * The default is the "SoftCacheWeakIdentityMap".
     */
    public void useRemoteNoIdentityMap() {
        getCachePolicy().setRemoteIdentityMapClass(ClassConstants.NoIdentityMap_Class);
    }

    /**
     * PUBLIC:
     * Set the class of identity map to be the soft cache weak identity map.
     * The SoftCacheIdentityMap holds a fixed number of objects is memory
     * (using SoftReferences) to improve caching.
     * The default is the "SoftCacheWeakIdentityMap".
     */
    public void useRemoteSoftCacheWeakIdentityMap() {
        getCachePolicy().setRemoteIdentityMapClass(ClassConstants.SoftCacheWeakIdentityMap_Class);
    }

    /**
     * PUBLIC:
     * Set the class of identity map to be the weak identity map.
     * The default is the "SoftCacheWeakIdentityMap".
     */
    public void useRemoteWeakIdentityMap() {
        getCachePolicy().setRemoteIdentityMapClass(ClassConstants.WeakIdentityMap_Class);
    }

    /**
     * PUBLIC:
     * Set the locking policy a selected fields locking policy.
     * A field locking policy is base on locking on the specified fields by comparing with their previous values to detect field-level collisions.
     * Note: the unit of work must be used for all updates when using field locking.
     * @see SelectedFieldsLockingPolicy
     */
    public void useSelectedFieldsLocking(Vector fieldNames) {
        SelectedFieldsLockingPolicy policy = new SelectedFieldsLockingPolicy();
        policy.setLockFieldNames(fieldNames);
        setOptimisticLockingPolicy(policy);
    }

    /**
     * INTERNAL:
     * Return true if the receiver uses either all or changed fields for optimistic locking.
     */
    public boolean usesFieldLocking() {
        return (usesOptimisticLocking() && (getOptimisticLockingPolicy() instanceof FieldsLockingPolicy));
    }

    /**
     * PUBLIC:
     * Set the class of identity map to be the soft cache weak identity map.
     * The SoftCacheIdentityMap holds a fixed number of objects is memory
     * (using SoftReferences) to improve caching.
     * The default is the "SoftCacheWeakIdentityMap".
     */
    public void useSoftCacheWeakIdentityMap() {
        setIdentityMapClass(ClassConstants.SoftCacheWeakIdentityMap_Class);
    }

    /**
     * PUBLIC:
     * Return true if the receiver uses write (optimistic) locking.
     */
    public boolean usesOptimisticLocking() {
        return (optimisticLockingPolicy != null);
    }

    /**
     * PUBLIC:
     * Return true if the receiver uses version optimistic locking.
     */
    public boolean usesVersionLocking() {
        return (usesOptimisticLocking() && (getOptimisticLockingPolicy() instanceof VersionLockingPolicy));
    }

    /**
     * PUBLIC:
     * Return true if the receiver uses sequence numbers.
     */
    public boolean usesSequenceNumbers() {
        return this.sequenceNumberField != null;
    }

    /**
     * PUBLIC:
     * Use the Timestamps locking policy and storing the value in the cache key
     * #see useVersionLocking(String)
     */
    public void useTimestampLocking(String writeLockFieldName) {
        useTimestampLocking(writeLockFieldName, true);
    }

    /**
     * PUBLIC:
     * Set the locking policy to use timestamp version locking.
     * This updates the timestamp field on all updates, first comparing that the field has not changed to detect locking conflicts.
     * Note: many database have limited precision of timestamps which can be an issue is highly concurrent systems.
     *
     * The parameter 'shouldStoreInCache' configures the version lock value to be stored in the cache or in the object.
     * Note: if using a stateless model where the object can be passed to a client and then later updated in a different transaction context,
     * then the version lock value should not be stored in the cache, but in the object to ensure it is the correct value for that object.
     * @see VersionLockingPolicy
     */
    public void useTimestampLocking(String writeLockFieldName, boolean shouldStoreInCache) {
        TimestampLockingPolicy policy = new TimestampLockingPolicy(writeLockFieldName);
        if (shouldStoreInCache) {
            policy.storeInCache();
        } else {
            policy.storeInObject();
        }
        setOptimisticLockingPolicy(policy);
    }

    /**
     * PUBLIC:
     * Default to use the version locking policy and storing the value in the cache key
     * #see useVersionLocking(String)
     */
    public void useVersionLocking(String writeLockFieldName) {
        useVersionLocking(writeLockFieldName, true);
    }

    /**
     * PUBLIC:
     * Set the locking policy to use numeric version locking.
     * This updates the version field on all updates, first comparing that the field has not changed to detect locking conflicts.
     *
     * The parameter 'shouldStoreInCache' configures the version lock value to be stored in the cache or in the object.
     * Note: if using a stateless model where the object can be passed to a client and then later updated in a different transaction context,
     * then the version lock value should not be stored in the cache, but in the object to ensure it is the correct value for that object.
     * @see TimestampLockingPolicy
     */
    public void useVersionLocking(String writeLockFieldName, boolean shouldStoreInCache) {
        VersionLockingPolicy policy = new VersionLockingPolicy(writeLockFieldName);
        if (shouldStoreInCache) {
            policy.storeInCache();
        } else {
            policy.storeInObject();
        }
        setOptimisticLockingPolicy(policy);
    }

    /**
     * PUBLIC:
     * Set the class of identity map to be the weak identity map.
     * The default is the "SoftCacheWeakIdentityMap".
     */
    public void useWeakIdentityMap() {
        getCachePolicy().useWeakIdentityMap();
    }

    /**
     * INTERNAL:
     * Validate the entire post-initialization descriptor.
     */
    protected void validateAfterInitialization(AbstractSession session) {
        selfValidationAfterInitialization(session);
        for (DatabaseMapping mapping : getMappings()) {
            mapping.validateAfterInitialization(session);
        }
    }

    /**
     * INTERNAL:
     * Validate the entire pre-initialization descriptor.
     */
    protected void validateBeforeInitialization(AbstractSession session) {
        selfValidationBeforeInitialization(session);
        for (DatabaseMapping mapping : getMappings()) {
            mapping.validateBeforeInitialization(session);
        }
    }

    /**
     * INTERNAL:
     * Check that the qualifier on the table names are properly set.
     */
    protected void verifyTableQualifiers(Platform platform) {
        String tableQualifier = platform.getTableQualifier();
        if (tableQualifier.length() == 0) {
            return;
        }

        for (DatabaseTable table : getTables()) {
            if (table.getTableQualifier().length() == 0) {
                table.setTableQualifier(tableQualifier);
            }
        }
    }

    /**
     * ADVANCED:
     * Return the cmp descriptor that holds cmp specific information.
     * A null return will mean that the descriptor does not represent an Entity,
     * however it may still represent a MappedSuperclass.
     * It will be null if it is not being used.
     */
    public CMPPolicy getCMPPolicy() {
        return cmpPolicy;
    }

    /**
     * ADVANCED:
     * Set the cmp descriptor that holds cmp specific information.
     */
    public void setCMPPolicy(CMPPolicy newCMPPolicy) {
        cmpPolicy = newCMPPolicy;
        if (cmpPolicy != null) {
            cmpPolicy.setDescriptor(this);
        }
    }

    /**
     * Return the cache policy.
     * The cache policy allows for the configuration of caching options.
     */
    public CachePolicy getCachePolicy() {
        if (this.cachePolicy == null) {
            this.cachePolicy = new CachePolicy();
        }
        return cachePolicy;
    }

    /**
     * ADVANCED:
     * Set cache policy for the descriptor.
     */
    public void setCachePolicy(CachePolicy cachePolicy) {
        this.cachePolicy = cachePolicy;
    }

    /**
     * INTERNAL:
     */
    public boolean hasPessimisticLockingPolicy() {
        return (cmpPolicy != null) && cmpPolicy.hasPessimisticLockingPolicy();
    }

    /**
     * PUBLIC:
     * Get the fetch group manager for the descriptor.  The fetch group manager is responsible
     * for managing the fetch group behaviors and operations.
     * To use the fetch group, the domain object must implement FetchGroupTracker interface. Otherwise,
     * a descriptor validation exception would throw during initialization.
     *
     * @see org.eclipse.persistence.queries.FetchGroupTracker
     */
    public FetchGroupManager getFetchGroupManager() {
        return this.fetchGroupManager;
    }

    /**
     * @return the fullyMergeEntity
     */
    public boolean getFullyMergeEntity() {
        return getCachePolicy().getFullyMergeEntity();
    }

    /**
     * PUBLIC:
     * Set the fetch group manager for the descriptor.  The fetch group manager is responsible
     * for managing the fetch group behaviors and operations.
     */
    public void setFetchGroupManager(FetchGroupManager fetchGroupManager) {
        this.fetchGroupManager = fetchGroupManager;
        if (fetchGroupManager != null) {
            //set the back reference
            fetchGroupManager.setDescriptor(this);
        }
    }

    /**
     * INTERNAL:
     * Return if the descriptor has a fetch group manager associated with.
     */
    public boolean hasFetchGroupManager() {
        return (fetchGroupManager != null);
    }

    /**
     * INTERNAL:
     */
    public boolean hasCascadeLockingPolicies() {
        return (this.cascadeLockingPolicies != null) && !this.cascadeLockingPolicies.isEmpty();
    }

    /**
     * INTERNAL:
     * Return if the descriptor has a CMP policy.
     */
    public boolean hasCMPPolicy() {
        return (cmpPolicy != null);
    }

    /**
     * INTERNAL:
     *
     * Return the default fetch group on the descriptor.
     * All read object and read all queries will use the default fetch group if
     * no fetch group is explicitly defined for the query.
     */
    public FetchGroup getDefaultFetchGroup() {
        if (!hasFetchGroupManager()) {
            //fetch group manager is not set, therefore no default fetch group.
            return null;
        }
        return getFetchGroupManager().getDefaultFetchGroup();
    }

    /**
     * INTERNAL:
     * Indicates if a return type is required for the field set on the
     * returning policy.  For relational descriptors, this should always
     * return true.
     */
    public boolean isReturnTypeRequiredForReturningPolicy() {
        return true;
    }

    /**
     * ADVANCED:
     * Set if the descriptor requires usage of a native (unwrapped) JDBC connection.
     * This may be required for some Oracle JDBC support when a wrapping DataSource is used.
     */
    public void setIsNativeConnectionRequired(boolean isNativeConnectionRequired) {
        this.isNativeConnectionRequired = isNativeConnectionRequired;
    }

    /**
     * ADVANCED:
     * Return if the descriptor requires usage of a native (unwrapped) JDBC connection.
     * This may be required for some Oracle JDBC support when a wrapping DataSource is used.
     */
    public boolean isNativeConnectionRequired() {
        return isNativeConnectionRequired;
    }

    /**
     * ADVANCED:
     * Set what types are allowed as a primary key (id).
     */
    public void setIdValidation(IdValidation idValidation) {
        this.idValidation = idValidation;
        if (getPrimaryKeyIdValidations() != null) {
            for (int index = 0; index < getPrimaryKeyIdValidations().size(); index++) {
                getPrimaryKeyIdValidations().set(index, idValidation);
            }
        }
    }

    /**
     * ADVANCED:
     * Return what types are allowed as a primary key (id).
     */
    public IdValidation getIdValidation() {
        return idValidation;
    }

    /**
     * ADVANCED:
     * Return what types are allowed in each primary key field (id).
     */
    public List<IdValidation> getPrimaryKeyIdValidations() {
        return primaryKeyIdValidations;
    }

    /**
     * ADVANCED:
     * Return what types are allowed in each primary key field (id).
     */
    public void setPrimaryKeyIdValidations(List<IdValidation> primaryKeyIdValidations) {
        this.primaryKeyIdValidations = primaryKeyIdValidations;
    }

    /**
     * ADVANCED:
     * Set what cache key type to use to store the object in the cache.
     */
    public void setCacheKeyType(CacheKeyType cacheKeyType) {
        getCachePolicy().setCacheKeyType(cacheKeyType);
    }

    /**
     * ADVANCED:
     * Return what cache key type to use to store the object in the cache.
     */
    public CacheKeyType getCacheKeyType() {
        return getCachePolicy().getCacheKeyType();
    }

    /**
     * A Default Query Redirector will be applied to any executing object query
     * that does not have a more precise default (like the default
     * ReadObjectQuery Redirector) or a redirector set directly on the query.
     * Query redirectors allow the user to intercept query execution preventing
     * it or alternately performing some side effect like auditing.
     *
     * @see org.eclipse.persistence.queries.QueryRedirector
     */
    public QueryRedirector getDefaultQueryRedirector() {
        return defaultQueryRedirector;
    }

    /**
     * A Default Query Redirector will be applied to any executing object query
     * that does not have a more precise default (like the default
     * ReadObjectQuery Redirector) or a redirector set directly on the query.
     * Query redirectors allow the user to intercept query execution preventing
     * it or alternately performing some side effect like auditing.
     *
     * @see org.eclipse.persistence.queries.QueryRedirector
     */
    public void setDefaultQueryRedirector(QueryRedirector defaultRedirector) {
        this.defaultQueryRedirector = defaultRedirector;
    }

    /**
     * A Default ReadAllQuery Redirector will be applied to any executing
     * ReadAllQuery that does not have a redirector set directly on the query.
     * Query redirectors allow the user to intercept query execution preventing
     * it or alternately performing some side effect like auditing.
     *
     * @see org.eclipse.persistence.queries.QueryRedirector
     */
    public QueryRedirector getDefaultReadAllQueryRedirector() {
        return defaultReadAllQueryRedirector;
    }

    /**
     * A Default ReadAllQuery Redirector will be applied to any executing
     * ReadAllQuery that does not have a redirector set directly on the query.
     * Query redirectors allow the user to intercept query execution preventing
     * it or alternately performing some side effect like auditing.
     *
     * @see org.eclipse.persistence.queries.QueryRedirector
     */
    public void setDefaultReadAllQueryRedirector(
            QueryRedirector defaultReadAllQueryRedirector) {
        this.defaultReadAllQueryRedirector = defaultReadAllQueryRedirector;
    }

    /**
     * A Default ReadObjectQuery Redirector will be applied to any executing
     * ReadObjectQuery that does not have a redirector set directly on the query.
     * Query redirectors allow the user to intercept query execution preventing
     * it or alternately performing some side effect like auditing.
     *
     * @see org.eclipse.persistence.queries.QueryRedirector
     */
    public QueryRedirector getDefaultReadObjectQueryRedirector() {
        return defaultReadObjectQueryRedirector;
    }

    /**
     * A Default ReadObjectQuery Redirector will be applied to any executing
     * ReadObjectQuery that does not have a redirector set directly on the query.
     * Query redirectors allow the user to intercept query execution preventing
     * it or alternately performing some side effect like auditing.
     *
     * @see org.eclipse.persistence.queries.QueryRedirector
     */
    public void setDefaultReadObjectQueryRedirector(
            QueryRedirector defaultReadObjectQueryRedirector) {
        this.defaultReadObjectQueryRedirector = defaultReadObjectQueryRedirector;
    }

    /**
     * A Default ReportQuery Redirector will be applied to any executing
     * ReportQuery that does not have a redirector set directly on the query.
     * Query redirectors allow the user to intercept query execution preventing
     * it or alternately performing some side effect like auditing.
     *
     * @see org.eclipse.persistence.queries.QueryRedirector
     */
    public QueryRedirector getDefaultReportQueryRedirector() {
        return defaultReportQueryRedirector;
    }

    /**
     * A Default ReportQuery Redirector will be applied to any executing
     * ReportQuery that does not have a redirector set directly on the query.
     * Query redirectors allow the user to intercept query execution preventing
     * it or alternately performing some side effect like auditing.
     *
     * @see org.eclipse.persistence.queries.QueryRedirector
     */
    public void setDefaultReportQueryRedirector(
            QueryRedirector defaultReportQueryRedirector) {
        this.defaultReportQueryRedirector = defaultReportQueryRedirector;
    }

    /**
     * A Default UpdateObjectQuery Redirector will be applied to any executing
     * UpdateObjectQuery or UpdateAllQuery that does not have a redirector set directly on the query.
     * Query redirectors allow the user to intercept query execution preventing
     * it or alternately performing some side effect like auditing.
     *
     * @see org.eclipse.persistence.queries.QueryRedirector
     */
    public QueryRedirector getDefaultUpdateObjectQueryRedirector() {
        return defaultUpdateObjectQueryRedirector;
    }

    /**
     * A Default UpdateObjectQuery Redirector will be applied to any executing
     * UpdateObjectQuery or UpdateAllQuery that does not have a redirector set directly on the query.
     * Query redirectors allow the user to intercept query execution preventing
     * it or alternately performing some side effect like auditing.
     *
     * @see org.eclipse.persistence.queries.QueryRedirector
     */
    public void setDefaultUpdateObjectQueryRedirector(QueryRedirector defaultUpdateQueryRedirector) {
        this.defaultUpdateObjectQueryRedirector = defaultUpdateQueryRedirector;
    }

    /**
     * A Default InsertObjectQuery Redirector will be applied to any executing
     * InsertObjectQuery that does not have a redirector set directly on the query.
     * Query redirectors allow the user to intercept query execution preventing
     * it or alternately performing some side effect like auditing.
     *
     * @see org.eclipse.persistence.queries.QueryRedirector
     */
    public QueryRedirector getDefaultInsertObjectQueryRedirector() {
        return defaultInsertObjectQueryRedirector;
    }

    /**
     * A Default InsertObjectQuery Redirector will be applied to any executing
     * InsertObjectQuery that does not have a redirector set directly on the query.
     * Query redirectors allow the user to intercept query execution preventing
     * it or alternately performing some side effect like auditing.
     *
     * @see org.eclipse.persistence.queries.QueryRedirector
     */
    public void setDefaultInsertObjectQueryRedirector(QueryRedirector defaultInsertQueryRedirector) {
        this.defaultInsertObjectQueryRedirector = defaultInsertQueryRedirector;
    }

    /**
     * A Default DeleteObjectQuery Redirector will be applied to any executing
     * DeleteObjectQuery or DeleteAllQuery that does not have a redirector set directly on the query.
     * Query redirectors allow the user to intercept query execution preventing
     * it or alternately performing some side effect like auditing.
     *
     * @see org.eclipse.persistence.queries.QueryRedirector
     */
    public QueryRedirector getDefaultDeleteObjectQueryRedirector() {
        return defaultDeleteObjectQueryRedirector;
    }

    /**
     * A Default DeleteObjectQuery Redirector will be applied to any executing
     * DeleteObjectQuery or DeleteAllQuery that does not have a redirector set directly on the query.
     * Query redirectors allow the user to intercept query execution preventing
     * it or alternately performing some side effect like auditing.
     *
     * @see org.eclipse.persistence.queries.QueryRedirector
     */
    public void setDefaultDeleteObjectQueryRedirector(QueryRedirector defaultDeleteObjectQueryRedirector) {
        this.defaultDeleteObjectQueryRedirector = defaultDeleteObjectQueryRedirector;
    }

    /**
     * A Default Query Redirector will be applied to any executing object query
     * that does not have a more precise default (like the default
     * ReadObjectQuery Redirector) or a redirector set directly on the query.
     * Query redirectors allow the user to intercept query execution preventing
     * it or alternately performing some side effect like auditing.
     *
     * @see org.eclipse.persistence.queries.QueryRedirector
     */
    public void setDefaultQueryRedirectorClassName(String defaultQueryRedirectorClassName) {
        this.defaultQueryRedirectorClassName = defaultQueryRedirectorClassName;
    }

    /**
     * A Default ReadAllQuery Redirector will be applied to any executing
     * ReadAllQuery that does not have a redirector set directly on the query.
     * Query redirectors allow the user to intercept query exection preventing
     * it or alternately performing some side effect like auditing.
     *
     * @see org.eclipse.persistence.queries.QueryRedirector
     */
    public void setDefaultReadAllQueryRedirectorClassName(String defaultReadAllQueryRedirectorClassName) {
        this.defaultReadAllQueryRedirectorClassName = defaultReadAllQueryRedirectorClassName;
    }

    /**
     * A Default ReadObjectQuery Redirector will be applied to any executing
     * ReadObjectQuery that does not have a redirector set directly on the query.
     * Query redirectors allow the user to intercept query execution preventing
     * it or alternately performing some side effect like auditing.
     *
     * @see org.eclipse.persistence.queries.QueryRedirector
     */
    public void setDefaultReadObjectQueryRedirectorClassName(
            String defaultReadObjectQueryRedirectorClassName) {
        this.defaultReadObjectQueryRedirectorClassName = defaultReadObjectQueryRedirectorClassName;
    }

    /**
     * A Default ReportQuery Redirector will be applied to any executing
     * ReportQuery that does not have a redirector set directly on the query.
     * Query redirectors allow the user to intercept query execution preventing
     * it or alternately performing some side effect like auditing.
     *
     * @see org.eclipse.persistence.queries.QueryRedirector
     */
   public void setDefaultReportQueryRedirectorClassName(
            String defaultReportQueryRedirectorClassName) {
        this.defaultReportQueryRedirectorClassName = defaultReportQueryRedirectorClassName;
    }

   /**
    * A Default UpdateObjectQuery Redirector will be applied to any executing
    * UpdateObjectQuery or UpdateAllQuery that does not have a redirector set directly on the query.
    * Query redirectors allow the user to intercept query execution preventing
    * it or alternately performing some side effect like auditing.
    *
    * @see org.eclipse.persistence.queries.QueryRedirector
    */
    public void setDefaultUpdateObjectQueryRedirectorClassName(
            String defaultUpdateObjectQueryRedirectorClassName) {
        this.defaultUpdateObjectQueryRedirectorClassName = defaultUpdateObjectQueryRedirectorClassName;
    }

    /**
     * A Default InsertObjectQuery Redirector will be applied to any executing
     * InsertObjectQuery that does not have a redirector set directly on the query.
     * Query redirectors allow the user to intercept query exection preventing
     * it or alternately performing some side effect like auditing.
     *
     * @see org.eclipse.persistence.queries.QueryRedirector
     */
    public void setDefaultInsertObjectQueryRedirectorClassName(
            String defaultInsertObjectQueryRedirectorClassName) {
        this.defaultInsertObjectQueryRedirectorClassName = defaultInsertObjectQueryRedirectorClassName;
    }

    /**
     * A Default DeleteObjectQuery Redirector will be applied to any executing
     * DeleteObjectQuery or DeleteAllQuery that does not have a redirector set directly on the query.
     * Query redirectors allow the user to intercept query exection preventing
     * it or alternately performing some side effect like auditing.
     *
     * @see org.eclipse.persistence.queries.QueryRedirector
     */
    public void setDefaultDeleteObjectQueryRedirectorClassName(
            String defaultDeleteObjectQueryRedirectorClassName) {
        this.defaultDeleteObjectQueryRedirectorClassName = defaultDeleteObjectQueryRedirectorClassName;
    }

    /**
     * Return the descriptor's sequence.
     * This is normally set when the descriptor is initialized.
     */
    public Sequence getSequence() {
        return sequence;
    }

    /**
     * Set the descriptor's sequence.
     * This is normally set when the descriptor is initialized.
     */
    public void setSequence(Sequence sequence) {
        this.sequence = sequence;
    }

    /**
     * Mappings that require postCalculateChanges method to be called
     */
    public List<DatabaseMapping> getMappingsPostCalculateChanges() {
        if(mappingsPostCalculateChanges == null) {
            mappingsPostCalculateChanges = new ArrayList<>();
        }
        return mappingsPostCalculateChanges;
    }

    /**
     * Are there any mappings that require postCalculateChanges method to be called.
     */
    public boolean hasMappingsPostCalculateChanges() {
        return mappingsPostCalculateChanges != null;
    }

    /**
     * Add a mapping to the list of mappings that require postCalculateChanges method to be called.
     */
    public void addMappingsPostCalculateChanges(DatabaseMapping mapping) {
        //474752 :ReferenceDescriptor may not be available during
        //predeploy.  It is required for calculating changes.
        if (mapping.getReferenceDescriptor() != null) {
            getMappingsPostCalculateChanges().add(mapping);
        }
    }

    /**
     * Mappings that require mappingsPostCalculateChangesOnDeleted method to be called
     */
    public List<DatabaseMapping> getMappingsPostCalculateChangesOnDeleted() {
        if (mappingsPostCalculateChangesOnDeleted == null) {
            mappingsPostCalculateChangesOnDeleted = new ArrayList<>();
        }
        return mappingsPostCalculateChangesOnDeleted;
    }

    /**
     * Are there any mappings that require mappingsPostCalculateChangesOnDeleted method to be called.
     */
    public boolean hasMappingsPostCalculateChangesOnDeleted() {
        return mappingsPostCalculateChangesOnDeleted != null;
    }

    /**
     * Add a mapping to the list of mappings that require mappingsPostCalculateChangesOnDeleted method to be called.
     */
    public void addMappingsPostCalculateChangesOnDeleted(DatabaseMapping mapping) {
        getMappingsPostCalculateChangesOnDeleted().add(mapping);
    }

    /**
     * Return if any mapping reference a field in a secondary table.
     * This is used to disable deferring multiple table writes.
     */
    public boolean hasMultipleTableConstraintDependecy() {
        return hasMultipleTableConstraintDependecy;
    }

    /**
     * Return true if the descriptor has a multitenant policy
     */
    public boolean hasMultitenantPolicy() {
        return multitenantPolicy != null;
    }
    /**
     * PUBLIC
     * @return true if this descriptor is configured with a table per tenant policy.
     */
    public boolean hasTablePerMultitenantPolicy() {
        return hasMultitenantPolicy() && getMultitenantPolicy().isTablePerMultitenantPolicy();
    }

    /**
     * INTERNAL:
     * Used to store un-converted properties, which are subsequenctly converted
     * at runtime (through the convertClassNamesToClasses method.
     */
    public boolean hasUnconvertedProperties() {
        return unconvertedProperties != null;
    }

    /**
     * Set if any mapping reference a field in a secondary table.
     * This is used to disable deferring multiple table writes.
     */
    public void setHasMultipleTableConstraintDependecy(boolean hasMultipleTableConstraintDependecy) {
        this.hasMultipleTableConstraintDependecy = hasMultipleTableConstraintDependecy;
    }

    /**
     * INTERNAL:
     * Return whether this descriptor uses property access. This information is used to
     * modify the behavior of some of our weaving features
     */
    public boolean usesPropertyAccessForWeaving(){
        return weavingUsesPropertyAccess;
    }


    /**
     * INTERNAL:
     * Record that this descriptor uses property access. This information is used to
     * modify the behavior of some of our weaving features
     */
    public void usePropertyAccessForWeaving(){
        weavingUsesPropertyAccess = true;
    }

    /**
     * INTERNAL:
     * Return the list of virtual methods sets for this Entity.
     * This list is used to control which methods are weaved
     **/
    public List<VirtualAttributeMethodInfo> getVirtualAttributeMethods() {
        if (this.virtualAttributeMethods == null) {
            this.virtualAttributeMethods = new ArrayList<>();
        }
        return this.virtualAttributeMethods;
    }

    /**
     * INTERNAL:
     * Set the list of methods used my mappings with virtual access
     * this list is used to determine which methods to weave
     */
    public void setVirtualAttributeMethods(List<VirtualAttributeMethodInfo> virtualAttributeMethods) {
        this.virtualAttributeMethods = virtualAttributeMethods;
    }

    /**
     * INTERNAL:
     * Indicates whether descriptor has at least one target foreign key mapping
     */
    public boolean hasTargetForeignKeyMapping(AbstractSession session) {
        for (DatabaseMapping mapping: getMappings()) {
            if (mapping.isCollectionMapping() ||
                    (mapping.isObjectReferenceMapping() && !((ObjectReferenceMapping)mapping).isForeignKeyRelationship()) ||
                    mapping.isAbstractCompositeDirectCollectionMapping()) {
                return true;
            } else if (mapping.isAggregateObjectMapping()) {
                ClassDescriptor referenceDescriptor = mapping.getReferenceDescriptor();
                if (referenceDescriptor == null) {
                    // the mapping has not been initialized yet
                    referenceDescriptor = session.getDescriptor(((AggregateObjectMapping)mapping).getReferenceClass());
                }
                if (referenceDescriptor.hasTargetForeignKeyMapping(session)) {
                    return true;
                }
            }
        }
        return false;
    }

    @Override
    public AttributeGroup getAttributeGroup(String name) {
        return super.getAttributeGroup(name);
    }

    @Override
    public Map<String, AttributeGroup> getAttributeGroups() {
        return super.getAttributeGroups();
    }

    /**
     * INTERNAL:
     * Cleans referencingClasses set. Called from ClientSession for proper cleanup and avoid memory leak.
     */
    public void clearReferencingClasses() {
        this.referencingClasses.clear();
    }
}
