/*
 * Copyright (c) 2011, 2020 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:
//     dclarke, mnorman - Dynamic Persistence
//       http://wiki.eclipse.org/EclipseLink/Development/Dynamic
//       (https://bugs.eclipse.org/bugs/show_bug.cgi?id=200045)
//
//     11/10/2011-2.4 Guy Pelletier
//       - 357474: Address primaryKey option from tenant discriminator column
package org.eclipse.persistence.dynamic;

//javase imports
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Iterator;

import jakarta.persistence.Embeddable;

//EclipseLink imports
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.descriptors.RelationalDescriptor;
import org.eclipse.persistence.exceptions.ValidationException;
import org.eclipse.persistence.indirection.IndirectList;
import org.eclipse.persistence.internal.dynamic.DynamicPropertiesManager;
import org.eclipse.persistence.internal.dynamic.DynamicTypeImpl;
import org.eclipse.persistence.internal.dynamic.ValuesAccessor;
import org.eclipse.persistence.internal.helper.ConversionManager;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.sessions.factories.ObjectPersistenceWorkbenchXMLProject;
import org.eclipse.persistence.mappings.AggregateObjectMapping;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.DirectCollectionMapping;
import org.eclipse.persistence.mappings.DirectToFieldMapping;
import org.eclipse.persistence.mappings.ForeignReferenceMapping;
import org.eclipse.persistence.mappings.ManyToManyMapping;
import org.eclipse.persistence.mappings.OneToManyMapping;
import org.eclipse.persistence.mappings.OneToOneMapping;
import org.eclipse.persistence.mappings.converters.EnumTypeConverter;
import org.eclipse.persistence.mappings.foundation.AbstractDirectMapping;
import org.eclipse.persistence.platform.database.DatabasePlatform;
import org.eclipse.persistence.platform.xml.XMLParser;
import org.eclipse.persistence.platform.xml.XMLPlatformFactory;
import org.eclipse.persistence.sequencing.Sequence;
import org.eclipse.persistence.sessions.DatabaseLogin;
import org.eclipse.persistence.sessions.Project;
import org.eclipse.persistence.sessions.factories.XMLProjectReader;
import org.eclipse.persistence.tools.schemaframework.SchemaManager;
import org.w3c.dom.Document;

/**
 * The EntityTypeBuilder is a factory class for creating and extending dynamic
 * entity types. After being constructed in either usage the application can
 * then use the provided API to customize mapping information of the type.
 *
 * @author dclarke, mnorman
 * @since EclipseLink 1.2
 */
public class DynamicTypeBuilder {

    static XMLParser xmlParser = XMLPlatformFactory.getInstance().getXMLPlatform().newXMLParser();

    /**
     * The type being configured for dynamic use or being created/extended
     */
    protected DynamicTypeImpl entityType;

