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/02/15 18:49:04 UTC

svn commit: r744707 - in /camel/trunk/camel-core/src: main/java/org/apache/camel/builder/ main/java/org/apache/camel/language/bean/ main/java/org/apache/camel/language/simple/ main/java/org/apache/camel/util/ test/java/org/apache/camel/language/ test/j...

Author: davsclaus
Date: Sun Feb 15 17:49:04 2009
New Revision: 744707

URL: http://svn.apache.org/viewvc?rev=744707&view=rev
Log:
CAMEL-1338: Added basic operator support for simple language - end users is confused its not working, and nice to have core support for basic operators. Added ?method=methodname for the bean langauge so its in line with the bean component.

Added:
    camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/SimpleLangaugeOperator.java   (with props)
    camel/trunk/camel-core/src/test/java/org/apache/camel/language/SimpleOperatorTest.java
      - copied, changed from r744631, camel/trunk/camel-core/src/test/java/org/apache/camel/language/SimpleTest.java
Modified:
    camel/trunk/camel-core/src/main/java/org/apache/camel/builder/ExpressionBuilder.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/language/bean/BeanLanguage.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/SimpleLanguageSupport.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/util/ObjectHelper.java
    camel/trunk/camel-core/src/test/java/org/apache/camel/language/BeanTest.java
    camel/trunk/camel-core/src/test/java/org/apache/camel/util/ObjectHelperTest.java

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/builder/ExpressionBuilder.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/ExpressionBuilder.java?rev=744707&r1=744706&r2=744707&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/builder/ExpressionBuilder.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/builder/ExpressionBuilder.java Sun Feb 15 17:49:04 2009
@@ -290,6 +290,22 @@
     }
 
     /**
+     * Returns the expression for the exchanges inbound message body type
+     */
+    public static Expression bodyType() {
+        return new ExpressionAdapter() {
+            public Object evaluate(Exchange exchange) {
+                return exchange.getIn().getBody().getClass();
+            }
+
+            @Override
+            public String toString() {
+                return "bodyType";
+            }
+        };
+    }
+
+    /**
      * Returns the expression for the exchanges inbound message body converted
      * to the given type
      */
@@ -445,6 +461,23 @@
     }
 
     /**
+     * Returns an expression which converts the given expression to the given type the type
+     * expression is evaluted to
+     */
+    public static Expression convertTo(final Expression expression, final Expression type) {
+        return new ExpressionAdapter() {
+            public Object evaluate(Exchange exchange) {
+                return expression.evaluate(exchange, type.evaluate(exchange).getClass());
+            }
+
+            @Override
+            public String toString() {
+                return "" + expression + ".convertTo(" + type + ")";
+            }
+        };
+    }
+
+    /**
      * Returns a tokenize expression which will tokenize the string with the
      * given token
      */

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/language/bean/BeanLanguage.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/language/bean/BeanLanguage.java?rev=744707&r1=744706&r2=744707&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/language/bean/BeanLanguage.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/language/bean/BeanLanguage.java Sun Feb 15 17:49:04 2009
@@ -82,13 +82,20 @@
     public Expression createExpression(String expression) {
         ObjectHelper.notNull(expression, "expression");
 
-        int idx = expression.lastIndexOf('.');
         String beanName = expression;
         String method = null;
+
+        // we support both the .method name and the ?method= syntax
+        // as the ?method= syntax is very common for the bean component
+        int idx = expression.lastIndexOf('.');
         if (idx > 0) {
             beanName = expression.substring(0, idx);
             method = expression.substring(idx + 1);
+        } else if (expression.contains("?method=")) {
+            beanName = ObjectHelper.before(expression, "?");
+            method = ObjectHelper.after(expression, "?method=");
         }
+        
         return new BeanExpression(beanName, method);
     }
 

