use of org.apache.openejb.jee.jpa.MappedSuperclass in project tomee by apache.
the class CmpJpaConversion method mapClass1x.
/**
* Create the class mapping for a CMP 1.x entity bean.
* Since the fields for 1.x persistence are defined
* in the objects directly, we need to create superclass
* mappings for each of the defined fields to identify
* which classes implement each of the managed fields.
*
* @param ejbClassName The name of the class we're processing.
* @param mapping The mappings we're going to generate.
* @param bean The bean metadata for the ejb.
* @param classLoader The classloader used to load the bean class for
* inspection.
* @return The set of mapped superclasses used in this
* bean mapping.
*/
private Collection<MappedSuperclass> mapClass1x(final String ejbClassName, final Mapping mapping, final EntityBean bean, final ClassLoader classLoader) {
final Class ejbClass = loadClass(classLoader, ejbClassName);
// build a set of all field names
final Set<String> allFields = new TreeSet<>();
for (final CmpField cmpField : bean.getCmpField()) {
allFields.add(cmpField.getFieldName());
}
// build a map from the field name to the super class that contains that field
final Map<String, MappedSuperclass> superclassByField = mapFields(ejbClass, allFields);
//
// id: the primary key
//
final Set<String> primaryKeyFields = new HashSet<>();
if (bean.getPrimkeyField() != null) {
final String fieldName = bean.getPrimkeyField();
final MappedSuperclass superclass = superclassByField.get(fieldName);
if (superclass == null) {
throw new IllegalStateException("Primary key field " + fieldName + " is not defined in class " + ejbClassName + " or any super classes");
}
superclass.addField(new Id(fieldName));
mapping.addField(new AttributeOverride(fieldName));
primaryKeyFields.add(fieldName);
} else if ("java.lang.Object".equals(bean.getPrimKeyClass())) {
// a primary field type of Object is an automatically generated
// pk field. Mark it as such and add it to the mapping.
final String fieldName = "OpenEJB_pk";
final Id field = new Id(fieldName);
field.setGeneratedValue(new GeneratedValue(GenerationType.AUTO));
mapping.addField(field);
} else if (bean.getPrimKeyClass() != null) {
// we have a primary key class. We need to define the mappings between the key class fields
// and the bean's managed fields.
Class<?> pkClass = null;
try {
pkClass = classLoader.loadClass(bean.getPrimKeyClass());
MappedSuperclass superclass = null;
MappedSuperclass idclass = null;
for (final Field pkField : pkClass.getFields()) {
final String fieldName = pkField.getName();
final int modifiers = pkField.getModifiers();
// AND must also exist in the class hierarchy (not enforced by mapFields());
if (Modifier.isPublic(modifiers) && !Modifier.isStatic(modifiers) && allFields.contains(fieldName)) {
superclass = superclassByField.get(fieldName);
if (superclass == null) {
throw new IllegalStateException("Primary key field " + fieldName + " is not defined in class " + ejbClassName + " or any super classes");
}
// these are defined ast ID fields because they are part of the primary key
superclass.addField(new Id(fieldName));
mapping.addField(new AttributeOverride(fieldName));
primaryKeyFields.add(fieldName);
idclass = resolveIdClass(idclass, superclass, ejbClass);
}
}
// if we've located an ID class, set it as such
if (idclass != null) {
idclass.setIdClass(new IdClass(bean.getPrimKeyClass()));
}
} catch (final ClassNotFoundException e) {
throw (IllegalStateException) new IllegalStateException("Could not find entity primary key class " + bean.getPrimKeyClass()).initCause(e);
}
}
//
for (final CmpField cmpField : bean.getCmpField()) {
final String fieldName = cmpField.getFieldName();
// all of the primary key fields have been processed, so only handle whatever is left over
if (!primaryKeyFields.contains(fieldName)) {
final MappedSuperclass superclass = superclassByField.get(fieldName);
if (superclass == null) {
throw new IllegalStateException("CMP field " + fieldName + " is not defined in class " + ejbClassName + " or any super classes");
}
superclass.addField(new Basic(fieldName));
mapping.addField(new AttributeOverride(fieldName));
}
}
// the field mappings
return new HashSet<>(superclassByField.values());
}
use of org.apache.openejb.jee.jpa.MappedSuperclass in project tomee by apache.
the class CmpJpaConversion method processEntityBean.
/**
* Generate the CMP mapping data for an individual
* EntityBean.
*
* @param ejbModule The module containing the bean.
* @param ignoreClasses
* @param entityMappings The accumulated set of entity mappings.
* @param bean The been we're generating the mapping for.
*/
private void processEntityBean(final EjbModule ejbModule, final Collection<String> ignoreClasses, final EntityMappings entityMappings, final EntityBean bean) {
// try to add a new persistence-context-ref for cmp
if (!addPersistenceContextRef(bean)) {
// which means it has a mapping, so skip this bean
return;
}
// get the real bean class
final Class ejbClass = loadClass(ejbModule.getClassLoader(), bean.getEjbClass());
// and generate a name for the subclass that will be generated and handed to the JPA
// engine as the managed class.
final String jpaEntityClassName = CmpUtil.getCmpImplClassName(bean.getAbstractSchemaName(), ejbClass.getName());
// We don't use this mapping directly, instead we pull entries from it
// the reason being is that we intend to support mappings that aren't
// exactly correct. i.e. users should be able to write mappings completely
// ignorant of the fact that we subclass. The fact that we subclass means
// these user supplied mappings might need to be adjusted as the jpa orm.xml
// file is extremely subclass/supperclass aware and mappings specified in it
// need to be spot on.
final EntityMappings userMappings = getUserEntityMappings(ejbModule);
// chain of the bean looking for any that have user defined mappings.
for (Class clazz = ejbClass; clazz != null; clazz = clazz.getSuperclass()) {
final MappedSuperclass mappedSuperclass = removeMappedSuperclass(userMappings, clazz.getName());
// that the mapping is correct. Copy it from their mappings to ours
if (mappedSuperclass != null) {
entityMappings.getMappedSuperclass().add(mappedSuperclass);
}
}
// Check that this mapping hasn't already been defined in another mapping file on the persistence unit
if (ignoreClasses.contains(jpaEntityClassName)) {
return;
}
// Look for an existing mapping using the openejb generated subclass name
Entity entity = removeEntity(userMappings, jpaEntityClassName);
// because we are going to ignore all other xml metadata.
if (entity != null) {
// XmlMetadataComplete is an OpenEJB specific flag that
// tells all other legacy descriptor converters to keep
// their hands off.
entity.setXmlMetadataComplete(true);
entityMappings.getEntity().add(entity);
return;
}
if (entity == null) {
entity = new Entity(jpaEntityClassName);
}
// have to check for null everywhere.
if (entity.getAttributes() == null) {
entity.setAttributes(new Attributes());
}
// add the entity
entityMappings.getEntity().add(entity);
// OVERWRITE: description: contains the name of the entity bean
entity.setDescription(ejbModule.getModuleId() + "#" + bean.getEjbName());
// PRESERVE has queries: name: the name of the entity in queries
final String entityName = bean.getAbstractSchemaName();
entity.setName(entityName);
entity.setEjbName(bean.getEjbName());
final ClassLoader classLoader = ejbModule.getClassLoader();
final Collection<MappedSuperclass> mappedSuperclasses;
if (bean.getCmpVersion() == CmpVersion.CMP2) {
// perform the 2.x class mapping. This really just identifies the primary key and
// other cmp fields that will be generated for the concrete class and identify them
// to JPA.
mappedSuperclasses = mapClass2x(entity, bean, classLoader);
} else {
// map the cmp class, but if we are using a mapped super class,
// generate attribute-override instead of id and basic
mappedSuperclasses = mapClass1x(bean.getEjbClass(), entity, bean, classLoader);
}
// configuration. f
if (mappedSuperclasses != null) {
// that will get passed to the JPA engine.
for (final MappedSuperclass mappedSuperclass : mappedSuperclasses) {
entityMappings.getMappedSuperclass().add(mappedSuperclass);
}
}
// process queries
for (final Query query : bean.getQuery()) {
final NamedQuery namedQuery = new NamedQuery();
final QueryMethod queryMethod = query.getQueryMethod();
// todo deployment id could change in one of the later conversions... use entity name instead, but we need to save it off
final StringBuilder name = new StringBuilder();
name.append(entityName).append(".").append(queryMethod.getMethodName());
if (queryMethod.getMethodParams() != null && !queryMethod.getMethodParams().getMethodParam().isEmpty()) {
name.append('(');
boolean first = true;
for (final String methodParam : queryMethod.getMethodParams().getMethodParam()) {
if (!first) {
name.append(",");
}
name.append(methodParam);
first = false;
}
name.append(')');
}
namedQuery.setName(name.toString());
namedQuery.setQuery(query.getEjbQl());
entity.getNamedQuery().add(namedQuery);
}
// todo: there should be a common interface between ejb query object and openejb query object
final OpenejbJar openejbJar = ejbModule.getOpenejbJar();
final EjbDeployment ejbDeployment = openejbJar.getDeploymentsByEjbName().get(bean.getEjbName());
if (ejbDeployment != null) {
for (final org.apache.openejb.jee.oejb3.Query query : ejbDeployment.getQuery()) {
final NamedQuery namedQuery = new NamedQuery();
final org.apache.openejb.jee.oejb3.QueryMethod queryMethod = query.getQueryMethod();
// todo deployment id could change in one of the later conversions... use entity name instead, but we need to save it off
final StringBuilder name = new StringBuilder();
name.append(entityName).append(".").append(queryMethod.getMethodName());
if (queryMethod.getMethodParams() != null && !queryMethod.getMethodParams().getMethodParam().isEmpty()) {
name.append('(');
boolean first = true;
for (final String methodParam : queryMethod.getMethodParams().getMethodParam()) {
if (!first) {
name.append(",");
}
name.append(methodParam);
first = false;
}
name.append(')');
}
namedQuery.setName(name.toString());
namedQuery.setQuery(query.getObjectQl());
entity.getNamedQuery().add(namedQuery);
}
}
}
Aggregations