/*
 * 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.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 = 150;//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 = 52;
    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_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_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
    */
}
