HHH-6173 allow embeddable classes to use inheritance as well
This commit is contained in:
parent
1ec38d23ab
commit
ff312720ce
|
@ -135,12 +135,11 @@ public class AnnotationBinder implements Binder {
|
|||
@Override
|
||||
public void bindMappingMetadata(MetadataSources sources, List<String> processedEntityNames) {
|
||||
// need to order our annotated entities into an order we can process
|
||||
Set<ConfiguredClassHierarchy> hierarchies = ConfiguredClassHierarchyBuilder.createEntityHierarchies(
|
||||
index, metadata.getServiceRegistry()
|
||||
);
|
||||
AnnotationBindingContext context = new AnnotationBindingContext( index, metadata.getServiceRegistry() );
|
||||
Set<ConfiguredClassHierarchy<EntityClass>> hierarchies = ConfiguredClassHierarchyBuilder.createEntityHierarchies( context );
|
||||
|
||||
// now we process each hierarchy one at the time
|
||||
for ( ConfiguredClassHierarchy hierarchy : hierarchies ) {
|
||||
for ( ConfiguredClassHierarchy<EntityClass> hierarchy : hierarchies ) {
|
||||
for ( EntityClass entityClass : hierarchy ) {
|
||||
LOG.bindingEntityFromAnnotatedClass( entityClass.getName() );
|
||||
EntityBinder entityBinder = new EntityBinder( metadata, entityClass );
|
||||
|
|
|
@ -58,6 +58,10 @@ public class AnnotationBindingContext {
|
|||
this.resolvedTypeCache = new HashMap<Class<?>, ResolvedType>();
|
||||
}
|
||||
|
||||
public Index getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
public ClassLoaderService classLoaderService() {
|
||||
if ( classLoaderService == null ) {
|
||||
classLoaderService = serviceRegistry.getService( ClassLoaderService.class );
|
||||
|
@ -70,6 +74,10 @@ public class AnnotationBindingContext {
|
|||
return index.getClassByName( dotName );
|
||||
}
|
||||
|
||||
public Class<?> loadClass(String className) {
|
||||
return classLoaderService.classForName( className );
|
||||
}
|
||||
|
||||
public void resolveAllTypes(String className) {
|
||||
// the resolved type for the top level class in the hierarchy
|
||||
Class<?> clazz = classLoaderService().classForName( className );
|
||||
|
|
|
@ -57,6 +57,7 @@ import org.hibernate.metamodel.source.annotations.attribute.AssociationAttribute
|
|||
import org.hibernate.metamodel.source.annotations.attribute.AttributeType;
|
||||
import org.hibernate.metamodel.source.annotations.attribute.MappedAttribute;
|
||||
import org.hibernate.metamodel.source.annotations.attribute.SimpleAttribute;
|
||||
import org.hibernate.metamodel.source.annotations.util.ConfiguredClassHierarchyBuilder;
|
||||
import org.hibernate.metamodel.source.annotations.util.JandexHelper;
|
||||
import org.hibernate.metamodel.source.annotations.util.ReflectionHelper;
|
||||
|
||||
|
@ -66,6 +67,12 @@ import org.hibernate.metamodel.source.annotations.util.ReflectionHelper;
|
|||
* @author Hardy Ferentschik
|
||||
*/
|
||||
public class ConfiguredClass {
|
||||
|
||||
/**
|
||||
* The parent of this configured class or {@code null} in case this configured class is the root of a hierarchy.
|
||||
*/
|
||||
private final ConfiguredClass parent;
|
||||
|
||||
/**
|
||||
* The Jandex class info for this configured class. Provides access to the annotation defined on this configured class.
|
||||
*/
|
||||
|
@ -104,7 +111,7 @@ public class ConfiguredClass {
|
|||
/**
|
||||
* The embedded classes for this entity
|
||||
*/
|
||||
private final Map<String, EmbeddedClass> embeddedClasses = new HashMap<String, EmbeddedClass>();
|
||||
private final Map<String, EmbeddableClass> embeddedClasses = new HashMap<String, EmbeddableClass>();
|
||||
|
||||
private final Set<String> transientFieldNames = new HashSet<String>();
|
||||
private final Set<String> transientMethodNames = new HashSet<String>();
|
||||
|
@ -113,7 +120,9 @@ public class ConfiguredClass {
|
|||
|
||||
public ConfiguredClass(ClassInfo classInfo,
|
||||
AccessType defaultAccessType,
|
||||
ConfiguredClass parent,
|
||||
AnnotationBindingContext context) {
|
||||
this.parent = parent;
|
||||
this.context = context;
|
||||
this.classInfo = classInfo;
|
||||
this.clazz = context.classLoaderService().classForName( classInfo.toString() );
|
||||
|
@ -148,6 +157,14 @@ public class ConfiguredClass {
|
|||
return classInfo;
|
||||
}
|
||||
|
||||
public ConfiguredClass getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public boolean isRoot() {
|
||||
return parent == null;
|
||||
}
|
||||
|
||||
public ConfiguredClassType getConfiguredClassType() {
|
||||
return configuredClassType;
|
||||
}
|
||||
|
@ -156,7 +173,7 @@ public class ConfiguredClass {
|
|||
return mappedAttributes.values();
|
||||
}
|
||||
|
||||
public Map<String, EmbeddedClass> getEmbeddedClasses() {
|
||||
public Map<String, EmbeddableClass> getEmbeddedClasses() {
|
||||
return embeddedClasses;
|
||||
}
|
||||
|
||||
|
@ -172,8 +189,6 @@ public class ConfiguredClass {
|
|||
sb.append( ", classAccessType=" ).append( classAccessType );
|
||||
sb.append( ", configuredClassType=" ).append( configuredClassType );
|
||||
sb.append( ", mappedAttributes=" ).append( mappedAttributes );
|
||||
sb.append( ", transientFieldNames=" ).append( transientFieldNames );
|
||||
sb.append( ", transientMethodNames=" ).append( transientMethodNames );
|
||||
sb.append( '}' );
|
||||
return sb.toString();
|
||||
}
|
||||
|
@ -391,15 +406,12 @@ public class ConfiguredClass {
|
|||
}
|
||||
|
||||
context.resolveAllTypes( type.getName() );
|
||||
EmbeddedClass embeddedClass = new EmbeddedClass(
|
||||
embeddableClassInfo,
|
||||
ConfiguredClassHierarchy<EmbeddableClass> hierarchy = ConfiguredClassHierarchyBuilder.createEmbeddableHierarchy(
|
||||
context.loadClass( embeddableClassInfo.toString() ),
|
||||
classAccessType,
|
||||
attributeOverrides,
|
||||
associationOverrides,
|
||||
context
|
||||
);
|
||||
|
||||
embeddedClasses.put( attributeName, embeddedClass );
|
||||
embeddedClasses.put( attributeName, hierarchy.getLeaf() );
|
||||
}
|
||||
// TODO handle the different association types
|
||||
default: {
|
||||
|
|
|
@ -44,30 +44,56 @@ import org.hibernate.metamodel.source.annotations.util.JandexHelper;
|
|||
*
|
||||
* @author Hardy Ferentschik
|
||||
*/
|
||||
public class ConfiguredClassHierarchy implements Iterable<EntityClass> {
|
||||
public class ConfiguredClassHierarchy<T extends ConfiguredClass> implements Iterable<T> {
|
||||
private final AccessType defaultAccessType;
|
||||
private final InheritanceType inheritanceType;
|
||||
private final List<EntityClass> entityClasses;
|
||||
private final List<T> configuredClasses;
|
||||
|
||||
public static ConfiguredClassHierarchy create(List<ClassInfo> classes, AnnotationBindingContext context) {
|
||||
return new ConfiguredClassHierarchy( classes, context );
|
||||
public static ConfiguredClassHierarchy<EntityClass> createEntityClassHierarchy(List<ClassInfo> classInfoList, AnnotationBindingContext context) {
|
||||
AccessType defaultAccessType = determineDefaultAccessType( classInfoList );
|
||||
InheritanceType inheritanceType = determineInheritanceType( classInfoList );
|
||||
return new ConfiguredClassHierarchy<EntityClass>(
|
||||
classInfoList,
|
||||
context,
|
||||
defaultAccessType,
|
||||
inheritanceType,
|
||||
EntityClass.class
|
||||
);
|
||||
}
|
||||
|
||||
private ConfiguredClassHierarchy(List<ClassInfo> classInfoList, AnnotationBindingContext context) {
|
||||
defaultAccessType = determineDefaultAccessType( classInfoList );
|
||||
inheritanceType = determineInheritanceType( classInfoList );
|
||||
public static ConfiguredClassHierarchy<EmbeddableClass> createEmbeddableClassHierarchy(List<ClassInfo> classes, AccessType accessType, AnnotationBindingContext context) {
|
||||
return new ConfiguredClassHierarchy<EmbeddableClass>(
|
||||
classes,
|
||||
context,
|
||||
accessType,
|
||||
InheritanceType.NO_INHERITANCE,
|
||||
EmbeddableClass.class
|
||||
);
|
||||
}
|
||||
|
||||
private ConfiguredClassHierarchy(List<ClassInfo> classInfoList, AnnotationBindingContext context, AccessType defaultAccessType, InheritanceType inheritanceType, Class<T> configuredClassType) {
|
||||
this.defaultAccessType = defaultAccessType;
|
||||
this.inheritanceType = inheritanceType;
|
||||
|
||||
// the resolved type for the top level class in the hierarchy
|
||||
context.resolveAllTypes( classInfoList.get( classInfoList.size() - 1 ).name().toString() );
|
||||
|
||||
entityClasses = new ArrayList<EntityClass>();
|
||||
EntityClass parent = null;
|
||||
configuredClasses = new ArrayList<T>();
|
||||
T parent = null;
|
||||
for ( ClassInfo info : classInfoList ) {
|
||||
EntityClass entityClass = new EntityClass(
|
||||
info, parent, defaultAccessType, inheritanceType, context
|
||||
);
|
||||
entityClasses.add( entityClass );
|
||||
parent = entityClass;
|
||||
T configuredClass;
|
||||
if ( EntityClass.class.equals( configuredClassType ) ) {
|
||||
configuredClass = (T) new EntityClass(
|
||||
info, (EntityClass) parent, defaultAccessType, inheritanceType, context
|
||||
);
|
||||
}
|
||||
else {
|
||||
configuredClass = (T) new EmbeddableClass(
|
||||
info, (EmbeddableClass) parent, defaultAccessType, context
|
||||
);
|
||||
}
|
||||
configuredClasses.add( configuredClass );
|
||||
parent = configuredClass;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -82,8 +108,22 @@ public class ConfiguredClassHierarchy implements Iterable<EntityClass> {
|
|||
/**
|
||||
* @return An iterator iterating in top down manner over the configured classes in this hierarchy.
|
||||
*/
|
||||
public Iterator<EntityClass> iterator() {
|
||||
return entityClasses.iterator();
|
||||
public Iterator<T> iterator() {
|
||||
return configuredClasses.iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the top level configured class
|
||||
*/
|
||||
public T getRoot() {
|
||||
return configuredClasses.get( 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the leaf configured class
|
||||
*/
|
||||
public T getLeaf() {
|
||||
return configuredClasses.get( configuredClasses.size() - 1 );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -91,7 +131,7 @@ public class ConfiguredClassHierarchy implements Iterable<EntityClass> {
|
|||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append( "ConfiguredClassHierarchy" );
|
||||
sb.append( "{defaultAccessType=" ).append( defaultAccessType );
|
||||
sb.append( ", configuredClasses=" ).append( entityClasses );
|
||||
sb.append( ", configuredClasses=" ).append( configuredClasses );
|
||||
sb.append( '}' );
|
||||
return sb.toString();
|
||||
}
|
||||
|
@ -103,7 +143,7 @@ public class ConfiguredClassHierarchy implements Iterable<EntityClass> {
|
|||
* {@code AccessType} annotations. The default access type is determined by the placement of the
|
||||
* annotations.
|
||||
*/
|
||||
private AccessType determineDefaultAccessType(List<ClassInfo> classes) {
|
||||
private static AccessType determineDefaultAccessType(List<ClassInfo> classes) {
|
||||
AccessType accessType = null;
|
||||
for ( ClassInfo info : classes ) {
|
||||
List<AnnotationInstance> idAnnotations = info.annotations().get( JPADotNames.ID );
|
||||
|
@ -120,7 +160,7 @@ public class ConfiguredClassHierarchy implements Iterable<EntityClass> {
|
|||
return accessType;
|
||||
}
|
||||
|
||||
private AccessType determineAccessTypeByIdPlacement(List<AnnotationInstance> idAnnotations) {
|
||||
private static AccessType determineAccessTypeByIdPlacement(List<AnnotationInstance> idAnnotations) {
|
||||
AccessType accessType = null;
|
||||
for ( AnnotationInstance annotation : idAnnotations ) {
|
||||
AccessType tmpAccessType;
|
||||
|
@ -146,7 +186,7 @@ public class ConfiguredClassHierarchy implements Iterable<EntityClass> {
|
|||
return accessType;
|
||||
}
|
||||
|
||||
private InheritanceType determineInheritanceType(List<ClassInfo> classes) {
|
||||
private static InheritanceType determineInheritanceType(List<ClassInfo> classes) {
|
||||
if ( classes.size() == 1 ) {
|
||||
return InheritanceType.NO_INHERITANCE;
|
||||
}
|
||||
|
@ -190,14 +230,14 @@ public class ConfiguredClassHierarchy implements Iterable<EntityClass> {
|
|||
return inheritanceType;
|
||||
}
|
||||
|
||||
private AccessType throwIdNotFoundAnnotationException(List<ClassInfo> classes) {
|
||||
private static AccessType throwIdNotFoundAnnotationException(List<ClassInfo> classes) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append( "Unable to determine identifier attribute for class hierarchy consisting of the classe(s) " );
|
||||
builder.append( hierarchyListString( classes ) );
|
||||
throw new AnnotationException( builder.toString() );
|
||||
}
|
||||
|
||||
private String hierarchyListString(List<ClassInfo> classes) {
|
||||
private static String hierarchyListString(List<ClassInfo> classes) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append( "[" );
|
||||
|
||||
|
|
|
@ -23,10 +23,8 @@
|
|||
*/
|
||||
package org.hibernate.metamodel.source.annotations.entity;
|
||||
|
||||
import java.util.List;
|
||||
import javax.persistence.AccessType;
|
||||
|
||||
import org.jboss.jandex.AnnotationInstance;
|
||||
import org.jboss.jandex.ClassInfo;
|
||||
|
||||
import org.hibernate.metamodel.source.annotations.AnnotationBindingContext;
|
||||
|
@ -34,14 +32,13 @@ import org.hibernate.metamodel.source.annotations.AnnotationBindingContext;
|
|||
/**
|
||||
* @author Hardy Ferentschik
|
||||
*/
|
||||
public class EmbeddedClass extends ConfiguredClass {
|
||||
public class EmbeddableClass extends ConfiguredClass {
|
||||
// todo - need to take care of the attribute path (HF)
|
||||
public EmbeddedClass(ClassInfo classInfo,
|
||||
AccessType defaultAccessType,
|
||||
List<AnnotationInstance> attributeOverrides,
|
||||
List<AnnotationInstance> associationOverrides,
|
||||
AnnotationBindingContext context) {
|
||||
super( classInfo, defaultAccessType, context );
|
||||
public EmbeddableClass(ClassInfo classInfo,
|
||||
EmbeddableClass parent,
|
||||
AccessType defaultAccessType,
|
||||
AnnotationBindingContext context) {
|
||||
super( classInfo, defaultAccessType, parent, context );
|
||||
}
|
||||
}
|
||||
|
|
@ -574,9 +574,9 @@ public class EntityBinder {
|
|||
}
|
||||
|
||||
private void bindEmbeddedAttributes(EntityBinding entityBinding) {
|
||||
for ( Map.Entry<String, EmbeddedClass> entry : entityClass.getEmbeddedClasses().entrySet() ) {
|
||||
for ( Map.Entry<String, EmbeddableClass> entry : entityClass.getEmbeddedClasses().entrySet() ) {
|
||||
String attributeName = entry.getKey();
|
||||
EmbeddedClass embeddedClass = entry.getValue();
|
||||
EmbeddableClass embeddedClass = entry.getValue();
|
||||
SingularAttribute component = entityBinding.getEntity().getOrCreateComponentAttribute( attributeName );
|
||||
for ( MappedAttribute mappedAttribute : embeddedClass.getMappedAttributes() ) {
|
||||
if ( mappedAttribute instanceof AssociationAttribute ) {
|
||||
|
|
|
@ -26,7 +26,6 @@ package org.hibernate.metamodel.source.annotations.entity;
|
|||
import java.util.List;
|
||||
import javax.persistence.AccessType;
|
||||
|
||||
import com.fasterxml.classmate.ResolvedTypeWithMembers;
|
||||
import org.jboss.jandex.AnnotationInstance;
|
||||
import org.jboss.jandex.AnnotationValue;
|
||||
import org.jboss.jandex.ClassInfo;
|
||||
|
@ -44,12 +43,6 @@ import org.hibernate.metamodel.source.annotations.util.JandexHelper;
|
|||
* @author Hardy Ferentschik
|
||||
*/
|
||||
public class EntityClass extends ConfiguredClass {
|
||||
/**
|
||||
* The parent of this configured class or {@code null} in case this configured class is the root of a hierarchy.
|
||||
*/
|
||||
private final EntityClass parent;
|
||||
|
||||
private final boolean isRoot;
|
||||
private final AccessType hierarchyAccessType;
|
||||
|
||||
private final InheritanceType inheritanceType;
|
||||
|
@ -64,9 +57,7 @@ public class EntityClass extends ConfiguredClass {
|
|||
InheritanceType inheritanceType,
|
||||
AnnotationBindingContext context) {
|
||||
|
||||
super( classInfo, hierarchyAccessType, context );
|
||||
this.parent = parent;
|
||||
this.isRoot = parent == null;
|
||||
super( classInfo, hierarchyAccessType, parent, context );
|
||||
this.hierarchyAccessType = hierarchyAccessType;
|
||||
this.inheritanceType = inheritanceType;
|
||||
this.idType = determineIdType();
|
||||
|
@ -75,14 +66,6 @@ public class EntityClass extends ConfiguredClass {
|
|||
this.primaryTableName = determinePrimaryTableName();
|
||||
}
|
||||
|
||||
public EntityClass getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public boolean isRoot() {
|
||||
return isRoot;
|
||||
}
|
||||
|
||||
public InheritanceType getInheritanceType() {
|
||||
return inheritanceType;
|
||||
}
|
||||
|
@ -104,7 +87,6 @@ public class EntityClass extends ConfiguredClass {
|
|||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append( "EntityClass" );
|
||||
sb.append( "{name=" ).append( getName() );
|
||||
sb.append( ", isRoot=" ).append( isRoot );
|
||||
sb.append( ", hierarchyAccessType=" ).append( hierarchyAccessType );
|
||||
sb.append( ", inheritanceType=" ).append( inheritanceType );
|
||||
sb.append( ", hasOwnTable=" ).append( hasOwnTable );
|
||||
|
@ -142,10 +124,10 @@ public class EntityClass extends ConfiguredClass {
|
|||
}
|
||||
}
|
||||
}
|
||||
else if ( parent != null
|
||||
&& !parent.getConfiguredClassType().equals( ConfiguredClassType.MAPPED_SUPERCLASS )
|
||||
&& !parent.getConfiguredClassType().equals( ConfiguredClassType.EMBEDDABLE ) ) {
|
||||
tableName = parent.getPrimaryTableName();
|
||||
else if ( getParent() != null
|
||||
&& !getParent().getConfiguredClassType().equals( ConfiguredClassType.MAPPED_SUPERCLASS )
|
||||
&& !getParent().getConfiguredClassType().equals( ConfiguredClassType.EMBEDDABLE ) ) {
|
||||
tableName = ( (EntityClass) getParent() ).getPrimaryTableName();
|
||||
}
|
||||
return tableName;
|
||||
}
|
||||
|
|
|
@ -24,5 +24,5 @@
|
|||
package org.hibernate.metamodel.source.annotations;
|
||||
|
||||
/**
|
||||
* This package contains the binding code for binding annotation based configuration to the Hibernate metamodel.
|
||||
* This package and its sub-packages contains the binding code for binding annotation based configuration to the Hibernate metamodel.
|
||||
*/
|
|
@ -30,51 +30,55 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.AccessType;
|
||||
|
||||
import org.jboss.jandex.AnnotationInstance;
|
||||
import org.jboss.jandex.ClassInfo;
|
||||
import org.jboss.jandex.DotName;
|
||||
import org.jboss.jandex.Index;
|
||||
|
||||
import org.hibernate.AnnotationException;
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.metamodel.source.annotations.AnnotationBindingContext;
|
||||
import org.hibernate.metamodel.source.annotations.JPADotNames;
|
||||
import org.hibernate.metamodel.source.annotations.entity.ConfiguredClassHierarchy;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
import org.hibernate.metamodel.source.annotations.entity.EmbeddableClass;
|
||||
import org.hibernate.metamodel.source.annotations.entity.EntityClass;
|
||||
import org.hibernate.service.classloading.spi.ClassLoaderService;
|
||||
|
||||
/**
|
||||
* Given a annotation index build a set of class hierarchies.
|
||||
* Given a (jandex) annotation index build processes all classes with JPA relevant annotations and pre-orders
|
||||
* JPA entities respectively their inheritance hierarchy.
|
||||
*
|
||||
* @author Hardy Ferentschik
|
||||
*/
|
||||
public class ConfiguredClassHierarchyBuilder {
|
||||
|
||||
/**
|
||||
* This methods pre-processes the annotated entities from the index and put them into a structure which can
|
||||
* Pre-processes the annotated entities from the index and put them into a structure which can
|
||||
* bound to the Hibernate metamodel.
|
||||
*
|
||||
* @param index The annotation index
|
||||
* @param serviceRegistry The service registry
|
||||
* @param context the annotation binding context with access to the service registry and the annotation index
|
||||
*
|
||||
* @return a set of {@code ConfiguredClassHierarchy}s. One for each "leaf" entity.
|
||||
*/
|
||||
public static Set<ConfiguredClassHierarchy> createEntityHierarchies(Index index, ServiceRegistry serviceRegistry) {
|
||||
ClassLoaderService classLoaderService = serviceRegistry.getService( ClassLoaderService.class );
|
||||
public static Set<ConfiguredClassHierarchy<EntityClass>> createEntityHierarchies(AnnotationBindingContext context) {
|
||||
ClassLoaderService classLoaderService = context.classLoaderService();
|
||||
Map<ClassInfo, List<ClassInfo>> processedClassInfos = new HashMap<ClassInfo, List<ClassInfo>>();
|
||||
|
||||
for ( ClassInfo info : index.getKnownClasses() ) {
|
||||
if ( !isConfiguredClass( info ) ) {
|
||||
for ( ClassInfo info : context.getIndex().getKnownClasses() ) {
|
||||
if ( !isEntityClass( info ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( processedClassInfos.containsKey( info ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
List<ClassInfo> configuredClassList = new ArrayList<ClassInfo>();
|
||||
ClassInfo tmpClassInfo = info;
|
||||
Class<?> clazz = classLoaderService.classForName( tmpClassInfo.toString() );
|
||||
while ( clazz != null && !clazz.equals( Object.class ) ) {
|
||||
tmpClassInfo = index.getClassByName( DotName.createSimple( clazz.getName() ) );
|
||||
tmpClassInfo = context.getIndex().getClassByName( DotName.createSimple( clazz.getName() ) );
|
||||
clazz = clazz.getSuperclass();
|
||||
if ( tmpClassInfo == null ) {
|
||||
continue;
|
||||
|
@ -95,12 +99,11 @@ public class ConfiguredClassHierarchyBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
AnnotationBindingContext context = new AnnotationBindingContext( index, serviceRegistry );
|
||||
Set<ConfiguredClassHierarchy> hierarchies = new HashSet<ConfiguredClassHierarchy>();
|
||||
Set<ConfiguredClassHierarchy<EntityClass>> hierarchies = new HashSet<ConfiguredClassHierarchy<EntityClass>>();
|
||||
List<List<ClassInfo>> processedList = new ArrayList<List<ClassInfo>>();
|
||||
for ( List<ClassInfo> classInfoList : processedClassInfos.values() ) {
|
||||
if ( !processedList.contains( classInfoList ) ) {
|
||||
hierarchies.add( ConfiguredClassHierarchy.create( classInfoList, context ) );
|
||||
hierarchies.add( ConfiguredClassHierarchy.createEntityClassHierarchy( classInfoList, context ) );
|
||||
processedList.add( classInfoList );
|
||||
}
|
||||
}
|
||||
|
@ -108,6 +111,52 @@ public class ConfiguredClassHierarchyBuilder {
|
|||
return hierarchies;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the configured class hierarchy for a an embeddable class.
|
||||
*
|
||||
* @param embeddableClass the top level embedded class
|
||||
* @param accessType the access type inherited from the class in which the embeddable gets embedded
|
||||
* @param context the annotation binding context with access to the service registry and the annotation index
|
||||
*
|
||||
* @return a set of {@code ConfiguredClassHierarchy}s. One for each "leaf" entity.
|
||||
*/
|
||||
public static ConfiguredClassHierarchy<EmbeddableClass> createEmbeddableHierarchy(Class<?> embeddableClass, AccessType accessType, AnnotationBindingContext context) {
|
||||
|
||||
ClassInfo embeddableClassInfo = context.getClassInfo( embeddableClass.getName() );
|
||||
if ( embeddableClassInfo == null ) {
|
||||
throw new AssertionFailure(
|
||||
String.format(
|
||||
"The specified class %s cannot be found in the annotation index",
|
||||
embeddableClass.getName()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if ( JandexHelper.getSingleAnnotation( embeddableClassInfo, JPADotNames.EMBEDDABLE ) == null ) {
|
||||
throw new AssertionFailure(
|
||||
String.format(
|
||||
"The specified class %s is not annotated with @Embeddable",
|
||||
embeddableClass.getName()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
List<ClassInfo> classInfoList = new ArrayList<ClassInfo>();
|
||||
ClassInfo tmpClassInfo;
|
||||
Class<?> clazz = embeddableClass;
|
||||
while ( clazz != null && !clazz.equals( Object.class ) ) {
|
||||
tmpClassInfo = context.getIndex().getClassByName( DotName.createSimple( clazz.getName() ) );
|
||||
clazz = clazz.getSuperclass();
|
||||
if ( tmpClassInfo == null ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
classInfoList.add( 0, tmpClassInfo );
|
||||
}
|
||||
|
||||
return ConfiguredClassHierarchy.createEmbeddableClassHierarchy( classInfoList, accessType, context );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the passed jandex class info needs to be processed.
|
||||
*
|
||||
|
@ -115,7 +164,7 @@ public class ConfiguredClassHierarchyBuilder {
|
|||
*
|
||||
* @return {@code true} if the class represented by {@code info} is relevant for the JPA mappings, {@code false} otherwise.
|
||||
*/
|
||||
private static boolean isConfiguredClass(ClassInfo info) {
|
||||
private static boolean isEntityClass(ClassInfo info) {
|
||||
boolean isConfiguredClass = true;
|
||||
AnnotationInstance jpaEntityAnnotation = JandexHelper.getSingleAnnotation( info, JPADotNames.ENTITY );
|
||||
AnnotationInstance mappedSuperClassAnnotation = JandexHelper.getSingleAnnotation(
|
||||
|
|
|
@ -40,6 +40,7 @@ import org.junit.Before;
|
|||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.metamodel.binding.InheritanceType;
|
||||
import org.hibernate.metamodel.source.annotations.AnnotationBindingContext;
|
||||
import org.hibernate.metamodel.source.annotations.util.ConfiguredClassHierarchyBuilder;
|
||||
import org.hibernate.metamodel.source.annotations.util.JandexHelper;
|
||||
import org.hibernate.service.ServiceRegistryBuilder;
|
||||
|
@ -84,8 +85,9 @@ public class TableNameTest extends BaseUnitTestCase {
|
|||
}
|
||||
|
||||
Index index = JandexHelper.indexForClass( service, A.class, B.class );
|
||||
Set<ConfiguredClassHierarchy> hierarchies = ConfiguredClassHierarchyBuilder.createEntityHierarchies(
|
||||
index, serviceRegistry
|
||||
AnnotationBindingContext context = new AnnotationBindingContext( index, serviceRegistry );
|
||||
Set<ConfiguredClassHierarchy<EntityClass>> hierarchies = ConfiguredClassHierarchyBuilder.createEntityHierarchies(
|
||||
context
|
||||
);
|
||||
assertEquals( "There should be only one hierarchy", 1, hierarchies.size() );
|
||||
|
||||
|
@ -131,8 +133,9 @@ public class TableNameTest extends BaseUnitTestCase {
|
|||
}
|
||||
|
||||
Index index = JandexHelper.indexForClass( service, A.class, B.class );
|
||||
Set<ConfiguredClassHierarchy> hierarchies = ConfiguredClassHierarchyBuilder.createEntityHierarchies(
|
||||
index, serviceRegistry
|
||||
AnnotationBindingContext context = new AnnotationBindingContext( index, serviceRegistry );
|
||||
Set<ConfiguredClassHierarchy<EntityClass>> hierarchies = ConfiguredClassHierarchyBuilder.createEntityHierarchies(
|
||||
context
|
||||
);
|
||||
assertEquals( "There should be only one hierarchy", 1, hierarchies.size() );
|
||||
|
||||
|
@ -179,8 +182,9 @@ public class TableNameTest extends BaseUnitTestCase {
|
|||
}
|
||||
|
||||
Index index = JandexHelper.indexForClass( service, B.class, A.class );
|
||||
Set<ConfiguredClassHierarchy> hierarchies = ConfiguredClassHierarchyBuilder.createEntityHierarchies(
|
||||
index, serviceRegistry
|
||||
AnnotationBindingContext context = new AnnotationBindingContext( index, serviceRegistry );
|
||||
Set<ConfiguredClassHierarchy<EntityClass>> hierarchies = ConfiguredClassHierarchyBuilder.createEntityHierarchies(
|
||||
context
|
||||
);
|
||||
assertEquals( "There should be only one hierarchy", 1, hierarchies.size() );
|
||||
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2010, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.metamodel.source.annotations.util;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.AccessType;
|
||||
|
||||
import org.jboss.jandex.Index;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
||||
import org.hibernate.metamodel.source.annotations.AnnotationBindingContext;
|
||||
import org.hibernate.metamodel.source.annotations.entity.ConfiguredClassHierarchy;
|
||||
import org.hibernate.metamodel.source.annotations.entity.EmbeddableClass;
|
||||
import org.hibernate.metamodel.source.annotations.entity.EntityClass;
|
||||
import org.hibernate.service.ServiceRegistryBuilder;
|
||||
import org.hibernate.service.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.service.internal.BasicServiceRegistryImpl;
|
||||
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
||||
|
||||
/**
|
||||
* @author Hardy Ferentschik
|
||||
*/
|
||||
public abstract class BaseAnnotationIndexTestCase extends BaseUnitTestCase {
|
||||
private BasicServiceRegistryImpl serviceRegistry;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
serviceRegistry = (BasicServiceRegistryImpl) new ServiceRegistryBuilder().buildServiceRegistry();
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
serviceRegistry.destroy();
|
||||
}
|
||||
|
||||
public Set<ConfiguredClassHierarchy<EntityClass>> createEntityHierarchies(Class<?>... clazz) {
|
||||
Index index = JandexHelper.indexForClass( serviceRegistry.getService( ClassLoaderService.class ), clazz );
|
||||
AnnotationBindingContext context = new AnnotationBindingContext( index, serviceRegistry );
|
||||
return ConfiguredClassHierarchyBuilder.createEntityHierarchies( context );
|
||||
}
|
||||
|
||||
public ConfiguredClassHierarchy<EmbeddableClass> createEmbeddableHierarchy(AccessType accessType, Class<?>... configuredClasses) {
|
||||
Index index = JandexHelper.indexForClass(
|
||||
serviceRegistry.getService( ClassLoaderService.class ),
|
||||
configuredClasses
|
||||
);
|
||||
AnnotationBindingContext context = new AnnotationBindingContext( index, serviceRegistry );
|
||||
return ConfiguredClassHierarchyBuilder.createEmbeddableHierarchy( configuredClasses[0], accessType, context );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -35,49 +35,28 @@ import javax.persistence.MappedSuperclass;
|
|||
|
||||
import org.jboss.jandex.ClassInfo;
|
||||
import org.jboss.jandex.DotName;
|
||||
import org.jboss.jandex.Index;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.AnnotationException;
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.metamodel.binding.InheritanceType;
|
||||
import org.hibernate.metamodel.source.annotations.entity.ConfiguredClassHierarchy;
|
||||
import org.hibernate.metamodel.source.annotations.entity.EmbeddableClass;
|
||||
import org.hibernate.metamodel.source.annotations.entity.EntityClass;
|
||||
import org.hibernate.service.ServiceRegistryBuilder;
|
||||
import org.hibernate.service.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.service.internal.BasicServiceRegistryImpl;
|
||||
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.assertNotNull;
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
|
||||
/**
|
||||
* @author Hardy Ferentschik
|
||||
*/
|
||||
public class ConfiguredClassHierarchyBuilderTest extends BaseUnitTestCase {
|
||||
|
||||
private BasicServiceRegistryImpl serviceRegistry;
|
||||
private ClassLoaderService classLoaderService;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
serviceRegistry = (BasicServiceRegistryImpl) new ServiceRegistryBuilder().buildServiceRegistry();
|
||||
classLoaderService = serviceRegistry.getService( ClassLoaderService.class );
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
serviceRegistry.destroy();
|
||||
}
|
||||
public class EmbeddableHierarchyTest extends BaseAnnotationIndexTestCase {
|
||||
|
||||
@Test
|
||||
public void testSingleEntity() {
|
||||
Index index = JandexHelper.indexForClass( classLoaderService, Foo.class );
|
||||
Set<ConfiguredClassHierarchy> hierarchies = ConfiguredClassHierarchyBuilder.createEntityHierarchies(
|
||||
index, serviceRegistry
|
||||
);
|
||||
Set<ConfiguredClassHierarchy<EntityClass>> hierarchies = createEntityHierarchies( Foo.class );
|
||||
assertEquals( "There should be only one hierarchy", 1, hierarchies.size() );
|
||||
|
||||
Iterator<EntityClass> iter = hierarchies.iterator().next().iterator();
|
||||
|
@ -88,10 +67,7 @@ public class ConfiguredClassHierarchyBuilderTest extends BaseUnitTestCase {
|
|||
|
||||
@Test
|
||||
public void testSimpleInheritance() {
|
||||
Index index = JandexHelper.indexForClass( classLoaderService, B.class, A.class );
|
||||
Set<ConfiguredClassHierarchy> hierarchies = ConfiguredClassHierarchyBuilder.createEntityHierarchies(
|
||||
index, serviceRegistry
|
||||
);
|
||||
Set<ConfiguredClassHierarchy<EntityClass>> hierarchies = createEntityHierarchies( B.class, A.class );
|
||||
assertEquals( "There should be only one hierarchy", 1, hierarchies.size() );
|
||||
|
||||
Iterator<EntityClass> iter = hierarchies.iterator().next().iterator();
|
||||
|
@ -104,10 +80,7 @@ public class ConfiguredClassHierarchyBuilderTest extends BaseUnitTestCase {
|
|||
|
||||
@Test
|
||||
public void testMultipleHierarchies() {
|
||||
Index index = JandexHelper.indexForClass( classLoaderService, B.class, A.class, Foo.class );
|
||||
Set<ConfiguredClassHierarchy> hierarchies = ConfiguredClassHierarchyBuilder.createEntityHierarchies(
|
||||
index, serviceRegistry
|
||||
);
|
||||
Set<ConfiguredClassHierarchy<EntityClass>> hierarchies = createEntityHierarchies( B.class, Foo.class, A.class );
|
||||
assertEquals( "There should be only one hierarchy", 2, hierarchies.size() );
|
||||
}
|
||||
|
||||
|
@ -129,11 +102,10 @@ public class ConfiguredClassHierarchyBuilderTest extends BaseUnitTestCase {
|
|||
private String mappedProperty;
|
||||
}
|
||||
|
||||
Index index = JandexHelper.indexForClass(
|
||||
classLoaderService, MappedSubClass.class, MappedSuperClass.class, UnmappedSubClass.class
|
||||
);
|
||||
Set<ConfiguredClassHierarchy> hierarchies = ConfiguredClassHierarchyBuilder.createEntityHierarchies(
|
||||
index, serviceRegistry
|
||||
Set<ConfiguredClassHierarchy<EntityClass>> hierarchies = createEntityHierarchies(
|
||||
MappedSubClass.class,
|
||||
MappedSuperClass.class,
|
||||
UnmappedSubClass.class
|
||||
);
|
||||
assertEquals( "There should be only one hierarchy", 1, hierarchies.size() );
|
||||
|
||||
|
@ -154,8 +126,7 @@ public class ConfiguredClassHierarchyBuilderTest extends BaseUnitTestCase {
|
|||
class EntityAndMappedSuperClass {
|
||||
}
|
||||
|
||||
Index index = JandexHelper.indexForClass( classLoaderService, EntityAndMappedSuperClass.class );
|
||||
ConfiguredClassHierarchyBuilder.createEntityHierarchies( index, serviceRegistry );
|
||||
createEntityHierarchies( EntityAndMappedSuperClass.class );
|
||||
}
|
||||
|
||||
@Test(expected = AnnotationException.class)
|
||||
|
@ -165,8 +136,7 @@ public class ConfiguredClassHierarchyBuilderTest extends BaseUnitTestCase {
|
|||
class EntityAndEmbeddable {
|
||||
}
|
||||
|
||||
Index index = JandexHelper.indexForClass( classLoaderService, EntityAndEmbeddable.class );
|
||||
ConfiguredClassHierarchyBuilder.createEntityHierarchies( index, serviceRegistry );
|
||||
createEntityHierarchies( EntityAndEmbeddable.class );
|
||||
}
|
||||
|
||||
@Test(expected = AnnotationException.class)
|
||||
|
@ -181,8 +151,7 @@ public class ConfiguredClassHierarchyBuilderTest extends BaseUnitTestCase {
|
|||
class B extends A {
|
||||
}
|
||||
|
||||
Index index = JandexHelper.indexForClass( classLoaderService, B.class, A.class );
|
||||
ConfiguredClassHierarchyBuilder.createEntityHierarchies( index, serviceRegistry );
|
||||
createEntityHierarchies( B.class, A.class );
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -197,10 +166,7 @@ public class ConfiguredClassHierarchyBuilderTest extends BaseUnitTestCase {
|
|||
class B extends A {
|
||||
}
|
||||
|
||||
Index index = JandexHelper.indexForClass( classLoaderService, B.class, A.class );
|
||||
Set<ConfiguredClassHierarchy> hierarchies = ConfiguredClassHierarchyBuilder.createEntityHierarchies(
|
||||
index, serviceRegistry
|
||||
);
|
||||
Set<ConfiguredClassHierarchy<EntityClass>> hierarchies = createEntityHierarchies( B.class, A.class );
|
||||
assertTrue( hierarchies.size() == 1 );
|
||||
ConfiguredClassHierarchy hierarchy = hierarchies.iterator().next();
|
||||
assertEquals( "Wrong default access type", AccessType.FIELD, hierarchy.getDefaultAccessType() );
|
||||
|
@ -226,10 +192,7 @@ public class ConfiguredClassHierarchyBuilderTest extends BaseUnitTestCase {
|
|||
class B extends A {
|
||||
}
|
||||
|
||||
Index index = JandexHelper.indexForClass( classLoaderService, B.class, A.class );
|
||||
Set<ConfiguredClassHierarchy> hierarchies = ConfiguredClassHierarchyBuilder.createEntityHierarchies(
|
||||
index, serviceRegistry
|
||||
);
|
||||
Set<ConfiguredClassHierarchy<EntityClass>> hierarchies = createEntityHierarchies( B.class, A.class );
|
||||
assertTrue( hierarchies.size() == 1 );
|
||||
ConfiguredClassHierarchy hierarchy = hierarchies.iterator().next();
|
||||
assertEquals( "Wrong default access type", AccessType.PROPERTY, hierarchy.getDefaultAccessType() );
|
||||
|
@ -247,10 +210,7 @@ public class ConfiguredClassHierarchyBuilderTest extends BaseUnitTestCase {
|
|||
class B extends A {
|
||||
}
|
||||
|
||||
Index index = JandexHelper.indexForClass( classLoaderService, B.class, A.class );
|
||||
Set<ConfiguredClassHierarchy> hierarchies = ConfiguredClassHierarchyBuilder.createEntityHierarchies(
|
||||
index, serviceRegistry
|
||||
);
|
||||
Set<ConfiguredClassHierarchy<EntityClass>> hierarchies = createEntityHierarchies( B.class, A.class );
|
||||
assertTrue( hierarchies.size() == 1 );
|
||||
ConfiguredClassHierarchy hierarchy = hierarchies.iterator().next();
|
||||
assertEquals( "Wrong inheritance type", InheritanceType.SINGLE_TABLE, hierarchy.getInheritanceType() );
|
||||
|
@ -275,9 +235,10 @@ public class ConfiguredClassHierarchyBuilderTest extends BaseUnitTestCase {
|
|||
class B extends A {
|
||||
}
|
||||
|
||||
Index index = JandexHelper.indexForClass( classLoaderService, B.class, MappedSuperClass.class, A.class );
|
||||
Set<ConfiguredClassHierarchy> hierarchies = ConfiguredClassHierarchyBuilder.createEntityHierarchies(
|
||||
index, serviceRegistry
|
||||
Set<ConfiguredClassHierarchy<EntityClass>> hierarchies = createEntityHierarchies(
|
||||
B.class,
|
||||
MappedSuperClass.class,
|
||||
A.class
|
||||
);
|
||||
assertTrue( hierarchies.size() == 1 );
|
||||
ConfiguredClassHierarchy hierarchy = hierarchies.iterator().next();
|
||||
|
@ -300,8 +261,47 @@ public class ConfiguredClassHierarchyBuilderTest extends BaseUnitTestCase {
|
|||
class B extends A {
|
||||
}
|
||||
|
||||
Index index = JandexHelper.indexForClass( classLoaderService, B.class, A.class );
|
||||
ConfiguredClassHierarchyBuilder.createEntityHierarchies( index, serviceRegistry );
|
||||
createEntityHierarchies( B.class, A.class );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmbeddableHierarchy() {
|
||||
@Embeddable
|
||||
class A {
|
||||
String foo;
|
||||
}
|
||||
|
||||
class B extends A {
|
||||
}
|
||||
|
||||
@Embeddable
|
||||
class C extends B {
|
||||
String bar;
|
||||
}
|
||||
|
||||
ConfiguredClassHierarchy<EmbeddableClass> hierarchy = createEmbeddableHierarchy(
|
||||
AccessType.FIELD,
|
||||
C.class,
|
||||
A.class,
|
||||
B.class
|
||||
);
|
||||
Iterator<EmbeddableClass> iter = hierarchy.iterator();
|
||||
ClassInfo info = iter.next().getClassInfo();
|
||||
assertEquals( "wrong class", DotName.createSimple( A.class.getName() ), info.name() );
|
||||
info = iter.next().getClassInfo();
|
||||
assertEquals( "wrong class", DotName.createSimple( B.class.getName() ), info.name() );
|
||||
info = iter.next().getClassInfo();
|
||||
assertEquals( "wrong class", DotName.createSimple( C.class.getName() ), info.name() );
|
||||
assertFalse( iter.hasNext() );
|
||||
assertNotNull( hierarchy );
|
||||
}
|
||||
|
||||
@Test(expected = AssertionFailure.class)
|
||||
public void testEmbeddableHierarchyWithNotAnnotatedEntity() {
|
||||
class NonAnnotatedEmbeddable {
|
||||
}
|
||||
|
||||
createEmbeddableHierarchy( AccessType.FIELD, NonAnnotatedEmbeddable.class );
|
||||
}
|
||||
|
||||
@Entity
|
|
@ -0,0 +1,327 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.metamodel.source.annotations.util;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import javax.persistence.AccessType;
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Inheritance;
|
||||
import javax.persistence.MappedSuperclass;
|
||||
|
||||
import org.jboss.jandex.ClassInfo;
|
||||
import org.jboss.jandex.DotName;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.AnnotationException;
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.metamodel.binding.InheritanceType;
|
||||
import org.hibernate.metamodel.source.annotations.entity.ConfiguredClassHierarchy;
|
||||
import org.hibernate.metamodel.source.annotations.entity.EmbeddableClass;
|
||||
import org.hibernate.metamodel.source.annotations.entity.EntityClass;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.assertNotNull;
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
|
||||
/**
|
||||
* @author Hardy Ferentschik
|
||||
*/
|
||||
public class EntityHierarchyTest extends BaseAnnotationIndexTestCase {
|
||||
|
||||
@Test
|
||||
public void testSingleEntity() {
|
||||
Set<ConfiguredClassHierarchy<EntityClass>> hierarchies = createEntityHierarchies( Foo.class );
|
||||
assertEquals( "There should be only one hierarchy", 1, hierarchies.size() );
|
||||
|
||||
Iterator<EntityClass> iter = hierarchies.iterator().next().iterator();
|
||||
ClassInfo info = iter.next().getClassInfo();
|
||||
assertEquals( "wrong class", DotName.createSimple( Foo.class.getName() ), info.name() );
|
||||
assertFalse( iter.hasNext() );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleInheritance() {
|
||||
Set<ConfiguredClassHierarchy<EntityClass>> hierarchies = createEntityHierarchies( B.class, A.class );
|
||||
assertEquals( "There should be only one hierarchy", 1, hierarchies.size() );
|
||||
|
||||
Iterator<EntityClass> iter = hierarchies.iterator().next().iterator();
|
||||
ClassInfo info = iter.next().getClassInfo();
|
||||
assertEquals( "wrong class", DotName.createSimple( A.class.getName() ), info.name() );
|
||||
info = iter.next().getClassInfo();
|
||||
assertEquals( "wrong class", DotName.createSimple( B.class.getName() ), info.name() );
|
||||
assertFalse( iter.hasNext() );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleHierarchies() {
|
||||
Set<ConfiguredClassHierarchy<EntityClass>> hierarchies = createEntityHierarchies( B.class, Foo.class, A.class );
|
||||
assertEquals( "There should be only one hierarchy", 2, hierarchies.size() );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMappedSuperClass() {
|
||||
@MappedSuperclass
|
||||
class MappedSuperClass {
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private int id;
|
||||
}
|
||||
|
||||
class UnmappedSubClass extends MappedSuperClass {
|
||||
private String unmappedProperty;
|
||||
}
|
||||
|
||||
@Entity
|
||||
class MappedSubClass extends UnmappedSubClass {
|
||||
private String mappedProperty;
|
||||
}
|
||||
|
||||
Set<ConfiguredClassHierarchy<EntityClass>> hierarchies = createEntityHierarchies(
|
||||
MappedSubClass.class,
|
||||
MappedSuperClass.class,
|
||||
UnmappedSubClass.class
|
||||
);
|
||||
assertEquals( "There should be only one hierarchy", 1, hierarchies.size() );
|
||||
|
||||
Iterator<EntityClass> iter = hierarchies.iterator().next().iterator();
|
||||
ClassInfo info = iter.next().getClassInfo();
|
||||
assertEquals( "wrong class", DotName.createSimple( MappedSuperClass.class.getName() ), info.name() );
|
||||
info = iter.next().getClassInfo();
|
||||
assertEquals( "wrong class", DotName.createSimple( UnmappedSubClass.class.getName() ), info.name() );
|
||||
info = iter.next().getClassInfo();
|
||||
assertEquals( "wrong class", DotName.createSimple( MappedSubClass.class.getName() ), info.name() );
|
||||
assertFalse( iter.hasNext() );
|
||||
}
|
||||
|
||||
@Test(expected = AnnotationException.class)
|
||||
public void testEntityAndMappedSuperClassAnnotations() {
|
||||
@Entity
|
||||
@MappedSuperclass
|
||||
class EntityAndMappedSuperClass {
|
||||
}
|
||||
|
||||
createEntityHierarchies( EntityAndMappedSuperClass.class );
|
||||
}
|
||||
|
||||
@Test(expected = AnnotationException.class)
|
||||
public void testEntityAndEmbeddableAnnotations() {
|
||||
@Entity
|
||||
@Embeddable
|
||||
class EntityAndEmbeddable {
|
||||
}
|
||||
|
||||
createEntityHierarchies( EntityAndEmbeddable.class );
|
||||
}
|
||||
|
||||
@Test(expected = AnnotationException.class)
|
||||
public void testNoIdAnnotation() {
|
||||
|
||||
@Entity
|
||||
class A {
|
||||
String id;
|
||||
}
|
||||
|
||||
@Entity
|
||||
class B extends A {
|
||||
}
|
||||
|
||||
createEntityHierarchies( B.class, A.class );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultFieldAccess() {
|
||||
@Entity
|
||||
class A {
|
||||
@Id
|
||||
String id;
|
||||
}
|
||||
|
||||
@Entity
|
||||
class B extends A {
|
||||
}
|
||||
|
||||
Set<ConfiguredClassHierarchy<EntityClass>> hierarchies = createEntityHierarchies( B.class, A.class );
|
||||
assertTrue( hierarchies.size() == 1 );
|
||||
ConfiguredClassHierarchy hierarchy = hierarchies.iterator().next();
|
||||
assertEquals( "Wrong default access type", AccessType.FIELD, hierarchy.getDefaultAccessType() );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultPropertyAccess() {
|
||||
@Entity
|
||||
class A {
|
||||
String id;
|
||||
|
||||
@Id
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity
|
||||
class B extends A {
|
||||
}
|
||||
|
||||
Set<ConfiguredClassHierarchy<EntityClass>> hierarchies = createEntityHierarchies( B.class, A.class );
|
||||
assertTrue( hierarchies.size() == 1 );
|
||||
ConfiguredClassHierarchy hierarchy = hierarchies.iterator().next();
|
||||
assertEquals( "Wrong default access type", AccessType.PROPERTY, hierarchy.getDefaultAccessType() );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultInheritanceStrategy() {
|
||||
@Entity
|
||||
class A {
|
||||
@Id
|
||||
String id;
|
||||
}
|
||||
|
||||
@Entity
|
||||
class B extends A {
|
||||
}
|
||||
|
||||
Set<ConfiguredClassHierarchy<EntityClass>> hierarchies = createEntityHierarchies( B.class, A.class );
|
||||
assertTrue( hierarchies.size() == 1 );
|
||||
ConfiguredClassHierarchy hierarchy = hierarchies.iterator().next();
|
||||
assertEquals( "Wrong inheritance type", InheritanceType.SINGLE_TABLE, hierarchy.getInheritanceType() );
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testExplicitInheritanceStrategy() {
|
||||
@MappedSuperclass
|
||||
class MappedSuperClass {
|
||||
|
||||
}
|
||||
|
||||
@Entity
|
||||
@Inheritance(strategy = javax.persistence.InheritanceType.JOINED)
|
||||
class A extends MappedSuperClass {
|
||||
@Id
|
||||
String id;
|
||||
}
|
||||
|
||||
@Entity
|
||||
class B extends A {
|
||||
}
|
||||
|
||||
Set<ConfiguredClassHierarchy<EntityClass>> hierarchies = createEntityHierarchies(
|
||||
B.class,
|
||||
MappedSuperClass.class,
|
||||
A.class
|
||||
);
|
||||
assertTrue( hierarchies.size() == 1 );
|
||||
ConfiguredClassHierarchy hierarchy = hierarchies.iterator().next();
|
||||
assertEquals(
|
||||
"Wrong inheritance type", InheritanceType.JOINED, hierarchy.getInheritanceType()
|
||||
);
|
||||
}
|
||||
|
||||
@Test(expected = AnnotationException.class)
|
||||
public void testMultipleConflictingInheritanceDefinitions() {
|
||||
|
||||
@Entity
|
||||
@Inheritance(strategy = javax.persistence.InheritanceType.JOINED)
|
||||
class A {
|
||||
String id;
|
||||
}
|
||||
|
||||
@Entity
|
||||
@Inheritance(strategy = javax.persistence.InheritanceType.TABLE_PER_CLASS)
|
||||
class B extends A {
|
||||
}
|
||||
|
||||
createEntityHierarchies( B.class, A.class );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmbeddableHierarchy() {
|
||||
@Embeddable
|
||||
class A {
|
||||
String foo;
|
||||
}
|
||||
|
||||
class B extends A {
|
||||
}
|
||||
|
||||
@Embeddable
|
||||
class C extends B {
|
||||
String bar;
|
||||
}
|
||||
|
||||
ConfiguredClassHierarchy<EmbeddableClass> hierarchy = createEmbeddableHierarchy(
|
||||
AccessType.FIELD,
|
||||
C.class,
|
||||
A.class,
|
||||
B.class
|
||||
);
|
||||
Iterator<EmbeddableClass> iter = hierarchy.iterator();
|
||||
ClassInfo info = iter.next().getClassInfo();
|
||||
assertEquals( "wrong class", DotName.createSimple( A.class.getName() ), info.name() );
|
||||
info = iter.next().getClassInfo();
|
||||
assertEquals( "wrong class", DotName.createSimple( B.class.getName() ), info.name() );
|
||||
info = iter.next().getClassInfo();
|
||||
assertEquals( "wrong class", DotName.createSimple( C.class.getName() ), info.name() );
|
||||
assertFalse( iter.hasNext() );
|
||||
assertNotNull( hierarchy );
|
||||
}
|
||||
|
||||
@Test(expected = AssertionFailure.class)
|
||||
public void testEmbeddableHierarchyWithNotAnnotatedEntity() {
|
||||
class NonAnnotatedEmbeddable {
|
||||
}
|
||||
|
||||
createEmbeddableHierarchy( AccessType.FIELD, NonAnnotatedEmbeddable.class );
|
||||
}
|
||||
|
||||
@Entity
|
||||
public class Foo {
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private int id;
|
||||
}
|
||||
|
||||
@Entity
|
||||
public class A {
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private int id;
|
||||
}
|
||||
|
||||
@Entity
|
||||
public class B extends A {
|
||||
private String name;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -33,19 +33,12 @@ import javax.persistence.MappedSuperclass;
|
|||
|
||||
import org.jboss.jandex.ClassInfo;
|
||||
import org.jboss.jandex.DotName;
|
||||
import org.jboss.jandex.Index;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.metamodel.source.annotations.attribute.MappedAttribute;
|
||||
import org.hibernate.metamodel.source.annotations.entity.ConfiguredClass;
|
||||
import org.hibernate.metamodel.source.annotations.entity.ConfiguredClassHierarchy;
|
||||
import org.hibernate.metamodel.source.annotations.entity.EntityClass;
|
||||
import org.hibernate.service.ServiceRegistryBuilder;
|
||||
import org.hibernate.service.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.service.internal.BasicServiceRegistryImpl;
|
||||
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.assertFalse;
|
||||
|
@ -54,26 +47,15 @@ import static junit.framework.Assert.assertTrue;
|
|||
/**
|
||||
* @author Hardy Ferentschik
|
||||
*/
|
||||
public class GenericTypeDiscoveryTest extends BaseUnitTestCase {
|
||||
private BasicServiceRegistryImpl serviceRegistry;
|
||||
private ClassLoaderService service;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
serviceRegistry = (BasicServiceRegistryImpl) new ServiceRegistryBuilder().buildServiceRegistry();
|
||||
service = serviceRegistry.getService( ClassLoaderService.class );
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
serviceRegistry.destroy();
|
||||
}
|
||||
public class GenericTypeDiscoveryTest extends BaseAnnotationIndexTestCase {
|
||||
|
||||
@Test
|
||||
public void testGenericClassHierarchy() {
|
||||
Index index = JandexHelper.indexForClass( service, Paper.class, Stuff.class, Item.class, PricedStuff.class );
|
||||
Set<ConfiguredClassHierarchy> hierarchies = ConfiguredClassHierarchyBuilder.createEntityHierarchies(
|
||||
index, serviceRegistry
|
||||
Set<ConfiguredClassHierarchy<EntityClass>> hierarchies = createEntityHierarchies(
|
||||
Paper.class,
|
||||
Stuff.class,
|
||||
Item.class,
|
||||
PricedStuff.class
|
||||
);
|
||||
assertEquals( "There should be only one hierarchy", 1, hierarchies.size() );
|
||||
|
||||
|
@ -113,10 +95,7 @@ public class GenericTypeDiscoveryTest extends BaseUnitTestCase {
|
|||
|
||||
@Test
|
||||
public void testUnresolvedType() {
|
||||
Index index = JandexHelper.indexForClass( service, UnresolvedType.class );
|
||||
Set<ConfiguredClassHierarchy> hierarchies = ConfiguredClassHierarchyBuilder.createEntityHierarchies(
|
||||
index, serviceRegistry
|
||||
);
|
||||
Set<ConfiguredClassHierarchy<EntityClass>> hierarchies = createEntityHierarchies( UnresolvedType.class );
|
||||
assertEquals( "There should be only one hierarchy", 1, hierarchies.size() );
|
||||
}
|
||||
|
||||
|
|
|
@ -28,9 +28,6 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
import javax.persistence.Id;
|
||||
|
||||
import org.jboss.jandex.Index;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.annotations.Parameter;
|
||||
|
@ -39,37 +36,17 @@ import org.hibernate.metamodel.source.annotations.attribute.MappedAttribute;
|
|||
import org.hibernate.metamodel.source.annotations.entity.ConfiguredClass;
|
||||
import org.hibernate.metamodel.source.annotations.entity.ConfiguredClassHierarchy;
|
||||
import org.hibernate.metamodel.source.annotations.entity.EntityClass;
|
||||
import org.hibernate.service.ServiceRegistryBuilder;
|
||||
import org.hibernate.service.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.service.internal.BasicServiceRegistryImpl;
|
||||
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* @author Hardy Ferentschik
|
||||
*/
|
||||
public class TypeDiscoveryTest extends BaseUnitTestCase {
|
||||
private BasicServiceRegistryImpl serviceRegistry;
|
||||
private ClassLoaderService service;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
serviceRegistry = (BasicServiceRegistryImpl) new ServiceRegistryBuilder().buildServiceRegistry();
|
||||
service = serviceRegistry.getService( ClassLoaderService.class );
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
serviceRegistry.destroy();
|
||||
}
|
||||
public class TypeDiscoveryTest extends BaseAnnotationIndexTestCase {
|
||||
|
||||
@Test
|
||||
public void testImplicitAndExplicitType() {
|
||||
Index index = JandexHelper.indexForClass( service, Entity.class );
|
||||
Set<ConfiguredClassHierarchy> hierarchies = ConfiguredClassHierarchyBuilder.createEntityHierarchies(
|
||||
index, serviceRegistry
|
||||
);
|
||||
Set<ConfiguredClassHierarchy<EntityClass>> hierarchies = createEntityHierarchies( Entity.class );
|
||||
assertEquals( "There should be only one hierarchy", 1, hierarchies.size() );
|
||||
|
||||
Iterator<EntityClass> iter = hierarchies.iterator().next().iterator();
|
||||
|
|
Loading…
Reference in New Issue