    /**
     * Create an EntityType for a new dynamic type. The contained EntityType and
     * its wrapped descriptor are not automatically added to any session. This
     * must be done by the application after the type's is fully configured.
     * <p>
     * <b>Creating new type Example</b>: <code>
     *  DynamicHelper helper = new DynamicHelper(session);
     *  DynamicClassLoader dcl = helper.getDynamicClassLoader();<br>
     *  <br>
     *  Class{@literal <?>} javaType = dcl.creatDynamicClass("model.Simple");<br>
     *  <br>
     *  DynamicTypeBuilder typeBuilder = new JPADynamicTypeBuilder(javaType, null, "SIMPLE_TYPE");<br>
     *  typeBuilder.setPrimaryKeyFields("SID");<br>
     *  typeBuilder.addDirectMapping("id", int.class, "SID");<br>
     *  typeBuilder.addDirectMapping("value1", String.class, "VAL_1");<br>
     *  typeBuilder.addDirectMapping("value2", boolean.class, "VAL_2");<br>
     *  typeBuilder.addDirectMapping("value3", Calendar.class, "VAL_3");<br>
     *  typeBuilder.addDirectMapping("value4", Character.class, "VAL_4");<br>
     *  <br>
     *  helper.addTypes(true, true, typeBuilder.getType());<br>
     * </code>
     *
     * @param dynamicClass
     * @param parentType
     * @param tableNames
     */
    public DynamicTypeBuilder(Class<?> dynamicClass, DynamicType parentType, String... tableNames) {
        RelationalDescriptor descriptor = new RelationalDescriptor();
        descriptor.setJavaClass(dynamicClass);
        this.entityType = new DynamicTypeImpl(descriptor, parentType);
        // JAXB generates some classes that do not conform to DynamicEntity interface - ignore
        if (DynamicEntity.class.isAssignableFrom(dynamicClass)) {
            try {
                Field dpmField = dynamicClass.getField(DynamicPropertiesManager.PROPERTIES_MANAGER_FIELD);
                DynamicPropertiesManager dpm = (DynamicPropertiesManager)dpmField.get(null);
                dpm.setType(entityType);
                entityType.setDynamicPropertiesManager(dpm);
            }
            catch (Exception e) {
                // this is bad! Without the dpmField, not much to do but die :-( ...
                e.printStackTrace();
                return;
            }
        }
        configure(descriptor, tableNames);
    }

    /**
     * Create an EntityTypeBuilder for an existing descriptor. This is used
     *
     * @param dcl
     * @param descriptor
     * @param parentType
     *            provided since the InheritancePolicy on the descriptor may not
     *            have its parent descriptor initialized.
     */
    public DynamicTypeBuilder(DynamicClassLoader dcl, ClassDescriptor descriptor, DynamicType parentType) {
        this.entityType = new DynamicTypeImpl(descriptor, parentType);
        Class<?> dynamicClass = descriptor.getJavaClass();
        if (dynamicClass == null) {
            addDynamicClasses(dcl, descriptor.getJavaClassName(), parentType);
        }
        else {
            // JAXB generates some classes that do not conform to DynamicEntity interface - ignore
            if (DynamicEntity.class.isAssignableFrom(dynamicClass)) {
                try {
                    Field dpmField =
                        descriptor.getJavaClass().getField(DynamicPropertiesManager.PROPERTIES_MANAGER_FIELD);
                    DynamicPropertiesManager dpm = (DynamicPropertiesManager)dpmField.get(null);
                    dpm.setType(entityType);
                    entityType.setDynamicPropertiesManager(dpm);
                }
                catch (Exception e) {
                    // this is bad! Without the dpmField, not much to do but die :-( ...
                    e.printStackTrace();
                    return;
                }
            }
        }
        configure(descriptor);
    }

    /**
     * Register a {@link DynamicClassWriter} with the provided
     * {@link DynamicClassLoader} so that a dynamic class can be generated when
     * needed.
     */
    protected void addDynamicClasses(DynamicClassLoader dcl, String className, DynamicType parentType) {
        if (parentType == null) {
            dcl.addClass(className);
        } else {
            if (parentType.getJavaClass() == null) {
                dcl.addClass(className, new DynamicClassWriter(parentType.getClassName()));
            } else {
                dcl.addClass(className, parentType.getJavaClass());
            }
        }
    }

    /**
     * Initialize a new or existing descriptor configuring the necessary
     * policies as well as
     */
    protected void configure(ClassDescriptor descriptor, String... tableNames) {
        // Configure Table names if provided
        if (tableNames != null) {
            if (tableNames.length == 0) {
                if (descriptor.getTables().size() == 0) {
                    descriptor.descriptorIsAggregate();
                }
            } else {
                for (int index = 0; index < tableNames.length; index++) {
                    descriptor.addTableName(tableNames[index]);
                }
            }

        }

        for (int index = 0; index < descriptor.getMappings().size(); index++) {
            addMapping(descriptor.getMappings().get(index));
        }

        descriptor.setProperty(DynamicType.DESCRIPTOR_PROPERTY, entityType);
    }

    public DynamicType getType() {
        return this.entityType;
    }

