Update of /cvsroot/hibernate/HibernateExt/metadata/src/java/org/hibernate/reflection/java In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv21308/metadata/src/java/org/hibernate/reflection/java Modified Files: JavaXProperty.java XMLAnnotationReader.java JavaAnnotationReader.java JavaXAnnotatedElement.java JavaXPackage.java JavaXClass.java Added Files: JavaXSimpleProperty.java JavaXFactory.java Util.java Couplet.java JavaXCollectionProperty.java JavaXArrayProperty.java Removed Files: JavaXMethod.java JavaReflectionManager.java JavaXField.java Log Message: Support for generics in reflection layer --- NEW FILE: JavaXSimpleProperty.java --- package org.hibernate.reflection.java; import java.lang.reflect.Member; import java.lang.reflect.Type; import java.util.Collection; import org.hibernate.reflection.XClass; import org.hibernate.reflection.java.generics.TypeEnvironment; class JavaXSimpleProperty extends JavaXProperty { JavaXSimpleProperty(Member member, Type type, TypeEnvironment env, JavaXFactory rm) { super( member, type, env, rm ); } public boolean isArray() { return false; } public boolean isCollection() { return false; } public Class<? extends Collection> getCollectionClass() { return null; } public XClass getElementClass() { return getType(); } public XClass getClassOrElementClass() { return getType( ); } } --- NEW FILE: JavaXFactory.java --- package org.hibernate.reflection.java; import java.lang.reflect.Member; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.HashMap; import java.util.Map; import org.dom4j.Document; import org.hibernate.reflection.ReflectionManager; import org.hibernate.reflection.XClass; import org.hibernate.reflection.XPackage; import org.hibernate.reflection.XProperty; import org.hibernate.reflection.java.generics.IdentityTypeEnvironment; import org.hibernate.reflection.java.generics.TypeEnvironment; import org.hibernate.reflection.java.generics.TypeEnvironmentFactory; import org.hibernate.reflection.java.generics.TypeSwitch; import org.hibernate.util.ReflectHelper; /** * The factory for all the objects in this package. * * @author Paolo Perrotta * @author Davide Marchignoli */ public class JavaXFactory implements ReflectionManager { private static class PropertyKey extends Couplet<Member, XClass> { PropertyKey( Member member, XClass owner ) { super( member, owner ); } } private static class TypeKey extends Couplet<Type, TypeEnvironment> { TypeKey( Type t, TypeEnvironment context ) { super( t, context ); } } private final Map<TypeKey, JavaXClass> xClasses = new HashMap<TypeKey, JavaXClass>(); private final Map<Package, JavaXPackage> packagesToXPackages = new HashMap<Package, JavaXPackage>(); private final Map<PropertyKey, JavaXProperty> xProperties = new HashMap<PropertyKey, JavaXProperty>(); private final TypeEnvironmentFactory typeEnvs = new TypeEnvironmentFactory(); private final Document xml; public JavaXFactory() { this.xml = null; } public JavaXFactory( Document xmlDescriptor ) { this.xml = xmlDescriptor; } public XClass toXClass(Class clazz) { return toXClass( clazz, IdentityTypeEnvironment.INSTANCE ); } public XClass classForName(String name, Class caller) throws ClassNotFoundException { return toXClass( ReflectHelper.classForName( name, caller ) ); } public XPackage packageForName(String packageName) throws ClassNotFoundException { return getXAnnotatedElement( ReflectHelper.classForName( packageName + ".package-info" ).getPackage() ); } XClass toXClass(Type t, final TypeEnvironment context) { return new TypeSwitch<XClass>() { @Override public XClass caseClass(Class classType) { TypeKey key = new TypeKey( classType, context ); JavaXClass result = xClasses.get( key ); if ( result == null ) { result = new JavaXClass( classType, context, JavaXFactory.this ); result.setXMLDescriptor( xml ); xClasses.put( key, result ); } return result; } @Override public XClass caseParameterizedType(ParameterizedType parameterizedType) { return toXClass( parameterizedType.getRawType(), context ); } }.doSwitch( t ); } XPackage getXAnnotatedElement(Package pkg) { JavaXPackage xPackage = packagesToXPackages.get( pkg ); if ( xPackage == null ) { xPackage = new JavaXPackage( pkg, this ); xPackage.setXMLDescriptor( xml ); packagesToXPackages.put( pkg, xPackage ); } return xPackage; } XProperty getXAnnotatedElement(Member member, JavaXClass owner) { PropertyKey key = new PropertyKey( member, owner ); JavaXProperty xProperty = xProperties.get( key ); if ( xProperty != null ) return xProperty; TypeEnvironment context = owner.getTypeEnvironment(); Type propType = Util.typeOf( member, context ); JavaXProperty result = null; if ( JavaXProperty.isArrayType( propType ) ) return new JavaXArrayProperty( member, propType, context, this ); else if ( JavaXProperty.isCollectionType( propType ) ) result = new JavaXCollectionProperty( member, propType, context, JavaXFactory.this ); else if ( JavaXProperty.isBaseType( propType ) ) result = new JavaXSimpleProperty( member, propType, context, this ); else return null; xProperties.put( key, result ); return result; } TypeEnvironment getTypeEnvironment(final Type t) { return new TypeSwitch<TypeEnvironment>() { @Override public TypeEnvironment caseClass(Class classType) { return typeEnvs.getEnvironment( classType ); } @Override public TypeEnvironment caseParameterizedType(ParameterizedType parameterizedType) { return typeEnvs.getEnvironment( parameterizedType ); } @Override public TypeEnvironment defaultCase(Type type) { return IdentityTypeEnvironment.INSTANCE; } }.doSwitch( t ); } public boolean equals(XClass class1, Class class2) { if ( class1 == null ) return class2 == null; return ( (JavaXClass) class1 ).toClass().equals( class2 ); } } --- NEW FILE: Util.java --- package org.hibernate.reflection.java; import java.lang.reflect.Field; import java.lang.reflect.Member; import java.lang.reflect.Method; import java.lang.reflect.Type; import org.hibernate.reflection.java.generics.IdentityTypeEnvironment; import org.hibernate.reflection.java.generics.TypeEnvironment; class Util { static Type typeOf(Member member) { return typeOf( member, IdentityTypeEnvironment.INSTANCE ); } static Type typeOf(Member member, TypeEnvironment env) { if ( member instanceof Field ) return env.bind( ( (Field) member ).getGenericType() ); if ( member instanceof Method ) return env.bind( ( (Method) member ).getGenericReturnType() ); throw new IllegalArgumentException( "Member " + member + " is neither a field nor a method" ); } } --- NEW FILE: Couplet.java --- package org.hibernate.reflection.java; /** * A pair of objects that can be used as a key in a Map. * * @author Paolo Perrotta * @author Davide Marchignoli */ abstract class Couplet<T, U> { private final T o1; private final U o2; Couplet( T o1, U o2 ) { this.o1 = o1; this.o2 = o2; } @Override public boolean equals(Object obj) { Couplet other = (Couplet) obj; return safeEquals( o1, other.o1 ) && safeEquals( o2, other.o2 ); } @Override public int hashCode() { return safeHashCode( o1 ) ^ safeHashCode( o2 ); } private int safeHashCode(Object o) { if( o == null ) return 0; return o.hashCode(); } private boolean safeEquals(Object obj1, Object obj2) { if ( obj1 == null ) return obj2 == null; boolean result = obj1.equals( obj2 ); return result; } } --- NEW FILE: JavaXCollectionProperty.java --- package org.hibernate.reflection.java; import java.lang.reflect.Member; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.Map; import org.hibernate.reflection.XClass; import org.hibernate.reflection.java.generics.TypeEnvironment; import org.hibernate.reflection.java.generics.TypeSwitch; class JavaXCollectionProperty extends JavaXProperty { JavaXCollectionProperty( Member member, Type type, TypeEnvironment env, JavaXFactory rm ) { super( member, type, env, rm ); } public boolean isArray() { return false; } public boolean isCollection() { return true; } public XClass getElementClass() { return new TypeSwitch<XClass>() { @Override public XClass caseParameterizedType(ParameterizedType parameterizedType) { Type[] args = parameterizedType.getActualTypeArguments(); Type componentType; if ( getCollectionClass().isAssignableFrom( Map.class ) ) componentType = args[1]; else componentType = args[0]; return getFactory().toXClass( componentType, getTypeEnvironment() ); } }.doSwitch( getJavaType() ); } public XClass getClassOrElementClass() { return getType(); } } --- NEW FILE: JavaXArrayProperty.java --- package org.hibernate.reflection.java; import java.lang.reflect.GenericArrayType; import java.lang.reflect.Member; import java.lang.reflect.Type; import java.util.Collection; import org.hibernate.reflection.XClass; import org.hibernate.reflection.java.generics.TypeEnvironment; import org.hibernate.reflection.java.generics.TypeSwitch; class JavaXArrayProperty extends JavaXProperty { JavaXArrayProperty( Member member, Type type, TypeEnvironment env, JavaXFactory rm ) { super( member, type, env, rm ); assert ( type instanceof Class && ((Class)type).isArray() ) || type instanceof GenericArrayType; } public boolean isArray() { return true; } public boolean isCollection() { return false; } public Class<? extends Collection> getCollectionClass() { return null; } public XClass getElementClass() { return new TypeSwitch<XClass>() { @Override public XClass caseClass(Class classType) { return getFactory().toXClass( classType.getComponentType(), getTypeEnvironment() ); } @Override public XClass caseGenericArrayType(GenericArrayType genericArrayType) { return getFactory().toXClass( genericArrayType.getGenericComponentType(), getTypeEnvironment() ); } @Override public XClass defaultCase(Type t) { throw new IllegalArgumentException( t + " is not an array type" ); } }.doSwitch( getJavaType() ); } public XClass getClassOrElementClass() { return getElementClass(); } } Index: JavaXProperty.java =================================================================== RCS file: /cvsroot/hibernate/HibernateExt/metadata/src/java/org/hibernate/reflection/java/JavaXProperty.java,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- JavaXProperty.java 25 Jan 2006 21:48:21 -0000 1.2 +++ JavaXProperty.java 13 Feb 2006 19:14:35 -0000 1.3 @@ -1,127 +1,175 @@ package org.hibernate.reflection.java; +import java.beans.Introspector; +import java.lang.reflect.AnnotatedElement; +import java.lang.reflect.Field; +import java.lang.reflect.GenericArrayType; import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; -import java.lang.reflect.TypeVariable; import java.util.Collection; -import org.hibernate.AssertionFailure; -import org.hibernate.reflection.ReflectionManager; import org.hibernate.reflection.XClass; import org.hibernate.reflection.XProperty; +import org.hibernate.reflection.java.generics.TypeEnvironment; +import org.hibernate.reflection.java.generics.TypeSwitch; /** * @author Paolo Perrotta * @author Davide Marchignoli */ -@SuppressWarnings("unchecked") abstract class JavaXProperty extends JavaXAnnotatedElement implements XProperty { - - protected abstract Type getGenericType(); - - protected abstract JavaXClass getRawType(); - protected abstract Member toJavaMember(); + private final Type type; - public boolean isCollection() { - return getRawType().isCollection(); - } - - public boolean isArray() { - return getRawType().isArray(); - } - - public Class<? extends Collection> getCollectionClass() { - if(!isCollection()) - throw new RuntimeException("Property " + toJavaMember() + " is not a collection"); - return getRawType().toClass(); - } + private final TypeEnvironment env; - public XClass getClassOrElementClass() { - if(isArray()) - return ReflectionManager.INSTANCE.toXClass(getRawType().toClass().getComponentType()); - if(isCollection()) { - Type t = getGenericType(); - if(t instanceof Class) - return null; - if(t instanceof ParameterizedType) { - Type[] typeArgs = ((ParameterizedType)t).getActualTypeArguments(); - Type result; - if(typeArgs.length == 1 && typeArgs[0] instanceof Class) // List, Set - result = typeArgs[0]; - else if(typeArgs.length == 2 && typeArgs[1] instanceof Class) // Map - result = typeArgs[1]; - else - return null; - return ReflectionManager.INSTANCE.toXClass((Class)result); - } - return null; - } - return getRawType(); - } - - // TODO: refactor - public XClass getClassOrElement(XClass rootEntity) { - XClass c = getType(rootEntity); - if ( ((JavaXClass)c).isArray() ) - return getClassOrElementClass(); - else - return c; - } - - // TODO: refactor - public final XClass getType(XClass rootEntity) { - Type t = getGenericType(); - - if (t instanceof Class) - return ReflectionManager.INSTANCE.toXClass((Class) t); + static boolean isCollectionType(Type t) { + return getCollectionClass( t ) != null; + } - else if ( t instanceof ParameterizedType ) { - ParameterizedType pt = (ParameterizedType) t; - Type rawType = pt.getRawType(); - if ( rawType instanceof Class ) { - return ReflectionManager.INSTANCE.toXClass((Class) rawType); - } - else { - throw new AssertionFailure("rawType of parameterized type is not a class for type " + t); - } - } + static boolean isArrayType(Type t) { + return new TypeSwitch<Boolean>() { + @Override + public Boolean caseClass(Class clazz) { + return clazz.isArray(); + } + + @Override + public Boolean caseGenericArrayType(GenericArrayType genericArrayType) { + return isBaseType( genericArrayType.getGenericComponentType() ); + } + + @Override + public Boolean defaultCase(Type type) { + return false; + } + }.doSwitch( t ); + } - if ( t instanceof TypeVariable ) { - TypeVariable neededType = (TypeVariable) t; - String varName = neededType.getName(); - Class clazz = (Class) neededType.getGenericDeclaration(); - TypeVariable[] tvs = clazz.getTypeParameters(); - int typeIndexInGenerics = 0; - if (varName != null) { - for (int index = 0 ; index < tvs.length ; index++) { - if ( varName.equals( tvs[index].getName() ) ) { - typeIndexInGenerics = index; - break; - } - } - } - Type type = rootEntity.toClass().getGenericSuperclass(); - do { - if (type != null && type instanceof ParameterizedType) { - ParameterizedType paramType = (ParameterizedType) type; - if ( clazz.equals( paramType.getRawType() ) - && paramType.getActualTypeArguments()[typeIndexInGenerics] instanceof Class) { - return ReflectionManager.INSTANCE.toXClass((Class) paramType.getActualTypeArguments()[typeIndexInGenerics]); - } - //useful to go to the next level - type = paramType.getRawType(); - } - if (type instanceof Class) { - type = ( (Class) type ).getGenericSuperclass(); - } - else { - type = null; - } - } - while (type != null); - } - throw new AssertionFailure("Unknown type Java type: " + t); - } -} + static boolean isBaseType(Type type) { + return new TypeSwitch<Boolean>() { + @Override + public Boolean caseClass(Class classType) { + return classType != void.class; + } + + @Override + public Boolean caseParameterizedType(ParameterizedType parameterizedType) { + for ( Type actualTypeArgument : parameterizedType.getActualTypeArguments() ) + if ( !isBaseType( actualTypeArgument ) ) + return false; + return true; + } + + @Override + public Boolean defaultCase(Type t) { + return false; + } + }.doSwitch( type ); + } + + static boolean isProperty(Field f, Type boundType) { + return isPropertyType( boundType ) + && !f.isSynthetic() + && !Modifier.isStatic( f.getModifiers() ) + && !Modifier.isTransient( f.getModifiers() ); + } + + private static Class<? extends Collection> getCollectionClass(Type type) { + return new TypeSwitch<Class<? extends Collection>>() { + @Override + public Class<? extends Collection> caseClass(Class clazz) { + return isCollectionClass( clazz ) ? (Class<? extends Collection>) clazz : null; + } + + @Override + public Class<? extends Collection> caseParameterizedType(ParameterizedType parameterizedType) { + Class rawType = (Class) parameterizedType.getRawType(); + for ( Type actualTypeArgument : parameterizedType.getActualTypeArguments() ) + if ( !isBaseType( actualTypeArgument ) ) + return null; + return getCollectionClass( rawType ); + } + + @Override + public Class<? extends Collection> defaultCase(Type t) { + return null; + } + }.doSwitch( type ); + } + + private static boolean isCollectionClass(Class<?> clazz) { + return clazz == java.util.Collection.class + || clazz == java.util.List.class + || clazz == java.util.Set.class + || clazz == java.util.Map.class + || clazz == java.util.SortedSet.class // extension to the specs + || clazz == java.util.SortedMap.class; // extension to the specs + } + + private static boolean isPropertyType(Type type) { + return isArrayType( type ) || isCollectionType( type ) || isBaseType( type ); + } + + static boolean isProperty(Method m, Type boundType) { + return isPropertyType( boundType ) + &&!m.isSynthetic() + && !m.isBridge() + && !Modifier.isStatic( m.getModifiers() ) + && m.getParameterTypes().length == 0 + && ( m.getName().startsWith( "get" ) || m.getName().startsWith( "is" ) ); + // TODO should we use stronger checking on the naming of getters/setters, or just leave this to the validator? + } + + protected JavaXProperty(Member member, Type type, TypeEnvironment env, JavaXFactory factory) { + super( (AnnotatedElement) member, factory ); + assert member instanceof Field || member instanceof Method; + this.type = type; + this.env = env; + } + + public XClass getType() { + return getFactory().toXClass( env.bind( type ), env ); + } + + public String getName() { + String fullName = getMember().getName(); + if ( getMember() instanceof Method ) { + // FIXME emmanuel: + // get/is and RE otherwise is an issue in my opinion + // this layer is needed for Validator and EntityManager + // EM for example needs to work on non-getter/setter methods for + // entity + // listeners + // Only the caller know if it expect a getter or a regular method + // a slighly dirty solution might be to add a isJavaBeanAttribute() + // method?? + if ( fullName.startsWith( "get" ) ) + return Introspector.decapitalize( fullName.substring( "get".length() ) ); + if ( fullName.startsWith( "is" ) ) + return Introspector.decapitalize( fullName.substring( "is".length() ) ); + throw new RuntimeException( "Method " + fullName + " is not a property getter" ); + } + else + return fullName; + } + + public Class<? extends Collection> getCollectionClass() { + return getCollectionClass( getJavaType() ); + } + + protected Type getJavaType() { + return type; + } + + protected TypeEnvironment getTypeEnvironment() { + return env; + } + + private Member getMember() { + return (Member) toAnnotatedElement(); + } +} \ No newline at end of file Index: XMLAnnotationReader.java =================================================================== RCS file: /cvsroot/hibernate/HibernateExt/metadata/src/java/org/hibernate/reflection/java/XMLAnnotationReader.java,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- XMLAnnotationReader.java 25 Jan 2006 21:48:21 -0000 1.2 +++ XMLAnnotationReader.java 13 Feb 2006 19:14:35 -0000 1.3 @@ -3,6 +3,8 @@ import java.lang.annotation.Annotation; import java.lang.reflect.AnnotatedElement; +import org.dom4j.Document; + /** * Encapsulates the overriding of Java annotations from an EJB 3.0 descriptor. * @@ -11,29 +13,24 @@ */ class XMLAnnotationReader extends JavaAnnotationReader { - public XMLAnnotationReader(AnnotatedElement el, String xmlDescriptor) { - super(el); - // TODO: it just ignores the XML for now. write the overriding mechanism - // (and use something smarter than a String to represent the xml, - // such as the DOM tree) - // - // This class is supposed to use the facilities in package annotationfactory - // to actually instance annotations (maybe we should move the whole package - // here?) - } - - public <T extends Annotation> T getAnnotation(Class<T> annotationType) { - // TODO: override - return super.getAnnotation(annotationType); - } + public XMLAnnotationReader( AnnotatedElement el, Document xmlDescriptor ) { + super( el ); + // TODO: it just ignores the XML for now. write the overrides + // + // This class is supposed to use the facilities in package + // annotationfactory to actually instance annotations (maybe we should + // move the whole package here?) + } - public <T extends Annotation> boolean isAnnotationPresent(Class<T> annotationType) { - // TODO: override - return super.isAnnotationPresent(annotationType); - } + public <T extends Annotation> T getAnnotation(Class<T> annotationType) { + return super.getAnnotation( annotationType ); + } - public Annotation[] getAnnotations() { - // TODO: override (this is also a good place to cache the xml annotations) - return super.getAnnotations(); - } + public <T extends Annotation> boolean isAnnotationPresent(Class<T> annotationType) { + return super.isAnnotationPresent( annotationType ); + } + + public Annotation[] getAnnotations() { + return super.getAnnotations(); + } } Index: JavaAnnotationReader.java =================================================================== RCS file: /cvsroot/hibernate/HibernateExt/metadata/src/java/org/hibernate/reflection/java/JavaAnnotationReader.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- JavaAnnotationReader.java 24 Jan 2006 16:01:03 -0000 1.1 +++ JavaAnnotationReader.java 13 Feb 2006 19:14:35 -0000 1.2 @@ -11,21 +11,21 @@ */ class JavaAnnotationReader { - private final AnnotatedElement element; + private final AnnotatedElement element; - public JavaAnnotationReader(AnnotatedElement el) { - this.element = el; - } - - public <T extends Annotation> T getAnnotation(Class<T> annotationType) { - return element.getAnnotation(annotationType); - } + public JavaAnnotationReader( AnnotatedElement el ) { + this.element = el; + } - public <T extends Annotation> boolean isAnnotationPresent(Class<T> annotationType) { - return element.isAnnotationPresent(annotationType); - } + public <T extends Annotation> T getAnnotation(Class<T> annotationType) { + return element.getAnnotation( annotationType ); + } - public Annotation[] getAnnotations() { - return element.getAnnotations(); - } + public <T extends Annotation> boolean isAnnotationPresent(Class<T> annotationType) { + return element.isAnnotationPresent( annotationType ); + } + + public Annotation[] getAnnotations() { + return element.getAnnotations(); + } } Index: JavaXAnnotatedElement.java =================================================================== RCS file: /cvsroot/hibernate/HibernateExt/metadata/src/java/org/hibernate/reflection/java/JavaXAnnotatedElement.java,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- JavaXAnnotatedElement.java 26 Jan 2006 15:02:55 -0000 1.3 +++ JavaXAnnotatedElement.java 13 Feb 2006 19:14:35 -0000 1.4 @@ -5,45 +5,70 @@ import org.hibernate.reflection.XAnnotatedElement; +import org.dom4j.Document; + /** * @author Paolo Perrotta * @author Davide Marchignoli */ abstract class JavaXAnnotatedElement implements XAnnotatedElement { - // does the actual job of extracting annotations - private JavaAnnotationReader annotationReader; + // responsible for extracting annotations + private JavaAnnotationReader annotationReader; - private JavaAnnotationReader getAnnotationReader() { - //FIXME emmanuel prossibly refactor that to initialize the value in the constructor - if(annotationReader == null) - annotationReader = new JavaAnnotationReader(this.toAnnotatedElement()); - return annotationReader; - } - - public void setXMLDescriptor(String xml) { - if(xml == null) - return; - annotationReader = new XMLAnnotationReader(this.toAnnotatedElement(), xml); - } - - public <T extends Annotation> T getAnnotation(Class<T> annotationType) { - return getAnnotationReader().getAnnotation(annotationType); - } + private final JavaXFactory factory; - public <T extends Annotation> boolean isAnnotationPresent( - Class<T> annotationType) { - return getAnnotationReader().isAnnotationPresent(annotationType); - } - - public Annotation[] getAnnotations() { - return getAnnotationReader().getAnnotations(); - } - - protected abstract AnnotatedElement toAnnotatedElement(); + private final AnnotatedElement annotatedElement; + + public JavaXAnnotatedElement( AnnotatedElement annotatedElement, JavaXFactory factory ) { + this.annotationReader = new JavaAnnotationReader( annotatedElement ); + this.factory = factory; + this.annotatedElement = annotatedElement; + } - @Override - public String toString() { - return toAnnotatedElement().toString(); - } + protected JavaXFactory getFactory() { + return factory; + } + + private JavaAnnotationReader getAnnotationReader() { + return annotationReader; + } + + public void setXMLDescriptor(Document xml) { + if ( xml == null ) + return; + annotationReader = new XMLAnnotationReader( this.toAnnotatedElement(), xml ); + } + + public <T extends Annotation> T getAnnotation(Class<T> annotationType) { + return getAnnotationReader().getAnnotation( annotationType ); + } + + public <T extends Annotation> boolean isAnnotationPresent(Class<T> annotationType) { + return getAnnotationReader().isAnnotationPresent( annotationType ); + } + + public Annotation[] getAnnotations() { + return getAnnotationReader().getAnnotations(); + } + + protected AnnotatedElement toAnnotatedElement() { + return annotatedElement; + } + + @Override + public boolean equals(Object obj) { + JavaXClass other = (JavaXClass) obj; + return toAnnotatedElement().equals( other.toAnnotatedElement() ); + } + + @Override + public int hashCode() { + return toAnnotatedElement().hashCode(); + } + + @Override + public String toString() { + return toAnnotatedElement().toString(); + } } Index: JavaXPackage.java =================================================================== RCS file: /cvsroot/hibernate/HibernateExt/metadata/src/java/org/hibernate/reflection/java/JavaXPackage.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- JavaXPackage.java 24 Jan 2006 16:01:03 -0000 1.1 +++ JavaXPackage.java 13 Feb 2006 19:14:35 -0000 1.2 @@ -1,7 +1,5 @@ package org.hibernate.reflection.java; -import java.lang.reflect.AnnotatedElement; - import org.hibernate.reflection.XPackage; /** @@ -10,18 +8,11 @@ */ class JavaXPackage extends JavaXAnnotatedElement implements XPackage { - private final Package pkg; - - public JavaXPackage(Package p) { - pkg = p; - } - - public String getName() { - return pkg.getName(); - } + public JavaXPackage( Package pkg, JavaXFactory factory ) { + super( pkg, factory ); + } - @Override - protected AnnotatedElement toAnnotatedElement() { - return pkg; - } + public String getName() { + return ((Package) toAnnotatedElement()).getName(); + } } Index: JavaXClass.java =================================================================== RCS file: /cvsroot/hibernate/HibernateExt/metadata/src/java/org/hibernate/reflection/java/JavaXClass.java,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- JavaXClass.java 26 Jan 2006 15:02:55 -0000 1.2 +++ JavaXClass.java 13 Feb 2006 19:14:35 -0000 1.3 @@ -1,119 +1,96 @@ package org.hibernate.reflection.java; -import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Field; +import java.lang.reflect.Member; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.LinkedList; import java.util.List; -import org.hibernate.AssertionFailure; -import org.hibernate.reflection.ReflectionManager; import org.hibernate.reflection.XClass; import org.hibernate.reflection.XProperty; -import org.hibernate.reflection.XPackage; +import org.hibernate.reflection.java.generics.TypeEnvironment; /** * @author Paolo Perrotta * @author Davide Marchignoli */ -class JavaXClass<T> extends JavaXAnnotatedElement implements XClass { +class JavaXClass extends JavaXAnnotatedElement implements XClass { - private final Class<T> clazz; - - public JavaXClass(Class<T> c) { - clazz = c; - } + private final TypeEnvironment context; - public String getName() { - return toClass().getName(); - } + public JavaXClass( Class clazz, TypeEnvironment env, JavaXFactory factory ) { + super( clazz, factory ); + this.context = env; + } - public XClass getSuperclass() { - return ReflectionManager.INSTANCE.toXClass( toClass().getSuperclass() ); - } + public String getName() { + return toClass().getName(); + } - public boolean isAbstract() { - return Modifier.isAbstract( toClass().getModifiers() ); - } + public XClass getSuperclass() { + return getFactory().toXClass( toClass().getSuperclass(), getFactory().getTypeEnvironment( toClass() ) ); + } - public boolean isPrimitive() { - return toClass().isPrimitive(); - } + public boolean isAbstract() { + return Modifier.isAbstract( toClass().getModifiers() ); + } - public boolean isEnum() { - return toClass().isEnum(); - } + public boolean isPrimitive() { + return toClass().isPrimitive(); + } - private List<XProperty> getDeclaredMethodProperties() { - Method[] declaredMethods = toClass().getDeclaredMethods(); - List<XProperty> result = new LinkedList<XProperty>(); - for (int i = 0; i < declaredMethods.length; i++) - if(isProperty(declaredMethods[i])) - result.add(new JavaXMethod(declaredMethods[i])); - return result; - } + public boolean isEnum() { + return toClass().isEnum(); + } - private boolean isProperty(Method m) { - return !m.isSynthetic() && - !m.isBridge() && - !Modifier.isStatic( m.getModifiers() ) && - m.getParameterTypes().length == 0 && - m.getReturnType() != void.class && - ( m.getName().startsWith( "get" ) || m.getName().startsWith( "is" ) ); - } + private List<XProperty> getDeclaredFieldProperties() { + List<XProperty> result = new LinkedList<XProperty>(); + for ( Field f : toClass().getDeclaredFields() ) + if ( JavaXProperty.isProperty( f, getTypeEnvironment().bind( f.getGenericType() ) ) ) + maybeAdd( f, result ); + return result; + } - private List<XProperty> getDeclaredFieldProperties() { - Field[] declaredFields = toClass().getDeclaredFields(); - List<XProperty> result = new LinkedList<XProperty>(); - for (int i = 0; i < declaredFields.length; i++) - if(isProperty(declaredFields[i])) - result.add(new JavaXField(declaredFields[i])); - return result; - } - - private boolean isProperty(Field f) { - return !f.isSynthetic() && - !Modifier.isStatic( f.getModifiers() ) && - !Modifier.isTransient( f.getModifiers() ); - } + private List<XProperty> getDeclaredMethodProperties() { + List<XProperty> result = new LinkedList<XProperty>(); + for ( Method m : toClass().getDeclaredMethods() ) + if ( JavaXProperty.isProperty( m, getTypeEnvironment().bind( m.getGenericReturnType() ) ) ) + maybeAdd( m, result ); + return result; + } - public List getDeclaredProperties(String accessType) { - if(accessType.equals("field")) - return getDeclaredFieldProperties(); - if(accessType.equals("property")) - return getDeclaredMethodProperties(); - throw new AssertionFailure("Unknown access type " + accessType); - } + private void maybeAdd(Member m, List<XProperty> result) { + XProperty p = getFactory().getXAnnotatedElement( m, this ); + if ( p != null ) + result.add( p ); + } - public Class<T> toClass() { - return clazz; - } + public List<XProperty> getDeclaredProperties(String accessType) { + if ( accessType.equals( "field" ) ) + return getDeclaredFieldProperties(); + if ( accessType.equals( "property" ) ) + return getDeclaredMethodProperties(); + throw new IllegalArgumentException( "Unknown access type " + accessType ); + } - public XPackage getPackage() { - return ReflectionManager.INSTANCE.toXPackage(toClass().getPackage()); - } + public Class<?> toClass() { + return (Class) toAnnotatedElement(); + } - public boolean isAssignableFrom(XClass c) { - return toClass().isAssignableFrom( ((JavaXClass)c).toClass() ); - } + public boolean isAssignableFrom(XClass c) { + return toClass().isAssignableFrom( ( (JavaXClass) c ).toClass() ); + } - boolean isCollection() { - return - toClass() == java.util.Collection.class || - toClass() == java.util.List.class || - toClass() == java.util.Set.class || - toClass() == java.util.Map.class || - toClass() == java.util.SortedSet.class || // extension to the specs - toClass() == java.util.SortedMap.class; // extension to the specs + boolean isArray() { + return toClass().isArray(); } - @Override - protected AnnotatedElement toAnnotatedElement() { - return clazz; - } + public Method[] getDeclaredMethods() { + return toClass().getDeclaredMethods(); + } - boolean isArray() { - return toClass().isArray(); - } + TypeEnvironment getTypeEnvironment() { + return context; + } } --- JavaXMethod.java DELETED --- --- JavaReflectionManager.java DELETED --- --- JavaXField.java DELETED --- |