/*
 * Copyright (c) 2011, 2021 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     03/19/2009-2.0  dclarke  - initial API start
//     06/30/2009-2.0  mobrien - finish JPA Metadata API modifications in support
//       of the Metamodel implementation for EclipseLink 2.0 release involving
//       Map, ElementCollection and Embeddable types on MappedSuperclass descriptors
//       - 266912: JPA 2.0 Metamodel API (part of the JSR-317 EJB 3.1 Criteria API)
//     07/06/2009-2.0  mobrien - 266912: Introduce IdentifiableTypeImpl between ManagedTypeImpl
//       - EntityTypeImpl now inherits from IdentifiableTypeImpl instead of ManagedTypeImpl
//       - MappedSuperclassTypeImpl now inherits from IdentifiableTypeImpl instead
//       of implementing IdentifiableType indirectly
//       - implement Set<SingularAttribute<? super X, ?>> getSingularAttributes()
//     07/09/2009-2.0  mobrien - 266912: implement get//Attribute() functionality
//       - functions throw 2 types of IllegalArgumentExceptions depending on whether
//         the member is missing or is the wrong type - see design issue #41
//         http://wiki.eclipse.org/EclipseLink/Development/JPA_2.0/metamodel_api#DI_41:_When_to_throw_IAE_for_missing_member_or_wrong_type_on_get.28.29_call
//     07/14/2009-2.0  mobrien - 266912: implement getDeclared//() functionality
//       - Implement 14 functions for ManagedType - see design issue #43
//         http://wiki.eclipse.org/EclipseLink/Development/JPA_2.0/metamodel_api#DI_43:_20090710:_Implement_getDeclaredX.28.29_methods
//     07/28/2009-2.0  mobrien - 284877: implement recursive functionality for hasDeclaredAttribute()
//       - see design issue #52
//         http://wiki.eclipse.org/EclipseLink/Development/JPA_2.0/metamodel_api#DI_52:_20090728:_JPA_2:_Implement_recursive_ManagedType.getDeclared.2A_algorithm_to_differentiate_by_IdentifiableType
//     08/08/2009-2.0  mobrien - 266912: implement Collection and List separation during attribute initialization
//       - see design issue #58
//       http://wiki.eclipse.org/EclipseLink/Development/JPA_2.0/metamodel_api#DI_58:_20090807:_ManagedType_Attribute_Initialization_must_differentiate_between_Collection_and_List
//     08/17/2009-2.0  mobrien - 284877: The base case for the recursive function
//         managedTypeImpl.hasDeclaredAttribute() does not handle use case 1.4 (root-level managedType)
//         when the caller of the function does not do it's own inheritedType check.
//       - see design issue #52
//         http://wiki.eclipse.org/EclipseLink/Development/JPA_2.0/metamodel_api#DI:52_Refactor:_20090817
//     08/19/2009-2.0  mobrien - 266912: Handle MappedSuperclass in ManagedTypeImpl.create()
//       - see design issue #39 (partial)
//       http://wiki.eclipse.org/EclipseLink/Development/JPA_2.0/metamodel_api#DI_39:_20090708:_Handle_MappedSuperclass_in_ManagedTypeImpl.create.28.29
//     08/19/2009-2.0  mobrien - 266912: ManagedType.getDeclaredX() leaks members into entity-entity hierarchy
//       - see design issue #61
//       http://wiki.eclipse.org/EclipseLink/Development/JPA_2.0/metamodel_api#DI_61:_20090820:_ManagedType.getDeclaredX.28.29_leaks_members_into_entity-entity_hierarchy
//     06/01/2010-2.1  mobrien - 315287: Handle BasicType as inheritance root for ManagedTypes
//       - see design issue #103
//       http://wiki.eclipse.org/EclipseLink/Development/JPA_2.0/metamodel_api#DI_103:_20100601:_315287:_Handle_BasicType_as_inheritance_root_for_ManagedTypes
//     09/09/2010-2.2  mobrien - 322166: If attribute is defined on this current ManagedType (and not on a superclass)
//       - do not attempt a reflective call on a superclass
//       - see design issue #25
//       http://wiki.eclipse.org/EclipseLink/Development/JPA_2.0/metamodel_api#DI_25:_20090616:_Inherited_parameterized_generics_for_Element_Collections_.28Basic.29
//
package org.eclipse.persistence.internal.jpa.metamodel;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import jakarta.persistence.metamodel.Attribute;
import jakarta.persistence.metamodel.CollectionAttribute;
import jakarta.persistence.metamodel.ListAttribute;
import jakarta.persistence.metamodel.ManagedType;
import jakarta.persistence.metamodel.MapAttribute;
import jakarta.persistence.metamodel.PluralAttribute;
import jakarta.persistence.metamodel.PluralAttribute.CollectionType;
import jakarta.persistence.metamodel.SetAttribute;
import jakarta.persistence.metamodel.SingularAttribute;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.internal.descriptors.InstanceVariableAttributeAccessor;
import org.eclipse.persistence.internal.descriptors.MethodAttributeAccessor;
import org.eclipse.persistence.internal.dynamic.ValuesAccessor;
import org.eclipse.persistence.internal.helper.BasicTypeHelperImpl;
import org.eclipse.persistence.internal.helper.ClassConstants;
import org.eclipse.persistence.internal.localization.ExceptionLocalization;
import org.eclipse.persistence.internal.queries.ContainerPolicy;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.internal.security.PrivilegedGetDeclaredField;
import org.eclipse.persistence.internal.security.PrivilegedGetDeclaredMethod;
import org.eclipse.persistence.logging.AbstractSessionLog;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.mappings.CollectionMapping;
import org.eclipse.persistence.mappings.DatabaseMapping;

/**
 * <p>
 * <b>Purpose</b>: Provides the implementation for the ManagedType interface
 *  of the JPA 2.0 Metamodel API (part of the JSR-317 EJB 3.1 Criteria API)
 * <p>
 * <b>Description</b>:
 *  Instances of the type ManagedType represent entities, mapped superclasses
 *   and embeddable types.
 *
 * @see jakarta.persistence.metamodel.ManagedType
 *
 * @since EclipseLink 1.2 - JPA 2.0
 * @param <X> The represented type.
 */
public abstract class ManagedTypeImpl<X> extends TypeImpl<X> implements ManagedType<X> {

    /** Native RelationalDescriptor that contains all the mappings of this type **/
    protected ClassDescriptor descriptor;

    /** The map of attributes keyed on attribute string name **/
    private Map<String, Attribute<X,?>> members;

    /** Reference to the metamodel that this managed type belongs to **/
    protected MetamodelImpl metamodel;

    /**
     * INTERNAL:
     * This constructor will create a ManagedType but will not initialize its member mappings.
     * This is accomplished by delayed initialization in MetamodelImpl.initialize()
     * in order that we have access to all types when resolving relationships in mappings.
     * @param metamodel - the metamodel that this managedType is associated with
     * @param descriptor - the RelationalDescriptor that defines this managedType
     */
    protected ManagedTypeImpl(MetamodelImpl metamodel, ClassDescriptor descriptor) {
        // A valid descriptor will always have a javaClass set except in bug# 303063
        super(descriptor.getJavaClass(), descriptor.getJavaClassName());
        this.descriptor = descriptor;
        // the metamodel field must be instantiated prior to any *AttributeImpl instantiation which will use the metamodel
        this.metamodel = metamodel;
        // Cache the ManagedType on the descriptor - avoid doing this, use metamodel map instead.
        // descriptor.setProperty(getClass().getName(), this);
        metamodel.getManagedTypesMap().put(descriptor.getJavaClassName(), this);
        // Note: Full initialization of the ManagedType occurs during MetamodelImpl.initialize() after all types are instantiated
    }