    /**
     * Test if a mapping requires initialization when a new instance is created.
     * This is true for:
     * <ul>
     * <li>primitives
     * <li>collection mappings
     * <li>basic indirection references
     * </ul>
     *
     * @see DynamicHelper#newDynamicEntity for creation and initialization
     */
    private boolean requiresInitialization(DatabaseMapping mapping) {
        if (mapping.isDirectToFieldMapping() && mapping.getAttributeClassification() != null && mapping.getAttributeClassification().isPrimitive()) {
            return true;
        }
        if (mapping.isForeignReferenceMapping()) {
            ForeignReferenceMapping frMapping = (ForeignReferenceMapping) mapping;
            return frMapping.usesIndirection() || frMapping.isCollectionMapping();
        }
        if (mapping.isAggregateObjectMapping() && !mapping.isXMLMapping()) {
            return !((AggregateObjectMapping) mapping).isNullAllowed();
        }
        return false;
    }

    /**
     * Set the PK field names on the underlying descriptor ensuring no duplicate
     * names are added.
     *
     * @param pkFieldNames
     *            qualified or unqualified field names
     */
    public void setPrimaryKeyFields(String... pkFieldNames) {
        if (pkFieldNames != null && pkFieldNames.length > 0) {
            for (int index = 0; index < pkFieldNames.length; index++) {
                DatabaseField pkField = new DatabaseField(pkFieldNames[index]);

                if (!getType().getDescriptor().getPrimaryKeyFields().contains(pkField)) {
                    getType().getDescriptor().addPrimaryKeyFieldName(pkFieldNames[index]);
                }
            }
        }
    }

    /**
     * Allows {@link DirectToFieldMapping} (@Basic) mapping to be added to a
     * dynamic type through API. This method can be used on a new
     * {@link DynamicTypeImpl} that has yet to be added to a session and have
     * its descriptor initialized, or it can be called on an active
     * (initialized) descriptor.
     * <p>
     * There is no support currently for having the EclipseLink
     * {@link SchemaManager} generate ALTER TABLE calls so any new columns
     * expected must be added without the help of EclipseLink or use the
     * {@link SchemaManager#replaceObject(org.eclipse.persistence.tools.schemaframework.DatabaseObjectDefinition)}
     * to DROP and CREATE the table. WARNING: This will cause data loss.
     *
     * @param javaType
     *            is the type of the attribute. If the type is a primitive it
     *            will be converted to the comparable non-primitive type.
     */
    public DirectToFieldMapping addDirectMapping(String name, Class<?> javaType, String fieldName) {
        DirectToFieldMapping mapping = new DirectToFieldMapping();
        mapping.setAttributeName(name);
        mapping.setFieldName(fieldName);
        mapping.setAttributeClassification(javaType);

        return (DirectToFieldMapping) addMapping(mapping);
    }

    /**
     * Allows {@link OneToOneMapping} (@OneToOne and @ManyToOne) mappings to be
     * added to a dynamic type through API. This method can be used on a new
     * {@link DynamicTypeImpl} that has yet to be added to a session and have
     * its descriptor initialized, or it can be called on an active
     * (initialized) descriptor.
     * <p>
     * There is no support currently for having the EclipseLink
     * {@link SchemaManager} generate ALTER TABLE calls so any new columns
     * expected must be added without the help of EclipseLink or use the
     * {@link SchemaManager#replaceObject(org.eclipse.persistence.tools.schemaframework.DatabaseObjectDefinition)}
     * to DROP and CREATE the table. WARNING: This will cause data loss.
     */
    public OneToOneMapping addOneToOneMapping(String name, DynamicType refType, String... fkFieldNames) {
        if (fkFieldNames == null) {
            throw new IllegalArgumentException("Invalid FK field names: 'null' for target: " + refType);
        }
        if (refType.getDescriptor().getPrimaryKeyFields().size() != fkFieldNames.length) {
            throw new IllegalArgumentException("Invalid FK field names: " + Arrays.asList(fkFieldNames) + " for target: " + refType);
        }

        OneToOneMapping mapping = new OneToOneMapping();
        mapping.setAttributeName(name);
        mapping.setReferenceClass(refType.getJavaClass());

        for (int index = 0; index < fkFieldNames.length; index++) {
            String targetField = refType.getDescriptor().getPrimaryKeyFields().get(index).getName();
            mapping.addForeignKeyFieldName(fkFieldNames[index], targetField);
        }

        return (OneToOneMapping) addMapping(mapping);
    }

