You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2009/05/22 20:42:18 UTC
svn commit: r777654 - in /camel/trunk/camel-core/src:
main/java/org/apache/camel/language/simple/SimpleLangaugeOperator.java
main/java/org/apache/camel/language/simple/SimpleLanguageSupport.java
test/java/org/apache/camel/language/SimpleOperatorTest.java
Author: davsclaus
Date: Fri May 22 18:42:18 2009
New Revision: 777654
URL: http://svn.apache.org/viewvc?rev=777654&view=rev
Log:
CAMEL-1637: Added support for and,or to concat two expressions with the simple language.
Modified:
camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/SimpleLangaugeOperator.java
camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/SimpleLanguageSupport.java
camel/trunk/camel-core/src/test/java/org/apache/camel/language/SimpleOperatorTest.java
Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/SimpleLangaugeOperator.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/SimpleLangaugeOperator.java?rev=777654&r1=777653&r2=777654&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/SimpleLangaugeOperator.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/SimpleLangaugeOperator.java Fri May 22 18:42:18 2009
@@ -35,11 +35,22 @@
* <li>not is: tested for not if type is an instanceof the given type</li>
* <li>range : tested for if it is within the provided range</li>
* <li>not range : tested for not if it is within the provided range</li>
+ * <li>and : and operator to combine two groups of expressions</li>
+ * <li>or : or operator to combine two groups of expressions</li>
* </ul>
+ * <p/>
+ * The <tt>and</tt> and <tt>or</tt> operator is special as they are used as optional operator to combine two expressions.
+ * This allows you to build combiled expressions. Currently only one and/or operator is supported, but this might change
+ * in the future.
+ * <br/>
+ * For example we can create this compound expression that has two groups that is combined with the and operator:
+ * <tt>${in.header.action} == 'login' and ${in.header.password} != null</tt>
+ * <br/>
*/
public enum SimpleLangaugeOperator {
- EQ, GT, GTE, LT, LTE, NOT, CONTAINS, NOT_CONTAINS, REGEX, NOT_REGEX, IN, NOT_IN, IS, NOT_IS, RANGE, NOT_RANGE;
+ EQ, GT, GTE, LT, LTE, NOT, CONTAINS, NOT_CONTAINS, REGEX, NOT_REGEX,
+ IN, NOT_IN, IS, NOT_IS, RANGE, NOT_RANGE, AND, OR;
public static SimpleLangaugeOperator asOperator(String text) {
if ("==".equals(text)) {
@@ -74,6 +85,10 @@
return RANGE;
} else if ("not range".equals(text)) {
return NOT_RANGE;
+ } else if ("and".equals(text)) {
+ return AND;
+ } else if ("or".equals(text)) {
+ return OR;
}
throw new IllegalArgumentException("Operator not supported: " + text);
}
@@ -111,6 +126,10 @@
return "range";
} else if (operator == NOT_RANGE) {
return "not range";
+ } else if (operator == AND) {
+ return "and";
+ } else if (operator == OR) {
+ return "or";
}
return "";
}
Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/SimpleLanguageSupport.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/SimpleLanguageSupport.java?rev=777654&r1=777653&r2=777654&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/SimpleLanguageSupport.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/SimpleLanguageSupport.java Fri May 22 18:42:18 2009
@@ -40,8 +40,14 @@
*/
public abstract class SimpleLanguageSupport implements Language, IsSingleton {
- protected static final Pattern PATTERN = Pattern.compile(
- "^\\$\\{(.+)\\}\\s+(==|>|>=|<|<=|!=|contains|not contains|regex|not regex|in|not in|is|not is|range|not range)\\s+(.+)$");
+ // this is a regex for a given group in a simple expression that uses operators
+ private static final String GROUP_PATTERN =
+ "\\$\\{(\\S+)\\}\\s+(==|>|>=|<|<=|!=|contains|not contains|regex|not regex|in|not in|is|not is|range|not range)\\s+('.*'|\\S+)";
+
+ // this is the operator reg ex pattern used to match if a given expression is operator based or not
+ protected static final Pattern PATTERN = Pattern.compile("^(" + GROUP_PATTERN + ")(\\s+(and|or)\\s+(" + GROUP_PATTERN + "))?$");
+
+ // this is special for the range operator where you define the range as from..to (where from and to are numbers)
protected static final Pattern RANGE_PATTERN = Pattern.compile("^(\\d+)(\\.\\.)(\\d+)$");
protected final Log log = LogFactory.getLog(getClass());
@@ -70,35 +76,73 @@
}
private Expression createOperatorExpression(final Matcher matcher, final String expression) {
- final Expression left = createSimpleExpression(matcher.group(1), true);
- final SimpleLangaugeOperator operator = asOperator(matcher.group(2));
+ int groupCount = matcher.groupCount();
- // the right hand side expression can either be a constant expression wiht ' '
- // or another simple expression using ${ } placeholders
- String text = matcher.group(3);
+ if (log.isTraceEnabled()) {
+ log.trace("Matcher expression: " + expression);
+ log.trace("Matcher group count: " + groupCount);
+ for (int i = 0; i < matcher.groupCount() + 1; i++) {
+ String group = matcher.group(i);
+ if (log.isTraceEnabled()) {
+ log.trace("Matcher group #" + i + ": " + group);
+ }
+ }
+ }
+ // a simple expression with operator can either be a single group or a dual group
+ String operatorText = matcher.group(6);
+ if (operatorText == null) {
+ // single group
+ return doCreateOperatorExpression(expression, matcher.group(2), matcher.group(3), matcher.group(4));
+ } else {
+ // dual group with an and/or operator between the two groups
+ final Expression first = doCreateOperatorExpression(expression, matcher.group(2), matcher.group(3), matcher.group(4));
+ final SimpleLangaugeOperator operator = asOperator(operatorText);
+ final Expression last = doCreateOperatorExpression(expression, matcher.group(8), matcher.group(9), matcher.group(10));
+
+ // create a compound predicate to combine the two groups with the operator
+ final Predicate compoundPredicate;
+ if (operator == AND) {
+ compoundPredicate = PredicateBuilder.and(PredicateBuilder.toPredicate(first), PredicateBuilder.toPredicate(last));
+ } else if (operator == OR) {
+ compoundPredicate = PredicateBuilder.or(PredicateBuilder.toPredicate(first), PredicateBuilder.toPredicate(last));
+ } else {
+ throw new IllegalArgumentException("Syntax error in expression: " + expression
+ + ". Expected operator as either and/or but was: " + operator);
+ }
+
+ // return the expression that evaluates this expression
+ return new Expression() {
+ public <T> T evaluate(Exchange exchange, Class<T> type) {
+ boolean matches = compoundPredicate.matches(exchange);
+ return exchange.getContext().getTypeConverter().convertTo(type, matches);
+ }
+
+ @Override
+ public String toString() {
+ return first + " " + operator + " " + last;
+ }
+ };
+ }
+ }
+
+ private Expression doCreateOperatorExpression(final String expression, final String leftText,
+ final String operatorText, final String rightText) {
+ // left value is always a simple expression
+ final Expression left = createSimpleExpression(leftText, true);
+ final SimpleLangaugeOperator operator = asOperator(operatorText);
+
+ // the right hand side expression can either be a constant expression with or without enclosing ' '
+ // or another simple expression using ${ } placeholders
final Expression right;
- final Expression rightConverted;
final Boolean isNull;
// special null handling
- if ("null".equals(text) || "'null'".equals(text)) {
+ if ("null".equals(rightText) || "'null'".equals(rightText)) {
isNull = Boolean.TRUE;
- right = createConstantExpression(null);
- rightConverted = right;
+ right = createSimpleOrConstantExpression(null);
} else {
isNull = Boolean.FALSE;
- // text can either be a constant enclosed by ' ' or another expression using ${ } placeholders
- String constant = ObjectHelper.between(text, "'", "'");
- if (constant == null) {
- // if no ' ' around then fallback to the text itself
- constant = text;
- }
- String simple = ObjectHelper.between(text, "${", "}");
-
- right = simple != null ? createSimpleExpression(simple, true) : createConstantExpression(constant);
- // to support numeric comparions using > and < operators we must convert the right hand side
- // to the same type as the left
- rightConverted = ExpressionBuilder.convertToExpression(right, left);
+ right = createSimpleOrConstantExpression(rightText);
}
return new Expression() {
@@ -112,19 +156,19 @@
// special for not EQ null
predicate = PredicateBuilder.isNotNull(left);
} else if (operator == EQ) {
- predicate = PredicateBuilder.isEqualTo(left, rightConverted);
+ predicate = PredicateBuilder.isEqualTo(left, right);
} else if (operator == GT) {
- predicate = PredicateBuilder.isGreaterThan(left, rightConverted);
+ predicate = PredicateBuilder.isGreaterThan(left, right);
} else if (operator == GTE) {
- predicate = PredicateBuilder.isGreaterThanOrEqualTo(left, rightConverted);
+ predicate = PredicateBuilder.isGreaterThanOrEqualTo(left, right);
} else if (operator == LT) {
- predicate = PredicateBuilder.isLessThan(left, rightConverted);
+ predicate = PredicateBuilder.isLessThan(left, right);
} else if (operator == LTE) {
- predicate = PredicateBuilder.isLessThanOrEqualTo(left, rightConverted);
+ predicate = PredicateBuilder.isLessThanOrEqualTo(left, right);
} else if (operator == NOT) {
- predicate = PredicateBuilder.isNotEqualTo(left, rightConverted);
+ predicate = PredicateBuilder.isNotEqualTo(left, right);
} else if (operator == CONTAINS || operator == NOT_CONTAINS) {
- predicate = PredicateBuilder.contains(left, rightConverted);
+ predicate = PredicateBuilder.contains(left, right);
if (operator == NOT_CONTAINS) {
predicate = PredicateBuilder.not(predicate);
}
@@ -228,6 +272,22 @@
return ExpressionBuilder.concatExpression(results, expression);
}
+ protected Expression createSimpleOrConstantExpression(String text) {
+ if (text != null) {
+ String simple = ObjectHelper.between(text, "${", "}");
+ if (simple != null) {
+ return createSimpleExpression(simple, true);
+ }
+
+ simple = ObjectHelper.between(text, "'", "'");
+ if (simple != null) {
+ return createConstantExpression(simple);
+ }
+ }
+
+ return createConstantExpression(text);
+ }
+
protected Expression createConstantExpression(String expression, int start, int end) {
return ExpressionBuilder.constantExpression(expression.substring(start, end));
}
Modified: camel/trunk/camel-core/src/test/java/org/apache/camel/language/SimpleOperatorTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/language/SimpleOperatorTest.java?rev=777654&r1=777653&r2=777654&view=diff
==============================================================================
--- camel/trunk/camel-core/src/test/java/org/apache/camel/language/SimpleOperatorTest.java (original)
+++ camel/trunk/camel-core/src/test/java/org/apache/camel/language/SimpleOperatorTest.java Fri May 22 18:42:18 2009
@@ -32,6 +32,33 @@
return jndi;
}
+ public void tesValueWithSpace() throws Exception {
+ exchange.getIn().setBody("Hello Big World");
+ assertExpression("${in.body} == 'Hello Big World'", true);
+ }
+
+ public void testAnd() throws Exception {
+ assertExpression("${in.header.foo} == abc and ${in.header.bar} == 123", true);
+ assertExpression("${in.header.foo} == abc and ${in.header.bar} == 444", false);
+ assertExpression("${in.header.foo} == def and ${in.header.bar} == 123", false);
+ assertExpression("${in.header.foo} == def and ${in.header.bar} == 444", false);
+
+ assertExpression("${in.header.foo} == abc and ${in.header.bar} > 100", true);
+ assertExpression("${in.header.foo} == abc and ${in.header.bar} < 200", true);
+ }
+
+ public void testOr() throws Exception {
+ assertExpression("${in.header.foo} == abc or ${in.header.bar} == 123", true);
+ assertExpression("${in.header.foo} == abc or ${in.header.bar} == 444", true);
+ assertExpression("${in.header.foo} == def or ${in.header.bar} == 123", true);
+ assertExpression("${in.header.foo} == def or ${in.header.bar} == 444", false);
+
+ assertExpression("${in.header.foo} == abc or ${in.header.bar} < 100", true);
+ assertExpression("${in.header.foo} == abc or ${in.header.bar} < 200", true);
+ assertExpression("${in.header.foo} == def or ${in.header.bar} < 200", true);
+ assertExpression("${in.header.foo} == def or ${in.header.bar} < 100", false);
+ }
+
public void testEqualOperator() throws Exception {
// string to string comparison
assertExpression("${in.header.foo} == 'abc'", true);
@@ -255,7 +282,7 @@
assertExpression("${in.header.foo} not is Integer", true);
try {
- assertExpression("${in.header.foo} is not com.mycompany.DoesNotExist", false);
+ assertExpression("${in.header.foo} not is com.mycompany.DoesNotExist", false);
fail("Should have thrown an exception");
} catch (IllegalArgumentException e) {
assertTrue(e.getMessage().startsWith("Syntax error"));
@@ -287,18 +314,16 @@
}
try {
- assertExpression("${in.header.foo} range 100 200", false);
- fail("Should have thrown an exception");
- } catch (IllegalArgumentException e) {
- assertTrue(e.getMessage().startsWith("Syntax error"));
- }
-
- try {
assertExpression("${in.header.foo} range 100.200", false);
fail("Should have thrown an exception");
} catch (IllegalArgumentException e) {
assertTrue(e.getMessage().startsWith("Syntax error"));
}
+
+ assertExpression("${in.header.bar} range 100..200 and ${in.header.foo} == abc" , true);
+ assertExpression("${in.header.bar} range 200..300 and ${in.header.foo} == abc" , false);
+ assertExpression("${in.header.bar} range 200..300 or ${in.header.foo} == abc" , true);
+ assertExpression("${in.header.bar} range 200..300 or ${in.header.foo} == def" , false);
}
public void testNotRange() throws Exception {
@@ -326,13 +351,6 @@
}
try {
- assertExpression("${in.header.foo} not range 100 200", false);
- fail("Should have thrown an exception");
- } catch (IllegalArgumentException e) {
- assertTrue(e.getMessage().startsWith("Syntax error"));
- }
-
- try {
assertExpression("${in.header.foo} not range 100.200", false);
fail("Should have thrown an exception");
} catch (IllegalArgumentException e) {