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

// Contributors:
//     03/19/2009-2.0  dclarke  - initial API start
//     06/30/2009-2.0  mobrien - finish JPA Metadata API modifications in support
//       of the Metamodel implementation for EclipseLink 2.0 release involving
//       Map, ElementCollection and Embeddable types on MappedSuperclass descriptors
//       - 266912: JPA 2.0 Metamodel API (part of the JSR-317 EJB 3.1 Criteria API)
//     07/06/2009-2.0  mobrien - Metamodel implementation expansion
//       - 282518: Metamodel superType requires javaClass set on custom
//         descriptor on MappedSuperclassAccessor.
//     07/10/2009-2.0  mobrien - Adjust BasicType processing to handle non-Entity Java types
//       - 266912: As part of Attribute.getType() and specifically SingularAttribute.getBindableJavaType
//         set the appropriate elementType based on the mapping type.
//     09/23/2009-2.0  mobrien - 266912: Implement hasSingleIdAttribute() and
//       all other 6 remaining methods for Id and Version support.
//       DI 70 - 77 and 56
//       http://wiki.eclipse.org/EclipseLink/Development/JPA_2.0/metamodel_api#DI_74:_20090909:_Implement_IdentifiableType.hasSingleIdAttribute.28.29
//     10/14/2009-2.0  mobrien - 285512: managedType(clazz) now throws IAE again for
//        any clazz that resolves to a BasicType - use getType(clazz) in implementations instead
//        when you are expecting a BasicType
//     08/06/2010-2.2 mobrien 322018 - reduce protected instance variables to private to enforce encapsulation
//     08/06/2010-2.2 mobrien 303063 - handle null descriptor.javaClass passed from the metadata API
//     03/06/2011-2.3 mobrien 338837 - Metamodel entity processing requires specified entities in persistence.xml
//        to avoid IllegalArgumentException when accessing an EntityType|EmbeddableType|ManagedType
//        "The type [null] is not the expected [EntityType] for the key class" will result in certain managed persistence contexts
package org.eclipse.persistence.internal.jpa.metamodel;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
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.EmbeddableType;
import jakarta.persistence.metamodel.EntityType;
import jakarta.persistence.metamodel.IdentifiableType;
import jakarta.persistence.metamodel.ManagedType;
import jakarta.persistence.metamodel.Metamodel;
import jakarta.persistence.metamodel.Type;
import jakarta.persistence.metamodel.Type.PersistenceType;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.internal.helper.ClassConstants;
import org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl;
import org.eclipse.persistence.internal.localization.ExceptionLocalization;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.jpa.JpaHelper;
import org.eclipse.persistence.logging.AbstractSessionLog;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.sessions.Project;

/**
 * <p>
 * <b>Purpose</b>: Provides the implementation for the Metamodel interface
 *  of the JPA 2.0 Metamodel API (part of the JSR-317 EJB 3.1 Criteria API)
 * <p>
 * <b>Description</b>:
 * Provides access to the metamodel of persistent
 * Entities, MappedSuperclasses, Embeddables, ManagedTypes and Types  in the persistence unit.
 * Note: Since the types Map is lazy-loaded with key:value pairs - the designer and especially the user
 * must realized that a particular BasicType may not be in the Map until it is referenced.
 *
 * @see jakarta.persistence.metamodel.Metamodel
 *
 * @since EclipseLink 1.2 - JPA 2.0
 *
 */
public class MetamodelImpl implements Metamodel, Serializable {

    /** Item 54: DI 89: explicit UID will avoid performance hit runtime generation of one */
    private static final long serialVersionUID = -7352420189248464690L;

    /** The EclipseLink Session associated with this Metamodel implementation that contains all our descriptors with mappings **/
    private AbstractSession session;

    /** The Map of entities in this metamodel keyed on Class **/
    private Map<String, EntityTypeImpl<?>> entities;

    /** The Map of embeddables in this metamodel keyed on Class **/
    private Map<String, EmbeddableTypeImpl<?>> embeddables;

    /** The Map of managed types (Entity, Embeddable and MappedSuperclass) in this metamodel keyed on Class **/
    private Map<String, ManagedTypeImpl<?>> managedTypes;

    /** The Map of types (Entity, Embeddable, MappedSuperclass and Basic - essentially Basic + managedTypes) in this metamodel keyed on Class **/
    private Map<String, TypeImpl<?>> types;

