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

// Contributors:
//     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)
//     10/15/2009-2.0  mobrien - 266912
//          http://wiki.eclipse.org/EclipseLink/Development/JPA_2.0/metamodel_api#DI_94:_20091015:_Split_and_Granularize_Test_Suite
//     16/06/2010-2.2  mobrien - 316991: Attribute.getJavaMember() requires reflective getMethod call
//       when only getMethodName is available on accessor for attributes of Embeddable types.
//       see testAttribute_getJavaMember_BasicType_on_Embeddable_Method()
//       http://wiki.eclipse.org/EclipseLink/Development/JPA_2.0/metamodel_api#DI_95:_20091017:_Attribute.getJavaMember.28.29_returns_null_for_a_BasicType_on_a_MappedSuperclass_because_of_an_uninitialized_accessor
//     30/11/2010-2.2  mobrien - 300626: Nested Embeddable testing
package org.eclipse.persistence.testing.tests.jpa.metamodel;


import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.math.BigInteger;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;

import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.metamodel.Attribute;
import jakarta.persistence.metamodel.Bindable;
import jakarta.persistence.metamodel.CollectionAttribute;
import jakarta.persistence.metamodel.EmbeddableType;
import jakarta.persistence.metamodel.EntityType;
import jakarta.persistence.metamodel.IdentifiableType;
import jakarta.persistence.metamodel.ListAttribute;
import jakarta.persistence.metamodel.ManagedType;
import jakarta.persistence.metamodel.MapAttribute;
import jakarta.persistence.metamodel.MappedSuperclassType;
import jakarta.persistence.metamodel.Metamodel;
import jakarta.persistence.metamodel.PluralAttribute;
import jakarta.persistence.metamodel.SetAttribute;
import jakarta.persistence.metamodel.SingularAttribute;
import jakarta.persistence.metamodel.Type;
import jakarta.persistence.metamodel.Attribute.PersistentAttributeType;
import jakarta.persistence.metamodel.PluralAttribute.CollectionType;
import jakarta.persistence.metamodel.Type.PersistenceType;

import junit.framework.Test;
import junit.framework.TestSuite;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.internal.jpa.metamodel.AttributeImpl;
import org.eclipse.persistence.internal.jpa.metamodel.BasicTypeImpl;
import org.eclipse.persistence.internal.jpa.metamodel.EmbeddableTypeImpl;
import org.eclipse.persistence.internal.jpa.metamodel.EntityTypeImpl;
import org.eclipse.persistence.internal.jpa.metamodel.ManagedTypeImpl;
import org.eclipse.persistence.internal.jpa.metamodel.MapAttributeImpl;
import org.eclipse.persistence.internal.jpa.metamodel.MappedSuperclassTypeImpl;
import org.eclipse.persistence.internal.jpa.metamodel.MetamodelImpl;
import org.eclipse.persistence.internal.jpa.metamodel.PluralAttributeImpl;
import org.eclipse.persistence.internal.jpa.metamodel.SingularAttributeImpl;
import org.eclipse.persistence.internal.jpa.metamodel.TypeImpl;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.testing.models.jpa.metamodel.ArrayProcessor;
import org.eclipse.persistence.testing.models.jpa.metamodel.Board;
import org.eclipse.persistence.testing.models.jpa.metamodel.CPU;
import org.eclipse.persistence.testing.models.jpa.metamodel.CPUEmbeddedId;
import org.eclipse.persistence.testing.models.jpa.metamodel.Computer;
import org.eclipse.persistence.testing.models.jpa.metamodel.Core;
import org.eclipse.persistence.testing.models.jpa.metamodel.Corporation;
import org.eclipse.persistence.testing.models.jpa.metamodel.Designer;
import org.eclipse.persistence.testing.models.jpa.metamodel.EmbeddedPK;
import org.eclipse.persistence.testing.models.jpa.metamodel.Enclosure;
import org.eclipse.persistence.testing.models.jpa.metamodel.EnclosureIdClassPK;
import org.eclipse.persistence.testing.models.jpa.metamodel.FooBar;
import org.eclipse.persistence.testing.models.jpa.metamodel.FooBarId;
import org.eclipse.persistence.testing.models.jpa.metamodel.GalacticPosition;
import org.eclipse.persistence.testing.models.jpa.metamodel.HardwareDesigner;
import org.eclipse.persistence.testing.models.jpa.metamodel.MSRootPropertyAccess;
import org.eclipse.persistence.testing.models.jpa.metamodel.MS_MS_Entity_Center;
import org.eclipse.persistence.testing.models.jpa.metamodel.MS_MS_Entity_Leaf;
import org.eclipse.persistence.testing.models.jpa.metamodel.MS_MS_Entity_Root;
import org.eclipse.persistence.testing.models.jpa.metamodel.Manufacturer;
import org.eclipse.persistence.testing.models.jpa.metamodel.Memory;
import org.eclipse.persistence.testing.models.jpa.metamodel.MultiCoreCPU;
import org.eclipse.persistence.testing.models.jpa.metamodel.Observation;
import org.eclipse.persistence.testing.models.jpa.metamodel.ObservationDetail;
import org.eclipse.persistence.testing.models.jpa.metamodel.Person;
import org.eclipse.persistence.testing.models.jpa.metamodel.Position;
import org.eclipse.persistence.testing.models.jpa.metamodel.Processor;
import org.eclipse.persistence.testing.models.jpa.metamodel.VectorProcessor;
import org.eclipse.persistence.testing.models.jpa.metamodel.WithInner;
import org.eclipse.persistence.testing.framework.junit.JUnitTestCase;

/**
 * These tests verify the JPA 2.0 Metamodel API.
 * The framework is as follows:
 *   - initialize persistence unit
 *   - start a transaction
 *   - persist some entities to test
 *   - verify metamodel
 *   - delete test entities created above (to reset the database)
 *   - close persistence unit
 *
 *   API Usage
 *   There are three ways to query using the Criteria API which can wrap the Metamodel API
 *   1) Static canonical metamodel class model for type safe queries - these are the _Underscore design time classes
 *   2) Dynamic metamodel class model for type safe queries
 *      - we use generics and pass in both the return type and the type containing the return type
 *   3) String attribute references for non-type safe queries
 *      - see p.262 of the JPA 2.0 specification section 6.7
 *      - there may be type or generic usage compiler warnings that
 *        the user will need to workaround when using this non-type-safe query in a type-safe environment.
 *
 *   This enhancement deals only with # 2) Dynamic metamodel query generation.
 *
 */
public class MetamodelMetamodelTest extends MetamodelTest {

    public static final int METAMODEL_ALL_ATTRIBUTES_SIZE = 158;//6;
    // Note: Since BasicTypes are lazy - loaded into the metamodel-types Map - this test must preceed any test that verifies all BasicType objects like "testIdentifiableType_getIdType_Method"
    public static final int METAMODEL_ALL_TYPES = 56;
    public static final int METAMODEL_MANUFACTURER_DECLARED_TYPES = 28;
    // Get # of processor cores (hard cores + hyperthreaded cores)
    public static final int numberProcessingUnits = Runtime.getRuntime().availableProcessors();

    public MetamodelMetamodelTest() {
        super();
    }

    public MetamodelMetamodelTest(String name) {
        super(name);
    }

    public static Test suite() {
        TestSuite suite = new TestSuite("MetamodelMetamodelTest");
        /**
         * 300051: EmbeddedId directly on MappedSuperclass
         * In the following 2 tests we verify that when an EmbeddedId is on a MappedSuperclass - we do not
         * use the non-persisting MAPPED_SUPERCLASS_RESERVED_PK_NAME PK field.
         * Normally when the MappedSuperclass is part of an inheritance hierarchy of the form MS->MS->E,
         * where there is an PK Id on the root Entity E, we need to add this key solely for metadata processing to complete.
         * Why? because even though we treat MappedSuperclass objects as a RelationalDescriptor - we only persist
         * RelationalDescriptor objects that relate to concrete Entities.
         */
        if (! JUnitTestCase.isJPA10()) {
            suite.addTest(new MetamodelMetamodelTest("testMetamodelEmbeddedIdDirectlyOnMappedSuperclassRootPassesValidation"));
            // Note: Since BasicTypes are lazy - loaded into the metamodel-types Map - this test must preceed any test that verifies all BasicType objects like "testIdentifiableType_getIdType_Method"
            suite.addTest(new MetamodelMetamodelTest("testTransientNonEntityNonMappedSuperclass_SuperclassOfEntity_Exists_as_BasicType"));
            suite.addTest(new MetamodelMetamodelTest("testAttribute_getAttribute_of_TransientNonEntityNonMappedSuperclass_SuperclassOfEntity_throws_IAE"));
            suite.addTest(new MetamodelMetamodelTest("testAttribute_getPersistentAttributeType_BASIC_Method"));
            suite.addTest(new MetamodelMetamodelTest("testAttribute_getPersistentAttributeType_EMBEDDED_Method"));
            suite.addTest(new MetamodelMetamodelTest("testAttribute_getPersistentAttributeType_ONE_TO_ONE_Method"));
            suite.addTest(new MetamodelMetamodelTest("testAttribute_getPersistentAttributeType_ONE_TO_MANY_Method"));
            suite.addTest(new MetamodelMetamodelTest("testAttribute_getPersistentAttributeType_MANY_TO_MANY_Method"));
            suite.addTest(new MetamodelMetamodelTest("testAttribute_getPersistentAttributeType_MANY_TO_ONE_Method"));
            suite.addTest(new MetamodelMetamodelTest("testAttribute_getPersistentAttributeType_ELEMENT_COLLECTION_Method"));
            suite.addTest(new MetamodelMetamodelTest("testAttribute_getName_Method"));
            suite.addTest(new MetamodelMetamodelTest("testAttribute_getDeclaringType_Method"));
            suite.addTest(new MetamodelMetamodelTest("testAttribute_getJavaType_BasicType_Method"));
            suite.addTest(new MetamodelMetamodelTest("testAttribute_getJavaType_ManagedType_Method"));
            suite.addTest(new MetamodelMetamodelTest("testAttribute_getJavaMember_BasicType_on_MappedSuperclass_Method"));
            suite.addTest(new MetamodelMetamodelTest("testAttribute_getJavaMember_BasicType_FieldAccess_on_Embeddable_Method")); // 316991
            suite.addTest(new MetamodelMetamodelTest("testAttribute_getJavaMember_BasicType_PropertyAccess_on_Embeddable_Method")); // 316991
            suite.addTest(new MetamodelMetamodelTest("testAttribute_getJavaMember_BasicType_on_Entity_Method"));
            suite.addTest(new MetamodelMetamodelTest("testAttribute_getJavaMember_EntityType_FieldLevel_on_Entity_Method")); // 316991
            suite.addTest(new MetamodelMetamodelTest("testAttribute_getJavaMember_EntityType_FieldLevel_on_MappedSuperclass_Method")); // 316991
            suite.addTest(new MetamodelMetamodelTest("testAttribute_getJavaMember_EntityType_PropertyMethodLevel_on_Entity_Method")); // 316991
            suite.addTest(new MetamodelMetamodelTest("testAttribute_getJavaMember_EntityType_PropertyMethodLevel_on_MappedSuperclass_Method")); // 316991
            suite.addTest(new MetamodelMetamodelTest("testAttribute_getJavaMember_ManagedType_Method"));
            suite.addTest(new MetamodelMetamodelTest("testAttribute_isAssociation_on_Plural_Method"));
            suite.addTest(new MetamodelMetamodelTest("testAttribute_isAssociation_on_Singular_Method"));
            suite.addTest(new MetamodelMetamodelTest("testAttribute_isCollection_false_Method"));
            suite.addTest(new MetamodelMetamodelTest("testAttribute_isCollection_true_Method"));

            suite.addTest(new MetamodelMetamodelTest("testBasicType"));
            suite.addTest(new MetamodelMetamodelTest("testBindable_getBindableType_Method"));
            suite.addTest(new MetamodelMetamodelTest("testBindable_getBindableJavaType_Method"));
            suite.addTest(new MetamodelMetamodelTest("testEmbeddableType"));
            suite.addTest(new MetamodelMetamodelTest("testNestedEmbeddableType"));  // 300626
            suite.addTest(new MetamodelMetamodelTest("testEntityType"));
            suite.addTest(new MetamodelMetamodelTest("testEntityAttribute_getBindableJavaType_Method"));
            // Note: Since BasicTypes are lazy - loaded into the metamodel-types Map - this test must proceed any test that first gets the Position class BasicType object - see  like "testTransientNonEntityNonMappedSuperclass_SuperclassOfEntity_Exists_as_BasicType"
            // You will get a lower number here - if only this single test is run via the Testing Browser
            suite.addTest(new MetamodelMetamodelTest("testIdentifiableType_getIdType_Method"));
            suite.addTest(new MetamodelMetamodelTest("testIdentifiableType_getIdClassAttributes_Method"));
            suite.addTest(new MetamodelMetamodelTest("testIdentifiableType_getIdClassAttributesAcrossMappedSuperclassChain_Method")); // 288792
            suite.addTest(new MetamodelMetamodelTest("testIdentifiableType_hasVersionAttribute_Method"));
            suite.addTest(new MetamodelMetamodelTest("testIdentifiableType_hasSingleIdAttribute_Method"));
            suite.addTest(new MetamodelMetamodelTest("testIdentifiableType_getSupertype_Method"));
            suite.addTest(new MetamodelMetamodelTest("testIdentifiableType_getDeclaredVersion_exists_Method"));
            suite.addTest(new MetamodelMetamodelTest("testIdentifiableType_getDeclaredVersion_exists_above_Method"));
            suite.addTest(new MetamodelMetamodelTest("testIdentifiableType_getDeclaredVersion_does_not_exist_at_all_Method"));
            suite.addTest(new MetamodelMetamodelTest("testIdentifiableType_getVersion_Method"));
            suite.addTest(new MetamodelMetamodelTest("testIdentifiableType_getDeclaredId_Method"));
            suite.addTest(new MetamodelMetamodelTest("testIdentifiableType_getId_Method"));
            suite.addTest(new MetamodelMetamodelTest("testIdentifiableType_getId_with_EmbeddedId_Method"));
            suite.addTest(new MetamodelMetamodelTest("testIdentifiableType_getDeclaredId_normal_execution_attribute_is_declared"));
            suite.addTest(new MetamodelMetamodelTest("testIdentifiableType_getDeclaredId_variant_execution_attribute_is_declared_above"));
            suite.addTest(new MetamodelMetamodelTest("testIdentifiableType_getDeclaredId_variant_execution_attribute_is_not_declared_at_all"));
            suite.addTest(new MetamodelMetamodelTest("testIdentifiableType_getDeclaredId_normal_execution_attribute_is_declared"));
            suite.addTest(new MetamodelMetamodelTest("testIdentifiableType_getIdType_handles_possible_null_cmppolicy"));

            suite.addTest(new MetamodelMetamodelTest("testListAttribute"));
            suite.addTest(new MetamodelMetamodelTest("testManagedType_getAttributes_Method"));
            suite.addTest(new MetamodelMetamodelTest("testManagedType_getDeclaredAttributes_Method"));
            suite.addTest(new MetamodelMetamodelTest("testManagedType_getSingularAttribute_Type_param_Method"));
            suite.addTest(new MetamodelMetamodelTest("testManagedType_getDeclaredSingularAttribute_Type_param_Method"));
            suite.addTest(new MetamodelMetamodelTest("testManagedType_getSingularAttributes_Method"));
            suite.addTest(new MetamodelMetamodelTest("testManagedType_getDeclaredSingularAttributes_Method"));
            suite.addTest(new MetamodelMetamodelTest("testManagedType_getCollection_Type_param_Method"));
            suite.addTest(new MetamodelMetamodelTest("testManagedType_getDeclaredCollection_Type_param_Method"));
            suite.addTest(new MetamodelMetamodelTest("testManagedType_getSet_Type_param_Method"));
            suite.addTest(new MetamodelMetamodelTest("testManagedType_getDeclaredSet_Type_param_Method"));
            suite.addTest(new MetamodelMetamodelTest("testManagedType_getList_Type_param_Method"));
            suite.addTest(new MetamodelMetamodelTest("testManagedType_getDeclaredList_Type_param_Method"));
            suite.addTest(new MetamodelMetamodelTest("testManagedType_getMap_Type_param_Method"));
            suite.addTest(new MetamodelMetamodelTest("testManagedType_getDeclaredMap_Type_param_Method"));
            suite.addTest(new MetamodelMetamodelTest("testManagedType_getDeclaredMap_Type_param_not_found_iae_Method"));
            suite.addTest(new MetamodelMetamodelTest("testManagedType_getDeclaredMap_Type_param_declared_above_Method"));
            suite.addTest(new MetamodelMetamodelTest("testManagedType_getPluralAttributes_Method"));
            suite.addTest(new MetamodelMetamodelTest("testManagedType_getDeclaredPluralAttributes_internal_entity_Method"));
            suite.addTest(new MetamodelMetamodelTest("testManagedType_getDeclaredPluralAttributes_root_entity_Method"));
            suite.addTest(new MetamodelMetamodelTest("testManagedType_getDeclaredPluralAttributes_root_mappedSuperclass_Method"));
            suite.addTest(new MetamodelMetamodelTest("testManagedType_getAttribute_on_Entity_Method"));
            suite.addTest(new MetamodelMetamodelTest("testManagedType_getAttribute_on_MappedSuperclass_Method"));
            suite.addTest(new MetamodelMetamodelTest("testManagedType_getAttribute_doesNotExist_on_Entity_Method"));
            suite.addTest(new MetamodelMetamodelTest("testManagedType_getAttribute_doesNotExist_on_MappedSuperclass_Method"));
            suite.addTest(new MetamodelMetamodelTest("testManagedType_getDeclaredAttribute_Method"));
            suite.addTest(new MetamodelMetamodelTest("testManagedType_getDeclaredListAttribute_Method"));
            suite.addTest(new MetamodelMetamodelTest("testManagedType_getDeclaredAttribute_above_throws_iae_Method"));
            suite.addTest(new MetamodelMetamodelTest("testManagedType_getDeclaredAttribute_doesNotExist_Method"));
            suite.addTest(new MetamodelMetamodelTest("testManagedType_getSingularAttribute_BASIC_Method"));
            suite.addTest(new MetamodelMetamodelTest("testManagedType_getSingularAttribute_EMBEDDED_Method"));
            suite.addTest(new MetamodelMetamodelTest("testManagedType_getDeclaredSingularAttribute_on_Entity_Method"));
            suite.addTest(new MetamodelMetamodelTest("testManagedType_getDeclaredSingularAttribute_on_MappedSuperclass_Method"));
            suite.addTest(new MetamodelMetamodelTest("testManagedType_getCollection_Method"));
            suite.addTest(new MetamodelMetamodelTest("testManagedType_getDeclaredCollection_Method"));
            suite.addTest(new MetamodelMetamodelTest("testManagedType_getSet_Method"));
            suite.addTest(new MetamodelMetamodelTest("testManagedType_getDeclaredSet_Method"));
            suite.addTest(new MetamodelMetamodelTest("testManagedType_getList_Method"));
            suite.addTest(new MetamodelMetamodelTest("testManagedType_getDeclaredList_Method"));
            suite.addTest(new MetamodelMetamodelTest("testManagedType_getMap_Method"));
            suite.addTest(new MetamodelMetamodelTest("testManagedType_getDeclaredMap_Method"));
            suite.addTest(new MetamodelMetamodelTest("testManagedType_variantCases"));
            suite.addTest(new MetamodelMetamodelTest("testMapAttribute_getKeyJavaType_UC0_Method"));
            suite.addTest(new MetamodelMetamodelTest("testMapAttribute_getKeyJavaType_UC1a_Method"));
            suite.addTest(new MetamodelMetamodelTest("testMapAttribute_getKeyJavaType_UC2_Method"));
            suite.addTest(new MetamodelMetamodelTest("testMapAttribute_getKeyJavaType_UC4_Method"));
            suite.addTest(new MetamodelMetamodelTest("testMapAttribute_getKeyJavaType_UC7_Method"));
            suite.addTest(new MetamodelMetamodelTest("testMapAttribute_getKeyJavaType_UC8_Method"));
            // http://wiki.eclipse.org/EclipseLink/Development/JPA_2.0/metamodel_api#DI_86:_20090921:_Handle_Embeddable_Type_keyType_in_MapAttributeImpl_constructor
            suite.addTest(new MetamodelMetamodelTest("testMapAttribute_getKeyJavaType_UC9_DI86_Embeddable_IdClass_keyType_Method"));
            suite.addTest(new MetamodelMetamodelTest("testMapAttribute_getKeyType_UC0_Method"));
            suite.addTest(new MetamodelMetamodelTest("testMapAttribute_getKeyType_UC1a_Method"));
            suite.addTest(new MetamodelMetamodelTest("testMapAttribute_getKeyType_UC2_Method"));
            suite.addTest(new MetamodelMetamodelTest("testMapAttribute_getKeyType_UC4_Method"));
            suite.addTest(new MetamodelMetamodelTest("testMapAttribute_getKeyType_UC7_Method"));
            suite.addTest(new MetamodelMetamodelTest("testMapAttribute_getKeyType_UC8_Method"));
            suite.addTest(new MetamodelMetamodelTest("testMapAttribute_getKeyType_UC9_DI86_Embeddable_IdClass_keyType_Method"));
            // These 3 test verify the workaround for 294811
            suite.addTest(new MetamodelMetamodelTest("testMapAttribute_getKeyType_294811_UC10_DI86_Embeddable_IdClass_keyType_Method"));
            suite.addTest(new MetamodelMetamodelTest("testMapAttribute_getKeyType_294811_UC12_DI86_Embedded_keyType_Method"));
            suite.addTest(new MetamodelMetamodelTest("testMapAttribute_getKeyType_294811_UC13_DI86_Embedded_keyType_Method"));
            suite.addTest(new MetamodelMetamodelTest("testMapAtributeElementTypeWhenMapKeySetButNameAttributeIsDefaulted"));
            suite.addTest(new MetamodelMetamodelTest("testMapAtributeElementTypeWhenMapKeySetAndNameAttributeSet"));
            // Pending implementation
            //suite.addTest(new MetamodelMetamodelTest("testMapAtributeElementTypeWhenMapKeyNotSet_MapKeyColumnSet"));
            //suite.addTest(new MetamodelMetamodelTest("testMapAtributeElementTypeWhenMapKeyNotSet_MapKeyColumnSet")); // JPA 2.0 specific

            suite.addTest(new MetamodelMetamodelTest("testMappedSuperclassType"));
            suite.addTest(new MetamodelMetamodelTest("testMetamodel_entity_Method"));
            suite.addTest(new MetamodelMetamodelTest("testMetamodel_embeddable_Method"));
            suite.addTest(new MetamodelMetamodelTest("testMetamodel_managedType_Method"));
            suite.addTest(new MetamodelMetamodelTest("testMetamodel_getEntities_Method"));
            suite.addTest(new MetamodelMetamodelTest("testMetamodel_getManagedTypes_Method"));
            suite.addTest(new MetamodelMetamodelTest("testMetamodel_getEmbeddables_Method"));
            suite.addTest(new MetamodelMetamodelTest("testPluralAttribute_CollectionType_enum"));
            suite.addTest(new MetamodelMetamodelTest("testPluralAttribute_getCollectionType_Method"));
            suite.addTest(new MetamodelMetamodelTest("testPluralAttribute_getElementType_Method"));
            suite.addTest(new MetamodelMetamodelTest("testPluralAttribute_getBindableJavaType_Method"));
            suite.addTest(new MetamodelMetamodelTest("testSetAttribute"));
            suite.addTest(new MetamodelMetamodelTest("testSingularAttribute_isOptional_Method"));
            suite.addTest(new MetamodelMetamodelTest("testSingularAttribute_isId_Method"));
            suite.addTest(new MetamodelMetamodelTest("testSingularAttribute_isVersion_Method"));
            suite.addTest(new MetamodelMetamodelTest("testSingularAttribute_getBindableType_Method"));
            suite.addTest(new MetamodelMetamodelTest("testSingularAttribute_getBindableJavaType_Method"));
            suite.addTest(new MetamodelMetamodelTest("testSingularAttribute_getJavaType_Method"));
            suite.addTest(new MetamodelMetamodelTest("testSingularAttribute_getType_Method"));
            suite.addTest(new MetamodelMetamodelTest("testToStringOverrides"));
            suite.addTest(new MetamodelMetamodelTest("testType_PersistenceType_enum"));
            suite.addTest(new MetamodelMetamodelTest("testType_getPersistenceType_Method"));
            suite.addTest(new MetamodelMetamodelTest("testType_getJavaType_Method"));
            suite.addTest(new MetamodelMetamodelTest("testOutOfSpecificationInternalAPI"));
            suite.addTest(new MetamodelMetamodelTest("testMapAttribute_getDeclaredPluralAttributesForEmbeddable"));
            // Not implemented yet
            //suite.addTest(new MetamodelMetamodelTest("testObscureInvalidStateUnitTests"));
        }
        return suite;
    }

    @Override
    public void setUp() {
        super.setUp();
    }

    /**
     * Perform a test by "Not" caching the EMF and letting the test close the EMF to
     * verify variant use cases that may throw an IAE on a closed EntityManger
     */
    private EntityManager privateTestSetup(boolean overrideEMFCachingForTesting) {
        EntityManagerFactory emf = null;
        EntityManager em = null;
        boolean exceptionThrown = false;
        Metamodel metamodel = null;

        try {
            emf = initialize(overrideEMFCachingForTesting);
            em = emf.createEntityManager();

            metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
        } catch (Exception e) {
            e.printStackTrace();
            cleanup(em);
        }
        return em;
    }

    private EntityManager privateTestSetup() {
        return privateTestSetup(false);
    }

    private void privateTestTeardown() {
    }

    // 300051: Test is that the class passes processing in the testing browser - verify that the model has loaded here as well
    public void testMetamodelEmbeddedIdDirectlyOnMappedSuperclassRootPassesValidation() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            // Verify our classes involved in an @EmbeddedId on a @MappedSuperclass loaded
            ManagedType<CPU> msCPU = metamodel.managedType(CPU.class);
            assertNotNull(msCPU);
            assertEquals(Type.PersistenceType.MAPPED_SUPERCLASS, msCPU.getPersistenceType());

            ManagedType<MultiCoreCPU> eMultiCoreCPU = metamodel.managedType(MultiCoreCPU.class);
            assertNotNull(eMultiCoreCPU);
            assertEquals(Type.PersistenceType.ENTITY, eMultiCoreCPU.getPersistenceType());

            ManagedType<Core> eCore = metamodel.managedType(Core.class);
            assertNotNull(eCore);
            assertEquals(Type.PersistenceType.ENTITY, eCore.getPersistenceType());

