/*
* Copyright 2015, The Querydsl Team (http://www.querydsl.com/team)
*
* 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
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.querydsl.core;
import java.util.*;
import com.google.common.collect.ImmutableList;
import com.querydsl.core.types.CollectionExpression;
import com.querydsl.core.types.MapExpression;
import com.querydsl.core.types.Path;
import com.querydsl.core.types.Predicate;
import com.querydsl.core.types.dsl.*;
/**
* @author tiwe
*
*/
public class FilterFactory {
private final ProjectionsFactory projections;
private final Module module;
private final Target target;
public FilterFactory(ProjectionsFactory projections, Module module, Target target) {
this.projections = projections;
this.module = module;
this.target = target;
}
public Collection<Predicate> booleanFilters(BooleanExpression expr, BooleanExpression other) {
HashSet<Predicate> rv = new HashSet<Predicate>();
rv.add(expr.and(other));
rv.add(expr.or(other));
rv.add(expr.not().and(other.not()));
rv.add(expr.not());
rv.add(other.not());
return ImmutableList.copyOf(rv);
}
public <A> Collection<Predicate> collection(CollectionExpressionBase<?,A> expr,
CollectionExpression<?,A> other, A knownElement) {
HashSet<Predicate> rv = new HashSet<Predicate>();
rv.add(expr.contains(knownElement));
rv.add(expr.isEmpty());
rv.add(expr.isNotEmpty());
if (!module.equals(Module.RDFBEAN)) {
rv.add(expr.size().gt(0));
}
return ImmutableList.copyOf(rv);
}
public <A> Collection<Predicate> array(ArrayExpression<A[], A> expr, ArrayExpression<A[], A> other,
A knownElement) {
HashSet<Predicate> rv = new HashSet<Predicate>();
if (!module.equals(Module.RDFBEAN)) {
rv.add(expr.size().gt(0));
}
rv.add(expr.get(0).eq(knownElement));
return ImmutableList.copyOf(rv);
}
private <A extends Comparable<A>> Collection<Predicate> comparable(ComparableExpression<A> expr,
ComparableExpression<A> other, A knownValue) {
List<Predicate> rv = new ArrayList<Predicate>();
rv.addAll(exprFilters(expr, other, knownValue));
rv.add(expr.gt(other));
rv.add(expr.gt(knownValue));
rv.add(expr.goe(other));
rv.add(expr.goe(knownValue));
rv.add(expr.lt(other));
rv.add(expr.lt(knownValue));
rv.add(expr.loe(other));
rv.add(expr.loe(knownValue));
// rv.add(expr.in(IntervalImpl.create(knownValue, null)));
// rv.add(expr.in(IntervalImpl.create(null, knownValue)));
return ImmutableList.copyOf(rv);
}
private <A extends Comparable<A>> Collection<Predicate> dateOrTime(TemporalExpression<A> expr,
TemporalExpression<A> other, A knownValue) {
List<Predicate> rv = new ArrayList<Predicate>();
rv.add(expr.after(other));
rv.add(expr.after(knownValue));
rv.add(expr.before(other));
rv.add(expr.before(knownValue));
return ImmutableList.copyOf(rv);
}
@SuppressWarnings("unchecked")
public <A extends Comparable> Collection<Predicate> date(DateExpression<A> expr,
DateExpression<A> other, A knownValue) {
List<Predicate> rv = new ArrayList<Predicate>();
rv.addAll(comparable(expr, other, knownValue));
rv.addAll(dateOrTime(expr, other, knownValue));
rv.add(expr.dayOfMonth().eq(other.dayOfMonth()));
rv.add(expr.month().eq(other.month()));
rv.add(expr.year().eq(other.year()));
rv.add(expr.yearMonth().eq(other.yearMonth()));
if (module.equals(Module.SQL) || module.equals(Module.COLLECTIONS)) {
if (target != Target.DERBY) {
rv.add(expr.yearWeek().eq(other.yearWeek()));
}
}
return ImmutableList.copyOf(rv);
}
@SuppressWarnings("unchecked")
public <A extends Comparable> Collection<Predicate> dateTime(DateTimeExpression<A> expr,
DateTimeExpression<A> other, A knownValue) {
List<Predicate> rv = new ArrayList<Predicate>();
rv.addAll(comparable(expr, other, knownValue));
rv.addAll(dateOrTime(expr, other, knownValue));
rv.add(expr.dayOfMonth().eq(1));
rv.add(expr.dayOfMonth().eq(other.dayOfMonth()));
rv.add(expr.month().eq(1));
rv.add(expr.month().eq(other.month()));
rv.add(expr.year().eq(2000));
rv.add(expr.year().eq(other.year()));
rv.add(expr.yearMonth().eq(other.yearMonth()));
if (module.equals(Module.SQL) || module.equals(Module.COLLECTIONS)) {
if (target != Target.DERBY) {
rv.add(expr.yearWeek().eq(other.yearWeek()));
}
}
rv.add(expr.hour().eq(1));
rv.add(expr.hour().eq(other.hour()));
rv.add(expr.minute().eq(1));
rv.add(expr.minute().eq(other.minute()));
rv.add(expr.second().eq(1));
rv.add(expr.second().eq(other.second()));
return ImmutableList.copyOf(rv);
}
private <A> Collection<BooleanExpression> exprFilters(SimpleExpression<A> expr,
SimpleExpression<A> other, A knownValue) {
HashSet<BooleanExpression> rv = new HashSet<BooleanExpression>();
rv.add(expr.eq(other));
rv.add(expr.eq(knownValue));
rv.add(expr.ne(other));
rv.add(expr.ne(knownValue));
return ImmutableList.copyOf(rv);
}
public <A, Q extends SimpleExpression<A>> Collection<Predicate> list(ListPath<A, Q> expr,
ListExpression<A, Q> other, A knownElement) {
List<Predicate> rv = new ArrayList<Predicate>();
rv.addAll(collection(expr, other, knownElement));
rv.add(expr.get(0).eq(knownElement));
return ImmutableList.copyOf(rv);
}
public <K,V> Collection<Predicate> map(MapExpressionBase<K,V,?> expr,
MapExpression<K,V> other, K knownKey, V knownValue) {
HashSet<Predicate> rv = new HashSet<Predicate>();
rv.add(expr.containsKey(knownKey));
rv.add(expr.containsValue(knownValue));
rv.add(expr.get(knownKey).eq(knownValue));
rv.add(expr.get(knownKey).ne(knownValue));
rv.add(expr.isEmpty());
rv.add(expr.isNotEmpty());
if (!module.equals(Module.RDFBEAN)) {
rv.add(expr.size().gt(0));
}
return ImmutableList.copyOf(rv);
}
@SuppressWarnings("unchecked")
public <A extends Number & Comparable<A>> Collection<Predicate> numeric(NumberExpression<A> expr,
NumberExpression<A> other, A knownValue) {
List<Predicate> rv = new ArrayList<Predicate>();
for (NumberExpression<?> num : projections.numeric(expr, other, knownValue, true)) {
rv.add(num.lt(expr));
}
rv.add(expr.ne(other));
rv.add(expr.ne(knownValue));
rv.add(expr.goe(other));
rv.add(expr.goe(knownValue));
rv.add(expr.gt(other));
rv.add(expr.gt(knownValue));
rv.add(expr.loe(other));
rv.add(expr.loe(knownValue));
rv.add(expr.lt(other));
rv.add(expr.lt(knownValue));
rv.add(expr.in(1,2,3));
rv.add(expr.in(1L,2L,3L));
if (expr.getType().equals(Integer.class)) {
NumberExpression<Integer> eint = (NumberExpression) expr;
rv.add(eint.between(1, 2));
rv.add(eint.notBetween(1, 2));
rv.add(eint.mod(5).eq(0));
} else if (expr.getType().equals(Double.class)) {
NumberExpression<Double> edouble = (NumberExpression) expr;
rv.add(edouble.between(1.0, 2.0));
rv.add(edouble.notBetween(1.0, 2.0));
} else if (expr.getType().equals(Long.class)) {
NumberExpression<Long> elong = (NumberExpression) expr;
rv.add(elong.mod(5L).eq(0L));
}
// rv.add(expr.in(IntervalImpl.create(0, 100)));
return ImmutableList.copyOf(rv);
}
public <A> Collection<Predicate> pathFilters(SimpleExpression<A> expr,
SimpleExpression<A> other, A knownValue) {
return Arrays.<Predicate>asList(
expr.isNull(),
expr.isNotNull()
);
}
@SuppressWarnings("unchecked")
public Collection<Predicate> string(StringExpression expr, StringExpression other,
String knownValue) {
List<Predicate> rv = new ArrayList<Predicate>();
if (expr instanceof Path && other instanceof Path) {
rv.addAll(pathFilters(expr, other, knownValue));
}
rv.addAll(comparable(expr, other, knownValue));
for (SimpleExpression<String> eq : projections.string(expr, other, knownValue)) {
rv.add(eq.eq(other));
}
rv.add(expr.between("A", "Z"));
rv.add(expr.charAt(0).eq(knownValue.charAt(0)));
rv.add(expr.notBetween("A", "Z"));
rv.add(expr.contains(other));
rv.add(expr.contains(knownValue.substring(0,1)));
rv.add(expr.contains(knownValue.substring(1,2)));
rv.add(expr.containsIgnoreCase(other));
rv.add(expr.containsIgnoreCase(knownValue.substring(0,1)));
rv.add(expr.containsIgnoreCase(knownValue.substring(1,2)));
rv.add(expr.endsWith(other));
rv.add(expr.endsWith(knownValue.substring(1)));
rv.add(expr.endsWith(knownValue.substring(2)));
rv.add(expr.equalsIgnoreCase(other));
rv.add(expr.equalsIgnoreCase(knownValue));
rv.add(expr.in(Arrays.asList(knownValue)));
rv.add(expr.indexOf(other).gt(0));
rv.add(expr.indexOf("X", 1).gt(0));
rv.add(expr.indexOf(knownValue).gt(0));
rv.add(expr.locate(other).gt(1));
if (!target.equals(Target.FIREBIRD)) { // FIXME
rv.add(expr.locate("X", 2).gt(1));
}
rv.add(expr.locate(knownValue).gt(1));
// if (!module.equals(Module.HQL) && !module.equals(Module.JDOQL) && !module.equals(Module.SQL)) {
// rv.add(expr.lastIndexOf(other).gt(0));
// rv.add(expr.lastIndexOf(knownValue).gt(0));
// }
rv.add(expr.in("A","B","C"));
rv.add(expr.isEmpty());
rv.add(expr.isNotEmpty());
rv.add(expr.length().gt(0));
rv.add(expr.like(knownValue.substring(0,1) + "%"));
rv.add(expr.like("%" + knownValue.substring(1)));
rv.add(expr.like("%" + knownValue.substring(1,2) + "%"));
rv.add(expr.like(knownValue.substring(0,1) + "%", '!'));
rv.add(expr.like("%" + knownValue.substring(1), '!'));
rv.add(expr.like("%" + knownValue.substring(1,2) + "%", '!'));
rv.add(expr.likeIgnoreCase(knownValue.substring(0, 1) + "%"));
rv.add(expr.likeIgnoreCase("%" + knownValue.substring(1)));
rv.add(expr.likeIgnoreCase("%" + knownValue.substring(1, 2) + "%"));
rv.add(expr.likeIgnoreCase(knownValue.substring(0, 1) + "%", '!'));
rv.add(expr.likeIgnoreCase("%" + knownValue.substring(1), '!'));
rv.add(expr.likeIgnoreCase("%" + knownValue.substring(1, 2) + "%", '!'));
rv.add(expr.notLike(knownValue.substring(0,1) + "%"));
rv.add(expr.notLike("%" + knownValue.substring(1)));
rv.add(expr.notLike("%" + knownValue.substring(1,2) + "%"));
if (!target.equals(Target.DERBY)
&& !target.equals(Target.DB2)
&& !target.equals(Target.FIREBIRD)
&& !target.equals(Target.HSQLDB)
&& !target.equals(Target.H2)
&& !target.equals(Target.SQLITE)
&& !target.equals(Target.SQLSERVER)) {
rv.add(expr.matches(knownValue.substring(0,1) + ".*"));
rv.add(expr.matches(".*" + knownValue.substring(1)));
rv.add(expr.matches(".*" + knownValue.substring(1,2) + ".*"));
}
rv.add(expr.notIn("A","B","C"));
rv.add(expr.notBetween("A", "Z"));
rv.add(expr.notBetween(other, other));
if (!target.equals(Target.DERBY) && !module.equals(Module.JDO)) {
// https://issues.apache.org/jira/browse/DERBY-4389
rv.add(new Coalesce<String>(String.class, expr, other).getValue().eq("xxx"));
}
// rv.add(expr.in(IntervalImpl.create("A", "Z")));
return ImmutableList.copyOf(rv);
}
@SuppressWarnings("unchecked")
public <A extends Comparable> Collection<Predicate> time(TimeExpression<A> expr,
TimeExpression<A> other, A knownValue) {
List<Predicate> rv = new ArrayList<Predicate>();
rv.addAll(comparable(expr, other, knownValue));
rv.addAll(dateOrTime(expr, other, knownValue));
rv.add(expr.hour().eq(other.hour()));
rv.add(expr.minute().eq(other.minute()));
rv.add(expr.second().eq(other.second()));
return ImmutableList.copyOf(rv);
}
}