    /**
     * Add a {@link OneToManyMapping} to the {@link #entityType} being built or
     * extended. This mapping is created using standard foreign keys from the
     * source table(s) to the target table(s) and transparent indirection (
     * {@link IndirectList}).
     *
     * @param name
     *            attribute name to use in the dynamic entity. Also the property
     *            name used to access the state of the entity
     * @param refType
     * @param fkFieldNames
     *            the FK field names specified in the same order to match the PK
     *            field names of the target class
     *
     * @return the newly created, configured mappin. It will be initialized if
     *         the descriptor is already initialized.
     */
    public OneToManyMapping addOneToManyMapping(String name, DynamicType refType, String... fkFieldNames) {
        if (fkFieldNames == null) {
            throw new IllegalArgumentException("Invalid FK field names: 'null' for target: " + refType);
        }
        if (getType().getDescriptor().getPrimaryKeyFields().size() != fkFieldNames.length) {
            throw new IllegalArgumentException("Invalid FK field names: " + Arrays.asList(fkFieldNames) + " for target: " + refType);
        }

        OneToManyMapping mapping = new OneToManyMapping();
        mapping.setAttributeName(name);
        mapping.setReferenceClass(refType.getJavaClass());

        for (int index = 0; index < fkFieldNames.length; index++) {
            String targetField = getType().getDescriptor().getPrimaryKeyFields().get(index).getName();
            mapping.addTargetForeignKeyFieldName(fkFieldNames[index], targetField);
        }

        mapping.useTransparentList();

        return (OneToManyMapping) addMapping(mapping);
    }

    /**
     * Add a {@link DirectCollectionMapping} to the {@link #entityType} being
     * built or extended. This mapping is created using standard foreign keys
     * from the target table(s) to the source table(s) and transparent
     * indirection ( {@link IndirectList}).
     *
     * @param name
     *            attribute name to use in the dynamic entity. Also the property
     *            name used to access the state of the entity
     * @param targetTable
     *            name of table holding the direct values
     * @param valueColumn
     *            name of column in target table holding the direct value for
     *            the collection
     * @param valueType
     *            the type of the attribute assumed to be a known basic type
     * @param fkFieldNames
     *            the FK field names on the source table specified in order to
     *            match the PK field names on the source.
     * @return the new mapping configured and initialized (if the descriptor is
     *         already initialized.
     * @throws IllegalArgumentException
     */
    public DirectCollectionMapping addDirectCollectionMapping(String name, String targetTable, String valueColumn, Class<?> valueType, String... fkFieldNames) throws IllegalArgumentException {
        if (fkFieldNames == null) {
            throw new IllegalArgumentException("Invalid FK field names: 'null' for target: ");
        }
        if (getType().getDescriptor().getPrimaryKeyFields().size() != fkFieldNames.length) {
            throw new IllegalArgumentException("Invalid FK field names: " + Arrays.asList(fkFieldNames) + " for target: ");
        }

        DirectCollectionMapping mapping = new DirectCollectionMapping();
        mapping.setAttributeName(name);
        mapping.setReferenceTableName(targetTable);
        mapping.setDirectFieldName(valueColumn);
        mapping.setDirectFieldClassification(valueType);

        for (int index = 0; index < fkFieldNames.length; index++) {
            String targetField = getType().getDescriptor().getPrimaryKeyFields().get(index).getName();
            mapping.addReferenceKeyFieldName(fkFieldNames[index], targetField);
        }

        mapping.useTransparentList();

        return (DirectCollectionMapping) addMapping(mapping);
    }

