diff --git a/querydsl-collections/src/main/java/com/mysema/query/collections/CollQueryFunctions.java b/querydsl-collections/src/main/java/com/mysema/query/collections/CollQueryFunctions.java index fd595004c..7282196f4 100644 --- a/querydsl-collections/src/main/java/com/mysema/query/collections/CollQueryFunctions.java +++ b/querydsl-collections/src/main/java/com/mysema/query/collections/CollQueryFunctions.java @@ -25,6 +25,7 @@ import java.util.Set; import javax.annotation.Nullable; +import com.google.common.base.Objects; import com.mysema.query.types.Expression; import com.mysema.query.types.Operator; import com.mysema.query.types.Ops; @@ -79,8 +80,22 @@ public final class CollQueryFunctions { private static final List nullList = Arrays.asList((Object)null); + public static boolean equals(Object o1, Object o2) { + return Objects.equal(o1, o2); + } + + public static > int compareTo(T c1, T c2) { + if (c1 == null) { + return c2 == null ? 0 : -1; + } else if (c2 == null) { + return 1; + } else { + return c1.compareTo(c2); + } + } + public static > boolean between(A a, A b, A c) { - return a.compareTo(b) >= 0 && a.compareTo(c) <= 0; + return compareTo(a, b) >= 0 && compareTo(a, c) <= 0; } public static double cot(double x) { diff --git a/querydsl-collections/src/main/java/com/mysema/query/collections/CollQueryMixin.java b/querydsl-collections/src/main/java/com/mysema/query/collections/CollQueryMixin.java index b0f8a7497..f52026f0e 100644 --- a/querydsl-collections/src/main/java/com/mysema/query/collections/CollQueryMixin.java +++ b/querydsl-collections/src/main/java/com/mysema/query/collections/CollQueryMixin.java @@ -1,6 +1,6 @@ /* * Copyright 2011, Mysema Ltd - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -24,13 +24,13 @@ import com.mysema.query.types.template.BooleanTemplate; /** * CollQueryMixin extends {@link QueryMixin} to provide normalization logic specific to this module - * + * * @author tiwe * * @param */ public class CollQueryMixin extends QueryMixin { - + private static final Predicate ANY = BooleanTemplate.create("any"); public CollQueryMixin() {} @@ -42,22 +42,22 @@ public class CollQueryMixin extends QueryMixin { public CollQueryMixin(T self, QueryMetadata metadata) { super(self, metadata); } - + @Override protected Predicate normalize(Predicate predicate, boolean where) { predicate = (Predicate)ExpressionUtils.extract(predicate); - if (predicate != null) { + if (predicate != null) { Context context = new Context(); Predicate transformed = (Predicate) predicate.accept(CollectionAnyVisitor.DEFAULT, context); for (int i = 0; i < context.paths.size(); i++) { - innerJoin( - (Path)context.paths.get(i).getMetadata().getParent(), + leftJoin( + (Path)context.paths.get(i).getMetadata().getParent(), (Path)context.replacements.get(i)); on(ANY); } - return transformed; + return transformed; } else { return predicate; } } -} +} diff --git a/querydsl-collections/src/main/java/com/mysema/query/collections/CollQueryTemplates.java b/querydsl-collections/src/main/java/com/mysema/query/collections/CollQueryTemplates.java index 2ae2bde78..c3315761b 100644 --- a/querydsl-collections/src/main/java/com/mysema/query/collections/CollQueryTemplates.java +++ b/querydsl-collections/src/main/java/com/mysema/query/collections/CollQueryTemplates.java @@ -29,16 +29,16 @@ public class CollQueryTemplates extends JavaTemplates { protected CollQueryTemplates() { String functions = CollQueryFunctions.class.getName(); - add(Ops.EQ, "{0}.equals({1})"); - add(Ops.NE, "!{0}.equals({1})"); + add(Ops.EQ, functions + ".equals({0}, {1})"); + add(Ops.NE, "!" + functions + ".equals({0}, {1})"); add(Ops.INSTANCE_OF, "{1}.isInstance({0})"); // Comparable - add(Ops.GT, "{0}.compareTo({1}) > 0"); - add(Ops.LT, "{0}.compareTo({1}) < 0"); - add(Ops.GOE, "{0}.compareTo({1}) >= 0"); - add(Ops.LOE, "{0}.compareTo({1}) <= 0"); - add(Ops.BETWEEN, functions + ".between({0},{1},{2})"); + add(Ops.GT, functions + ".compareTo({0}, {1}) > 0"); + add(Ops.LT, functions + ".compareTo({0}, {1}) < 0"); + add(Ops.GOE, functions + ".compareTo({0}, {1}) >= 0"); + add(Ops.LOE, functions + ".compareTo({0}, {1}) <= 0"); + add(Ops.BETWEEN, functions + ".between({0}, {1}, {2})"); add(Ops.STRING_CAST, "String.valueOf({0})"); // Number diff --git a/querydsl-collections/src/test/java/com/mysema/query/collections/Document.java b/querydsl-collections/src/test/java/com/mysema/query/collections/Document.java new file mode 100644 index 000000000..fc92b8dd9 --- /dev/null +++ b/querydsl-collections/src/test/java/com/mysema/query/collections/Document.java @@ -0,0 +1,31 @@ +package com.mysema.query.collections; + +import java.util.ArrayList; +import java.util.List; + +import com.mysema.query.annotations.QueryEntity; + +@QueryEntity +public class Document { + + private Long id; + + private List meshThesaurusTerms = new ArrayList(); + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public List getMeshThesaurusTerms() { + return meshThesaurusTerms; + } + + public void setMeshThesaurusTerms(List meshThesaurusTerms) { + this.meshThesaurusTerms = meshThesaurusTerms; + } + +} \ No newline at end of file diff --git a/querydsl-collections/src/test/java/com/mysema/query/collections/DocumentTest.java b/querydsl-collections/src/test/java/com/mysema/query/collections/DocumentTest.java new file mode 100644 index 000000000..cd85280c6 --- /dev/null +++ b/querydsl-collections/src/test/java/com/mysema/query/collections/DocumentTest.java @@ -0,0 +1,61 @@ +package com.mysema.query.collections; + +import static org.junit.Assert.assertTrue; + +import java.util.List; + +import org.junit.Before; +import org.junit.Test; + +import com.mysema.query.types.Predicate; + +public class DocumentTest { + + private Document doc1, doc2, doc3; + + private QDocument qDoc = QDocument.document; + + @Before + public void setUp() { + doc1 = new Document(); + doc1.setId(1L); + doc1.getMeshThesaurusTerms().add("x"); + + doc2 = new Document(); + doc2.setId(2L); + + doc3 = new Document(); + doc3.setId(3L); + } + + @Test + public void test1() { + Predicate crit = qDoc.id.eq(3L); + List expResult = CollQueryFactory.from(qDoc, doc1, doc2, doc3).where(crit).list(qDoc); + assertTrue(expResult.contains(doc3)); //ok + } + + @Test + public void test2() { + Predicate crit = qDoc.meshThesaurusTerms.any().eq("x"); + List expResult = CollQueryFactory.from(qDoc, doc1, doc2, doc3).where(crit).list(qDoc); + assertTrue(expResult.contains(doc1)); //ok + } + + @Test + public void test3() { + Predicate crit = qDoc.meshThesaurusTerms.any().eq("x").or(qDoc.id.eq(3L)); + List expResult = CollQueryFactory.from(qDoc, doc1, doc2, doc3).where(crit).list(qDoc); + assertTrue(expResult.contains(doc1)); + assertTrue(expResult.contains(doc3)); //fails, expResult contains only doc1, but should contain doc1 and doc3! + } + + @Test + public void test4() { + Predicate crit = qDoc.id.eq(3L).or(qDoc.meshThesaurusTerms.any().eq("x")); + List expResult = CollQueryFactory.from(qDoc, doc1, doc2, doc3).where(crit).list(qDoc); + assertTrue(expResult.contains(doc1)); + assertTrue(expResult.contains(doc3)); //fails, expResult contains only doc1, but should contain doc1 and doc3! + } + +}