            ManagedType<CPUEmbeddedId> embedCPUEmbeddedId = metamodel.managedType(CPUEmbeddedId.class);
            assertNotNull(embedCPUEmbeddedId);
            assertEquals(Type.PersistenceType.EMBEDDABLE, embedCPUEmbeddedId.getPersistenceType());
            // 316991: DI 95: Handle case where getMethod is not set - but getMethodName is
            // http://wiki.eclipse.org/EclipseLink/Development/JPA_2.0/metamodel_api#DI_95:_20091017:_Attribute.getJavaMember.28.29_returns_null_for_a_BasicType_on_a_MappedSuperclass_because_of_an_uninitialized_accessor
            Attribute embeddedAttribute = embedCPUEmbeddedId.getAttribute("pk_part1");
            assertNotNull(embeddedAttribute);
            Member aMember = embeddedAttribute.getJavaMember();
            assertNotNull(aMember);
            assertNotNull("id java member is null", aMember);
            assertTrue("id attribute java member is not an instance of Method", aMember instanceof Method);
            assertEquals("getPk_part1", aMember.getName());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }


    /**
     * There is no simple way to test the predeploy() for this issue - however we can
     * verify that the MS - MS - Entity chain is loaded correctly.
     *
     */
    public void testValidation_relaxed_for_composite_pk_on_mappedSuperclass_chain() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            ManagedType<Person> msPerson = metamodel.managedType(Person.class);
            assertNotNull(msPerson);
            assertEquals(Type.PersistenceType.MAPPED_SUPERCLASS, msPerson.getPersistenceType());
        } catch (IllegalArgumentException iae) {
            //iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }


    // http://wiki.eclipse.org/EclipseLink/Development/JPA_2.0/metamodel_api#DI_93:_20091014:_Single_PK_support_in_IdentifiableTypeImpl.getIdType.28.29_does_not_fully_handle_a_null_CMPPolicy_on_the_Descriptor
    public void testIdentifiableType_getIdType_handles_possible_null_cmppolicy() {
        boolean exceptionThrown = false;
        EntityManager em = null;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
        boolean expectedIAExceptionThrown = false;
            Type<?> personIdType = null;
            MappedSuperclassTypeImpl<Person> msPerson_ = (MappedSuperclassTypeImpl)metamodel.managedType(Person.class);
            assertNotNull(msPerson_);

            personIdType = msPerson_.getIdType();
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
            assertNotNull(personIdType);
            assertEquals(PersistenceType.BASIC, personIdType.getPersistenceType());
            assertEquals(Integer.class, personIdType.getJavaType());
        } catch (IllegalArgumentException iae) {
            // expecting no exception
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur on getIdType() here.", exceptionThrown);
        }
    }

    /**
     * These tests are for states that should never be reached by API implementors.
     */
    // TODO: This is not testing anything yet.
    public void testObscureInvalidStateUnitTests() {
        boolean exceptionThrown = false;
        EntityManager em = null;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);

            // Test toString() for a Type without a javaType attribute
            //Type invalidType = new BasicTypeImpl(null);
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    public void testIdentifiableType_getDeclaredId_variant_execution_attribute_is_declared_above() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            ManagedType<Manufacturer> entityManufacturer_ = metamodel.managedType(Manufacturer.class);
            assertNotNull(entityManufacturer_);
            assertEquals(Type.PersistenceType.ENTITY, entityManufacturer_.getPersistenceType());

            /**
             *  Return the attribute that corresponds to the id attribute
             *  declared by the entity or mapped superclass.
             *  @param type  the type of the represented declared id attribute
             *  @return declared id attribute
             *  @throws IllegalArgumentException if id attribute of the given
             *          type is not declared in the identifiable type or if
             *          the identifiable type has an id class
             */
            //<Y> SingularAttribute<X, Y> getDeclaredId(Class<Y> type);
            // Not declared  - invalid - IAE thrown (actually declared 2 levels above in "Person")
            Attribute idAttribute = ((IdentifiableType)entityManufacturer_).getDeclaredId(Integer.class);
        } catch (IllegalArgumentException iae) {
            //iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertTrue("non-declared attribute should throw an IAE", exceptionThrown);
        }
    }

    // TODO: This is not testing anything yet.
    public void testIdentifiableType_getDeclaredId_variant_execution_attribute_is_not_declared_at_all() {
    }

    public void testIdentifiableType_getDeclaredId_normal_execution_attribute_is_declared() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            ManagedType<Person> msPerson = metamodel.managedType(Person.class);
            assertNotNull(msPerson);
            assertEquals(Type.PersistenceType.MAPPED_SUPERCLASS, msPerson.getPersistenceType());

            /**
             *  Return the attribute that corresponds to the id attribute
             *  declared by the entity or mapped superclass.
             *  @param type  the type of the represented declared id attribute
             *  @return declared id attribute
             *  @throws IllegalArgumentException if id attribute of the given
             *          type is not declared in the identifiable type or if
             *          the identifiable type has an id class
             */
            //<Y> SingularAttribute<X, Y> getDeclaredId(Class<Y> type);
            // declared  - valid
            Attribute idAttribute = ((IdentifiableType)msPerson).getDeclaredId(Integer.class);
            assertNotNull(idAttribute);
            assertEquals(Integer.class, idAttribute.getJavaType());
            // declared and valid

            //*********************************************/
            // FUTURE: Require a version on a MappedSuperclass
            //assertNotNull(msPerson1_.getDeclaredId(Integer.class)); - keep commented
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    public void testAttribute_getPersistentAttributeType_BASIC_Method() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);
            assertEquals(Type.PersistenceType.ENTITY, entityManufacturer_.getPersistenceType());

            // Actual Test Case
            /*public static enum PersistentAttributeType {
            MANY_TO_ONE, ONE_TO_ONE, BASIC, EMBEDDED,
            MANY_TO_MANY, ONE_TO_MANY, ELEMENT_COLLECTION
            }*/

            /**
             *  Return the persistent attribute type for the attribute.
             *  @return persistent attribute type
             */
            //PersistentAttributeType getPersistentAttributeType();

            Attribute anAttribute = entityManufacturer_.getAttribute("anInt");
            assertNotNull(anAttribute);
            assertEquals(int.class, anAttribute.getJavaType());
            assertEquals(PersistentAttributeType.BASIC, anAttribute.getPersistentAttributeType());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    public void testAttribute_getPersistentAttributeType_ONE_TO_ONE_Method() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Computer> entityComputer_ = (EntityTypeImpl)metamodel.entity(Computer.class);
            assertNotNull(entityComputer_);

            // Actual Test Case
            /*public static enum PersistentAttributeType {
            MANY_TO_ONE, ONE_TO_ONE, BASIC, EMBEDDED,
            MANY_TO_MANY, ONE_TO_MANY, ELEMENT_COLLECTION
            }*/

            /**
             *  Return the persistent attribute type for the attribute.
             *  @return persistent attribute type
             */
            //PersistentAttributeType getPersistentAttributeType();

            Attribute anAttribute = entityComputer_.getAttribute("location");
            assertNotNull(anAttribute);
            assertEquals(GalacticPosition.class, anAttribute.getJavaType());
            assertEquals(PersistentAttributeType.ONE_TO_ONE, anAttribute.getPersistentAttributeType());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    public void testAttribute_getPersistentAttributeType_ONE_TO_MANY_Method() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);
            assertEquals(Type.PersistenceType.ENTITY, entityManufacturer_.getPersistenceType());

            // Actual Test Case
            /*public static enum PersistentAttributeType {
            MANY_TO_ONE, ONE_TO_ONE, BASIC, EMBEDDED,
            MANY_TO_MANY, ONE_TO_MANY, ELEMENT_COLLECTION
            }*/

            /**
             *  Return the persistent attribute type for the attribute.
             *  @return persistent attribute type
             */
            //PersistentAttributeType getPersistentAttributeType();

            Attribute anAttribute = entityManufacturer_.getAttribute("computers");
            assertNotNull(anAttribute);
            assertTrue(((AttributeImpl)anAttribute).isPlural());
            assertTrue(anAttribute instanceof PluralAttribute);
            Bindable aPluralAttribute = entityManufacturer_.getSet("computers");
            assertEquals(Computer.class, aPluralAttribute.getBindableJavaType());
            assertEquals(Set.class, anAttribute.getJavaType());
            assertEquals(PersistentAttributeType.ONE_TO_MANY, anAttribute.getPersistentAttributeType());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    // TODO: This is not testing anything yet.
    public void testAttribute_getPersistentAttributeType_MANY_TO_MANY_Method() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);

            // Actual Test Case
            /*public static enum PersistentAttributeType {
            MANY_TO_ONE, ONE_TO_ONE, BASIC, EMBEDDED,
            MANY_TO_MANY, ONE_TO_MANY, ELEMENT_COLLECTION
            }*/

            /**
             *  Return the persistent attribute type for the attribute.
             *  @return persistent attribute type
             */
            //PersistentAttributeType getPersistentAttributeType();
            // note: not implemented yet - need a manyToMany in the model
            //assertEquals(PersistentAttributeType.MANY_TO_MANY, anAttribute.getPersistentAttributeType());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    public void testAttribute_getPersistentAttributeType_MANY_TO_ONE_Method() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Board> entityBoard_ = (EntityTypeImpl)metamodel.entity(Board.class);
            assertNotNull(entityBoard_);
            assertEquals(Type.PersistenceType.ENTITY, entityBoard_.getPersistenceType());

            // Actual Test Case
            /*public static enum PersistentAttributeType {
            MANY_TO_ONE, ONE_TO_ONE, BASIC, EMBEDDED,
            MANY_TO_MANY, ONE_TO_MANY, ELEMENT_COLLECTION
            }*/

            /**
             *  Return the persistent attribute type for the attribute.
             *  @return persistent attribute type
             */
            //PersistentAttributeType getPersistentAttributeType();

            Attribute anAttribute = entityBoard_.getAttribute("computer");
            assertNotNull(anAttribute);
            assertEquals(Computer.class, anAttribute.getJavaType());
            // Note: internally our MANY_TO_ONE is treated as a ONE_TO_ONE - although with a DB constraint
            assertEquals(PersistentAttributeType.MANY_TO_ONE, anAttribute.getPersistentAttributeType());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    // TODO: This is not testing anything yet.
    public void testAttribute_getPersistentAttributeType_ELEMENT_COLLECTION_Method() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);
            assertEquals(Type.PersistenceType.ENTITY, entityManufacturer_.getPersistenceType());

            // Actual Test Case
            /*public static enum PersistentAttributeType {
            MANY_TO_ONE, ONE_TO_ONE, BASIC, EMBEDDED,
            MANY_TO_MANY, ONE_TO_MANY, ELEMENT_COLLECTION
            }*/

            /**
             *  Return the persistent attribute type for the attribute.
             *  @return persistent attribute type
             */
            //PersistentAttributeType getPersistentAttributeType();

            Attribute anAttribute = entityManufacturer_.getAttribute("computers");
            // FUTURE: Not Implemented
            //assertNotNull(anAttribute);
            //assertEquals(Computer.class, anAttribute.getJavaType());
            //assertEquals(PersistentAttributeType.ELEMENT_COLLECTION, anAttribute.getPersistentAttributeType());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    public void testAttribute_getPersistentAttributeType_EMBEDDED_Method() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<GalacticPosition> entityGalacticPosition_ = (EntityTypeImpl)metamodel.entity(GalacticPosition.class);
            assertNotNull(entityGalacticPosition_);
            assertEquals(Type.PersistenceType.ENTITY, entityGalacticPosition_.getPersistenceType());

            // Actual Test Case
            /*public static enum PersistentAttributeType {
            MANY_TO_ONE, ONE_TO_ONE, BASIC, EMBEDDED,
            MANY_TO_MANY, ONE_TO_MANY, ELEMENT_COLLECTION
            }*/

            /**
             *  Return the persistent attribute type for the attribute.
             *  @return persistent attribute type
             */
            //PersistentAttributeType getPersistentAttributeType();

            Attribute anAttribute = entityGalacticPosition_.getAttribute("primaryKey");
            assertNotNull(anAttribute);
            assertEquals(EmbeddedPK.class, anAttribute.getJavaType());
            assertEquals(PersistentAttributeType.EMBEDDED, anAttribute.getPersistentAttributeType());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    public void testAttribute_getName_Method() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);

            /**
             * Return the name of the attribute.
             * @return name
             */
            //String getName();

            ManagedType<Person> msPerson = metamodel.managedType(Person.class);
            assertNotNull(msPerson);
            assertEquals(Type.PersistenceType.MAPPED_SUPERCLASS, msPerson.getPersistenceType());
            Attribute idAttribute = ((IdentifiableType)msPerson).getDeclaredId(Integer.class);
            assertNotNull(idAttribute);
            assertEquals(Integer.class, idAttribute.getJavaType());
            assertEquals("id", idAttribute.getName());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    public void testAttribute_getDeclaringType_Method() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);
            EntityTypeImpl<HardwareDesigner> entityHardwareDesigner_ = (EntityTypeImpl)metamodel.entity(HardwareDesigner.class);
            assertNotNull(entityHardwareDesigner_);

            /**
             *  Return the managed type representing the type in which
             *  the attribute was declared.
             *  @return declaring type
             */
            //ManagedType<X> getDeclaringType();

            // Test case
            Attribute anAttribute = entityManufacturer_.getDeclaredAttribute("hardwareDesignersMapUC4");
            ManagedType aManagedType = anAttribute.getDeclaringType();
            assertEquals(entityManufacturer_, aManagedType);
            assertNotNull(anAttribute);
            assertEquals(PersistentAttributeType.ONE_TO_MANY, anAttribute.getPersistentAttributeType());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    public void testAttribute_getJavaType_BasicType_Method() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);

            /**
             *  Return the Java type of the represented attribute.
             *  @return Java type
             */
            //Class<Y> getJavaType();
            ManagedType<Person> msPerson = metamodel.managedType(Person.class);
            assertNotNull(msPerson);
            assertEquals(Type.PersistenceType.MAPPED_SUPERCLASS, msPerson.getPersistenceType());
            Attribute idAttribute = ((IdentifiableType)msPerson).getDeclaredId(Integer.class);
            assertNotNull(idAttribute);
            assertEquals(Integer.class, idAttribute.getJavaType());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    public void testAttribute_getJavaType_ManagedType_Method() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);

            /**
             *  Return the Java type of the represented attribute.
             *  @return Java type
             */
            //Class<Y> getJavaType();
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);
            assertEquals(Type.PersistenceType.ENTITY, entityManufacturer_.getPersistenceType());
            Attribute anAttribute = entityManufacturer_.getAttribute("computers");
            assertNotNull(anAttribute);
            assertTrue(((AttributeImpl)anAttribute).isPlural());
            assertTrue(anAttribute instanceof PluralAttribute);
            Bindable aPluralAttribute = entityManufacturer_.getSet("computers");
            assertEquals(Computer.class, aPluralAttribute.getBindableJavaType());
            assertEquals(Set.class, anAttribute.getJavaType());
            assertEquals(PersistentAttributeType.ONE_TO_MANY, anAttribute.getPersistentAttributeType());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    public void testAttribute_getJavaMember_BasicType_on_MappedSuperclass_Method() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            ManagedType<Person> msPerson = metamodel.managedType(Person.class);
            assertNotNull(msPerson);
            assertEquals(Type.PersistenceType.MAPPED_SUPERCLASS, msPerson.getPersistenceType());

            /**
             *  Return the java.lang.reflect.Member for the represented
             *  attribute.
             *  @return corresponding java.lang.reflect.Member
             */
            //java.lang.reflect.Member getJavaMember();
            Attribute idAttribute = ((IdentifiableType)msPerson).getDeclaredId(Integer.class);
            assertNotNull(idAttribute);
            assertEquals(Integer.class, idAttribute.getJavaType());
            // For primitive and basic types - we should not return null - the attributeAccessor on the MappedSuperclass is not initialized - see
            // http://wiki.eclipse.org/EclipseLink/Development/JPA_2.0/metamodel_api#DI_95:_20091017:_Attribute.getJavaMember.28.29_returns_null_for_a_BasicType_on_a_MappedSuperclass_because_of_an_uninitialized_accessor
            Member aMember = idAttribute.getJavaMember();
            assertNotNull("id java member is null", aMember);
            assertTrue("id attribute java member is not an instance of Field", aMember instanceof Field);
            assertEquals("id", aMember.getName());
            assertNotNull(((Field)aMember).getType());
            assertEquals(Integer.class.getName(), ((Field)aMember).getType().getName());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    // 316991: handle missing getMethod on embeddables by using the getMethodName
    public void testAttribute_getJavaMember_BasicType_FieldAccess_on_Embeddable_Method() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);

            /**
             *  Return the java.lang.reflect.Member for the represented attribute.
             *  @return corresponding java.lang.reflect.Member
             */
            //java.lang.reflect.Member getJavaMember();
            ManagedType<EmbeddedPK> embedableAttribute = metamodel.managedType(EmbeddedPK.class);
            assertNotNull(embedableAttribute);
            assertEquals(Type.PersistenceType.EMBEDDABLE, embedableAttribute.getPersistenceType());
            // 316991: DI 95: Handle case where getMethod is not set - but getMethodName is
            // http://wiki.eclipse.org/EclipseLink/Development/JPA_2.0/metamodel_api#DI_95:_20091017:_Attribute.getJavaMember.28.29_returns_null_for_a_BasicType_on_a_MappedSuperclass_because_of_an_uninitialized_accessor
            Attribute embeddedAttribute = embedableAttribute.getAttribute("pk_part1");
            assertNotNull(embeddedAttribute);
            // The following line exercises the 2nd field part for non-MappedSuperclasses in getJavaMember()
            Member aMember = embeddedAttribute.getJavaMember();
            assertNotNull(aMember); // Fix for missing getMethod in 316991
            assertNotNull("pk_part1 java member is null", aMember);
            assertTrue("pk_part1 attribute java member is not an instance of Method", aMember instanceof Field);
            assertEquals("pk_part1", aMember.getName());
            assertNotNull(((Field)aMember).getType());
            assertEquals(int.class.getName(), ((Field)aMember).getType().getName());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    // 316991: handle missing getMethod on embeddables by using the getMethodName
    public void testAttribute_getJavaMember_BasicType_PropertyAccess_on_Embeddable_Method() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);

            /**
             *  Return the java.lang.reflect.Member for the represented attribute.
             *  @return corresponding java.lang.reflect.Member
             */
            //java.lang.reflect.Member getJavaMember();
            ManagedType<CPUEmbeddedId> embedCPUEmbeddedId = metamodel.managedType(CPUEmbeddedId.class);
            assertNotNull(embedCPUEmbeddedId);
            assertEquals(Type.PersistenceType.EMBEDDABLE, embedCPUEmbeddedId.getPersistenceType());
            // 316991: DI 95: Handle case where getMethod is not set - but getMethodName is
            // http://wiki.eclipse.org/EclipseLink/Development/JPA_2.0/metamodel_api#DI_95:_20091017:_Attribute.getJavaMember.28.29_returns_null_for_a_BasicType_on_a_MappedSuperclass_because_of_an_uninitialized_accessor
            Attribute embeddedAttribute = embedCPUEmbeddedId.getAttribute("pk_part1");
            assertNotNull(embeddedAttribute);
            Member aMember = embeddedAttribute.getJavaMember();
            assertNotNull(aMember); // Fix for missing getMethod in 316991
            assertNotNull("id java member is null", aMember);
            assertTrue("id attribute java member is not an instance of Method", aMember instanceof Method);
            assertEquals("getPk_part1", aMember.getName());
            assertEquals(int.class, ((Method)aMember).getReturnType());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    public void testAttribute_getJavaMember_BasicType_on_Entity_Method() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);
            assertEquals(Type.PersistenceType.ENTITY, entityManufacturer_.getPersistenceType());

            /**
             *  Return the java.lang.reflect.Member for the represented
             *  attribute.
             *  @return corresponding java.lang.reflect.Member
             */
            //java.lang.reflect.Member getJavaMember();
            Attribute anAttribute = entityManufacturer_.getAttribute("anInt");
            assertNotNull(anAttribute);
            assertEquals(int.class, anAttribute.getJavaType());
            // For primitive and basic types - we should not return null - the attributeAccessor on the MappedSuperclass is not initialized - see
            // http://wiki.eclipse.org/EclipseLink/Development/JPA_2.0/metamodel_api#DI_95:_20091017:_Attribute.getJavaMember.28.29_returns_null_for_a_BasicType_on_a_MappedSuperclass_because_of_an_uninitialized_accessor
            Member aMember = anAttribute.getJavaMember();
            assertNotNull("anInt java member is null", aMember);
            assertTrue("anInt attribute java member is not an instance of Field", aMember instanceof Field);
            assertEquals("anInt", aMember.getName());
            assertNotNull(((Field)aMember).getType());
            assertEquals(int.class.getName(), ((Field)aMember).getType().getName());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    // 316991: regression test getJavaMember() on field level access Entity attribute @OneToOne on an Entity
    public void testAttribute_getJavaMember_EntityType_FieldLevel_on_Entity_Method() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Computer> entityComputer_ = (EntityTypeImpl)metamodel.entity(Computer.class);
            assertNotNull(entityComputer_);
            assertEquals(Type.PersistenceType.ENTITY, entityComputer_.getPersistenceType());

            /**
             *  Return the java.lang.reflect.Member for the represented
             *  attribute.
             *  @return corresponding java.lang.reflect.Member
             */
            //java.lang.reflect.Member getJavaMember();
            Attribute anAttribute = entityComputer_.getAttribute("location");
            assertNotNull(anAttribute);
            assertEquals(GalacticPosition.class, anAttribute.getJavaType());
            Member aMember = anAttribute.getJavaMember();
            assertNotNull("location java member is null", aMember);
            assertTrue("location attribute java member is not an instance of Field", aMember instanceof Field);
            assertEquals("location", aMember.getName());
            assertNotNull(((Field)aMember).getType());
            assertEquals(GalacticPosition.class.getName(), ((Field)aMember).getType().getName());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    // 316991: regression test getJavaMember() on field level access Entity attribute unidirectional @OneToOne on a MappedSuperclass
    // This test exercises special handling code late in getJavaMember() for MappedSuperclasses
    public void testAttribute_getJavaMember_EntityType_FieldLevel_on_MappedSuperclass_Method() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            MappedSuperclassTypeImpl<Designer> msDesigner_ = (MappedSuperclassTypeImpl)metamodel.managedType(Designer.class);
            assertNotNull(msDesigner_);
            assertEquals(Type.PersistenceType.MAPPED_SUPERCLASS, msDesigner_.getPersistenceType());

            /**
             *  Return the java.lang.reflect.Member for the represented
             *  attribute.
             *  @return corresponding java.lang.reflect.Member
             */
            //java.lang.reflect.Member getJavaMember();
            Attribute anAttribute = msDesigner_.getAttribute("primaryEmployer");
            assertNotNull(anAttribute);
            assertEquals(Manufacturer.class, anAttribute.getJavaType());
            Member aMember = anAttribute.getJavaMember();
            assertNotNull("primaryEmployer java member is null", aMember);
            assertTrue("primaryEmployer attribute java member is not an instance of Field", aMember instanceof Field);
            assertEquals("primaryEmployer", aMember.getName());
            assertNotNull(((Field)aMember).getType());
            assertEquals(Manufacturer.class.getName(), ((Field)aMember).getType().getName());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    // 316991: regression test getJavaMember() on method level access Entity attribute unidirectional @OneToOne on an Entity
    public void testAttribute_getJavaMember_EntityType_PropertyMethodLevel_on_Entity_Method() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityType<VectorProcessor> anEntity_ = metamodel.entity(VectorProcessor.class);
            assertNotNull(anEntity_);
            assertEquals(Type.PersistenceType.ENTITY, anEntity_.getPersistenceType());

            /**
             *  Return the java.lang.reflect.Member for the represented
             *  attribute.
             *  @return corresponding java.lang.reflect.Member
             */
            //java.lang.reflect.Member getJavaMember();
            Attribute anAttribute = anEntity_.getAttribute("host");
            assertNotNull(anAttribute);
            assertEquals(Computer.class, anAttribute.getJavaType());
            Member aMember = anAttribute.getJavaMember();
            assertNotNull("host java member is null", aMember);
            assertTrue("host attribute java member is not an instance of Method", aMember instanceof Method);
            assertEquals("getHost", aMember.getName());
            assertEquals(Computer.class, ((Method)aMember).getReturnType());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    // 316991: regression test getJavaMember() on method level access Entity attribute unidirectional @OneToOne on a MappedSuperclass
    // This test exercises special handling code early in getJavaMember() for MappedSuperclasses
    public void testAttribute_getJavaMember_EntityType_PropertyMethodLevel_on_MappedSuperclass_Method() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            MappedSuperclassTypeImpl<MSRootPropertyAccess> aMappedSuperclass_ = (MappedSuperclassTypeImpl)metamodel.managedType(MSRootPropertyAccess.class);
            assertNotNull(aMappedSuperclass_);
            assertEquals(Type.PersistenceType.MAPPED_SUPERCLASS, aMappedSuperclass_.getPersistenceType());

            /**
             *  Return the java.lang.reflect.Member for the represented
             *  attribute.
             *  @return corresponding java.lang.reflect.Member
             */
            //java.lang.reflect.Member getJavaMember();
            Attribute anAttribute = aMappedSuperclass_.getAttribute("primarySuperComputer"); // if attribute is missing from model we throw an IAE
            assertNotNull(anAttribute);
            assertEquals(ArrayProcessor.class, anAttribute.getJavaType());
            Member aMember = anAttribute.getJavaMember();
            assertNotNull("primarySuperComputer java member is null", aMember);
            assertTrue("primarySuperComputer attribute java member is not an instance of Method", aMember instanceof Method);
            assertEquals("getPrimarySuperComputer", aMember.getName());
            assertEquals(ArrayProcessor.class, ((Method)aMember).getReturnType());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    public void testAttribute_getJavaMember_ManagedType_Method() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);
            assertEquals(Type.PersistenceType.ENTITY, entityManufacturer_.getPersistenceType());

            /**
             *  Return the java.lang.reflect.Member for the represented
             *  attribute.
             *  @return corresponding java.lang.reflect.Member
             */
            //java.lang.reflect.Member getJavaMember();
            Attribute anAttribute = entityManufacturer_.getAttribute("computers");
            assertNotNull(anAttribute);
            assertTrue(((AttributeImpl)anAttribute).isPlural());
            assertTrue(anAttribute instanceof PluralAttribute);
            Bindable aPluralAttribute = entityManufacturer_.getSet("computers");
            assertEquals(Computer.class, aPluralAttribute.getBindableJavaType());
            assertEquals(Set.class, anAttribute.getJavaType());
            assertEquals(PersistentAttributeType.ONE_TO_MANY, anAttribute.getPersistentAttributeType());

            Member aMember = anAttribute.getJavaMember();
            assertNotNull(aMember);
            assertTrue(aMember instanceof Field);
            assertEquals("computers", aMember.getName());
            assertNotNull(((Field)aMember).getType());
            assertEquals(Set.class.getName(), ((Field)aMember).getType().getName());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    public void testAttribute_isAssociation_on_Plural_Method() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);
            assertEquals(Type.PersistenceType.ENTITY, entityManufacturer_.getPersistenceType());

            /**
             *  Is the attribute an association.
             *  @return whether boolean indicating whether attribute
             *          corresponds to an association
             */
            //boolean isAssociation();
            Attribute anAttribute = entityManufacturer_.getAttribute("computers");
            assertNotNull(anAttribute);
            assertTrue(((AttributeImpl)anAttribute).isPlural());
            assertTrue(anAttribute instanceof PluralAttribute);
            Bindable aBindable = entityManufacturer_.getSet("computers");
            PluralAttribute aPluralAttribute = entityManufacturer_.getSet("computers");
            assertEquals(Computer.class, aPluralAttribute.getBindableJavaType());
            assertEquals(Set.class, anAttribute.getJavaType());
            assertEquals(PersistentAttributeType.ONE_TO_MANY, anAttribute.getPersistentAttributeType());

            boolean isAssociation = anAttribute.isAssociation();
            assertTrue(isAssociation);
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    public void testAttribute_isAssociation_on_Singular_Method() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<GalacticPosition> entityLocation_ = (EntityTypeImpl) metamodel.entity(GalacticPosition.class);
            assertNotNull(entityLocation_);
            EntityTypeImpl<Computer> entityComputer_ = (EntityTypeImpl)metamodel.entity(Computer.class);
            assertNotNull(entityComputer_);

            /**
             *  Is the attribute an association.
             *  @return whether boolean indicating whether attribute
             *          corresponds to an association
             */
            //boolean isAssociation();
            Attribute anAttribute = entityComputer_.getAttribute("location");
            assertNotNull(anAttribute);
            assertEquals(GalacticPosition.class, anAttribute.getJavaType());
            boolean isAssociation = anAttribute.isAssociation();
            // Only a ReferenceMapping that extends ObjectReferenceMapping returns true
            assertTrue(isAssociation);
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    public void testAttribute_isCollection_false_Method() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<GalacticPosition> entityLocation_ = (EntityTypeImpl) metamodel.entity(GalacticPosition.class);
            assertNotNull(entityLocation_);
            Type<?> locationIdType = entityLocation_.getIdType();
            assertNotNull(locationIdType);
            assertEquals(PersistenceType.EMBEDDABLE, locationIdType.getPersistenceType());
            assertEquals(EmbeddedPK.class, locationIdType.getJavaType());
            Attribute locationIdAttribute = entityLocation_.getAttribute("primaryKey");
            assertNotNull(locationIdAttribute);
            assertTrue(locationIdAttribute instanceof SingularAttributeImpl);

            /**
             *  Is the attribute collection-valued.
             *  @return boolean indicating whether attribute is
             *          collection-valued
             */
            //boolean isCollection();
            assertFalse(locationIdAttribute.isCollection());
            assertFalse(((AttributeImpl)locationIdAttribute).isPlural()); // non-spec.
            ManagedType locationIdAttributeManagedType = locationIdAttribute.getDeclaringType();
            assertEquals(entityLocation_, locationIdAttributeManagedType);
            ManagedTypeImpl locationIdAttributeManagedTypeImpl = ((SingularAttributeImpl)locationIdAttribute).getManagedTypeImpl();
            assertEquals(locationIdType.getJavaType(), ((SingularAttributeImpl)locationIdAttribute).getBindableJavaType());
            assertEquals(Bindable.BindableType.SINGULAR_ATTRIBUTE, ((SingularAttributeImpl)locationIdAttribute).getBindableType());
            assertEquals(locationIdType.getJavaType(), locationIdAttribute.getJavaType());
            Type embeddableType = ((SingularAttributeImpl)locationIdAttribute).getType();
            assertNotNull(embeddableType);
            assertNotSame(embeddableType, locationIdAttributeManagedType);
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    public void testAttribute_isCollection_true_Method() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);
            assertEquals(Type.PersistenceType.ENTITY, entityManufacturer_.getPersistenceType());
            Attribute anAttribute = entityManufacturer_.getAttribute("computers");
            assertNotNull(anAttribute);
            assertEquals(PersistentAttributeType.ONE_TO_MANY, anAttribute.getPersistentAttributeType());
            assertNotNull(anAttribute);
            assertTrue(((AttributeImpl)anAttribute).isPlural());
            assertTrue(anAttribute instanceof PluralAttribute);
            PluralAttribute aPluralAttribute = entityManufacturer_.getSet("computers");
            assertEquals(Computer.class, aPluralAttribute.getBindableJavaType());
            // 314906: javaType for collections is the collection type not the element type
            assertEquals(Set.class, aPluralAttribute.getJavaType());

            /**
             *  Is the attribute collection-valued.
             *  @return boolean indicating whether attribute is
             *          collection-valued
             */
            //boolean isCollection();
            assertTrue(anAttribute.isCollection());
            assertTrue(((AttributeImpl)anAttribute).isPlural()); // non-spec.
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    public void testBasicType() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);

            // This interface is empty - however we can test BasicTypeImpl INTERNAL functionality
            // Test lazy creation of random basic types
            TypeImpl aRandomType = ((MetamodelImpl)metamodel).getType(Integer.class);
            assertEquals(Type.PersistenceType.BASIC, aRandomType.getPersistenceType());
            BasicTypeImpl aRandomBasicType = (BasicTypeImpl) aRandomType;
            assertFalse(aRandomBasicType.isEntity());
            assertFalse(aRandomBasicType.isMappedSuperclass());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    public void testBindable_getBindableType_Method() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);

            // Actual Test Case
            /*public static enum BindableType {
            SINGULAR_ATTRIBUTE, PLURAL_ATTRIBUTE, ENTITY_TYPE}*/
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);

            /**
             *  Return the bindable type of the represented object.
             *  @return bindable type
             */
            //BindableType getBindableType();
            // EntityTypeImpl
            assertEquals(Bindable.BindableType.ENTITY_TYPE, entityManufacturer_.getBindableType());
            // SingularAttributeImpl
            SingularAttribute<Manufacturer, Boolean> manufacturer_booleanObject =
            entityManufacturer_.getDeclaredSingularAttribute("aBooleanObject", Boolean.class);
            assertNotNull(manufacturer_booleanObject);
            assertEquals(Bindable.BindableType.SINGULAR_ATTRIBUTE, manufacturer_booleanObject.getBindableType());
            // PluralAttributeImpl
            ListAttribute<Manufacturer, HardwareDesigner> manufacturer_hardwareDesignersList =
            entityManufacturer_.getDeclaredList("hardwareDesigners", HardwareDesigner.class);
            assertNotNull(manufacturer_hardwareDesignersList);
            assertEquals(Bindable.BindableType.PLURAL_ATTRIBUTE, manufacturer_hardwareDesignersList.getBindableType());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    public void testBindable_getBindableJavaType_Method() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);

            // Actual Test Case
            /*public static enum BindableType {
            SINGULAR_ATTRIBUTE, PLURAL_ATTRIBUTE, ENTITY_TYPE}*/
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);

            SingularAttribute<Manufacturer, Boolean> manufacturer_booleanObject =
            entityManufacturer_.getDeclaredSingularAttribute("aBooleanObject", Boolean.class);
            assertNotNull(manufacturer_booleanObject);
            ListAttribute<Manufacturer, HardwareDesigner> manufacturer_hardwareDesignersList =
            entityManufacturer_.getDeclaredList("hardwareDesigners", HardwareDesigner.class);
            assertNotNull(manufacturer_hardwareDesignersList);

            /**
             * Return the Java type of the represented object.
             * If the bindable type of the object is <code>PLURAL_ATTRIBUTE</code>,
             * the Java element type is returned. If the bindable type is
             * <code>SINGULAR_ATTRIBUTE</code> or <code>ENTITY_TYPE</code>,
             * the Java type of the
             * represented entity or attribute is returned.
             * @return Java type
             */
            //Class<T> getBindableJavaType();
            // EntityTypeImpl
            assertEquals(entityManufacturer_.getJavaType(), entityManufacturer_.getBindableJavaType());
            // SingularAttribute
            assertEquals(manufacturer_booleanObject.getJavaType(), manufacturer_booleanObject.getBindableJavaType());
            // PluralAttribute
            Type<HardwareDesigner> manufacturer_hardwareDesignersType = manufacturer_hardwareDesignersList.getElementType();
            assertNotNull(manufacturer_hardwareDesignersType);
            assertNotNull(manufacturer_hardwareDesignersType.getJavaType());
            assertEquals(manufacturer_hardwareDesignersType.getJavaType(), manufacturer_hardwareDesignersList.getBindableJavaType());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    public void testEmbeddableType() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);

            // The EmbeddableType interface has no methods - however we can test EmbeddableTypeImpl INTERNAL functionality
            Type<EmbeddedPK> aType_ = metamodel.managedType(EmbeddedPK.class);
            assertNotNull("The EmbeddableType EmbeddedPK should not be null", aType_);
            EmbeddableTypeImpl embeddableType_ = (EmbeddableTypeImpl) aType_;
            assertFalse("Expected EmbeddedPK.isEntity = false", embeddableType_.isEntity());
            assertFalse("Expected EmbeddedPK.isMappedSuperclass = false", embeddableType_.isMappedSuperclass());
            assertEquals(PersistenceType.EMBEDDABLE, embeddableType_.getPersistenceType());
            assertEquals(EmbeddedPK.class, embeddableType_.getJavaType());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    // 300626
    public void testNestedEmbeddableType() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);

            // Get the containing Entity
            Type<GalacticPosition> containingEntity_ = metamodel.managedType(GalacticPosition.class);
            assertNotNull("The containing Entity GalacticPosition should not be null", containingEntity_);
            // Get the Embeddable on the Entity
            Type<Observation> rootEmbeddable_ = metamodel.embeddable(Observation.class);
            assertNotNull("The contained embeddable Observation should not be null", rootEmbeddable_);
            EmbeddableTypeImpl rootEmbeddableType_ = (EmbeddableTypeImpl) rootEmbeddable_;
            assertFalse("Expected Observation.isEntity = false", rootEmbeddableType_.isEntity());
            assertFalse("Expected Observation.isMappedSuperclass = false", rootEmbeddableType_.isMappedSuperclass());
            assertEquals(PersistenceType.EMBEDDABLE, rootEmbeddable_.getPersistenceType());
            assertEquals(Observation.class, rootEmbeddable_.getJavaType());

            // Get the nested embeddable on the parent Embeddable
            Type<ObservationDetail> nestedEmbeddable_ = metamodel.embeddable(ObservationDetail.class);
            assertNotNull("The contained embeddable Observation should not be null", nestedEmbeddable_);
            EmbeddableTypeImpl nestedEmbeddableType_ = (EmbeddableTypeImpl) nestedEmbeddable_;
            assertFalse("Expected ObservationData.isEntity = false", nestedEmbeddableType_.isEntity());
            assertFalse("Expected Observation.isMappedSuperclass = false", nestedEmbeddableType_.isMappedSuperclass());
            assertEquals(PersistenceType.EMBEDDABLE, nestedEmbeddable_.getPersistenceType());
            assertEquals(ObservationDetail.class, nestedEmbeddable_.getJavaType());
            // verify that the nested embeddable is a member of the root embeddable
            SingularAttribute<Observation, ObservationDetail> nestedEmbeddableAttribute_ = rootEmbeddableType_.getSingularAttribute("detail", ObservationDetail.class);
            assertNotNull("The nested embeddable ObservationDetail should be a member of the root embeddable Observation",
                    nestedEmbeddableAttribute_);
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    public void testEntityType() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull(metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);
            EntityTypeImpl<HardwareDesigner> entityHardwareDesigner_ = (EntityTypeImpl)metamodel.entity(HardwareDesigner.class);
            assertNotNull(entityHardwareDesigner_);

            // Actual Test Case
            /**
             *  Return the entity name.
             *  @return entity name
             */
            //String getName();
            String entityNameWithNameAttribute = entityManufacturer_.getName();
            assertNotNull("EntityType.getName() should not be null", entityNameWithNameAttribute);
            // this should match the @Entity(name="ManuMetamodel")
            assertEquals("ManuMetamodel", entityNameWithNameAttribute);

            String entityNameWithoutAttribute = entityHardwareDesigner_.getName();
            assertNotNull("EntityType.getName() should not be null", entityNameWithoutAttribute);
            // this should match the @Entity(name="HardwareDesigner")
            assertEquals("HardwareDesigner", entityNameWithoutAttribute);

            // Normal use cases
            // Composite table FK's that include a MappedSuperclass
            // get an Attribute<Container, Type==String>
            Attribute nameAttribute = entityManufacturer_.getAttribute("name");
            assertTrue(null != nameAttribute);

            // get an Attribute<Container, Type==MappedSuperclass>
            Attribute employerAttribute = entityHardwareDesigner_.getAttribute("employer");
            assertTrue(null != employerAttribute);
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    public void testIdentifiableType_getId_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull(metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);
            EntityTypeImpl<GalacticPosition> entityLocation_ = (EntityTypeImpl) metamodel.entity(GalacticPosition.class);
            assertNotNull(entityLocation_);
            EntityTypeImpl<Computer> entityComputer_ = (EntityTypeImpl)metamodel.entity(Computer.class);
            assertNotNull(entityComputer_);

            // Actual Test Case
            /**
             *  Return the attribute that corresponds to the id attribute of
             *  the entity or mapped superclass.
             *  @param type  the type of the represented id attribute
             *  @return id attribute
             *  @throws IllegalArgumentException if id attribute of the given
             *          type is not present in the identifiable type or if
             *          the identifiable type has an id class
             */
            //<Y> SingularAttribute<? super X, Y> getId(Class<Y> type);
            EntityType<Manufacturer> aManufacturerType = metamodel.entity(Manufacturer.class);
            assertNotNull(aManufacturerType.getId(Integer.class));
            // declared and valid
            MappedSuperclassTypeImpl<Person> msPerson1_ = (MappedSuperclassTypeImpl)metamodel.managedType(Person.class);
            assertNotNull(msPerson1_.getId(Integer.class));
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    public void testIdentifiableType_getId_with_EmbeddedId_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull(metamodel);
            EntityType<FooBar> fooBarEntityType = metamodel.entity(FooBar.class);
            assertNotNull(fooBarEntityType);
            assertTrue(fooBarEntityType.hasSingleIdAttribute());

            // Actual Test Case
            /**
             *  Return the attribute that corresponds to the id attribute of
             *  the entity or mapped superclass.
             *  @param type  the type of the represented id attribute
             *  @return id attribute
             *  @throws IllegalArgumentException if id attribute of the given
             *          type is not present in the identifiable type or if
             *          the identifiable type has an id class
             */
            //<Y> SingularAttribute<? super X, Y> getId(Class<Y> type);

            SingularAttribute<? super FooBar, FooBarId> fooBarId = fooBarEntityType.getId(FooBarId.class);
            //FooBarId declared by @EmbeddedId
            assertNotNull(fooBarId);
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    public void testIdentifiableType_getVersion_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull(metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);
            EntityTypeImpl<GalacticPosition> entityLocation_ = (EntityTypeImpl) metamodel.entity(GalacticPosition.class);
            assertNotNull(entityLocation_);
            EntityTypeImpl<Computer> entityComputer_ = (EntityTypeImpl)metamodel.entity(Computer.class);
            assertNotNull(entityComputer_);

            // Actual Test Case
            /**
             *  Return the attribute that corresponds to the version
             *    attribute of the entity or mapped superclass.
             *  @param type  the type of the represented version attribute
             *  @return version attribute
             *  @throws IllegalArgumentException if version attribute of the
             *          given type is not present in the identifiable type
             */
            //<Y> SingularAttribute<? super X, Y> getVersion(Class<Y> type);