    /**
     * Add a {@link AggregateObjectMapping} ({@link Embeddable} in JPA) to the
     * {@link #entityType} being built or extended.
     *
     * @param name
     *            attribute name to use in the dynamic entity. Also the property
     *            name used to access the state of the entity
     * @param refType
     *            dynamic type re[presenting the Embeddable/AggregateObject
     * @param allowsNull
     *            true indicates that the attribute can be null if all values
     *            are null.
     * @return the new mapping configured and initialized (if the descriptor has
     *         been initialized).
     */
    public AggregateObjectMapping addAggregateObjectMapping(String name, DynamicType refType, boolean allowsNull) {
        AggregateObjectMapping mapping = new AggregateObjectMapping();
        mapping.setAttributeName(name);
        mapping.setReferenceClass(refType.getJavaClass());
        mapping.setIsNullAllowed(allowsNull);

        return (AggregateObjectMapping) addMapping(mapping);
    }

    /**
     * Add a {@link ManyToManyMapping} to the {@link #entityType} being built or
     * extended. This method assumes that the columns names on the relationship
     * table match the PK columns names they relate to. In the case of the
     * target keys from the relationship table a '_' will be appended to the
     * column names if they collide with the names from the source table.
     *
     * @param name
     *            attribute name to use in the dynamic entity. Also the property
     *            name used to access the state of the entity
     * @param refType
     *            target dynamic entity
     * @param relationshipTableName
     */
    public void addManyToManyMapping(String name, DynamicType refType, String relationshipTableName) {
        ManyToManyMapping mapping = new ManyToManyMapping();
        mapping.setAttributeName(name);
        mapping.setReferenceClass(refType.getJavaClass());
        mapping.setRelationTableName(relationshipTableName);

        for (DatabaseField sourcePK : getType().getDescriptor().getPrimaryKeyFields()) {
            mapping.addSourceRelationKeyFieldName(sourcePK.getName(), sourcePK.getQualifiedName());
        }
        for (DatabaseField targetPK : refType.getDescriptor().getPrimaryKeyFields()) {
            String relField = targetPK.getName();
            if (mapping.getSourceRelationKeyFieldNames().contains(relField)) {
                relField = refType.getName() + "_" + relField;
            }
            mapping.addTargetRelationKeyFieldName(relField, targetPK.getQualifiedName());
        }
        mapping.useTransparentList();

        addMapping(mapping);
    }

    /**
     * Add the mapping to the {@link #entityType}'s descriptor being built or
     * extended. This is where the {@link ValuesAccessor} is created and the
     * position of the mapping in the descriptor is captured to use as its
     * index.
     */
    public DatabaseMapping addMapping(DatabaseMapping mapping) {
        ClassDescriptor descriptor = getType().getDescriptor();

        if (!descriptor.getMappings().contains(mapping)) {
            descriptor.addMapping(mapping);
        }

        int index = descriptor.getMappings().indexOf(mapping);

        // Need to account for inherited mappings. When initialized a child
        // descriptor has all of its parent mappings added ahead of its
        // mappings. This adds the necessary offset.
        if (getType().getParentType() != null) {
            DynamicType current = getType();
            while (current.getParentType() != null) {
                index += current.getParentType().getDescriptor().getMappings().size();
                current = current.getParentType();
            }
        }

        // Try to configure the attribute classification if name is available
        if (mapping.getAttributeClassification() == null && mapping.isAbstractDirectMapping()) {
            String typeName = ((AbstractDirectMapping) mapping).getAttributeClassificationName();
            if (typeName != null) {
                // Remove any additional padding
                typeName = typeName.trim();
                try {
                    Class<?> attrType = ConversionManager.getDefaultManager().convertClassNameToClass(typeName);
                    ((AbstractDirectMapping) mapping).setAttributeClassification(attrType);
                } catch (Exception e) {
                }
            }
        }

        mapping.setAttributeAccessor(new ValuesAccessor(mapping));

        if (requiresInitialization(mapping)) {
            this.entityType.getMappingsRequiringInitialization().add(mapping);
        }

        return mapping;
    }