    /** The Set of MappedSuperclassTypes in this metamodel**/
    private Set<MappedSuperclassTypeImpl<?>> mappedSuperclasses;

    /** maintains initialization state to avoid extra work in calls to initialize **/
    private boolean isInitialized = false;

    /** Default elementType Class when we the type cannot be determined for unsupported mappings such as Transformation and VariableOneToOne */
    public static final Class DEFAULT_ELEMENT_TYPE_FOR_UNSUPPORTED_MAPPINGS = Object.class;

    public MetamodelImpl(AbstractSession session) {
        this.session = session;
        preInitialize();
    }

    public MetamodelImpl(EntityManager em) {
        // Create a new Metamodel using the EclipseLink session on the EM
        this(JpaHelper.getEntityManager(em).getAbstractSession());
    }

    public MetamodelImpl(EntityManagerFactory emf) {
        // Create a new Metamodel using the EclipseLink session on the EMF
        this(((AbstractSession)JpaHelper.getDatabaseSession(emf)));
    }

    /**
     * INTERNAL:
     * @param emSetupImpl
     */
    public MetamodelImpl(EntityManagerSetupImpl emSetupImpl) {
        // Create a new Metamodel using the EclipseLink session on the EM
        this(emSetupImpl.getSession());
    }

    /**
     *  Return the metamodel embeddable type representing the
     *  embeddable class.
     *  @param clazz  the type of the represented embeddable class
     *  @return the metamodel embeddable type
     *  @throws IllegalArgumentException if not an embeddable class
     */
    @Override
    public <X> EmbeddableType<X> embeddable(Class<X> clazz) {
        String key = clazz == null ? null : clazz.getName();
        EmbeddableTypeImpl<?> aType = this.embeddables.get(key);
        if(aType == null) {
            entityEmbeddableManagedTypeNotFound(embeddables, null, clazz, "Embeddable", "EmbeddableType");
        }
        return (EmbeddableType<X>) aType;
    }

    /**
     * INTERNAL:
     * This function will warn the user and/or throw an IllegalArgumentException if the type is not found in the metamodel.
     * There is a chance that the entire metamodel is empty because the model was not found during entity search.  This is
     * usually due to the case where an expected managed persistence unit in a Java EE environment is actually processed as a
     * Java SE (unmanaged) persistence unit.
     * This may occur on certain configurations of Spring or on Java EE 6 Web Profile implementations that are not in compliance
     * with the specification.
     * See http://bugs.eclipse.org/338837
     * @param aType
     * @param clazz
     * @param metamodelType
     * @param metamodelTypeName
     */
    private void entityEmbeddableManagedTypeNotFound(Map typeMap, Object aType, Class clazz, String metamodelType, String metamodelTypeName) {
        // 338837: verify that the collection is not empty - this would mean entities did not make it into the search path
        if(typeMap.isEmpty()) {
            AbstractSessionLog.getLog().log(SessionLog.WARNING, SessionLog.METAMODEL, "metamodel_type_collection_empty_during_lookup", clazz, metamodelTypeName);
        }
        // A null type will mean either the metamodel type does not exist because it was not found/processed, or the clazz is not part of the model
        if(null == clazz) {
                throw new IllegalArgumentException(ExceptionLocalization.buildMessage(
                        "metamodel_class_null_type_instance_for_null_key",
                        new Object[] { metamodelTypeName, metamodelType}));
        } else {
            if(null == aType) {
                throw new IllegalArgumentException(ExceptionLocalization.buildMessage(
                        "metamodel_class_null_type_instance",
                        new Object[] { clazz.getCanonicalName(), metamodelTypeName, metamodelType}));
            } else {
                throw new IllegalArgumentException(ExceptionLocalization.buildMessage(
                        "metamodel_class_incorrect_type_instance",
                        new Object[] { clazz, metamodelTypeName, aType}));
            }
        }
    }

    /**
     *  Return the metamodel entity type representing the entity.
     *  @param clazz  the type of the represented entity
     *  @return the metamodel entity type
     *  @throws IllegalArgumentException if not an entity
     */
    @Override
    public <X> EntityType<X> entity(Class<X> clazz) {
        String key = clazz == null ? null : clazz.getName();
        EntityTypeImpl<?> aType = this.entities.get(key);
        if(aType == null) {
            entityEmbeddableManagedTypeNotFound(entities, null, clazz, "Entity", "EntityType");
        }
        return (EntityType<X>) aType;
    }

