001    /**
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.camel.builder;
018    
019    import java.util.regex.Matcher;
020    import java.util.regex.Pattern;
021    
022    import org.apache.camel.Exchange;
023    import org.apache.camel.Expression;
024    import org.apache.camel.Predicate;
025    import org.apache.camel.impl.BinaryPredicateSupport;
026    import org.apache.camel.impl.PredicateSupport;
027    import org.apache.camel.util.ObjectHelper;
028    
029    import static org.apache.camel.util.ObjectHelper.compare;
030    import static org.apache.camel.util.ObjectHelper.notNull;
031    
032    /**
033     * A helper class for working with predicates
034     *
035     * @version $Revision: 36321 $
036     */
037    public final class PredicateBuilder {
038    
039        /**
040         * Utility classes should not have a public constructor.
041         */
042        private PredicateBuilder() {
043        }
044    
045        /**
046         * Converts the given expression into an {@link Predicate}
047         */
048        public static <E extends Exchange> Predicate<E> toPredicate(final Expression<E> expression) {
049            return new PredicateSupport<E>() {
050                public boolean matches(E exchange) {
051                    Object value = expression.evaluate(exchange);
052                    return evaluateValuePredicate(value);
053                }
054    
055                @Override
056                public String toString() {
057                    return expression.toString();
058                }
059            };
060        }
061    
062        /**
063         * Evaluate the value as a predicate which attempts to convert the value to
064         * a boolean otherwise true is returned if the value is not null
065         */
066        public static boolean evaluateValuePredicate(Object value) {
067            if (value instanceof Boolean) {
068                Boolean aBoolean = (Boolean)value;
069                return aBoolean.booleanValue();
070            }
071            return value != null;
072        }
073    
074        /**
075         * A helper method to return the logical not of the given predicate
076         */
077        public static <E extends Exchange> Predicate<E> not(final Predicate<E> predicate) {
078            notNull(predicate, "predicate");
079            return new PredicateSupport<E>() {
080                public boolean matches(E exchange) {
081                    return !predicate.matches(exchange);
082                }
083    
084                @Override
085                public String toString() {
086                    return "not " + predicate;
087                }
088            };
089        }
090    
091        /**
092         * A helper method to combine multiple predicates by a logical AND
093         */
094        public static <E extends Exchange> Predicate<E> and(final Predicate<E> left, final Predicate<E> right) {
095            notNull(left, "left");
096            notNull(right, "right");
097            return new PredicateSupport<E>() {
098                public boolean matches(E exchange) {
099                    return left.matches(exchange) && right.matches(exchange);
100                }
101    
102                @Override
103                public String toString() {
104                    return "(" + left + ") and (" + right + ")";
105                }
106            };
107        }
108    
109        /**
110         * A helper method to combine multiple predicates by a logical OR
111         */
112        public static <E extends Exchange> Predicate<E> or(final Predicate<E> left, final Predicate<E> right) {
113            notNull(left, "left");
114            notNull(right, "right");
115            return new PredicateSupport<E>() {
116                public boolean matches(E exchange) {
117                    return left.matches(exchange) || right.matches(exchange);
118                }
119    
120                @Override
121                public String toString() {
122                    return "(" + left + ") or (" + right + ")";
123                }
124            };
125        }
126    
127        public static <E extends Exchange> Predicate<E> isEqualTo(final Expression<E> left,
128                                                                  final Expression<E> right) {
129            return new BinaryPredicateSupport<E>(left, right) {
130    
131                protected boolean matches(E exchange, Object leftValue, Object rightValue) {
132                    return ObjectHelper.equal(leftValue, rightValue);
133                }
134    
135                protected String getOperationText() {
136                    return "==";
137                }
138            };
139        }
140    
141        public static <E extends Exchange> Predicate<E> isNotEqualTo(final Expression<E> left,
142                                                                     final Expression<E> right) {
143            return new BinaryPredicateSupport<E>(left, right) {
144    
145                protected boolean matches(E exchange, Object leftValue, Object rightValue) {
146                    return !ObjectHelper.equal(leftValue, rightValue);
147                }
148    
149                protected String getOperationText() {
150                    return "!=";
151                }
152            };
153        }
154    
155        public static <E extends Exchange> Predicate<E> isLessThan(final Expression<E> left,
156                                                                   final Expression<E> right) {
157            return new BinaryPredicateSupport<E>(left, right) {
158    
159                protected boolean matches(E exchange, Object leftValue, Object rightValue) {
160                    return compare(leftValue, rightValue) < 0;
161                }
162    
163                protected String getOperationText() {
164                    return "<";
165                }
166            };
167        }
168    
169        public static <E extends Exchange> Predicate<E> isLessThanOrEqualTo(final Expression<E> left,
170                                                                            final Expression<E> right) {
171            return new BinaryPredicateSupport<E>(left, right) {
172    
173                protected boolean matches(E exchange, Object leftValue, Object rightValue) {
174                    return compare(leftValue, rightValue) <= 0;
175                }
176    
177                protected String getOperationText() {
178                    return "<=";
179                }
180            };
181        }
182    
183        public static <E extends Exchange> Predicate<E> isGreaterThan(final Expression<E> left,
184                                                                      final Expression<E> right) {
185            return new BinaryPredicateSupport<E>(left, right) {
186    
187                protected boolean matches(E exchange, Object leftValue, Object rightValue) {
188                    return compare(leftValue, rightValue) > 0;
189                }
190    
191                protected String getOperationText() {
192                    return ">";
193                }
194            };
195        }
196    
197        public static <E extends Exchange> Predicate<E> isGreaterThanOrEqualTo(final Expression<E> left,
198                                                                               final Expression<E> right) {
199            return new BinaryPredicateSupport<E>(left, right) {
200    
201                protected boolean matches(E exchange, Object leftValue, Object rightValue) {
202                    return compare(leftValue, rightValue) >= 0;
203                }
204    
205                protected String getOperationText() {
206                    return ">=";
207                }
208            };
209        }
210    
211        public static <E extends Exchange> Predicate<E> contains(final Expression<E> left,
212                                                                 final Expression<E> right) {
213            return new BinaryPredicateSupport<E>(left, right) {
214    
215                protected boolean matches(E exchange, Object leftValue, Object rightValue) {
216                    return ObjectHelper.contains(leftValue, rightValue);
217                }
218    
219                protected String getOperationText() {
220                    return "contains";
221                }
222            };
223        }
224    
225        public static <E extends Exchange> Predicate<E> isNull(final Expression<E> expression) {
226            return isEqualTo(expression, ExpressionBuilder.<E> constantExpression(null));
227        }
228    
229        public static <E extends Exchange> Predicate<E> isNotNull(final Expression<E> expression) {
230            return isNotEqualTo(expression, ExpressionBuilder.<E> constantExpression(null));
231        }
232    
233        public static <E extends Exchange> Predicate<E> isInstanceOf(final Expression<E> expression,
234                                                                     final Class type) {
235            notNull(expression, "expression");
236            notNull(type, "type");
237    
238            return new PredicateSupport<E>() {
239                public boolean matches(E exchange) {
240                    Object value = expression.evaluate(exchange);
241                    return type.isInstance(value);
242                }
243    
244                @Override
245                public String toString() {
246                    return expression + " instanceof " + type.getName();
247                }
248    
249                @Override
250                protected String assertionFailureMessage(E exchange) {
251                    return super.assertionFailureMessage(exchange) + " for <" + expression.evaluate(exchange)
252                           + ">";
253                }
254            };
255        }
256    
257        /**
258         * Returns a predicate which is true if the expression matches the given
259         * regular expression
260         *
261         * @param expression the expression to evaluate
262         * @param regex the regular expression to match against
263         * @return a new predicate
264         */
265        public static <E extends Exchange> Predicate<E> regex(final Expression<E> expression, final String regex) {
266            return regex(expression, Pattern.compile(regex));
267        }
268    
269        /**
270         * Returns a predicate which is true if the expression matches the given
271         * regular expression
272         *
273         * @param expression the expression to evaluate
274         * @param pattern the regular expression to match against
275         * @return a new predicate
276         */
277        public static <E extends Exchange> Predicate<E> regex(final Expression<E> expression,
278                                                              final Pattern pattern) {
279            notNull(expression, "expression");
280            notNull(pattern, "pattern");
281    
282            return new PredicateSupport<E>() {
283                public boolean matches(E exchange) {
284                    Object value = expression.evaluate(exchange);
285                    if (value != null) {
286                        Matcher matcher = pattern.matcher(value.toString());
287                        return matcher.matches();
288                    }
289                    return false;
290                }
291    
292                @Override
293                public String toString() {
294                    return expression + ".matches(" + pattern + ")";
295                }
296    
297                @Override
298                protected String assertionFailureMessage(E exchange) {
299                    return super.assertionFailureMessage(exchange) + " for <" + expression.evaluate(exchange)
300                           + ">";
301                }
302    
303            };
304        }
305    }