    /**
     * Configure default sequencing.
     */
    public void configureSequencing(String numberName, String numberFieldName) {
        getType().getDescriptor().setSequenceNumberName(numberName);
        getType().getDescriptor().setSequenceNumberFieldName(numberFieldName);
    }

    /**
     * Configure sequencing specifying the sequence type to use.
     */
    public void configureSequencing(Sequence sequence, String numberName, String numberFieldName) {
        configureSequencing(numberName, numberFieldName);
        getType().getDescriptor().setSequence(sequence);
    }

    public DynamicEnumBuilder addEnum(String fieldName, String className, String columnName,
        DynamicClassLoader dcl) {
        dcl.addEnum(className, (Object)null);
        AbstractDirectMapping adm = addDirectMappingForEnum(fieldName, className, columnName);
        return new DynamicEnumBuilder(className, adm, dcl);
    }

    protected AbstractDirectMapping addDirectMappingForEnum(String fieldName, String className,
        String columnName) {
        DirectToFieldMapping dtfm = addDirectMapping(fieldName, null, columnName);
        dtfm.setConverter(new EnumTypeConverter(dtfm, className));
        addMapping(dtfm);
        return dtfm;
    }

    /**
     * Load a dynamic project from deployment XML creating dynamic types for all
     * descriptors where the provided class name does not exist.
     *
     * @param resourcePath
     * @param login
     * @param dynamicClassLoader
     * @return a Project with {@link DynamicClassLoader} and associated
     *         {@link DynamicClassWriter} configured. Ensure if a new
     *         Login/Platform is being configured that the
     *         {@link ConversionManager#getLoader()} is maintained.
     *         <p>
     *         <code>null</code> is returned if the resourcePath cannot locate a
     *         deployment XML
     * @throws IOException
     */
    public static Project loadDynamicProject(String resourcePath, DatabaseLogin login, DynamicClassLoader dynamicClassLoader) throws IOException {

        if (resourcePath == null) {
            throw new NullPointerException("null resourceStream");
        }
        if (dynamicClassLoader == null) {
            throw new NullPointerException("null dynamicClassLoader");
        }
        return loadDynamicProject(dynamicClassLoader.getResourceAsStream(resourcePath), login, dynamicClassLoader);
    }



    /**
     * Load a dynamic project from deployment XML creating dynamic types for all
     * descriptors where the provided class name does not exist.
     *
     * @param resourceStream
     * @param login
     * @param dynamicClassLoader
     * @return a Project with {@link DynamicClassLoader} and associated
     *         {@link DynamicClassWriter} configured. Ensure if a new
     *         Login/Platform is being configured that the
     *         {@link ConversionManager#getLoader()} is maintained.
     *         <p>
     *         <code>null</code> is returned if the resourcePath cannot locate a
     *         deployment XML
     * @throws IOException
     */
    public static Project loadDynamicProject(InputStream resourceStream, DatabaseLogin login, DynamicClassLoader dynamicClassLoader) throws IOException {

        if (resourceStream == null) {
            throw new NullPointerException("null resourceStream");
        }
        if (dynamicClassLoader == null) {
            throw new NullPointerException("null dynamicClassLoader");
        }

        // Build an OXM project that loads the deployment XML without converting
        // the class names into classes
        ObjectPersistenceWorkbenchXMLProject opmProject = new ObjectPersistenceWorkbenchXMLProject();
        Document document = xmlParser.parse(resourceStream);
        Project project = XMLProjectReader.readObjectPersistenceRuntimeFormat(document, dynamicClassLoader, opmProject);
        return loadDynamicProject(project, login, dynamicClassLoader);
    }