Added: 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=744707&view=auto
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/SimpleLangaugeOperator.java (added)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/SimpleLangaugeOperator.java Sun Feb 15 17:49:04 2009
@@ -0,0 +1,72 @@
+/**
+ * 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.language.simple;
+
+/**
+ * Operators supported by simple language
+ * <ul>
+ *   <li>EQ : ==</li>
+ *   <li>GT : ></li>
+ *   <li>GTE : >=</li>
+ *   <li>LT : <</li>
+ *   <li>LTE : <=</li>
+ *   <li>NOT : !=</li>
+ * </ul>
+ */
+public enum SimpleLangaugeOperator {
+
+    EQ, GT, GTE, LT, LTE, NOT;
+
+    public static SimpleLangaugeOperator asOperator(String text) {
+        if ("==".equals(text)) {
+            return EQ;
+        } else if (">".equals(text)) {
+            return GT;
+        } else if (">=".equals(text)) {
+            return GTE;
+        } else if ("<".equals(text)) {
+            return LT;
+        } else if ("<=".equals(text)) {
+            return LTE;
+        } else if ("!=".equals(text)) {
+            return NOT;
+        }
+        throw new IllegalArgumentException("Operator not supported: " + text);
+    }
+
+    public String getOperatorText(SimpleLangaugeOperator operator) {
+        if (operator == EQ) {
+            return "==";
+        } else if (operator == GT) {
+            return ">";
+        } else if (operator == GTE) {
+            return ">=";
+        } else if (operator == LT) {
+            return "<";
+        } else if (operator == LTE) {
+            return "<=";
+        } else if (operator == NOT) {
+            return "!=";
+        } 
+        return "";
+    }
+
+    @Override
+    public String toString() {
+        return getOperatorText(this);
+    }
+}

Propchange: camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/SimpleLangaugeOperator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/SimpleLangaugeOperator.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

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=744707&r1=744706&r2=744707&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 Sun Feb 15 17:49:04 2009
@@ -18,30 +18,113 @@
 
 import java.util.ArrayList;
 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.builder.ExpressionBuilder;
 import org.apache.camel.builder.PredicateBuilder;
+import org.apache.camel.impl.ExpressionAdapter;
 import org.apache.camel.spi.Language;
