/**
*
* Copyright (c) 2006-2017, Speedment, Inc. All Rights Reserved.
*
* 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.speedment.runtime.core.internal.manager.sql;
import com.speedment.runtime.core.db.FieldPredicateView;
import com.speedment.runtime.core.db.SqlPredicateFragment;
import com.speedment.runtime.field.Field;
import static com.speedment.runtime.field.internal.predicate.PredicateUtil.*;
import com.speedment.runtime.field.predicate.FieldPredicate;
import com.speedment.runtime.field.predicate.Inclusion;
import com.speedment.runtime.field.predicate.PredicateType;
import java.util.Collection;
import static java.util.Objects.requireNonNull;
import java.util.Set;
import java.util.function.Function;
import static java.util.stream.Collectors.joining;
/**
*
* @author Per Minborg
*/
public abstract class AbstractFieldPredicateView implements FieldPredicateView {
protected abstract SqlPredicateFragment equalIgnoreCaseHelper(String cn, FieldPredicate<?> model, boolean negated);
protected abstract SqlPredicateFragment startsWithHelper(String cn, FieldPredicate<?> model, boolean negated);
protected abstract SqlPredicateFragment startsWithIgnoreCaseHelper(String cn, FieldPredicate<?> model, boolean negated);
protected abstract SqlPredicateFragment endsWithHelper(String cn, FieldPredicate<?> model, boolean negated);
protected abstract SqlPredicateFragment endsWithIgnoreCaseHelper(String cn, FieldPredicate<?> model, boolean negated);
protected abstract SqlPredicateFragment containsHelper(String cn, FieldPredicate<?> model, boolean negated);
protected abstract SqlPredicateFragment containsIgnoreCaseHelper(String cn, FieldPredicate<?> model, boolean negated);
@Override
public <ENTITY> SqlPredicateFragment transform(
final Function<Field<ENTITY>, String> columnNamer,
final Function<Field<ENTITY>, Class<?>> columnDbTypeFunction,
final FieldPredicate<ENTITY> model
) {
return render(
requireNonNull(columnNamer),
requireNonNull(columnDbTypeFunction),
requireNonNull(model)
);
}
protected <ENTITY> SqlPredicateFragment render(
final Function<Field<ENTITY>, String> columnNamer,
final Function<Field<ENTITY>, Class<?>> columnDbTypeFunction,
final FieldPredicate<ENTITY> predicate
) {
final PredicateType pt = predicate.getEffectivePredicateType();
final Field<ENTITY> f = predicate.getField();
final String cn = columnNamer.apply(f);
switch (pt) {
// Constants
case ALWAYS_TRUE:
return alwaysTrue();
case ALWAYS_FALSE:
return alwaysFalse();
// Reference
case IS_NULL:
return isNull(cn);
case IS_NOT_NULL:
return isNotNull(cn);
// Comparable
case EQUAL: {
final Class<?> dbClass = columnDbTypeFunction.apply(f);
return String.class.equals(dbClass)
? equalString(cn, predicate)
: equal(cn, dbClass, predicate);
}
case NOT_EQUAL: {
final Class<?> dbClass = columnDbTypeFunction.apply(f);
return String.class.equals(dbClass)
? notEqualString(cn, predicate)
: notEqual(cn, dbClass, predicate);
}
case GREATER_THAN: {
final Class<?> dbClass = columnDbTypeFunction.apply(f);
return String.class.equals(dbClass)
? greaterThanString(cn, predicate)
: greaterThan(cn, dbClass, predicate);
}
case GREATER_OR_EQUAL: {
final Class<?> dbClass = columnDbTypeFunction.apply(f);
return String.class.equals(dbClass)
? greaterOrEqualString(cn, predicate)
: greaterOrEqual(cn, dbClass, predicate);
}
case LESS_THAN: {
final Class<?> dbClass = columnDbTypeFunction.apply(f);
return String.class.equals(dbClass)
? lessThanString(cn, predicate)
: lessThan(cn, dbClass, predicate);
}
case LESS_OR_EQUAL: {
final Class<?> dbClass = columnDbTypeFunction.apply(f);
return String.class.equals(dbClass)
? lessOrEqualString(cn, predicate)
: lessOrEqual(cn, dbClass, predicate);
}
case BETWEEN: {
final Class<?> dbClass = columnDbTypeFunction.apply(f);
return String.class.equals(dbClass)
? betweenString(cn, predicate)
: between(cn, dbClass, predicate);
}
case NOT_BETWEEN: {
final Class<?> dbClass = columnDbTypeFunction.apply(f);
return String.class.equals(dbClass)
? notBetweenString(cn, predicate)
: notBetween(cn, dbClass, predicate);
}
case IN: {
final Class<?> dbClass = columnDbTypeFunction.apply(f);
return String.class.equals(dbClass)
? inString(cn, predicate)
: in(cn, dbClass, predicate);
}
case NOT_IN: {
final Class<?> dbClass = columnDbTypeFunction.apply(f);
return String.class.equals(dbClass)
? notInString(cn, predicate)
: notIn(cn, dbClass, predicate);
}
// String
case EQUAL_IGNORE_CASE:
return equalIgnoreCase(cn, predicate);
case NOT_EQUAL_IGNORE_CASE:
return notEqualIgnoreCase(cn, predicate);
case STARTS_WITH:
return startsWith(cn, predicate);
case NOT_STARTS_WITH:
return notStartsWith(cn, predicate);
case STARTS_WITH_IGNORE_CASE:
return startsWithIgnoreCase(cn, predicate);
case NOT_STARTS_WITH_IGNORE_CASE:
return notStartsWithIgnoreCase(cn, predicate);
case ENDS_WITH:
return endsWith(cn, predicate);
case NOT_ENDS_WITH:
return notEndsWith(cn, predicate);
case ENDS_WITH_IGNORE_CASE:
return endsWithIgnoreCase(cn, predicate);
case NOT_ENDS_WITH_IGNORE_CASE:
return notEndsWithIgnoreCase(cn, predicate);
case CONTAINS:
return contains(cn, predicate);
case NOT_CONTAINS:
return notContains(cn, predicate);
case CONTAINS_IGNORE_CASE:
return containsIgnoreCase(cn, predicate);
case NOT_CONTAINS_IGNORE_CASE:
return notContainsIgnoreCase(cn, predicate);
case IS_EMPTY:
return isEmpty(cn);
case IS_NOT_EMPTY:
return isNotEmpty(cn);
default:
throw new UnsupportedOperationException(
"Unknown PredicateType " + pt.name() + ". Column name:" + predicate.getField().identifier().getColumnName()
);
}
}
protected SqlPredicateFragment alwaysTrue() {
return of("(TRUE)");
}
protected SqlPredicateFragment alwaysFalse() {
return of("(FALSE)");
}
protected SqlPredicateFragment isNull(String cn) {
return of("(" + cn + " IS NULL)");
}
protected SqlPredicateFragment isNotNull(String cn) {
return of("(" + cn + " IS NOT NULL)");
}
protected SqlPredicateFragment equal(String cn, Class<?> dbClass, FieldPredicate<?> model) {
return of("(" + cn + " = ?)").add(getFirstOperandAsRaw(model));
}
protected SqlPredicateFragment equalString(String cn, FieldPredicate<?> model) {
return equal(cn, String.class, model);
}
protected SqlPredicateFragment notEqual(String cn, Class<?> dbClass, FieldPredicate<?> model) {
return of("(NOT (" + cn + " = ?))").add(getFirstOperandAsRaw(model));
}
protected SqlPredicateFragment notEqualString(String cn, FieldPredicate<?> model) {
return notEqual(cn, String.class, model);
}
protected SqlPredicateFragment greaterThan(String cn, Class<?> dbClass, FieldPredicate<?> model) {
return of("(" + cn + " > ?)").add(getFirstOperandAsRaw(model));
}
protected SqlPredicateFragment greaterThanString(String cn, FieldPredicate<?> model) {
return greaterThan(cn, String.class, model);
}
protected SqlPredicateFragment greaterOrEqual(String cn, Class<?> dbClass, FieldPredicate<?> model) {
return of("(" + cn + " >= ?)").add(getFirstOperandAsRaw(model));
}
protected SqlPredicateFragment greaterOrEqualString(String cn, FieldPredicate<?> model) {
return greaterOrEqual(cn, String.class, model);
}
protected SqlPredicateFragment lessThan(String cn, Class<?> dbClass, FieldPredicate<?> model) {
return of("(" + cn + " < ?)").add(getFirstOperandAsRaw(model));
}
protected SqlPredicateFragment lessThanString(String cn, FieldPredicate<?> model) {
return lessThan(cn, String.class, model);
}
protected SqlPredicateFragment lessOrEqual(String cn, Class<?> dbClass, FieldPredicate<?> model) {
return of("(" + cn + " <= ?)").add(getFirstOperandAsRaw(model));
}
protected SqlPredicateFragment lessOrEqualString(String cn, FieldPredicate<?> model) {
return lessOrEqual(cn, String.class, model);
}
protected SqlPredicateFragment between(String cn, Class<?> dbClass, FieldPredicate<?> model) {
return betweenHelper(cn, dbClass, model, false);
}
protected SqlPredicateFragment betweenString(String cn, FieldPredicate<?> model) {
return between(cn, String.class, model);
}
protected SqlPredicateFragment notBetween(String cn, Class<?> dbClass, FieldPredicate<?> model) {
return betweenHelper(cn, dbClass, model, true);
}
protected SqlPredicateFragment notBetweenString(String cn, FieldPredicate<?> model) {
return notBetween(cn, String.class, model);
}
protected SqlPredicateFragment betweenHelper(String cn, Class<?> dbClass, FieldPredicate<?> model, boolean negated) {
final Inclusion inclusion = getInclusionOperand(model);
switch (inclusion) {
case START_EXCLUSIVE_END_EXCLUSIVE: {
return of("(" + cn + " > ? AND " + cn + " < ?)", negated).add(getFirstOperandAsRaw(model)).add(getSecondOperand(model));
}
case START_INCLUSIVE_END_EXCLUSIVE: {
return of("(" + cn + " >= ? AND " + cn + " < ?)", negated).add(getFirstOperandAsRaw(model)).add(getSecondOperand(model));
}
case START_EXCLUSIVE_END_INCLUSIVE: {
return of("(" + cn + " > ? AND " + cn + " <= ?)", negated).add(getFirstOperandAsRaw(model)).add(getSecondOperand(model));
}
case START_INCLUSIVE_END_INCLUSIVE: {
return of("(" + cn + " >= ? AND " + cn + " <= ?)", negated).add(getFirstOperandAsRaw(model)).add(getSecondOperand(model));
}
}
throw new IllegalArgumentException("Unknown Inclusion:" + inclusion);
}
protected SqlPredicateFragment in(String cn, Class<?> dbClass, FieldPredicate<?> model) {
return inHelper(cn, dbClass, model, false);
}
protected SqlPredicateFragment inString(String cn, FieldPredicate<?> model) {
return in(cn, String.class, model);
}
protected SqlPredicateFragment notIn(String cn, Class<?> dbClass, FieldPredicate<?> model) {
return inHelper(cn, dbClass, model, true);
}
protected SqlPredicateFragment notInString(String cn, FieldPredicate<?> model) {
return notIn(cn, String.class, model);
}
protected SqlPredicateFragment inHelper(String cn, Class<?> dbClass, FieldPredicate<?> model, boolean negated) {
final Set<?> set = getFirstOperandAsRawSet(model);
return of("(" + cn + " IN (" + set.stream().map($ -> "?").collect(joining(",")) + "))", negated).addAll(set);
}
/// String methods
protected SqlPredicateFragment equalIgnoreCase(String cn, FieldPredicate<?> model) {
return equalIgnoreCaseHelper(cn, model, false);
}
protected SqlPredicateFragment notEqualIgnoreCase(String cn, FieldPredicate<?> model) {
return equalIgnoreCaseHelper(cn, model, true);
}
protected SqlPredicateFragment startsWith(String cn, FieldPredicate<?> model) {
return startsWithHelper(cn, model, false);
}
protected SqlPredicateFragment notStartsWith(String cn, FieldPredicate<?> model) {
return startsWithHelper(cn, model, true);
}
protected SqlPredicateFragment startsWithIgnoreCase(String cn, FieldPredicate<?> model) {
return startsWithIgnoreCaseHelper(cn, model, false);
}
protected SqlPredicateFragment notStartsWithIgnoreCase(String cn, FieldPredicate<?> model) {
return startsWithIgnoreCaseHelper(cn, model, true);
}
protected SqlPredicateFragment endsWith(String cn, FieldPredicate<?> model) {
return endsWithHelper(cn, model, false);
}
protected SqlPredicateFragment notEndsWith(String cn, FieldPredicate<?> model) {
return endsWithHelper(cn, model, true);
}
protected SqlPredicateFragment endsWithIgnoreCase(String cn, FieldPredicate<?> model) {
return endsWithIgnoreCaseHelper(cn, model, false);
}
protected SqlPredicateFragment notEndsWithIgnoreCase(String cn, FieldPredicate<?> model) {
return endsWithIgnoreCaseHelper(cn, model, true);
}
protected SqlPredicateFragment contains(String cn, FieldPredicate<?> model) {
return containsHelper(cn, model, false);
}
protected SqlPredicateFragment notContains(String cn, FieldPredicate<?> model) {
return containsHelper(cn, model, true);
}
protected SqlPredicateFragment containsIgnoreCase(String cn, FieldPredicate<?> model) {
return containsIgnoreCaseHelper(cn, model, false);
}
protected SqlPredicateFragment notContainsIgnoreCase(String cn, FieldPredicate<?> model) {
return containsIgnoreCaseHelper(cn, model, true);
}
protected SqlPredicateFragment isEmpty(String cn) {
return of("(" + cn + " = '')");
}
protected SqlPredicateFragment isNotEmpty(String cn) {
return of("(" + cn + " <> '')");
}
public static SqlPredicateFragment of(String sql) {
return SqlPredicateFragment.of(sql);
}
public static SqlPredicateFragment of(String sql, Object object) {
return SqlPredicateFragment.of(sql, object);
}
public static SqlPredicateFragment of(String sql, Collection<Object> objects) {
return SqlPredicateFragment.of(sql, objects);
}
public static SqlPredicateFragment of(String sql, boolean negated) {
if (negated) {
return of("(NOT(" + sql + "))");
} else {
return of(sql);
}
}
public static SqlPredicateFragment of(String sql, Object object, boolean negated) {
if (negated) {
return of("(NOT(" + sql + "))", object);
} else {
return of(sql, object);
}
}
public static SqlPredicateFragment of(String sql, Collection<Object> objects, boolean negated) {
if (negated) {
return of("(NOT(" + sql + "))", objects);
} else {
return of(sql, objects);
}
}
}