/*
 * 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
     * @param metamodel
     * @param descriptor
     * @return
     */
    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
     * @return
     */
    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.
     * @return
     */
    protected java.util.Map<String, Attribute<X, ?>> getMembers() {
        return this.members;
    }

    /**
     * INTERNAL:
     * Return the Metamodel that this ManagedType is associated with.
     * @return
     */
    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
     * @return
     */
    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%.
     * @param managedType
     * @param collectionMapping
     * @param validation
     */
    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.
     * @param mapping
     * @return
     */
    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
     * @return
     */
    @Override
    protected boolean isIdentifiableType() {
        return false;
    }

    /**
     * INTERNAL:
     * Return whether this type is identifiable.
     * This would be EmbeddableType as well as EntityType and MappedSuperclassType
     * @return
     */
    @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());
        }
    }
}
