/** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.camel.builder; import java.util.Arrays; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.camel.Exchange; import org.apache.camel.Expression; import org.apache.camel.Predicate; import org.apache.camel.util.ExpressionToPredicateAdapter; import org.apache.camel.util.ObjectHelper; import static org.apache.camel.util.ObjectHelper.notNull; /** * A helper class for working with predicates * * @version */ public final class PredicateBuilder { /** * Utility classes should not have a public constructor. */ private PredicateBuilder() { } /** * Converts the given expression into an {@link Predicate} */ public static Predicate toPredicate(final Expression expression) { return ExpressionToPredicateAdapter.toPredicate(expression); } /** * A helper method to return the logical not of the given predicate */ public static Predicate not(final Predicate predicate) { notNull(predicate, "predicate"); return new Predicate() { public boolean matches(Exchange exchange) { return !predicate.matches(exchange); } @Override public String toString() { return "not (" + predicate + ")"; } }; } /** * A helper method to combine multiple predicates by a logical AND */ public static Predicate and(final Predicate left, final Predicate right) { notNull(left, "left"); notNull(right, "right"); return new Predicate() { public boolean matches(Exchange exchange) { return left.matches(exchange) && right.matches(exchange); } @Override public String toString() { return "(" + left + ") and (" + right + ")"; } }; } /** * A helper method to combine two predicates by a logical OR. * If you want to combine multiple predicates see {@link #in(Predicate...)} */ public static Predicate or(final Predicate left, final Predicate right) { notNull(left, "left"); notNull(right, "right"); return new Predicate() { public boolean matches(Exchange exchange) { return left.matches(exchange) || right.matches(exchange); } @Override public String toString() { return "(" + left + ") or (" + right + ")"; } }; } /** * Concat the given predicates into a single predicate, which matches * if at least one predicates matches. * * @param predicates predicates * @return a single predicate containing all the predicates */ public static Predicate or(List<Predicate> predicates) { Predicate answer = null; for (Predicate predicate : predicates) { if (answer == null) { answer = predicate; } else { answer = or(answer, predicate); } } return answer; } /** * Concat the given predicates into a single predicate, which matches * if at least one predicates matches. * * @param predicates predicates * @return a single predicate containing all the predicates */ public static Predicate or(Predicate... predicates) { return or(Arrays.asList(predicates)); } /** * A helper method to return true if any of the predicates matches. */ public static Predicate in(final Predicate... predicates) { notNull(predicates, "predicates"); return new Predicate() { public boolean matches(Exchange exchange) { for (Predicate in : predicates) { if (in.matches(exchange)) { return true; } } return false; } @Override public String toString() { return "in (" + Arrays.asList(predicates) + ")"; } }; } /** * A helper method to return true if any of the predicates matches. */ public static Predicate in(List<Predicate> predicates) { return in(predicates.toArray(new Predicate[0])); } public static Predicate isEqualTo(final Expression left, final Expression right) { return new BinaryPredicateSupport(left, right) { protected boolean matches(Exchange exchange, Object leftValue, Object rightValue) { if (leftValue == null && rightValue == null) { // they are equal return true; } else if (leftValue == null || rightValue == null) { // only one of them is null so they are not equal return false; } return ObjectHelper.typeCoerceEquals(exchange.getContext().getTypeConverter(), leftValue, rightValue); } protected String getOperationText() { return "=="; } }; } public static Predicate isEqualToIgnoreCase(final Expression left, final Expression right) { return new BinaryPredicateSupport(left, right) { protected boolean matches(Exchange exchange, Object leftValue, Object rightValue) { if (leftValue == null && rightValue == null) { // they are equal return true; } else if (leftValue == null || rightValue == null) { // only one of them is null so they are not equal return false; } return ObjectHelper.typeCoerceEquals(exchange.getContext().getTypeConverter(), leftValue, rightValue, true); } protected String getOperationText() { return "=~"; } }; } public static Predicate isNotEqualTo(final Expression left, final Expression right) { return new BinaryPredicateSupport(left, right) { protected boolean matches(Exchange exchange, Object leftValue, Object rightValue) { if (leftValue == null && rightValue == null) { // they are equal return false; } else if (leftValue == null || rightValue == null) { // only one of them is null so they are not equal return true; } return ObjectHelper.typeCoerceNotEquals(exchange.getContext().getTypeConverter(), leftValue, rightValue); } protected String getOperationText() { return "!="; } }; } public static Predicate isLessThan(final Expression left, final Expression right) { return new BinaryPredicateSupport(left, right) { protected boolean matches(Exchange exchange, Object leftValue, Object rightValue) { if (leftValue == null && rightValue == null) { // they are equal return true; } else if (leftValue == null || rightValue == null) { // only one of them is null so they are not equal return false; } return ObjectHelper.typeCoerceCompare(exchange.getContext().getTypeConverter(), leftValue, rightValue) < 0; } protected String getOperationText() { return "<"; } }; } public static Predicate isLessThanOrEqualTo(final Expression left, final Expression right) { return new BinaryPredicateSupport(left, right) { protected boolean matches(Exchange exchange, Object leftValue, Object rightValue) { if (leftValue == null && rightValue == null) { // they are equal return true; } else if (leftValue == null || rightValue == null) { // only one of them is null so they are not equal return false; } return ObjectHelper.typeCoerceCompare(exchange.getContext().getTypeConverter(), leftValue, rightValue) <= 0; } protected String getOperationText() { return "<="; } }; } public static Predicate isGreaterThan(final Expression left, final Expression right) { return new BinaryPredicateSupport(left, right) { protected boolean matches(Exchange exchange, Object leftValue, Object rightValue) { if (leftValue == null && rightValue == null) { // they are equal return false; } else if (leftValue == null || rightValue == null) { // only one of them is null so they are not equal return false; } return ObjectHelper.typeCoerceCompare(exchange.getContext().getTypeConverter(), leftValue, rightValue) > 0; } protected String getOperationText() { return ">"; } }; } public static Predicate isGreaterThanOrEqualTo(final Expression left, final Expression right) { return new BinaryPredicateSupport(left, right) { protected boolean matches(Exchange exchange, Object leftValue, Object rightValue) { if (leftValue == null && rightValue == null) { // they are equal return true; } else if (leftValue == null || rightValue == null) { // only one of them is null so they are not equal return false; } return ObjectHelper.typeCoerceCompare(exchange.getContext().getTypeConverter(), leftValue, rightValue) >= 0; } protected String getOperationText() { return ">="; } }; } public static Predicate contains(final Expression left, final Expression right) { return new BinaryPredicateSupport(left, right) { protected boolean matches(Exchange exchange, Object leftValue, Object rightValue) { if (leftValue == null && rightValue == null) { // they are equal return true; } else if (leftValue == null || rightValue == null) { // only one of them is null so they are not equal return false; } return ObjectHelper.contains(leftValue, rightValue); } protected String getOperationText() { return "contains"; } }; } public static Predicate isNull(final Expression expression) { return new BinaryPredicateSupport(expression, ExpressionBuilder.constantExpression(null)) { protected boolean matches(Exchange exchange, Object leftValue, Object rightValue) { if (leftValue == null) { // the left operator is null so its true return true; } return ObjectHelper.typeCoerceEquals(exchange.getContext().getTypeConverter(), leftValue, rightValue); } protected String getOperationText() { // leave the operation text as "is not" as Camel will insert right and left expression around it // so it will be displayed as: XXX is null return "is"; } }; } public static Predicate isNotNull(final Expression expression) { return new BinaryPredicateSupport(expression, ExpressionBuilder.constantExpression(null)) { protected boolean matches(Exchange exchange, Object leftValue, Object rightValue) { if (leftValue != null) { // the left operator is not null so its true return true; } return ObjectHelper.typeCoerceNotEquals(exchange.getContext().getTypeConverter(), leftValue, rightValue); } protected String getOperationText() { // leave the operation text as "is not" as Camel will insert right and left expression around it // so it will be displayed as: XXX is not null return "is not"; } }; } public static Predicate isInstanceOf(final Expression expression, final Class<?> type) { notNull(expression, "expression"); notNull(type, "type"); return new Predicate() { public boolean matches(Exchange exchange) { Object value = expression.evaluate(exchange, Object.class); return type.isInstance(value); } @Override public String toString() { return expression + " instanceof " + type.getCanonicalName(); } }; } public static Predicate startsWith(final Expression left, final Expression right) { return new BinaryPredicateSupport(left, right) { protected boolean matches(Exchange exchange, Object leftValue, Object rightValue) { if (leftValue == null && rightValue == null) { // they are equal return true; } else if (leftValue == null || rightValue == null) { // only one of them is null so they are not equal return false; } String leftStr = exchange.getContext().getTypeConverter().convertTo(String.class, leftValue); String rightStr = exchange.getContext().getTypeConverter().convertTo(String.class, rightValue); if (leftStr != null && rightStr != null) { return leftStr.startsWith(rightStr); } else { return false; } } protected String getOperationText() { return "startsWith"; } }; } public static Predicate endsWith(final Expression left, final Expression right) { return new BinaryPredicateSupport(left, right) { protected boolean matches(Exchange exchange, Object leftValue, Object rightValue) { if (leftValue == null && rightValue == null) { // they are equal return true; } else if (leftValue == null || rightValue == null) { // only one of them is null so they are not equal return false; } String leftStr = exchange.getContext().getTypeConverter().convertTo(String.class, leftValue); String rightStr = exchange.getContext().getTypeConverter().convertTo(String.class, rightValue); if (leftStr != null && rightStr != null) { return leftStr.endsWith(rightStr); } else { return false; } } protected String getOperationText() { return "endsWith"; } }; } /** * Returns a predicate which is true if the expression matches the given * regular expression * * @param expression the expression to evaluate * @param regex the regular expression to match against * @return a new predicate */ public static Predicate regex(final Expression expression, final String regex) { return regex(expression, Pattern.compile(regex)); } /** * Returns a predicate which is true if the expression matches the given * regular expression * * @param expression the expression to evaluate * @param pattern the regular expression to match against * @return a new predicate */ public static Predicate regex(final Expression expression, final Pattern pattern) { notNull(expression, "expression"); notNull(pattern, "pattern"); return new Predicate() { public boolean matches(Exchange exchange) { String value = expression.evaluate(exchange, String.class); if (value != null) { Matcher matcher = pattern.matcher(value); return matcher.matches(); } return false; } @Override public String toString() { return expression + ".matches('" + pattern + "')"; } }; } /** * Concat the given predicates into a single predicate, which * only matches if all the predicates matches. * * @param predicates predicates * @return a single predicate containing all the predicates */ public static Predicate and(List<Predicate> predicates) { Predicate answer = null; for (Predicate predicate : predicates) { if (answer == null) { answer = predicate; } else { answer = and(answer, predicate); } } return answer; } /** * Concat the given predicates into a single predicate, which only matches * if all the predicates matches. * * @param predicates predicates * @return a single predicate containing all the predicates */ public static Predicate and(Predicate... predicates) { return and(Arrays.asList(predicates)); } /** * A constant predicate. * * @param answer the constant matches * @return a predicate that always returns the given answer. */ public static Predicate constant(final boolean answer) { return new Predicate() { @Override public boolean matches(Exchange exchange) { return answer; } @Override public String toString() { return "" + answer; } }; } }