    /**
     * INTERNAL:
     * Return a List of all attributes for all ManagedTypes.
     * @return
     */
    public List<Attribute> getAllManagedTypeAttributes() {
        List<Attribute> attributeList = new ArrayList<Attribute>();
        for(ManagedType managedType : this.managedTypes.values()) {
            attributeList.addAll(managedType.getAttributes());
        }
        return attributeList;
    }

    /**
     * Return the metamodel embeddable types.
     * @return the metamodel embeddable types
     */
    @Override
    public Set<EmbeddableType<?>> getEmbeddables() {
        return new LinkedHashSet<EmbeddableType<?>>(this.embeddables.values());
    }

    /**
     * Return the metamodel entity types.
     * @return the metamodel entity types
     */
    @Override
    public Set<EntityType<?>> getEntities() {
        return new LinkedHashSet<EntityType<?>>(this.entities.values());
    }

    /**
     *  Return the metamodel managed types map.
     */
    public Map<String, ManagedTypeImpl<?>> getManagedTypesMap() {
        return this.managedTypes;
    }

    /**
     *  Return the metamodel managed types.
     *  @return the metamodel managed types
     */
    @Override
    public Set<ManagedType<?>> getManagedTypes() {
        return new LinkedHashSet<ManagedType<?>>(this.managedTypes.values());
    }

    /**
     * INTERNAL:
     * Return the Set of MappedSuperclassType objects
     * @return
     */
    public Set<MappedSuperclassTypeImpl<?>> getMappedSuperclasses() {
        return new LinkedHashSet<MappedSuperclassTypeImpl<?>>(this.mappedSuperclasses);
    }

    /**
     * INTERNAL:
     * Return the core API Project associated with the DatabaseSession
     * that is associated with this Metamodel
     * @return
     */
    public Project getProject() {
        return this.getSession().getProject();
    }
    /**
     * INTERNAL:
     * Return the DatabaseSession associated with this Metamodel
     * @return
     */
    protected AbstractSession getSession() {
        return this.session;
    }

    /**
     * INTERNAL:
     * This function is a wrapper around a Map.put(K,V)<br>
     * We return a boolean that is unused but provides a way to add a
     * breakpoint for the false condition.
     * @param javaClassKey
     * @param typeValue
     * @return
     */
    private boolean putType(String javaClassKey, TypeImpl typeValue) {
        boolean isValid = true;
        // DI99: Check for an invalid key without reporting it (a non-Fail-Fast pattern)
        if(null == javaClassKey) {
            // Use Case: doing an emf.getCriteriaBuilder() before an EM has been created
            isValid = false;
        }
        this.types.put(javaClassKey, typeValue);
        return isValid;
    }

    /**
     * INTERNAL:
     * Return a Type representation of a java Class for use by the Metamodel Attributes.<p>
     * If a type does not yet exist - one will be created and added to the Metamodel - this usually only for Basic types.<p>
     * This function will handle all Metamodel defined and core java classes.
     *
     * @param javaClass
     * @return
     */
    public <X> TypeImpl<X> getType(Class<X> javaClass) {
        // Return an existing matching type on the metamodel keyed on class name
        String key = javaClass == null ? null : javaClass.getName();
        TypeImpl type = this.types.get(key);
        // the type was not cached yet on the metamodel - lets add it - usually a non Metamodel class like Integer
        if (null == type) {
            // make types field modification thread-safe
            synchronized (this.types) {
                // check for a cached type right after we synchronize
                type = this.types.get(key);
                // If a type is not found (not created during metamodel.initialize() - it is usually a Basic type
                if(null == type) {
                    type = new BasicTypeImpl<X>(javaClass);
                    // add the type to the types map keyed on Java class
                    putType(key, type);
                }
            } // synchronized end
        }
        return type;
    }

    /**
     * INTERNAL:
     * Return the Map of types on this metamodel.
     * This includes all Entity, MappedSuperclass, Embeddable and Basic types
     * @return
     */
    public Map<String, TypeImpl<?>> getTypes() {
        return types;
    }

