/*
 * 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:
//     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>
     *
     */
    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 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 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.
     */
    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
     */
    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.
     *
     * @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
     */
    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.
     *
     * @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
     */
    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;
    }
}