+import org.apache.camel.util.ObjectHelper;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import static org.apache.camel.language.simple.SimpleLangaugeOperator.*;
 
 /**
  * Abstract base class for Simple languages.
  */
 public abstract class SimpleLanguageSupport implements Language {
-    
+
+    protected static final Pattern PATTERN = Pattern.compile("^\\$\\{(.+)\\}\\s+(==|>|>=|<|<=|!=|is)\\s+(.+)$");
+    protected final Log log = LogFactory.getLog(getClass());
+
     public Predicate createPredicate(String expression) {
         return PredicateBuilder.toPredicate(createExpression(expression));
     }
 
     public Expression createExpression(String expression) {
-        if (expression.indexOf("${") >= 0) {
-            return createComplexExpression(expression);
+        Matcher matcher = PATTERN.matcher(expression);
+        if (matcher.matches()) {
+            if (log.isDebugEnabled()) {
+                log.debug("Expression is evaluated as operator expression: " + expression);
+            }
+            return createOperatorExpression(matcher, expression);
+        } else if (expression.indexOf("${") >= 0) {
+            if (log.isDebugEnabled()) {
+                log.debug("Expression is evaluated as complex expression: " + expression);
+            }
+            return createComplexConcatExpression(expression);
+        } else {
+            if (log.isDebugEnabled()) {
+                log.debug("Expression is evaluated as simple expression: " + expression);
+            }
+            return createSimpleExpression(expression);
         }
-        return createSimpleExpression(expression);
     }
 
-    protected Expression createComplexExpression(String expression) {
+    private Expression createOperatorExpression(final Matcher matcher, final String expression) {
+        final Expression left = createSimpleExpression(matcher.group(1));
+        final SimpleLangaugeOperator operator = asOperator(matcher.group(2));
+
+        // the right hand side expression can either be a constant expression wiht ' '
+        // or another simple expression using ${ } placeholders
+        String text = matcher.group(3);
+
+        final Expression right;
+        // special null handling
+        if ("null".equals(text)) {
+            right = createConstantExpression(null);
+        } else {
+            // text can either be a constant enclosed by ' ' or another expression using ${ } placeholders
+            String constant = ObjectHelper.between(text, "'", "'");
+            String simple = ObjectHelper.between(text, "${", "}");
+
+            Expression exp = simple != null ? createSimpleExpression(simple) : createConstantExpression(constant);
+            // to support numeric comparions using > and < operators we must convert the right hand side
+            // to the same type as the left
+            right = ExpressionBuilder.convertTo(exp, left);
+        }
+
+        return new ExpressionAdapter() {
+            @Override
+            protected String assertionFailureMessage(Exchange exchange) {
+                return super.assertionFailureMessage(exchange);
+            }
+
+            @Override
+            public Object evaluate(Exchange exchange) {
+                Predicate predicate = null;
+                if (operator == EQ) {
+                    predicate = PredicateBuilder.isEqualTo(left, right);
+                } else if (operator == GT) {
+                    predicate = PredicateBuilder.isGreaterThan(left, right);
+                } else if (operator == GTE) {
+                    predicate = PredicateBuilder.isGreaterThanOrEqualTo(left, right);
+                } else if (operator == LT) {
+                    predicate = PredicateBuilder.isLessThan(left, right);
+                } else if (operator == LTE) {
+                    predicate = PredicateBuilder.isLessThanOrEqualTo(left, right);
+                } else if (operator == NOT) {
+                    predicate = PredicateBuilder.isNotEqualTo(left, right);
+                }
+
+                if (predicate == null) {
+                    throw new IllegalArgumentException("Unsupported operator: " + operator + " for expression: " + expression);
+                }
+                return predicate.matches(exchange);
+            }
+
+            @Override
+            public String toString() {
+                return left + " " + operator + " " + right;
+            }
+        };
+    }
+
+    protected Expression createComplexConcatExpression(String expression) {
         List<Expression> results = new ArrayList<Expression>();
 
         int pivot = 0;
@@ -74,6 +157,10 @@
         return ExpressionBuilder.constantExpression(expression.substring(start, end));
     }
 
+    protected Expression createConstantExpression(String expression) {
+        return ExpressionBuilder.constantExpression(expression);
+    }
+
     /**
      * Creates the simple expression based on the extracted content from the ${ } place holders
      *

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/util/ObjectHelper.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/util/ObjectHelper.java?rev=744707&r1=744706&r2=744707&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/util/ObjectHelper.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/util/ObjectHelper.java Sun Feb 15 17:49:04 2009
@@ -291,6 +291,28 @@
         return answer;
     }
 
+    public static String after(String text, String after) {
+        if (!text.contains(after)) {
+            return null;
+        }
+        return text.substring(text.indexOf(after) + after.length());
+    }
+
+    public static String before(String text, String before) {
+        if (!text.contains(before)) {
+            return null;
+        }
+        return text.substring(0, text.indexOf(before));
+    }
+
+    public static String between(String text, String after, String before) {
+        text = after(text, after);
+        if (text == null) {
+            return null;
+        }
+        return before(text, before);
+    }
+
     /**
      * Returns true if the collection contains the specified value
      */

Modified: camel/trunk/camel-core/src/test/java/org/apache/camel/language/BeanTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/language/BeanTest.java?rev=744707&r1=744706&r2=744707&view=diff
==============================================================================
--- camel/trunk/camel-core/src/test/java/org/apache/camel/language/BeanTest.java (original)
+++ camel/trunk/camel-core/src/test/java/org/apache/camel/language/BeanTest.java Sun Feb 15 17:49:04 2009
@@ -32,10 +32,12 @@
 
     public void testSimpleExpressions() throws Exception {
         assertExpression("foo.cheese", "abc");
+        assertExpression("foo?method=cheese", "abc");
     }
 
     public void testPredicates() throws Exception {
         assertPredicate("foo.isFooHeaderAbc");
+        assertPredicate("foo?method=isFooHeaderAbc");
     }
 
     public void testBeanTypeExpression() throws Exception {

Copied: camel/trunk/camel-core/src/test/java/org/apache/camel/language/SimpleOperatorTest.java (from r744631, camel/trunk/camel-core/src/test/java/org/apache/camel/language/SimpleTest.java)
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/language/SimpleOperatorTest.java?p2=camel/trunk/camel-core/src/test/java/org/apache/camel/language/SimpleOperatorTest.java&p1=camel/trunk/camel-core/src/test/java/org/apache/camel/language/SimpleTest.java&r1=744631&r2=744707&rev=744707&view=diff
==============================================================================
--- camel/trunk/camel-core/src/test/java/org/apache/camel/language/SimpleTest.java (original)
+++ camel/trunk/camel-core/src/test/java/org/apache/camel/language/SimpleOperatorTest.java Sun Feb 15 17:49:04 2009
@@ -16,63 +16,128 @@
  */
 package org.apache.camel.language;
 
+import org.apache.camel.Exchange;
 import org.apache.camel.LanguageTestSupport;
+import org.apache.camel.impl.JndiRegistry;
 
 /**
  * @version $Revision$
  */
-public class SimpleTest extends LanguageTestSupport {
+public class SimpleOperatorTest extends LanguageTestSupport {
 
-    public void testConstantExpression() throws Exception {
-        try {
-            assertExpression("Hello World", "Hello World");
-            fail("Should have thrown an Exception");
-        } catch (IllegalSyntaxException e) {
-            // constants is not supported
-        }
+    @Override
+    protected JndiRegistry createRegistry() throws Exception {
+        JndiRegistry jndi = super.createRegistry();
+        jndi.bind("generator", new MyFileNameGenerator());
+        return jndi;
     }
 
-    public void testSimpleExpressions() throws Exception {
-        assertExpression("id", exchange.getIn().getMessageId());
-        assertExpression("body", "<hello id='m123'>world!</hello>");
-        assertExpression("in.body", "<hello id='m123'>world!</hello>");
-        assertExpression("in.header.foo", "abc");
-        assertExpression("header.foo", "abc");
-    }
-
-    public void testComplexExpressions() throws Exception {
-        assertExpression("hey ${in.header.foo}", "hey abc");
-        assertExpression("hey ${in.header.foo}!", "hey abc!");
-        assertExpression("hey ${in.header.foo}-${in.header.foo}!", "hey abc-abc!");
-        assertExpression("hey ${in.header.foo}${in.header.foo}", "hey abcabc");
-        assertExpression("${in.header.foo}${in.header.foo}", "abcabc");
-        assertExpression("${in.header.foo}", "abc");
-        assertExpression("${in.header.foo}!", "abc!");
+    public void testEqualOperator() throws Exception {
+        // string to string comparison
+        assertExpression("${in.header.foo} == 'abc'", true);
+        assertExpression("${in.header.foo} == 'def'", false);
+        assertExpression("${in.header.foo} == '1'", false);
+
+        // integer to string comparioson
+        assertExpression("${in.header.bar} == '123'", true);
+        assertExpression("${in.header.bar} == '444'", false);
+        assertExpression("${in.header.bar} == '1'", false);
     }
 
+    public void testNotEqualOperator() throws Exception {
+        // string to string comparison
+        assertExpression("${in.header.foo} != 'abc'", false);
+        assertExpression("${in.header.foo} != 'def'", true);
+        assertExpression("${in.header.foo} != '1'", true);
 
-    public void testInvalidComplexExpression() throws Exception {
-        try {
-            assertExpression("hey ${foo", "bad expression!");
-            fail("Should have thrown an exception!");
-        } catch (IllegalArgumentException e) {
-            log.debug("Caught expected exception: " + e, e);
-        }
+        // integer to string comparioson
+        assertExpression("${in.header.bar} != '123'", false);
+        assertExpression("${in.header.bar} != '444'", true);
+        assertExpression("${in.header.bar} != '1'", true);
+    }
+
+    public void testGreatherThanOperator() throws Exception {
+        // string to string comparison
+        assertExpression("${in.header.foo} > 'aaa'", true);
+        assertExpression("${in.header.foo} > 'def'", false);
+
+        // integer to string comparioson
+        assertExpression("${in.header.bar} > '100'", true);
+        assertExpression("${in.header.bar} > '123'", false);
+        assertExpression("${in.header.bar} > '200'", false);
+    }
+
+    public void testGreatherThanOrEqualOperator() throws Exception {
+        // string to string comparison
+        assertExpression("${in.header.foo} >= 'aaa'", true);
+        assertExpression("${in.header.foo} >= 'abc'", true);
+        assertExpression("${in.header.foo} >= 'def'", false);
+
+        // integer to string comparioson
+        assertExpression("${in.header.bar} >= '100'", true);
+        assertExpression("${in.header.bar} >= '123'", true);
+        assertExpression("${in.header.bar} >= '200'", false);
+    }
+
+    public void testLessThanOperator() throws Exception {
+        // string to string comparison
+        assertExpression("${in.header.foo} < 'aaa'", false);
+        assertExpression("${in.header.foo} < 'def'", true);
+
+        // integer to string comparioson
+        assertExpression("${in.header.bar} < '100'", false);
+        assertExpression("${in.header.bar} < '123'", false);
+        assertExpression("${in.header.bar} < '200'", true);
+    }
+
+    public void testLessThanOrEqualOperator() throws Exception {
+        // string to string comparison
+        assertExpression("${in.header.foo} <= 'aaa'", false);
+        assertExpression("${in.header.foo} <= 'abc'", true);
+        assertExpression("${in.header.foo} <= 'def'", true);
+
+        // integer to string comparioson
+        assertExpression("${in.header.bar} <= '100'", false);
+        assertExpression("${in.header.bar} <= '123'", true);
+        assertExpression("${in.header.bar} <= '200'", true);
+    }
+
+    public void testIsNull() throws Exception {
+        assertExpression("${in.header.foo} == null", false);
+        assertExpression("${in.header.none} == null", true);
     }
 
-    public void testPredicates() throws Exception {
-        assertPredicate("body");
-        assertPredicate("header.foo");
-        assertPredicate("header.madeUpHeader", false);
+    public void testIsNotNull() throws Exception {
+        assertExpression("${in.header.foo} != null", true);
+        assertExpression("${in.header.none} != null", false);
     }
 
-    public void testExceptionMessage() throws Exception {
-        exchange.setException(new IllegalArgumentException("Just testing"));
-        assertExpression("exception.message", "Just testing");
-        assertExpression("Hello ${exception.message} World", "Hello Just testing World");
+    public void testRightOperatorIsSimpleLanauge() throws Exception {
+        // operator on right side is also using ${ } placeholders
+        assertExpression("${in.header.foo} == ${in.header.foo}", true);
+        assertExpression("${in.header.foo} == ${in.header.bar}", false);
+    }
+
+    public void testRightOperatorIsBeanLanauge() throws Exception {
+        // operator on right side is also using ${ } placeholders
+        assertExpression("${in.header.foo} == ${bean:generator.generateFilename}", true);
+
+        assertExpression("${in.header.bar} == ${bean:generator.generateId}", true);
+        assertExpression("${in.header.bar} >= ${bean:generator.generateId}", true);
     }
 
     protected String getLanguageName() {
         return "simple";
     }
+
+    public class MyFileNameGenerator {
+        public String generateFilename(Exchange exchange) {
+            return "abc";
+        }
+
+        public int generateId(Exchange exchange) {
+            return 123;
+        }
+    }
+
 }
\ No newline at end of file

Modified: camel/trunk/camel-core/src/test/java/org/apache/camel/util/ObjectHelperTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/util/ObjectHelperTest.java?rev=744707&r1=744706&r2=744707&view=diff
==============================================================================
--- camel/trunk/camel-core/src/test/java/org/apache/camel/util/ObjectHelperTest.java (original)
+++ camel/trunk/camel-core/src/test/java/org/apache/camel/util/ObjectHelperTest.java Sun Feb 15 17:49:04 2009
@@ -150,4 +150,22 @@
         assertEquals("c", it.next());
     }
 
+    public void testBefore() {
+        assertEquals("Hello ", ObjectHelper.before("Hello World", "World"));
+        assertEquals("Hello ", ObjectHelper.before("Hello World Again", "World"));
+        assertEquals(null, ObjectHelper.before("Hello Again", "Foo"));
+    }
+
+    public void testAfter() {
+        assertEquals(" World", ObjectHelper.after("Hello World", "Hello"));
+        assertEquals(" World Again", ObjectHelper.after("Hello World Again", "Hello"));
+        assertEquals(null, ObjectHelper.after("Hello Again", "Foo"));
+    }
+
+    public void testBetween() {
+        assertEquals("foo bar", ObjectHelper.between("Hello 'foo bar' how are you", "'", "'"));
+        assertEquals("foo bar", ObjectHelper.between("Hello ${foo bar} how are you", "${", "}"));
+        assertEquals(null, ObjectHelper.between("Hello ${foo bar} how are you", "'", "'"));
+    }
+
 }