//              EntityType<Enclosure> anEnclosureType = metamodel.entity(Enclosure.class);
//              assertNotNull(anEnclosureType.getVersion(Integer.class));
            // declared and inherited

            // declared
            assertNotNull(entityManufacturer_.getVersion(int.class));
            // declared and valid
            // FUTURE : require MS version
            //assertNotNull(msPerson1_.getVersion(Integer.class)); - keep commented
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    // TODO: This is not testing anything yet.
    public void testIdentifiableType_getDeclaredId_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull(metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);
            EntityTypeImpl<GalacticPosition> entityLocation_ = (EntityTypeImpl) metamodel.entity(GalacticPosition.class);
            assertNotNull(entityLocation_);
            EntityTypeImpl<Computer> entityComputer_ = (EntityTypeImpl)metamodel.entity(Computer.class);
            assertNotNull(entityComputer_);

            // Actual Test Case
            /**
             *  Return the attribute that corresponds to the id attribute
             *  declared by the entity or mapped superclass.
             *  @param type  the type of the represented declared id attribute
             *  @return declared id attribute
             *  @throws IllegalArgumentException if id attribute of the given
             *          type is not declared in the identifiable type or if
             *          the identifiable type has an id class
             */
            //<Y> SingularAttribute<X, Y> getDeclaredId(Class<Y> type);
            // Not declared  - invalid
            // assertNotNull(aManufacturerType.getDeclaredId(Integer.class)); - keep commented
            // declared and valid

            //*********************************************/
            // FUTURE: Require a version on a MappedSuperclass
            //assertNotNull(msPerson1_.getDeclaredId(Integer.class));
        } catch (Exception e) {
            //e.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    public void testIdentifiableType_getDeclaredVersion_exists_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull(metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);

            // Actual Test Case
            /**
             *  Return the attribute that corresponds to the version
             *  attribute declared by the entity or mapped superclass.
             *  @param type  the type of the represented declared version
             *               attribute
             *  @return declared version attribute
             *  @throws IllegalArgumentException if version attribute of the
             *          type is not declared in the identifiable type
             */
            //<Y> SingularAttribute<X, Y> getDeclaredVersion(Class<Y> type);
            // FUTURE: need an undeclared subclass
            // Is declared
            SingularAttribute<Manufacturer,?> anAttribute = entityManufacturer_.getDeclaredVersion(int.class);
            assertNotNull(anAttribute);
            assertNotNull(anAttribute.getType());
            assertNotNull(anAttribute.getBindableType());
            assertNotNull(anAttribute.getBindableJavaType());
            assertNotNull(anAttribute.getDeclaringType());
            assertEquals(entityManufacturer_, anAttribute.getDeclaringType());
            assertFalse(anAttribute.isId());
            assertTrue(anAttribute.isVersion());
            assertEquals(PersistentAttributeType.BASIC, anAttribute.getPersistentAttributeType());
            assertTrue(anAttribute.isOptional());
            assertNotNull(anAttribute.getJavaType());
            assertFalse(anAttribute.isAssociation());
            assertFalse(anAttribute.isCollection());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    public void testIdentifiableType_getDeclaredVersion_exists_above_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull(metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);

            // Actual Test Case
            /**
             *  Return the attribute that corresponds to the version
             *  attribute declared by the entity or mapped superclass.
             *  @param type  the type of the represented declared version
             *               attribute
             *  @return declared version attribute
             *  @throws IllegalArgumentException if version attribute of the
             *          type is not declared in the identifiable type
             */
            //<Y> SingularAttribute<X, Y> getDeclaredVersion(Class<Y> type);
            // Does not exist
//            EntityType<Enclosure> anEnclosureType = metamodel.entity(Enclosure.class);
//            assertNotNull(anEnclosureType.getDeclaredVersion(Integer.class));
            // Is declared
            assertNotNull(entityManufacturer_.getDeclaredVersion(int.class));

            // FUTURE: need an undeclared subclass
            // Is declared for assertNotNull(msPerson1_.getDeclaredVersion(Integer.class));
        } catch (IllegalArgumentException iae) {
            //iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    // TODO: This is not testing anything different?
    public void testIdentifiableType_getDeclaredVersion_does_not_exist_at_all_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull(metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);

            // Actual Test Case
            /**
             *  Return the attribute that corresponds to the version
             *  attribute declared by the entity or mapped superclass.
             *  @param type  the type of the represented declared version
             *               attribute
             *  @return declared version attribute
             *  @throws IllegalArgumentException if version attribute of the
             *          type is not declared in the identifiable type
             */
            //<Y> SingularAttribute<X, Y> getDeclaredVersion(Class<Y> type);
            // Does not exist
//            EntityType<Enclosure> anEnclosureType = metamodel.entity(Enclosure.class);
//            assertNotNull(anEnclosureType.getDeclaredVersion(Integer.class));
            // Is declared
            assertNotNull(entityManufacturer_.getDeclaredVersion(int.class));

            // FUTURE: need an undeclared subclass
            // Is declared for assertNotNull(msPerson1_.getDeclaredVersion(Integer.class));
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    // TODO: This is not testing anything different?
    public void testIdentifiableType_getSupertype_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull(metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);
            EntityTypeImpl<GalacticPosition> entityLocation_ = (EntityTypeImpl) metamodel.entity(GalacticPosition.class);
            assertNotNull(entityLocation_);
            EntityTypeImpl<Computer> entityComputer_ = (EntityTypeImpl)metamodel.entity(Computer.class);
            assertNotNull(entityComputer_);

            /**
             *  Return the identifiable type that corresponds to the most
             *  specific mapped superclass or entity extended by the entity
             *  or mapped superclass.
             *  @return supertype of identifiable type or null if no such supertype
             */
            //IdentifiableType<? super X> getSupertype();

            // Test normal path
            expectedIAExceptionThrown = false;
            IdentifiableType<? super Manufacturer> superTypeManufacturer = null;
        try {
            superTypeManufacturer = entityManufacturer_.getSupertype();
        } catch (IllegalArgumentException iae) {
            // expecting no exception
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
            }
            assertFalse(expectedIAExceptionThrown);
            assertNotNull(superTypeManufacturer);
            /**
             * see
     metamodel    MetamodelImpl  (id=113)
        embeddables LinkedHashMap<K,V>  (id=251)
            size    0
        entities    LinkedHashMap<K,V>  (id=253)
            size    10
        managedTypes    LinkedHashMap<K,V>  (id=254)
            size    14
        mappedSuperclasses  HashSet<E>  (id=255)
            map HashMap<K,V>  (id=278)
            size    4
        types   LinkedHashMap<K,V>  (id=259)
            size    17
              */
            // Check for superclass using non-API code
            //assertEquals(metamodel.type("org.eclipse.persistence.testing.models.jpa.metamodel.Corporation"), superType);

            // Test error path (null return)
            expectedIAExceptionThrown = false;
            IdentifiableType<? super GalacticPosition> superTypeLocation = null;
        try {
            superTypeLocation = entityLocation_.getSupertype();
        } catch (IllegalArgumentException iae) {
            // expecting no exception
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
            }
            assertFalse(expectedIAExceptionThrown);
            assertNull(superTypeLocation);
        } catch (IllegalArgumentException iae) {
            //iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    public void testIdentifiableType_hasSingleIdAttribute_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull(metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);
            EntityTypeImpl<GalacticPosition> entityLocation_ = (EntityTypeImpl) metamodel.entity(GalacticPosition.class);
            assertNotNull(entityLocation_);
            EntityTypeImpl<Computer> entityComputer_ = (EntityTypeImpl)metamodel.entity(Computer.class);
            assertNotNull(entityComputer_);
            EntityTypeImpl<WithInner> withInner_ = (EntityTypeImpl)metamodel.entity(WithInner.class);
            assertNotNull(withInner_);

            /**
             *  Whether or not the identifiable type has an id attribute.
             *  Returns true for a simple id or embedded id; returns false
             *  for an idclass.
             *  @return boolean indicating whether or not the identifiable
             *           type has a single id attribute
             */
            // We do not need to test Embeddable to Basic as they do not implement IdentifiableType
            //boolean hasSingleIdAttribute();
            // verify false for "no" type of Id attribute
            // @Id - test normal path
            expectedIAExceptionThrown = false;
            boolean hasSingleIdAttribute = false;
        try {
            EntityType<Manufacturer> aType = metamodel.entity(Manufacturer.class);
            hasSingleIdAttribute = aType.hasSingleIdAttribute();
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
            }
            assertFalse(expectedIAExceptionThrown);
            assertTrue(hasSingleIdAttribute);

            // @EmbeddedId
            expectedIAExceptionThrown = false;
            hasSingleIdAttribute = false;
        try {
            EntityType<GalacticPosition> aType = metamodel.entity(GalacticPosition.class);
            hasSingleIdAttribute = aType.hasSingleIdAttribute();
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
            }
            assertFalse(expectedIAExceptionThrown);
            assertTrue(hasSingleIdAttribute);

            // @IdClass - test exception path
            expectedIAExceptionThrown = false;
            hasSingleIdAttribute = true;
        try {
            EntityType<Enclosure> aType = metamodel.entity(Enclosure.class);
            hasSingleIdAttribute = aType.hasSingleIdAttribute();
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
            }
            assertFalse(expectedIAExceptionThrown);
            assertFalse(hasSingleIdAttribute);

            // @IdClass - inner
            expectedIAExceptionThrown = false;
            hasSingleIdAttribute = false;
        try {
            EntityType<WithInner> aType = metamodel.entity(WithInner.class);
            hasSingleIdAttribute = aType.hasSingleIdAttribute();
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
            }
            assertFalse(expectedIAExceptionThrown);
            assertFalse(hasSingleIdAttribute);
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    public void testIdentifiableType_hasVersionAttribute_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull(metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);

            // Actual Test Case
            /**
             *  Whether or not the identifiable type has a version attribute.
             *  @return boolean indicating whether or not the identifiable
             *           type has a version attribute
             */
            //boolean hasVersionAttribute();
            EntityType<Enclosure> anEnclosureType = metamodel.entity(Enclosure.class);
            assertFalse(anEnclosureType.hasVersionAttribute());
            assertTrue(entityManufacturer_.hasVersionAttribute());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    public void testIdentifiableType_getIdClassAttributes_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull(metamodel);
            // Actual Test Case
            /**
             *   Return the attributes corresponding to the id class of the
             *   identifiable type.
             *   @return id attributes
             *   @throws IllegalArgumentException if the identifiable type
             *           does not have an id class
             */
             //java.util.Set<SingularAttribute<? super X, ?>> getIdClassAttributes();
            // @IdClass - test normal path
            expectedIAExceptionThrown = false;
            boolean hasSingleIdAttribute = true;
            Set<SingularAttribute<? super Enclosure, ?>> idClassAttributes = null;
            EntityType<Enclosure> aType = metamodel.entity(Enclosure.class);
            hasSingleIdAttribute = aType.hasSingleIdAttribute();
            // We verify that an @IdClass exists - no single @Id or @EmbeddedId exists
            assertFalse(hasSingleIdAttribute);
            idClassAttributes = aType.getIdClassAttributes();
            assertNotNull(idClassAttributes);
            assertEquals(4, idClassAttributes.size());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    public void testIdentifiableType_getIdClassAttributesAcrossMappedSuperclassChain_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull(metamodel);

            // Actual Test Case
            /**
             *   Return the attributes corresponding to the id class of the
             *   identifiable type.
             *   @return id attributes
             *   @throws IllegalArgumentException if the identifiable type
             *           does not have an id class
             */
             //java.util.Set<SingularAttribute<? super X, ?>> getIdClassAttributes();
            // @IdClass - test normal path
            expectedIAExceptionThrown = false;
            boolean hasSingleIdAttribute = true;
            // 0 id attributes here
            Set<SingularAttribute<? super MS_MS_Entity_Leaf, ?>> idClassAttributesLeaf = null;
            IdentifiableType<MS_MS_Entity_Leaf> aTypeLeaf = metamodel.entity(MS_MS_Entity_Leaf.class);
            // 1 id attribute here
            Set<SingularAttribute<? super MS_MS_Entity_Center, ?>> idClassAttributesCenter = null;
            MappedSuperclassType<MS_MS_Entity_Center> aTypeCenter = (MappedSuperclassType)metamodel.managedType(MS_MS_Entity_Center.class);
            // 3 id attributes here
            Set<SingularAttribute<? super MS_MS_Entity_Root, ?>> idClassAttributesRoot = null;
            MappedSuperclassType<MS_MS_Entity_Root> aTypeRoot = (MappedSuperclassType)metamodel.managedType(MS_MS_Entity_Root.class);

            hasSingleIdAttribute = aTypeLeaf.hasSingleIdAttribute();
            // We verify that an an @IdClass exists above
            assertFalse(hasSingleIdAttribute); // This tests the IdentifiableType part of the transaction for DI 78
            hasSingleIdAttribute = aTypeCenter.hasSingleIdAttribute();
            // We verify that an one part of an @IdClass exists
            assertTrue(hasSingleIdAttribute); // This tests the IdentifiableType part of the transaction for DI 78
            hasSingleIdAttribute = aTypeRoot.hasSingleIdAttribute();
            // We verify that an @IdClass exists - no single @Id or @EmbeddedId exists
            assertFalse(hasSingleIdAttribute); // This tests the IdentifiableType part of the transaction for DI 78
            //idClassAttributesLeaf = aTypeLeaf.getIdClassAttributes(); // expected IAE - leave commented
            idClassAttributesCenter = aTypeCenter.getIdClassAttributes();
            assertNotNull(idClassAttributesCenter);
            assertEquals(1, idClassAttributesCenter.size());
            // The following call is not valid because the IdClass attribute is defined one level below
        try {
            idClassAttributesRoot = aTypeRoot.getIdClassAttributes();
        } catch (IllegalArgumentException iae) {
            expectedIAExceptionThrown = true;
            }
            assertTrue(expectedIAExceptionThrown);
            expectedIAExceptionThrown = false;
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    public void testIdentifiableType_getIdType_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull(metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);
            EntityTypeImpl<GalacticPosition> entityLocation_ = (EntityTypeImpl) metamodel.entity(GalacticPosition.class);
            assertNotNull(entityLocation_);
            EntityTypeImpl<Computer> entityComputer_ = (EntityTypeImpl)metamodel.entity(Computer.class);
            assertNotNull(entityComputer_);

            // Actual Test Case
            /**
             *  Return the type that represents the type of the id.
             *  @return type of id
             */
            //Type<?> getIdType();

            // Test EntityType

            // Test normal path for an [Embeddable] type via @EmbeddedId
            expectedIAExceptionThrown = false;
            Type<?> locationIdType = null;
        try {
            locationIdType = entityLocation_.getIdType();
        } catch (IllegalArgumentException iae) {
            // expecting no exception
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
            }
            assertFalse(expectedIAExceptionThrown);
            assertNotNull(locationIdType);
            assertEquals(PersistenceType.EMBEDDABLE, locationIdType.getPersistenceType());
            assertEquals(EmbeddedPK.class, locationIdType.getJavaType());

            // check that the elementType and the owningType (managedType) are set correctly
            // See issue 50 where some mapping types were not setting the elementType correctly (this includes aggregate types like Embeddable)
            // http://wiki.eclipse.org/EclipseLink/Development/JPA_2.0/metamodel_api#DI_50:_20090727:_Handle_all_mapping_types_in_the_SingularAttribute_constructor
            // Get the ManagedType and check this SingularAttribute PK
            Attribute locationIdAttribute = entityLocation_.getAttribute("primaryKey");
            assertNotNull(locationIdAttribute);
            assertTrue(locationIdAttribute instanceof SingularAttributeImpl);
            assertFalse(locationIdAttribute.isCollection());
            assertFalse(((AttributeImpl)locationIdAttribute).isPlural()); // non-spec.
            ManagedType locationIdAttributeManagedType = locationIdAttribute.getDeclaringType();
            assertEquals(entityLocation_, locationIdAttributeManagedType);
            ManagedTypeImpl locationIdAttributeManagedTypeImpl = ((SingularAttributeImpl)locationIdAttribute).getManagedTypeImpl();
            assertEquals(locationIdType.getJavaType(), ((SingularAttributeImpl)locationIdAttribute).getBindableJavaType());
            assertEquals(Bindable.BindableType.SINGULAR_ATTRIBUTE, ((SingularAttributeImpl)locationIdAttribute).getBindableType());
            assertEquals(locationIdType.getJavaType(), locationIdAttribute.getJavaType());
            Type embeddableType = ((SingularAttributeImpl)locationIdAttribute).getType();
            assertNotNull(embeddableType);
            assertNotSame(embeddableType, locationIdAttributeManagedType);

            // Test normal path for a [Basic] type
            expectedIAExceptionThrown = false;
            Type<?> computerIdType = null;
            try {
                computerIdType = entityComputer_.getIdType();
            } catch (IllegalArgumentException iae) {
                // expecting no exception
                iae.printStackTrace();
                expectedIAExceptionThrown = true;
            }
            assertFalse(expectedIAExceptionThrown);
            assertNotNull(computerIdType);
            assertEquals(PersistenceType.BASIC, computerIdType.getPersistenceType());
            assertEquals(Integer.class, computerIdType.getJavaType());

            // Test MappedSuperclassType
            // Test normal path for a [Basic] type
            expectedIAExceptionThrown = false;
            Type<?> personIdType = null;
            MappedSuperclassTypeImpl<Person> msPerson_ = (MappedSuperclassTypeImpl)metamodel.managedType(Person.class);
            assertNotNull(msPerson_);
            MappedSuperclassTypeImpl<Corporation> msCorporation_ = (MappedSuperclassTypeImpl)metamodel.managedType(Corporation.class);
            assertNotNull(msCorporation_);

            // Verify all types (entities, embeddables, mappedsuperclasses and basic)
            // get all 21 types (a non spec function - for testing introspection)
            Map<String, TypeImpl<?>> typesMap = ((MetamodelImpl)metamodel).getTypes();
            // verify each one
            assertNotNull(typesMap);
            ((MetamodelImpl)metamodel).printAllTypes();
            // Note: Since BasicTypes are lazy - loaded into the metamodel-types Map - this test must preceed any test that verifies all BasicType objects like "testIdentifiableType_getIdType_Method"
            // You will get a lower number here - if only this single test is run via the Testing Browser
            assertEquals(METAMODEL_ALL_TYPES, typesMap.size());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    // TODO: This is not testing anything different?
    public void testListAttribute() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull(metamodel);

            // Actual Test Case

        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    public void testManagedType_getAttributes_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);
            MappedSuperclassTypeImpl<Person> msPerson_ = (MappedSuperclassTypeImpl)metamodel.managedType(Person.class);
            assertNotNull(msPerson_);
            MappedSuperclassTypeImpl<Corporation> msCorporation_ = (MappedSuperclassTypeImpl)metamodel.managedType(Corporation.class);
            assertNotNull(msCorporation_);
            EntityTypeImpl<GalacticPosition> entityLocation_ =(EntityTypeImpl) metamodel.entity(GalacticPosition.class);
            assertNotNull(entityLocation_);
            EntityTypeImpl<Computer> entityComputer_ = (EntityTypeImpl)metamodel.entity(Computer.class);
            assertNotNull(entityComputer_);
            EntityTypeImpl<HardwareDesigner> entityHardwareDesigner_ = (EntityTypeImpl)metamodel.entity(HardwareDesigner.class);
            assertNotNull(entityHardwareDesigner_);

            // Actual Test Case
            /**
             * The following variant test cases are common to all functions
             * 1) get*Attribute(name) = null (missing) --> IAE
             * 2) get*Attribute(name, type) = null (missing, type=irrelevant) --> IAE
             * 3) get*Attribute(name, type) = exists but type != returned type --> IAE
             */

            /**
             *  Return the attributes of the managed type.
             */
             //java.util.Set<Attribute<? super X, ?>> getAttributes();
            Set<Attribute<? super Manufacturer, ?>> attributeSet = entityManufacturer_.getAttributes();
            assertNotNull(attributeSet);
            // We should see 30 attributes (3 List, 3 Singular, 17 basic (java.lang, java.math) for Manufacturer (computers, hardwareDesigners, id(from the mappedSuperclass),
            // version, name(from the mappedSuperclass) and corporateComputers from the Corporation mappedSuperclass)
            assertEquals(METAMODEL_MANUFACTURER_DECLARED_TYPES + 6, attributeSet.size());
            // for each managed entity we will see 2 entries (one for the Id, one for the Version)
            assertTrue(attributeSet.contains(entityManufacturer_.getAttribute("id"))); //
            assertTrue(attributeSet.contains(entityManufacturer_.getAttribute("version"))); //
            assertTrue(attributeSet.contains(entityManufacturer_.getAttribute("name"))); //
            assertTrue(attributeSet.contains(entityManufacturer_.getAttribute("computers"))); //
            assertTrue(attributeSet.contains(entityManufacturer_.getAttribute("hardwareDesigners"))); //
            assertTrue(attributeSet.contains(entityManufacturer_.getAttribute("corporateComputers"))); //
            assertTrue(attributeSet.contains(entityManufacturer_.getAttribute("hardwareDesignersMap"))); //
            assertTrue(attributeSet.contains(entityManufacturer_.getAttribute("hardwareDesignersMapUC1a"))); //
            assertTrue(attributeSet.contains(entityManufacturer_.getAttribute("hardwareDesignersMapUC2"))); //
            assertTrue(attributeSet.contains(entityManufacturer_.getAttribute("hardwareDesignersMapUC4"))); //
            assertTrue(attributeSet.contains(entityManufacturer_.getAttribute("hardwareDesignersMapUC7"))); //
            assertTrue(attributeSet.contains(entityManufacturer_.getAttribute("hardwareDesignersMapUC8"))); //
            // ManyToMany Collection Attribute from Person MappedSuperclass
            assertTrue(attributeSet.contains(entityManufacturer_.getCollection("historicalEmps"))); //
            assertTrue(entityManufacturer_.getCollection("historicalEmps").isCollection()); //
            // Basic java.lang and java.math primitive and primitive object types
        //private Object anObject; - invalid
            //assertTrue(attributeSet.contains(entityManufacturer.getAttribute("anObject"))); //
            //assertNotNull(entityManufacturer.getAttribute("anObject"));
            //assertTrue(entityManufacturer.getAttribute("anObject").getPersistentAttributeType().equals(PersistentAttributeType.BASIC));
            //assertEquals(Object.class, entityManufacturer.getAttribute("anObject").getJavaType());
        //private Boolean aBooleanObject;
            assertTrue(attributeSet.contains(entityManufacturer_.getAttribute("aBooleanObject"))); //
            assertNotNull(entityManufacturer_.getAttribute("aBooleanObject"));
            assertTrue(entityManufacturer_.getAttribute("aBooleanObject").getPersistentAttributeType().equals(PersistentAttributeType.BASIC));
            assertEquals(Boolean.class, entityManufacturer_.getAttribute("aBooleanObject").getJavaType());
        //private Byte aByteObject;
            assertTrue(attributeSet.contains(entityManufacturer_.getAttribute("aByteObject"))); //
            assertNotNull(entityManufacturer_.getAttribute("aByteObject"));
            assertTrue(entityManufacturer_.getAttribute("aByteObject").getPersistentAttributeType().equals(PersistentAttributeType.BASIC));
            assertEquals(Byte.class, entityManufacturer_.getAttribute("aByteObject").getJavaType());
        //private Short aShortObject;
            assertTrue(attributeSet.contains(entityManufacturer_.getAttribute("aShortObject"))); //
            assertNotNull(entityManufacturer_.getAttribute("aShortObject"));
            assertTrue(entityManufacturer_.getAttribute("aShortObject").getPersistentAttributeType().equals(PersistentAttributeType.BASIC));
            assertEquals(Short.class, entityManufacturer_.getAttribute("aShortObject").getJavaType());
        //private Integer anIntegerObject;
            assertTrue(attributeSet.contains(entityManufacturer_.getAttribute("anIntegerObject"))); //
            assertNotNull(entityManufacturer_.getAttribute("anIntegerObject"));
            assertTrue(entityManufacturer_.getAttribute("anIntegerObject").getPersistentAttributeType().equals(PersistentAttributeType.BASIC));
            assertEquals(Integer.class, entityManufacturer_.getAttribute("anIntegerObject").getJavaType());
        //private Long aLongObject;
            assertTrue(attributeSet.contains(entityManufacturer_.getAttribute("aLongObject"))); //
            assertNotNull(entityManufacturer_.getAttribute("aLongObject"));
            assertTrue(entityManufacturer_.getAttribute("aLongObject").getPersistentAttributeType().equals(PersistentAttributeType.BASIC));
            assertEquals(Long.class, entityManufacturer_.getAttribute("aLongObject").getJavaType());
        //private BigInteger aBigIntegerObject;
            assertTrue(attributeSet.contains(entityManufacturer_.getAttribute("aBigIntegerObject"))); //
            assertNotNull(entityManufacturer_.getAttribute("aBigIntegerObject"));
            assertTrue(entityManufacturer_.getAttribute("aBigIntegerObject").getPersistentAttributeType().equals(PersistentAttributeType.BASIC));
            assertEquals(BigInteger.class, entityManufacturer_.getAttribute("aBigIntegerObject").getJavaType());
        //private Float aFloatObject;
            assertTrue(attributeSet.contains(entityManufacturer_.getAttribute("aFloatObject"))); //
            assertNotNull(entityManufacturer_.getAttribute("aFloatObject"));
            assertTrue(entityManufacturer_.getAttribute("aFloatObject").getPersistentAttributeType().equals(PersistentAttributeType.BASIC));
            assertEquals(Float.class, entityManufacturer_.getAttribute("aFloatObject").getJavaType());
        //private Double aDoubleObject;
            assertTrue(attributeSet.contains(entityManufacturer_.getAttribute("aDoubleObject"))); //
            assertNotNull(entityManufacturer_.getAttribute("aDoubleObject"));
            assertTrue(entityManufacturer_.getAttribute("aDoubleObject").getPersistentAttributeType().equals(PersistentAttributeType.BASIC));
            assertEquals(Double.class, entityManufacturer_.getAttribute("aDoubleObject").getJavaType());
        //private Character aCharacterObject;
            assertTrue(attributeSet.contains(entityManufacturer_.getAttribute("aCharacterObject"))); //
            assertNotNull(entityManufacturer_.getAttribute("aCharacterObject"));
            assertTrue(entityManufacturer_.getAttribute("aCharacterObject").getPersistentAttributeType().equals(PersistentAttributeType.BASIC));
            assertEquals(Character.class, entityManufacturer_.getAttribute("aCharacterObject").getJavaType());
        //private Enum anEnum;
            // FUTURE: the following 4 lines are not implemented yet
            //assertTrue(attributeSet.contains(entityManufacturer.getAttribute("anEnum"))); //
            //assertNotNull(entityManufacturer.getAttribute("anEnum"));
            //assertTrue(entityManufacturer.getAttribute("anEnum").getPersistentAttributeType().equals(PersistentAttributeType.BASIC));
            //assertEquals(Enum.class, entityManufacturer.getAttribute("anEnum").getJavaType());
        //private boolean aBoolean;
            assertTrue(attributeSet.contains(entityManufacturer_.getAttribute("aBoolean"))); //
            assertNotNull(entityManufacturer_.getAttribute("aBoolean"));
            assertTrue(entityManufacturer_.getAttribute("aBoolean").getPersistentAttributeType().equals(PersistentAttributeType.BASIC));
            assertEquals(boolean.class, entityManufacturer_.getAttribute("aBoolean").getJavaType());
        //private byte aByte;
            assertTrue(attributeSet.contains(entityManufacturer_.getAttribute("aByte"))); //
            assertNotNull(entityManufacturer_.getAttribute("aByte"));
            assertTrue(entityManufacturer_.getAttribute("aByte").getPersistentAttributeType().equals(PersistentAttributeType.BASIC));
            assertEquals(byte.class, entityManufacturer_.getAttribute("aByte").getJavaType());
        //private short aShort;
            assertTrue(attributeSet.contains(entityManufacturer_.getAttribute("aShort"))); //
            assertNotNull(entityManufacturer_.getAttribute("aShort"));
            assertTrue(entityManufacturer_.getAttribute("aShort").getPersistentAttributeType().equals(PersistentAttributeType.BASIC));
            assertEquals(short.class, entityManufacturer_.getAttribute("aShort").getJavaType());
        //private int anInt;
            assertTrue(attributeSet.contains(entityManufacturer_.getAttribute("anInt"))); //
            assertNotNull(entityManufacturer_.getAttribute("anInt"));
            assertTrue(entityManufacturer_.getAttribute("anInt").getPersistentAttributeType().equals(PersistentAttributeType.BASIC));
            assertEquals(int.class, entityManufacturer_.getAttribute("anInt").getJavaType());
        //private long aLong;
            assertTrue(attributeSet.contains(entityManufacturer_.getAttribute("aLong"))); //
            assertNotNull(entityManufacturer_.getAttribute("aLong"));
            assertTrue(entityManufacturer_.getAttribute("aLong").getPersistentAttributeType().equals(PersistentAttributeType.BASIC));
            assertEquals(long.class, entityManufacturer_.getAttribute("aLong").getJavaType());
        //private float aFloat;
            assertTrue(attributeSet.contains(entityManufacturer_.getAttribute("aFloat"))); //
            assertNotNull(entityManufacturer_.getAttribute("aFloat"));
            assertTrue(entityManufacturer_.getAttribute("aFloat").getPersistentAttributeType().equals(PersistentAttributeType.BASIC));
            assertEquals(float.class, entityManufacturer_.getAttribute("aFloat").getJavaType());
        //private double aDouble;
            assertTrue(attributeSet.contains(entityManufacturer_.getAttribute("aDouble"))); //
            assertNotNull(entityManufacturer_.getAttribute("aDouble"));
            assertTrue(entityManufacturer_.getAttribute("aDouble").getPersistentAttributeType().equals(PersistentAttributeType.BASIC));
            assertEquals(double.class, entityManufacturer_.getAttribute("aDouble").getJavaType());
        //private char aChar;
            assertTrue(attributeSet.contains(entityManufacturer_.getAttribute("aChar"))); //
            assertNotNull(entityManufacturer_.getAttribute("aChar"));
            assertTrue(entityManufacturer_.getAttribute("aChar").getPersistentAttributeType().equals(PersistentAttributeType.BASIC));
            assertEquals(char.class, entityManufacturer_.getAttribute("aChar").getJavaType());

            /**
             *  Return the attributes declared by the managed type.
             *  Testing for Design Issue 52:
             *  http://wiki.eclipse.org/EclipseLink/Development/JPA_2.0/metamodel_api#DI:52_Refactor:_20090817
             */
             //java.util.Set<Attribute<X, ?>> getDeclaredAttributes();
            expectedIAExceptionThrown = false;
        try {
            /**
             * Hierarchy:
             *   Person : MappedSuperclass
             *     +
             *     +- id : Integer
             *     +- name : String
             *     +- historicalEmps : Manufacturer
             *
             *     Corporation : MappedSuperclass extends Person
             *       +
             *       +- corporateComputers : Collection
             *
             *       Manufacturer : Entity extends Corporation
             *         +
             *         +- computers : Set
             *         +- hardwareDesigners : List
             *         +- hardwareDesignersMap : Map
             *         +- version : int
             */
            Set<Attribute<Manufacturer, ?>> declaredAttributesSet = entityManufacturer_.getDeclaredAttributes();
            assertNotNull(declaredAttributesSet);
            // We should see 8+17 declared out of 12 attributes for Manufacturer
            assertEquals(METAMODEL_MANUFACTURER_DECLARED_TYPES + 1, declaredAttributesSet.size());
            // Id is declared 2 levels above
            assertFalse(declaredAttributesSet.contains(entityManufacturer_.getAttribute("id"))); //
            // name is declared 2 levels above
            assertFalse(declaredAttributesSet.contains(entityManufacturer_.getAttribute("name"))); //
            // corporateComputers is declared 1 level above
            assertFalse(declaredAttributesSet.contains(entityManufacturer_.getAttribute("corporateComputers"))); //
            // version is declared at this level
            assertTrue(declaredAttributesSet.contains(entityManufacturer_.getAttribute("version"))); //
            // computers is declared at this level
            assertTrue(declaredAttributesSet.contains(entityManufacturer_.getAttribute("computers"))); //
            // hardwareDesigners is declared at this level
            assertTrue(declaredAttributesSet.contains(entityManufacturer_.getAttribute("hardwareDesigners"))); //
            // hardwareDesignersMap is declared at this level
            assertTrue(declaredAttributesSet.contains(entityManufacturer_.getAttribute("hardwareDesignersMap"))); //
            assertTrue(declaredAttributesSet.contains(entityManufacturer_.getAttribute("hardwareDesignersMapUC1a"))); //
            assertTrue(declaredAttributesSet.contains(entityManufacturer_.getAttribute("hardwareDesignersMapUC2"))); //
            assertTrue(declaredAttributesSet.contains(entityManufacturer_.getAttribute("hardwareDesignersMapUC4"))); //
            assertTrue(declaredAttributesSet.contains(entityManufacturer_.getAttribute("hardwareDesignersMapUC7"))); //
            assertTrue(declaredAttributesSet.contains(entityManufacturer_.getAttribute("hardwareDesignersMapUC8"))); //
            // historicalEmps is declared 2 levels above
            assertFalse(declaredAttributesSet.contains(entityManufacturer_.getAttribute("historicalEmps"))); //

            Set<Attribute<Corporation, ?>> declaredAttributesSetForCorporation = msCorporation_.getDeclaredAttributes();
            assertNotNull(declaredAttributesSetForCorporation);
            // We should see 2 declared out of 5 attributes for Computer
            assertEquals(2, declaredAttributesSetForCorporation.size());
            // Id is declared 1 level above
            //assertFalse(declaredAttributesSetForCorporation.contains(msCorporation.getAttribute("id"))); //
            // name is declared 1 level above but is not visible in a ms-->ms hierarchy
            //assertFalse(declaredAttributesSetForCorporation.contains(msCorporation.getAttribute("name"))); //
            // corporateComputers is declared at this level
            // Note: internally EclipseLink treats a ONE_TO_MANY as a MANY_TO_MANY for the case of a unidirectional mapping on a MappedSuperclass
            assertTrue(declaredAttributesSetForCorporation.contains(msCorporation_.getAttribute("corporateComputers"))); //
            // historicalEmps is declared 1 level above but is not visible in a ms-->ms hierarchy
            //assertFalse(declaredAttributesSetForCorporation.contains(msCorporation.getAttribute("historicalEmps"))); //

            Set<Attribute<Person, ?>> declaredAttributesSetForPerson = msPerson_.getDeclaredAttributes();
            assertNotNull(declaredAttributesSetForPerson);
            // We should see 3 declared out of 20 attributes for Person
            assertEquals(3, declaredAttributesSetForPerson.size());
            // Id is declared at this level
            assertTrue(declaredAttributesSetForPerson.contains(msPerson_.getAttribute("id"))); //
            // name is declared at this level
            assertTrue(declaredAttributesSetForPerson.contains(msPerson_.getAttribute("name"))); //
            // historicalEmps is declared at this level
            assertTrue(declaredAttributesSetForPerson.contains(msPerson_.getAttribute("historicalEmps"))); //

        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
            }
            assertFalse(expectedIAExceptionThrown);

            // Test Entity-->Entity hierarchy
            /**
             *  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
             */
            //<Y> SingularAttribute<? super X, Y> getSingularAttribute(String name, Class<Y> type);
            // Test normal path
            expectedIAExceptionThrown = false;
            SingularAttribute<? super Manufacturer, Double> aManufacturer_DoubleAttribute = null;
        try {
            aManufacturer_DoubleAttribute = entityManufacturer_.getSingularAttribute("aDoubleObject", Double.class);
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
            }
            assertFalse(expectedIAExceptionThrown);
            assertNotNull(aManufacturer_DoubleAttribute);

            expectedIAExceptionThrown = false;
            SingularAttribute<? super Manufacturer, ?> aManufacturer_doubleAttribute = null;
            // Test autoboxed rules relax throwing an IAE
        try {
            aManufacturer_doubleAttribute = entityManufacturer_.getSingularAttribute("aDoubleObject", double.class);
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
            }
            assertFalse(expectedIAExceptionThrown);
            assertNotNull(aManufacturer_doubleAttribute);

            // Test IAE handling on wrong type
            expectedIAExceptionThrown = false;
            SingularAttribute<? super Manufacturer, ?> aManufacturer_wrong_intAttribute = null;
            // Test autoboxed rules relax throwing an IAE
        try {
            aManufacturer_wrong_intAttribute = entityManufacturer_.getSingularAttribute("aDoubleObject", int.class);
        } catch (IllegalArgumentException iae) {
            // expecting
            expectedIAExceptionThrown = true;
            }
            assertTrue("Expected thrown IllegalArgumentException", expectedIAExceptionThrown);
            assertNull(aManufacturer_wrong_intAttribute);

            // Test IAE handling on wrong type
            expectedIAExceptionThrown = false;
            SingularAttribute<? super Manufacturer, ?> aManufacturer_wrong_IntegerAttribute = null;
            // Test autoboxed rules relax throwing an IAE
        try {
            aManufacturer_wrong_IntegerAttribute = entityManufacturer_.getSingularAttribute("aDoubleObject", Integer.class);
        } catch (IllegalArgumentException iae) {
            // expecting
            expectedIAExceptionThrown = true;
            }
            assertTrue("Expected thrown IllegalArgumentException", expectedIAExceptionThrown);
            assertNull(aManufacturer_wrong_IntegerAttribute);

            /**
             *  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
             */
            //<Y> SingularAttribute<X, Y> getDeclaredSingularAttribute(String name, Class<Y> type);
            // Test normal path
            expectedIAExceptionThrown = false;
            SingularAttribute<? super Manufacturer, Double> aDeclaredManufacturer_DoubleAttribute = null;
        try {
            aDeclaredManufacturer_DoubleAttribute = entityManufacturer_.getDeclaredSingularAttribute("aDoubleObject", Double.class);
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
            }
            assertFalse(expectedIAExceptionThrown);
            assertNotNull(aDeclaredManufacturer_DoubleAttribute);

            expectedIAExceptionThrown = false;
            SingularAttribute<? super Manufacturer, ?> aDeclaredManufacturer_doubleAttribute = null;
            // Test autoboxed rules relax throwing an IAE
        try {
            aDeclaredManufacturer_doubleAttribute = entityManufacturer_.getDeclaredSingularAttribute("aDoubleObject", double.class);
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
            }
            assertFalse(expectedIAExceptionThrown);
            assertNotNull(aDeclaredManufacturer_doubleAttribute);

            // Test IAE handling on wrong type
            expectedIAExceptionThrown = false;
            SingularAttribute<? super Manufacturer, ?> aDeclaredManufacturer_wrong_intAttribute = null;
            // Test autoboxed rules relax throwing an IAE
        try {
            aDeclaredManufacturer_wrong_intAttribute = entityManufacturer_.getDeclaredSingularAttribute("aDoubleObject", int.class);
        } catch (IllegalArgumentException iae) {
            // expecting
            expectedIAExceptionThrown = true;
            }
            assertTrue("Expected thrown IllegalArgumentException", expectedIAExceptionThrown);
            assertNull(aDeclaredManufacturer_wrong_intAttribute);

            // Test IAE handling on wrong type
            expectedIAExceptionThrown = false;
            SingularAttribute<? super Manufacturer, ?> aDeclaredManufacturer_wrong_IntegerAttribute = null;
            // Test autoboxed rules relax throwing an IAE
        try {
            aDeclaredManufacturer_wrong_IntegerAttribute = entityManufacturer_.getDeclaredSingularAttribute("aDoubleObject", Integer.class);
        } catch (IllegalArgumentException iae) {
            // expecting
            expectedIAExceptionThrown = true;
            }
            assertTrue("Expected thrown IllegalArgumentException", expectedIAExceptionThrown);
            assertNull(aDeclaredManufacturer_wrong_IntegerAttribute);

            // Test wrong hierarchy IAE failures


            /**
             *  Return the single-valued attributes of the managed type.
             *  @return single-valued attributes
             */
            //java.util.Set<SingularAttribute<? super X, ?>> getSingularAttributes();
            Set<SingularAttribute<? super Manufacturer, ?>> singularAttributeSet = entityManufacturer_.getSingularAttributes();
            assertNotNull(singularAttributeSet);
            // We should see 4+18 singular attributes for Manufacturer (id(from the mappedSuperclass), version, name(from the mappedSuperclass))
            assertEquals(METAMODEL_MANUFACTURER_DECLARED_TYPES - 6, singularAttributeSet.size());
            // for each managed entity we will see 2 entries (one for the Id, one for the Version)
            assertTrue(singularAttributeSet.contains(entityManufacturer_.getAttribute("id"))); //
            assertTrue(singularAttributeSet.contains(entityManufacturer_.getAttribute("version"))); //
            assertTrue(singularAttributeSet.contains(entityManufacturer_.getAttribute("name"))); //

            /**
             *  Return the single-valued attributes declared by the managed
             *  type.
             *  @return declared single-valued attributes
             */
            //java.util.Set<SingularAttribute<X, ?>> getDeclaredSingularAttributes();

            /**
             *  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
             */
            //<E> CollectionAttribute<? super X, E> getCollection(String name, Class<E> elementType);

            /**
             *  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
             */
            //<E> SetAttribute<? super X, E> getSet(String name, Class<E> elementType);

            /**
             *  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
             */
            //<E> ListAttribute<? super X, E> getList(String name, Class<E> elementType);


            /**
             *  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
             */
            //<E> CollectionAttribute<X, E> getDeclaredCollection(String name, Class<E> elementType);
            expectedIAExceptionThrown = false;
        try {
            //<E> ListAttribute<X, E> getDeclaredList(String name, Class<E> elementType);
            // UC1 - the attribute does not exist on the managedType (regardless of whether it is on any superType)
            CollectionAttribute<Manufacturer, GalacticPosition> anAttribute =
                entityManufacturer_.getDeclaredCollection("locations", entityLocation_.getJavaType());
        } catch (IllegalArgumentException iae) {
            // expecting
            //java.lang.IllegalArgumentException: The attribute [locations] from the managed type [ManagedTypeImpl[RelationalDescriptor(org.eclipse.persistence.testing.models.jpa.metamodel.Manufacturer --> [DatabaseTable(CMP3_MM_MANUF)])]] is not present.
            expectedIAExceptionThrown = true;
            }
            assertTrue("Expected thrown IllegalArgumentException", expectedIAExceptionThrown);

            expectedIAExceptionThrown = false;
        try {
            //<E> ListAttribute<X, E> getDeclaredList(String name, Class<E> elementType);
            // UC2 - the attribute is on the managedType (but is the wrong type)
            // Also avoid a CCE on a List attribute
            //java.lang.ClassCastException: org.eclipse.persistence.internal.jpa.metamodel.ListAttributeImpl cannot be cast to jakarta.persistence.metamodel.CollectionAttribute
            CollectionAttribute<Manufacturer, ?> anAttribute =
                entityManufacturer_.getDeclaredCollection("hardwareDesigners", entityManufacturer_.getJavaType());
        } catch (IllegalArgumentException iae) {
            // expecting
            //java.lang.IllegalArgumentException: Expected attribute return type [COLLECTION] on the existing attribute [hardwareDesigners] on the managed type [ManagedTypeImpl[RelationalDescriptor(org.eclipse.persistence.testing.models.jpa.metamodel.Manufacturer --> [DatabaseTable(CMP3_MM_MANUF)])]] but found attribute return type [LIST].
            expectedIAExceptionThrown = true;
            }
            assertTrue("Expected thrown IllegalArgumentException", expectedIAExceptionThrown);


            // FUTURE: We need a Collection (computers is a Set)
    /*            expectedIAExceptionThrown = false;
        try {
            //<E> ListAttribute<X, E> getDeclaredList(String name, Class<E> elementType);
            // UC3 - the attribute is on the managedType (not on any superType)
            CollectionAttribute<Manufacturer, HardwareDesigner> anAttribute =
                entityManufacturer.getDeclaredCollection("computers", entityHardwareDesigner.getJavaType());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
            }
            assertFalse(expectedIAExceptionThrown);
    */

    /*            // FUTURE: We need a Collection on a superclass (computers is a Set)
            expectedIAExceptionThrown = false;
        try {
            //<E> ListAttribute<X, E> getDeclaredList(String name, Class<E> elementType);
            // UC4 - the attribute is on the immediate superclass but it is the wrong return type of LIST instead of COLLECTION
            CollectionAttribute<Manufacturer, Computer> anAttribute =
                entityManufacturer.getDeclaredCollection("corporateComputers", entityComputer.getJavaType());
        } catch (IllegalArgumentException iae) {
            // expecting
            // java.lang.IllegalArgumentException: The declared attribute [corporateComputers] from the managed type [ManagedTypeImpl[RelationalDescriptor(org.eclipse.persistence.testing.models.jpa.metamodel.Manufacturer --> [DatabaseTable(CMP3_MM_MANUF)])]] is not present - however, it is declared on a superclass.
            //iae.printStackTrace();
            expectedIAExceptionThrown = true;
            }
            assertTrue("Expected thrown IllegalArgumentException", expectedIAExceptionThrown);
    */

            //     private Collection<Computer> corporateComputers = new HashSet<Computer>();
            // http://wiki.eclipse.org/EclipseLink/Development/JPA_2.0/metamodel_api#DI_91:_20091008:_ManagedType.getDeclaredAttribute.28.29_does_not_throw_expected_IAE_for_Entity.28target.29-MappedSuperclass-MappedSuperclass.28attribute.29_Hierarchy
            expectedIAExceptionThrown = false;
        try {
            //<E> ListAttribute<X, E> getDeclaredList(String name, Class<E> elementType);
            // Note: internally EclipseLink treats a ONE_TO_MANY as a MANY_TO_MANY for the case of a unidirectional mapping on a MappedSuperclass
            // UC4 - the attribute is on the immediate superclass and is the correct COLLECTION - we still get an IAE
            CollectionAttribute<Manufacturer, Computer> anAttribute =
                entityManufacturer_.getDeclaredCollection("corporateComputers", entityComputer_.getJavaType());
        } catch (IllegalArgumentException iae) {
            // expecting
            // java.lang.IllegalArgumentException: Expected attribute return type [COLLECTION] on the existing attribute [corporateComputers] on the managed type [ManagedTypeImpl[RelationalDescriptor(org.eclipse.persistence.testing.models.jpa.metamodel.Manufacturer --> [DatabaseTable(CMP3_MM_MANUF)])]] but found attribute return type [LIST].
            expectedIAExceptionThrown = true;
            }
            assertTrue("Expected thrown IllegalArgumentException", expectedIAExceptionThrown);

            /**
             *  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
             */
            //<E> SetAttribute<X, E> getDeclaredSet(String name, Class<E> elementType);

            /**
             *  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
             */
            expectedIAExceptionThrown = false;
        try {
            //<E> ListAttribute<X, E> getDeclaredList(String name, Class<E> elementType);
            // UC1 - the attribute does not exist on the managedType (regardless of whether it is on any superType)
            ListAttribute<Manufacturer, GalacticPosition> anAttribute =
                entityManufacturer_.getDeclaredList("locations", entityLocation_.getJavaType());
        } catch (IllegalArgumentException iae) {
            // expecting
            //java.lang.IllegalArgumentException: The attribute [locations] from the managed type [ManagedTypeImpl[RelationalDescriptor(org.eclipse.persistence.testing.models.jpa.metamodel.Manufacturer --> [DatabaseTable(CMP3_MM_MANUF)])]] is not present.
            expectedIAExceptionThrown = true;
            }
            assertTrue("Expected thrown IllegalArgumentException", expectedIAExceptionThrown);

            expectedIAExceptionThrown = false;
        try {
            //<E> ListAttribute<X, E> getDeclaredList(String name, Class<E> elementType);
            // UC2 - the attribute is on the managedType (but is the wrong type)
            ListAttribute<Manufacturer, ?> anAttribute =
                entityManufacturer_.getDeclaredList("hardwareDesigners", entityManufacturer_.getJavaType());
        } catch (IllegalArgumentException iae) {
            // expecting
            //java.lang.IllegalArgumentException: Expected attribute type [class org.eclipse.persistence.testing.models.jpa.metamodel.Manufacturer] on the existing attribute [hardwareDesigners] on the managed type [ManagedTypeImpl[RelationalDescriptor(org.eclipse.persistence.testing.models.jpa.metamodel.Manufacturer --> [DatabaseTable(CMP3_MM_MANUF)])]] but found attribute type [class org.eclipse.persistence.testing.models.jpa.metamodel.HardwareDesigner].
            expectedIAExceptionThrown = true;
            }
            assertTrue("Expected thrown IllegalArgumentException", expectedIAExceptionThrown);

            expectedIAExceptionThrown = false;
        try {
            //<E> ListAttribute<X, E> getDeclaredList(String name, Class<E> elementType);
            // UC3 - the attribute is on the managedType (not on any superType)
            ListAttribute<Manufacturer, HardwareDesigner> anAttribute =
                entityManufacturer_.getDeclaredList("hardwareDesigners", entityHardwareDesigner_.getJavaType());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
            }
            assertFalse(expectedIAExceptionThrown);

            //     private Collection<Computer> corporateComputers = new HashSet<Computer>();
            // http://wiki.eclipse.org/EclipseLink/Development/JPA_2.0/metamodel_api#DI_91:_20091008:_ManagedType.getDeclaredAttribute.28.29_does_not_throw_expected_IAE_for_Entity.28target.29-MappedSuperclass-MappedSuperclass.28attribute.29_Hierarchy
            expectedIAExceptionThrown = false;
        try {
            //<E> ListAttribute<X, E> getDeclaredList(String name, Class<E> elementType);
            // UC4 - the attribute is on the immediate superclass
            // Note: internally EclipseLink treats a ONE_TO_MANY as a MANY_TO_MANY for the case of a unidirectional mapping on a MappedSuperclass
            CollectionAttribute<Manufacturer, Computer> anAttribute =
                entityManufacturer_.getDeclaredCollection("corporateComputers", entityComputer_.getJavaType());
        } catch (IllegalArgumentException iae) {
            // expecting
            // java.lang.IllegalArgumentException: The declared attribute [corporateComputers] from the managed type [ManagedTypeImpl[RelationalDescriptor(org.eclipse.persistence.testing.models.jpa.metamodel.Manufacturer --> [DatabaseTable(CMP3_MM_MANUF)])]] is not present - however, it is declared on a superclass.
            expectedIAExceptionThrown = true;
            }
            assertTrue("Expected thrown IllegalArgumentException", expectedIAExceptionThrown);


            /**
             *  Return all collection-valued attributes of the managed type.
             *  @return collection valued attributes
             */
            //java.util.Set<PluralAttribute<? super X, ?, ?>> getCollections();

            /**
             *  Return all collection-valued attributes declared by the
             *  managed type.
             *  @return declared collection valued attributes
             */
            //java.util.Set<PluralAttribute<X, ?, ?>> getDeclaredCollections();
            // This also tests getCollections()
            // Here we start with 6 attributes in getAttributes() - this is reduced to 3 in getCollections before declared filtering
            // In declaredCollections we reduce this to 2 because one of the types "corporateComputers" is on a mappedSuperclass
            expectedIAExceptionThrown = false;
        try {
            //<E> ListAttribute<X, E> getDeclaredList(String name, Class<E> elementType);
            // UC3 - the attribute is on the managedType (not on any superType)
            Set<PluralAttribute<Manufacturer, ?, ?>> collections =
                entityManufacturer_.getDeclaredPluralAttributes();
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
            }
            assertFalse(expectedIAExceptionThrown);


            /**
             *  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
             */
            //Attribute<? super X, ?> getAttribute(String name);

            /**
             *  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
             */
            //Attribute<X, ?> getDeclaredAttribute(String name);
            expectedIAExceptionThrown = false;
        try {
            //<E> ListAttribute<X, E> getDeclaredList(String name, Class<E> elementType);
            // UC1 - the attribute does not exist on the managedType (regardless of whether it is on any superType)
            Attribute<Manufacturer, ?> anAttribute =
                entityManufacturer_.getDeclaredAttribute("locations");//, entityLocation.getJavaType());
        } catch (IllegalArgumentException iae) {
            // expecting
            //java.lang.IllegalArgumentException: The attribute [locations] from the managed type [ManagedTypeImpl[RelationalDescriptor(org.eclipse.persistence.testing.models.jpa.metamodel.Manufacturer --> [DatabaseTable(CMP3_MM_MANUF)])]] is not present.
            expectedIAExceptionThrown = true;
            }
            assertTrue("Expected thrown IllegalArgumentException", expectedIAExceptionThrown);

            expectedIAExceptionThrown = false;
        try {
            //<E> ListAttribute<X, E> getDeclaredList(String name, Class<E> elementType);
            // UC3 - the attribute is on the managedType (not on any superType)
            Attribute<Manufacturer, ?> anAttribute =
                entityManufacturer_.getDeclaredAttribute("hardwareDesigners");//, entityHardwareDesigner.getJavaType());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
            }
            assertFalse(expectedIAExceptionThrown);

            expectedIAExceptionThrown = false;
        try {
            //<E> ListAttribute<X, E> getDeclaredList(String name, Class<E> elementType);
            // UC4 - the attribute is on the immediate superclass
            // Note: internally EclipseLink treats a ONE_TO_MANY as a MANY_TO_MANY for the case of a unidirectional mapping on a MappedSuperclass
            Attribute<Manufacturer, ?> anAttribute =
                entityManufacturer_.getDeclaredAttribute("corporateComputers");//, entityComputer.getJavaType());
        } catch (IllegalArgumentException iae) {
            // expecting
            // java.lang.IllegalArgumentException: The declared attribute [corporateComputers] from the managed type [ManagedTypeImpl[RelationalDescriptor(org.eclipse.persistence.testing.models.jpa.metamodel.Manufacturer --> [DatabaseTable(CMP3_MM_MANUF)])]] is not present - however, it is declared on a superclass.
            expectedIAExceptionThrown = true;
            }
            assertTrue("Expected thrown IllegalArgumentException", expectedIAExceptionThrown);

            expectedIAExceptionThrown = false;
            Attribute<Manufacturer, ?> aListAttribute = null;
        try {
            //<E> ListAttribute<X, E> getDeclaredList(String name, Class<E> elementType);
            // the attribute is on the class
            aListAttribute = entityManufacturer_.getDeclaredAttribute("hardwareDesigners");//, entityComputer.getJavaType());
        } catch (IllegalArgumentException iae) {
            // expecting
            // java.lang.IllegalArgumentException: The declared attribute [corporateComputers] from the managed type [ManagedTypeImpl[RelationalDescriptor(org.eclipse.persistence.testing.models.jpa.metamodel.Manufacturer --> [DatabaseTable(CMP3_MM_MANUF)])]] is not present - however, it is declared on a superclass.
            //iae.printStackTrace();
            expectedIAExceptionThrown = true;
            }
            assertFalse(expectedIAExceptionThrown);
            assertNotNull(aListAttribute);


            // check the root
            expectedIAExceptionThrown = false;
            Attribute<Person, Manufacturer> aCollectionAttribute = null;
        try {
            //<E> ListAttribute<X, E> getDeclaredList(String name, Class<E> elementType);
            // the attribute is on the class
            IdentifiableType person = entityManufacturer_.getSupertype().getSupertype();
            aCollectionAttribute = person.getDeclaredAttribute("historicalEmps");//, entityComputer.getJavaType());
        } catch (IllegalArgumentException iae) {
            // expecting
            // java.lang.IllegalArgumentException: The declared attribute [corporateComputers] from the managed type [ManagedTypeImpl[RelationalDescriptor(org.eclipse.persistence.testing.models.jpa.metamodel.Manufacturer --> [DatabaseTable(CMP3_MM_MANUF)])]] is not present - however, it is declared on a superclass.
            //iae.printStackTrace();
            expectedIAExceptionThrown = true;
            }
            assertFalse(expectedIAExceptionThrown);
            assertNotNull(aCollectionAttribute);
            // check managed type
            assertEquals(msPerson_, aCollectionAttribute.getDeclaringType());
            // check element type
            //assertEquals(entityManufacturer, aCollectionAttribute.getDeclaringType());

            // positive: check one level down from the root
            expectedIAExceptionThrown = false;
            Attribute<Corporation,?> aCollectionAttribute2 = null;
        try {
            //<E> ListAttribute<X, E> getDeclaredList(String name, Class<E> elementType);
            // the attribute is on the class
            IdentifiableType corporation = entityManufacturer_.getSupertype();
            // Note: internally EclipseLink treats a ONE_TO_MANY as a MANY_TO_MANY for the case of a unidirectional mapping on a MappedSuperclass
            aCollectionAttribute2 = corporation.getDeclaredAttribute("corporateComputers");//, entityComputer.getJavaType());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
            }
            assertFalse(expectedIAExceptionThrown);
            assertNotNull(aCollectionAttribute2);

            // negative: check one level down from the root
            expectedIAExceptionThrown = false;
            aCollectionAttribute2 = null;
        try {
            //<E> ListAttribute<X, E> getDeclaredList(String name, Class<E> elementType);
            // the attribute is on the class
            IdentifiableType corporation = entityManufacturer_.getSupertype();
            aCollectionAttribute2 = corporation.getDeclaredAttribute("notFound");//, entityComputer.getJavaType());
        } catch (IllegalArgumentException iae) {
            // expecting
            // java.lang.IllegalArgumentException: The declared attribute [corporateComputers] from the managed type [ManagedTypeImpl[RelationalDescriptor(org.eclipse.persistence.testing.models.jpa.metamodel.Manufacturer --> [DatabaseTable(CMP3_MM_MANUF)])]] is not present - however, it is declared on a superclass.
            expectedIAExceptionThrown = true;
            }
            // we expect an IAE on getAttribute(name) if name does not exist
            assertTrue("Expected thrown IllegalArgumentException", expectedIAExceptionThrown);


            /**
             *  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
             */
            //SingularAttribute<? super X, ?> getSingularAttribute(String name);

            /**
             *  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
             */
            //SingularAttribute<X, ?> getDeclaredSingularAttribute(String name);

            /**
             *  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
             */
            //CollectionAttribute<? super X, ?> getCollection(String name);

            /**
             *  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
             */
            //SetAttribute<? super X, ?> getSet(String name);

            /**
             *  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
             */
            //ListAttribute<? super X, ?> getList(String name);

            /**
             *  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
             */
            //MapAttribute<? super X, ?, ?> getMap(String name);

            /**
             *  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
             */
            //CollectionAttribute<X, ?> getDeclaredCollection(String name);
            expectedIAExceptionThrown = false;
        try {
            // UC4 - the attribute is on the immediate superclass
            // Note: internally EclipseLink treats a ONE_TO_MANY as a MANY_TO_MANY for the case of a unidirectional mapping on a MappedSuperclass
            CollectionAttribute<Manufacturer, ?> anAttribute =
                entityManufacturer_.getDeclaredCollection("corporateComputers");
        } catch (IllegalArgumentException iae) {
            // expecting
            // java.lang.IllegalArgumentException: The declared attribute [corporateComputers] from the managed type [ManagedTypeImpl[RelationalDescriptor(org.eclipse.persistence.testing.models.jpa.metamodel.Manufacturer --> [DatabaseTable(CMP3_MM_MANUF)])]] is not present - however, it is declared on a superclass.
            expectedIAExceptionThrown = true;
            }
            // IAE because the attribute is declared one level above
            assertTrue("Expected thrown IllegalArgumentException", expectedIAExceptionThrown);

            expectedIAExceptionThrown = false;
        try {
            // Note: internally EclipseLink treats a ONE_TO_MANY as a MANY_TO_MANY for the case of a unidirectional mapping on a MappedSuperclass
            CollectionAttribute<Corporation, ?> anAttribute =
                msCorporation_.getDeclaredCollection("corporateComputers");
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
            }
            assertFalse(expectedIAExceptionThrown);

            expectedIAExceptionThrown = false;
        try {
            //<E> ListAttribute<X, E> getDeclaredList(String name, Class<E> elementType);
            // UC4 - the attribute is on the immediate superclass
            // Note: internally EclipseLink treats a ONE_TO_MANY as a MANY_TO_MANY for the case of a unidirectional mapping on a MappedSuperclass
            CollectionAttribute<Manufacturer, Computer> anAttribute =
                entityManufacturer_.getDeclaredCollection("corporateComputers", entityComputer_.getJavaType());
        } catch (IllegalArgumentException iae) {
            // expecting
            // java.lang.IllegalArgumentException: The declared attribute [corporateComputers] from the managed type [ManagedTypeImpl[RelationalDescriptor(org.eclipse.persistence.testing.models.jpa.metamodel.Manufacturer --> [DatabaseTable(CMP3_MM_MANUF)])]] is not present - however, it is declared on a superclass.
            expectedIAExceptionThrown = true;
            }
            assertTrue("Expected thrown IllegalArgumentException", expectedIAExceptionThrown);
            // reset state
            expectedIAExceptionThrown = false;
            /**
             *  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
             */
            //SetAttribute<X, ?> getDeclaredSet(String name);

            /**
             *  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
             */
            //ListAttribute<X, ?> getDeclaredList(String name);

            /**
             *  Return the Map-valued attribute declared by the managed
             *  type that corresponds to the specified name.
             *  @param name  the name of the represented attribute
             *  @return declared MapAttribute of the given name
             *  @throws IllegalArgumentException if attribute of the given
             *          name is not declared in the managed type
             */
            //MapAttribute<X, ?, ?> getDeclaredMap(String name);


        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    // TODO: This is not testing anything different?
    public void testManagedType_getDeclaredAttributes_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);
            MappedSuperclassTypeImpl<Person> msPerson_ = (MappedSuperclassTypeImpl)metamodel.managedType(Person.class);
            assertNotNull(msPerson_);
            MappedSuperclassTypeImpl<Corporation> msCorporation_ = (MappedSuperclassTypeImpl)metamodel.managedType(Corporation.class);
            assertNotNull(msCorporation_);
            EntityTypeImpl<GalacticPosition> entityLocation_ =(EntityTypeImpl) metamodel.entity(GalacticPosition.class);
            assertNotNull(entityLocation_);
            EntityTypeImpl<Computer> entityComputer_ = (EntityTypeImpl)metamodel.entity(Computer.class);
            assertNotNull(entityComputer_);
            EntityTypeImpl<HardwareDesigner> entityHardwareDesigner_ = (EntityTypeImpl)metamodel.entity(HardwareDesigner.class);
            assertNotNull(entityHardwareDesigner_);

        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    // TODO: This is not testing anything different?
    public void testManagedType_getSingularAttribute_Type_param_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);
            MappedSuperclassTypeImpl<Person> msPerson_ = (MappedSuperclassTypeImpl)metamodel.managedType(Person.class);
            assertNotNull(msPerson_);
            MappedSuperclassTypeImpl<Corporation> msCorporation_ = (MappedSuperclassTypeImpl)metamodel.managedType(Corporation.class);
            assertNotNull(msCorporation_);
            EntityTypeImpl<GalacticPosition> entityLocation_ =(EntityTypeImpl) metamodel.entity(GalacticPosition.class);
            assertNotNull(entityLocation_);
            EntityTypeImpl<Computer> entityComputer_ = (EntityTypeImpl)metamodel.entity(Computer.class);
            assertNotNull(entityComputer_);
            EntityTypeImpl<HardwareDesigner> entityHardwareDesigner_ = (EntityTypeImpl)metamodel.entity(HardwareDesigner.class);
            assertNotNull(entityHardwareDesigner_);

        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    // TODO: This is not testing anything different?
    public void testManagedType_getDeclaredSingularAttribute_Type_param_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);
            MappedSuperclassTypeImpl<Person> msPerson_ = (MappedSuperclassTypeImpl)metamodel.managedType(Person.class);
            assertNotNull(msPerson_);
            MappedSuperclassTypeImpl<Corporation> msCorporation_ = (MappedSuperclassTypeImpl)metamodel.managedType(Corporation.class);
            assertNotNull(msCorporation_);
            EntityTypeImpl<GalacticPosition> entityLocation_ =(EntityTypeImpl) metamodel.entity(GalacticPosition.class);
            assertNotNull(entityLocation_);
            EntityTypeImpl<Computer> entityComputer_ = (EntityTypeImpl)metamodel.entity(Computer.class);
            assertNotNull(entityComputer_);
            EntityTypeImpl<HardwareDesigner> entityHardwareDesigner_ = (EntityTypeImpl)metamodel.entity(HardwareDesigner.class);
            assertNotNull(entityHardwareDesigner_);

        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    // TODO: This is not testing anything different?
    public void testManagedType_getSingularAttributes_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);
            MappedSuperclassTypeImpl<Person> msPerson_ = (MappedSuperclassTypeImpl)metamodel.managedType(Person.class);
            assertNotNull(msPerson_);
            MappedSuperclassTypeImpl<Corporation> msCorporation_ = (MappedSuperclassTypeImpl)metamodel.managedType(Corporation.class);
            assertNotNull(msCorporation_);
            EntityTypeImpl<GalacticPosition> entityLocation_ =(EntityTypeImpl) metamodel.entity(GalacticPosition.class);
            assertNotNull(entityLocation_);
            EntityTypeImpl<Computer> entityComputer_ = (EntityTypeImpl)metamodel.entity(Computer.class);
            assertNotNull(entityComputer_);
            EntityTypeImpl<HardwareDesigner> entityHardwareDesigner_ = (EntityTypeImpl)metamodel.entity(HardwareDesigner.class);
            assertNotNull(entityHardwareDesigner_);

        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    // TODO: This is not testing anything different?
    public void testManagedType_getDeclaredSingularAttributes_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);
            MappedSuperclassTypeImpl<Person> msPerson_ = (MappedSuperclassTypeImpl)metamodel.managedType(Person.class);
            assertNotNull(msPerson_);
            MappedSuperclassTypeImpl<Corporation> msCorporation_ = (MappedSuperclassTypeImpl)metamodel.managedType(Corporation.class);
            assertNotNull(msCorporation_);
            EntityTypeImpl<GalacticPosition> entityLocation_ =(EntityTypeImpl) metamodel.entity(GalacticPosition.class);
            assertNotNull(entityLocation_);
            EntityTypeImpl<Computer> entityComputer_ = (EntityTypeImpl)metamodel.entity(Computer.class);
            assertNotNull(entityComputer_);
            EntityTypeImpl<HardwareDesigner> entityHardwareDesigner_ = (EntityTypeImpl)metamodel.entity(HardwareDesigner.class);
            assertNotNull(entityHardwareDesigner_);

        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    // TODO: This is not testing anything different?
    public void testManagedType_getCollection_Type_param_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);
            MappedSuperclassTypeImpl<Person> msPerson_ = (MappedSuperclassTypeImpl)metamodel.managedType(Person.class);
            assertNotNull(msPerson_);
            MappedSuperclassTypeImpl<Corporation> msCorporation_ = (MappedSuperclassTypeImpl)metamodel.managedType(Corporation.class);
            assertNotNull(msCorporation_);
            EntityTypeImpl<GalacticPosition> entityLocation_ =(EntityTypeImpl) metamodel.entity(GalacticPosition.class);
            assertNotNull(entityLocation_);
            EntityTypeImpl<Computer> entityComputer_ = (EntityTypeImpl)metamodel.entity(Computer.class);
            assertNotNull(entityComputer_);
            EntityTypeImpl<HardwareDesigner> entityHardwareDesigner_ = (EntityTypeImpl)metamodel.entity(HardwareDesigner.class);
            assertNotNull(entityHardwareDesigner_);

        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    // TODO: This is not testing anything different?
    public void testManagedType_getDeclaredCollection_Type_param_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);
            MappedSuperclassTypeImpl<Person> msPerson_ = (MappedSuperclassTypeImpl)metamodel.managedType(Person.class);
            assertNotNull(msPerson_);
            MappedSuperclassTypeImpl<Corporation> msCorporation_ = (MappedSuperclassTypeImpl)metamodel.managedType(Corporation.class);
            assertNotNull(msCorporation_);
            EntityTypeImpl<GalacticPosition> entityLocation_ =(EntityTypeImpl) metamodel.entity(GalacticPosition.class);
            assertNotNull(entityLocation_);
            EntityTypeImpl<Computer> entityComputer_ = (EntityTypeImpl)metamodel.entity(Computer.class);
            assertNotNull(entityComputer_);
            EntityTypeImpl<HardwareDesigner> entityHardwareDesigner_ = (EntityTypeImpl)metamodel.entity(HardwareDesigner.class);
            assertNotNull(entityHardwareDesigner_);

        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    // TODO: This is not testing anything different?
    public void testManagedType_getSet_Type_param_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);
            MappedSuperclassTypeImpl<Person> msPerson_ = (MappedSuperclassTypeImpl)metamodel.managedType(Person.class);
            assertNotNull(msPerson_);
            MappedSuperclassTypeImpl<Corporation> msCorporation_ = (MappedSuperclassTypeImpl)metamodel.managedType(Corporation.class);
            assertNotNull(msCorporation_);
            EntityTypeImpl<GalacticPosition> entityLocation_ =(EntityTypeImpl) metamodel.entity(GalacticPosition.class);
            assertNotNull(entityLocation_);
            EntityTypeImpl<Computer> entityComputer_ = (EntityTypeImpl)metamodel.entity(Computer.class);
            assertNotNull(entityComputer_);
            EntityTypeImpl<HardwareDesigner> entityHardwareDesigner_ = (EntityTypeImpl)metamodel.entity(HardwareDesigner.class);
            assertNotNull(entityHardwareDesigner_);

        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    // TODO: This is not testing anything different?
    public void testManagedType_getDeclaredSet_Type_param_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);
            MappedSuperclassTypeImpl<Person> msPerson_ = (MappedSuperclassTypeImpl)metamodel.managedType(Person.class);
            assertNotNull(msPerson_);
            MappedSuperclassTypeImpl<Corporation> msCorporation_ = (MappedSuperclassTypeImpl)metamodel.managedType(Corporation.class);
            assertNotNull(msCorporation_);
            EntityTypeImpl<GalacticPosition> entityLocation_ =(EntityTypeImpl) metamodel.entity(GalacticPosition.class);
            assertNotNull(entityLocation_);
            EntityTypeImpl<Computer> entityComputer_ = (EntityTypeImpl)metamodel.entity(Computer.class);
            assertNotNull(entityComputer_);
            EntityTypeImpl<HardwareDesigner> entityHardwareDesigner_ = (EntityTypeImpl)metamodel.entity(HardwareDesigner.class);
            assertNotNull(entityHardwareDesigner_);

        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    // TODO: This is not testing anything different?
    public void testManagedType_getList_Type_param_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);
            MappedSuperclassTypeImpl<Person> msPerson_ = (MappedSuperclassTypeImpl)metamodel.managedType(Person.class);
            assertNotNull(msPerson_);
            MappedSuperclassTypeImpl<Corporation> msCorporation_ = (MappedSuperclassTypeImpl)metamodel.managedType(Corporation.class);
            assertNotNull(msCorporation_);
            EntityTypeImpl<GalacticPosition> entityLocation_ =(EntityTypeImpl) metamodel.entity(GalacticPosition.class);
            assertNotNull(entityLocation_);
            EntityTypeImpl<Computer> entityComputer_ = (EntityTypeImpl)metamodel.entity(Computer.class);
            assertNotNull(entityComputer_);
            EntityTypeImpl<HardwareDesigner> entityHardwareDesigner_ = (EntityTypeImpl)metamodel.entity(HardwareDesigner.class);
            assertNotNull(entityHardwareDesigner_);

        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    // TODO: This is not testing anything different?
    public void testManagedType_getDeclaredList_Type_param_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);
            MappedSuperclassTypeImpl<Person> msPerson_ = (MappedSuperclassTypeImpl)metamodel.managedType(Person.class);
            assertNotNull(msPerson_);
            MappedSuperclassTypeImpl<Corporation> msCorporation_ = (MappedSuperclassTypeImpl)metamodel.managedType(Corporation.class);
            assertNotNull(msCorporation_);
            EntityTypeImpl<GalacticPosition> entityLocation_ =(EntityTypeImpl) metamodel.entity(GalacticPosition.class);
            assertNotNull(entityLocation_);
            EntityTypeImpl<Computer> entityComputer_ = (EntityTypeImpl)metamodel.entity(Computer.class);
            assertNotNull(entityComputer_);
            EntityTypeImpl<HardwareDesigner> entityHardwareDesigner_ = (EntityTypeImpl)metamodel.entity(HardwareDesigner.class);
            assertNotNull(entityHardwareDesigner_);

        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    public void testManagedType_getMap_Type_param_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);
            MappedSuperclassTypeImpl<Person> msPerson_ = (MappedSuperclassTypeImpl)metamodel.managedType(Person.class);
            assertNotNull(msPerson_);
            MappedSuperclassTypeImpl<Corporation> msCorporation_ = (MappedSuperclassTypeImpl)metamodel.managedType(Corporation.class);
            assertNotNull(msCorporation_);
            EntityTypeImpl<GalacticPosition> entityLocation_ =(EntityTypeImpl) metamodel.entity(GalacticPosition.class);
            assertNotNull(entityLocation_);
            EntityTypeImpl<Computer> entityComputer_ = (EntityTypeImpl)metamodel.entity(Computer.class);
            assertNotNull(entityComputer_);
            EntityTypeImpl<HardwareDesigner> entityHardwareDesigner_ = (EntityTypeImpl)metamodel.entity(HardwareDesigner.class);
            assertNotNull(entityHardwareDesigner_);

            /**
             *  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
             */
            //<K, V> MapAttribute<? super X, K, V> getMap(String name, Class<K> keyType, Class<V> valueType);
            expectedIAExceptionThrown = false;
            MapAttribute<? super Manufacturer, ?, ?> anAttribute =
            entityManufacturer_.getMap("hardwareDesignersMap", Integer.class,  HardwareDesigner.class);
            // verify the default key type is the not the Map key - rather that is is the managedType PK
            Class<?> keyJavaType = anAttribute.getKeyJavaType();
            //@OneToMany(cascade=ALL, mappedBy="mappedEmployer")
            //private Map<String, HardwareDesigner> hardwareDesignersMap;// = new HashMap<String, HardwareDesigner>();
            // http://wiki.eclipse.org/EclipseLink/Development/JPA_2.0/metamodel_api#DI_63:_20090824:_Add_Map_support_for_.40MapKey_to_MapAttribute
            // Key is the primary key (PK) of the target entity - in this case HardwareDesigner which inherits its @Id from the Person @MappedSuperclass as '''Integer'''.
            Type keyType = anAttribute.getKeyType();
            assertEquals(String.class, keyJavaType); // When @MapKey(name="name") is present - or generics are set
            //assertEquals(Integer.class, keyJavaType); // When @MapKey or generics are not present - we default to the PK
            assertNotNull(keyType);
            assertTrue(keyType instanceof Type);
            assertEquals(Type.PersistenceType.BASIC, keyType.getPersistenceType());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    // TODO: This is not testing anything?
    public void testManagedType_getDeclaredMap_Type_param_declared_above_Method() {

    }

    // TODO: This is not testing anything?
    public void testManagedType_getDeclaredMap_Type_param_not_found_iae_Method() {

    }

    public void testManagedType_getDeclaredMap_Type_param_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);
            MappedSuperclassTypeImpl<Person> msPerson_ = (MappedSuperclassTypeImpl)metamodel.managedType(Person.class);
            assertNotNull(msPerson_);
            MappedSuperclassTypeImpl<Corporation> msCorporation_ = (MappedSuperclassTypeImpl)metamodel.managedType(Corporation.class);
            assertNotNull(msCorporation_);
            EntityTypeImpl<GalacticPosition> entityLocation_ =(EntityTypeImpl) metamodel.entity(GalacticPosition.class);
            assertNotNull(entityLocation_);
            EntityTypeImpl<Computer> entityComputer_ = (EntityTypeImpl)metamodel.entity(Computer.class);
            assertNotNull(entityComputer_);
            EntityTypeImpl<HardwareDesigner> entityHardwareDesigner_ = (EntityTypeImpl)metamodel.entity(HardwareDesigner.class);
            assertNotNull(entityHardwareDesigner_);

            /**
             *  Return the Map-valued attribute declared by 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 declared MapAttribute of the given name and key
             *          and value types
             *  @throws IllegalArgumentException if attribute of the given
             *          name and type is not declared in the managed type
             */
            //<K, V> MapAttribute<X, K, V> getDeclaredMap(String name, Class<K> keyType, Class<V> valueType);
            expectedIAExceptionThrown = false;
            MapAttribute<? super Manufacturer, ?, ?> anAttribute =
            entityManufacturer_.getDeclaredMap("hardwareDesignersMap", Integer.class,  HardwareDesigner.class);
            // verify the default key type is the not the Map key - rather that is is the managedType PK
            Class<?> keyJavaType = anAttribute.getKeyJavaType();
            //@OneToMany(cascade=ALL, mappedBy="mappedEmployer")
            //private Map<String, HardwareDesigner> hardwareDesignersMap;// = new HashMap<String, HardwareDesigner>();
            // http://wiki.eclipse.org/EclipseLink/Development/JPA_2.0/metamodel_api#DI_63:_20090824:_Add_Map_support_for_.40MapKey_to_MapAttribute
            // Key is the primary key (PK) of the target entity - in this case HardwareDesigner which inherits its @Id from the Person @MappedSuperclass as '''Integer'''.
            Type keyType = anAttribute.getKeyType();
            assertEquals(String.class, keyJavaType); // When @MapKey(name="name") is present - or generics are set
            //assertEquals(Integer.class, keyJavaType); // When @MapKey or generics are not present - we default to the PK
            assertNotNull(keyType);
            assertTrue(keyType instanceof Type);
            assertEquals(Type.PersistenceType.BASIC, keyType.getPersistenceType());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    // TODO: This is not testing anything?
    public void testManagedType_getPluralAttributes_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);
            MappedSuperclassTypeImpl<Person> msPerson_ = (MappedSuperclassTypeImpl)metamodel.managedType(Person.class);
            assertNotNull(msPerson_);
            MappedSuperclassTypeImpl<Corporation> msCorporation_ = (MappedSuperclassTypeImpl)metamodel.managedType(Corporation.class);
            assertNotNull(msCorporation_);
            EntityTypeImpl<GalacticPosition> entityLocation_ =(EntityTypeImpl) metamodel.entity(GalacticPosition.class);
            assertNotNull(entityLocation_);
            EntityTypeImpl<Computer> entityComputer_ = (EntityTypeImpl)metamodel.entity(Computer.class);
            assertNotNull(entityComputer_);
            EntityTypeImpl<HardwareDesigner> entityHardwareDesigner_ = (EntityTypeImpl)metamodel.entity(HardwareDesigner.class);
            assertNotNull(entityHardwareDesigner_);

        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    public void testManagedType_getDeclaredPluralAttributes_internal_entity_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);
            MappedSuperclassTypeImpl<Person> msPerson_ = (MappedSuperclassTypeImpl)metamodel.managedType(Person.class);
            assertNotNull(msPerson_);
            MappedSuperclassTypeImpl<Corporation> msCorporation_ = (MappedSuperclassTypeImpl)metamodel.managedType(Corporation.class);
            assertNotNull(msCorporation_);
            EntityTypeImpl<GalacticPosition> entityLocation_ =(EntityTypeImpl) metamodel.entity(GalacticPosition.class);
            assertNotNull(entityLocation_);
            EntityTypeImpl<Computer> entityComputer_ = (EntityTypeImpl)metamodel.entity(Computer.class);
            assertNotNull(entityComputer_);
            EntityTypeImpl<HardwareDesigner> entityHardwareDesigner_ = (EntityTypeImpl)metamodel.entity(HardwareDesigner.class);
            assertNotNull(entityHardwareDesigner_);

            // This also tests getCollections()
            // Here we start with 6 attributes in getAttributes() - this is reduced to 3 in getCollections before declared filtering
            // In declaredCollections we reduce this to 2 because one of the types "corporateComputers" is on a mappedSuperclass
            expectedIAExceptionThrown = false;
        try {
            Set<PluralAttribute<Manufacturer, ?, ?>> collections =
                entityManufacturer_.getDeclaredPluralAttributes();
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
            }
            assertFalse(expectedIAExceptionThrown);
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    public void testManagedType_getDeclaredPluralAttributes_root_entity_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Computer> entityComputer_ = (EntityTypeImpl)metamodel.entity(Computer.class);
            assertNotNull(entityComputer_);
            // This also tests getCollections()
            expectedIAExceptionThrown = false;
            Set<PluralAttribute<Computer, ?, ?>> collections =
            entityComputer_.getDeclaredPluralAttributes();
            assertNotNull(collections);
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    // Requires test model expansion before enabling test
    public void testManagedType_getDeclaredPluralAttributes_root_mappedSuperclass_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);
            MappedSuperclassTypeImpl<Person> msPerson_ = (MappedSuperclassTypeImpl)metamodel.managedType(Person.class);
            assertNotNull(msPerson_);

            // This also tests getCollections()
            expectedIAExceptionThrown = false;
            // historicalComputers is defined as a plural declared attribute on a root mappedSuperclass
            Set<PluralAttribute<Person, ?, ?>> collections =
            msPerson_.getDeclaredPluralAttributes();
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    public void testManagedType_getAttribute_on_Entity_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);
            EntityTypeImpl<HardwareDesigner> entityHardwareDesigner_ = (EntityTypeImpl)metamodel.entity(HardwareDesigner.class);
            assertNotNull(entityHardwareDesigner_);

            // Test case
            Attribute anAttribute = entityManufacturer_.getAttribute("hardwareDesignersMapUC4");
            assertNotNull(anAttribute);
            assertEquals(PersistentAttributeType.ONE_TO_MANY, anAttribute.getPersistentAttributeType());
            assertTrue(((AttributeImpl)anAttribute).isPlural());
            assertTrue(anAttribute instanceof MapAttribute);
            assertEquals(entityHardwareDesigner_, ((MapAttribute)anAttribute).getElementType());
            assertEquals(CollectionType.MAP, ((MapAttribute)anAttribute).getCollectionType());
            assertEquals(String.class, ((MapAttribute)anAttribute).getKeyJavaType());

            assertTrue(((AttributeImpl)anAttribute).isPlural());
            assertTrue(anAttribute instanceof PluralAttribute);
            Bindable aPluralAttribute = entityManufacturer_.getMap("hardwareDesignersMapUC4");
            assertEquals(HardwareDesigner.class, aPluralAttribute.getBindableJavaType());
            assertEquals(Map.class, anAttribute.getJavaType());
            assertEquals(PersistentAttributeType.ONE_TO_MANY, anAttribute.getPersistentAttributeType());

        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    public void testManagedType_getAttribute_on_MappedSuperclass_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            ManagedType<Corporation> msCorporation_  = metamodel.managedType(Corporation.class);
            assertNotNull(msCorporation_);
            EntityTypeImpl<Computer> entityComputer_ = (EntityTypeImpl)metamodel.entity(Computer.class);
            assertNotNull(entityComputer_);


            // Test case
            // Note: internally EclipseLink treats a ONE_TO_MANY as a MANY_TO_MANY for the case of a unidirectional mapping on a MappedSuperclass
            Attribute anAttribute = msCorporation_.getAttribute("corporateComputers");
            assertNotNull(anAttribute);
            assertEquals(PersistentAttributeType.ONE_TO_MANY, anAttribute.getPersistentAttributeType());
            assertTrue(((AttributeImpl)anAttribute).isPlural());
            assertTrue(anAttribute instanceof CollectionAttribute);
            assertEquals(entityComputer_, ((CollectionAttribute)anAttribute).getElementType());
            assertEquals(CollectionType.COLLECTION, ((CollectionAttribute)anAttribute).getCollectionType());

            assertTrue(((AttributeImpl)anAttribute).isPlural());
            assertTrue(anAttribute instanceof PluralAttribute);
            Bindable aPluralAttribute = msCorporation_.getCollection("corporateComputers");
            assertEquals(Computer.class, aPluralAttribute.getBindableJavaType());
            assertEquals(Collection.class, anAttribute.getJavaType());
            assertEquals(PersistentAttributeType.ONE_TO_MANY, anAttribute.getPersistentAttributeType());


        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    public void testManagedType_getAttribute_doesNotExist_on_Entity_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
            Attribute anAttribute = null;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);
            EntityTypeImpl<HardwareDesigner> entityHardwareDesigner_ = (EntityTypeImpl)metamodel.entity(HardwareDesigner.class);
            assertNotNull(entityHardwareDesigner_);

            // Test case
            anAttribute = entityManufacturer_.getAttribute("does_not_exist");
        } catch (IllegalArgumentException iae) {
            // We expect an exception
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertNull(anAttribute);
            assertTrue("An IAE exception should have occured on a non-existent attribute.", expectedIAExceptionThrown);
        }
    }

    public void testManagedType_getAttribute_doesNotExist_on_MappedSuperclass_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
            Attribute anAttribute = null;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            ManagedType<Corporation> msCorporation_  = metamodel.managedType(Corporation.class);
            assertNotNull(msCorporation_);

            // Test case
            anAttribute = msCorporation_.getAttribute("does_not_exist");
        } catch (IllegalArgumentException iae) {
            // We expect an exception
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertNull(anAttribute);
            assertTrue("An IAE exception should have occured on a non-existent attribute.", expectedIAExceptionThrown);
        }
    }

    public void testManagedType_getDeclaredAttribute_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);
            EntityTypeImpl<HardwareDesigner> entityHardwareDesigner_ = (EntityTypeImpl)metamodel.entity(HardwareDesigner.class);
            assertNotNull(entityHardwareDesigner_);

            // Test case
            Attribute anAttribute = entityManufacturer_.getDeclaredAttribute("hardwareDesignersMapUC4");
            assertNotNull(anAttribute);
            assertEquals(PersistentAttributeType.ONE_TO_MANY, anAttribute.getPersistentAttributeType());
            assertTrue(((AttributeImpl)anAttribute).isPlural());
            assertTrue(anAttribute instanceof MapAttribute);
            assertEquals(entityHardwareDesigner_, ((MapAttribute)anAttribute).getElementType());
            assertEquals(CollectionType.MAP, ((MapAttribute)anAttribute).getCollectionType());
            assertEquals(String.class, ((MapAttribute)anAttribute).getKeyJavaType());

            assertTrue(((AttributeImpl)anAttribute).isPlural());
            assertTrue(anAttribute instanceof PluralAttribute);
            Bindable aPluralAttribute = entityManufacturer_.getMap("hardwareDesignersMapUC4");
            assertEquals(HardwareDesigner.class, aPluralAttribute.getBindableJavaType());
            assertEquals(Map.class, anAttribute.getJavaType());
            assertEquals(PersistentAttributeType.ONE_TO_MANY, anAttribute.getPersistentAttributeType());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    public void testManagedType_getDeclaredListAttribute_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);
            EntityTypeImpl<HardwareDesigner> entityHardwareDesigner_ = (EntityTypeImpl)metamodel.entity(HardwareDesigner.class);
            assertNotNull(entityHardwareDesigner_);

            // Test case
            Attribute anAttribute = entityManufacturer_.getDeclaredAttribute("hardwareDesigners");
            assertNotNull(anAttribute);
            assertEquals(PersistentAttributeType.ONE_TO_MANY, anAttribute.getPersistentAttributeType());
            assertTrue(((AttributeImpl)anAttribute).isPlural());
            assertTrue(anAttribute instanceof ListAttribute);
            assertEquals(entityHardwareDesigner_, ((ListAttribute)anAttribute).getElementType());
            assertEquals(CollectionType.LIST, ((ListAttribute)anAttribute).getCollectionType());

            assertTrue(((AttributeImpl)anAttribute).isPlural());
            assertTrue(anAttribute instanceof PluralAttribute);
            Bindable aPluralAttribute = entityManufacturer_.getDeclaredList("hardwareDesigners");
            assertEquals(HardwareDesigner.class, aPluralAttribute.getBindableJavaType());
            assertEquals(List.class, anAttribute.getJavaType());
            assertEquals(PersistentAttributeType.ONE_TO_MANY, anAttribute.getPersistentAttributeType());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    public void testManagedType_getDeclaredAttribute_above_throws_iae_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
            Attribute anAttribute = null;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);

            // Test case
            // attribute is declared on a mappedsuperclass
            // Note: internally EclipseLink treats a ONE_TO_MANY as a MANY_TO_MANY for the case of a unidirectional mapping on a MappedSuperclass
            anAttribute = entityManufacturer_.getDeclaredAttribute("corporateComputers ");
        } catch (IllegalArgumentException iae) {
            // We expect and exception
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertNull(anAttribute);
            assertTrue("An IAE exception should have occured on an attribute declared above this entity.", expectedIAExceptionThrown);
        }
    }

    public void testManagedType_getDeclaredAttribute_doesNotExist_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
            Attribute anAttribute = null;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);

            // Test case
            anAttribute = entityManufacturer_.getDeclaredAttribute("does_not_exist");
        } catch (IllegalArgumentException iae) {
            // We expect and exception
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertNull(anAttribute);
            assertTrue("An IAE exception should have occured on a non-existent attribute.", expectedIAExceptionThrown);
        }
    }


    public void testManagedType_getSingularAttribute_BASIC_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<GalacticPosition> entityLocation_ =(EntityTypeImpl) metamodel.entity(GalacticPosition.class);
            assertNotNull(entityLocation_);
            EntityTypeImpl<Computer> entityComputer_ = (EntityTypeImpl)metamodel.entity(Computer.class);
            assertNotNull(entityComputer_);

            // Test case
            Attribute anAttribute = entityComputer_.getSingularAttribute("version");
            assertNotNull(anAttribute);
            assertEquals(PersistentAttributeType.BASIC, anAttribute.getPersistentAttributeType());
            assertFalse(((AttributeImpl)anAttribute).isPlural());
            assertTrue(anAttribute instanceof SingularAttribute);
            assertEquals(int.class, anAttribute.getJavaType());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    // TODO: This is not testing anything?
    public void testManagedType_getSingularAttribute_EMBEDDED_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<GalacticPosition> entityLocation_ =(EntityTypeImpl) metamodel.entity(GalacticPosition.class);
            assertNotNull(entityLocation_);
            EntityTypeImpl<Computer> entityComputer_ = (EntityTypeImpl)metamodel.entity(Computer.class);
            assertNotNull(entityComputer_);

            // not implemented
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    public void testManagedType_getDeclaredSingularAttribute_on_Entity_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<GalacticPosition> entityLocation_ =(EntityTypeImpl) metamodel.entity(GalacticPosition.class);
            assertNotNull(entityLocation_);
            EntityTypeImpl<Computer> entityComputer_ = (EntityTypeImpl)metamodel.entity(Computer.class);
            assertNotNull(entityComputer_);

            // Test case
            Attribute anAttribute = entityComputer_.getSingularAttribute("location");
            assertNotNull(anAttribute);
            assertEquals(PersistentAttributeType.ONE_TO_ONE, anAttribute.getPersistentAttributeType());
            assertFalse(((AttributeImpl)anAttribute).isPlural());
            assertTrue(anAttribute instanceof SingularAttribute);
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    public void testManagedType_getDeclaredSingularAttribute_on_MappedSuperclass_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            MappedSuperclassTypeImpl<Person> msPerson_ = (MappedSuperclassTypeImpl)metamodel.managedType(Person.class);
            assertNotNull(msPerson_);

            // Test case
            Attribute anAttribute = msPerson_.getSingularAttribute("name");
            assertNotNull(anAttribute);
            assertEquals(PersistentAttributeType.BASIC, anAttribute.getPersistentAttributeType());
            assertFalse(((AttributeImpl)anAttribute).isPlural());
            assertTrue(anAttribute instanceof SingularAttribute);
            assertEquals(String.class, anAttribute.getJavaType());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    // TODO: This is not testing anything?
    public void testManagedType_getCollection_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);
            MappedSuperclassTypeImpl<Person> msPerson_ = (MappedSuperclassTypeImpl)metamodel.managedType(Person.class);
            assertNotNull(msPerson_);
            MappedSuperclassTypeImpl<Corporation> msCorporation_ = (MappedSuperclassTypeImpl)metamodel.managedType(Corporation.class);
            assertNotNull(msCorporation_);
            EntityTypeImpl<GalacticPosition> entityLocation_ =(EntityTypeImpl) metamodel.entity(GalacticPosition.class);
            assertNotNull(entityLocation_);
            EntityTypeImpl<Computer> entityComputer_ = (EntityTypeImpl)metamodel.entity(Computer.class);
            assertNotNull(entityComputer_);
            EntityTypeImpl<HardwareDesigner> entityHardwareDesigner_ = (EntityTypeImpl)metamodel.entity(HardwareDesigner.class);
            assertNotNull(entityHardwareDesigner_);

        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    // TODO: This is not testing anything?
    public void testManagedType_getDeclaredCollection_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);
            MappedSuperclassTypeImpl<Person> msPerson_ = (MappedSuperclassTypeImpl)metamodel.managedType(Person.class);
            assertNotNull(msPerson_);
            MappedSuperclassTypeImpl<Corporation> msCorporation_ = (MappedSuperclassTypeImpl)metamodel.managedType(Corporation.class);
            assertNotNull(msCorporation_);
            EntityTypeImpl<GalacticPosition> entityLocation_ =(EntityTypeImpl) metamodel.entity(GalacticPosition.class);
            assertNotNull(entityLocation_);
            EntityTypeImpl<Computer> entityComputer_ = (EntityTypeImpl)metamodel.entity(Computer.class);
            assertNotNull(entityComputer_);
            EntityTypeImpl<HardwareDesigner> entityHardwareDesigner_ = (EntityTypeImpl)metamodel.entity(HardwareDesigner.class);
            assertNotNull(entityHardwareDesigner_);

        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    public void testManagedType_getSet_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);
            MappedSuperclassTypeImpl<Person> msPerson_ = (MappedSuperclassTypeImpl)metamodel.managedType(Person.class);
            assertNotNull(msPerson_);
            MappedSuperclassTypeImpl<Corporation> msCorporation_ = (MappedSuperclassTypeImpl)metamodel.managedType(Corporation.class);
            assertNotNull(msCorporation_);
            EntityTypeImpl<GalacticPosition> entityLocation_ =(EntityTypeImpl) metamodel.entity(GalacticPosition.class);
            assertNotNull(entityLocation_);
            EntityTypeImpl<Computer> entityComputer_ = (EntityTypeImpl)metamodel.entity(Computer.class);
            assertNotNull(entityComputer_);
            EntityTypeImpl<HardwareDesigner> entityHardwareDesigner_ = (EntityTypeImpl)metamodel.entity(HardwareDesigner.class);
            assertNotNull(entityHardwareDesigner_);
            SetAttribute<? super Manufacturer, Computer> computersAttribute =
            entityManufacturer_.getSet("computers", Computer.class);
            assertNotNull("computers SetAttribute should not be null in Manufacturer_", computersAttribute);
            EntityTypeImpl<MultiCoreCPU> entityMultiCoreCPU_ = (EntityTypeImpl)metamodel.entity(MultiCoreCPU.class);
            assertNotNull(entityMultiCoreCPU_);
            SetAttribute<? super MultiCoreCPU, Core> processorsAttribute =
                entityMultiCoreCPU_.getSet("cores", Core.class);
            assertNotNull("cores SetAttribute should not be null in MultiCoreCPU_", processorsAttribute);

        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    // TODO: This is not testing anything?
    public void testManagedType_getDeclaredSet_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);
            MappedSuperclassTypeImpl<Person> msPerson_ = (MappedSuperclassTypeImpl)metamodel.managedType(Person.class);
            assertNotNull(msPerson_);
            MappedSuperclassTypeImpl<Corporation> msCorporation_ = (MappedSuperclassTypeImpl)metamodel.managedType(Corporation.class);
            assertNotNull(msCorporation_);
            EntityTypeImpl<GalacticPosition> entityLocation_ =(EntityTypeImpl) metamodel.entity(GalacticPosition.class);
            assertNotNull(entityLocation_);
            EntityTypeImpl<Computer> entityComputer_ = (EntityTypeImpl)metamodel.entity(Computer.class);
            assertNotNull(entityComputer_);
            EntityTypeImpl<HardwareDesigner> entityHardwareDesigner_ = (EntityTypeImpl)metamodel.entity(HardwareDesigner.class);
            assertNotNull(entityHardwareDesigner_);

        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    // TODO: This is not testing anything?
    public void testManagedType_getList_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);
            MappedSuperclassTypeImpl<Person> msPerson_ = (MappedSuperclassTypeImpl)metamodel.managedType(Person.class);
            assertNotNull(msPerson_);
            MappedSuperclassTypeImpl<Corporation> msCorporation_ = (MappedSuperclassTypeImpl)metamodel.managedType(Corporation.class);
            assertNotNull(msCorporation_);
            EntityTypeImpl<GalacticPosition> entityLocation_ =(EntityTypeImpl) metamodel.entity(GalacticPosition.class);
            assertNotNull(entityLocation_);
            EntityTypeImpl<Computer> entityComputer_ = (EntityTypeImpl)metamodel.entity(Computer.class);
            assertNotNull(entityComputer_);
            EntityTypeImpl<HardwareDesigner> entityHardwareDesigner_ = (EntityTypeImpl)metamodel.entity(HardwareDesigner.class);
            assertNotNull(entityHardwareDesigner_);

        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    // TODO: This is not testing anything?
    public void testManagedType_getDeclaredList_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);
            MappedSuperclassTypeImpl<Person> msPerson_ = (MappedSuperclassTypeImpl)metamodel.managedType(Person.class);
            assertNotNull(msPerson_);
            MappedSuperclassTypeImpl<Corporation> msCorporation_ = (MappedSuperclassTypeImpl)metamodel.managedType(Corporation.class);
            assertNotNull(msCorporation_);
            EntityTypeImpl<GalacticPosition> entityLocation_ =(EntityTypeImpl) metamodel.entity(GalacticPosition.class);
            assertNotNull(entityLocation_);
            EntityTypeImpl<Computer> entityComputer_ = (EntityTypeImpl)metamodel.entity(Computer.class);
            assertNotNull(entityComputer_);
            EntityTypeImpl<HardwareDesigner> entityHardwareDesigner_ = (EntityTypeImpl)metamodel.entity(HardwareDesigner.class);
            assertNotNull(entityHardwareDesigner_);

        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    // TODO: This is not testing anything?
    public void testManagedType_getMap_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);
            MappedSuperclassTypeImpl<Person> msPerson_ = (MappedSuperclassTypeImpl)metamodel.managedType(Person.class);
            assertNotNull(msPerson_);
            MappedSuperclassTypeImpl<Corporation> msCorporation_ = (MappedSuperclassTypeImpl)metamodel.managedType(Corporation.class);
            assertNotNull(msCorporation_);
            EntityTypeImpl<GalacticPosition> entityLocation_ =(EntityTypeImpl) metamodel.entity(GalacticPosition.class);
            assertNotNull(entityLocation_);
            EntityTypeImpl<Computer> entityComputer_ = (EntityTypeImpl)metamodel.entity(Computer.class);
            assertNotNull(entityComputer_);
            EntityTypeImpl<HardwareDesigner> entityHardwareDesigner_ = (EntityTypeImpl)metamodel.entity(HardwareDesigner.class);
            assertNotNull(entityHardwareDesigner_);

        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    // TODO: This is not testing anything?
    public void testManagedType_getDeclaredMap_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);
            MappedSuperclassTypeImpl<Person> msPerson_ = (MappedSuperclassTypeImpl)metamodel.managedType(Person.class);
            assertNotNull(msPerson_);
            MappedSuperclassTypeImpl<Corporation> msCorporation_ = (MappedSuperclassTypeImpl)metamodel.managedType(Corporation.class);
            assertNotNull(msCorporation_);
            EntityTypeImpl<GalacticPosition> entityLocation_ =(EntityTypeImpl) metamodel.entity(GalacticPosition.class);
            assertNotNull(entityLocation_);
            EntityTypeImpl<Computer> entityComputer_ = (EntityTypeImpl)metamodel.entity(Computer.class);
            assertNotNull(entityComputer_);
            EntityTypeImpl<HardwareDesigner> entityHardwareDesigner_ = (EntityTypeImpl)metamodel.entity(HardwareDesigner.class);
            assertNotNull(entityHardwareDesigner_);

        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    public void testManagedType_variantCases() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);
            MappedSuperclassTypeImpl<Person> msPerson_ = (MappedSuperclassTypeImpl)metamodel.managedType(Person.class);
            assertNotNull(msPerson_);
            MappedSuperclassTypeImpl<Corporation> msCorporation_ = (MappedSuperclassTypeImpl)metamodel.managedType(Corporation.class);
            assertNotNull(msCorporation_);
            EntityTypeImpl<GalacticPosition> entityLocation_ =(EntityTypeImpl) metamodel.entity(GalacticPosition.class);
            assertNotNull(entityLocation_);
            EntityTypeImpl<Computer> entityComputer_ = (EntityTypeImpl)metamodel.entity(Computer.class);
            assertNotNull(entityComputer_);
            EntityTypeImpl<HardwareDesigner> entityHardwareDesigner_ = (EntityTypeImpl)metamodel.entity(HardwareDesigner.class);
            assertNotNull(entityHardwareDesigner_);
            EntityTypeImpl<Memory> entityMemory_ = (EntityTypeImpl)metamodel.entity(Memory.class);
            assertNotNull(entityMemory_);

            // Actual Test Case
            // try a getAttribute on a missing attribute - should cause an IAE
            boolean iae1thrown = false;
        try {
            entityManufacturer_.getAttribute("_unknownAttribute");
        } catch (IllegalArgumentException expectedIAE) {
            // java.lang.IllegalArgumentException: The attribute [_unknownAttribute] from the managed type [ManagedTypeImpl[RelationalDescriptor(org.eclipse.persistence.testing.models.jpa.metamodel.Manufacturer --> [DatabaseTable(CMP3_MM_MANUF)])]] is not present.
            iae1thrown = true;
            }
            // verify that we got an expected exception
            assertTrue("Expected thrown IllegalArgumentException", iae1thrown);

            // try a getSet on an unknown Set attribute - should still cause a IAE
            iae1thrown = false;
        try {
            entityManufacturer_.getSet("_unknownAttribute");
        } catch (IllegalArgumentException expectedIAE) {
            // java.lang.IllegalArgumentException: The attribute [_unknownAttribute] from the managed type [ManagedTypeImpl[RelationalDescriptor(org.eclipse.persistence.testing.models.jpa.metamodel.Manufacturer --> [DatabaseTable(CMP3_MM_MANUF)])]] is not present.
            iae1thrown = true;
            }
            // verify that we got an expected exception
            assertTrue("Expected thrown IllegalArgumentException", iae1thrown);

            // try a getSet on an unknown Set attribute - but with the right type (but how do we really know the type) - should still cause the same IAE
            iae1thrown = false;
        try {
            entityManufacturer_.getSet("_unknownSet", entityComputer_.getJavaType());
        } catch (IllegalArgumentException expectedIAE) {
            // java.lang.IllegalArgumentException: The attribute [_unknownSet] from the managed type [ManagedTypeImpl[RelationalDescriptor(org.eclipse.persistence.testing.models.jpa.metamodel.Manufacturer --> [DatabaseTable(CMP3_MM_MANUF)])]] is not present.
            iae1thrown = true;
            }
            // verify that we got an expected exception
            assertTrue("Expected thrown IllegalArgumentException", iae1thrown);

            // try a getSet on a known Set attribute - but with the wrong type like another EntityType Memory - should cause a different IAE
            iae1thrown = false;
        try {
            entityManufacturer_.getSet("computers", entityMemory_.getJavaType());
        } catch (IllegalArgumentException expectedIAE) {
            //expectedIAE.printStackTrace();
            //java.lang.IllegalArgumentException: Expected attribute type [class org.eclipse.persistence.testing.models.jpa.metamodel.Memory] on the existing attribute [computers] on the managed type [ManagedTypeImpl[RelationalDescriptor(org.eclipse.persistence.testing.models.jpa.metamodel.Manufacturer --> [DatabaseTable(CMP3_MM_MANUF)])]] but found attribute type [org.eclipse.persistence.testing.models.jpa.metamodel.Computer].
            iae1thrown = true;
        } catch (Exception unexpectedException) {
            unexpectedException.printStackTrace();
            }
            // verify that we got an expected exception
            assertTrue("Expected thrown IllegalArgumentException", iae1thrown);

            expectedIAExceptionThrown = false;
        try {
            // Ask for a Collection using a String type - invalid
            entityManufacturer_.getDeclaredCollection("name", String.class);
        } catch (Exception e) {
            // This exception is expected here
            expectedIAExceptionThrown = true;
            }
            assertTrue("Expected thrown IllegalArgumentException", expectedIAExceptionThrown);
            // reset exception flag
            expectedIAExceptionThrown = false;

            // get Mapped Superclass objects
            //Map<Class, MappedSuperclassTypeImpl<?>> mappedSuperclasses = ((MetamodelImpl)metamodel).getMappedSuperclasses();
            Set<MappedSuperclassTypeImpl<?>> mappedSuperclasses = ((MetamodelImpl)metamodel).getMappedSuperclasses();
            int count = 0;
            for (MappedSuperclassTypeImpl msType_ : mappedSuperclasses) {
                ClassDescriptor descriptor = msType_.getDescriptor();
                for (DatabaseMapping mapping : descriptor.getMappings()) {
                    count++;
                }
            }

            // we should have had a non-zero number of mappings on the descriptors
            if(count < 1) {
            fail("No mappedSuperclass mappings were found");
            }
            assertTrue(count > 0);

        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    /**
     * This test will verify that MapAttribute instance have their elementType set correctly.
     * The elementType corresponds to the 3rd V parameter on the class definition - which is the Map value.
     * {@code MapAttributeImpl<X, K, V>}
     */
    public void testMapAtributeElementTypeWhenMapKeySetButNameAttributeIsDefaulted() {
        boolean exceptionThrown = false;
        EntityManager em = null;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);

            EntityType<Manufacturer> entityManufacturer = metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer);
            Attribute hardwareDesignersMap = entityManufacturer.getAttribute("hardwareDesignersMapUC8");
            assertNotNull(hardwareDesignersMap);
            assertTrue(hardwareDesignersMap.isCollection());
            assertTrue(hardwareDesignersMap instanceof MapAttributeImpl);
            MapAttribute<? super Manufacturer, ?, ?> manufactuerHardwareDesignersMap = entityManufacturer.getMap("hardwareDesignersMapUC8");
            // Verify owning type
            assertNotNull(manufactuerHardwareDesignersMap);
            assertEquals(entityManufacturer, manufactuerHardwareDesignersMap.getDeclaringType());
            // Verify Map Key - should be PK of owning type
            assertEquals(Integer.class, manufactuerHardwareDesignersMap.getKeyJavaType());
            // Verify Map Value
            assertEquals(HardwareDesigner.class, manufactuerHardwareDesignersMap.getElementType().getJavaType());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    public void testMapAtributeElementTypeWhenMapKeySetAndNameAttributeSet() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);

            EntityType<Manufacturer> entityManufacturer = metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer);
            Attribute hardwareDesignersMap = entityManufacturer.getAttribute("hardwareDesignersMapUC4");
            assertNotNull(hardwareDesignersMap);
            assertTrue(hardwareDesignersMap.isCollection());
            assertTrue(hardwareDesignersMap instanceof MapAttributeImpl);
            MapAttribute<? super Manufacturer, ?, ?> manufactuerHardwareDesignersMap = entityManufacturer.getMap("hardwareDesignersMapUC4");
            // Verify owning type
            assertNotNull(manufactuerHardwareDesignersMap);
            assertEquals(entityManufacturer, manufactuerHardwareDesignersMap.getDeclaringType());
            // Verify Map Key - should not be PK of owning type
            assertEquals(String.class, manufactuerHardwareDesignersMap.getKeyJavaType());
            // Verify Map Value
            assertEquals(HardwareDesigner.class, manufactuerHardwareDesignersMap.getElementType().getJavaType());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    public void testMapAttribute_getKeyJavaType_UC0_Method() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);

            // Actual Test Case
            /**
             * Return the Java type of the map key.
             * @return Java key type
             */
            //Class<K> getKeyJavaType();
            MapAttribute<? super Manufacturer, ?, ?> anAttribute =
            entityManufacturer_.getMap("hardwareDesignersMap");
            // verify the default key type is the not the Map key - rather that is is the managedType PK
            Class<?> keyJavaType = anAttribute.getKeyJavaType();
            //@OneToMany(cascade=ALL, mappedBy="mappedEmployer")
            //private Map<String, HardwareDesigner> hardwareDesignersMap;// = new HashMap<String, HardwareDesigner>();
            // http://wiki.eclipse.org/EclipseLink/Development/JPA_2.0/metamodel_api#DI_63:_20090824:_Add_Map_support_for_.40MapKey_to_MapAttribute
            // Key is the primary key (PK) of the target entity - in this case HardwareDesigner which inherits its @Id from the Person @MappedSuperclass as '''Integer'''.
            Type keyType = anAttribute.getKeyType();
            assertEquals(String.class, keyJavaType); // When @MapKey(name="name") is present - or generics are set
            assertNotNull(keyType);
            assertTrue(keyType instanceof Type);
            assertEquals(Type.PersistenceType.BASIC, keyType.getPersistenceType());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    public void testMapAttribute_getKeyJavaType_UC1a_Method() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);

            // Actual Test Case
            /**
             * Return the Java type of the map key.
             * @return Java key type
             */
            //Class<K> getKeyJavaType();
            MapAttribute<? super Manufacturer, ?, ?> anAttribute =
            entityManufacturer_.getMap("hardwareDesignersMapUC1a");
            // verify the key type is the Map key - not the managedType PK
            Class<?> keyJavaType = anAttribute.getKeyJavaType();
            // UC 1a: Generics KV set, no @MapKey present, PK is singular field
            //@OneToMany(cascade=ALL, mappedBy="mappedEmployerUC1a")
            //private Map<String, HardwareDesigner> hardwareDesignersMapUC1a;
            Type keyType = anAttribute.getKeyType();
            assertEquals(String.class, keyJavaType); // When @MapKey(name="name") is present - or generics are set
            assertNotNull(keyType);
            assertTrue(keyType instanceof Type);
            assertEquals(Type.PersistenceType.BASIC, keyType.getPersistenceType());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    public void testMapAttribute_getKeyJavaType_UC2_Method() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);

            // Actual Test Case
            /**
             * Return the Java type of the map key.
             * @return Java key type
             */
            //Class<K> getKeyJavaType();
            MapAttribute<? super Manufacturer, ?, ?> anAttribute =
            entityManufacturer_.getMap("hardwareDesignersMapUC2");
            // verify the key type is the Map key - not the managedType PK
            Class<?> keyJavaType = anAttribute.getKeyJavaType();
            // UC 2: Generics KV set, @MapKey is present
            //@OneToMany(cascade=ALL, mappedBy="mappedEmployerUC2")
            //@MapKey(name="name")
            //private Map<String, HardwareDesigner> hardwareDesignersMapUC2;
            Type keyType = anAttribute.getKeyType();
            assertEquals(String.class, keyJavaType); // When @MapKey(name="name") is present
            assertNotNull(keyType);
            assertTrue(keyType instanceof Type);
            assertEquals(Type.PersistenceType.BASIC, keyType.getPersistenceType());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    public void testMapAttribute_getKeyJavaType_UC4_Method() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);

            // Actual Test Case
            /**
             * Return the Java type of the map key.
             * @return Java key type
             */
            //Class<K> getKeyJavaType();
            MapAttribute<? super Manufacturer, ?, ?> anAttribute =
            entityManufacturer_.getMap("hardwareDesignersMapUC4");
            // verify the key type is the Map key - not the managedType PK
            Class<?> keyJavaType = anAttribute.getKeyJavaType();
            // UC 4: No Generics KV set, @MapKey is present
            //@OneToMany(targetEntity=HardwareDesigner.class, cascade=ALL, mappedBy="mappedEmployerUC4")
            //@MapKey(name="name")
            //private Map hardwareDesignersMapUC4;
            Type keyType = anAttribute.getKeyType();
            assertEquals(String.class, keyJavaType); // When @MapKey(name="name") is present
            assertNotNull(keyType);
            assertTrue(keyType instanceof Type);
            assertEquals(Type.PersistenceType.BASIC, keyType.getPersistenceType());

        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    public void testMapAttribute_getKeyJavaType_UC7_Method() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);

            // Actual Test Case
            /**
             * Return the Java type of the map key.
             * @return Java key type
             */
            //Class<K> getKeyJavaType();
            MapAttribute<? super Manufacturer, ?, ?> anAttribute =
            entityManufacturer_.getMap("hardwareDesignersMapUC7");
            // verify the key type is the Map key - not the managedType PK
            Class<?> keyJavaType = anAttribute.getKeyJavaType();
            // UC 7: Generics KV set, targetEntity is also set, @MapKey is *(set/unset)
            //@OneToMany(targetEntity=HardwareDesigner.class, cascade=ALL, mappedBy="mappedEmployerUC7")
            // Same as UC1a - that is missing the @MapKey
            //private Map<String, HardwareDesigner> hardwareDesignersMapUC7;
            Type keyType = anAttribute.getKeyType();
            assertEquals(String.class, keyJavaType); // When @MapKey(name="name") is present - or generics are set
            assertNotNull(keyType);
            assertTrue(keyType instanceof Type);
            assertEquals(Type.PersistenceType.BASIC, keyType.getPersistenceType());

        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    public void testMapAttribute_getKeyJavaType_UC8_Method() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);

            // Actual Test Case
            /**
             * Return the Java type of the map key.
             * @return Java key type
             */
            //Class<K> getKeyJavaType();
            MapAttribute<? super Manufacturer, ?, ?> anAttribute =
            entityManufacturer_.getMap("hardwareDesignersMapUC8");
            // verify the key type is the Map key - not the managedType PK
            Class<?> keyJavaType = anAttribute.getKeyJavaType();
            // UC 8: Generics KV set, targetEntity not set, @MapKey is set but name attribute is defaulted
            //@OneToMany(targetEntity=HardwareDesigner.class, cascade=ALL, mappedBy="mappedEmployerUC8")
            // Same as UC1a - that is missing the @MapKey name attribute
            //private Map<String, HardwareDesigner> hardwareDesignersMapUC8;
            Type keyType = anAttribute.getKeyType();
            assertEquals(Integer.class, keyJavaType); // When @MapKey or generics are not present - we default to the PK
            assertNotNull(keyType);
            assertTrue(keyType instanceof Type);
            assertEquals(Type.PersistenceType.BASIC, keyType.getPersistenceType());

        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    // See
    // http://wiki.eclipse.org/EclipseLink/Development/JPA_2.0/metamodel_api#DI_86:_20090921:_Handle_Embeddable_Type_keyType_in_MapAttributeImpl_constructor
    public void testMapAttribute_getKeyJavaType_UC9_DI86_Embeddable_IdClass_keyType_Method() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);

            // Actual Test Case
            /**
             * Return the Java type of the map key.
             * @return Java key type
             */
            //Class<K> getKeyJavaType();
            MapAttribute<? super Manufacturer, ?, ?> anAttribute =
            entityManufacturer_.getMap("enclosureByBoardMapUC9");
            // verify the key type is the Map key - not the managedType PK
            Class<?> keyJavaType = anAttribute.getKeyJavaType();
            // UC9: no targetEntity, no MapKey, but generics are set (MapKey has an IdClass with an Embeddable)
            //@OneToMany(cascade=CascadeType.ALL, mappedBy="mappedManufacturerUC9")
            //private Map<Board, Enclosure> enclosureByBoardMapUC9;
            Type keyType = anAttribute.getKeyType();
            assertEquals(Board.class, keyJavaType); // When @MapKey(name="name") is present or we use generics
            assertNotNull(keyType);
            assertTrue(keyType instanceof Type);
            assertEquals(Type.PersistenceType.ENTITY, keyType.getPersistenceType());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    public void testMapAttribute_getKeyType_UC0_Method() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);

            // Actual Test Case
            /**
             * Return the type representing the key type of the map.
             * @return type representing key type
             */
            //Type<K> getKeyType();
            MapAttribute<? super Manufacturer, ?, ?> anAttribute =
            entityManufacturer_.getMap("hardwareDesignersMap");
            // verify the default key type is the not the Map key - rather that is is the managedType PK
            Class<?> keyJavaType = anAttribute.getKeyJavaType();
            //@OneToMany(cascade=ALL, mappedBy="mappedEmployer")
            //private Map<String, HardwareDesigner> hardwareDesignersMap;// = new HashMap<String, HardwareDesigner>();
            // http://wiki.eclipse.org/EclipseLink/Development/JPA_2.0/metamodel_api#DI_63:_20090824:_Add_Map_support_for_.40MapKey_to_MapAttribute
            // Key is the primary key (PK) of the target entity - in this case HardwareDesigner which inherits its @Id from the Person @MappedSuperclass as '''Integer'''.
            Type keyType = anAttribute.getKeyType();
            assertEquals(String.class, keyJavaType); // When @MapKey(name="name") is present - or generics are set
            assertNotNull(keyType);
            assertTrue(keyType instanceof Type);
            assertEquals(Type.PersistenceType.BASIC, keyType.getPersistenceType());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    public void testMapAttribute_getKeyType_UC1a_Method() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);

            // Actual Test Case
            /**
             * Return the type representing the key type of the map.
             * @return type representing key type
             */
            //Type<K> getKeyType();
            MapAttribute<? super Manufacturer, ?, ?> anAttribute =
            entityManufacturer_.getMap("hardwareDesignersMapUC1a");
            // verify the key type is the Map key - not the managedType PK
            Class<?> keyJavaType = anAttribute.getKeyJavaType();
            // UC 1a: Generics KV set, no @MapKey present, PK is singular field
            //@OneToMany(cascade=ALL, mappedBy="mappedEmployerUC1a")
            //private Map<String, HardwareDesigner> hardwareDesignersMapUC1a;
            Type keyType = anAttribute.getKeyType();
            assertEquals(String.class, keyJavaType); // When @MapKey(name="name") is present - or generics are set
            assertNotNull(keyType);
            assertTrue(keyType instanceof Type);
            assertEquals(Type.PersistenceType.BASIC, keyType.getPersistenceType());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    public void testMapAttribute_getKeyType_UC2_Method() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);

            // Actual Test Case
            /**
             * Return the type representing the key type of the map.
             * @return type representing key type
             */
            //Type<K> getKeyType();
            MapAttribute<? super Manufacturer, ?, ?> anAttribute =
            entityManufacturer_.getMap("hardwareDesignersMapUC2");
            // verify the key type is the Map key - not the managedType PK
            Class<?> keyJavaType = anAttribute.getKeyJavaType();
            // UC 2: Generics KV set, @MapKey is present
            //@OneToMany(cascade=ALL, mappedBy="mappedEmployerUC2")
            //@MapKey(name="name")
            //private Map<String, HardwareDesigner> hardwareDesignersMapUC2;
            Type keyType = anAttribute.getKeyType();
            assertEquals(String.class, keyJavaType); // When @MapKey(name="name") is present
            assertNotNull(keyType);
            assertTrue(keyType instanceof Type);
            assertEquals(Type.PersistenceType.BASIC, keyType.getPersistenceType());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    public void testMapAttribute_getKeyType_UC4_Method() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);

            // Actual Test Case
            /**
             * Return the type representing the key type of the map.
             * @return type representing key type
             */
            //Type<K> getKeyType();
            MapAttribute<? super Manufacturer, ?, ?> anAttribute =
            entityManufacturer_.getMap("hardwareDesignersMapUC4");
            // verify the key type is the Map key - not the managedType PK
            Class<?> keyJavaType = anAttribute.getKeyJavaType();
            // UC 4: No Generics KV set, @MapKey is present
            //@OneToMany(targetEntity=HardwareDesigner.class, cascade=ALL, mappedBy="mappedEmployerUC4")
            //@MapKey(name="name")
            //private Map hardwareDesignersMapUC4;
            Type keyType = anAttribute.getKeyType();
            assertEquals(String.class, keyJavaType); // When @MapKey(name="name") is present
            assertNotNull(keyType);
            assertTrue(keyType instanceof Type);
            assertEquals(Type.PersistenceType.BASIC, keyType.getPersistenceType());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    public void testMapAttribute_getKeyType_UC7_Method() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);

            // Actual Test Case
            /**
             * Return the type representing the key type of the map.
             * @return type representing key type
             */
            //Type<K> getKeyType();
            MapAttribute<? super Manufacturer, ?, ?> anAttribute =
            entityManufacturer_.getMap("hardwareDesignersMapUC7");
            // verify the key type is the Map key - not the managedType PK
            Class<?> keyJavaType = anAttribute.getKeyJavaType();
            // UC 7: Generics KV set, targetEntity is also set, @MapKey is *(set/unset)
            //@OneToMany(targetEntity=HardwareDesigner.class, cascade=ALL, mappedBy="mappedEmployerUC7")
            // Same as UC1a - that is missing the @MapKey
            //private Map<String, HardwareDesigner> hardwareDesignersMapUC7;
            Type keyType = anAttribute.getKeyType();
            assertEquals(String.class, keyJavaType); // When @MapKey(name="name") is present - or generics are set
            assertNotNull(keyType);
            assertTrue(keyType instanceof Type);
            assertEquals(Type.PersistenceType.BASIC, keyType.getPersistenceType());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    public void testMapAttribute_getKeyType_UC8_Method() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);

            // Actual Test Case
            /**
             * Return the type representing the key type of the map.
             * @return type representing key type
             */
            //Type<K> getKeyType();
            MapAttribute<? super Manufacturer, ?, ?> anAttribute =
            entityManufacturer_.getMap("hardwareDesignersMapUC8");
            // verify the key type is the Map key - not the managedType PK
            Class<?> keyJavaType = anAttribute.getKeyJavaType();
            // UC 8: Generics KV set, targetEntity not set, @MapKey is set but name attribute is defaulted
            //@OneToMany(targetEntity=HardwareDesigner.class, cascade=ALL, mappedBy="mappedEmployerUC8")
            // Same as UC1a - that is missing the @MapKey name attribute
            //private Map<String, HardwareDesigner> hardwareDesignersMapUC8;
            Type keyType = anAttribute.getKeyType();
            assertEquals(Integer.class, keyJavaType); // When @MapKey is not present or missing name attribute - we default to the PK
            assertNotNull(keyType);
            assertTrue(keyType instanceof Type);
            assertEquals(Type.PersistenceType.BASIC, keyType.getPersistenceType());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    // see
    // http://wiki.eclipse.org/EclipseLink/Development/JPA_2.0/metamodel_api#DI_86:_20090921:_Handle_Embeddable_Type_keyType_in_MapAttributeImpl_constructor
    public void testMapAttribute_getKeyType_UC9_DI86_Embeddable_IdClass_keyType_Method() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);

            // Actual Test Case
            /**
             * Return the type representing the key type of the map.
             * @return type representing key type
             */
            //Type<K> getKeyType();
            MapAttribute<? super Manufacturer, ?, ?> anAttribute =
            entityManufacturer_.getMap("enclosureByBoardMapUC9");
            // verify the key type is the Map key - not the managedType PK
            Class<?> keyJavaType = anAttribute.getKeyJavaType();
            // UC9: no targetEntity, no MapKey, but generics are set (MapKey has an IdClass with an Embeddable)
            //@OneToMany(cascade=CascadeType.ALL, mappedBy="mappedManufacturerUC9")
            //private Map<Board, Enclosure> enclosureByBoardMapUC9;
            Type keyType = anAttribute.getKeyType();
            assertEquals(Board.class, keyJavaType); // When @MapKey(name="name") is present or we use generics
            assertNotNull(keyType);
            assertTrue(keyType instanceof Type);
            assertEquals(Type.PersistenceType.ENTITY, keyType.getPersistenceType());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    // This test verifies the workaround for 294811
    public void testMapAttribute_getKeyType_294811_UC10_DI86_Embeddable_IdClass_keyType_Method() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Computer> entityComputer_ = (EntityTypeImpl)metamodel.entity(Computer.class);
            assertNotNull(entityComputer_);

            // Actual Test Case
            /**
             * Return the type representing the key type of the map.
             * @return type representing key type
             */
            //Type<K> getKeyType();
            MapAttribute<? super Computer, ?, ?> anAttribute =
            entityComputer_.getMap("enclosuresUC10");
            // verify the key type is the Map key - not the managedType PK
            Class<?> keyJavaType = anAttribute.getKeyJavaType();
            // UC10: no targetEntity, no MapKey attribute, but generics are set (MapKey has an IdClass with an Embeddable)
            //@OneToMany(mappedBy="computerUC10", cascade=ALL, fetch=EAGER)
            //@MapKey // key defaults to an instance of the composite pk class
            //private Map<EnclosureIdClassPK, Enclosure> enclosuresUC10;
            Type keyType = anAttribute.getKeyType();
            assertEquals(EnclosureIdClassPK.class, keyJavaType); // When @MapKey(name="name") is present or we use generics
            assertNotNull(keyType);
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    // This test verifies the workaround for 294811
    public void testMapAttribute_getKeyType_294811_UC13_DI86_Embedded_keyType_Method() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Computer> entityComputer_ = (EntityTypeImpl)metamodel.entity(Computer.class);
            assertNotNull(entityComputer_);

            // Actual Test Case
            /**
             * Return the type representing the key type of the map.
             * @return type representing key type
             */
            //Type<K> getKeyType();
            MapAttribute<? super Computer, ?, ?> anAttribute =
            entityComputer_.getMap("positionUniUC13");
            // verify the key type is the Map key - not the managedType PK
            Class<?> keyJavaType = anAttribute.getKeyJavaType();
            // UC13:  mapKey defined via generics and is an Embeddable (EmbeddedId) java class defined as an IdClass on the element(value) class
            // However, here we make the owning OneToMany - unidirectional and an effective ManyToMany
            //@MapKey // key defaults to an instance of the composite pk class
            //private Map<EmbeddedPK, GalacticPosition> positionUniUC13;
            Type keyType = anAttribute.getKeyType();
            assertEquals(EmbeddedPK.class, keyJavaType); // When @MapKey(name="name") is present or we use generics
            assertNotNull(keyType);
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    // This test verifies the workaround for 294811
    public void testMapAttribute_getKeyType_294811_UC12_DI86_Embedded_keyType_Method() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Computer> entityComputer_ = (EntityTypeImpl)metamodel.entity(Computer.class);
            assertNotNull(entityComputer_);

            // Actual Test Case
            /**
             * Return the type representing the key type of the map.
             * @return type representing key type
             */
            //Type<K> getKeyType();
            MapAttribute<? super Computer, ?, ?> anAttribute =
            entityComputer_.getMap("positionUC12");
            // verify the key type is the Map key - not the managedType PK
            Class<?> keyJavaType = anAttribute.getKeyJavaType();
            // UC12:  mapKey defined via generics and is an Embeddable (EmbeddedId) java class defined as an IdClass on the element(value) class
            //@OneToMany(mappedBy="computerUC12", cascade=ALL, fetch=EAGER)
            //@MapKey // key defaults to an instance of the composite pk class
            //private Map<EmbeddedPK, GalacticPosition> positionUC12;
            Type keyType = anAttribute.getKeyType();
            assertEquals(EmbeddedPK.class, keyJavaType); // When @MapKey(name="name") is present or we use generics
            assertNotNull(keyType);
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    // TODO: This is not testing anything?
    public void testMapAttribute_getKeyType_UC9_Method() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);

            // Actual Test Case
            /**
             * Return the type representing the key type of the map.
             * @return type representing key type
             */
            //Type<K> getKeyType();

        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    // TODO: This is not testing anything?
    public void testMappedSuperclassType() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);

            // Actual Test Case
            // Interface is empty - however we will test native functionality

        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    public void testMetamodel_managedType_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);

            // Actual Test Case
            /**
             *  Return the metamodel managed type representing the
             *  entity, mapped superclass, or embeddable class.
             *  @param cls  the type of the represented managed class
             *  @return the metamodel managed type
             *  @throws IllegalArgumentException if not a managed class
             */
            //<X> ManagedType<X> managedType(Class<X> cls);
            // test normal path (subtype = Basic)
    /*            expectedIAExceptionThrown = false;
        try {
            Type<Manufacturer> aType = metamodel.type(Basic.class);
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
            }
            assertFalse(expectedIAExceptionThrown);
    */
            // test normal path (subtype = Embeddable)
            expectedIAExceptionThrown = false;
        try {
            Type<EmbeddedPK> aType = metamodel.managedType(EmbeddedPK.class);
            assertFalse(((TypeImpl)aType).isEntity());
            assertFalse(((TypeImpl)aType).isMappedSuperclass());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
            }
            assertFalse(expectedIAExceptionThrown);

            // test normal path: (subtype = Entity)
            expectedIAExceptionThrown = false;
        try {
            Type<Manufacturer> aType = metamodel.managedType(Manufacturer.class);
            assertTrue(((TypeImpl)aType).isEntity());
            assertFalse(((TypeImpl)aType).isMappedSuperclass());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
            }
            assertFalse(expectedIAExceptionThrown);

            // test normal path: (subtype = MappedSuperclass)
            expectedIAExceptionThrown = false;
        try {
            Type<Person> aType = metamodel.managedType(Person.class);
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
            }
            assertFalse(expectedIAExceptionThrown);

            // test variant path: null does not cause an IAE in this case because its return type cannot be checked for isManagedType
            expectedIAExceptionThrown = false;
            // Set type to a temporary type - to verify that we get null and not confuse a return of null with an "unset" null.
            Type<?> aTypeFromNullClass = metamodel.managedType(Manufacturer.class);
        try {
            aTypeFromNullClass = metamodel.managedType(null);
        } catch (IllegalArgumentException iae) {
            //iae.printStackTrace();
            expectedIAExceptionThrown = true;
            }
            //assertNull(aTypeFromNullClass);
            assertTrue("IllegalArgumentException expected on Metamodel.managedType(null)",expectedIAExceptionThrown);

            // Type is basic - throw IAE
            expectedIAExceptionThrown = false;
        try {
            Type<Integer> aType = metamodel.managedType(Integer.class);
        } catch (IllegalArgumentException iae) {
            //iae.printStackTrace();
            expectedIAExceptionThrown = true;
            }
            assertTrue("IllegalArgumentException expected on Metamodel.managedType(Integer.class)",expectedIAExceptionThrown);

            // test variant path: wrong type (java simple type)
            expectedIAExceptionThrown = false;
        try {
            Type<?> aType = metamodel.embeddable(Integer.class);
        } catch (IllegalArgumentException iae) {
            //iae.printStackTrace();
            expectedIAExceptionThrown = true;
            }
            assertTrue(expectedIAExceptionThrown);
            // reset exception flag
            expectedIAExceptionThrown = false;

            // test variant path: wrong type (BasicType)


            // get some static (non-runtime) attributes parameterized by <Owning type, return Type>
            // Note: the String based attribute names are non type-safe
            /*
            aMember CollectionAttributeImpl<X,E>  (id=183)
             elementType BasicImpl<X>  (id=188)
            javaClass   Class<T> (org.eclipse.persistence.testing.models.jpa.metamodel.Computer) (id=126)
             managedType EntityTypeImpl<X>  (id=151)
            descriptor  RelationalDescriptor  (id=156)
            javaClass   Class<T> (org.eclipse.persistence.testing.models.jpa.metamodel.Manufacturer) (id=129)
            members HashMap<K,V>  (id=157)
            metamodel   MetamodelImpl  (id=52)
            supertype   null
            mapping OneToManyMapping  (id=191)
            */
            // The attributes are in the field ManagedTypeImpl.members
            // The managedType is the owner of the attribute
            //hardwareDesigners=CollectionAttribute[org.eclipse.persistence.mappings.OneToManyMapping[hardwareDesigners]],
            //computers=CollectionAttribute[org.eclipse.persistence.mappings.OneToManyMapping[computers]],

            // 20090707: We are getting a CCE because "all" Collections are defaulting to List
            // when they are lazy instantiated as IndirectList if persisted as a List independent of what the OneToOne mapping is defined as
