mirror of
https://github.com/querydsl/querydsl.git
synced 2026-07-03 21:07:49 +08:00
#517618 : added support for annotation access
This commit is contained in:
parent
46f905d9ea
commit
09191406f8
@ -5,6 +5,7 @@
|
||||
*/
|
||||
package com.mysema.query.types.path;
|
||||
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.lang.reflect.Array;
|
||||
|
||||
import javax.annotation.Nonnegative;
|
||||
@ -116,6 +117,11 @@ public class PArray<E> extends Expr<E[]> implements Path<E[]>, EArray<E>{
|
||||
return pathMixin.isNull();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotatedElement getAnnotatedElement(){
|
||||
return pathMixin.getAnnotatedElement();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an expression for the array size
|
||||
*
|
||||
|
||||
@ -5,6 +5,8 @@
|
||||
*/
|
||||
package com.mysema.query.types.path;
|
||||
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
|
||||
import com.mysema.query.types.Visitor;
|
||||
import com.mysema.query.types.expr.EBoolean;
|
||||
|
||||
@ -72,4 +74,9 @@ public class PBoolean extends EBoolean implements Path<Boolean> {
|
||||
return pathMixin.isNull();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotatedElement getAnnotatedElement(){
|
||||
return pathMixin.getAnnotatedElement();
|
||||
}
|
||||
|
||||
}
|
||||
@ -5,6 +5,7 @@
|
||||
*/
|
||||
package com.mysema.query.types.path;
|
||||
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.util.Collection;
|
||||
|
||||
import com.mysema.commons.lang.Assert;
|
||||
@ -90,5 +91,10 @@ public class PCollection<E> extends ECollectionBase<Collection<E>,E> implements
|
||||
public EBoolean isNull() {
|
||||
return pathMixin.isNull();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotatedElement getAnnotatedElement(){
|
||||
return pathMixin.getAnnotatedElement();
|
||||
}
|
||||
|
||||
}
|
||||
@ -5,6 +5,8 @@
|
||||
*/
|
||||
package com.mysema.query.types.path;
|
||||
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
|
||||
import com.mysema.query.types.Visitor;
|
||||
import com.mysema.query.types.expr.EBoolean;
|
||||
import com.mysema.query.types.expr.EComparable;
|
||||
@ -78,4 +80,9 @@ public class PComparable<D extends Comparable> extends EComparable<D> implements
|
||||
public EBoolean isNull() {
|
||||
return pathMixin.isNull();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotatedElement getAnnotatedElement(){
|
||||
return pathMixin.getAnnotatedElement();
|
||||
}
|
||||
}
|
||||
@ -5,6 +5,8 @@
|
||||
*/
|
||||
package com.mysema.query.types.path;
|
||||
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
|
||||
import com.mysema.query.types.Visitor;
|
||||
import com.mysema.query.types.expr.EBoolean;
|
||||
import com.mysema.query.types.expr.EDate;
|
||||
@ -71,5 +73,10 @@ public class PDate<D extends Comparable> extends EDate<D> implements Path<D>{
|
||||
public EBoolean isNull() {
|
||||
return pathMixin.isNull();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotatedElement getAnnotatedElement(){
|
||||
return pathMixin.getAnnotatedElement();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -5,6 +5,8 @@
|
||||
*/
|
||||
package com.mysema.query.types.path;
|
||||
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
|
||||
import com.mysema.query.types.Visitor;
|
||||
import com.mysema.query.types.expr.EBoolean;
|
||||
import com.mysema.query.types.expr.EDateTime;
|
||||
@ -71,4 +73,9 @@ public class PDateTime<D extends Comparable> extends EDateTime<D> implements Pat
|
||||
public EBoolean isNull() {
|
||||
return pathMixin.isNull();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotatedElement getAnnotatedElement(){
|
||||
return pathMixin.getAnnotatedElement();
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
*/
|
||||
package com.mysema.query.types.path;
|
||||
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@ -270,4 +271,9 @@ public class PEntity<D> extends Expr<D> implements Path<D> {
|
||||
public EBoolean isNull() {
|
||||
return pathMixin.isNull();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotatedElement getAnnotatedElement(){
|
||||
return pathMixin.getAnnotatedElement();
|
||||
}
|
||||
}
|
||||
@ -5,6 +5,7 @@
|
||||
*/
|
||||
package com.mysema.query.types.path;
|
||||
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
@ -142,6 +143,11 @@ public class PList<E, Q extends Expr<E>> extends ECollectionBase<List<E>,E> impl
|
||||
return pathMixin.isNull();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotatedElement getAnnotatedElement(){
|
||||
return pathMixin.getAnnotatedElement();
|
||||
}
|
||||
|
||||
private Q newInstance(PathMetadata<?> pm) throws Exception{
|
||||
if (constructor == null){
|
||||
try {
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
*/
|
||||
package com.mysema.query.types.path;
|
||||
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
@ -134,6 +135,11 @@ public class PMap<K, V, E extends Expr<V>> extends EMapBase<K, V> implements Pat
|
||||
return pathMixin.isNull();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotatedElement getAnnotatedElement(){
|
||||
return pathMixin.getAnnotatedElement();
|
||||
}
|
||||
|
||||
private E newInstance(PathMetadata<?> pm) throws Exception{
|
||||
if (constructor == null){
|
||||
try {
|
||||
|
||||
@ -5,6 +5,8 @@
|
||||
*/
|
||||
package com.mysema.query.types.path;
|
||||
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
|
||||
import com.mysema.query.types.Visitor;
|
||||
import com.mysema.query.types.expr.EBoolean;
|
||||
import com.mysema.query.types.expr.ENumber;
|
||||
@ -73,4 +75,9 @@ public class PNumber<D extends Number & Comparable<?>> extends ENumber<D> implem
|
||||
public EBoolean isNull() {
|
||||
return pathMixin.isNull();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotatedElement getAnnotatedElement(){
|
||||
return pathMixin.getAnnotatedElement();
|
||||
}
|
||||
}
|
||||
@ -5,6 +5,7 @@
|
||||
*/
|
||||
package com.mysema.query.types.path;
|
||||
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.util.Set;
|
||||
|
||||
import com.mysema.commons.lang.Assert;
|
||||
@ -90,5 +91,10 @@ public class PSet<E> extends ECollectionBase<Set<E>,E> implements Path<Set<E>> {
|
||||
public EBoolean isNull() {
|
||||
return pathMixin.isNull();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotatedElement getAnnotatedElement(){
|
||||
return pathMixin.getAnnotatedElement();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -5,6 +5,8 @@
|
||||
*/
|
||||
package com.mysema.query.types.path;
|
||||
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
|
||||
import com.mysema.query.types.Visitor;
|
||||
import com.mysema.query.types.expr.EBoolean;
|
||||
import com.mysema.query.types.expr.Expr;
|
||||
@ -73,4 +75,9 @@ public class PSimple<D> extends Expr<D> implements Path<D> {
|
||||
public EBoolean isNull() {
|
||||
return pathMixin.isNull();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotatedElement getAnnotatedElement(){
|
||||
return pathMixin.getAnnotatedElement();
|
||||
}
|
||||
}
|
||||
@ -5,6 +5,8 @@
|
||||
*/
|
||||
package com.mysema.query.types.path;
|
||||
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
|
||||
import com.mysema.query.types.Visitor;
|
||||
import com.mysema.query.types.expr.EBoolean;
|
||||
import com.mysema.query.types.expr.EString;
|
||||
@ -71,4 +73,9 @@ public class PString extends EString implements Path<String> {
|
||||
public EBoolean isNull() {
|
||||
return pathMixin.isNull();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotatedElement getAnnotatedElement(){
|
||||
return pathMixin.getAnnotatedElement();
|
||||
}
|
||||
}
|
||||
@ -5,6 +5,8 @@
|
||||
*/
|
||||
package com.mysema.query.types.path;
|
||||
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
|
||||
import com.mysema.query.types.Visitor;
|
||||
import com.mysema.query.types.expr.EBoolean;
|
||||
import com.mysema.query.types.expr.ETime;
|
||||
@ -70,4 +72,9 @@ public class PTime<D extends Comparable> extends ETime<D> implements Path<D>{
|
||||
public EBoolean isNull() {
|
||||
return pathMixin.isNull();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotatedElement getAnnotatedElement(){
|
||||
return pathMixin.getAnnotatedElement();
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,6 +5,8 @@
|
||||
*/
|
||||
package com.mysema.query.types.path;
|
||||
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
|
||||
import com.mysema.query.types.expr.EBoolean;
|
||||
import com.mysema.query.types.expr.Expr;
|
||||
|
||||
@ -55,5 +57,15 @@ public interface Path<C> {
|
||||
* @return
|
||||
*/
|
||||
EBoolean isNull();
|
||||
|
||||
/**
|
||||
* Return the annotated element related to the given path
|
||||
* For property paths the annotated element contains the annotations of the
|
||||
* related field and/or getter method and for all others paths the annotated element
|
||||
* is the expression type.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
AnnotatedElement getAnnotatedElement();
|
||||
|
||||
}
|
||||
|
||||
@ -6,8 +6,6 @@
|
||||
package com.mysema.query.types.path;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@ -38,8 +36,6 @@ public final class PathMetadata<T> implements Serializable{
|
||||
|
||||
private final PathType pathType;
|
||||
|
||||
// private transient AnnotatedElement annotatedElement;
|
||||
|
||||
PathMetadata(@Nullable Path<?> parent, Expr<T> expression, PathType type) {
|
||||
this.parent = parent;
|
||||
this.expression = expression;
|
||||
@ -87,35 +83,5 @@ public final class PathMetadata<T> implements Serializable{
|
||||
public boolean isRoot(){
|
||||
return parent == null;
|
||||
}
|
||||
//
|
||||
// private AnnotatedElement getAnnotatedElement(){
|
||||
// if (annotatedElement == null){
|
||||
// if (pathType == PathType.VARIABLE){
|
||||
// annotatedElement =
|
||||
// }
|
||||
// }
|
||||
// return annotatedElement;
|
||||
// }
|
||||
//
|
||||
// @SuppressWarnings("hiding")
|
||||
// @Override
|
||||
// public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
|
||||
// return getAnnotatedElement().getAnnotation(annotationClass);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public Annotation[] getAnnotations() {
|
||||
// return getAnnotatedElement().getAnnotations();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public Annotation[] getDeclaredAnnotations() {
|
||||
// return getAnnotatedElement().getDeclaredAnnotations();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
|
||||
// return getAnnotatedElement().isAnnotationPresent(annotationClass);
|
||||
// }
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -6,11 +6,13 @@
|
||||
package com.mysema.query.types.path;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
|
||||
import com.mysema.query.types.expr.EBoolean;
|
||||
import com.mysema.query.types.expr.Expr;
|
||||
import com.mysema.query.types.operation.OBoolean;
|
||||
import com.mysema.query.types.operation.Ops;
|
||||
import com.mysema.util.PropertyUtils;
|
||||
|
||||
/**
|
||||
* PathMixin defines a mixin version of the Path interface which can be used
|
||||
@ -31,6 +33,8 @@ class PathMixin<T> implements Path<T>, Serializable {
|
||||
|
||||
private final Expr<T> self;
|
||||
|
||||
private AnnotatedElement annotatedElement;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public PathMixin(Expr<T> self, PathMetadata<?> metadata){
|
||||
this.self = self;
|
||||
@ -84,4 +88,20 @@ class PathMixin<T> implements Path<T>, Serializable {
|
||||
return isnull;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotatedElement getAnnotatedElement() {
|
||||
if (annotatedElement == null){
|
||||
if (metadata.getPathType() == PathType.PROPERTY){
|
||||
Class<?> beanClass = metadata.getParent().getType();
|
||||
String propertyName = metadata.getExpression().toString();
|
||||
annotatedElement = PropertyUtils.getAnnotatedElement(beanClass, propertyName, self.getType());
|
||||
|
||||
}else{
|
||||
annotatedElement = self.getType();
|
||||
}
|
||||
}
|
||||
return annotatedElement;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,45 @@
|
||||
package com.mysema.util;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author tiwe
|
||||
*
|
||||
*/
|
||||
public class AnnotatedElementAdapter implements AnnotatedElement{
|
||||
|
||||
private final Map<Class<?>,Annotation> annotations = new HashMap<Class<?>,Annotation>();
|
||||
|
||||
public AnnotatedElementAdapter(AnnotatedElement... elements){
|
||||
for (AnnotatedElement element : elements){
|
||||
for (Annotation annotation : element.getAnnotations()){
|
||||
annotations.put(annotation.annotationType(), annotation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
|
||||
return (T) annotations.get(annotationClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Annotation[] getAnnotations() {
|
||||
return annotations.values().toArray(new Annotation[annotations.values().size()]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Annotation[] getDeclaredAnnotations() {
|
||||
return getAnnotations();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
|
||||
return annotations.containsKey(annotationClass);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,60 @@
|
||||
package com.mysema.util;
|
||||
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.sun.xml.internal.ws.util.StringUtils;
|
||||
|
||||
/**
|
||||
* @author tiwe
|
||||
*
|
||||
*/
|
||||
public final class PropertyUtils {
|
||||
|
||||
private PropertyUtils(){}
|
||||
|
||||
@Nullable
|
||||
public static AnnotatedElement getAnnotatedElement(Class<?> beanClass, String propertyName, Class<?> propertyClass){
|
||||
Field field = getField(beanClass, propertyName);
|
||||
Method method = getGetter(beanClass, propertyName, propertyClass);
|
||||
if (field == null || field.getAnnotations().length == 0){
|
||||
return method;
|
||||
}else if (method == null || method.getAnnotations().length == 0){
|
||||
return field;
|
||||
}else{
|
||||
return new AnnotatedElementAdapter(field, method);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Field getField(Class<?> beanClass, String propertyName){
|
||||
while (!beanClass.equals(Object.class)){
|
||||
try {
|
||||
return beanClass.getDeclaredField(propertyName);
|
||||
} catch (SecurityException e) { // skip
|
||||
} catch (NoSuchFieldException e) { // skip
|
||||
}
|
||||
beanClass = beanClass.getSuperclass();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Method getGetter(Class<?> beanClass, String name, Class<?> type){
|
||||
String methodName = (type.equals(Boolean.class) ? "is" : "get") + StringUtils.capitalize(name);
|
||||
while(!beanClass.equals(Object.class)){
|
||||
try {
|
||||
return beanClass.getDeclaredMethod(methodName);
|
||||
} catch (SecurityException e) { // skip
|
||||
} catch (NoSuchMethodException e) { // skip
|
||||
}
|
||||
beanClass = beanClass.getSuperclass();
|
||||
}
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,109 @@
|
||||
package com.mysema.query.types.path;
|
||||
|
||||
import static com.mysema.query.alias.Alias.$;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.mysema.query.alias.Alias;
|
||||
import com.mysema.query.annotations.QueryEntity;
|
||||
import com.mysema.query.annotations.QueryTransient;
|
||||
import com.mysema.util.AnnotatedElementAdapter;
|
||||
|
||||
public class PathTest {
|
||||
|
||||
public static class Superclass {
|
||||
|
||||
@Nullable
|
||||
public String getProperty4(){
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@QueryEntity
|
||||
public static class Entity extends Superclass{
|
||||
|
||||
@Nullable
|
||||
private String property1;
|
||||
|
||||
private String property2;
|
||||
|
||||
@QueryTransient
|
||||
private String property3;
|
||||
|
||||
public String getProperty1(){
|
||||
return property1;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public String getProperty2(){
|
||||
return property2;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public String getProperty3(){
|
||||
return property3;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAnnotatedElement(){
|
||||
Entity entity = Alias.alias(Entity.class);
|
||||
|
||||
AnnotatedElement element = $(entity).getAnnotatedElement();
|
||||
|
||||
// type
|
||||
assertEquals(Entity.class, element);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAnnotatedElement_for_property(){
|
||||
Entity entity = Alias.alias(Entity.class);
|
||||
AnnotatedElement property1 = $(entity.getProperty1()).getAnnotatedElement();
|
||||
AnnotatedElement property2 = $(entity.getProperty2()).getAnnotatedElement();
|
||||
AnnotatedElement property3 = $(entity.getProperty3()).getAnnotatedElement();
|
||||
AnnotatedElement property4 = $(entity.getProperty4()).getAnnotatedElement();
|
||||
|
||||
// property (field)
|
||||
assertEquals(Field.class, property1.getClass());
|
||||
assertTrue(property1.isAnnotationPresent(Nullable.class));
|
||||
assertNotNull(property1.getAnnotation(Nullable.class));
|
||||
assertFalse(property1.isAnnotationPresent(Nonnull.class));
|
||||
assertNull(property1.getAnnotation(Nonnull.class));
|
||||
|
||||
// property2 (method)
|
||||
assertEquals(Method.class, property2.getClass());
|
||||
assertTrue(property2.isAnnotationPresent(Nonnull.class));
|
||||
assertNotNull(property2.getAnnotation(Nonnull.class));
|
||||
assertFalse(property2.isAnnotationPresent(Nullable.class));
|
||||
assertNull(property2.getAnnotation(Nullable.class));
|
||||
|
||||
// property3 (both)
|
||||
assertEquals(AnnotatedElementAdapter.class, property3.getClass());
|
||||
assertTrue(property3.isAnnotationPresent(QueryTransient.class));
|
||||
assertNotNull(property3.getAnnotation(QueryTransient.class));
|
||||
assertTrue(property3.isAnnotationPresent(Nonnull.class));
|
||||
assertNotNull(property3.getAnnotation(Nonnull.class));
|
||||
assertFalse(property3.isAnnotationPresent(Nullable.class));
|
||||
assertNull(property3.getAnnotation(Nullable.class));
|
||||
|
||||
// property 4 (superclass)
|
||||
assertEquals(Method.class, property4.getClass());
|
||||
assertTrue(property4.isAnnotationPresent(Nullable.class));
|
||||
assertNotNull(property4.getAnnotation(Nullable.class));
|
||||
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user