    public static Project loadDynamicProject(Project project, DatabaseLogin login, DynamicClassLoader dynamicClassLoader) {
        if (project != null) {
            if (login == null) {
                if (project.getLogin() == null) {
                    project.setLogin(new DatabaseLogin());
                }
            } else {
                project.setLogin(login);
            }
            if (project.getLogin().getPlatform() == null) {
                project.getLogin().setPlatform(new DatabasePlatform());
            }

            project.getLogin().getPlatform().getConversionManager().setLoader(dynamicClassLoader);

            for (Iterator<?> i = project.getOrderedDescriptors().iterator(); i.hasNext();) {
                ClassDescriptor descriptor = (ClassDescriptor) i.next();
                if (descriptor.getJavaClass() == null) {
                    createType(dynamicClassLoader, descriptor, project);
                }
            }
            project.convertClassNamesToClasses(dynamicClassLoader);
            for (Iterator<?> i = project.getOrderedDescriptors().iterator(); i.hasNext();) {
                ClassDescriptor descriptor = (ClassDescriptor) i.next();
                Class<?> dynamicClass = descriptor.getJavaClass();
                // JAXB generates some classes that do not conform to DynamicEntity interface - ignore
                if (dynamicClass != null && DynamicEntity.class.isAssignableFrom(dynamicClass)) {
                    DynamicType type = DynamicHelper.getType(descriptor);
                    try {
                        Field dpmField =
                            descriptor.getJavaClass().getField(DynamicPropertiesManager.PROPERTIES_MANAGER_FIELD);
                        DynamicPropertiesManager dpm = (DynamicPropertiesManager)dpmField.get(null);
                        dpm.setType(type);
                        ((DynamicTypeImpl)type).setDynamicPropertiesManager(dpm);
                    }
                    catch (Exception e) {
                        // this is bad! Without the dpmField, not much to do but die :-( ...
                        e.printStackTrace();
                        return null;
                    }
                }
            }
        }

        return project;
    }

    /**
     * Create EntityType for a descriptor including the creation of a new
     * dynamic type. This method needs to handle inheritance where the parent
     * type needs to be defined before this type.
     */
    private static DynamicType createType(DynamicClassLoader dcl, ClassDescriptor descriptor, Project project) {
        Class<?> javaClass = null;
        try {
            javaClass = dcl.loadClass(descriptor.getJavaClassName());
        } catch (ClassNotFoundException e) {
        }

        if (javaClass != null) {
            descriptor.setJavaClass(javaClass);
        }

        DynamicType parent = null;

        if (descriptor.hasInheritance() && descriptor.getInheritancePolicy().getParentClassName() != null) {
            ClassDescriptor parentDesc = null;
            for (Iterator<?> i = project.getOrderedDescriptors().iterator(); parentDesc == null && i.hasNext();) {
                ClassDescriptor d = (ClassDescriptor) i.next();
                if (d.getJavaClassName().equals(descriptor.getInheritancePolicy().getParentClassName())) {
                    parentDesc = d;
                }
            }

            if (parentDesc == null) {
                throw ValidationException.missingDescriptor(descriptor.getInheritancePolicy().getParentClassName());
            }

            parent = DynamicHelper.getType(parentDesc);
            if (parent == null) {
                parent = createType(dcl, parentDesc, project);
            }
        }

        DynamicType type = DynamicHelper.getType(descriptor);
        if (type == null) {
            type = new DynamicTypeBuilder(dcl, descriptor, parent).getType();
        }

        // JAXB generates some classes that do not conform to DynamicEntity interface - ignore
        if (javaClass != null && DynamicEntity.class.isAssignableFrom(javaClass)) {
            try {
                Field dpmField = javaClass.getField(DynamicPropertiesManager.PROPERTIES_MANAGER_FIELD);
                DynamicPropertiesManager dpm = (DynamicPropertiesManager)dpmField.get(null);
                dpm.setType(type);
                ((DynamicTypeImpl)type).setDynamicPropertiesManager(dpm);
            }
            catch (Exception e) {
                // this is bad! Without the dpmField, not much to do but die :-( ...
                e.printStackTrace();
                return null;
            }
        }

        return type;
    }
}
