diff --git a/querydsl-apt/src/main/java/com/mysema/query/apt/ExtendedTypeFactory.java b/querydsl-apt/src/main/java/com/mysema/query/apt/ExtendedTypeFactory.java index dd128bd8f1..7e26ed095e 100644 --- a/querydsl-apt/src/main/java/com/mysema/query/apt/ExtendedTypeFactory.java +++ b/querydsl-apt/src/main/java/com/mysema/query/apt/ExtendedTypeFactory.java @@ -23,12 +23,17 @@ import javax.lang.model.element.TypeElement; import javax.lang.model.type.ArrayType; import javax.lang.model.type.DeclaredType; +import javax.lang.model.type.ErrorType; +import javax.lang.model.type.ExecutableType; import javax.lang.model.type.NoType; import javax.lang.model.type.NullType; +import javax.lang.model.type.PrimitiveType; import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeMirror; import javax.lang.model.type.TypeVariable; +import javax.lang.model.type.TypeVisitor; import javax.lang.model.type.WildcardType; +import javax.lang.model.util.AbstractTypeVisitor6; import com.mysema.codegen.model.SimpleType; import com.mysema.codegen.model.Type; @@ -41,6 +46,7 @@ import com.mysema.query.codegen.QueryTypeFactory; import com.mysema.query.codegen.Supertype; import com.mysema.query.codegen.TypeMappings; +import com.mysema.util.ClassPathUtils; /** * ExtendedTypeFactory is a factory for APT inspection based Type creation @@ -50,33 +56,210 @@ */ public final class ExtendedTypeFactory { - @Nullable - private static Class safeClassForName(String name){ - try { - return Class.forName(name); - } catch (ClassNotFoundException e) { - return null; - } - } - private final Map, Type> typeCache = new HashMap, Type>(); + private final Map, EntityType> entityTypeCache = new HashMap, EntityType>(); + private final Type defaultType; private final Set> entityAnnotations; - private final Map, EntityType> entityTypeCache = new HashMap, EntityType>(); - private final ProcessingEnvironment env; private final TypeElement numberType, comparableType; - private boolean doubleIndexEntities = true; - private final TypeMappings typeMappings; private final QueryTypeFactory queryTypeFactory; + private boolean doubleIndexEntities = true; + + private final TypeVisitor visitor = new AbstractTypeVisitor6() { + + @Override + public Type visitPrimitive(PrimitiveType primitiveType, Boolean p) { + switch (primitiveType.getKind()) { + case BOOLEAN: return Types.BOOLEAN; + case BYTE: return Types.BYTE; + case CHAR: return Types.CHARACTER; + case DOUBLE: return Types.DOUBLE; + case FLOAT: return Types.FLOAT; + case INT: return Types.INTEGER; + case LONG: return Types.LONG; + case SHORT: return Types.SHORT; + } + return null; + } + + @Override + public Type visitNull(NullType nullType, Boolean p) { + throw new IllegalStateException(); + } + + @Override + public Type visitArray(ArrayType arrayType, Boolean p) { + return visit(arrayType.getComponentType(), p).asArrayType(); + } + + @Override + public Type visitDeclared(DeclaredType declaredType, Boolean p) { + if (declaredType.asElement() instanceof TypeElement) { + TypeElement typeElement = (TypeElement)declaredType.asElement(); + switch(typeElement.getKind()){ + case ENUM: return createEnumType(declaredType, typeElement, p); + case CLASS: return createClassType(declaredType, typeElement, p); + case INTERFACE: return createInterfaceType(declaredType, typeElement, p); + default: throw new IllegalArgumentException("Illegal type " + typeElement); + } + } else { + throw new IllegalArgumentException("Unsupported element type " + declaredType.asElement()); + } + } + + @Override + public Type visitError(ErrorType errorType, Boolean p) { + return visitDeclared(errorType, p); + } + + @Override + public Type visitTypeVariable(TypeVariable typeVariable, Boolean p) { + String varName = typeVariable.toString(); + if (typeVariable.getUpperBound() != null) { + Type type = visit(typeVariable.getUpperBound(), p); + return new TypeExtends(varName, type); + } else if (typeVariable.getLowerBound() != null && !(typeVariable.getLowerBound() instanceof NullType)) { + return new TypeSuper(varName, visit(typeVariable.getLowerBound(), p)); + } else { + return null; + } + } + + @Override + public Type visitWildcard(WildcardType wildardType, Boolean p) { + if (wildardType.getExtendsBound() != null) { + Type type = visit(wildardType.getExtendsBound(), p); + return new TypeExtends(type); + } else if (wildardType.getSuperBound() != null) { + return new TypeSuper(visit(wildardType.getSuperBound(), p)); + } else { + return null; + } + } + + @Override + public Type visitExecutable(ExecutableType t, Boolean p) { + throw new IllegalStateException(); + } + + @Override + public Type visitNoType(NoType t, Boolean p) { + return defaultType; + } + + @Override + public Type visitUnknown(TypeMirror t, Boolean p) { + return defaultType; + } + + }; + + // TODO : return TypeMirror instead ?!? + + private final TypeVisitor, Boolean> keyBuilder = new AbstractTypeVisitor6, Boolean>() { + + private List visitBase(TypeMirror t) { + List rv = new ArrayList(); + String name = t.toString(); + if (name.contains("<")) { + name = name.substring(0, name.indexOf('<')); + } + rv.add(name); + return rv; + } + + @Override + public List visitPrimitive(PrimitiveType t, Boolean p) { + // TODO : optimize + switch (t.getKind()) { + case BOOLEAN: return Collections.singletonList("Boolean"); + case BYTE: return Collections.singletonList("Byte"); + case CHAR: return Collections.singletonList("Character"); + case DOUBLE: return Collections.singletonList("Double"); + case FLOAT: return Collections.singletonList("Float"); + case INT: return Collections.singletonList("Integer"); + case LONG: return Collections.singletonList("Long"); + case SHORT: return Collections.singletonList("Short"); + } + return null; + } + + @Override + public List visitNull(NullType t, Boolean p) { + return Collections.singletonList("Object"); + } + + @Override + public List visitArray(ArrayType t, Boolean p) { + List rv = new ArrayList(visit(t.getComponentType())); + rv.add("[]"); + return rv; + } + + @Override + public List visitDeclared(DeclaredType t, Boolean p) { + List rv = visitBase(t); + for (TypeMirror arg : t.getTypeArguments()) { + if (p) { + rv.addAll(visit(arg, false)); + } else { + rv.add(arg.toString()); + } + } + return rv; + } + + @Override + public List visitError(ErrorType t, Boolean p) { + return visitDeclared(t, p); + } + + @Override + public List visitTypeVariable(TypeVariable t, Boolean p) { + List rv = visitBase(t); + if (t.getUpperBound() != null) { + rv.addAll(visit(t.getUpperBound(), p)); + } + if (t.getLowerBound() != null) { + rv.addAll(visit(t.getLowerBound(), p)); + } + return rv; + } + + @Override + public List visitWildcard(WildcardType t, Boolean p) { + List rv = visitBase(t); + if (t.getExtendsBound() != null) { + rv.addAll(visit(t.getExtendsBound(), p)); + } + if (t.getSuperBound() != null) { + rv.addAll(visit(t.getSuperBound(), p)); + } + return rv; + } + + @Override + public List visitExecutable(ExecutableType t, Boolean p) { + throw new IllegalStateException(); + } + + @Override + public List visitNoType(NoType t, Boolean p) { + return Collections.singletonList("Object"); + } + + + }; + public ExtendedTypeFactory( ProcessingEnvironment env, Configuration configuration, @@ -91,34 +274,8 @@ public ExtendedTypeFactory( this.typeMappings = typeMappings; this.queryTypeFactory = queryTypeFactory; } - - private void appendToKey(List key, DeclaredType t, boolean deep) { - for (TypeMirror arg : t.getTypeArguments()) { - if (deep) { - key.addAll(createKey(arg, false)); - } else { - key.add(arg.toString()); - } - } - } - - private void appendToKey(List key, TypeVariable t) { - if (t.getUpperBound() != null) { - key.addAll(createKey(t.getUpperBound(), false)); - } - if (t.getLowerBound() != null) { - key.addAll(createKey(t.getLowerBound(), false)); - } - } - - private void appendToKey(List key, WildcardType t) { - if (t.getExtendsBound() != null) { - key.addAll(createKey(t.getExtendsBound(), false)); - } - if (t.getSuperBound() != null) { - key.addAll(createKey(t.getSuperBound(), false)); - } - } + + private Type createType(TypeElement typeElement, TypeCategory category, List typeArgs, boolean deep) { String name = typeElement.getQualifiedName().toString(); @@ -128,14 +285,8 @@ private Type createType(TypeElement typeElement, TypeCategory category, List getEntityTypes() { @@ -144,10 +295,7 @@ public Collection getEntityTypes() { @Nullable public Type getType(TypeMirror typeMirror, boolean deep){ - if (typeMirror.getKind().isPrimitive()) { - typeMirror = normalizePrimitiveType(typeMirror); - } - List key = createKey(typeMirror,true); + List key = keyBuilder.visit(typeMirror,true); if (entityTypeCache.containsKey(key)) { return entityTypeCache.get(key); } else if (typeCache.containsKey(key)) { @@ -160,7 +308,7 @@ public Type getType(TypeMirror typeMirror, boolean deep){ @Nullable private Type createType(TypeMirror typeMirror, List key, boolean deep) { typeCache.put(key, null); - Type type = handle(typeMirror, deep); + Type type = visitor.visit(typeMirror, deep); if (type != null && (type.getCategory() == TypeCategory.ENTITY || type.getCategory() == TypeCategory.CUSTOM)) { EntityType entityType = getEntityType(typeMirror, deep); typeCache.put(key, entityType); @@ -176,16 +324,13 @@ private Type createClassType(DeclaredType declaredType, TypeElement typeElement, String name = typeElement.getQualifiedName().toString(); TypeCategory typeCategory = TypeCategory.get(name); - if (typeCategory != TypeCategory.NUMERIC - && isImplemented(typeElement, comparableType) - && isSubType(typeElement, numberType)) { + if (typeCategory != TypeCategory.NUMERIC && isImplemented(typeElement, comparableType) && isSubType(typeElement, numberType)) { typeCategory = TypeCategory.NUMERIC; - } else if (!typeCategory.isSubCategoryOf(TypeCategory.COMPARABLE) - && isImplemented(typeElement, comparableType)) { + } else if (!typeCategory.isSubCategoryOf(TypeCategory.COMPARABLE) && isImplemented(typeElement, comparableType)) { typeCategory = TypeCategory.COMPARABLE; - } if (typeCategory == TypeCategory.SIMPLE){ + } if (typeCategory == TypeCategory.SIMPLE) { for (Class entityAnn : entityAnnotations) { if (typeElement.getAnnotation(entityAnn) != null) { typeCategory = TypeCategory.ENTITY; @@ -288,16 +433,13 @@ private Type createCollectionType(Type baseType, String simpleName, Iterator key = createKey(typeMirrors, true); + public EntityType getEntityType(TypeMirror typeMirror, boolean deep) { + List key = keyBuilder.visit(typeMirror, true); // get from cache if (entityTypeCache.containsKey(key)) { EntityType entityType = entityTypeCache.get(key); if (deep && entityType.getSuperTypes().isEmpty()) { - for (Type superType : getSupertypes(typeMirrors, entityType, deep)) { + for (Type superType : getSupertypes(typeMirror, entityType, deep)) { entityType.addSupertype(new Supertype(superType)); } } @@ -305,7 +447,7 @@ public EntityType getEntityType(TypeMirror typeMirrors, boolean deep) { // create } else { - return createEntityType(typeMirrors, key, deep); + return createEntityType(typeMirror, key, deep); } } @@ -313,7 +455,7 @@ public EntityType getEntityType(TypeMirror typeMirrors, boolean deep) { @Nullable private EntityType createEntityType(TypeMirror typeMirror, List key, boolean deep) { entityTypeCache.put(key, null); - Type value = handle(typeMirror, deep); + Type value = visitor.visit(typeMirror, deep); if (value != null) { EntityType entityType = null; if (value instanceof EntityType) { @@ -372,7 +514,7 @@ private Type createInterfaceType(DeclaredType declaredType, TypeElement typeElem String name = typeElement.getQualifiedName().toString(); String simpleName = typeElement.getSimpleName().toString(); Iterator i = declaredType.getTypeArguments().iterator(); - Class cl = safeClassForName(name); + Class cl = ClassPathUtils.safeClassForName(name); if (cl == null) { // class not available return createType(typeElement, TypeCategory.get(name), declaredType.getTypeArguments(), deep); @@ -393,26 +535,7 @@ private Type createInterfaceType(DeclaredType declaredType, TypeElement typeElem return createType(typeElement, TypeCategory.get(name), declaredType.getTypeArguments(), deep); } } - - private List createKey(TypeMirror typeMirror, boolean deep){ - List key = new ArrayList(); - String name = typeMirror.toString(); - if (name.contains("<")) { - name = name.substring(0, name.indexOf('<')); - } - key.add(name); - - if (typeMirror.getKind() == TypeKind.TYPEVAR) { - appendToKey(key, (TypeVariable) typeMirror); - } else if (typeMirror.getKind() == TypeKind.WILDCARD) { - appendToKey(key, (WildcardType)typeMirror); - } else if (typeMirror.getKind() == TypeKind.DECLARED) { - appendToKey(key, (DeclaredType)typeMirror, deep); - } - return key; - } - - + private Set getSupertypes(TypeMirror typeMirror, Type type, boolean deep) { boolean doubleIndex = doubleIndexEntities; doubleIndexEntities = false; @@ -455,78 +578,8 @@ private Set getSupertypes(TypeMirror typeMirror, Type type, boolean deep) doubleIndexEntities = doubleIndex; return superTypes; } - - @Nullable - private Type handle(TypeMirror typeMirror, boolean deep) { - if (typeMirror instanceof DeclaredType) { - return handleDeclaredType((DeclaredType)typeMirror, deep); - } else if (typeMirror instanceof TypeVariable) { - return handleTypeVariable((TypeVariable)typeMirror, deep); - } else if (typeMirror instanceof WildcardType) { - return handleWildcard((WildcardType)typeMirror, deep); - } else if (typeMirror instanceof ArrayType) { - ArrayType t = (ArrayType)typeMirror; - return getType(t.getComponentType(), deep).asArrayType(); - } else if (typeMirror instanceof NoType) { - return defaultType; - } else { - return null; - } - } - - private Type handleDeclaredType(DeclaredType declaredType, boolean deep) { - if (declaredType.asElement() instanceof TypeElement) { - TypeElement typeElement = (TypeElement)declaredType.asElement(); - switch(typeElement.getKind()){ - case ENUM: return createEnumType(declaredType, typeElement, deep); - case CLASS: return createClassType(declaredType, typeElement, deep); - case INTERFACE: return createInterfaceType(declaredType, typeElement, deep); - default: throw new IllegalArgumentException("Illegal type " + typeElement); - } - } else { - throw new IllegalArgumentException("Unsupported element type " + declaredType.asElement()); - } - } - - private TypeMirror normalizePrimitiveType(TypeMirror typeMirror){ - switch (typeMirror.getKind()) { - case BOOLEAN: return env.getElementUtils().getTypeElement(Boolean.class.getName()).asType(); - case BYTE: return env.getElementUtils().getTypeElement(Byte.class.getName()).asType(); - case CHAR: return env.getElementUtils().getTypeElement(Character.class.getName()).asType(); - case DOUBLE: return env.getElementUtils().getTypeElement(Double.class.getName()).asType(); - case FLOAT: return env.getElementUtils().getTypeElement(Float.class.getName()).asType(); - case INT: return env.getElementUtils().getTypeElement(Integer.class.getName()).asType(); - case LONG: return env.getElementUtils().getTypeElement(Long.class.getName()).asType(); - case SHORT: return env.getElementUtils().getTypeElement(Short.class.getName()).asType(); - } - throw new IllegalArgumentException("Unsupported type " + typeMirror.getKind() + " for " + typeMirror); - } - - @Nullable - private Type handleTypeVariable(TypeVariable typeVariable, boolean deep) { - String varName = typeVariable.toString(); - if (typeVariable.getUpperBound() != null) { - Type type = handle(typeVariable.getUpperBound(), deep); - return new TypeExtends(varName, type); - } else if (typeVariable.getLowerBound() != null && !(typeVariable.getLowerBound() instanceof NullType)) { - return new TypeSuper(varName, handle(typeVariable.getLowerBound(), deep)); - } else { - return null; - } - } - - @Nullable - private Type handleWildcard(WildcardType wildardType, boolean deep) { - if (wildardType.getExtendsBound() != null) { - Type type = handle(wildardType.getExtendsBound(), deep); - return new TypeExtends(type); - } else if (wildardType.getSuperBound() != null) { - return new TypeSuper(handle(wildardType.getSuperBound(), deep)); - } else { - return null; - } - } - + + // TODO : simplify this private boolean isImplemented(TypeElement type, TypeElement iface) { for (TypeMirror t : type.getInterfaces()) { diff --git a/querydsl-apt/src/test/apt/com/mysema/query/eclipse/SimpleEntity.java b/querydsl-apt/src/test/apt/com/mysema/query/eclipse/SimpleEntity.java index 087d817c69..dcb62f74df 100644 --- a/querydsl-apt/src/test/apt/com/mysema/query/eclipse/SimpleEntity.java +++ b/querydsl-apt/src/test/apt/com/mysema/query/eclipse/SimpleEntity.java @@ -23,7 +23,7 @@ public class SimpleEntity { } -class CustomComparable implements Comparable{ +class CustomComparable implements Comparable { @Override public int compareTo(CustomComparable o) { @@ -32,7 +32,7 @@ public int compareTo(CustomComparable o) { } -class CustomNumber extends Number implements Comparable{ +class CustomNumber extends Number implements Comparable { private static final long serialVersionUID = 8683978836725543780L; diff --git a/querydsl-collections/src/main/java/com/mysema/query/collections/ColDeleteClause.java b/querydsl-collections/src/main/java/com/mysema/query/collections/ColDeleteClause.java index c13f837fdc..254b0d4e6d 100644 --- a/querydsl-collections/src/main/java/com/mysema/query/collections/ColDeleteClause.java +++ b/querydsl-collections/src/main/java/com/mysema/query/collections/ColDeleteClause.java @@ -18,7 +18,7 @@ * * @param */ -public class ColDeleteClause implements DeleteClause>{ +public class ColDeleteClause implements DeleteClause> { private final Collection col; diff --git a/querydsl-collections/src/main/java/com/mysema/query/collections/ColUpdateClause.java b/querydsl-collections/src/main/java/com/mysema/query/collections/ColUpdateClause.java index f6632380d3..f4cca7670f 100644 --- a/querydsl-collections/src/main/java/com/mysema/query/collections/ColUpdateClause.java +++ b/querydsl-collections/src/main/java/com/mysema/query/collections/ColUpdateClause.java @@ -23,7 +23,7 @@ * * @param */ -public class ColUpdateClause implements UpdateClause>{ +public class ColUpdateClause implements UpdateClause> { private final Path expr; diff --git a/querydsl-core/src/main/java/com/mysema/query/dml/DeleteClause.java b/querydsl-core/src/main/java/com/mysema/query/dml/DeleteClause.java index 9ba8b0a9d3..16f7ddac9b 100644 --- a/querydsl-core/src/main/java/com/mysema/query/dml/DeleteClause.java +++ b/querydsl-core/src/main/java/com/mysema/query/dml/DeleteClause.java @@ -15,6 +15,6 @@ * * @param concrete subtype */ -public interface DeleteClause> extends DMLClause, FilteredClause{ +public interface DeleteClause> extends DMLClause, FilteredClause { } diff --git a/querydsl-core/src/main/java/com/mysema/query/dml/InsertClause.java b/querydsl-core/src/main/java/com/mysema/query/dml/InsertClause.java index 09368ac5d7..b16d104f02 100644 --- a/querydsl-core/src/main/java/com/mysema/query/dml/InsertClause.java +++ b/querydsl-core/src/main/java/com/mysema/query/dml/InsertClause.java @@ -15,7 +15,7 @@ * * @param concrete subtype */ -public interface InsertClause> extends StoreClause{ +public interface InsertClause> extends StoreClause { /** * Define the columns to be populated diff --git a/querydsl-core/src/main/java/com/mysema/query/dml/StoreClause.java b/querydsl-core/src/main/java/com/mysema/query/dml/StoreClause.java index 7113321aeb..abdd7b0483 100644 --- a/querydsl-core/src/main/java/com/mysema/query/dml/StoreClause.java +++ b/querydsl-core/src/main/java/com/mysema/query/dml/StoreClause.java @@ -17,7 +17,7 @@ * * @param concrete subtype */ -public interface StoreClause> extends DMLClause{ +public interface StoreClause> extends DMLClause { /** * Add a value binding diff --git a/querydsl-core/src/main/java/com/mysema/query/dml/UpdateClause.java b/querydsl-core/src/main/java/com/mysema/query/dml/UpdateClause.java index 015c5d7b5e..b765393db1 100644 --- a/querydsl-core/src/main/java/com/mysema/query/dml/UpdateClause.java +++ b/querydsl-core/src/main/java/com/mysema/query/dml/UpdateClause.java @@ -17,7 +17,7 @@ * * @param concrete subtype */ -public interface UpdateClause> extends StoreClause, FilteredClause{ +public interface UpdateClause> extends StoreClause, FilteredClause { /** * Set the paths to be updated diff --git a/querydsl-core/src/main/java/com/mysema/query/group/GList.java b/querydsl-core/src/main/java/com/mysema/query/group/GList.java index 810568726e..5eb6dde587 100644 --- a/querydsl-core/src/main/java/com/mysema/query/group/GList.java +++ b/querydsl-core/src/main/java/com/mysema/query/group/GList.java @@ -10,7 +10,7 @@ import com.mysema.query.types.Expression; -class GList extends AbstractGroupExpression>{ +class GList extends AbstractGroupExpression> { private static final long serialVersionUID = -5613861506383727078L; diff --git a/querydsl-core/src/main/java/com/mysema/query/group/GMap.java b/querydsl-core/src/main/java/com/mysema/query/group/GMap.java index 7771bbd096..2833bd9a2f 100644 --- a/querydsl-core/src/main/java/com/mysema/query/group/GMap.java +++ b/querydsl-core/src/main/java/com/mysema/query/group/GMap.java @@ -10,7 +10,7 @@ import com.mysema.commons.lang.Pair; -class GMap extends AbstractGroupExpression, Map>{ +class GMap extends AbstractGroupExpression, Map> { private static final long serialVersionUID = 7106389414200843920L; diff --git a/querydsl-core/src/main/java/com/mysema/query/group/GOne.java b/querydsl-core/src/main/java/com/mysema/query/group/GOne.java index 735a1c4038..24f5f35fcd 100644 --- a/querydsl-core/src/main/java/com/mysema/query/group/GOne.java +++ b/querydsl-core/src/main/java/com/mysema/query/group/GOne.java @@ -7,7 +7,7 @@ import com.mysema.query.types.Expression; -class GOne extends AbstractGroupExpression{ +class GOne extends AbstractGroupExpression { private static final long serialVersionUID = 3518868612387641383L; diff --git a/querydsl-core/src/main/java/com/mysema/query/group/GSet.java b/querydsl-core/src/main/java/com/mysema/query/group/GSet.java index b5744142ff..8dd4f111d6 100644 --- a/querydsl-core/src/main/java/com/mysema/query/group/GSet.java +++ b/querydsl-core/src/main/java/com/mysema/query/group/GSet.java @@ -8,7 +8,7 @@ import com.mysema.query.types.Expression; -class GSet extends AbstractGroupExpression>{ +class GSet extends AbstractGroupExpression> { private static final long serialVersionUID = -1575808026237160843L; diff --git a/querydsl-core/src/main/java/com/mysema/query/types/TemplateExpressionImpl.java b/querydsl-core/src/main/java/com/mysema/query/types/TemplateExpressionImpl.java index 0358c66d05..8209c78373 100644 --- a/querydsl-core/src/main/java/com/mysema/query/types/TemplateExpressionImpl.java +++ b/querydsl-core/src/main/java/com/mysema/query/types/TemplateExpressionImpl.java @@ -76,13 +76,12 @@ public Template getTemplate() { return template; } - @SuppressWarnings("unchecked") @Override public boolean equals(Object o) { if (o == this) { return true; } else if (o instanceof TemplateExpression) { - TemplateExpression c = (TemplateExpression)o; + TemplateExpression c = (TemplateExpression)o; return c.getTemplate().equals(template) && c.getType().equals(type); } else { diff --git a/querydsl-core/src/main/java/com/mysema/util/ClassPathUtils.java b/querydsl-core/src/main/java/com/mysema/util/ClassPathUtils.java index 1be05eea9d..1c5bd4b4cd 100644 --- a/querydsl-core/src/main/java/com/mysema/util/ClassPathUtils.java +++ b/querydsl-core/src/main/java/com/mysema/util/ClassPathUtils.java @@ -86,7 +86,7 @@ private static void scanJar(Set> classes, URL url, String packagePath) } } - private static Class safeClassForName(String className){ + public static Class safeClassForName(String className){ try { if (className.startsWith("com.sun")) { return null; diff --git a/querydsl-jdo/src/main/java/com/mysema/query/jdo/sql/AbstractSQLQuery.java b/querydsl-jdo/src/main/java/com/mysema/query/jdo/sql/AbstractSQLQuery.java index 5e4317c4ab..39ca4bbf51 100644 --- a/querydsl-jdo/src/main/java/com/mysema/query/jdo/sql/AbstractSQLQuery.java +++ b/querydsl-jdo/src/main/java/com/mysema/query/jdo/sql/AbstractSQLQuery.java @@ -10,10 +10,12 @@ import com.mysema.query.JoinExpression; import com.mysema.query.JoinFlag; import com.mysema.query.QueryFlag; -import com.mysema.query.QueryMetadata; import com.mysema.query.QueryFlag.Position; +import com.mysema.query.QueryMetadata; import com.mysema.query.sql.ForeignKey; +import com.mysema.query.sql.RelationalFunctionCall; import com.mysema.query.sql.RelationalPath; +import com.mysema.query.sql.SQLQueryMixin; import com.mysema.query.support.ProjectableQuery; import com.mysema.query.support.QueryMixin; import com.mysema.query.types.Expression; @@ -32,11 +34,14 @@ * * @param */ -public abstract class AbstractSQLQuery> extends ProjectableQuery{ +public abstract class AbstractSQLQuery> extends ProjectableQuery { + protected final SQLQueryMixin queryMixin; + @SuppressWarnings("unchecked") public AbstractSQLQuery(QueryMetadata metadata) { super(new QueryMixin(metadata)); + this.queryMixin = (SQLQueryMixin)super.queryMixin; this.queryMixin.setSelf((T)this); } @@ -59,13 +64,17 @@ public T from(SubQueryExpression subQuery, Path alias) { return queryMixin.from(ExpressionUtils.as((Expression)subQuery, alias)); } - public T fullJoin(ForeignKey key, RelationalPath entity) { - return queryMixin.innerJoin(entity).on(key.on(entity)); - } - public T fullJoin(RelationalPath o) { return queryMixin.fullJoin(o); } + + public T fullJoin(RelationalFunctionCall target, Path alias) { + return queryMixin.fullJoin(target, alias); + } + + public T fullJoin(ForeignKey key, RelationalPath entity) { + return queryMixin.fullJoin(entity).on(key.on(entity)); + } public T fullJoin(SubQueryExpression o, Path alias) { return queryMixin.fullJoin(o, alias); @@ -75,37 +84,49 @@ public QueryMetadata getMetadata() { return queryMixin.getMetadata(); } - public T innerJoin(ForeignKey key, RelationalPath entity) { - return queryMixin.innerJoin(entity).on(key.on(entity)); - } - public T innerJoin(RelationalPath o) { return queryMixin.innerJoin(o); } - - public T innerJoin(SubQueryExpression o, Path alias) { - return queryMixin.innerJoin(o, alias); + + public T innerJoin(RelationalFunctionCall target, Path alias) { + return queryMixin.innerJoin(target, alias); } - - public T join(ForeignKey key, RelationalPath entity) { + + public T innerJoin(ForeignKey key, RelationalPath entity) { return queryMixin.innerJoin(entity).on(key.on(entity)); } + public T innerJoin(SubQueryExpression o, Path alias) { + return queryMixin.innerJoin(o, alias); + } + public T join(RelationalPath o) { return queryMixin.join(o); } + + public T join(RelationalFunctionCall target, Path alias) { + return queryMixin.join(target, alias); + } + + public T join(ForeignKey key, RelationalPath entity) { + return queryMixin.join(entity).on(key.on(entity)); + } public T join(SubQueryExpression o, Path alias) { return queryMixin.join(o, alias); } - public T leftJoin(ForeignKey key, RelationalPath entity) { - return queryMixin.innerJoin(entity).on(key.on(entity)); - } - public T leftJoin(RelationalPath o) { return queryMixin.leftJoin(o); } + + public T leftJoin(RelationalFunctionCall target, Path alias) { + return queryMixin.leftJoin(target, alias); + } + + public T leftJoin(ForeignKey key, RelationalPath entity) { + return queryMixin.leftJoin(entity).on(key.on(entity)); + } public T leftJoin(SubQueryExpression o, Path alias) { return queryMixin.leftJoin(o, alias); @@ -115,14 +136,18 @@ public T on(Predicate... conditions) { return queryMixin.on(conditions); } - public T rightJoin(ForeignKey key, RelationalPath entity) { - return queryMixin.innerJoin(entity).on(key.on(entity)); - } - public T rightJoin(RelationalPath o) { return queryMixin.rightJoin(o); } + + public T rightJoin(RelationalFunctionCall target, Path alias) { + return queryMixin.rightJoin(target, alias); + } + public T rightJoin(ForeignKey key, RelationalPath entity) { + return queryMixin.innerJoin(entity).on(key.on(entity)); + } + public T rightJoin(SubQueryExpression o, Path alias) { return queryMixin.rightJoin(o, alias); } diff --git a/querydsl-jdo/src/main/java/com/mysema/query/jdo/sql/JDOSQLQuery.java b/querydsl-jdo/src/main/java/com/mysema/query/jdo/sql/JDOSQLQuery.java index f1e6972d84..98e6763d5c 100644 --- a/querydsl-jdo/src/main/java/com/mysema/query/jdo/sql/JDOSQLQuery.java +++ b/querydsl-jdo/src/main/java/com/mysema/query/jdo/sql/JDOSQLQuery.java @@ -42,7 +42,7 @@ * @author tiwe * */ -public final class JDOSQLQuery extends AbstractSQLQuery implements SQLCommonQuery{ +public final class JDOSQLQuery extends AbstractSQLQuery implements SQLCommonQuery { private static final Logger logger = LoggerFactory.getLogger(JDOSQLQuery.class); diff --git a/querydsl-jpa/src/main/java/com/mysema/query/jpa/AbstractSQLQuery.java b/querydsl-jpa/src/main/java/com/mysema/query/jpa/AbstractSQLQuery.java index 6d68572e4f..b60865efe5 100644 --- a/querydsl-jpa/src/main/java/com/mysema/query/jpa/AbstractSQLQuery.java +++ b/querydsl-jpa/src/main/java/com/mysema/query/jpa/AbstractSQLQuery.java @@ -10,12 +10,13 @@ import com.mysema.query.JoinExpression; import com.mysema.query.JoinFlag; import com.mysema.query.QueryFlag; -import com.mysema.query.QueryMetadata; import com.mysema.query.QueryFlag.Position; +import com.mysema.query.QueryMetadata; import com.mysema.query.sql.ForeignKey; +import com.mysema.query.sql.RelationalFunctionCall; import com.mysema.query.sql.RelationalPath; +import com.mysema.query.sql.SQLQueryMixin; import com.mysema.query.support.ProjectableQuery; -import com.mysema.query.support.QueryMixin; import com.mysema.query.types.Expression; import com.mysema.query.types.ExpressionUtils; import com.mysema.query.types.Path; @@ -32,11 +33,14 @@ * * @param concrete subtype */ -public abstract class AbstractSQLQuery> extends ProjectableQuery{ +public abstract class AbstractSQLQuery> extends ProjectableQuery { + protected final SQLQueryMixin queryMixin; + @SuppressWarnings("unchecked") public AbstractSQLQuery(QueryMetadata metadata) { - super(new QueryMixin(metadata)); + super(new SQLQueryMixin(metadata)); + this.queryMixin = (SQLQueryMixin)super.queryMixin; this.queryMixin.setSelf((T)this); } @@ -60,13 +64,17 @@ public T from(SubQueryExpression subQuery, Path alias) { return queryMixin.from(ExpressionUtils.as((Expression)subQuery, alias)); } - public T fullJoin(ForeignKey key, RelationalPath entity) { - return queryMixin.innerJoin(entity).on(key.on(entity)); - } - public T fullJoin(RelationalPath o) { return queryMixin.fullJoin(o); } + + public T fullJoin(RelationalFunctionCall target, Path alias) { + return queryMixin.fullJoin(target, alias); + } + + public T fullJoin(ForeignKey key, RelationalPath entity) { + return queryMixin.fullJoin(entity).on(key.on(entity)); + } public T fullJoin(SubQueryExpression o, Path alias) { return queryMixin.fullJoin(o, alias); @@ -76,37 +84,49 @@ public QueryMetadata getMetadata() { return queryMixin.getMetadata(); } - public T innerJoin(ForeignKey key, RelationalPath entity) { - return queryMixin.innerJoin(entity).on(key.on(entity)); - } - public T innerJoin(RelationalPath o) { return queryMixin.innerJoin(o); } - - public T innerJoin(SubQueryExpression o, Path alias) { - return queryMixin.innerJoin(o, alias); + + public T innerJoin(RelationalFunctionCall target, Path alias) { + return queryMixin.innerJoin(target, alias); } - - public T join(ForeignKey key, RelationalPath entity) { + + public T innerJoin(ForeignKey key, RelationalPath entity) { return queryMixin.innerJoin(entity).on(key.on(entity)); } + + public T innerJoin(SubQueryExpression o, Path alias) { + return queryMixin.innerJoin(o, alias); + } public T join(RelationalPath o) { return queryMixin.join(o); } + public T join(RelationalFunctionCall target, Path alias) { + return queryMixin.join(target, alias); + } + + public T join(ForeignKey key, RelationalPath entity) { + return queryMixin.join(entity).on(key.on(entity)); + } + public T join(SubQueryExpression o, Path alias) { return queryMixin.join(o, alias); } - public T leftJoin(ForeignKey key, RelationalPath entity) { - return queryMixin.innerJoin(entity).on(key.on(entity)); - } - public T leftJoin(RelationalPath o) { return queryMixin.leftJoin(o); } + + public T leftJoin(RelationalFunctionCall target, Path alias) { + return queryMixin.leftJoin(target, alias); + } + + public T leftJoin(ForeignKey key, RelationalPath entity) { + return queryMixin.innerJoin(entity).on(key.on(entity)); + } public T leftJoin(SubQueryExpression o, Path alias) { return queryMixin.leftJoin(o, alias); @@ -116,13 +136,17 @@ public T on(Predicate... conditions) { return queryMixin.on(conditions); } - public T rightJoin(ForeignKey key, RelationalPath entity) { - return queryMixin.innerJoin(entity).on(key.on(entity)); - } - public T rightJoin(RelationalPath o) { return queryMixin.rightJoin(o); } + + public T rightJoin(RelationalFunctionCall target, Path alias) { + return queryMixin.rightJoin(target, alias); + } + + public T rightJoin(ForeignKey key, RelationalPath entity) { + return queryMixin.innerJoin(entity).on(key.on(entity)); + } public T rightJoin(SubQueryExpression o, Path alias) { return queryMixin.rightJoin(o, alias); diff --git a/querydsl-sql/src/main/java/com/mysema/query/sql/AbstractSQLQuery.java b/querydsl-sql/src/main/java/com/mysema/query/sql/AbstractSQLQuery.java index 44b6c9d075..25e5e5d66c 100644 --- a/querydsl-sql/src/main/java/com/mysema/query/sql/AbstractSQLQuery.java +++ b/querydsl-sql/src/main/java/com/mysema/query/sql/AbstractSQLQuery.java @@ -30,13 +30,21 @@ import com.mysema.query.JoinFlag; import com.mysema.query.QueryException; import com.mysema.query.QueryFlag; +import com.mysema.query.QueryFlag.Position; import com.mysema.query.QueryMetadata; import com.mysema.query.QueryModifiers; import com.mysema.query.SearchResults; -import com.mysema.query.QueryFlag.Position; import com.mysema.query.support.ProjectableQuery; -import com.mysema.query.support.QueryMixin; -import com.mysema.query.types.*; +import com.mysema.query.types.Expression; +import com.mysema.query.types.ExpressionUtils; +import com.mysema.query.types.FactoryExpression; +import com.mysema.query.types.OrderSpecifier; +import com.mysema.query.types.ParamExpression; +import com.mysema.query.types.ParamNotSetException; +import com.mysema.query.types.Path; +import com.mysema.query.types.Predicate; +import com.mysema.query.types.QBean; +import com.mysema.query.types.SubQueryExpression; import com.mysema.query.types.query.ListSubQuery; import com.mysema.query.types.template.NumberTemplate; import com.mysema.query.types.template.SimpleTemplate; @@ -103,6 +111,8 @@ public String toString() { private final Configuration configuration; + protected final SQLQueryMixin queryMixin; + protected boolean unionAll; public AbstractSQLQuery(@Nullable Connection conn, Configuration configuration) { @@ -111,8 +121,9 @@ public AbstractSQLQuery(@Nullable Connection conn, Configuration configuration) @SuppressWarnings("unchecked") public AbstractSQLQuery(@Nullable Connection conn, Configuration configuration, QueryMetadata metadata) { - super(new QueryMixin(metadata)); - this.queryMixin.setSelf((Q) this); + super(new SQLQueryMixin(metadata)); + this.queryMixin = (SQLQueryMixin)super.queryMixin; + this.queryMixin.setSelf((Q) this); this.conn = conn; this.configuration = configuration; } @@ -220,6 +231,10 @@ public Q from(SubQueryExpression subQuery, Path alias) { public Q fullJoin(RelationalPath target) { return queryMixin.fullJoin(target); } + + public Q fullJoin(RelationalFunctionCall target, Path alias) { + return queryMixin.fullJoin(target, alias); + } public Q fullJoin(SubQueryExpression target, Path alias) { return queryMixin.fullJoin(target, alias); @@ -232,6 +247,10 @@ public Q fullJoin(ForeignKey key, RelationalPath entity) { public Q innerJoin(RelationalPath target) { return queryMixin.innerJoin(target); } + + public Q innerJoin(RelationalFunctionCall target, Path alias) { + return queryMixin.innerJoin(target, alias); + } public Q innerJoin(SubQueryExpression target, Path alias) { return queryMixin.innerJoin(target, alias); @@ -244,6 +263,10 @@ public Q innerJoin(ForeignKey key, RelationalPath entity) { public Q join(RelationalPath target) { return queryMixin.join(target); } + + public Q join(RelationalFunctionCall target, Path alias) { + return queryMixin.join(target, alias); + } public Q join(SubQueryExpression target, Path alias) { return queryMixin.join(target, alias); @@ -256,6 +279,10 @@ public Q join(ForeignKey key, RelationalPath entity) { public Q leftJoin(RelationalPath target) { return queryMixin.leftJoin(target); } + + public Q leftJoin(RelationalFunctionCall target, Path alias) { + return queryMixin.leftJoin(target, alias); + } public Q leftJoin(SubQueryExpression target, Path alias) { return queryMixin.leftJoin(target, alias); @@ -268,6 +295,10 @@ public Q leftJoin(ForeignKey key, RelationalPath entity) { public Q rightJoin(RelationalPath target) { return queryMixin.rightJoin(target); } + + public Q rightJoin(RelationalFunctionCall target, Path alias) { + return queryMixin.rightJoin(target, alias); + } public Q rightJoin(SubQueryExpression target, Path alias) { return queryMixin.rightJoin(target, alias); diff --git a/querydsl-sql/src/main/java/com/mysema/query/sql/AbstractSQLSubQuery.java b/querydsl-sql/src/main/java/com/mysema/query/sql/AbstractSQLSubQuery.java index 82f0ccede5..cc33952270 100644 --- a/querydsl-sql/src/main/java/com/mysema/query/sql/AbstractSQLSubQuery.java +++ b/querydsl-sql/src/main/java/com/mysema/query/sql/AbstractSQLSubQuery.java @@ -11,10 +11,9 @@ import com.mysema.query.JoinExpression; import com.mysema.query.JoinFlag; import com.mysema.query.QueryFlag; -import com.mysema.query.QueryMetadata; import com.mysema.query.QueryFlag.Position; +import com.mysema.query.QueryMetadata; import com.mysema.query.support.DetachableQuery; -import com.mysema.query.support.QueryMixin; import com.mysema.query.types.Expression; import com.mysema.query.types.ExpressionUtils; import com.mysema.query.types.Path; @@ -30,13 +29,16 @@ */ public class AbstractSQLSubQuery> extends DetachableQuery { + protected final SQLQueryMixin queryMixin; + public AbstractSQLSubQuery() { this(new DefaultQueryMetadata(false)); } @SuppressWarnings("unchecked") public AbstractSQLSubQuery(QueryMetadata metadata) { - super(new QueryMixin(metadata)); + super(new SQLQueryMixin(metadata)); + this.queryMixin = (SQLQueryMixin)super.queryMixin; this.queryMixin.setSelf((Q)this); } @@ -107,50 +109,66 @@ public Q from(Expression... args) { public Q from(SubQueryExpression subQuery, Path alias) { return queryMixin.from(ExpressionUtils.as((Expression)subQuery, alias)); } - - public Q fullJoin(ForeignKey key, RelationalPath entity) { - return queryMixin.fullJoin(entity).on(key.on(entity)); - } public Q fullJoin(RelationalPath target) { return queryMixin.fullJoin(target); } - - public Q fullJoin(SubQueryExpression target, Path alias) { + + public Q fullJoin(RelationalFunctionCall target, Path alias) { return queryMixin.fullJoin(target, alias); } + + public Q fullJoin(ForeignKey key, RelationalPath entity) { + return queryMixin.fullJoin(entity).on(key.on(entity)); + } - public Q innerJoin(ForeignKey key, RelationalPath entity) { - return queryMixin.innerJoin(entity).on(key.on(entity)); + public Q fullJoin(SubQueryExpression target, Path alias) { + return queryMixin.fullJoin(target, alias); } public Q innerJoin(RelationalPath target) { return queryMixin.innerJoin(target); } - - public Q innerJoin(SubQueryExpression target, Path alias) { + + public Q innerJoin(RelationalFunctionCall target, Path alias) { return queryMixin.innerJoin(target, alias); } - public Q join(ForeignKey key, RelationalPath entity) { - return queryMixin.join(entity).on(key.on(entity)); + public Q innerJoin(ForeignKey key, RelationalPath entity) { + return queryMixin.innerJoin(entity).on(key.on(entity)); + } + + public Q innerJoin(SubQueryExpression target, Path alias) { + return queryMixin.innerJoin(target, alias); } public Q join(RelationalPath target) { return queryMixin.join(target); } - - public Q join(SubQueryExpression target, Path alias) { + + public Q join(RelationalFunctionCall target, Path alias) { return queryMixin.join(target, alias); } - - public Q leftJoin(ForeignKey key, RelationalPath entity) { - return queryMixin.leftJoin(entity).on(key.on(entity)); + + public Q join(ForeignKey key, RelationalPath entity) { + return queryMixin.join(entity).on(key.on(entity)); + } + + public Q join(SubQueryExpression target, Path alias) { + return queryMixin.join(target, alias); } public Q leftJoin(RelationalPath target) { return queryMixin.leftJoin(target); } + + public Q leftJoin(RelationalFunctionCall target, Path alias) { + return queryMixin.leftJoin(target, alias); + } + + public Q leftJoin(ForeignKey key, RelationalPath entity) { + return queryMixin.leftJoin(entity).on(key.on(entity)); + } public Q leftJoin(SubQueryExpression target, Path alias) { return queryMixin.leftJoin(target, alias); @@ -160,13 +178,17 @@ public Q on(Predicate... conditions) { return queryMixin.on(conditions); } - public Q rightJoin(ForeignKey key, RelationalPath entity) { - return queryMixin.rightJoin(entity).on(key.on(entity)); - } - public Q rightJoin(RelationalPath target) { return queryMixin.rightJoin(target); } + + public Q rightJoin(RelationalFunctionCall target, Path alias) { + return queryMixin.fullJoin(target, alias); + } + + public Q rightJoin(ForeignKey key, RelationalPath entity) { + return queryMixin.rightJoin(entity).on(key.on(entity)); + } public Q rightJoin(SubQueryExpression target, Path alias) { return queryMixin.rightJoin(target, alias); diff --git a/querydsl-sql/src/main/java/com/mysema/query/sql/MetaDataExporter.java b/querydsl-sql/src/main/java/com/mysema/query/sql/MetaDataExporter.java index 39e437a5a6..da2b275f86 100644 --- a/querydsl-sql/src/main/java/com/mysema/query/sql/MetaDataExporter.java +++ b/querydsl-sql/src/main/java/com/mysema/query/sql/MetaDataExporter.java @@ -6,14 +6,8 @@ package com.mysema.query.sql; import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; import java.io.IOException; -import java.io.OutputStreamWriter; import java.io.StringWriter; -import java.io.UnsupportedEncodingException; -import java.io.Writer; import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.SQLException; @@ -25,7 +19,6 @@ import javax.annotation.Nullable; import org.apache.commons.io.FileUtils; -import org.apache.commons.io.IOUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/querydsl-sql/src/main/java/com/mysema/query/sql/MetaDataSerializer.java b/querydsl-sql/src/main/java/com/mysema/query/sql/MetaDataSerializer.java index a006ab8209..d96022a028 100644 --- a/querydsl-sql/src/main/java/com/mysema/query/sql/MetaDataSerializer.java +++ b/querydsl-sql/src/main/java/com/mysema/query/sql/MetaDataSerializer.java @@ -6,7 +6,6 @@ package com.mysema.query.sql; import static com.mysema.codegen.Symbols.NEW; -import static com.mysema.codegen.Symbols.UNCHECKED; import java.io.IOException; import java.lang.annotation.Annotation; @@ -31,7 +30,6 @@ import com.mysema.query.sql.support.InverseForeignKeyData; import com.mysema.query.sql.support.KeyData; import com.mysema.query.sql.support.PrimaryKeyData; -import com.mysema.query.types.Path; /** * MetaDataSerializer defines the Query type serialization logic for MetaDataExporter. @@ -63,17 +61,14 @@ public MetaDataSerializer( } @Override - @SuppressWarnings(UNCHECKED) protected void introClassHeader(CodeWriter writer, EntityType model) throws IOException { Type queryType = typeMappings.getPathType(model, model, true); - TypeCategory category = model.getOriginalCategory(); - Class pathType = RelationalPathBase.class; - + TypeCategory category = model.getOriginalCategory(); for (Annotation annotation : model.getAnnotations()) { writer.annotation(annotation); } - writer.beginClass(queryType, new ClassType(category, pathType, model)); + writer.beginClass(queryType, new ClassType(category, RelationalPathBase.class, model)); writer.privateStaticFinal(Types.LONG_P, "serialVersionUID", String.valueOf(model.hashCode())); } diff --git a/querydsl-sql/src/main/java/com/mysema/query/sql/RelationalFunctionCall.java b/querydsl-sql/src/main/java/com/mysema/query/sql/RelationalFunctionCall.java new file mode 100644 index 0000000000..52dbe1c7f1 --- /dev/null +++ b/querydsl-sql/src/main/java/com/mysema/query/sql/RelationalFunctionCall.java @@ -0,0 +1,85 @@ +package com.mysema.query.sql; + +import java.util.Arrays; +import java.util.List; + +import com.mysema.commons.lang.Assert; +import com.mysema.query.types.Expression; +import com.mysema.query.types.ExpressionBase; +import com.mysema.query.types.Template; +import com.mysema.query.types.TemplateExpression; +import com.mysema.query.types.TemplateFactory; +import com.mysema.query.types.Visitor; + +/** + * Represents a table valued function call + * + * @author tiwe + * + * @param + */ +public class RelationalFunctionCall extends ExpressionBase implements TemplateExpression { + + private static final long serialVersionUID = 256739044928186923L; + + private final List> args; + + private final Template template; + + /** + * Create a new TableValuedFunctionCall with the given template in String form and template arguments + * + * @param type + * @param template + * @param args + * @return + */ + public static RelationalFunctionCall create(Class type, String template, Expression... args) { + return new RelationalFunctionCall(type, template, args); + } + + public RelationalFunctionCall(Class type, String template, Expression... args) { + super(type); + this.args = Arrays.asList(Assert.notNull(args,"args")); + this.template = TemplateFactory.DEFAULT.create(Assert.notNull(template,"template")); + } + + @Override + public Expression getArg(int index) { + return getArgs().get(index); + } + + @Override + public List> getArgs() { + return args; + } + + @Override + public Template getTemplate() { + return template; + } + + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } else if (o instanceof TemplateExpression) { + TemplateExpression c = (TemplateExpression)o; + return c.getTemplate().equals(template) + && c.getType().equals(type); + } else { + return false; + } + } + + @Override + public int hashCode(){ + return getType().hashCode(); + } + + @Override + public R accept(Visitor v, C context) { + return v.visit(this, context); + } + +} diff --git a/querydsl-sql/src/main/java/com/mysema/query/sql/SQLCommonQuery.java b/querydsl-sql/src/main/java/com/mysema/query/sql/SQLCommonQuery.java index 6efe39c320..1c46280bce 100644 --- a/querydsl-sql/src/main/java/com/mysema/query/sql/SQLCommonQuery.java +++ b/querydsl-sql/src/main/java/com/mysema/query/sql/SQLCommonQuery.java @@ -81,22 +81,30 @@ public interface SQLCommonQuery> extends Query { * @return */ Q from(SubQueryExpression subQuery, Path alias); - + /** * Adds a full join to the given target * * @param o * @return */ - Q fullJoin(ForeignKey key, RelationalPath entity); - + Q fullJoin(RelationalPath o); + /** * Adds a full join to the given target * * @param o * @return */ - Q fullJoin(RelationalPath o); + Q fullJoin(RelationalFunctionCall o, Path alias); + + /** + * Adds a full join to the given target + * + * @param o + * @return + */ + Q fullJoin(ForeignKey key, RelationalPath entity); /** * Adds a full join to the given target @@ -105,14 +113,22 @@ public interface SQLCommonQuery> extends Query { * @return */ Q fullJoin(SubQueryExpression o, Path alias); - + /** * Adds an inner join to the given target * * @param o * @return */ - Q innerJoin(ForeignKey foreign, RelationalPath entity); + Q innerJoin(RelationalPath o); + + /** + * Adds a full join to the given target + * + * @param o + * @return + */ + Q innerJoin(RelationalFunctionCall o, Path alias); /** * Adds an inner join to the given target @@ -120,7 +136,7 @@ public interface SQLCommonQuery> extends Query { * @param o * @return */ - Q innerJoin(RelationalPath o); + Q innerJoin(ForeignKey foreign, RelationalPath entity); /** * Adds an inner join to the given target @@ -136,15 +152,23 @@ public interface SQLCommonQuery> extends Query { * @param o * @return */ - Q join(ForeignKey foreign, RelationalPath entity); - + Q join(RelationalPath o); + + /** + * Adds a full join to the given target + * + * @param o + * @return + */ + Q join(RelationalFunctionCall o, Path alias); + /** * Adds a join to the given target * * @param o * @return */ - Q join(RelationalPath o); + Q join(ForeignKey foreign, RelationalPath entity); /** * Adds a join to the given target @@ -153,14 +177,22 @@ public interface SQLCommonQuery> extends Query { * @return */ Q join(SubQueryExpression o, Path alias); - + /** * Adds a left join to the given target * * @param o * @return */ - Q leftJoin(ForeignKey foreign, RelationalPath entity); + Q leftJoin(RelationalPath o); + + /** + * Adds a full join to the given target + * + * @param o + * @return + */ + Q leftJoin(RelationalFunctionCall o, Path alias); /** * Adds a left join to the given target @@ -168,7 +200,7 @@ public interface SQLCommonQuery> extends Query { * @param o * @return */ - Q leftJoin(RelationalPath o); + Q leftJoin(ForeignKey foreign, RelationalPath entity); /** * Adds a left join to the given target @@ -185,22 +217,30 @@ public interface SQLCommonQuery> extends Query { * @return */ Q on(Predicate... conditions); - + /** * Adds a right join to the given target * * @param o * @return */ - Q rightJoin(ForeignKey foreign, RelationalPath entity); + Q rightJoin(RelationalPath o); + /** + * Adds a full join to the given target + * + * @param o + * @return + */ + Q rightJoin(RelationalFunctionCall o, Path alias); + /** * Adds a right join to the given target * * @param o * @return */ - Q rightJoin(RelationalPath o); + Q rightJoin(ForeignKey foreign, RelationalPath entity); /** * Adds a right join to the given target diff --git a/querydsl-sql/src/main/java/com/mysema/query/sql/SQLQueryMixin.java b/querydsl-sql/src/main/java/com/mysema/query/sql/SQLQueryMixin.java new file mode 100644 index 0000000000..dbbe5804e3 --- /dev/null +++ b/querydsl-sql/src/main/java/com/mysema/query/sql/SQLQueryMixin.java @@ -0,0 +1,51 @@ +package com.mysema.query.sql; + +import com.mysema.query.JoinType; +import com.mysema.query.QueryMetadata; +import com.mysema.query.support.QueryMixin; +import com.mysema.query.types.Path; + +/** + * @author tiwe + * + * @param + */ +public class SQLQueryMixin extends QueryMixin { + + public SQLQueryMixin() {} + + public SQLQueryMixin(QueryMetadata metadata) { + super(metadata); + } + + public SQLQueryMixin(T self, QueryMetadata metadata) { + super(self, metadata); + } + + public

T join(RelationalFunctionCall

target, Path

alias) { + getMetadata().addJoin(JoinType.JOIN, createAlias(target, alias)); + return getSelf(); + } + + public

T innerJoin(RelationalFunctionCall

target, Path

alias) { + getMetadata().addJoin(JoinType.INNERJOIN, createAlias(target, alias)); + return getSelf(); + } + + public

T leftJoin(RelationalFunctionCall

target, Path

alias) { + getMetadata().addJoin(JoinType.LEFTJOIN, createAlias(target, alias)); + return getSelf(); + } + + public

T rightJoin(RelationalFunctionCall

target, Path

alias) { + getMetadata().addJoin(JoinType.RIGHTJOIN, createAlias(target, alias)); + return getSelf(); + } + + public

T fullJoin(RelationalFunctionCall

target, Path

alias) { + getMetadata().addJoin(JoinType.FULLJOIN, createAlias(target, alias)); + return getSelf(); + } + + +} diff --git a/querydsl-sql/src/test/java/com/mysema/query/SelectBaseTest.java b/querydsl-sql/src/test/java/com/mysema/query/SelectBaseTest.java index 0db5810aa6..0178618cf6 100644 --- a/querydsl-sql/src/test/java/com/mysema/query/SelectBaseTest.java +++ b/querydsl-sql/src/test/java/com/mysema/query/SelectBaseTest.java @@ -582,10 +582,9 @@ public void Single_Column(){ } - @SuppressWarnings("unchecked") @Test public void Single_Column_via_Object_type(){ - for (Object s : query().from(survey).list(new PathImpl(Object.class, survey.name.getMetadata()))){ + for (Object s : query().from(survey).list(new PathImpl(Object.class, survey.name.getMetadata()))){ assertEquals(String.class, s.getClass()); } } @@ -632,6 +631,11 @@ public void StringFunctions2() throws SQLException { } } + @Test + public void SubQuery_Alias() { + query().from(sq().from(employee).list(employee.all()).as(employee2)).list(employee2.all()); + } + @Test public void SubQuery_with_Alias(){ List ids1 = query().from(employee).list(employee.id); diff --git a/querydsl-sql/src/test/java/com/mysema/query/sql/MetaDataExporterTest.java b/querydsl-sql/src/test/java/com/mysema/query/sql/MetaDataExporterTest.java index d11897a445..ed7bc43d36 100644 --- a/querydsl-sql/src/test/java/com/mysema/query/sql/MetaDataExporterTest.java +++ b/querydsl-sql/src/test/java/com/mysema/query/sql/MetaDataExporterTest.java @@ -5,7 +5,7 @@ */ package com.mysema.query.sql; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.io.File; diff --git a/querydsl-sql/src/test/java/com/mysema/query/sql/SQLSerializerTest.java b/querydsl-sql/src/test/java/com/mysema/query/sql/SQLSerializerTest.java index 542e49b807..2726ef9b0d 100644 --- a/querydsl-sql/src/test/java/com/mysema/query/sql/SQLSerializerTest.java +++ b/querydsl-sql/src/test/java/com/mysema/query/sql/SQLSerializerTest.java @@ -12,7 +12,9 @@ import org.junit.Test; import com.mysema.query.BooleanBuilder; +import com.mysema.query.SelectBaseTest.Survey; import com.mysema.query.sql.domain.QSurvey; +import com.mysema.query.support.Expressions; public class SQLSerializerTest { @@ -25,6 +27,24 @@ public void StartsWith(){ assertEquals(Arrays.asList("X%"), serializer.getConstants()); } + @Test + public void From_Function() { + SQLQuery query = new SQLQueryImpl(SQLTemplates.DEFAULT); + QSurvey survey = QSurvey.survey; + query.from(Expressions.template(Survey.class, "functionCall()")).join(survey); + query.where(survey.name.isNotNull()); + assertEquals("from functionCall()\njoin SURVEY SURVEY\nwhere SURVEY.NAME is not null", query.toString()); + } + + @Test + public void Join_To_Function_With_Alias() { + SQLQuery query = new SQLQueryImpl(SQLTemplates.DEFAULT); + QSurvey survey = QSurvey.survey; + query.from(survey).join(RelationalFunctionCall.create(Survey.class, "functionCall()"), Expressions.path(Survey.class, "fc")); + query.where(survey.name.isNotNull()); + assertEquals("from SURVEY SURVEY\njoin functionCall() as fc\nwhere SURVEY.NAME is not null", query.toString()); + } + @Test public void Boolean(){ QSurvey s = new QSurvey("s"); diff --git a/querydsl-sql/src/test/java/com/mysema/query/sql/mysql/MySQLQueryFactoryTest.java b/querydsl-sql/src/test/java/com/mysema/query/sql/mysql/MySQLQueryFactoryTest.java index 0a1819a154..cf847fd551 100644 --- a/querydsl-sql/src/test/java/com/mysema/query/sql/mysql/MySQLQueryFactoryTest.java +++ b/querydsl-sql/src/test/java/com/mysema/query/sql/mysql/MySQLQueryFactoryTest.java @@ -1,6 +1,6 @@ package com.mysema.query.sql.mysql; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import java.sql.Connection; diff --git a/querydsl-sql/src/test/java/com/mysema/query/sql/support/TypeTest.java b/querydsl-sql/src/test/java/com/mysema/query/sql/support/TypeTest.java index 01f0cbb01d..8649fb85f5 100644 --- a/querydsl-sql/src/test/java/com/mysema/query/sql/support/TypeTest.java +++ b/querydsl-sql/src/test/java/com/mysema/query/sql/support/TypeTest.java @@ -84,7 +84,7 @@ public Object invoke(Object proxy, Method method, Object[] args) throws Throwabl @SuppressWarnings("unchecked") @Test public void test() throws MalformedURLException, SQLException{ - List valueAndType = new ArrayList(); + List> valueAndType = new ArrayList>(); valueAndType.add(Pair.of(new BigDecimal("1"), new BigDecimalType())); valueAndType.add(Pair.of(new Boolean(true), new BooleanType())); valueAndType.add(Pair.of(new Byte((byte)1), new ByteType())); @@ -108,8 +108,8 @@ public void test() throws MalformedURLException, SQLException{ valueAndType.add(Pair.of(new LocalDate(), new LocalDateType())); valueAndType.add(Pair.of(new LocalTime(), new LocalTimeType())); - valueAndType.add(Pair.of(Gender.MALE, new EnumByNameType(Gender.class))); - valueAndType.add(Pair.of(Gender.MALE, new EnumByOrdinalType(Gender.class))); + valueAndType.add(Pair.of(Gender.MALE, new EnumByNameType(Gender.class))); + valueAndType.add(Pair.of(Gender.MALE, new EnumByOrdinalType(Gender.class))); valueAndType.add(Pair.of(EasyMock.createNiceMock(Blob.class), new BlobType())); valueAndType.add(Pair.of(EasyMock.createNiceMock(Clob.class), new ClobType())); diff --git a/querydsl-sql/src/test/resources/postgres.run b/querydsl-sql/src/test/resources/postgres.run new file mode 100644 index 0000000000..e69de29bb2