    /**
     * INTERNAL:
     * Return whether there is a descriptor that is keyed by the supplied class name.<p>
     * Referenced by ManagedTypeImpl.create()
     * @param qualifiedClassNameKeyString
     * @return
     */
    protected boolean hasMappedSuperclass(String qualifiedClassNameKeyString) {
        /**
         * This function is used before the metamodel has populated its Set of mappedSuperclasses -
         * therefore we go directly to the descriptor source.
         * Normally this functionality would be placed on the (core) Project class, however
         * this would create a JPA dependency in Core when we try to use MetadataClass functionality there.
         */
        return this.getSession().getProject().hasMappedSuperclass(qualifiedClassNameKeyString);
    }

    public boolean isInitialized() {
        return isInitialized;
    }

    /**
     * INTERNAL:
     * First phase of metamodel intialization.  Builds a list of the classes in the metamodel and
     * stores them in appropriate lists indexed by the classname.  We index by classname to avoid having
     * to load classes at this phase of initialization
     */
    private void preInitialize(){
        // Design Note: Use LinkedHashMap and LinkedHashSet to preserve ordering
        this.types = new LinkedHashMap<String, TypeImpl<?>>();
        this.entities = new LinkedHashMap<String, EntityTypeImpl<?>>();
        this.embeddables = new LinkedHashMap<String, EmbeddableTypeImpl<?>>();
        this.managedTypes = new LinkedHashMap<String, ManagedTypeImpl<?>>();
        this.mappedSuperclasses = new LinkedHashSet<MappedSuperclassTypeImpl<?>>();

        // Process all Entity and Embeddable types (MappedSuperclasses are handled later)
        for (ClassDescriptor descriptor : this.getSession().getProject().getOrderedDescriptors()) {
            // The ClassDescriptor is always of type RelationalDescriptor - the cast is safe
            ManagedTypeImpl<?> managedType = ManagedTypeImpl.create(this, descriptor);
            String descriptorJavaType = managedType.getJavaTypeName();
            if(null == descriptorJavaType) {
                AbstractSessionLog.getLog().log(SessionLog.FINEST, SessionLog.METAMODEL, "metamodel_relationaldescriptor_javaclass_null_on_managedType", descriptor, managedType);
            }
            putType(descriptorJavaType, managedType);
            this.managedTypes.put(descriptorJavaType, managedType);

            if (managedType.getPersistenceType().equals(PersistenceType.ENTITY)) {
                this.entities.put(descriptorJavaType, (EntityTypeImpl<?>) managedType);
            }
            if (managedType.getPersistenceType().equals(PersistenceType.EMBEDDABLE)) {
                this.embeddables.put(descriptorJavaType, (EmbeddableTypeImpl<?>) managedType);
            }

            // Process all Basic Types
            // Iterate by typeName
            // see
            // http://wiki.eclipse.org/EclipseLink/Development/JPA_2.0/metamodel_api#DI_54:_20090803:_Metamodel.type.28Clazz.29_should_differentiate_between_null_and_BasicType
        }

        // Future: verify that all entities or'd with embeddables matches the number of types

        // Handle all MAPPED_SUPERCLASS types
        // Get mapped superclass types (separate from descriptors on the session from the native project (not a regular descriptor)
        for (ClassDescriptor descriptor : this.getSession().getProject().getMappedSuperclassDescriptors().values()) {
            MappedSuperclassTypeImpl<?> mappedSuperclassType = (MappedSuperclassTypeImpl)ManagedTypeImpl.create(this, descriptor);

            // Add the MappedSuperclass to our Set of MappedSuperclasses
            this.mappedSuperclasses.add(mappedSuperclassType);

            String descriptorJavaType = mappedSuperclassType.getJavaTypeName();
            if(null == descriptorJavaType) {
                AbstractSessionLog.getLog().log(SessionLog.FINEST, SessionLog.METAMODEL, "metamodel_relationaldescriptor_javaclass_null_on_managedType",
                        descriptor, mappedSuperclassType);
            }

            // Add this MappedSuperclass to the Collection of Types
            putType(descriptorJavaType, mappedSuperclassType);
            // Add the MappedSuperclass to the Map of ManagedTypes
            // So we can find hierarchies of the form [Entity --> MappedSuperclass(abstract) --> Entity]
            this.managedTypes.put(descriptorJavaType, mappedSuperclassType);
        }
    }