    /**
     *  Return the attribute of the managed
     *  type that corresponds to the specified name.
     *  @param name  the name of the represented attribute
     *  @return attribute with given name
     *  @throws IllegalArgumentException if attribute of the given
     *          name is not present in the managed type
     */
    @Override
    public Attribute<X, ?> getAttribute(String name) {
        if(!members.containsKey(name)) {
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage(
                    "metamodel_managed_type_attribute_not_present",
                    new Object[] { name, this }));
        }
        return members.get(name);
    }

    /**
     *  Return the attributes of the managed type.
     */
    @Override
    public Set<Attribute<? super X, ?>> getAttributes() {
        // We return a new Set instead of directly returning the Collection of values from the members HashMap
        return new LinkedHashSet<Attribute<? super X, ?>>(this.members.values());
    }


    /**
     *  Return the Collection-valued attribute of the managed type
     *  that corresponds to the specified name.
     *  @param name  the name of the represented attribute
     *  @return CollectionAttribute of the given name
     *  @throws IllegalArgumentException if attribute of the given
     *          name is not present in the managed type
     */
    @Override
    public CollectionAttribute<? super X, ?> getCollection(String name) {
        // Get the named collection from the set directly
        /*
         * Note: We do not perform type checking on the get(name)
         * If the type is not of the correct Attribute implementation class then
         * a possible CCE will be allowed to propagate to the client.
         * For example if a getCollection() is performed on a ListAttribute a CCE will occur
         */
        CollectionAttribute<? super X, ?> anAttribute = (CollectionAttribute<? super X, ?>)this.members.get(name);
        if(null == anAttribute) {
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage(
                    "metamodel_managed_type_attribute_not_present",
                    new Object[] { name, this }));
        }
        return anAttribute;
    }

    /**
     *  Return the Collection-valued attribute of the managed type
     *  that corresponds to the specified name and Java element type.
     *  @param name  the name of the represented attribute
     *  @param elementType  the element type of the represented
     *                      attribute
     *  @return CollectionAttribute of the given name and element
     *          type
     *  @throws IllegalArgumentException if attribute of the given
     *          name and type is not present in the managed type
     */
    @Override
    public <E> CollectionAttribute<? super X, E> getCollection(String name, Class<E> elementType) {
        // We do not use getCollection(name) so that we can catch a possible CCE on the wrong attribute type
        Attribute<? super X, E> anAttribute = (Attribute<? super X, E>)this.members.get(name);
        if(null == anAttribute) {
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage(
                    "metamodel_managed_type_attribute_not_present",
                    new Object[] { name, this }));
        } else {
            // Throw appropriate IAException if required
            verifyAttributeTypeAndReturnType(anAttribute, elementType, CollectionType.COLLECTION);
        }
        return (CollectionAttribute<? super X, E>)anAttribute;
    }

    /**
     *  Return all collection-valued attributes of the managed type.
     *  @return collection valued attributes
     */
    @Override
    public Set<PluralAttribute<? super X, ?, ?>> getPluralAttributes() {
        // Get all attributes and filter only for PluralAttributes
        Set<Attribute<? super X, ?>> allAttributes = this.getAttributes();
        // Is it better to add to a new Set or remove from an existing Set without a concurrentModificationException
        Set<PluralAttribute<? super X, ?, ?>> pluralAttributes = new LinkedHashSet<PluralAttribute<? super X, ?, ?>>();
        for(Attribute<? super X, ?> anAttribute : allAttributes) {
            // Add only CollectionType attributes
            if(anAttribute.isCollection()) {
                pluralAttributes.add((PluralAttribute<? super X, ?, ?>)anAttribute);

            }
        }
        return pluralAttributes;
    }

    /**
     *  INTERNAL:
     *  Return the declared attribute of the managed
     *  type that corresponds to the specified name.
     *  @param name  the name of the represented attribute
     *  @param attributeKnownToExistOnLeafTarget true if we already know the attribute exists on the leaf
     *  @return attribute with given name
     *  @throws IllegalArgumentException if attribute of the given
     *          name is not declared in the managed type
     */
    protected Attribute<X, ?> getDeclaredAttribute(String name, boolean attributeKnownToExistOnLeafTarget){
        // get the attribute parameterized by <Owning type, return Type> - throw an IAE if not found (no need to check hierarchy)
        // Handles UC1 and UC2
        Attribute<X, ?> anAttribute = getAttribute(name);
        // If an Attribute is found then check the hierarchy for a declaration in the superclass(s)
        // Keep moving up only when the attribute is not found
        ManagedTypeImpl aManagedSuperType = getManagedSuperType();
        if(null == aManagedSuperType) {
            return anAttribute;
        } else {
           boolean isDeclaredAboveLeaf = false;
           // keep checking the hierarchy but skip this level and go directly to the superType
            if(attributeKnownToExistOnLeafTarget) {
                isDeclaredAboveLeaf = aManagedSuperType.isAttributeDeclaredOnlyInLeafType(name, anAttribute);
            } else {
               isDeclaredAboveLeaf = aManagedSuperType.isAttributeDeclaredOnlyInLeafType(name);
            }
            // Cases 10 and 01 throw an IAE, cases 00 and 11 are normal - an Exclusive OR (EOR)
            if((attributeKnownToExistOnLeafTarget && !isDeclaredAboveLeaf) || (!attributeKnownToExistOnLeafTarget && isDeclaredAboveLeaf)) {
                // Handles UC4 and UC5 - throw an IAE if the class is declared above
                throw new IllegalArgumentException(ExceptionLocalization.buildMessage(
                    "metamodel_managed_type_declared_attribute_not_present_but_is_on_superclass",
                    new Object[] { name, this }));
            } else {
                // Handles UC3 (normal case - attribute is not declared on a superclass)
                return anAttribute;
            }
        }
    }

    /**
     *  Return the declared attribute of the managed
     *  type that corresponds to the specified name.
     *  @param name  the name of the represented attribute
     *  @return attribute with given name
     *  @throws IllegalArgumentException if attribute of the given
     *          name is not declared in the managed type
     */
    @Override
    public Attribute<X, ?> getDeclaredAttribute(String name){
        return getDeclaredAttribute(name, false);
    }

    /**
     * All getDeclared*(name, *) function calls require navigation up the superclass tree
     * in order to determine if the member name is declared on the current managedType.<p>
     * If the attribute is found anywhere above on the superclass tree - then throw an IAE.
     *
        Use Case Partitioning:
            - attribute positioning(none, current, 1st parent, Nth parent)
            - attribute type (right, wrong type)
            - attribute classification for current and parents (Entity, MappedSuperclass, embeddable?, Basic?)
            UC1) Attribute is not found on current attribute (regardless of what is on its' superclasses)
                    - throw IAException
            UC2) Attribute is found on current attribute but is of the wrong type
                    - throw IAException
            UC3) Attribute is found on on current managedType Entity/MappedSuperclass
                    (but not found anywhere on the supertype hierarchy - declared above)
                    In this case we do the reverse - keep checking only when attribute is null
                    - return attribute
            UC4) Attribute is declared on immediate superclass
                    - throw IAException
            UC5) Attribute is declared on Nth superclass
                    - throw IAException

                We use two functions, one public, one a private recursive function.
            If the attribute is not found at the current level or above, or is of the wrong type - throw an IAException
            If the attribute is found then we still need to search to the
                top of the hierarchy tree to verify it is not declared above
                - if it is also not found above - return the attribute in this case only
     */

    /**
     *  Return the attributes declared by the managed type.
     */
    @Override
    public Set<Attribute<X, ?>> getDeclaredAttributes() {
        // return only the set of attributes declared on this class - not via inheritance
        // Get all attributes and filter only for declared attributes
        Set<Attribute<X, ?>> allAttributes = new LinkedHashSet<Attribute<X, ?>>(this.members.values());;
        // Is it better to add to a new Set or remove from an existing Set without a concurrentModificationException
        Set<Attribute<X, ?>> declaredAttributes = new LinkedHashSet<Attribute<X, ?>>();
        for(Attribute<X, ?> anAttribute : allAttributes) {
            // Check the inheritance hierarchy for higher declarations
            if(this.isAttributeDeclaredOnlyInLeafType(anAttribute.getName())) {
                declaredAttributes.add(anAttribute);
            }
        }
        return declaredAttributes;
    }

    /**
     *  Return the Collection-valued attribute declared by the
     *  managed type that corresponds to the specified name.
     *  @param name  the name of the represented attribute
     *  @return declared CollectionAttribute of the given name
     *  @throws IllegalArgumentException if attribute of the given
     *          name is not declared in the managed type
     */
    @Override
    public CollectionAttribute<X, ?> getDeclaredCollection(String name) {
        // return only a collection declared on this class - not via inheritance
        // Handles UC1 and UC2
        CollectionAttribute<X, ?> anAttribute = (CollectionAttribute<X, ?>) getCollection(name);
        // The following verification step will throw an appropriate IAException if required (we can discard the return attribute here)
        getDeclaredAttribute(name);
        // We return an attribute that has passed through both a get and a declared inheritance check
        // all of which would throw an IAException before the return below.
        return anAttribute;
    }

    /**
     *  Return the Collection-valued attribute declared by the
     *  managed type that corresponds to the specified name and Java
     *  element type.
     *  @param name  the name of the represented attribute
     *  @param elementType  the element type of the represented
     *                      attribute
     *  @return declared CollectionAttribute of the given name and
     *          element type
     *  @throws IllegalArgumentException if attribute of the given
     *          name and type is not declared in the managed type
     */
    @Override
    public <E> CollectionAttribute<X, E> getDeclaredCollection(String name, Class<E> elementType) {
        // return only a collection declared on this class - not via inheritance
        // Handles UC1 and UC2
        CollectionAttribute<X, E> anAttribute = (CollectionAttribute<X, E>) getCollection(name, elementType);
        // The following verification step will throw an appropriate IAException if required (type checking has been done, and we can discard the return attribute here)
        getDeclaredAttribute(name);
        // We return an attribute that has passed through both a get, (optionally a type check) and a declared inheritance check
        // all of which would throw an IAException before the return below.
        return anAttribute;
    }

    /**
     *  Return all collection-valued attributes declared by the
     *  managed type.
     *  @return declared collection valued attributes
     */
    @Override
    public Set<PluralAttribute<X, ?, ?>> getDeclaredPluralAttributes() {
        // It is evident from the fact that we have only getAttributes(), getPluralAttributes() and getSingularAttributes() that a Collection is a superset of all Set, List and even Map
        // return only a set of collections declared on this class - not via inheritance
        // Get all collection attribute and filter only on declared ones
        Set<PluralAttribute<? super X, ?, ?>> pluralAttributes = this.getPluralAttributes();
        // Is it better to add to a new Set or remove from an existing Set without a concurrentModificationException
        Set<PluralAttribute<X, ?, ?>> declaredAttributes = new LinkedHashSet<PluralAttribute<X, ?, ?>>();
        // The set is a copy of the underlying metamodel attribute set - we will remove all SingularAttribute(s)
        for(PluralAttribute<? super X, ?, ?>  anAttribute :pluralAttributes) {
                // check for declarations in the hierarchy and don't add if declared above
                // add attributes that don't have superclasses automatically
                ManagedTypeImpl potentialSuperType = getManagedSuperType();
                if(null == potentialSuperType) {
                    declaredAttributes.add((PluralAttribute<X, ?, ?>)anAttribute);
                } else {
                    // add only if we reach the root without finding another declaration
                    if(!potentialSuperType.isAttributeDeclaredOnlyInLeafType(anAttribute.getName())) {
                        declaredAttributes.add((PluralAttribute<X, ?, ?>)anAttribute);
                    }
                }
        }
        return declaredAttributes;
    }


    /**
     * INTERNAL:
     * Return an instance of a ManagedType based on the RelationalDescriptor parameter
     */
    protected static ManagedTypeImpl<?> create(MetamodelImpl metamodel, ClassDescriptor descriptor) {
        // Get the ManagedType property on the descriptor if it exists
        ManagedTypeImpl<?> managedType = metamodel.getManagedTypesMap().get(descriptor.getJavaClassName());
        // Create an Entity, Embeddable or MappedSuperclass
        if (null == managedType) {
            // The descriptor can be one of NORMAL:0, INTERFACE:1 (not supported), AGGREGATE:2 or AGGREGATE_COLLECTION:3
            if(descriptor.isDescriptorForInterface()) {
                // INTERFACE:1 (not supported)
/*                throw new IllegalArgumentException(ExceptionLocalization.buildMessage(
                        "metamodel_interface_inheritance_not_supported",
                        new Object[] { descriptor, "Interface"}));
*/
                // Default to Entity
                managedType = new EntityTypeImpl(metamodel, descriptor);
            } else if (descriptor.isDescriptorTypeAggregate()) {
                // AGGREGATE:2 or AGGREGATE_COLLECTION:3
                managedType = new EmbeddableTypeImpl(metamodel, descriptor);
            } else if(descriptor.isDescriptorTypeNormal()) {

                // NORMAL:0 = ENTITY | MAPPEDSUPERCLASS
                // DI 39: Determine if the descriptor is a mappedSuperclass
                if(metamodel.hasMappedSuperclass(descriptor.getJavaClassName())) {
                    // MAPPEDSUPERCLASS - defer to subclass
                    managedType = MappedSuperclassTypeImpl.create(metamodel, descriptor);
                } else {
                    // ENTITY
                    managedType = new EntityTypeImpl(metamodel, descriptor);
                }
            } else {
                // unknown descriptor type (or > 3)
                throw new IllegalArgumentException(ExceptionLocalization.buildMessage(
                    "metamodel_interface_inheritance_not_supported",
                    new Object[] { descriptor, "Unknown"}));
            }
        }
        return managedType;
    }

    /**
     *  Return the List-valued attribute declared by the managed
     *  type that corresponds to the specified name and Java
     *  element type.
     *  @param name  the name of the represented attribute
     *  @param elementType  the element type of the represented
     *                      attribute
     *  @return declared ListAttribute of the given name and
     *          element type
     *  @throws IllegalArgumentException if attribute of the given
     *          name and type is not declared in the managed type
     */
    @Override
    public <E> ListAttribute<X, E> getDeclaredList(String name, Class<E> elementType) {
        // get the attribute parameterized by <Owning type, return Type> - throw an IAE if not found (no need to check hierarchy)
        // Handles UC1 and UC2
        ListAttribute<X, E> anAttribute = (ListAttribute<X, E>) getList(name, elementType);
        // The following verification step will throw an appropriate IAException if required (type checking has been done, and we can discard the return attribute here)
        getDeclaredAttribute(name);
        // We return an attribute that has passed through both a get, (optionally a type check) and a declared inheritance check
        // all of which would throw an IAException before the return below.
        return anAttribute;
    }

    /**
     *  Return the List-valued attribute declared by the managed
     *  type that corresponds to the specified name.
     *  @param name  the name of the represented attribute
     *  @return declared ListAttribute of the given name
     *  @throws IllegalArgumentException if attribute of the given
     *          name is not declared in the managed type
     */
    @Override
    public ListAttribute<X, ?> getDeclaredList(String name) {
        // return only a List declared on this class - not via inheritance
        // Handles UC1 and UC2
        ListAttribute<X, ?> anAttribute = (ListAttribute<X, ?>) getList(name);
        // The following verification step will throw an appropriate IAException if required (we can discard the return attribute here)
        getDeclaredAttribute(name);
        // We return an attribute that has passed through both a get and a declared inheritance check
        // all of which would throw an IAException before the return below.
        return anAttribute;
    }

    /**
     *  Return the Map-valued attribute of the managed type that
     *  corresponds to the specified name.
     *  @param name  the name of the represented attribute
     *  @return MapAttribute of the given name
     *  @throws IllegalArgumentException if attribute of the given
     *          name is not present in the managed type
     */
    @Override
    public MapAttribute<X, ?, ?> getDeclaredMap(String name) {
        // return only a map declared on this class - not via inheritance
        // Handles UC1 and UC2
        MapAttribute<X, ?, ?> anAttribute = (MapAttribute<X, ?, ?>) getMap(name);
        // The following verification step will throw an appropriate IAException if required (we can discard the return attribute here)
        getDeclaredAttribute(name);
        // We return an attribute that has passed through both a get and a declared inheritance check
        // all of which would throw an IAException before the return below.
        return anAttribute;
    }

    /**
     *  Return the Map-valued attribute of the managed type that
     *  corresponds to the specified name and Java key and value
     *  types.
     *  @param name  the name of the represented attribute
     *  @param keyType  the key type of the represented attribute
     *  @param valueType  the value type of the represented attribute
     *  @return MapAttribute of the given name and key and value
     *  types
     *  @throws IllegalArgumentException if attribute of the given
     *          name and type is not present in the managed type
     */
    @Override
    public <K, V> MapAttribute<X, K, V> getDeclaredMap(String name, Class<K> keyType, Class<V> valueType) {
        // return only a map declared on this class - not via inheritance
        // Handles UC1 and UC2
        MapAttribute<X, K, V> anAttribute = (MapAttribute<X, K, V>) getMap(name, keyType, valueType);
        // The following verification step will throw an appropriate IAException if required (type checking has been done, and we can discard the return attribute here)
        getDeclaredAttribute(name);
        // We return an attribute that has passed through both a get, (optionally a type check) and a declared inheritance check
        // all of which would throw an IAException before the return below.
        return anAttribute;

    }

    /**
     *  Return the Set-valued attribute declared by the managed type
     *  that corresponds to the specified name.
     *  @param name  the name of the represented attribute
     *  @return declared SetAttribute of the given name
     *  @throws IllegalArgumentException if attribute of the given
     *          name is not declared in the managed type
     */
    @Override
    public SetAttribute<X, ?> getDeclaredSet(String name) {
        // return only a set declared on this class - not via inheritance
        // Handles UC1 and UC2
        SetAttribute<X, ?> anAttribute = (SetAttribute<X, ?>) getSet(name);
        // The following verification step will throw an appropriate IAException if required (we can discard the return attribute here)
        getDeclaredAttribute(name);
        // We return an attribute that has passed through both a get and a declared inheritance check
        // all of which would throw an IAException before the return below.
        return anAttribute;
    }

    /**
     *  Return the Set-valued attribute declared by the managed type
     *  that corresponds to the specified name and Java element type.
     *  @param name  the name of the represented attribute
     *  @param elementType  the element type of the represented
     *                      attribute
     *  @return declared SetAttribute of the given name and
     *          element type
     *  @throws IllegalArgumentException if attribute of the given
     *          name and type is not declared in the managed type
     */
    @Override
    public <E> SetAttribute<X, E> getDeclaredSet(String name, Class<E> elementType) {
        // return only a set declared on this class - not via inheritance
        // Handles UC1 and UC2
        SetAttribute<X, E> anAttribute = (SetAttribute<X, E>) getSet(name, elementType);
        // The following verification step will throw an appropriate IAException if required (type checking has been done, and we can discard the return attribute here)
        getDeclaredAttribute(name);
        // We return an attribute that has passed through both a get, (optionally a type check) and a declared inheritance check
        // all of which would throw an IAException before the return below.
        return anAttribute;
    }

    /**
     *  Return the declared single-valued attribute of the managed
     *  type that corresponds to the specified name in the
     *  represented type.
     *  @param name  the name of the represented attribute
     *  @return declared single-valued attribute of the given
     *          name
     *  @throws IllegalArgumentException if attribute of the given
     *          name is not declared in the managed type
     */
    @Override
    public SingularAttribute<X, ?> getDeclaredSingularAttribute(String name) {
        // return only a SingularAttribute declared on this class - not via inheritance
        // Handles UC1 and UC2
        SingularAttribute<X, ?> anAttribute = (SingularAttribute<X, ?>) getSingularAttribute(name);
        // The following verification step will throw an appropriate IAException if required (we can discard the return attribute here)
        getDeclaredAttribute(name);
        // We return an attribute that has passed through both a get and a declared inheritance check
        // all of which would throw an IAException before the return below.
        return anAttribute;
    }

    /**
     *  Return the declared single-valued attribute of the
     *  managed type that corresponds to the specified name and Java
     *  type in the represented type.
     *  @param name  the name of the represented attribute
     *  @param type  the type of the represented attribute
     *  @return declared single-valued attribute of the given
     *          name and type
     *  @throws IllegalArgumentException if attribute of the given
     *          name and type is not declared in the managed type
     */
    @Override
    public <Y> SingularAttribute<X, Y> getDeclaredSingularAttribute(String name, Class<Y> type) {
        // return only a SingularAttribute declared on this class - not via inheritance
        // Handles UC1 and UC2
        SingularAttribute<X, Y> anAttribute = (SingularAttribute<X, Y>) getSingularAttribute(name, type);
        // The following verification step will throw an appropriate IAException if required (type checking has been done, and we can discard the return attribute here)
        getDeclaredAttribute(name);
        // We return an attribute that has passed through both a get, (optionally a type check) and a declared inheritance check
        // all of which would throw an IAException before the return below.
        return anAttribute;
    }

    /**
     *  Return the single-valued attributes declared by the managed
     *  type.
     *  @return declared single-valued attributes
     */
    @Override
    public Set<SingularAttribute<X, ?>> getDeclaredSingularAttributes() {
        // return the set of SingularAttributes declared on this class - not via inheritance
        // Get all attributes and filter only for declared attributes
        Set<Attribute<X, ?>> allAttributes = new LinkedHashSet<Attribute<X, ?>>(this.members.values());;
        // Is it better to add to a new Set or remove from an existing Set without a concurrentModificationException
        Set<SingularAttribute<X, ?>> declaredAttributes = new LinkedHashSet<SingularAttribute<X, ?>>();
        for(Attribute<X, ?> anAttribute : allAttributes) {
            if(!anAttribute.isCollection()) {
                declaredAttributes.add((SingularAttribute<X, ?>)anAttribute);
            }
        }
        return declaredAttributes;

    }

    /**
     * INTERNAL:
     * Return the RelationalDescriptor associated with this ManagedType
     */
    public ClassDescriptor getDescriptor() {
        return this.descriptor;
    }

    /**
     *  Return the List-valued attribute of the managed type that
     *  corresponds to the specified name.
     *  @param name  the name of the represented attribute
     *  @return ListAttribute of the given name
     *  @throws IllegalArgumentException if attribute of the given
     *          name is not present in the managed type
     */
    @Override
    public ListAttribute<? super X, ?> getList(String name) {
        return getList(name, true);
    }

    /**
     * INTERNAL:
     *  Return the List-valued attribute of the managed type that
     *  corresponds to the specified name.
     *  @param name  the name of the represented attribute
     * @param performNullCheck - flag on whether we should be doing an IAException check
     *  @return ListAttribute of the given name
     *  @throws IllegalArgumentException if attribute of the given
     *          name is not present in the managed type
     */
    private ListAttribute<? super X, ?> getList(String name, boolean performNullCheck) {
        /*
         * Note: We do not perform type checking on the get(name)
         * If the type is not of the correct Attribute implementation class then
         * a possible CCE will be allowed to propagate to the client.
         */
        ListAttribute<? super X, ?> anAttribute = (ListAttribute<? super X, ?>)this.members.get(name);
        if(performNullCheck && null == anAttribute) {
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage(
                    "metamodel_managed_type_attribute_not_present",
                    new Object[] { name, this }));
        }
        return anAttribute;
    }

    /**
     * INTERNAL:
     * Perform type checking on the attribute and return types of the named attribute.
     * This function will cause an IllegalArgumentException if any of the passed in types are incorrect.
     * @param anAttribute - the Attribute we are verifying
     * @param attributeElementType - the java element or basic element type
     * @param aReturnCollectionType - the plural return type
     * @throws IllegalArgumentException if either type is wrong
     */
    private void verifyAttributeTypeAndReturnType(Attribute anAttribute, Class attributeElementType, CollectionType aReturnCollectionType) {
        // Check for plural or singular attribute
        if(anAttribute.isCollection()) {
            // check for CollectionAttribute
            if(((PluralAttribute)anAttribute).getCollectionType().equals(aReturnCollectionType)) {
                // check that the java class is correct (use BindableJavaType not elementType.getJavaType()
                Class aBindableJavaClass = ((PluralAttribute)anAttribute).getBindableJavaType();
                if(attributeElementType != aBindableJavaClass) {
                    throw new IllegalArgumentException(ExceptionLocalization.buildMessage(
                        "metamodel_managed_type_attribute_type_incorrect",
                        new Object[] { anAttribute.getName(), this, attributeElementType, aBindableJavaClass }));
                }
            } else {
                throw new IllegalArgumentException(ExceptionLocalization.buildMessage(
                    "metamodel_managed_type_attribute_return_type_incorrect",
                    new Object[] { anAttribute.getName(), this, aReturnCollectionType,
                            ((PluralAttribute)anAttribute).getCollectionType()}));
            }
        }
    }

    /**
     *  Return the List-valued attribute of the managed type that
     *  corresponds to the specified name and Java element type.
     *  @param name  the name of the represented attribute
     *  @param elementType  the element type of the represented
     *                      attribute
     *  @return ListAttribute of the given name and element type
     *  @throws IllegalArgumentException if attribute of the given
     *          name and type is not present in the managed type
     */
    @Override
    public <E> ListAttribute<? super X, E> getList(String name, Class<E> elementType) {
        // We do not use getList(name) so that we can catch a possible CCE on the wrong attribute type
        ListAttribute<? super X, E> anAttribute = (ListAttribute<? super X, E>)this.members.get(name);
        if(null == anAttribute) {
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage(
                    "metamodel_managed_type_attribute_not_present",
                    new Object[] { name, this }));
        } else {
            // Throw appropriate IAException if required
            verifyAttributeTypeAndReturnType(anAttribute, elementType, CollectionType.LIST);
        }
        return anAttribute;

    }

    /**
     * INTERNAL:
     * Return the ManagedType that represents the superType (superclass) of
     * the current ManagedType.
     * If the superType is a BasicType - return null
     *
     * @return ManagedType supertype or null if no superclass
     */
    private ManagedTypeImpl getManagedSuperType() {
        // Note this method provides the same functionality of the more specific IdentifiableType.superType but is general to ManagedTypeImpl
        ManagedTypeImpl<?> aSuperType = null;
        // Get the superType if it exists (without using IdentifiableType.superType)
        Class<? super X> aSuperClass = this.getJavaType().getSuperclass();
        // The superclass for top-level types will be Object - which we will leave as a null supertype on the type
        if(null != aSuperClass && aSuperClass != ClassConstants.OBJECT &&
                this.getMetamodel().getType(aSuperClass).isManagedType()) { // 315287: return null for BasicType
                aSuperType = (ManagedTypeImpl<?>)this.getMetamodel().managedType(aSuperClass);
        }
        return aSuperType;
    }


    /**
     *  Return the Map-valued attribute of the managed type that
     *  corresponds to the specified name.
     *  @param name  the name of the represented attribute
     *  @return MapAttribute of the given name
     *  @throws IllegalArgumentException if attribute of the given
     *          name is not present in the managed type
     */
    @Override
    public MapAttribute<? super X, ?, ?> getMap(String name) {
        /*
         * Note: We do not perform type checking on the get(name)
         * If the type is not of the correct Attribute implementation class then
         * a possible CCE will be allowed to propagate to the client.
         */
        MapAttribute<? super X, ?, ?> anAttribute = (MapAttribute<? super X, ?, ?>)this.members.get(name);
        if(null == anAttribute) {
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage(
                    "metamodel_managed_type_attribute_not_present",
                    new Object[] { name, this }));
        }
        return anAttribute;

    }

    /**
     *  Return the Map-valued attribute of the managed type that
     *  corresponds to the specified name and Java key and value
     *  types.
     *  @param name  the name of the represented attribute
     *  @param keyType  the key type of the represented attribute
     *  @param valueType  the value type of the represented attribute
     *  @return MapAttribute of the given name and key and value
     *  types
     *  @throws IllegalArgumentException if attribute of the given
     *          name and type is not present in the managed type
     */
    @Override
    public <K, V> MapAttribute<? super X, K, V> getMap(String name, Class<K> keyType, Class<V> valueType) {
        MapAttribute<? super X, K, V> anAttribute = (MapAttribute<? super X, K, V>)this.getMap(name);
        Class<V> aClass = anAttribute.getElementType().getJavaType();
        if(valueType != aClass) {
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage(
                    "metamodel_managed_type_attribute_type_incorrect",
                    new Object[] { name, this, valueType, aClass }));
        }
        return anAttribute;
    }

    /**
     * INTERNAL:
     * Return the Map of AttributeImpl members keyed by String.
     */
    protected java.util.Map<String, Attribute<X, ?>> getMembers() {
        return this.members;
    }

    /**
     * INTERNAL:
     * Return the Metamodel that this ManagedType is associated with.
     */
    protected MetamodelImpl getMetamodel() {
        return this.metamodel;
    }

    /**
     *  Return the Set-valued attribute of the managed type that
     *  corresponds to the specified name.
     *  @param name  the name of the represented attribute
     *  @return SetAttribute of the given name
     *  @throws IllegalArgumentException if attribute of the given
     *          name is not present in the managed type
     */
    @Override
    public SetAttribute<? super X, ?> getSet(String name) {
        /*
         * Note: We do not perform type checking on the get(name)
         * If the type is not of the correct Attribute implementation class then
         * a possible CCE will be allowed to propagate to the client.
         */
        SetAttribute<? super X, ?> anAttribute = (SetAttribute<? super X, ?>)this.members.get(name);
        if(null == anAttribute) {
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage(
                    "metamodel_managed_type_attribute_not_present",
                    new Object[] { name, this }));
        }
        return anAttribute;
    }

    /**
     *  Return the Set-valued attribute of the managed type that
     *  corresponds to the specified name and Java element type.
     *  @param name  the name of the represented attribute
     *  @param elementType  the element type of the represented
     *                      attribute
     *  @return SetAttribute of the given name and element type
     *  @throws IllegalArgumentException if attribute of the given
     *          name and type is not present in the managed type
     */
    @Override
    public <E> SetAttribute<? super X, E> getSet(String name, Class<E> elementType) {
        SetAttribute<? super X, E> anAttribute = (SetAttribute<? super X, E>)getSet(name);
        Class<E> aClass = anAttribute.getElementType().getJavaType();
        if(elementType != aClass) {
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage(
                "metamodel_managed_type_attribute_type_incorrect",
                new Object[] { name, this, elementType, aClass.getName() }));
        }
        return anAttribute;
    }

    /**
     *  Return the single-valued attribute of the managed type that
     *  corresponds to the specified name in the represented type.
     *  @param name  the name of the represented attribute
     *  @return single-valued attribute with the given name
     *  @throws IllegalArgumentException if attribute of the given
     *          name is not present in the managed type
     */
    @Override
    public SingularAttribute<? super X, ?> getSingularAttribute(String name) {
        Attribute<X, ?> anAttribute = getMembers().get(name);
        if(null == anAttribute) {
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage(
                    "metamodel_managed_type_attribute_not_present",
                    new Object[] { name, this }));
        }
        return (SingularAttribute<? super X, ?>)anAttribute;
    }

    /**
     * INTERNAL:
     * This function returns whether the Object class passed in can be autoboxed
     * (a primitive wrapped in its' object type) or the reverse - an autoboxed object
     * that wraps a primitive type).
     * It answers the question of whether the two classes can be considered to be essentially the same<br>
     * This function is used by the metamodel to determine whether the
     * IAE (IllegalArgumentException) type checking should be relaxed for SingleAttributes.
     *
     * @param targetPrimitiveOrWrapperClass (the type we are verifying against)
     * @param actualPrimitiveOrWrapperClass (the type that may be the autoboxed or primitive equal
     */
    private boolean isAutoboxedType(Class targetPrimitiveOrWrapperClass, Class actualPrimitiveOrWrapperClass) {
        BasicTypeHelperImpl typeHelper = BasicTypeHelperImpl.getInstance();
        if ((targetPrimitiveOrWrapperClass == null) || (actualPrimitiveOrWrapperClass == null)) {
            return false;
        }
        // Check for the same class in the same classloader or different classloaders
        if (targetPrimitiveOrWrapperClass == actualPrimitiveOrWrapperClass ||
                targetPrimitiveOrWrapperClass.getCanonicalName().equals(actualPrimitiveOrWrapperClass.getCanonicalName())) {
            return false;
        }

        /**
         * We return true for any of the following combinations.
         * boolean:Boolean byte:Byte short:Short char:Character int:Integer long:Long float:Float double:Double
         */
        // Are we dealing with autoboxed wrappers Boolean, Byte, Short, Character, Integer, Long, Float, Double
        // Or are we dealing with the primitives boolean, byte, short, char, int, long, float, double
        // Note BigDecimal, BigInteger, Calendar, Timestamp, Time and Date are not wrappers for pimitives
        if(typeHelper.isWrapperClass(targetPrimitiveOrWrapperClass) ||
                targetPrimitiveOrWrapperClass.isPrimitive()) {
            // Check each type (primitive or Class) against each Class type - the target and actual can both be primitives or Objects
            if(typeHelper.isBooleanType(targetPrimitiveOrWrapperClass)) {
                return typeHelper.isBooleanType(actualPrimitiveOrWrapperClass);
            }
            if(typeHelper.isByteType(targetPrimitiveOrWrapperClass)) {
                return typeHelper.isByteType(actualPrimitiveOrWrapperClass);
            }
            if(typeHelper.isShortType(targetPrimitiveOrWrapperClass)) {
                return typeHelper.isShortType(actualPrimitiveOrWrapperClass);
            }
            if(typeHelper.isCharacterType(targetPrimitiveOrWrapperClass)) {
                return typeHelper.isCharacterType(actualPrimitiveOrWrapperClass);
            }
            if(typeHelper.isIntType(targetPrimitiveOrWrapperClass)) {
                return typeHelper.isIntType(actualPrimitiveOrWrapperClass);
            }
            if(typeHelper.isLongType(targetPrimitiveOrWrapperClass)) {
                return typeHelper.isLongType(actualPrimitiveOrWrapperClass);
            }
            if(typeHelper.isFloatType(targetPrimitiveOrWrapperClass)) {
                return typeHelper.isFloatType(actualPrimitiveOrWrapperClass);
            }
            if(typeHelper.isDoubleType(targetPrimitiveOrWrapperClass)) {
                return typeHelper.isDoubleType(actualPrimitiveOrWrapperClass);
            }
        }
        return false;
    }

    /**
     *  Return the single-valued attribute of the managed
     *  type that corresponds to the specified name and Java type
     *  in the represented type.
     *  @param name  the name of the represented attribute
     *  @param type  the type of the represented attribute
     *  @return single-valued attribute with given name and type
     *  @throws IllegalArgumentException if attribute of the given
     *          name and type is not present in the managed type
     */
    @Override
    public <Y> SingularAttribute<? super X, Y> getSingularAttribute(String name, Class<Y> type) {
        SingularAttribute<? super X, Y> anAttribute = (SingularAttribute<? super X, Y>)getSingularAttribute(name);
        Class<Y> aClass = anAttribute.getType().getJavaType();
        // Determine whether to throw an IAE for the wrong type - Note: we relax the rules for autoboxed types
        if(type != aClass && !isAutoboxedType(type, aClass)) {
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage(
                "metamodel_managed_type_attribute_type_incorrect",
                new Object[] { name, this, type, aClass }));
        }
        return anAttribute;
    }

    /**
     *  Return the single-valued attributes of the managed type.
     *  @return single-valued attributes
     */
    @Override
    public Set<SingularAttribute<? super X, ?>> getSingularAttributes() {
        // Iterate the members set for attributes of type SingularAttribute
        Set singularAttributeSet = new LinkedHashSet<SingularAttribute<? super X, ?>>();
        for(Attribute<X, ?> anAttribute : this.members.values()) {
            if(!((AttributeImpl<? super X, ?>)anAttribute).isPlural()) {
                singularAttributeSet.add(anAttribute);
            }
        }
        return singularAttributeSet;
    }

    /**
     * INTERNAL:
     * Recursively search the superclass tree of the current managedType
     * for the named attribute.<p>
     * This internal function is used exclusively by the getDeclared*() calls on ManagedType objects.<p>
     * This function is type agnostic (Set, List, Map and Collection are treated as attributes)
     * @param attributeName - String name of possible declared attribute search
     * @return true if the attribute is declared at this first level,
     *             false if no attribute is found in the superTree, or
     *             false if the attribute is found declared higher up in the inheritance superTree
     */
    private boolean isAttributeDeclaredOnlyInLeafType(String attributeName) {
        return isAttributeDeclaredOnlyInLeafType(attributeName, this.getMembers().get(attributeName));
    }

    /**
     * INTERNAL:
     * Recursively search the superclass tree of the current managedType
     * for the named attribute.<p>
     * This internal function is used exclusively by the getDeclared*() calls on ManagedType objects.<p>
     * This function is type agnostic (Set, List, Map and Collection are treated as attributes)
     * @param attributeName - String name of possible declared attribute search
     * @return true if the attribute is declared at this first level,
     *             false if no attribute is found in the superTree, or
     *             false if the attribute is found declared higher up in the inheritance superTree
     */
    private boolean isAttributeDeclaredOnlyInLeafType(String attributeName, Attribute firstLevelAttribute) {
        /*
         * Issues: We need to take into account whether the superType is an Entity or MappedSuperclass
         * - If superType is entity then inheriting entities will not have copies of the inherited mappings
         * - however, if superType is mappedSuperclass then all inheriting mappedSuperclasses and the first
         *   entity will have copies of the inherited mappings
         * - Note: a sub-entity can override a mapping above it
         * Use Cases:
         *   UC1 Superclass declares attribute
         *     UC1.1: Entity (searched) --> Entity --> Entity (declares attribute)
         *     UC1.2: Entity (searched) --> Entity (copy of attribute) --> MappedSuperclass (declares attribute)
         *     UC1.3: Entity (searched) --> MappedSuperclass --> Entity (declares attribute)
         *     UC1.4: Entity (copy of attribute) (searched) --> MappedSuperclass (no copy of attribute) (searched) --> MappedSuperclass (declares attribute) (searched)
         *     UC1.5: Entity (copy of attribute) (searched) --> MappedSuperclass (declares attribute) (searched) --> MappedSuperclass
         *   UC2 Nobody declares attribute
         *     UC2.1: Entity (searched) --> Entity --> MappedSuperclass (declares attribute)
         *     UC2.2: Entity (searched) --> Entity --> Entity (declares attribute)
         *     UC2.3: Entity (searched) --> MappedSuperclass (searched) --> MappedSuperclass (declares attribute)
         *     UC2.4: Entity (searched) --> MappedSuperclass (searched) --> Entity (declares attribute)
         *   UC3 Superclass declares attribute but child overrides it
         *     UC3.1: Entity (searched) --> Entity --> MappedSuperclass (declares attribute)
         *     UC3.2: Entity (searched) --> Entity --> Entity (declares attribute)
         *     UC3.3: Entity (searched) --> MappedSuperclass (override attribute) (searched) --> MappedSuperclass (declares attribute)
         *     UC3.4: Entity (searched) --> MappedSuperclass (override attribute) (searched) --> Entity (declares attribute) (searched)
         *     UC3.5: Entity (override attribute) (searched) --> MappedSuperclass (searched) --> MappedSuperclass (declares attribute) (searched)
         *     UC3.6: Entity (override attribute) (searched) --> MappedSuperclass (searched) --> Entity (declares attribute)
         * Solution:
         *   Results Expected for hasDeclaredAttribute()
         *     True = attribute declared only on current type
         *     False = attribute not found in superType tree or attribute found in more than one(1) level of the superType tree
         *   Base Case
         *     attribute found && no superType exists = true
         *     attribute not found && no superType exists = false
         *   Recursive Case
         *     Exit(false) as soon as attribute is found in a superType - without continuing to the root
         *     continue as long as we find an attribute in the superType (essentially only MappedSuperclass parents)
         **/
        Attribute<X, ?> anAttribute = this.getMembers().get(attributeName);
        ManagedTypeImpl<?> aSuperType = getManagedSuperType();

        // Base Case: If we are at the root, check for the attribute and return results immediately
        if(null == aSuperType) { // 315287: the superType will be null if the root is a BasicType (non-Entity|non-MappedSuperclass)
            if(null == anAttribute && null != firstLevelAttribute) {
                return true;
            } else {
                // UC 1.3 (part of the else condition (anAttribute != null)) is handled by the return false in null != aSuperTypeAttribute
                // UC 1.4 (when caller is firstLevel) superType does not contain the attribute - check that the current attribute and the first differ
                if(null != anAttribute && anAttribute == firstLevelAttribute) {
                    return true;
                } else {
                    return false;
                }
            }
        } else {
           // Recursive Case: check hierarchy both if the immediate superclass is a MappedSuperclassType or EntityType
           Attribute<?, ?> aSuperTypeAttribute = aSuperType.getMembers().get(attributeName);
           // UC1.3 The immediate mappedSuperclass may have the attribute - we check it in the base case of the next recursive call
           if(null != aSuperTypeAttribute) {
               // return false immediately if a superType exists above the first level
               return false;
           } else {
               // UC1.4 (when caller is firstLevel.supertype) - the immediate mappedSuperclass may not have the attribute if another one up the chain of rmappedSuperclasses declares it
               // UC 1.5: keep searching a possible chain of mappedSuperclasses or entities
               return aSuperType.isAttributeDeclaredOnlyInLeafType(attributeName, firstLevelAttribute);
           }
        }
    }

    /**
     * INTERNAL:
     * Handle the case where we were unable to determine the element type of the plural attribute.
     * Normally this function is never required and should have a code coverage of 0%.
     */
    private AttributeImpl initializePluralAttributeTypeNotFound(ManagedTypeImpl managedType, CollectionMapping collectionMapping, boolean validation) {
        // default to List
        // TODO: System.out.println("_Warning: type is null on " + colMapping);
        AttributeImpl<X, ?> member = new ListAttributeImpl(managedType, collectionMapping, validation);
        return member;
    }

    /**
     * INTERNAL:
     * Initialize the members of this ManagedType based on the mappings defined on the descriptor.
     * We process the appropriate Map, List, Set, Collection or Object/primitive types.<p>
     * Initialization should occur after all types in the metamodel have been created already.
     *
     */
    protected void initialize() { // Future: Check all is*Policy() calls
        /*
         * Design Issue 37 and 58:
         * http://wiki.eclipse.org/EclipseLink/Development/JPA_2.0/metamodel_api#DI_37:_20090708:_CollectionAttribute_acts_as_a_peer_of_Map.2C_Set.2C_List_but_should_be_a_super_interface
         * http://wiki.eclipse.org/EclipseLink/Development/JPA_2.0/metamodel_api#DI_58:_20090807:_ManagedType_Attribute_Initialization_must_differentiate_between_Collection_and_List
         *
         *     The hierarchy of the Metamodel API has Collection alongside List, Set and Map.
         * However, in a normal Java collections framework Collection is an
         * abstract superclass of List, Set and Map (with Map not really a Collection).
         * We therefore need to treat Collection here as a peer of the other "collections" while also treating it as a non-instantiated superclass.
         */

        // this could have been initialized earlier if it is an inheriting subclass of a MappedSuperclassType
        // See MappedSuperclassType.getMemberFromInheritingType()
        if (null != this.members) {
            //this is already initialized
            return;
        }

        this.members = new HashMap<String, Attribute<X, ?>>();
        // Get and process all mappings on the relationalDescriptor
        for (DatabaseMapping mapping : getDescriptor().getMappings()) {
            AttributeImpl<X, ?> member = null;

            /**
             * The following section will determine the plural attribute type for each mapping on the managedType.
             * Special handling is required for differentiation of List and Collection
             * beyond their shared IndirectList ContainerPolicy,
             * as even though a List is an implementation of Collection in Java,
             * In the Metamodel we treat the Collection as a peer of a List.
             *
             * Collection.class   --> via IndirectList          --> CollectionAttributeImpl
             *    List.class          --> via IndirectList          -->  ListAttributeImpl
             *    Set.class           --> SetAttributeImpl
             *    Map.class         -->  MapAttributeImpl
             *
             * If the type is Embeddable then special handling will be required to get the plural type.
             * The embeddable's MethodAttributeAccessor will not have the getMethod set.
             * We can however use reflection and get the returnType directly from the class
             * using the getMethodName on the accessor.
             */
            // Tie into the collection hierarchy at a lower level
            if (mapping instanceof CollectionMapping) {
                // Handle 1:m, n:m collection mappings
                CollectionMapping colMapping = (CollectionMapping) mapping;
                ContainerPolicy collectionContainerPolicy = colMapping.getContainerPolicy();
                if (collectionContainerPolicy.isMapPolicy()) {
                    // Handle the 3 Map type mappings (policy.isMappedKeyMapPolicy()) is handled by isMapPolicy())


                    member = new MapAttributeImpl(this, colMapping, true);
                    // check mapping.attributeAcessor.attributeField.type=Collection
                } else if (collectionContainerPolicy.isListPolicy()) {
                    // This seems very over complex...
                    /**
                     * Handle lazy Collections and Lists and the fact that both return an IndirectList policy.
                     * We check the type on the attributeField of the attributeAccessor on the mapping
                     */
                    Class aType = null;
                    // 325699: AttributeAccessor is subclassed by both IntanceVariableAttributeAccessor (JPA) and ValuesAccessor (Dynamic JPA)
                    if(colMapping.getAttributeAccessor() instanceof ValuesAccessor) {
                        member = new ListAttributeImpl(this, colMapping);
                    } else if(colMapping.getAttributeAccessor() instanceof InstanceVariableAttributeAccessor) {
                        Field aField = ((InstanceVariableAttributeAccessor)colMapping.getAttributeAccessor()).getAttributeField();
                        // MappedSuperclasses need special handling to get their type from an inheriting subclass
                        if(null == aField) { // MappedSuperclass field will not be set
                            if(this.isMappedSuperclass()) {
                                // get inheriting subtype member (without handling @override annotations)
                                MappedSuperclassTypeImpl aMappedSuperclass = ((MappedSuperclassTypeImpl)this);
                                AttributeImpl inheritingTypeMember = aMappedSuperclass.getMemberFromInheritingType(colMapping.getAttributeName());
                                // 322166: If attribute is defined on this current ManagedType (and not on a superclass) - do not attempt a reflective call on a superclass
                                if(null != inheritingTypeMember) {
                                    // Verify we have an attributeAccessor
                                    aField = ((InstanceVariableAttributeAccessor)inheritingTypeMember.getMapping().getAttributeAccessor()).getAttributeField();
                                }
                            }
                        }
                        // 322166: The attribute may be defined on the current ManagedType - not inherited
                        if(null == aField) {
                            // Check attributeName when the field is null
                            aType = this.getTypeClassFromAttributeOrMethodLevelAccessor(mapping);
                        } else {
                            aType = aField.getType();
                        }
                        // This attribute is declared as List
                        if((aType != null) && List.class.isAssignableFrom(aType)) {
                            member = new ListAttributeImpl(this, colMapping, true);
                        } else if((aType != null) && Collection.class.isAssignableFrom(aType)) {
                            // This attribute is therefore declared as Collection
                            member = new CollectionAttributeImpl(this, colMapping, true);
                        } else {
                            member = initializePluralAttributeTypeNotFound(this, colMapping, true);
                        }
                    } else {
                        // handle variations of missing get/set methods - only for Collection vs List
                        if(colMapping.getAttributeAccessor() instanceof MethodAttributeAccessor) {
                            /**
                             * The following call will perform a getMethod call for us.
                             * If no getMethod exists, we will secondarily check the getMethodName below.
                             */
                            aType = colMapping.getAttributeAccessor().getAttributeClass();
                            if((aType != null) && List.class.isAssignableFrom(aType)) {
                                member = new ListAttributeImpl(this, colMapping, true);
                            } else if((aType != null) && Collection.class.isAssignableFrom(aType)) {
                                member = new CollectionAttributeImpl(this, colMapping, true);
                            } else {
                                /**
                                 * In this block we have the following scenario:
                                 * 1) The access type is "field"
                                 * 2) The get method is not set on the entity
                                 * 3) The get method is named differently than the attribute
                                 */
                                // Type may be null when no getMethod exists for the class for a ManyToMany mapping
                                // Here we check the returnType on the declared method on the class directly
                                String getMethodName = ((MethodAttributeAccessor)colMapping.getAttributeAccessor()).getGetMethodName();
                                if(null == getMethodName) {
                                    // Check declaredFields in the case where we have no getMethod or getMethodName
                                    try {
                                        Field field = null;
                                        if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
                                            try {
                                                field = AccessController.doPrivileged(new PrivilegedGetDeclaredField(
                                                        this.getJavaType(), colMapping.getAttributeName(), false));
                                            } catch (PrivilegedActionException exception) {
                                                member = initializePluralAttributeTypeNotFound(this, colMapping, true);
                                            }
                                        } else {
                                            field = PrivilegedAccessHelper.getDeclaredField(
                                                    this.getJavaType(), colMapping.getAttributeName(), false);
                                        }
                                        if(null == field) {
                                            member = initializePluralAttributeTypeNotFound(this, colMapping, true);
                                        } else {
                                            aType = field.getType();
                                            if((aType != null) && List.class.isAssignableFrom(aType)) {
                                                member = new ListAttributeImpl(this, colMapping, true);
                                            } else if((aType != null) && Collection.class.isAssignableFrom(aType)) {
                                                member = new CollectionAttributeImpl(this, colMapping, true);
                                            } else {
                                                member = initializePluralAttributeTypeNotFound(this, colMapping, true);
                                            }
                                        }
                                    } catch (Exception e) {
                                        member = initializePluralAttributeTypeNotFound(this, colMapping, true);
                                    }
                                } else {
                                    /**
                                     * Field access Handling:
                                     * If a get method name exists, we check the return type on the method directly
                                     * using reflection.
                                     * In all failure cases we default to the List type.
                                     */
                                    try {
                                        Method aMethod = null;
                                        if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()) {
                                            aMethod = AccessController.doPrivileged(new PrivilegedGetDeclaredMethod(
                                                    this.getJavaType(), getMethodName, null));
                                        } else {
                                            aMethod = PrivilegedAccessHelper.getDeclaredMethod(
                                                    this.getJavaType(), getMethodName, null);
                                        }

                                        if(null == aMethod) {
                                            member = initializePluralAttributeTypeNotFound(this, colMapping, true);
                                        } else {
                                            aType = aMethod.getReturnType();
                                            if((aType != null) && List.class.isAssignableFrom(aType)) {
                                                member = new ListAttributeImpl(this, colMapping, true);
                                            } else if((aType != null) && Collection.class.isAssignableFrom(aType)) {
                                                member = new CollectionAttributeImpl(this, colMapping, true);
                                            } else {
                                                member = initializePluralAttributeTypeNotFound(this, colMapping, true);
                                            }
                                        }
                                    } catch (Exception e) {
                                        member = initializePluralAttributeTypeNotFound(this, colMapping, true);
                                    }
                                }
                            }
                        }
                    }
                } else {
                    // Handle non-lazy Collection or Set type mappings (IndirectSet.isAssignableFrom(Set.class) == false)
                    if ((collectionContainerPolicy.getContainerClass() != null) && Set.class.isAssignableFrom(collectionContainerPolicy.getContainerClass())) {
                        member = new SetAttributeImpl(this, colMapping, true);
                    } else {
                        // Check for non-lazy Collection policy possibly instantiated to a Set or List (both of which is ignored)
                        if(collectionContainerPolicy.isCollectionPolicy()) {
                            member = new CollectionAttributeImpl(this, colMapping, true);
                        } else {
                            // Handle Collection type mappings as a default (we should never get here)
                            // TODO: System.out.println("_Warning: defaulting to non-Set specific Collection type on " + colMapping);
                            member = new CollectionAttributeImpl(this, colMapping);
                        }
                    }
                }
            } else {
                // Handle 1:1 single object and direct mappings including EnumSet
                member = new SingularAttributeImpl(this, mapping, true);
            }
            // 303063: secondary check for a null value put - should never happen but this will show on code coverage
            if(null == member) {
                AbstractSessionLog.getLog().log(SessionLog.FINEST, "metamodel_attribute_getmember_is_null",
                        mapping.getAttributeName(), this, descriptor);
            }

            this.members.put(mapping.getAttributeName(), member);
        }
    }

    /**
     * INTERNAL:
     * Get the elementType directly from the class using a reflective method call
     * directly on the containing java class associated with this managedType.
     */
    protected Class getTypeClassFromAttributeOrMethodLevelAccessor(DatabaseMapping mapping) {
        /**
         * In this block we have the following scenario:
         * 1) The access type is "method" or "field"
         * 1a) The get method is set on the entity (method access)
         * 1b) The get method is not set on the entity (field access)
         * 1c) The get method is named differently than the attribute
         */
        // Type may be null when no getMethod exists for the class for a ManyToMany mapping
        // Here we check the returnType on the declared method on the class directly
        Class aType = null;
        Field aField = null;
        String getMethodName = null;
        //boolean isFieldLevelAccess = false;

        // 1) Check access Type
        if(mapping.getAttributeAccessor() instanceof MethodAttributeAccessor) {
            //isFieldLevelAccess = false;
            getMethodName = ((MethodAttributeAccessor)mapping.getAttributeAccessor()).getGetMethodName();
        } else if(mapping.getAttributeAccessor() instanceof InstanceVariableAttributeAccessor) {
            //isFieldLevelAccess = true;
            aField = ((InstanceVariableAttributeAccessor)mapping.getAttributeAccessor()).getAttributeField();
        }

        // 2) based on access type get the element type
        // 3) If field level access - perform a getDeclaredField call
        if(null == aField && this.getJavaType() != null) {
            // Field level access
            // Check declaredFields in the case where we have no getMethod or getMethodName
            try {
                if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
                    aField = AccessController.doPrivileged(new PrivilegedGetDeclaredField(
                        this.getJavaType(), mapping.getAttributeName(), false));
                } else {
                    aField = PrivilegedAccessHelper.getDeclaredField(
                        this.getJavaType(), mapping.getAttributeName(), false);
                }
            } catch (PrivilegedActionException pae) {
            } catch (NoSuchFieldException nsfe) {
            }
        }

        // 4) If method level access - perform a getDeclaredMethod call
        /**
         * Field access Handling:
         * If a get method name exists, we check the return type on the method directly
         * using reflection.
         * In all failure cases we default to the List type.
         */
        if(null == aField && this.getJavaType() != null && getMethodName !=null) {
            Method aMethod = null;
            try {
                if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()) {
                    aMethod = AccessController.doPrivileged(new PrivilegedGetDeclaredMethod(
                            this.getJavaType(), getMethodName, null));
                } else {
                    aMethod = PrivilegedAccessHelper.getDeclaredMethod(
                            this.getJavaType(), getMethodName, null);
                }
            } catch (PrivilegedActionException pae) {
            } catch (NoSuchMethodException nsfe) {
            } catch (NullPointerException npe) {
                // case: null name arg to Class.searchMethods from getDeclaredMethod if getMethodName is null
                // because we do not know the javaType on the Type (descriptor.javaClass was null)
                // See bug# 303063
                npe.printStackTrace();
            }

            if(null != aMethod) {
                aType = aMethod.getReturnType();
            }
        }

        // 5) Special processing for MappedSuperclass hierarchies
        // MappedSuperclasses need special handling to get their type from an inheriting subclass
        if(null == aField && null == aType && this.isMappedSuperclass()) {
            // get inheriting subtype member (without handling @override annotations)
            MappedSuperclassTypeImpl aMappedSuperclass = ((MappedSuperclassTypeImpl)this);
            AttributeImpl inheritingTypeMember = aMappedSuperclass.getMemberFromInheritingType(mapping.getAttributeName());
            aField = ((InstanceVariableAttributeAccessor)inheritingTypeMember.getMapping().getAttributeAccessor()).getAttributeField();
        }

        // 6) get the type from the resulting field (method level access was handled)
        if(null != aField) {
            // field access
            aType = aField.getType();
        }


        // 7) catch unsupported element type
        if(null == aType) {
            aType = MetamodelImpl.DEFAULT_ELEMENT_TYPE_FOR_UNSUPPORTED_MAPPINGS;
        }

        // 303063: secondary check for case where descriptor has no java class set - should never happen but this will show on code coverage
        if(null == this.getJavaType()) {
            AbstractSessionLog.getLog().log(SessionLog.FINEST, SessionLog.METAMODEL, "metamodel_relationaldescriptor_javaclass_null_on_managedType", descriptor, this);
        }

        return aType;
    }

    /**
     * INTERNAL:
     * Return whether this type is identifiable.
     * This would be EntityType and MappedSuperclassType
     */
    @Override
    protected boolean isIdentifiableType() {
        return false;
    }

    /**
     * INTERNAL:
     * Return whether this type is identifiable.
     * This would be EmbeddableType as well as EntityType and MappedSuperclassType
     */
    @Override
    protected boolean isManagedType() {
        return true;
    }

    /**
     * INTERNAL:
     * Append the partial string representation of the receiver to the StringBuffer.
     */
    @Override
    protected void toStringHelper(StringBuffer aBuffer) {
        aBuffer.append(" descriptor: ");
        aBuffer.append(this.getDescriptor());
        if(null != this.getDescriptor()) {
            aBuffer.append(", mappings: ");
            aBuffer.append(this.getDescriptor().getMappings().size());
        }
    }
}
