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