    /**
     * INTERNAL:
     *
     * Initialize the JPA metamodel that wraps the EclipseLink JPA metadata created descriptors.<br>
     * Note: Since the types Map is lazy-loaded with key:value pairs - the designer and especially the user
     * must realized that a particular BasicType may not be in the Map until it is referenced.
     *
     * Also note 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 will have no JPA annotations.
     *
     * This is the second phase of metamodel initialization.  It causes preindexed classes to have their
     * attributes populated.
     */
    public void initialize(ClassLoader classLoader) {

        // Handle all IdentifiableTypes (after all ManagedTypes have been created)
        // Assign all superType fields on all IdentifiableTypes (only after all managedType objects have been created)
        for(ManagedTypeImpl<?> potentialIdentifiableType : managedTypes.values()) {
            Class aClass = potentialIdentifiableType.getJavaType(classLoader);
            /**
             * The superclass for top-level types is Object - however we set [null] as the supertype for root types.
             * 1) We are constrained by the fact that the spec requires that a superType be an IdentifiableType.
             *    Since [Object] is not an Entity or MappedSuperclass - it fails this criteria - as it would be a BasicType
             *    because it has no @Entity or @MappedSuperclass annotation.<p>
             * 2) Another object space reasoning issue behind this is to separate the Java and Metamodel object spaces.
             * In Java all types inherit from Object, however in the JPA Metamodel all types DO NOT inherit from a common type.
             * Therefore in the metamodel top-level root types have a superType of null.
             * See design issue discussion:
             * http://wiki.eclipse.org/EclipseLink/Development/JPA_2.0/metamodel_api#DI_42:_20090709:_IdentifiableType.supertype_-_what_do_top-level_types_set_it_to
             */
            // 303063: secondary check for a null javaType (metadata processing should never allow this to happen - however we must handle it here in case
            // http://wiki.eclipse.org/EclipseLink/Development/JPA_2.0/metamodel_api#DI_101:_20100218:_Descriptor.javaClass_is_null_on_a_container_EM_for_a_specific_case
            if(null == aClass) {
                AbstractSessionLog.getLog().log(SessionLog.FINEST, SessionLog.METAMODEL, "metamodel_itentifiableType_javaclass_null_cannot_set_supertype",
                        potentialIdentifiableType.getDescriptor(), this);
            } else {
                Class superclass = aClass.getSuperclass();
                // explicitly set the superType to null (just in case it is initialized to a non-null value in a constructor)
                IdentifiableType<?> identifiableTypeSuperclass = null;
                if(potentialIdentifiableType.isIdentifiableType() && (superclass != ClassConstants.OBJECT && superclass != null)) {
                    // Get the Entity or MappedSuperclass
                    // A hierarchy of Entity --> Entity or Entity --> MappedSuperclass will be found
                    identifiableTypeSuperclass = (IdentifiableType<?>)managedTypes.get(superclass.getName());
                    // If there is no superclass (besides Object for a top level identifiable type) then keep the supertype set to null
                    // See design issue #42 - we return Object for top-level types (with no superclass) and null if the supertype was not set
                    // http://wiki.eclipse.org/EclipseLink/Development/JPA_2.0/metamodel_api#DI_42:_20090709:_IdentifiableType.supertype_-_what_do_top-level_types_set_it_to
                    ((IdentifiableTypeImpl)potentialIdentifiableType).setSupertype(identifiableTypeSuperclass);
                    // set back pointer if mappedSuperclass
                    if(null != identifiableTypeSuperclass && ((IdentifiableTypeImpl)identifiableTypeSuperclass).isMappedSuperclass()) {
                        ((MappedSuperclassTypeImpl)identifiableTypeSuperclass).addInheritingType(((IdentifiableTypeImpl)potentialIdentifiableType));
                    }
                    ((IdentifiableTypeImpl)potentialIdentifiableType).setSupertype(identifiableTypeSuperclass);
                }
            }
        }

        //1 - process all non-mappedSuperclass types first so we pick up attribute types
        //2 - process mappedSuperclass types and lookup collection attribute types on inheriting entity types when field is not set

        /**
         * Delayed-Initialization (process all mappings) of all Managed types
         *  (This includes all IdentifiableTypes = Entity and MappedSuperclass types).
         * To avoid a ConcurrentModificationException on the types map, iterate a list instead of the Map values directly.
         * The following code section may add BasicTypes to the types map.
         */
        for(ManagedTypeImpl<?> managedType : new ArrayList<ManagedTypeImpl<?>>(managedTypes.values())) {
            managedType.initialize();
        }

        // 3 - process all the Id attributes on each IdentifiableType
        for(ManagedTypeImpl<?> potentialIdentifiableType : managedTypes.values()) {
            if(potentialIdentifiableType.isIdentifiableType()) {
                ((IdentifiableTypeImpl<?>)potentialIdentifiableType).initializeIdAttributes();
            }
        }

        // 338837: verify that the collections are not empty - this would mean entities did not make it into the search path
        if((null == this.embeddables || this.embeddables.isEmpty()) &&
                (null == this.managedTypes || this.managedTypes.isEmpty()) &&
                (null == this.entities || this.entities.isEmpty())) {
            AbstractSessionLog.getLog().log(SessionLog.WARNING, SessionLog.METAMODEL, "metamodel_type_collection_empty", null, true);
        }
        isInitialized = true;
    }