//            jakarta.persistence.metamodel.CollectionAttribute<? super Manufacturer, Computer> computersAttribute =
//            entityManufacturer.getCollection("computers", Computer.class);
//            jakarta.persistence.metamodel.CollectionAttribute<? super Manufacturer, Computer> computersAttribute2 =
//            entityManufacturer.getCollection("computers", Computer.class);
            jakarta.persistence.metamodel.SetAttribute<? super Manufacturer, Computer> computersAttribute =
            entityManufacturer_.getSet("computers", Computer.class);

            //version=Attribute[org.eclipse.persistence.mappings.DirectToFieldMapping[version-->CMP3_MM_MANUF.MANUF_VERSION]],
            //name=Attribute[org.eclipse.persistence.mappings.DirectToFieldMapping[name-->CMP3_MM_MANUF.NAME]],
            //id=Attribute[org.eclipse.persistence.mappings.DirectToFieldMapping[id-->CMP3_MM_MANUF.PERSON_ID]]

        } catch (IllegalArgumentException iae) {
            //iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    // TODO: This is not testing anything?
    public void testMetamodel_getEmbeddables_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);

            // Actual Test Case
            /**
             * Return the metamodel embeddable types.
             * @return the metamodel embeddable types
             */
            //java.util.Set<EmbeddableType<?>> getEmbeddables();
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    // TODO: This is not testing anything?
    public void testMetamodel_getEntities_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);

            // Actual Test Case
            /**
             * Return the metamodel entity types.
             * @return the metamodel entity types
             */
            //java.util.Set<EntityType<?>> getEntities();

        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    // TODO: This is not testing anything?
    public void testMetamodel_getManagedTypes_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);

            // Actual Test Case

            /**
             *  Return the metamodel managed types.
             *  @return the metamodel managed types
             */
            //java.util.Set<ManagedType<?>> getManagedTypes();

        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    public void testMetamodel_embeddable_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);

            // Actual Test Case
            /**
             *  Return the metamodel embeddable type representing the
             *  embeddable class.
             *  @param cls  the type of the represented embeddable class
             *  @return the metamodel embeddable type
             *  @throws IllegalArgumentException if not an embeddable class
             */
            //<X> EmbeddableType<X> embeddable(Class<X> cls);
            // test normal path
            expectedIAExceptionThrown = false;
        try {
            EmbeddableType<EmbeddedPK> aType = metamodel.embeddable(EmbeddedPK.class);
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
            }
            assertFalse(expectedIAExceptionThrown);

            // test variant path: null causes IAE
            expectedIAExceptionThrown = false;
        try {
            EmbeddableType<Manufacturer> aType = metamodel.embeddable(null);
        } catch (IllegalArgumentException iae) {
            expectedIAExceptionThrown = true;
            }
            assertTrue("Expected thrown IllegalArgumentException", expectedIAExceptionThrown);

            // test variant path: wrong type (subtype = Entity)
            expectedIAExceptionThrown = false;
        try {
            EmbeddableType<Manufacturer> aType = metamodel.embeddable(Manufacturer.class);
        } catch (IllegalArgumentException iae) {
            expectedIAExceptionThrown = true;
            }
            assertTrue("Expected thrown IllegalArgumentException", expectedIAExceptionThrown);

            // test variant path: wrong type (java simple type)
            expectedIAExceptionThrown = false;
        try {
            EmbeddableType<?> aType = metamodel.embeddable(Integer.class);
        } catch (IllegalArgumentException iae) {
            expectedIAExceptionThrown = true;
            }
            assertTrue("Expected thrown IllegalArgumentException", expectedIAExceptionThrown);
            // reset state
            expectedIAExceptionThrown = false;
        } catch (IllegalArgumentException iae) {
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }


    public void testMetamodel_entity_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);

            // Actual Test Case
            /**
             *  Return the metamodel entity type representing the entity.
             *  @param cls  the type of the represented entity
             *  @return the metamodel entity type
             *  @throws IllegalArgumentException if not an entity
             */
            //<X> EntityType<X> entity(Class<X> cls);
            // test normal path
            expectedIAExceptionThrown = false;
        try {
            EntityType<Manufacturer> aType = metamodel.entity(Manufacturer.class);
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
            }
            assertFalse(expectedIAExceptionThrown);

            // test variant path: null causes IAE
            expectedIAExceptionThrown = false;
        try {
            EntityType<Manufacturer> aType = metamodel.entity(null);
        } catch (IllegalArgumentException iae) {
            expectedIAExceptionThrown = true;
            }
            assertTrue("Expected thrown IllegalArgumentException", expectedIAExceptionThrown);

            // test variant path: wrong type (java simple type)
            expectedIAExceptionThrown = false;
        try {
            EntityType<Integer> aType = metamodel.entity(Integer.class);
        } catch (IllegalArgumentException iae) {
            expectedIAExceptionThrown = true;
            }
            assertTrue("Expected thrown IllegalArgumentException", expectedIAExceptionThrown);
            // reset exception flag
            expectedIAExceptionThrown = false;
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    // TODO: This is not testing anything?
    public void testPluralAttribute_CollectionType_enum() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);

            // Actual Test Case
            //public static enum CollectionType {COLLECTION, SET, LIST, MAP}
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    // TODO: This is not testing anything?
    public void testPluralAttribute_getCollectionType_Method() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);

            // Actual Test Case
            //public static enum CollectionType {COLLECTION, SET, LIST, MAP}

            /**
             * Return the collection type.
             * @return collection type
             */
            //CollectionType getCollectionType();
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    // TODO: This is not testing anything?
    public void testPluralAttribute_getElementType_Method() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);

            // Actual Test Case
            /**
             * Return the type representing the element type of the
             * collection.
             * @return element type
             */
            //Type<E> getElementType();

        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    // TODO: This is not testing anything?
    public void testSetAttribute() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);

            // Actual Test Case
            // The interface is empty - we will test native functionality

        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    public void testSingularAttribute_isOptional_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);
            EntityTypeImpl<HardwareDesigner> entityHardwareDesigner_ = (EntityTypeImpl)metamodel.entity(HardwareDesigner.class);
            assertNotNull(entityHardwareDesigner_);
            // Composite table FK's that include a MappedSuperclass
            // get an Attribute<Container, Type==String>
            Attribute nameAttribute = entityManufacturer_.getAttribute("name");
            assertTrue(null != nameAttribute);

            /**
             *  Can the attribute be null.
             *  @return boolean indicating whether the attribute can
             *          be null
             */
            //boolean isOptional();
            assertFalse(((AttributeImpl)nameAttribute).isPlural());
            assertFalse(((SingularAttributeImpl)nameAttribute).isVersion());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    public void testSingularAttribute_isId_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);
            EntityTypeImpl<HardwareDesigner> entityHardwareDesigner_ = (EntityTypeImpl)metamodel.entity(HardwareDesigner.class);
            assertNotNull(entityHardwareDesigner_);
            // Composite table FK's that include a MappedSuperclass
            // get an Attribute<Container, Type==String>
            Attribute nameAttribute = entityManufacturer_.getAttribute("name");
            assertTrue(null != nameAttribute);

            /**
             *  Is the attribute an id attribute.  This method will return
             *  true if the attribute is an attribute that corresponds to
             *  a simple id, an embedded id, or an attribute of an id class.
             *  @return boolean indicating whether the attribute is an id
             */
            //boolean isId();
            assertFalse(((AttributeImpl)nameAttribute).isPlural());
            assertFalse(((SingularAttributeImpl)nameAttribute).isVersion());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    public void testSingularAttribute_isVersion_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);
            EntityTypeImpl<HardwareDesigner> entityHardwareDesigner_ = (EntityTypeImpl)metamodel.entity(HardwareDesigner.class);
            assertNotNull(entityHardwareDesigner_);
            // Composite table FK's that include a MappedSuperclass
            // get an Attribute<Container, Type==String>
            Attribute nameAttribute = entityManufacturer_.getAttribute("name");
            assertTrue(null != nameAttribute);

            /**
             *  Is the attribute a version attribute.
             *  @return boolean indicating whether or not attribute is
             *          a version attribute
             */
            //public boolean isVersion() {
            assertFalse(((AttributeImpl)nameAttribute).isPlural());
            assertFalse(((SingularAttributeImpl)nameAttribute).isVersion());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    // TODO: This is not testing anything?
    public void testSingularAttribute_getBindableType_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            //public static enum BindableType {SINGULAR_ATTRIBUTE, PLURAL_ATTRIBUTE, ENTITY_TYPE}

            /**
             *  Return the bindable type of the represented object.
             *  @return bindable type
             */
            //BindableType getBindableType();
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    // Same as Entity unless used on Basic
    public void testSingularAttribute_getBindableJavaType_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<GalacticPosition> entityLocation_ = (EntityTypeImpl) metamodel.entity(GalacticPosition.class);
            assertNotNull(entityLocation_);
            EntityTypeImpl<Computer> entityComputer_ = (EntityTypeImpl)metamodel.entity(Computer.class);
            assertNotNull(entityComputer_);

            /**
             * Return the Java type of the represented object.
             * If the bindable type of the object is <code>PLURAL_ATTRIBUTE</code>,
             * the Java element type is returned. If the bindable type is
             * <code>SINGULAR_ATTRIBUTE</code> or <code>ENTITY_TYPE</code>,
             * the Java type of the
             * represented entity or attribute is returned.
             * @return Java type
             */
            //Class<T> getBindableJavaType();
            Attribute anAttribute = entityComputer_.getSingularAttribute("location");
            assertNotNull(anAttribute);
            assertEquals(PersistentAttributeType.ONE_TO_ONE, anAttribute.getPersistentAttributeType());
            assertFalse(((AttributeImpl)anAttribute).isPlural());
            assertTrue(anAttribute instanceof SingularAttribute);
            assertEquals(Type.PersistenceType.ENTITY, entityComputer_.getPersistenceType());
            Bindable aSingularAttribute = entityComputer_.getSingularAttribute("location");
            assertEquals(GalacticPosition.class, aSingularAttribute.getBindableJavaType());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    // same as Singular unless used on Basic
    public void testEntityAttribute_getBindableJavaType_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            EntityTypeImpl<GalacticPosition> entityLocation_ = (EntityTypeImpl) metamodel.entity(GalacticPosition.class);
            assertNotNull(entityLocation_);
            EntityTypeImpl<Computer> entityComputer_ = (EntityTypeImpl)metamodel.entity(Computer.class);
            assertNotNull(entityComputer_);

            /**
             * Return the Java type of the represented object.
             * If the bindable type of the object is <code>PLURAL_ATTRIBUTE</code>,
             * the Java element type is returned. If the bindable type is
             * <code>SINGULAR_ATTRIBUTE</code> or <code>ENTITY_TYPE</code>,
             * the Java type of the
             * represented entity or attribute is returned.
             * @return Java type
             */
            //Class<T> getBindableJavaType();
            Attribute anAttribute = entityComputer_.getSingularAttribute("location");
            assertNotNull(anAttribute);
            assertEquals(PersistentAttributeType.ONE_TO_ONE, anAttribute.getPersistentAttributeType());
            assertFalse(((AttributeImpl)anAttribute).isPlural());
            assertTrue(anAttribute instanceof SingularAttribute);
            assertEquals(Type.PersistenceType.ENTITY, entityComputer_.getPersistenceType());
            Bindable aSingularAttribute = entityComputer_.getSingularAttribute("location");
            assertEquals(GalacticPosition.class, aSingularAttribute.getBindableJavaType());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    public void testPluralAttribute_getBindableJavaType_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            /**
             * Return the Java type of the represented object.
             * If the bindable type of the object is <code>PLURAL_ATTRIBUTE</code>,
             * the Java element type is returned. If the bindable type is
             * <code>SINGULAR_ATTRIBUTE</code> or <code>ENTITY_TYPE</code>,
             * the Java type of the
             * represented entity or attribute is returned.
             * @return Java type
             */
            //Class<T> getBindableJavaType();
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);
            assertEquals(Type.PersistenceType.ENTITY, entityManufacturer_.getPersistenceType());
            Attribute anAttribute = entityManufacturer_.getAttribute("computers");
            assertEquals(PersistentAttributeType.ONE_TO_MANY, anAttribute.getPersistentAttributeType());
            assertNotNull(anAttribute);
            assertTrue(((AttributeImpl)anAttribute).isPlural());
            assertTrue(anAttribute instanceof PluralAttribute);
            Bindable aPluralAttribute = entityManufacturer_.getSet("computers");
            assertEquals(Computer.class, aPluralAttribute.getBindableJavaType());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    // TODO: This is not testing anything?
    public void testSingularAttribute_getJavaType_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            /**
             *  Return the Java type of the represented attribute.
             *  @return Java type
             */
            //public Class<T> getJavaType() {
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    // TODO: This is not testing anything?
    public void testSingularAttribute_getType_Method() {
        EntityManager em = null;
        boolean expectedIAExceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);

            /**
             * Return the type that represents the type of the attribute.
             * @return type of attribute
             */
             //public Type<T> getType() {

            /**
             * Return the String representation of the receiver.
             */
            //public String toString() {

        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            expectedIAExceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", expectedIAExceptionThrown);
        }
    }

    // TODO: This is not testing anything?
    public void testType_PersistenceType_enum() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);

            // Actual Test Case
            //public static enum PersistenceType { ENTITY,  EMBEDDABLE, MAPPED_SUPERCLASS, BASIC }

             /**
              *  Return the persistence type.
              *  @return persistence type
              */
             //PersistenceType getPersistenceType();

        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    // TODO: This is not testing anything?
    public void testType_getPersistenceType_Method() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);

            // Actual Test Case
            //public static enum PersistenceType { ENTITY,  EMBEDDABLE, MAPPED_SUPERCLASS, BASIC }

             /**
              *  Return the persistence type.
              *  @return persistence type
              */
             //PersistenceType getPersistenceType();

             /**
              *  Return the represented Java type.
              *  @return Java type
              */
             //Class<X> getJavaType();
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    // TODO: This is not testing anything?
    public void testType_getJavaType_Method() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);

            // Actual Test Case
            //public static enum PersistenceType { ENTITY,  EMBEDDABLE, MAPPED_SUPERCLASS, BASIC }
             /**
              *  Return the represented Java type.
              *  @return Java type
              */
             //Class<X> getJavaType();
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    public void testOutOfSpecificationInternalAPI() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull(metamodel);

            // Actual Test Case
            EntityTypeImpl<ArrayProcessor> entityArrayProcessor_ =(EntityTypeImpl) metamodel.entity(ArrayProcessor.class);
            assertNotNull(entityArrayProcessor_);
            EntityTypeImpl<Processor> entityProcessor_ = (EntityTypeImpl) metamodel.entity(Processor.class);
            assertNotNull(entityProcessor_);

            // verify all Types have their javaClass set
            Collection<TypeImpl<?>> types = ((MetamodelImpl)metamodel).getTypes().values();
            assertNotNull(types);
            for(TypeImpl type : types) {
            assertNotNull(type);
            assertNotNull(type.getJavaType());
            }

            // verify all embeddables are only embeddables
            Set<EmbeddableType<?>> embeddables = metamodel.getEmbeddables();
            assertNotNull(embeddables);
            for(EmbeddableType embeddable : embeddables) {
            // This method works only on EntityType
            assertNotNull(embeddable);
            assertTrue(embeddable instanceof EmbeddableTypeImpl);
            }

            // verify all entities are only entities
            Set<EntityType<?>> entities = metamodel.getEntities();
            assertNotNull(entities);
            for(EntityType entity : entities) {
            // This method works only on EntityType
            assertNotNull(entity.getName());
            assertTrue(entity instanceof EntityTypeImpl);
            }

            // Verify all Attributes and their element and declaring/managed types
            List<Attribute> allAttributes = ((MetamodelImpl)metamodel).getAllManagedTypeAttributes();
            assertNotNull(allAttributes);
            assertEquals(METAMODEL_ALL_ATTRIBUTES_SIZE, allAttributes.size());
            // Why do we have this function? So we can verify attribute integrity
            for(Attribute anAttribute : allAttributes) {
            ManagedType declaringType = anAttribute.getDeclaringType();
            assertNotNull(declaringType);
            Type elementType = null;
            if(((AttributeImpl)anAttribute).isPlural()) {
                elementType = ((PluralAttributeImpl)anAttribute).getElementType();
            } else {
                elementType = ((SingularAttributeImpl)anAttribute).getType();
            }
            assertNotNull("elementType should not be null", elementType);
            // Since the javaType may be computed off the elementType - it must not be null or we will get a NPE below
            Class<?> javaType = anAttribute.getJavaType();
            }

        boolean expectedIAExceptionThrown = false;
            // Check entity-->entity hierarchy
            // Processor:entity (Board boards)
            //  +--VectorProcessor

            Set<Attribute<ArrayProcessor, ?>> entityArrayProcessorDeclaredAttributes = entityArrayProcessor_.getDeclaredAttributes();
            assertEquals(1, entityArrayProcessorDeclaredAttributes.size());
            // verify getting the attribute directly
            Attribute<ArrayProcessor, ?> entityArrayProcessorDeclaredAttribute = entityArrayProcessor_.getDeclaredAttribute("speed");
            // verify we do get an IAE on declared type above
        try {
            Attribute<ArrayProcessor, ?> entityArrayProcessorDeclaredAttributeThatIsNonExistent = entityArrayProcessor_.getDeclaredAttribute("non-existent");
        } catch (IllegalArgumentException iae) {
            // expecting no exception
            expectedIAExceptionThrown = true;
            }
            assertTrue("Expected thrown IllegalArgumentException", expectedIAExceptionThrown);

            // Verify we get an IAE on a type declared above
        try {
            Attribute<ArrayProcessor, ?> entityArrayProcessorDeclaredAttributeThatIsDeclaredAbove = entityArrayProcessor_.getDeclaredAttribute("id");
        } catch (IllegalArgumentException iae) {
            // expecting no exception
            expectedIAExceptionThrown = true;
            }
            assertTrue("Expected thrown IllegalArgumentException", expectedIAExceptionThrown);

            Set<Attribute<Processor, ?>> entityProcessorDeclaredAttributes = entityProcessor_.getDeclaredAttributes();
            assertEquals(3, entityProcessorDeclaredAttributes.size());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    public void testToStringOverrides() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull(metamodel);

            // Actual Test Case
            // Test toString() overrides
            EntityTypeImpl<Manufacturer> entityManufacturer_ = (EntityTypeImpl)metamodel.entity(Manufacturer.class);
            assertNotNull(entityManufacturer_);
            assertNotNull(metamodel.toString());
            assertNotNull(entityManufacturer_.getSingularAttribute("aBooleanObject").toString());
            // In the absence of a getPluralAttribute()
            assertNotNull(entityManufacturer_.getAttribute("computers").toString());
            assertNotNull(entityManufacturer_.getList("hardwareDesigners").toString());
            assertNotNull(entityManufacturer_.getMap("hardwareDesignersMap").toString());
            assertNotNull(entityManufacturer_.getSet("computers").toString());
        } catch (IllegalArgumentException iae) {
            //iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    // 316991: regression test getJavaMember() on field level access Entity attribute @OneToOne on an Entity
    /**
     * This test will verify that a transient superclass (non-entity, non-mappedSuperclass)
     * exists as a BasicType (it has no attributes), and that any inheriting Entity either
     * directly subclassing or indirectly subclassing via a MappedSuperclass inheritance chain
     * - does not pick up non-persistence fields that normally would be inherited.
     * (The fields exist in Java but not in ORM:Metamodel)
     * The transient class must have no JPA annotations.
     */
    public void testTransientNonEntityNonMappedSuperclass_SuperclassOfEntity_Exists_as_BasicType() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            // Verify that the non-Entity/non-MappedSuperclass is a BasicType
            Type positionNonEntity = ((MetamodelImpl)metamodel).getType(Position.class);
            assertNotNull(positionNonEntity);
            assertEquals(Type.PersistenceType.BASIC, positionNonEntity.getPersistenceType());
            // Get direct inheriting subclass
            EntityTypeImpl<GalacticPosition> entityLocation_ = (EntityTypeImpl) metamodel.entity(GalacticPosition.class);
            assertNotNull(entityLocation_);

            // Verify it is a BasicType in other INTERNAL API ways
            assertFalse(((TypeImpl)positionNonEntity).isMappedSuperclass());
            assertFalse(((TypeImpl)positionNonEntity).isEntity());
        } catch (IllegalArgumentException iae) {
            iae.printStackTrace();
            exceptionThrown = true;
        } finally {
            cleanup(em);
            assertFalse("An IAE exception should not occur here.", exceptionThrown);
        }
    }

    // Test that we are getting an Illegal argument exception when trying to access non-persistent fields from transient classes
    public void testAttribute_getAttribute_of_TransientNonEntityNonMappedSuperclass_SuperclassOfEntity_throws_IAE() {
        EntityManager em = null;
        boolean exceptionThrown = false;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            assertNotNull("The metamodel should never be null after an em.getMetamodel() call here.", metamodel);
            // Verify that the non-Entity/non-MappedSuperclass is a BasicType
            Type positionNonEntity = ((MetamodelImpl)metamodel).getType(Position.class);
            assertNotNull(positionNonEntity);
            assertEquals(Type.PersistenceType.BASIC, positionNonEntity.getPersistenceType());
            // Get direct inheriting subclass
            EntityTypeImpl<GalacticPosition> entityLocation_ = (EntityTypeImpl) metamodel.entity(GalacticPosition.class);
            assertNotNull(entityLocation_);

            // We will be testing that the non-persistent fields
            Attribute anAttributeThatShouldNotHaveBeenInherited = entityLocation_.getAttribute("nonPersistentObject");
            // we should never get to the following line - go directly to catch block
            assertTrue("IllegalArgumentException expected on transient type attribute should not be in subclass for managedType.getAttribute()",exceptionThrown);
        } catch (IllegalArgumentException iae) {
            //iae.printStackTrace();
            exceptionThrown = true;
            assertTrue("IllegalArgumentException expected on transient type attribute should not be in subclass for managedType.getAttribute()",exceptionThrown);
        } finally {
            cleanup(em);
        }
    }

    public void testMapAttribute_getDeclaredPluralAttributesForEmbeddable(){
        boolean exceptionThrown = false;
        EntityManager em = null;
        try {
            em = privateTestSetup();
            assertNotNull(em);
            Metamodel metamodel = em.getMetamodel();
            EmbeddableTypeImpl<Observation> observation_ = (EmbeddableTypeImpl)metamodel.embeddable(Observation.class);
            Set<PluralAttribute<Observation, ?, ?>> pluralAtrributes = observation_.getDeclaredPluralAttributes();
            boolean foundDetails = false;
            boolean foundLocations = false;
            for (PluralAttribute<Observation, ?, ?> attribute: pluralAtrributes){
                if (attribute.getName().equals("details")){
                    foundDetails = true;
                } else if (attribute.getName().equals("locations")){
                    foundLocations = true;
                }
            }
            assertTrue("Map ElementCollection Plural Attribute not found.", foundDetails);
            assertTrue("Collection ElementCollection Plural Attribute not found.", foundLocations);
        } finally {
            cleanup(em);
        }
    }

    /**
    * Disclaimer:
        *    The following work may still need to be fully implemented - subject to available time.
        *    - proper and fully optimized test cases
        *    - full exception handling
        *    - full rollback handling
        *    - better documented assertion failures
        *    - fully described test model with links to design document
        *    - traceability back to use cases
    */
}
