#658206 : Added any() accessor

This commit is contained in:
Timo Westkämper 2010-10-11 13:06:09 +00:00
parent ad23153f7f
commit df7f6ddd82
24 changed files with 258 additions and 83 deletions

View File

@ -72,8 +72,8 @@ public final class Alias {
return aliasFactory.<EnumPath<T>> getCurrentAndReset();
}
public static <D> CollectionPath<D> $(Collection<D> args) {
return aliasFactory.<CollectionPath<D>> getCurrentAndReset();
public static <D> CollectionPath<D,?> $(Collection<D> args) {
return aliasFactory.<CollectionPath<D,?>> getCurrentAndReset();
}
public static <D extends Comparable<?>> ComparablePath<D> $(D arg) {
@ -127,8 +127,8 @@ public final class Alias {
return aliasFactory.<MapPath<K, V,?>> getCurrentAndReset();
}
public static <D> SetPath<D> $(Set<D> args) {
return aliasFactory.<SetPath<D>> getCurrentAndReset();
public static <D> SetPath<D,?> $(Set<D> args) {
return aliasFactory.<SetPath<D,?>> getCurrentAndReset();
}
public static NumberPath<Short> $(Short arg) {

View File

@ -30,9 +30,10 @@ public class DefaultPathFactory implements PathFactory{
return new BooleanPath(metadata);
}
@SuppressWarnings("unchecked")
@Override
public <E> Path<Collection<E>> createCollectionPath(Class<E> elementType, PathMetadata<?> metadata) {
return new CollectionPath<E>(elementType, elementType.getSimpleName(), metadata);
return new CollectionPath<E,EntityPathBase<E>>(elementType, (Class)EntityPathBase.class, metadata);
}
@Override
@ -77,9 +78,10 @@ public class DefaultPathFactory implements PathFactory{
return new NumberPath<T>(type, metadata);
}
@SuppressWarnings("unchecked")
@Override
public <E> Path<Set<E>> createSetPath(Class<E> elementType, PathMetadata<?> metadata) {
return new SetPath<E>(elementType, elementType.getName(), metadata);
return new SetPath<E,EntityPathBase<E>>(elementType, (Class)EntityPathBase.class, metadata);
}
@Override

View File

@ -627,6 +627,7 @@ public class EntitySerializer implements Serializer{
// strips of "? extends " etc
Type propertyType = new SimpleType(property.getType(), property.getType().getParameters());
Type queryType = typeMappings.getPathType(propertyType, model, false);
Type genericQueryType = null;
String localRawName = writer.getRawName(property.getType());
switch(property.getType().getCategory()){
@ -664,17 +665,23 @@ public class EntitySerializer implements Serializer{
serialize(model, property, new ClassType(ArrayPath.class, property.getType().getComponentType()), writer, "createArray", localRawName + DOT_CLASS);
break;
case COLLECTION:
genericQueryType = typeMappings.getPathType(getRaw(property.getParameter(0)), model, false);
localRawName = writer.getRawName(property.getParameter(0));
serialize(model, property, new ClassType(CollectionPath.class, getRaw(property.getParameter(0))), writer, "createCollection", localRawName + DOT_CLASS);
queryType = typeMappings.getPathType(property.getParameter(0), model, true);
serialize(model, property, new ClassType(CollectionPath.class, getRaw(property.getParameter(0)), genericQueryType), writer, "createCollection", localRawName + DOT_CLASS, writer.getRawName(queryType) + DOT_CLASS);
break;
case SET:
genericQueryType = typeMappings.getPathType(getRaw(property.getParameter(0)), model, false);
localRawName = writer.getRawName(property.getParameter(0));
serialize(model, property, new ClassType(SetPath.class, getRaw(property.getParameter(0))), writer, "createSet", localRawName + DOT_CLASS);
queryType = typeMappings.getPathType(property.getParameter(0), model, true);
serialize(model, property, new ClassType(SetPath.class, getRaw(property.getParameter(0)), genericQueryType), writer, "createSet", localRawName + DOT_CLASS, writer.getRawName(queryType) + DOT_CLASS);
break;
case MAP:
String genericKey = writer.getGenericName(true, property.getParameter(0));
String genericValue = writer.getGenericName(true, property.getParameter(1));
Type genericQueryType = typeMappings.getPathType(getRaw(property.getParameter(1)), model, false);
genericQueryType = typeMappings.getPathType(getRaw(property.getParameter(1)), model, false);
String keyType = writer.getRawName(property.getParameter(0));
String valueType = writer.getRawName(property.getParameter(1));
queryType = typeMappings.getPathType(property.getParameter(1), model, true);

View File

@ -11,7 +11,7 @@ import javax.annotation.Nullable;
/**
* Utilities for constructing common operation instances
* ExpressionUtils provides utilities for constructing common operation instances
*
* @author tiwe
*

View File

@ -8,7 +8,7 @@ package com.mysema.query.types;
import javax.annotation.Nullable;
/**
* PredicateOperation provides a Boolean typed Operation implemenentation
* PredicateOperation provides a Boolean typed Operation implementation
*
* @author tiwe
*

View File

@ -8,7 +8,7 @@ package com.mysema.query.types;
import com.mysema.query.QueryMetadata;
/**
* SubQueryImpl is the default implementation of the SubQuery interface
* SubQueryExpressionImpl is the default implementation of the SubQueryExpression interface
*
* @author tiwe
*

View File

@ -16,7 +16,7 @@ import com.mysema.query.types.Expression;
*
* @param <EA>
*/
public interface ArrayExpression<E> {
public interface ArrayExpression<E> extends Expression<E[]>{
/**
* Get the size of the array

View File

@ -21,7 +21,7 @@ import com.mysema.query.types.Ops;
* e.g.
*
* <pre>
* Expr&lt;String&gt; cases = new CaseBuilder()
* Expression&lt;String&gt; cases = new CaseBuilder()
* .when(c.annualSpending.gt(10000)).then("Premier")
* .when(c.annualSpending.gt(5000)).then("Gold")
* .when(c.annualSpending.gt(2000)).then("Silver")

View File

@ -22,7 +22,7 @@ import com.mysema.query.types.Ops;
*
* <pre>
* QCustomer c = QCustomer.customer;
* Expr<Integer> cases = c.annualSpending
* Expression&lt;Integer&gt; cases = c.annualSpending
* .when(1000l).then(1)
* .when(2000l).then(2)
* .when(5000l).then(3)

View File

@ -5,6 +5,8 @@
*/
package com.mysema.query.types.expr;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import javax.annotation.Nullable;
@ -13,9 +15,10 @@ import com.mysema.query.types.CollectionExpression;
import com.mysema.query.types.ConstantImpl;
import com.mysema.query.types.Expression;
import com.mysema.query.types.Ops;
import com.mysema.query.types.PathMetadata;
/**
* CollectionExpressionBase is an abstract base class for ECollection implementations
* CollectionExpressionBase is an abstract base class for CollectionExpression implementations
*
* @author tiwe
*
@ -30,11 +33,16 @@ public abstract class CollectionExpressionBase<C extends Collection<E>, E> exten
@Nullable
private volatile NumberExpression<Integer> size;
@Nullable
private transient volatile Constructor<?> constructor;
public CollectionExpressionBase(Class<? extends C> type) {
super(type);
}
public abstract SimpleExpression<E> any();
public final BooleanExpression contains(E child) {
return contains(new ConstantImpl<E>(child));
}
@ -63,6 +71,22 @@ public abstract class CollectionExpressionBase<C extends Collection<E>, E> exten
return size;
}
@SuppressWarnings("unchecked")
protected <Q extends SimpleExpression<E>> Q newInstance(Class<Q> queryType, boolean typed, PathMetadata<?> pm) throws NoSuchMethodException,
InstantiationException, IllegalAccessException,
InvocationTargetException {
if (constructor == null) {
if (typed){
constructor = queryType.getConstructor(Class.class, PathMetadata.class);
}else{
constructor = queryType.getConstructor(PathMetadata.class);
}
}
if (typed){
return (Q)constructor.newInstance(getElementType(), pm);
}else{
return (Q)constructor.newInstance(pm);
}
}
}

View File

@ -139,10 +139,11 @@ public class BeanPath<D> extends SimpleExpression<D> implements Path<D> {
* @param type
* @return
*/
protected <A> CollectionPath<A> createCollection(String property, Class<? super A> type) {
return add(new CollectionPath<A>(type, type.getSimpleName(), forProperty(property)));
@SuppressWarnings("unchecked")
protected <A, E extends SimpleExpression<A>> CollectionPath<A, E> createCollection(String property, Class<? super A> type, Class<? super E> queryType) {
return add(new CollectionPath<A, E>(type, (Class) queryType, forProperty(property)));
}
/**
* Create a new Comparable typed path
*
@ -247,8 +248,9 @@ public class BeanPath<D> extends SimpleExpression<D> implements Path<D> {
* @param type
* @return
*/
protected <A> SetPath<A> createSet(String property, Class<? super A> type) {
return add(new SetPath<A>(type, type.getSimpleName(), forProperty(property)));
@SuppressWarnings("unchecked")
protected <A, E extends SimpleExpression<A>> SetPath<A, E> createSet(String property, Class<? super A> type, Class<? super E> queryType) {
return add(new SetPath<A, E>(type, (Class) queryType, forProperty(property)));
}
/**

View File

@ -6,14 +6,19 @@
package com.mysema.query.types.path;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import javax.annotation.Nullable;
import com.mysema.commons.lang.Assert;
import com.mysema.query.types.ExpressionException;
import com.mysema.query.types.Path;
import com.mysema.query.types.PathImpl;
import com.mysema.query.types.PathMetadata;
import com.mysema.query.types.Visitor;
import com.mysema.query.types.expr.CollectionExpressionBase;
import com.mysema.query.types.expr.SimpleExpression;
/**
* CollectionPath represents collection paths
@ -22,21 +27,24 @@ import com.mysema.query.types.expr.CollectionExpressionBase;
*
* @param <E> component type
*/
public class CollectionPath<E> extends CollectionExpressionBase<Collection<E>,E> implements Path<Collection<E>> {
public class CollectionPath<E, Q extends SimpleExpression<E>> extends CollectionExpressionBase<Collection<E>,E> implements Path<Collection<E>>{
private static final long serialVersionUID = -4982311799113762600L;
private final Class<E> elementType;
private final String entityName;
private final Path<Collection<E>> pathMixin;
@Nullable
private transient Q any;
private final Class<Q> queryType;
@SuppressWarnings("unchecked")
public CollectionPath(Class<? super E> type, String entityName, PathMetadata<?> metadata) {
public CollectionPath(Class<? super E> type, Class<Q> queryType, PathMetadata<?> metadata) {
super((Class)Collection.class);
this.elementType = (Class<E>) Assert.notNull(type,"type");
this.entityName = Assert.notNull(entityName,"entityName");
this.queryType = queryType;
this.pathMixin = new PathImpl<Collection<E>>((Class)Collection.class, metadata);
}
@ -44,6 +52,24 @@ public class CollectionPath<E> extends CollectionExpressionBase<Collection<E>,E>
public <R,C> R accept(Visitor<R,C> v, C context) {
return v.visit(this, context);
}
@Override
public Q any(){
if (any == null){
try {
any = newInstance(queryType, Constants.isTyped(queryType), pathMixin.getMetadata());
} catch (NoSuchMethodException e) {
throw new ExpressionException(e);
} catch (InstantiationException e) {
throw new ExpressionException(e);
} catch (IllegalAccessException e) {
throw new ExpressionException(e);
} catch (InvocationTargetException e) {
throw new ExpressionException(e);
}
}
return any;
}
@Override
public boolean equals(Object o) {
@ -54,15 +80,6 @@ public class CollectionPath<E> extends CollectionExpressionBase<Collection<E>,E>
return elementType;
}
/**
* Get the entity name for this Entity collection path
*
* @return
*/
public String getEntityName() {
return entityName;
}
@Override
public PathMetadata<?> getMetadata() {
return pathMixin.getMetadata();
@ -91,7 +108,5 @@ public class CollectionPath<E> extends CollectionExpressionBase<Collection<E>,E>
throw new IndexOutOfBoundsException(String.valueOf(index));
}
}
}

View File

@ -11,7 +11,7 @@ import java.util.Set;
public final class Constants {
static final Set<Class<?>> typedClasses = new HashSet<Class<?>>(Arrays.<Class<?>>asList(
private static final Set<Class<?>> typedClasses = new HashSet<Class<?>>(Arrays.<Class<?>>asList(
PathBuilder.class,
ComparablePath.class,
EnumPath.class,
@ -24,6 +24,10 @@ public final class Constants {
TimePath.class
));
public static boolean isTyped(Class<?> cl){
return typedClasses.contains(cl);
}
private Constants(){}
}

View File

@ -6,7 +6,6 @@
package com.mysema.query.types.path;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.List;
@ -18,9 +17,9 @@ import com.mysema.commons.lang.Assert;
import com.mysema.query.types.Expression;
import com.mysema.query.types.ExpressionException;
import com.mysema.query.types.Path;
import com.mysema.query.types.PathImpl;
import com.mysema.query.types.PathMetadata;
import com.mysema.query.types.PathMetadataFactory;
import com.mysema.query.types.PathImpl;
import com.mysema.query.types.Visitor;
import com.mysema.query.types.expr.CollectionExpressionBase;
import com.mysema.query.types.expr.ListExpression;
@ -46,7 +45,7 @@ public class ListPath<E, Q extends SimpleExpression<E>> extends CollectionExpres
private final Class<Q> queryType;
@Nullable
private transient Constructor<Q> constructor;
private transient Q any;
@SuppressWarnings("unchecked")
public ListPath(Class<? super E> elementType, Class<Q> queryType, PathMetadata<?> metadata) {
@ -60,6 +59,24 @@ public class ListPath<E, Q extends SimpleExpression<E>> extends CollectionExpres
public <R,C> R accept(Visitor<R,C> v, C context) {
return v.visit(this, context);
}
@Override
public Q any(){
if (any == null){
try {
any = newInstance(pathMixin.getMetadata());
} catch (NoSuchMethodException e) {
throw new ExpressionException(e);
} catch (InstantiationException e) {
throw new ExpressionException(e);
} catch (IllegalAccessException e) {
throw new ExpressionException(e);
} catch (InvocationTargetException e) {
throw new ExpressionException(e);
}
}
return any;
}
protected PathMetadata<Integer> forListAccess(int index){
return PathMetadataFactory.forListAccess(this, index);
@ -105,6 +122,11 @@ public class ListPath<E, Q extends SimpleExpression<E>> extends CollectionExpres
}
}
private Q newInstance(PathMetadata<?> md) throws NoSuchMethodException, InstantiationException,
IllegalAccessException, InvocationTargetException {
return newInstance(queryType, Constants.isTyped(queryType), md);
}
@Override
public Q get(int index) {
if (cache.containsKey(index)){
@ -140,23 +162,6 @@ public class ListPath<E, Q extends SimpleExpression<E>> extends CollectionExpres
return pathMixin.getAnnotatedElement();
}
private Q newInstance(PathMetadata<?> pm) throws NoSuchMethodException,
InstantiationException, IllegalAccessException,
InvocationTargetException {
if (constructor == null) {
if (Constants.typedClasses.contains(queryType)){
constructor = queryType.getConstructor(Class.class, PathMetadata.class);
}else{
constructor = queryType.getConstructor(PathMetadata.class);
}
}
if (Constants.typedClasses.contains(queryType)){
return constructor.newInstance(getElementType(), pm);
}else{
return constructor.newInstance(pm);
}
}
@Override
public Class<?> getParameter(int index) {
if (index == 0){

View File

@ -136,13 +136,13 @@ public class MapPath<K, V, E extends SimpleExpression<V>> extends MapExpressionB
InstantiationException, IllegalAccessException,
InvocationTargetException {
if (constructor == null){
if (Constants.typedClasses.contains(queryType)){
if (Constants.isTyped(queryType)){
constructor = queryType.getConstructor(Class.class, PathMetadata.class);
}else{
constructor = queryType.getConstructor(PathMetadata.class);
}
}
if (Constants.typedClasses.contains(queryType)){
if (Constants.isTyped(queryType)){
return constructor.newInstance(getValueType(), pm);
}else{
return constructor.newInstance(pm);

View File

@ -118,8 +118,22 @@ public final class PathBuilder<D> extends EntityPathBase<D> {
* @param type
* @return
*/
public <A> CollectionPath<A> getCollection(String property, Class<A> type) {
return super.createCollection(property, type);
public <A> CollectionPath<A, PathBuilder<A>> getCollection(String property, Class<A> type) {
return super.createCollection(property, type, PathBuilder.class);
}
/**
* Get a new Collection typed path
*
* @param <A>
* @param <E>
* @param property property name
* @param type
* @param queryType
* @return
*/
public <A, E extends SimpleExpression<A>> CollectionPath<A, E> getCollection(String property, Class<A> type, Class<E> queryType) {
return super.createCollection(property, type, queryType);
}
/**
@ -274,10 +288,24 @@ public final class PathBuilder<D> extends EntityPathBase<D> {
* @param type
* @return
*/
public <A> SetPath<A> getSet(String property, Class<A> type) {
return super.createSet(property, type);
public <A> SetPath<A, PathBuilder<A>> getSet(String property, Class<A> type) {
return super.createSet(property, type, PathBuilder.class);
}
/**
* Get a new Set typed path
*
* @param <A>
* @param <E>
* @param property property name
* @param type
* @param queryType
* @return
*/
public <A, E extends SimpleExpression<A>> SetPath<A, E> getSet(String property, Class<A> type, Class<E> queryType) {
return super.createSet(property, type, queryType);
}
/**
* @param <A>
* @param path

View File

@ -6,14 +6,19 @@
package com.mysema.query.types.path;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.InvocationTargetException;
import java.util.Set;
import javax.annotation.Nullable;
import com.mysema.commons.lang.Assert;
import com.mysema.query.types.ExpressionException;
import com.mysema.query.types.Path;
import com.mysema.query.types.PathMetadata;
import com.mysema.query.types.PathImpl;
import com.mysema.query.types.Visitor;
import com.mysema.query.types.expr.CollectionExpressionBase;
import com.mysema.query.types.expr.SimpleExpression;
/**
* SetPath represents set paths
@ -22,21 +27,24 @@ import com.mysema.query.types.expr.CollectionExpressionBase;
*
* @param <E> component type
*/
public class SetPath<E> extends CollectionExpressionBase<Set<E>,E> implements Path<Set<E>> {
public class SetPath<E, Q extends SimpleExpression<E>> extends CollectionExpressionBase<Set<E>,E> implements Path<Set<E>> {
private static final long serialVersionUID = 4145848445507037373L;
private final Class<E> elementType;
private final String entityName;
private final Path<Set<E>> pathMixin;
@Nullable
private transient Q any;
private final Class<Q> queryType;
@SuppressWarnings("unchecked")
public SetPath(Class<? super E> type, String entityName, PathMetadata<?> metadata) {
public SetPath(Class<? super E> type, Class<Q> queryType, PathMetadata<?> metadata) {
super((Class)Set.class);
this.elementType = (Class<E>) Assert.notNull(type,"type");
this.entityName = Assert.notNull(entityName,"entityName");
this.queryType = queryType;
this.pathMixin = new PathImpl<Set<E>>((Class)Set.class, metadata);
}
@ -44,6 +52,24 @@ public class SetPath<E> extends CollectionExpressionBase<Set<E>,E> implements Pa
public <R,C> R accept(Visitor<R,C> v, C context) {
return v.visit(this, context);
}
@Override
public Q any(){
if (any == null){
try {
any = newInstance(queryType, Constants.isTyped(queryType), pathMixin.getMetadata());
} catch (NoSuchMethodException e) {
throw new ExpressionException(e);
} catch (InstantiationException e) {
throw new ExpressionException(e);
} catch (IllegalAccessException e) {
throw new ExpressionException(e);
} catch (InvocationTargetException e) {
throw new ExpressionException(e);
}
}
return any;
}
@Override
public boolean equals(Object o) {
@ -54,15 +80,6 @@ public class SetPath<E> extends CollectionExpressionBase<Set<E>,E> implements Pa
return elementType;
}
/**
* Get the entity name for this Entity collection path
*
* @return
*/
public String getEntityName() {
return entityName;
}
@Override
public PathMetadata<?> getMetadata() {
return pathMixin.getMetadata();

View File

@ -4,6 +4,8 @@ import com.mysema.query.types.SubQueryExpression;
import com.mysema.query.types.expr.BooleanExpression;
/**
* Extensions to the SubQueryExpression interface
*
* @author tiwe
*
* @param <T>

View File

@ -38,7 +38,7 @@ public final class ListSubQuery<A> extends CollectionExpressionBase<List<A>,A> i
@Nullable
private volatile BooleanExpression exists;
@SuppressWarnings("unchecked")
public ListSubQuery(Class<A> elementType, QueryMetadata md) {
super((Class)List.class);
@ -50,6 +50,11 @@ public final class ListSubQuery<A> extends CollectionExpressionBase<List<A>,A> i
public <R,C> R accept(Visitor<R,C> v, C context) {
return v.visit(this, context);
}
@Override
public SimpleExpression<A> any(){
throw new UnsupportedOperationException();
}
@Override
public boolean equals(Object o) {

View File

@ -0,0 +1,21 @@
package com.mysema.query.types.path;
import static org.junit.Assert.*;
import org.junit.Test;
import com.mysema.query.types.PathMetadataFactory;
public class CollectionPathTest {
@Test
public void test(){
CollectionPath<String,StringPath> stringPath = new CollectionPath<String,StringPath>(
String.class, StringPath.class,
PathMetadataFactory.forVariable("stringPath"));
assertEquals("stringPath", stringPath.toString());
assertEquals("stringPath", stringPath.any().toString());
assertEquals("eqIc(stringPath,X)", stringPath.any().equalsIgnoreCase("X").toString());
}
}

View File

@ -0,0 +1,22 @@
package com.mysema.query.types.path;
import static org.junit.Assert.*;
import org.junit.Test;
import com.mysema.query.types.PathMetadataFactory;
public class ListPathTest {
@Test
public void test(){
ListPath<String,StringPath> stringPath = new ListPath<String,StringPath>(
String.class, StringPath.class,
PathMetadataFactory.forVariable("stringPath"));
assertEquals("stringPath", stringPath.toString());
assertEquals("stringPath", stringPath.any().toString());
assertEquals("eqIc(stringPath.get(0),X)", stringPath.get(0).equalsIgnoreCase("X").toString());
assertEquals("eqIc(stringPath,X)", stringPath.any().equalsIgnoreCase("X").toString());
}
}

View File

@ -0,0 +1,21 @@
package com.mysema.query.types.path;
import static org.junit.Assert.*;
import org.junit.Test;
import com.mysema.query.types.PathMetadataFactory;
public class SetPathTest {
@Test
public void test(){
SetPath<String,StringPath> stringPath = new SetPath<String,StringPath>(
String.class, StringPath.class,
PathMetadataFactory.forVariable("stringPath"));
assertEquals("stringPath", stringPath.toString());
assertEquals("stringPath", stringPath.any().toString());
assertEquals("eqIc(stringPath,X)", stringPath.any().equalsIgnoreCase("X").toString());
}
}

View File

@ -43,7 +43,7 @@ public class JDOQLMethodsTest extends AbstractJDOTest {
private <A,K,V> List<BooleanExpression> getFilters(
StringExpression str, StringExpression other, String knownString,
CollectionPath<A> list, A element,
CollectionPath<A,?> list, A element,
MapPath<K,V, ?> map, K key, V value,
NumberExpression<Integer> number){
return Arrays.<BooleanExpression>asList(

View File

@ -25,7 +25,7 @@ public class QStore extends EntityPathBase<com.mysema.query.jdo.test.domain.Stor
public final MapPath<String,Product,QProduct> productsByName = this.<String,Product,QProduct>createMap("productsByName",String.class,Product.class,QProduct.class);
public final CollectionPath<Product> products = createCollection("products",Product.class);
public final CollectionPath<Product,QProduct> products = createCollection("products",Product.class,QProduct.class);
public QProduct productsByName(String key) {
return new QProduct(PathMetadataFactory.forMapAccess(productsByName,key));