    /**
     *  Return the metamodel managed type representing the
     *  entity, mapped superclass, or embeddable class.
     *  @param clazz  the type of the represented managed class
     *  @return the metamodel managed type
     *  @throws IllegalArgumentException if not a managed class
     */
    @Override
    public <X> ManagedType<X> managedType(Class<X> clazz) {
        String key = clazz == null ? null : clazz.getName();
        ManagedTypeImpl<?> aType = this.managedTypes.get(key);
        // Throw an IAE exception if the returned type is not a ManagedType
        // For any clazz that resolves to a BasicType - use getType(clazz) in implementations when you are expecting a BasicType
        if (aType == null) {
            entityEmbeddableManagedTypeNotFound(managedTypes, null, clazz, "Managed", "ManagedType");
        }
        return (ManagedType<X>) aType;
    }

    /**
     * INTERNAL:
     * Print out all the Type attributes in the Metamodel
     */
    public void printAllTypes() {
        if ((null == types) || types.isEmpty()) {
            // 338837: verify that the collection is not empty - this would mean entities did not make it into the search path
            AbstractSessionLog.getLog().log(SessionLog.WARNING, SessionLog.METAMODEL, "metamodel_type_collection_empty", null, true);
        } else {
            this.session.log(SessionLog.INFO, SessionLog.METAMODEL, "metamodel_print_type_header",this.types.size());
            for (Type aType : this.types.values()) {
                this.session.log(SessionLog.INFO, SessionLog.METAMODEL, "metamodel_print_type_value",aType);
            }
        }
    }

    /**
     * INTERNAL:
     * Return the string representation of the receiver.
     */
    @Override
    public String toString() {
        StringBuffer aBuffer = new StringBuffer();
        aBuffer.append(this.getClass().getSimpleName());
        aBuffer.append("@");
        aBuffer.append(hashCode());
        aBuffer.append(" [");
        if(null != this.types) {
            aBuffer.append(" ");
            aBuffer.append(this.types.size());
            aBuffer.append(" Types: ");
            //aBuffer.append(this.types.keySet());
        }
        if(null != this.managedTypes) {
            aBuffer.append(", ");
            aBuffer.append(this.managedTypes.size());
            aBuffer.append(" ManagedTypes: ");
            //aBuffer.append(this.managedTypes.keySet());
        }
        if(null != this.entities) {
            aBuffer.append(", ");
            aBuffer.append(this.entities.size());
            aBuffer.append(" EntityTypes: ");
            //aBuffer.append(this.entities.keySet());
        }
        if(null != this.mappedSuperclasses) {
            aBuffer.append(", ");
            aBuffer.append(this.mappedSuperclasses.size());
            aBuffer.append(" MappedSuperclassTypes: ");
            //aBuffer.append(this.mappedSuperclasses);
        }
        if(null != this.embeddables) {
            aBuffer.append(", ");
            aBuffer.append(this.embeddables.size());
            aBuffer.append(" EmbeddableTypes: ");
            //aBuffer.append(this.embeddables.keySet());
        }
        aBuffer.append("]");
        return aBuffer.toString();
    }
}
