HHH-6114 Discovering mapped properties
This commit is contained in:
parent
78ad67cff6
commit
5273a75094
|
@ -53,8 +53,9 @@ public class AnnotationBinder {
|
|||
|
||||
public void bindMappedClasses(Index annotationIndex) {
|
||||
// need to order our annotated entities into an order we can process
|
||||
ConfiguredClassHierarchyBuilder builder = new ConfiguredClassHierarchyBuilder();
|
||||
Set<ConfiguredClassHierarchy> hierarchies = builder.createEntityHierarchies( annotationIndex );
|
||||
Set<ConfiguredClassHierarchy> hierarchies = ConfiguredClassHierarchyBuilder.createEntityHierarchies(
|
||||
annotationIndex, metadata.getServiceRegistry()
|
||||
);
|
||||
|
||||
// now we process each hierarchy one at the time
|
||||
for ( ConfiguredClassHierarchy hierarchy : hierarchies ) {
|
||||
|
@ -75,7 +76,7 @@ public class AnnotationBinder {
|
|||
classInfo, JPADotNames.MAPPED_SUPER_CLASS
|
||||
);
|
||||
AnnotationInstance hibernateEntityAnnotation = JandexHelper.getSingleAnnotation(
|
||||
classInfo, JPADotNames.HIBERNATE_ENTITY
|
||||
classInfo, HibernateDotNames.ENTITY
|
||||
);
|
||||
|
||||
|
||||
|
|
|
@ -23,13 +23,26 @@
|
|||
*/
|
||||
package org.hibernate.metamodel.source.annotations;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Member;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import javax.persistence.AccessType;
|
||||
|
||||
import org.jboss.jandex.AnnotationInstance;
|
||||
import org.jboss.jandex.AnnotationTarget;
|
||||
import org.jboss.jandex.ClassInfo;
|
||||
import org.jboss.jandex.FieldInfo;
|
||||
import org.jboss.jandex.MethodInfo;
|
||||
|
||||
import org.hibernate.AnnotationException;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
import org.hibernate.service.classloading.spi.ClassLoaderService;
|
||||
|
||||
/**
|
||||
* Represents an entity, mapped superclass or component configured via annotations/xml.
|
||||
|
@ -38,12 +51,13 @@ import org.hibernate.AnnotationException;
|
|||
*/
|
||||
public class ConfiguredClass {
|
||||
private final ClassInfo classInfo;
|
||||
private final Class<?> clazz;
|
||||
private final AccessType classAccessType;
|
||||
private final ConfiguredClassHierarchy hierarchy;
|
||||
private final boolean isMappedSuperClass;
|
||||
private final List<MappedProperty> mappedProperties;
|
||||
|
||||
public ConfiguredClass(ClassInfo info, ConfiguredClassHierarchy hierarchy) {
|
||||
public ConfiguredClass(ClassInfo info, ConfiguredClassHierarchy hierarchy, ServiceRegistry serviceRegistry) {
|
||||
this.classInfo = info;
|
||||
this.hierarchy = hierarchy;
|
||||
|
||||
|
@ -60,9 +74,12 @@ public class ConfiguredClass {
|
|||
);
|
||||
}
|
||||
|
||||
this.clazz = serviceRegistry.getService( ClassLoaderService.class ).classForName( info.toString() );
|
||||
isMappedSuperClass = mappedSuperClassAnnotation != null;
|
||||
classAccessType = determineClassAccessType( hierarchy.getDefaultAccessType() );
|
||||
mappedProperties = collectMappedProperties();
|
||||
// make sure the properties are ordered by property name
|
||||
Collections.sort( mappedProperties );
|
||||
}
|
||||
|
||||
public ClassInfo getClassInfo() {
|
||||
|
@ -95,7 +112,122 @@ public class ConfiguredClass {
|
|||
}
|
||||
|
||||
private List<MappedProperty> collectMappedProperties() {
|
||||
return null; //To change body of created methods use File | Settings | File Templates.
|
||||
Set<String> transientFieldNames = new HashSet<String>();
|
||||
Set<String> transientMethodNames = new HashSet<String>();
|
||||
populateTransientFieldAndMethodLists( transientFieldNames, transientMethodNames );
|
||||
|
||||
List<Member> classMembers = new ArrayList<Member>();
|
||||
Set<String> explicitlyConfiguredAccessMemberNames;
|
||||
if ( AccessType.FIELD.equals( classAccessType ) ) {
|
||||
explicitlyConfiguredAccessMemberNames = addExplicitAccessMembers( classMembers, MethodInfo.class );
|
||||
Field fields[] = clazz.getDeclaredFields();
|
||||
Field.setAccessible( fields, true );
|
||||
for ( Field field : fields ) {
|
||||
if ( !transientFieldNames.contains( field.getName() )
|
||||
&& !explicitlyConfiguredAccessMemberNames.contains( field.getName() ) ) {
|
||||
classMembers.add( field );
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
explicitlyConfiguredAccessMemberNames = addExplicitAccessMembers( classMembers, FieldInfo.class );
|
||||
Method[] methods = clazz.getDeclaredMethods();
|
||||
Method.setAccessible( methods, true );
|
||||
for ( Method method : methods ) {
|
||||
if ( !transientMethodNames.contains( method.getName() )
|
||||
&& !explicitlyConfiguredAccessMemberNames.contains( ReflectionHelper.getPropertyName( method ) ) ) {
|
||||
classMembers.add( method );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<MappedProperty> properties = new ArrayList<MappedProperty>();
|
||||
return properties;
|
||||
}
|
||||
|
||||
private Set<String> addExplicitAccessMembers(List<Member> classMembers, Class<? extends AnnotationTarget> targetClass) {
|
||||
Set<String> explicitAccessMembers = new HashSet<String>();
|
||||
|
||||
List<AnnotationInstance> accessAnnotations = classInfo.annotations().get( JPADotNames.ACCESS );
|
||||
if ( accessAnnotations == null ) {
|
||||
return explicitAccessMembers;
|
||||
}
|
||||
|
||||
for ( AnnotationInstance accessAnnotation : accessAnnotations ) {
|
||||
// at this stage we are only interested at annotations defined on fields and methods
|
||||
AnnotationTarget target = accessAnnotation.target();
|
||||
if ( !target.getClass().equals( targetClass ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
AccessType accessType = Enum.valueOf( AccessType.class, accessAnnotation.value().asEnum() );
|
||||
|
||||
if ( target instanceof MethodInfo && MethodInfo.class.equals( targetClass ) ) {
|
||||
// annotating a field with @AccessType(PROPERTY) has not effect
|
||||
if ( !AccessType.PROPERTY.equals( accessType ) ) {
|
||||
continue;
|
||||
}
|
||||
Method m;
|
||||
try {
|
||||
m = clazz.getMethod( ( (MethodInfo) target ).name() );
|
||||
}
|
||||
catch ( NoSuchMethodException e ) {
|
||||
throw new HibernateException(
|
||||
"Unable to load method "
|
||||
+ ( (MethodInfo) target ).name()
|
||||
+ " of class " + clazz.getName()
|
||||
);
|
||||
}
|
||||
classMembers.add( m );
|
||||
explicitAccessMembers.add( ReflectionHelper.getPropertyName( m ) );
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( target instanceof FieldInfo && FieldInfo.class.equals( targetClass ) ) {
|
||||
// annotating a method w/ @AccessType(FIELD) has no effect
|
||||
if ( !AccessType.FIELD.equals( accessType ) ) {
|
||||
continue;
|
||||
}
|
||||
Field f;
|
||||
try {
|
||||
f = clazz.getField( ( (FieldInfo) target ).name() );
|
||||
}
|
||||
catch ( NoSuchFieldException e ) {
|
||||
throw new HibernateException(
|
||||
"Unable to load field "
|
||||
+ ( (FieldInfo) target ).name()
|
||||
+ " of class " + clazz.getName()
|
||||
);
|
||||
}
|
||||
classMembers.add( f );
|
||||
explicitAccessMembers.add( f.getName() );
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return explicitAccessMembers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates the sets of transient field and method names.
|
||||
*
|
||||
* @param transientFieldNames Set to populate with the field names explicitly marked as @Transient
|
||||
* @param transientMethodNames set to populate with the method names explicitly marked as @Transient
|
||||
*/
|
||||
private void populateTransientFieldAndMethodLists(Set<String> transientFieldNames, Set<String> transientMethodNames) {
|
||||
List<AnnotationInstance> transientMembers = classInfo.annotations().get( JPADotNames.TRANSIENT );
|
||||
if ( transientMembers == null ) {
|
||||
return;
|
||||
}
|
||||
|
||||
for ( AnnotationInstance transientMember : transientMembers ) {
|
||||
AnnotationTarget target = transientMember.target();
|
||||
if ( target instanceof FieldInfo ) {
|
||||
transientFieldNames.add( ( (FieldInfo) target ).name() );
|
||||
}
|
||||
else {
|
||||
transientMethodNames.add( ( (MethodInfo) target ).name() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@ import org.jboss.jandex.FieldInfo;
|
|||
import org.jboss.jandex.MethodInfo;
|
||||
|
||||
import org.hibernate.AnnotationException;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
|
||||
/**
|
||||
* Represents the inheritance structure of the configured classes within a class hierarchy.
|
||||
|
@ -46,13 +47,14 @@ public class ConfiguredClassHierarchy implements Iterable<ConfiguredClass> {
|
|||
private final InheritanceType inheritanceType;
|
||||
private final List<ConfiguredClass> configuredClasses;
|
||||
|
||||
ConfiguredClassHierarchy(List<ClassInfo> classes) {
|
||||
ConfiguredClassHierarchy(List<ClassInfo> classes, ServiceRegistry serviceRegistry) {
|
||||
defaultAccessType = determineDefaultAccessType( classes );
|
||||
inheritanceType = determineInheritanceType( classes );
|
||||
|
||||
configuredClasses = new ArrayList<ConfiguredClass>();
|
||||
for ( ClassInfo info : classes ) {
|
||||
configuredClasses.add( new ConfiguredClass( info, this ) );
|
||||
configuredClasses.add( new ConfiguredClass( info, this, serviceRegistry ) );
|
||||
}
|
||||
defaultAccessType = determineDefaultAccessType();
|
||||
inheritanceType = determineInheritanceType();
|
||||
}
|
||||
|
||||
public AccessType getDefaultAccessType() {
|
||||
|
@ -82,16 +84,15 @@ public class ConfiguredClassHierarchy implements Iterable<ConfiguredClass> {
|
|||
}
|
||||
|
||||
/**
|
||||
* @param classes the classes in the hierarchy
|
||||
*
|
||||
* @return Returns the default access type for the configured class hierarchy independent of explicit
|
||||
* {@code AccessType} annotations. The default access type is determined by the placement of the
|
||||
* annotations.
|
||||
*/
|
||||
private AccessType determineDefaultAccessType() {
|
||||
Iterator<ConfiguredClass> iter = iterator();
|
||||
private AccessType determineDefaultAccessType(List<ClassInfo> classes) {
|
||||
AccessType accessType = null;
|
||||
while ( iter.hasNext() ) {
|
||||
ConfiguredClass configuredClass = iter.next();
|
||||
ClassInfo info = configuredClass.getClassInfo();
|
||||
for ( ClassInfo info : classes ) {
|
||||
List<AnnotationInstance> idAnnotations = info.annotations().get( JPADotNames.ID );
|
||||
if ( idAnnotations == null || idAnnotations.size() == 0 ) {
|
||||
continue;
|
||||
|
@ -100,7 +101,7 @@ public class ConfiguredClassHierarchy implements Iterable<ConfiguredClass> {
|
|||
}
|
||||
|
||||
if ( accessType == null ) {
|
||||
return throwIdNotFoundAnnotationException();
|
||||
return throwIdNotFoundAnnotationException( classes );
|
||||
}
|
||||
|
||||
return accessType;
|
||||
|
@ -125,19 +126,16 @@ public class ConfiguredClassHierarchy implements Iterable<ConfiguredClass> {
|
|||
}
|
||||
else {
|
||||
if ( !accessType.equals( tmpAccessType ) ) {
|
||||
throw new AnnotationException( "Inconsistent placement of @Id annotation within hierarchy " + hierarchyListString() );
|
||||
throw new AnnotationException( "Inconsistent placement of @Id annotation within hierarchy " );
|
||||
}
|
||||
}
|
||||
}
|
||||
return accessType;
|
||||
}
|
||||
|
||||
private InheritanceType determineInheritanceType() {
|
||||
Iterator<ConfiguredClass> iter = iterator();
|
||||
private InheritanceType determineInheritanceType(List<ClassInfo> classes) {
|
||||
InheritanceType inheritanceType = null;
|
||||
while ( iter.hasNext() ) {
|
||||
ConfiguredClass configuredClass = iter.next();
|
||||
ClassInfo info = configuredClass.getClassInfo();
|
||||
for ( ClassInfo info : classes ) {
|
||||
AnnotationInstance inheritanceAnnotation = JandexHelper.getSingleAnnotation(
|
||||
info, JPADotNames.INHERITANCE
|
||||
);
|
||||
|
@ -159,7 +157,8 @@ public class ConfiguredClassHierarchy implements Iterable<ConfiguredClass> {
|
|||
else {
|
||||
if ( !inheritanceType.equals( tmpInheritanceType ) ) {
|
||||
throw new AnnotationException(
|
||||
"Multiple incompatible instances of @Inheritance specified within hierarchy " + hierarchyListString()
|
||||
"Multiple incompatible instances of @Inheritance specified within classes "
|
||||
+ hierarchyListString( classes )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -173,23 +172,24 @@ public class ConfiguredClassHierarchy implements Iterable<ConfiguredClass> {
|
|||
return inheritanceType;
|
||||
}
|
||||
|
||||
private AccessType throwIdNotFoundAnnotationException() {
|
||||
private AccessType throwIdNotFoundAnnotationException(List<ClassInfo> classes) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append( "Unable to find Id property for class hierarchy " );
|
||||
builder.append( hierarchyListString() );
|
||||
builder.append( hierarchyListString( classes ) );
|
||||
throw new AnnotationException( builder.toString() );
|
||||
}
|
||||
|
||||
private String hierarchyListString() {
|
||||
Iterator<ConfiguredClass> iter;
|
||||
private String hierarchyListString(List<ClassInfo> classes) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append( "[" );
|
||||
iter = iterator();
|
||||
while ( iter.hasNext() ) {
|
||||
builder.append( iter.next().getClassInfo().name().toString() );
|
||||
if ( iter.hasNext() ) {
|
||||
|
||||
int count = 0;
|
||||
for ( ClassInfo info : classes ) {
|
||||
builder.append( info.name().toString() );
|
||||
if ( count < classes.size() ) {
|
||||
builder.append( ", " );
|
||||
}
|
||||
count++;
|
||||
}
|
||||
builder.append( "]" );
|
||||
return builder.toString();
|
||||
|
|
|
@ -34,7 +34,8 @@ import org.jboss.jandex.ClassInfo;
|
|||
import org.jboss.jandex.DotName;
|
||||
import org.jboss.jandex.Index;
|
||||
|
||||
import org.hibernate.internal.util.ReflectHelper;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
import org.hibernate.service.classloading.spi.ClassLoaderService;
|
||||
|
||||
/**
|
||||
* Given a annotation index build a list of class hierarchies.
|
||||
|
@ -43,7 +44,17 @@ import org.hibernate.internal.util.ReflectHelper;
|
|||
*/
|
||||
public class ConfiguredClassHierarchyBuilder {
|
||||
|
||||
public Set<ConfiguredClassHierarchy> createEntityHierarchies(Index index) {
|
||||
/**
|
||||
* This methods 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
|
||||
*
|
||||
* @return a set of {@code ConfiguredClassHierarchy}s. One for each configured "leaf" entity.
|
||||
*/
|
||||
public static Set<ConfiguredClassHierarchy> createEntityHierarchies(Index index, ServiceRegistry serviceRegistry) {
|
||||
ClassLoaderService classLoaderService = serviceRegistry.getService( ClassLoaderService.class );
|
||||
Map<ClassInfo, List<ClassInfo>> processedClassInfos = new HashMap<ClassInfo, List<ClassInfo>>();
|
||||
|
||||
for ( ClassInfo info : index.getKnownClasses() ) {
|
||||
|
@ -52,7 +63,7 @@ public class ConfiguredClassHierarchyBuilder {
|
|||
}
|
||||
List<ClassInfo> configuredClassList = new ArrayList<ClassInfo>();
|
||||
ClassInfo tmpClassInfo = info;
|
||||
Class<?> clazz = classForName( tmpClassInfo );
|
||||
Class<?> clazz = classLoaderService.classForName( tmpClassInfo.toString() );
|
||||
while ( clazz != null && !clazz.equals( Object.class ) ) {
|
||||
tmpClassInfo = index.getClassByName( DotName.createSimple( clazz.getName() ) );
|
||||
clazz = clazz.getSuperclass();
|
||||
|
@ -73,14 +84,13 @@ public class ConfiguredClassHierarchyBuilder {
|
|||
processedClassInfos.put( tmpClassInfo, configuredClassList );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Set<ConfiguredClassHierarchy> hierarchies = new HashSet<ConfiguredClassHierarchy>();
|
||||
List<List<ClassInfo>> processedList = new ArrayList<List<ClassInfo>>();
|
||||
for ( List<ClassInfo> classInfoList : processedClassInfos.values() ) {
|
||||
if ( !processedList.contains( classInfoList ) ) {
|
||||
hierarchies.add( new ConfiguredClassHierarchy( classInfoList ) );
|
||||
hierarchies.add( new ConfiguredClassHierarchy( classInfoList, serviceRegistry ) );
|
||||
processedList.add( classInfoList );
|
||||
}
|
||||
}
|
||||
|
@ -88,7 +98,7 @@ public class ConfiguredClassHierarchyBuilder {
|
|||
return hierarchies;
|
||||
}
|
||||
|
||||
private boolean existsHierarchyWithClassInfoAsLeaf(Map<ClassInfo, List<ClassInfo>> processedClassInfos, ClassInfo tmpClassInfo) {
|
||||
private static boolean existsHierarchyWithClassInfoAsLeaf(Map<ClassInfo, List<ClassInfo>> processedClassInfos, ClassInfo tmpClassInfo) {
|
||||
if ( !processedClassInfos.containsKey( tmpClassInfo ) ) {
|
||||
return false;
|
||||
}
|
||||
|
@ -96,17 +106,6 @@ public class ConfiguredClassHierarchyBuilder {
|
|||
List<ClassInfo> classInfoList = processedClassInfos.get( tmpClassInfo );
|
||||
return classInfoList.get( classInfoList.size() - 1 ).equals( tmpClassInfo );
|
||||
}
|
||||
|
||||
private Class<?> classForName(ClassInfo info) {
|
||||
Class<?> clazz = null;
|
||||
try {
|
||||
clazz = ReflectHelper.classForName( info.toString() );
|
||||
}
|
||||
catch ( ClassNotFoundException e ) {
|
||||
// todo what to do here!?i
|
||||
}
|
||||
return clazz;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
import org.jboss.jandex.DotName;
|
||||
|
||||
import org.hibernate.annotations.Entity;
|
||||
import org.hibernate.annotations.FetchProfile;
|
||||
import org.hibernate.annotations.FetchProfiles;
|
||||
|
||||
/**
|
||||
* Defines the dot names for the Hibernate specific annotations.
|
||||
*
|
||||
* @author Hardy Ferentschik
|
||||
*/
|
||||
public interface HibernateDotNames {
|
||||
public static final DotName ENTITY = DotName.createSimple( Entity.class.getName() );
|
||||
public static final DotName FETCH_PROFILES = DotName.createSimple( FetchProfiles.class.getName() );
|
||||
public static final DotName FETCH_PROFILE = DotName.createSimple( FetchProfile.class.getName() );
|
||||
}
|
||||
|
||||
|
|
@ -28,6 +28,7 @@ import javax.persistence.Entity;
|
|||
import javax.persistence.Id;
|
||||
import javax.persistence.Inheritance;
|
||||
import javax.persistence.MappedSuperclass;
|
||||
import javax.persistence.Transient;
|
||||
|
||||
import org.jboss.jandex.DotName;
|
||||
|
||||
|
@ -38,13 +39,12 @@ import org.jboss.jandex.DotName;
|
|||
*/
|
||||
public interface JPADotNames {
|
||||
public static final DotName ENTITY = DotName.createSimple( Entity.class.getName() );
|
||||
public static final DotName HIBERNATE_ENTITY = DotName.createSimple( org.hibernate.annotations.Entity.class.getName() );
|
||||
public static final DotName MAPPED_SUPER_CLASS = DotName.createSimple( MappedSuperclass.class.getName() );
|
||||
|
||||
public static final DotName INHERITANCE = DotName.createSimple( Inheritance.class.getName() );
|
||||
public static final DotName ACCESS = DotName.createSimple( Access.class.getName() );
|
||||
|
||||
public static final DotName ID = DotName.createSimple( Id.class.getName() );
|
||||
public static final DotName ACCESS = DotName.createSimple( Access.class.getName() );
|
||||
public static final DotName TRANSIENT = DotName.createSimple( Transient.class.getName() );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -28,7 +28,21 @@ package org.hibernate.metamodel.source.annotations;
|
|||
*
|
||||
* @author Hardy Ferentschik
|
||||
*/
|
||||
public class MappedProperty {
|
||||
public class MappedProperty implements Comparable<MappedProperty> {
|
||||
private final String name;
|
||||
|
||||
MappedProperty(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(MappedProperty mappedProperty) {
|
||||
return name.compareTo( mappedProperty.getName() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
package org.hibernate.metamodel.source.annotations;
|
||||
|
||||
import java.beans.Introspector;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Member;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* Some helper methods for reflection tasks
|
||||
*
|
||||
* @author Hardy Ferentschik
|
||||
*/
|
||||
public class ReflectionHelper {
|
||||
private ReflectionHelper() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Process bean properties getter by applying the JavaBean naming conventions.
|
||||
*
|
||||
* @param member the member for which to get the property name.
|
||||
*
|
||||
* @return The bean method name with the "is" or "get" prefix stripped off, <code>null</code>
|
||||
* the method name id not according to the JavaBeans standard.
|
||||
*/
|
||||
public static String getPropertyName(Member member) {
|
||||
String name = null;
|
||||
|
||||
if ( member instanceof Field ) {
|
||||
name = member.getName();
|
||||
}
|
||||
|
||||
if ( member instanceof Method ) {
|
||||
String methodName = member.getName();
|
||||
if ( methodName.startsWith( "is" ) ) {
|
||||
name = Introspector.decapitalize( methodName.substring( 2 ) );
|
||||
}
|
||||
else if ( methodName.startsWith( "has" ) ) {
|
||||
name = Introspector.decapitalize( methodName.substring( 3 ) );
|
||||
}
|
||||
else if ( methodName.startsWith( "get" ) ) {
|
||||
name = Introspector.decapitalize( methodName.substring( 3 ) );
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2,6 +2,7 @@ package org.hibernate.metamodel.source.annotations;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import javax.persistence.AccessType;
|
||||
|
@ -16,9 +17,13 @@ import org.jboss.jandex.ClassInfo;
|
|||
import org.jboss.jandex.DotName;
|
||||
import org.jboss.jandex.Index;
|
||||
import org.jboss.jandex.Indexer;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.AnnotationException;
|
||||
import org.hibernate.metamodel.source.Metadata;
|
||||
import org.hibernate.service.internal.BasicServiceRegistryImpl;
|
||||
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
|
@ -31,11 +36,24 @@ import static org.junit.Assert.fail;
|
|||
*/
|
||||
public class ConfiguredClassHierarchyBuilderTest extends BaseUnitTestCase {
|
||||
|
||||
private BasicServiceRegistryImpl serviceRegistry;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
serviceRegistry = new BasicServiceRegistryImpl( Collections.emptyMap() );
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
serviceRegistry.destroy();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingleEntity() {
|
||||
Index index = indexForClass( Foo.class );
|
||||
ConfiguredClassHierarchyBuilder builder = new ConfiguredClassHierarchyBuilder();
|
||||
Set<ConfiguredClassHierarchy> hierarchies = builder.createEntityHierarchies( index );
|
||||
Set<ConfiguredClassHierarchy> hierarchies = ConfiguredClassHierarchyBuilder.createEntityHierarchies(
|
||||
index, serviceRegistry
|
||||
);
|
||||
assertEquals( "There should be only one hierarchy", 1, hierarchies.size() );
|
||||
|
||||
Iterator<ConfiguredClass> iter = hierarchies.iterator().next().iterator();
|
||||
|
@ -47,8 +65,9 @@ public class ConfiguredClassHierarchyBuilderTest extends BaseUnitTestCase {
|
|||
@Test
|
||||
public void testSimpleInheritance() {
|
||||
Index index = indexForClass( B.class, A.class );
|
||||
ConfiguredClassHierarchyBuilder builder = new ConfiguredClassHierarchyBuilder();
|
||||
Set<ConfiguredClassHierarchy> hierarchies = builder.createEntityHierarchies( index );
|
||||
Set<ConfiguredClassHierarchy> hierarchies = ConfiguredClassHierarchyBuilder.createEntityHierarchies(
|
||||
index, serviceRegistry
|
||||
);
|
||||
assertEquals( "There should be only one hierarchy", 1, hierarchies.size() );
|
||||
|
||||
Iterator<ConfiguredClass> iter = hierarchies.iterator().next().iterator();
|
||||
|
@ -62,8 +81,9 @@ public class ConfiguredClassHierarchyBuilderTest extends BaseUnitTestCase {
|
|||
@Test
|
||||
public void testMultipleHierarchies() {
|
||||
Index index = indexForClass( B.class, A.class, Foo.class );
|
||||
ConfiguredClassHierarchyBuilder builder = new ConfiguredClassHierarchyBuilder();
|
||||
Set<ConfiguredClassHierarchy> hierarchies = builder.createEntityHierarchies( index );
|
||||
Set<ConfiguredClassHierarchy> hierarchies = ConfiguredClassHierarchyBuilder.createEntityHierarchies(
|
||||
index, serviceRegistry
|
||||
);
|
||||
assertEquals( "There should be only one hierarchy", 2, hierarchies.size() );
|
||||
}
|
||||
|
||||
|
@ -86,8 +106,9 @@ public class ConfiguredClassHierarchyBuilderTest extends BaseUnitTestCase {
|
|||
}
|
||||
|
||||
Index index = indexForClass( MappedSubClass.class, MappedSuperClass.class, UnmappedSubClass.class );
|
||||
ConfiguredClassHierarchyBuilder builder = new ConfiguredClassHierarchyBuilder();
|
||||
Set<ConfiguredClassHierarchy> hierarchies = builder.createEntityHierarchies( index );
|
||||
Set<ConfiguredClassHierarchy> hierarchies = ConfiguredClassHierarchyBuilder.createEntityHierarchies(
|
||||
index, serviceRegistry
|
||||
);
|
||||
assertEquals( "There should be only one hierarchy", 1, hierarchies.size() );
|
||||
|
||||
Iterator<ConfiguredClass> iter = hierarchies.iterator().next().iterator();
|
||||
|
@ -108,8 +129,7 @@ public class ConfiguredClassHierarchyBuilderTest extends BaseUnitTestCase {
|
|||
}
|
||||
|
||||
Index index = indexForClass( EntityAndMappedSuperClass.class );
|
||||
ConfiguredClassHierarchyBuilder builder = new ConfiguredClassHierarchyBuilder();
|
||||
builder.createEntityHierarchies( index );
|
||||
ConfiguredClassHierarchyBuilder.createEntityHierarchies( index, serviceRegistry );
|
||||
}
|
||||
|
||||
@Test(expected = AnnotationException.class)
|
||||
|
@ -125,8 +145,7 @@ public class ConfiguredClassHierarchyBuilderTest extends BaseUnitTestCase {
|
|||
}
|
||||
|
||||
Index index = indexForClass( B.class, A.class );
|
||||
ConfiguredClassHierarchyBuilder builder = new ConfiguredClassHierarchyBuilder();
|
||||
builder.createEntityHierarchies( index );
|
||||
ConfiguredClassHierarchyBuilder.createEntityHierarchies( index, serviceRegistry );
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -142,8 +161,9 @@ public class ConfiguredClassHierarchyBuilderTest extends BaseUnitTestCase {
|
|||
}
|
||||
|
||||
Index index = indexForClass( B.class, A.class );
|
||||
ConfiguredClassHierarchyBuilder builder = new ConfiguredClassHierarchyBuilder();
|
||||
Set<ConfiguredClassHierarchy> hierarchies = builder.createEntityHierarchies( index );
|
||||
Set<ConfiguredClassHierarchy> hierarchies = ConfiguredClassHierarchyBuilder.createEntityHierarchies(
|
||||
index, serviceRegistry
|
||||
);
|
||||
assertTrue( hierarchies.size() == 1 );
|
||||
ConfiguredClassHierarchy hierarchy = hierarchies.iterator().next();
|
||||
assertEquals( "Wrong default access type", AccessType.FIELD, hierarchy.getDefaultAccessType() );
|
||||
|
@ -170,8 +190,9 @@ public class ConfiguredClassHierarchyBuilderTest extends BaseUnitTestCase {
|
|||
}
|
||||
|
||||
Index index = indexForClass( B.class, A.class );
|
||||
ConfiguredClassHierarchyBuilder builder = new ConfiguredClassHierarchyBuilder();
|
||||
Set<ConfiguredClassHierarchy> hierarchies = builder.createEntityHierarchies( index );
|
||||
Set<ConfiguredClassHierarchy> hierarchies = ConfiguredClassHierarchyBuilder.createEntityHierarchies(
|
||||
index, serviceRegistry
|
||||
);
|
||||
assertTrue( hierarchies.size() == 1 );
|
||||
ConfiguredClassHierarchy hierarchy = hierarchies.iterator().next();
|
||||
assertEquals( "Wrong default access type", AccessType.PROPERTY, hierarchy.getDefaultAccessType() );
|
||||
|
@ -190,8 +211,9 @@ public class ConfiguredClassHierarchyBuilderTest extends BaseUnitTestCase {
|
|||
}
|
||||
|
||||
Index index = indexForClass( B.class, A.class );
|
||||
ConfiguredClassHierarchyBuilder builder = new ConfiguredClassHierarchyBuilder();
|
||||
Set<ConfiguredClassHierarchy> hierarchies = builder.createEntityHierarchies( index );
|
||||
Set<ConfiguredClassHierarchy> hierarchies = ConfiguredClassHierarchyBuilder.createEntityHierarchies(
|
||||
index, serviceRegistry
|
||||
);
|
||||
assertTrue( hierarchies.size() == 1 );
|
||||
ConfiguredClassHierarchy hierarchy = hierarchies.iterator().next();
|
||||
assertEquals( "Wrong inheritance type", InheritanceType.SINGLE_TABLE, hierarchy.getInheritanceType() );
|
||||
|
@ -217,8 +239,9 @@ public class ConfiguredClassHierarchyBuilderTest extends BaseUnitTestCase {
|
|||
}
|
||||
|
||||
Index index = indexForClass( B.class, MappedSuperClass.class, A.class );
|
||||
ConfiguredClassHierarchyBuilder builder = new ConfiguredClassHierarchyBuilder();
|
||||
Set<ConfiguredClassHierarchy> hierarchies = builder.createEntityHierarchies( index );
|
||||
Set<ConfiguredClassHierarchy> hierarchies = ConfiguredClassHierarchyBuilder.createEntityHierarchies(
|
||||
index, serviceRegistry
|
||||
);
|
||||
assertTrue( hierarchies.size() == 1 );
|
||||
ConfiguredClassHierarchy hierarchy = hierarchies.iterator().next();
|
||||
assertEquals( "Wrong inheritance type", InheritanceType.JOINED, hierarchy.getInheritanceType() );
|
||||
|
@ -239,8 +262,7 @@ public class ConfiguredClassHierarchyBuilderTest extends BaseUnitTestCase {
|
|||
}
|
||||
|
||||
Index index = indexForClass( B.class, A.class );
|
||||
ConfiguredClassHierarchyBuilder builder = new ConfiguredClassHierarchyBuilder();
|
||||
builder.createEntityHierarchies( index );
|
||||
ConfiguredClassHierarchyBuilder.createEntityHierarchies( index, serviceRegistry );
|
||||
}
|
||||
|
||||
private Index indexForClass(Class<?>... classes) {
|
||||
|
|
Loading…
Reference in New Issue