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.Arrays; 020 import java.util.regex.Matcher; 021 import java.util.regex.Pattern; 022 023 import org.apache.camel.Exchange; 024 import org.apache.camel.Expression; 025 import org.apache.camel.Predicate; 026 import org.apache.camel.util.ObjectHelper; 027 import static org.apache.camel.util.ObjectHelper.compare; 028 import static org.apache.camel.util.ObjectHelper.notNull; 029 030 031 /** 032 * A helper class for working with predicates 033 * 034 * @version $Revision: 776194 $ 035 */ 036 public final class PredicateBuilder { 037 038 /** 039 * Utility classes should not have a public constructor. 040 */ 041 private PredicateBuilder() { 042 } 043 044 /** 045 * Converts the given expression into an {@link Predicate} 046 */ 047 public static Predicate toPredicate(final Expression expression) { 048 return new Predicate() { 049 public boolean matches(Exchange exchange) { 050 Object value = expression.evaluate(exchange, Object.class); 051 return ObjectHelper.evaluateValuePredicate(value); 052 } 053 054 @Override 055 public String toString() { 056 return expression.toString(); 057 } 058 }; 059 } 060 061 /** 062 * A helper method to return the logical not of the given predicate 063 */ 064 public static Predicate not(final Predicate predicate) { 065 notNull(predicate, "predicate"); 066 return new Predicate() { 067 public boolean matches(Exchange exchange) { 068 return !predicate.matches(exchange); 069 } 070 071 @Override 072 public String toString() { 073 return "not (" + predicate + ")"; 074 } 075 }; 076 } 077 078 /** 079 * A helper method to combine multiple predicates by a logical AND 080 */ 081 public static Predicate and(final Predicate left, final Predicate right) { 082 notNull(left, "left"); 083 notNull(right, "right"); 084 return new Predicate() { 085 public boolean matches(Exchange exchange) { 086 return left.matches(exchange) && right.matches(exchange); 087 } 088 089 @Override 090 public String toString() { 091 return "(" + left + ") and (" + right + ")"; 092 } 093 }; 094 } 095 096 /** 097 * A helper method to combine multiple predicates by a logical OR 098 */ 099 public static Predicate or(final Predicate left, final Predicate right) { 100 notNull(left, "left"); 101 notNull(right, "right"); 102 return new Predicate() { 103 public boolean matches(Exchange exchange) { 104 return left.matches(exchange) || right.matches(exchange); 105 } 106 107 @Override 108 public String toString() { 109 return "(" + left + ") or (" + right + ")"; 110 } 111 }; 112 } 113 114 /** 115 * A helper method to return true if any of the predicates matches. 116 */ 117 public static Predicate in(final Predicate... predicates) { 118 notNull(predicates, "predicates"); 119 120 return new Predicate() { 121 public boolean matches(Exchange exchange) { 122 for (Predicate in : predicates) { 123 if (in.matches(exchange)) { 124 return true; 125 } 126 } 127 return false; 128 } 129 130 @Override 131 public String toString() { 132 return "in (" + Arrays.asList(predicates) + ")"; 133 } 134 }; 135 } 136 137 public static Predicate isEqualTo(final Expression left, final Expression right) { 138 return new BinaryPredicateSupport(left, right) { 139 140 protected boolean matches(Exchange exchange, Object leftValue, Object rightValue) { 141 if (leftValue == null && rightValue == null) { 142 // they are equal 143 return true; 144 } else if (leftValue == null || rightValue == null) { 145 // only one of them is null so they are not equal 146 return false; 147 } 148 149 return ObjectHelper.typeCoerceEquals(exchange.getContext().getTypeConverter(), leftValue, rightValue); 150 } 151 152 protected String getOperationText() { 153 return "=="; 154 } 155 }; 156 } 157 158 public static Predicate isNotEqualTo(final Expression left, final Expression right) { 159 return new BinaryPredicateSupport(left, right) { 160 161 protected boolean matches(Exchange exchange, Object leftValue, Object rightValue) { 162 if (leftValue == null && rightValue == null) { 163 // they are equal 164 return false; 165 } else if (leftValue == null || rightValue == null) { 166 // only one of them is null so they are not equal 167 return true; 168 } 169 170 return ObjectHelper.typeCoerceNotEquals(exchange.getContext().getTypeConverter(), leftValue, rightValue); 171 } 172 173 protected String getOperationText() { 174 return "!="; 175 } 176 }; 177 } 178 179 public static Predicate isLessThan(final Expression left, final Expression right) { 180 return new BinaryPredicateSupport(left, right) { 181 182 protected boolean matches(Exchange exchange, Object leftValue, Object rightValue) { 183 if (leftValue == null && rightValue == null) { 184 // they are equal 185 return true; 186 } else if (leftValue == null || rightValue == null) { 187 // only one of them is null so they are not equal 188 return false; 189 } 190 191 return ObjectHelper.typeCoerceCompare(exchange.getContext().getTypeConverter(), leftValue, rightValue) < 0; 192 } 193 194 protected String getOperationText() { 195 return "<"; 196 } 197 }; 198 } 199 200 public static Predicate isLessThanOrEqualTo(final Expression left, final Expression right) { 201 return new BinaryPredicateSupport(left, right) { 202 203 protected boolean matches(Exchange exchange, Object leftValue, Object rightValue) { 204 if (leftValue == null && rightValue == null) { 205 // they are equal 206 return true; 207 } else if (leftValue == null || rightValue == null) { 208 // only one of them is null so they are not equal 209 return false; 210 } 211 212 return ObjectHelper.typeCoerceCompare(exchange.getContext().getTypeConverter(), leftValue, rightValue) <= 0; 213 } 214 215 protected String getOperationText() { 216 return "<="; 217 } 218 }; 219 } 220 221 public static Predicate isGreaterThan(final Expression left, final Expression right) { 222 return new BinaryPredicateSupport(left, right) { 223 224 protected boolean matches(Exchange exchange, Object leftValue, Object rightValue) { 225 if (leftValue == null && rightValue == null) { 226 // they are equal 227 return false; 228 } else if (leftValue == null || rightValue == null) { 229 // only one of them is null so they are not equal 230 return false; 231 } 232 233 return ObjectHelper.typeCoerceCompare(exchange.getContext().getTypeConverter(), leftValue, rightValue) > 0; 234 } 235 236 protected String getOperationText() { 237 return ">"; 238 } 239 }; 240 } 241 242 public static Predicate isGreaterThanOrEqualTo(final Expression left, final Expression right) { 243 return new BinaryPredicateSupport(left, right) { 244 245 protected boolean matches(Exchange exchange, Object leftValue, Object rightValue) { 246 if (leftValue == null && rightValue == null) { 247 // they are equal 248 return true; 249 } else if (leftValue == null || rightValue == null) { 250 // only one of them is null so they are not equal 251 return false; 252 } 253 254 return ObjectHelper.typeCoerceCompare(exchange.getContext().getTypeConverter(), leftValue, rightValue) >= 0; 255 } 256 257 protected String getOperationText() { 258 return ">="; 259 } 260 }; 261 } 262 263 public static Predicate contains(final Expression left, final Expression right) { 264 return new BinaryPredicateSupport(left, right) { 265 266 protected boolean matches(Exchange exchange, Object leftValue, Object rightValue) { 267 if (leftValue == null && rightValue == null) { 268 // they are equal 269 return true; 270 } else if (leftValue == null || rightValue == null) { 271 // only one of them is null so they are not equal 272 return false; 273 } 274 275 return ObjectHelper.contains(leftValue, rightValue); 276 } 277 278 protected String getOperationText() { 279 return "contains"; 280 } 281 }; 282 } 283 284 public static Predicate isNull(final Expression expression) { 285 return new BinaryPredicateSupport(expression, ExpressionBuilder.constantExpression(null)) { 286 287 protected boolean matches(Exchange exchange, Object leftValue, Object rightValue) { 288 if (leftValue == null) { 289 // the left operator is null so its true 290 return true; 291 } 292 293 return ObjectHelper.typeCoerceEquals(exchange.getContext().getTypeConverter(), leftValue, rightValue); 294 } 295 296 protected String getOperationText() { 297 // leave the operation text as "is not" as Camel will insert right and left expression around it 298 // so it will be displayed as: XXX is null 299 return "is"; 300 } 301 }; 302 } 303 304 public static Predicate isNotNull(final Expression expression) { 305 return new BinaryPredicateSupport(expression, ExpressionBuilder.constantExpression(null)) { 306 307 protected boolean matches(Exchange exchange, Object leftValue, Object rightValue) { 308 if (leftValue != null) { 309 // the left operator is not null so its true 310 return true; 311 } 312 313 return ObjectHelper.typeCoerceNotEquals(exchange.getContext().getTypeConverter(), leftValue, rightValue); 314 } 315 316 protected String getOperationText() { 317 // leave the operation text as "is not" as Camel will insert right and left expression around it 318 // so it will be displayed as: XXX is not null 319 return "is not"; 320 } 321 }; 322 } 323 324 public static Predicate isInstanceOf(final Expression expression, final Class<?> type) { 325 notNull(expression, "expression"); 326 notNull(type, "type"); 327 328 return new Predicate() { 329 public boolean matches(Exchange exchange) { 330 Object value = expression.evaluate(exchange, Object.class); 331 return type.isInstance(value); 332 } 333 334 @Override 335 public String toString() { 336 return expression + " instanceof " + type.getCanonicalName(); 337 } 338 }; 339 } 340 341 /** 342 * Returns a predicate which is true if the expression matches the given 343 * regular expression 344 * 345 * @param expression the expression to evaluate 346 * @param regex the regular expression to match against 347 * @return a new predicate 348 */ 349 public static Predicate regex(final Expression expression, final String regex) { 350 return regex(expression, Pattern.compile(regex)); 351 } 352 353 /** 354 * Returns a predicate which is true if the expression matches the given 355 * regular expression 356 * 357 * @param expression the expression to evaluate 358 * @param pattern the regular expression to match against 359 * @return a new predicate 360 */ 361 public static Predicate regex(final Expression expression, final Pattern pattern) { 362 notNull(expression, "expression"); 363 notNull(pattern, "pattern"); 364 365 return new Predicate() { 366 public boolean matches(Exchange exchange) { 367 String value = expression.evaluate(exchange, String.class); 368 if (value != null) { 369 Matcher matcher = pattern.matcher(value); 370 return matcher.matches(); 371 } 372 return false; 373 } 374 375 @Override 376 public String toString() { 377 return expression + ".matches('" + pattern + "')"; 378 } 379 }; 380 } 381 }