blob: 2a85d0387ebd6dd8c14c69b4ef48914577dc4783 [file] [log] [blame]
/*
* 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;
}
}