camel-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From davscl...@apache.org
Subject svn commit: r1167462 [2/3] - in /camel/trunk/camel-core/src: main/java/org/apache/camel/builder/ main/java/org/apache/camel/language/simple/ main/java/org/apache/camel/language/simple/ast/ test/java/org/apache/camel/component/bean/ test/java/org/apache...
Date Sat, 10 Sep 2011 05:43:16 GMT
Added: camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/SimpleTokenType.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/SimpleTokenType.java?rev=1167462&view=auto
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/SimpleTokenType.java (added)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/SimpleTokenType.java Sat Sep 10 05:43:14 2011
@@ -0,0 +1,124 @@
+/**
+ * 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;
+
+/**
+ * The different token types used by the simple parser.
+ */
+public class SimpleTokenType {
+
+    private final TokenType type;
+    private final String value;
+
+    public SimpleTokenType(TokenType type, String value) {
+        this.type = type;
+        this.value = value;
+    }
+
+    /**
+     * Gets the type of this token
+     *
+     * @return the type
+     */
+    public TokenType getType() {
+        return type;
+    }
+
+    /**
+     * Gets the input value in this token
+     *
+     * @return the value
+     */
+    public String getValue() {
+        return value;
+    }
+
+    /**
+     * Whether the type is whitespace
+     */
+    public boolean isWhitespace() {
+        return type == TokenType.whiteSpace;
+    }
+
+    /**
+     * Whether the type is eol
+     */
+    public boolean isEol() {
+        return type == TokenType.eol;
+    }
+
+    /**
+     * Whether the type is single quote
+     */
+    public boolean isSingleQuote() {
+        return type == TokenType.singleQuote;
+    }
+
+    /**
+     * Whether the type is double quote
+     */
+    public boolean isDoubleQuote() {
+        return type == TokenType.doubleQuote;
+    }
+
+    /**
+     * Whether the type is a function start
+     */
+    public boolean isFunctionStart() {
+        return type == TokenType.functionStart;
+    }
+
+    /**
+     * Whether the type is a function end
+     */
+    public boolean isFunctionEnd() {
+        return type == TokenType.functionEnd;
+    }
+
+    /**
+     * Whether the type is binary operator
+     */
+    public boolean isBinary() {
+        return type == TokenType.binaryOperator;
+    }
+
+    /**
+     * Whether the type is unary operator
+     */
+    public boolean isUnary() {
+        return type == TokenType.unaryOperator;
+    }
+
+    /**
+     * Whether the type is logical operator
+     */
+    public boolean isLogical() {
+        return type == TokenType.logicalOperator;
+    }
+
+    /**
+     * Whether the type is a null value
+     */
+    public boolean isNullValue() {
+        return type == TokenType.nullValue;
+    }
+
+    @Override
+    public String toString() {
+        return value;
+    }
+}

Added: camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/SimpleTokenizer.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/SimpleTokenizer.java?rev=1167462&view=auto
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/SimpleTokenizer.java (added)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/SimpleTokenizer.java Sat Sep 10 05:43:14 2011
@@ -0,0 +1,183 @@
+/**
+ * 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;
+
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+/**
+ * Tokenizer to create {@link SimpleToken} from the input.
+ */
+public final class SimpleTokenizer {
+
+    // use CopyOnWriteArrayList so we can modify it in the for loop when changing function start/end tokens
+    private static final List<SimpleTokenType> KNOWN_TOKENS = new CopyOnWriteArrayList<SimpleTokenType>();
+
+    static {
+        // add known tokens
+        KNOWN_TOKENS.add(new SimpleTokenType(TokenType.whiteSpace, " "));
+        KNOWN_TOKENS.add(new SimpleTokenType(TokenType.singleQuote, "'"));
+        KNOWN_TOKENS.add(new SimpleTokenType(TokenType.doubleQuote, "\""));
+        KNOWN_TOKENS.add(new SimpleTokenType(TokenType.functionStart, "${"));
+        KNOWN_TOKENS.add(new SimpleTokenType(TokenType.functionStart, "$simple{"));
+        KNOWN_TOKENS.add(new SimpleTokenType(TokenType.functionEnd, "}"));
+        KNOWN_TOKENS.add(new SimpleTokenType(TokenType.booleanValue, "true"));
+        KNOWN_TOKENS.add(new SimpleTokenType(TokenType.booleanValue, "false"));
+        KNOWN_TOKENS.add(new SimpleTokenType(TokenType.nullValue, "null"));
+
+        // binary operators
+        KNOWN_TOKENS.add(new SimpleTokenType(TokenType.binaryOperator, "=="));
+        KNOWN_TOKENS.add(new SimpleTokenType(TokenType.binaryOperator, ">="));
+        KNOWN_TOKENS.add(new SimpleTokenType(TokenType.binaryOperator, "<="));
+        KNOWN_TOKENS.add(new SimpleTokenType(TokenType.binaryOperator, ">"));
+        KNOWN_TOKENS.add(new SimpleTokenType(TokenType.binaryOperator, "<"));
+        KNOWN_TOKENS.add(new SimpleTokenType(TokenType.binaryOperator, "!="));
+        KNOWN_TOKENS.add(new SimpleTokenType(TokenType.binaryOperator, "not is"));
+        KNOWN_TOKENS.add(new SimpleTokenType(TokenType.binaryOperator, "is"));
+        KNOWN_TOKENS.add(new SimpleTokenType(TokenType.binaryOperator, "not contains"));
+        KNOWN_TOKENS.add(new SimpleTokenType(TokenType.binaryOperator, "contains"));
+        KNOWN_TOKENS.add(new SimpleTokenType(TokenType.binaryOperator, "not regex"));
+        KNOWN_TOKENS.add(new SimpleTokenType(TokenType.binaryOperator, "regex"));
+        KNOWN_TOKENS.add(new SimpleTokenType(TokenType.binaryOperator, "not in"));
+        KNOWN_TOKENS.add(new SimpleTokenType(TokenType.binaryOperator, "in"));
+        KNOWN_TOKENS.add(new SimpleTokenType(TokenType.binaryOperator, "range"));
+        KNOWN_TOKENS.add(new SimpleTokenType(TokenType.binaryOperator, "not range"));
+
+        // unary operators
+        KNOWN_TOKENS.add(new SimpleTokenType(TokenType.unaryOperator, "++"));
+        KNOWN_TOKENS.add(new SimpleTokenType(TokenType.unaryOperator, "--"));
+
+        // logical operators
+        KNOWN_TOKENS.add(new SimpleTokenType(TokenType.logicalOperator, "&&"));
+        KNOWN_TOKENS.add(new SimpleTokenType(TokenType.logicalOperator, "||"));
+        // TODO: @deprecated logical operators, to be removed in Camel 3.0
+        KNOWN_TOKENS.add(new SimpleTokenType(TokenType.logicalOperator, "and"));
+        KNOWN_TOKENS.add(new SimpleTokenType(TokenType.logicalOperator, "or"));
+    }
+
+    private SimpleTokenizer() {
+        // static methods
+    }
+
+    public static void changeFunctionStartToken(String... startToken) {
+        for (SimpleTokenType type : KNOWN_TOKENS) {
+            if (type.getType() == TokenType.functionStart) {
+                KNOWN_TOKENS.remove(type);
+            }
+        }
+
+        // add in start as its a more common token to be used
+        for (String token : startToken) {
+            KNOWN_TOKENS.add(0, new SimpleTokenType(TokenType.functionStart, token));
+        }
+    }
+
+    public static void changeFunctionEndToken(String... endToken) {
+        for (SimpleTokenType type : KNOWN_TOKENS) {
+            if (type.getType() == TokenType.functionEnd) {
+                KNOWN_TOKENS.remove(type);
+            }
+        }
+
+        // add in start as its a more common token to be used
+        for (String token : endToken) {
+            KNOWN_TOKENS.add(0, new SimpleTokenType(TokenType.functionEnd, token));
+        }
+    }
+
+    /**
+     * Create the next token
+     *
+     * @param expression  the input expression
+     * @param index       the current index
+     * @param filter      defines the accepted token types to be returned (character is always used as fallback)
+     * @return the created token, will always return a token
+     */
+    public static SimpleToken nextToken(String expression, int index, TokenType... filter) {
+        return doNextToken(expression, index, filter);
+    }
+
+    /**
+     * Create the next token
+     *
+     * @param expression  the input expression
+     * @param index       the current index
+     * @return the created token, will always return a token
+     */
+    public static SimpleToken nextToken(String expression, int index) {
+        return doNextToken(expression, index);
+    }
+
+    private static SimpleToken doNextToken(String expression, int index, TokenType... filters) {
+
+        boolean escapedAllowed = acceptType(TokenType.escapedValue, filters);
+        if (escapedAllowed) {
+            // is it an escaped value
+            if (expression.charAt(index) == '\\' && index < expression.length() - 1) {
+                String text = "" + expression.charAt(index + 1);
+                // use 2 as length for escaped as we need to jump to the next symbol
+                return new SimpleToken(new SimpleTokenType(TokenType.escapedValue, text), index, 2);
+            }
+        }
+
+        boolean numericAllowed = acceptType(TokenType.numericValue, filters);
+        if (numericAllowed) {
+            // is it a numeric value
+            StringBuilder sb = new StringBuilder();
+            boolean digit = true;
+            while (digit && index < expression.length()) {
+                digit = Character.isDigit(expression.charAt(index));
+                if (digit) {
+                    char ch = expression.charAt(index);
+                    sb.append(ch);
+                    index++;
+                }
+            }
+            if (sb.length() > 0) {
+                return new SimpleToken(new SimpleTokenType(TokenType.numericValue, sb.toString()), index);
+            }
+        }
+
+        // it could be any of the known tokens
+        String text = expression.substring(index);
+        for (SimpleTokenType token : KNOWN_TOKENS) {
+            if (acceptType(token.getType(), filters)) {
+                if (text.startsWith(token.getValue())) {
+                    return new SimpleToken(token, index);
+                }
+            }
+        }
+
+        // fallback and create a character token
+        char ch = expression.charAt(index);
+        SimpleToken token = new SimpleToken(new SimpleTokenType(TokenType.character, "" + ch), index);
+        return token;
+    }
+
+    private static boolean acceptType(TokenType type, TokenType... filters) {
+        if (filters == null || filters.length == 0) {
+            return true;
+        }
+        for (TokenType filter : filters) {
+            if (type == filter) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+}

Added: camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/TokenType.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/TokenType.java?rev=1167462&view=auto
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/TokenType.java (added)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/TokenType.java Sat Sep 10 05:43:14 2011
@@ -0,0 +1,31 @@
+/**
+ * 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;
+
+/**
+ * Classifications of known token types.
+ */
+public enum TokenType {
+
+    whiteSpace, character,
+    escapedValue, booleanValue, numericValue, nullValue,
+    singleQuote, doubleQuote,
+    functionStart, functionEnd,
+    binaryOperator, unaryOperator, logicalOperator,
+    eol;
+
+}

Added: camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/UnaryOperatorType.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/UnaryOperatorType.java?rev=1167462&view=auto
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/UnaryOperatorType.java (added)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/UnaryOperatorType.java Sat Sep 10 05:43:14 2011
@@ -0,0 +1,52 @@
+/**
+ * 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;
+
+/**
+ * Types of unary operators supported.
+ * <p/>
+ * An unary operator can only work on the left hand side, which means the operator
+ * should be defined directly <i>after</i> the function it should work upon.
+ */
+public enum UnaryOperatorType {
+
+    INC, DEC;
+
+    public static UnaryOperatorType asOperator(String text) {
+        if ("++".equals(text)) {
+            return INC;
+        } else if ("--".equals(text)) {
+            return DEC;
+        }
+        throw new IllegalArgumentException("Operator not supported: " + text);
+    }
+
+    public String getOperatorText(UnaryOperatorType operator) {
+        if (operator == INC) {
+            return "++";
+        } else if (operator == DEC) {
+            return "--";
+        }
+        return "";
+    }
+
+    @Override
+    public String toString() {
+        return getOperatorText(this);
+    }
+
+}

Added: camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/BaseSimpleNode.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/BaseSimpleNode.java?rev=1167462&view=auto
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/BaseSimpleNode.java (added)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/BaseSimpleNode.java Sat Sep 10 05:43:14 2011
@@ -0,0 +1,40 @@
+/**
+ * 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.ast;
+
+import org.apache.camel.language.simple.SimpleToken;
+
+/**
+ * Base class for {@link SimpleNode} nodes.
+ */
+public abstract class BaseSimpleNode implements SimpleNode {
+
+    protected final SimpleToken token;
+
+    protected BaseSimpleNode(SimpleToken token) {
+        this.token = token;
+    }
+
+    public SimpleToken getToken() {
+        return token;
+    }
+
+    @Override
+    public String toString() {
+        return token.getText();
+    }
+}

Added: camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/BinaryExpression.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/BinaryExpression.java?rev=1167462&view=auto
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/BinaryExpression.java (added)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/BinaryExpression.java Sat Sep 10 05:43:14 2011
@@ -0,0 +1,238 @@
+/**
+ * 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.ast;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+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.builder.ValueBuilder;
+import org.apache.camel.language.simple.BinaryOperatorType;
+import org.apache.camel.language.simple.SimpleIllegalSyntaxException;
+import org.apache.camel.language.simple.SimpleParserException;
+import org.apache.camel.language.simple.SimpleToken;
+import org.apache.camel.util.ObjectHelper;
+
+/**
+ * Represents a binary expression in the AST.
+ */
+public class BinaryExpression extends BaseSimpleNode {
+
+    // this is special for the range operator where you define the range as from..to (where from and to are numbers)
+    private static final Pattern RANGE_PATTERN = Pattern.compile("^(\\d+)(\\.\\.)(\\d+)$");
+
+    private final BinaryOperatorType operator;
+    private SimpleNode left;
+    private SimpleNode right;
+
+    public BinaryExpression(SimpleToken token) {
+        super(token);
+        operator = BinaryOperatorType.asOperator(token.getText());
+    }
+
+    @Override
+    public String toString() {
+        return left + " " + token.getText() + " " + right;
+    }
+
+    public boolean acceptLeftNode(SimpleNode lef) {
+        this.left = lef;
+        return true;
+    }
+
+    public boolean acceptRightNode(SimpleNode right) {
+        this.right = right;
+        return true;
+    }
+
+    public BinaryOperatorType getOperator() {
+        return operator;
+    }
+
+    @Override
+    public Expression createExpression(String expression) {
+        ObjectHelper.notNull(left, "left node", this);
+        ObjectHelper.notNull(right, "right node", this);
+
+        final Expression leftExp = left.createExpression(expression);
+        final Expression rightExp = right.createExpression(expression);
+
+        if (operator == BinaryOperatorType.EQ) {
+            return createExpression(leftExp, rightExp, PredicateBuilder.isEqualTo(leftExp, rightExp));
+        } else if (operator == BinaryOperatorType.GT) {
+            return createExpression(leftExp, rightExp, PredicateBuilder.isGreaterThan(leftExp, rightExp));
+        } else if (operator == BinaryOperatorType.GTE) {
+            return createExpression(leftExp, rightExp, PredicateBuilder.isGreaterThanOrEqualTo(leftExp, rightExp));
+        } else if (operator == BinaryOperatorType.LT) {
+            return createExpression(leftExp, rightExp, PredicateBuilder.isLessThan(leftExp, rightExp));
+        } else if (operator == BinaryOperatorType.LTE) {
+            return createExpression(leftExp, rightExp, PredicateBuilder.isLessThanOrEqualTo(leftExp, rightExp));
+        } else if (operator == BinaryOperatorType.NOT_EQ) {
+            return createExpression(leftExp, rightExp, PredicateBuilder.isNotEqualTo(leftExp, rightExp));
+        } else if (operator == BinaryOperatorType.CONTAINS) {
+            return createExpression(leftExp, rightExp, PredicateBuilder.contains(leftExp, rightExp));
+        } else if (operator == BinaryOperatorType.NOT_CONTAINS) {
+            return createExpression(leftExp, rightExp, PredicateBuilder.not(PredicateBuilder.contains(leftExp, rightExp)));
+        } else if (operator == BinaryOperatorType.IS || operator == BinaryOperatorType.NOT_IS) {
+            return createIsExpression(expression, leftExp, rightExp);
+        } else if (operator == BinaryOperatorType.REGEX || operator == BinaryOperatorType.NOT_REGEX) {
+            return createRegexExpression(leftExp, rightExp);
+        } else if (operator == BinaryOperatorType.IN || operator == BinaryOperatorType.NOT_IN) {
+            return createInExpression(leftExp, rightExp);
+        } else if (operator == BinaryOperatorType.RANGE || operator == BinaryOperatorType.NOT_RANGE) {
+            return createRangeExpression(expression, leftExp, rightExp);
+        }
+
+        throw new SimpleParserException("Unknown binary operator " + operator, token.getIndex());
+    }
+
+    private Expression createIsExpression(final String expression, final Expression leftExp, final Expression rightExp) {
+        return new Expression() {
+            @Override
+            public <T> T evaluate(Exchange exchange, Class<T> type) {
+                Predicate predicate;
+                String name = rightExp.evaluate(exchange, String.class);
+                if (name == null || "null".equals(name)) {
+                    throw new SimpleIllegalSyntaxException(expression, right.getToken().getIndex(), operator + " operator cannot accept null. A class type must be provided.");
+                }
+                Class<?> rightType = exchange.getContext().getClassResolver().resolveClass(name);
+                if (rightType == null) {
+                    throw new SimpleIllegalSyntaxException(expression, right.getToken().getIndex(), operator + " operator cannot find class with name: " + name);
+                }
+
+                predicate = PredicateBuilder.isInstanceOf(leftExp, rightType);
+                if (operator == BinaryOperatorType.NOT_IS) {
+                    predicate = PredicateBuilder.not(predicate);
+                }
+                boolean answer = predicate.matches(exchange);
+
+                return exchange.getContext().getTypeConverter().convertTo(type, answer);
+            }
+
+            @Override
+            public String toString() {
+                return left + " " + token.getText() + " " + right;
+            }
+        };
+    }
+
+    private Expression createRegexExpression(final Expression leftExp, final Expression rightExp) {
+        return new Expression() {
+            @Override
+            public <T> T evaluate(Exchange exchange, Class<T> type) {
+                // reg ex should use String pattern, so we evaluate the right hand side as a String
+                Predicate predicate = PredicateBuilder.regex(leftExp, rightExp.evaluate(exchange, String.class));
+                if (operator == BinaryOperatorType.NOT_REGEX) {
+                    predicate = PredicateBuilder.not(predicate);
+                }
+                boolean answer = predicate.matches(exchange);
+                return exchange.getContext().getTypeConverter().convertTo(type, answer);
+            }
+
+            @Override
+            public String toString() {
+                return left + " " + token.getText() + " " + right;
+            }
+        };
+    }
+
+    private Expression createInExpression(final Expression leftExp, final Expression rightExp) {
+        return new Expression() {
+            @Override
+            public <T> T evaluate(Exchange exchange, Class<T> type) {
+                // okay the in operator is a bit more complex as we need to build a list of values
+                // from the right hand side expression.
+                // each element on the right hand side must be separated by comma (default for create iterator)
+                Iterator<Object> it = ObjectHelper.createIterator(rightExp.evaluate(exchange, Object.class));
+                List<Object> values = new ArrayList<Object>();
+                while (it.hasNext()) {
+                    values.add(it.next());
+                }
+                // then reuse value builder to create the in predicate with the list of values
+                ValueBuilder vb = new ValueBuilder(leftExp);
+                Predicate predicate = vb.in(values.toArray());
+                if (operator == BinaryOperatorType.NOT_IN) {
+                    predicate = PredicateBuilder.not(predicate);
+                }
+                boolean answer = predicate.matches(exchange);
+                return exchange.getContext().getTypeConverter().convertTo(type, answer);
+            }
+
+            @Override
+            public String toString() {
+                return left + " " + token.getText() + " " + right;
+            }
+        };
+    }
+
+    private Expression createRangeExpression(final String expression, final Expression leftExp, final Expression rightExp) {
+        return new Expression() {
+            @Override
+            public <T> T evaluate(Exchange exchange, Class<T> type) {
+                Predicate predicate;
+
+                String range = rightExp.evaluate(exchange, String.class);
+                Matcher matcher = RANGE_PATTERN.matcher(range);
+                if (matcher.matches()) {
+                    // wrap as constant expression for the from and to values
+                    Expression from = ExpressionBuilder.constantExpression(matcher.group(1));
+                    Expression to = ExpressionBuilder.constantExpression(matcher.group(3));
+
+                    // build a compound predicate for the range
+                    predicate = PredicateBuilder.isGreaterThanOrEqualTo(leftExp, from);
+                    predicate = PredicateBuilder.and(predicate, PredicateBuilder.isLessThanOrEqualTo(leftExp, to));
+                } else {
+                    throw new SimpleIllegalSyntaxException(expression, right.getToken().getIndex(), operator + " operator is not valid. Valid syntax:'from..to' (where from and to are numbers).");
+                }
+                if (operator == BinaryOperatorType.NOT_RANGE) {
+                    predicate = PredicateBuilder.not(predicate);
+                }
+
+                boolean answer = predicate.matches(exchange);
+                return exchange.getContext().getTypeConverter().convertTo(type, answer);
+            }
+
+            @Override
+            public String toString() {
+                return left + " " + token.getText() + " " + right;
+            }
+        };
+    }
+
+    private Expression createExpression(final Expression left, final Expression right, final Predicate predicate) {
+        return new Expression() {
+            @Override
+            public <T> T evaluate(Exchange exchange, Class<T> type) {
+                boolean answer = predicate.matches(exchange);
+                return exchange.getContext().getTypeConverter().convertTo(type, answer);
+            }
+
+            @Override
+            public String toString() {
+                return left + " " + token.getText() + " " + right;
+            }
+        };
+    }
+
+}

Added: camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/Block.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/Block.java?rev=1167462&view=auto
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/Block.java (added)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/Block.java Sat Sep 10 05:43:14 2011
@@ -0,0 +1,35 @@
+/**
+ * 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.ast;
+
+/**
+ * A model which is a block, containing other nodes.
+ * <p/>
+ * This node will keep adding other nodes until no longer
+ * accepted, by returning <tt>false</tt> in the {@link #acceptAndAddNode(SimpleNode)} method.
+ */
+public interface Block extends SimpleNode {
+
+    /**
+     * Whether to accept and add the given node in this block.
+     *
+     * @param node the other node.
+     * @return <tt>true</tt> to accept and add to this block, <tt>false</tt> to end this block.
+     */
+    boolean acceptAndAddNode(SimpleNode node);
+
+}

Added: camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/BlockEnd.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/BlockEnd.java?rev=1167462&view=auto
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/BlockEnd.java (added)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/BlockEnd.java Sat Sep 10 05:43:14 2011
@@ -0,0 +1,23 @@
+/**
+ * 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.ast;
+
+/**
+ * Marks an end of a block.
+ */
+public interface BlockEnd {
+}

Added: camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/BlockStart.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/BlockStart.java?rev=1167462&view=auto
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/BlockStart.java (added)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/BlockStart.java Sat Sep 10 05:43:14 2011
@@ -0,0 +1,23 @@
+/**
+ * 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.ast;
+
+/**
+ * Marks a start of a block.
+ */
+public interface BlockStart extends Block {
+}

Added: camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/CompositeNodes.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/CompositeNodes.java?rev=1167462&view=auto
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/CompositeNodes.java (added)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/CompositeNodes.java Sat Sep 10 05:43:14 2011
@@ -0,0 +1,65 @@
+/**
+ * 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.ast;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.camel.Expression;
+import org.apache.camel.builder.ExpressionBuilder;
+import org.apache.camel.language.simple.SimpleToken;
+
+/**
+ * A node which contains other {@link SimpleNode nodes}.
+ */
+public class CompositeNodes extends BaseSimpleNode {
+
+    private final List<SimpleNode> children = new ArrayList<SimpleNode>();
+
+    public CompositeNodes(SimpleToken token) {
+        super(token);
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        for (SimpleNode child : children) {
+            sb.append(child.toString());
+        }
+        return sb.toString();
+    }
+
+    public void addChild(SimpleNode child) {
+        children.add(child);
+    }
+
+    @Override
+    public Expression createExpression(String expression) {
+        if (children.isEmpty()) {
+            return null;
+        } else if (children.size() == 1) {
+            return children.get(0).createExpression(expression);
+        } else {
+            List<Expression> answer = new ArrayList<Expression>();
+            for (SimpleNode child : children) {
+                answer.add(child.createExpression(expression));
+            }
+            return ExpressionBuilder.concatExpression(answer);
+        }
+    }
+
+}

Added: camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/DoubleQuoteEnd.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/DoubleQuoteEnd.java?rev=1167462&view=auto
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/DoubleQuoteEnd.java (added)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/DoubleQuoteEnd.java Sat Sep 10 05:43:14 2011
@@ -0,0 +1,36 @@
+/**
+ * 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.ast;
+
+import org.apache.camel.Expression;
+import org.apache.camel.language.simple.SimpleToken;
+
+/**
+ * Ends a block enclosed by double quotes
+ */
+public class DoubleQuoteEnd extends BaseSimpleNode implements BlockEnd {
+
+    public DoubleQuoteEnd(SimpleToken token) {
+        super(token);
+    }
+
+    @Override
+    public Expression createExpression(String expression) {
+        return null;
+    }
+
+}

Added: camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/DoubleQuoteStart.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/DoubleQuoteStart.java?rev=1167462&view=auto
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/DoubleQuoteStart.java (added)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/DoubleQuoteStart.java Sat Sep 10 05:43:14 2011
@@ -0,0 +1,55 @@
+/**
+ * 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.ast;
+
+import org.apache.camel.Expression;
+import org.apache.camel.language.simple.SimpleToken;
+
+/**
+ * Starts a block enclosed by double quotes
+ */
+public class DoubleQuoteStart extends BaseSimpleNode implements BlockStart {
+
+    private final CompositeNodes block;
+
+    public DoubleQuoteStart(SimpleToken token) {
+        super(token);
+        this.block = new CompositeNodes(token);
+    }
+
+    @Override
+    public String toString() {
+        // output a nice toString so it makes debugging easier as we can see the entire block
+        return "\"" + block + "\"";
+    }
+
+    @Override
+    public Expression createExpression(String expression) {
+        if (block != null) {
+            return block.createExpression(expression);
+        } else {
+            return null;
+        }
+    }
+
+    @Override
+    public boolean acceptAndAddNode(SimpleNode node) {
+        block.addChild(node);
+        return true;
+    }
+
+}

Added: camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/LiteralExpression.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/LiteralExpression.java?rev=1167462&view=auto
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/LiteralExpression.java (added)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/LiteralExpression.java Sat Sep 10 05:43:14 2011
@@ -0,0 +1,53 @@
+/**
+ * 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.ast;
+
+import org.apache.camel.Expression;
+import org.apache.camel.builder.ExpressionBuilder;
+import org.apache.camel.language.simple.SimpleToken;
+
+/**
+ * Represents literals in the AST.
+ */
+public class LiteralExpression extends BaseSimpleNode implements LiteralNode {
+
+    protected StringBuilder text = new StringBuilder();
+
+    public LiteralExpression(SimpleToken token) {
+        super(token);
+    }
+
+    @Override
+    public String toString() {
+        return getText();
+    }
+
+    @Override
+    public void addText(String text) {
+        this.text.append(text);
+    }
+
+    @Override
+    public String getText() {
+        return text.toString();
+    }
+
+    @Override
+    public Expression createExpression(String expression) {
+        return ExpressionBuilder.constantExpression(getText());
+    }
+}

Added: camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/LiteralNode.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/LiteralNode.java?rev=1167462&view=auto
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/LiteralNode.java (added)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/LiteralNode.java Sat Sep 10 05:43:14 2011
@@ -0,0 +1,40 @@
+/**
+ * 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.ast;
+
+/**
+ * Represents a node in the AST which contains literals
+ */
+public interface LiteralNode extends SimpleNode {
+
+    /**
+     * Adds the given text to this model.
+     * <p/>
+     * This operation can be invoked multiple times to add more text.
+     *
+     * @param text the text to add
+     */
+    void addText(String text);
+
+    /**
+     * Gets the text
+     *
+     * @return the text, will never be <tt>null</tt>, but may contain an empty string.
+     */
+    String getText();
+
+}

Added: camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/LogicalExpression.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/LogicalExpression.java?rev=1167462&view=auto
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/LogicalExpression.java (added)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/LogicalExpression.java Sat Sep 10 05:43:14 2011
@@ -0,0 +1,114 @@
+/**
+ * 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.ast;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Expression;
+import org.apache.camel.Predicate;
+import org.apache.camel.builder.PredicateBuilder;
+import org.apache.camel.language.simple.LogicalOperatorType;
+import org.apache.camel.language.simple.SimpleParserException;
+import org.apache.camel.language.simple.SimpleToken;
+import org.apache.camel.util.ObjectHelper;
+
+/**
+ * Represents a logical expression in the AST
+ */
+public class LogicalExpression extends BaseSimpleNode {
+
+    private LogicalOperatorType operator;
+    private SimpleNode left;
+    private SimpleNode right;
+
+    public LogicalExpression(SimpleToken token) {
+        super(token);
+        operator = LogicalOperatorType.asOperator(token.getText());
+    }
+
+    @Override
+    public String toString() {
+        return left + " " + token.getText() + " " + right;
+    }
+
+    public boolean acceptLeftNode(SimpleNode lef) {
+        this.left = lef;
+        return true;
+    }
+
+    public boolean acceptRightNode(SimpleNode right) {
+        this.right = right;
+        return true;
+    }
+
+    public LogicalOperatorType getOperator() {
+        return operator;
+    }
+
+    @Override
+    public Expression createExpression(String expression) {
+        ObjectHelper.notNull(left, "left node", this);
+        ObjectHelper.notNull(right, "right node", this);
+
+        final Expression leftExp = left.createExpression(expression);
+        final Expression rightExp = right.createExpression(expression);
+
+        if (operator == LogicalOperatorType.AND) {
+            return createAndExpression(leftExp, rightExp);
+        } else if (operator == LogicalOperatorType.OR) {
+            return createOrExpression(leftExp, rightExp);
+        }
+
+        throw new SimpleParserException("Unknown logical operator " + operator, token.getIndex());
+    }
+
+    private Expression createAndExpression(final Expression leftExp, final Expression rightExp) {
+        return new Expression() {
+            @Override
+            public <T> T evaluate(Exchange exchange, Class<T> type) {
+                Predicate predicate = PredicateBuilder.toPredicate(leftExp);
+                predicate = PredicateBuilder.and(predicate, PredicateBuilder.toPredicate(rightExp));
+
+                boolean answer = predicate.matches(exchange);
+                return exchange.getContext().getTypeConverter().convertTo(type, answer);
+            }
+
+            @Override
+            public String toString() {
+                return left + " " + token.getText() + " " + right;
+            }
+        };
+    }
+
+    private Expression createOrExpression(final Expression leftExp, final Expression rightExp) {
+        return new Expression() {
+            @Override
+            public <T> T evaluate(Exchange exchange, Class<T> type) {
+                Predicate predicate = PredicateBuilder.toPredicate(leftExp);
+                predicate = PredicateBuilder.or(predicate, PredicateBuilder.toPredicate(rightExp));
+
+                boolean answer = predicate.matches(exchange);
+                return exchange.getContext().getTypeConverter().convertTo(type, answer);
+            }
+
+            @Override
+            public String toString() {
+                return left + " " + token.getText() + " " + right;
+            }
+        };
+    }
+
+}

Added: camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/NullExpression.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/NullExpression.java?rev=1167462&view=auto
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/NullExpression.java (added)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/NullExpression.java Sat Sep 10 05:43:14 2011
@@ -0,0 +1,47 @@
+/**
+ * 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.ast;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Expression;
+import org.apache.camel.language.simple.SimpleParserException;
+import org.apache.camel.language.simple.SimpleToken;
+
+/**
+ * Represents a null expression.
+ */
+public class NullExpression extends BaseSimpleNode {
+
+    public NullExpression(SimpleToken token) {
+        super(token);
+    }
+
+    @Override
+    public Expression createExpression(String expression) throws SimpleParserException {
+        return new Expression() {
+            @Override
+            public <T> T evaluate(Exchange exchange, Class<T> type) {
+                return null;
+            }
+
+            @Override
+            public String toString() {
+                return "null";
+            }
+        };
+    }
+}

Added: camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionEnd.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionEnd.java?rev=1167462&view=auto
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionEnd.java (added)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionEnd.java Sat Sep 10 05:43:14 2011
@@ -0,0 +1,36 @@
+/**
+ * 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.ast;
+
+import org.apache.camel.Expression;
+import org.apache.camel.language.simple.SimpleToken;
+
+/**
+ * Ends a function
+ */
+public class SimpleFunctionEnd extends BaseSimpleNode implements BlockEnd {
+
+    public SimpleFunctionEnd(SimpleToken token) {
+        super(token);
+    }
+
+    @Override
+    public Expression createExpression(String expression) {
+        return null;
+    }
+
+}

Added: camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionExpression.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionExpression.java?rev=1167462&view=auto
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionExpression.java (added)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionExpression.java Sat Sep 10 05:43:14 2011
@@ -0,0 +1,322 @@
+/**
+ * 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.ast;
+
+import org.apache.camel.Expression;
+import org.apache.camel.builder.ExpressionBuilder;
+import org.apache.camel.language.simple.SimpleParserException;
+import org.apache.camel.language.simple.SimpleToken;
+import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.util.OgnlHelper;
+import org.apache.camel.util.StringHelper;
+
+/**
+ * Represents one of built-in functions of the
+ * <a href="http://camel.apache.org/simple.html">simple language</a>
+ */
+public class SimpleFunctionExpression extends LiteralExpression {
+
+    public SimpleFunctionExpression(SimpleToken token) {
+        super(token);
+    }
+
+    @Override
+    public Expression createExpression(String expression) {
+        String function = text.toString();
+        return createSimpleExpression(function, true);
+    }
+
+    /**
+     * Creates a Camel {@link Expression} based on this model.
+     *
+     * @param expression the input string
+     * @param strict whether to throw exception if the expression was not a function,
+     *          otherwise <tt>null</tt> is returned
+     * @return the created {@link Expression}
+     * @throws org.apache.camel.language.simple.SimpleParserException
+     *          should be thrown if error parsing the model
+     */
+    public Expression createExpression(String expression, boolean strict) {
+        String function = text.toString();
+        return createSimpleExpression(function, strict);
+    }
+
+    private Expression createSimpleExpression(String function, boolean strict) {
+        // return the function directly if we can create function without analyzing the prefix
+        Expression answer = createSimpleExpressionDirectly(function);
+        if (answer != null) {
+            return answer;
+        }
+
+        // bodyAs
+        String remainder = ifStartsWithReturnRemainder("bodyAs", function);
+        if (remainder != null) {
+            String type = ObjectHelper.between(remainder, "(", ")");
+            if (type == null) {
+                throw new SimpleParserException("Valid syntax: ${bodyAs(type)} was: " + function, token.getIndex());
+            }
+            type = StringHelper.removeQuotes(type);
+            return ExpressionBuilder.bodyExpression(type);
+        }
+        // mandatoryBodyAs
+        remainder = ifStartsWithReturnRemainder("mandatoryBodyAs", function);
+        if (remainder != null) {
+            String type = ObjectHelper.between(remainder, "(", ")");
+            if (type == null) {
+                throw new SimpleParserException("Valid syntax: ${mandatoryBodyAs(type)} was: " + function, token.getIndex());
+            }
+            type = StringHelper.removeQuotes(type);
+            return ExpressionBuilder.mandatoryBodyExpression(type);
+        }
+
+        // body OGNL
+        remainder = ifStartsWithReturnRemainder("body", function);
+        if (remainder == null) {
+            remainder = ifStartsWithReturnRemainder("in.body", function);
+        }
+        if (remainder != null) {
+            boolean invalid = OgnlHelper.isInvalidValidOgnlExpression(remainder);
+            if (invalid) {
+                throw new SimpleParserException("Valid syntax: ${body.OGNL} was: " + function, token.getIndex());
+            }
+            return ExpressionBuilder.bodyOgnlExpression(remainder);
+        }
+
+        // Exception OGNL
+        remainder = ifStartsWithReturnRemainder("exception", function);
+        if (remainder != null) {
+            boolean invalid = OgnlHelper.isInvalidValidOgnlExpression(remainder);
+            if (invalid) {
+                throw new SimpleParserException("Valid syntax: ${exception.OGNL} was: " + function, token.getIndex());
+            }
+            return ExpressionBuilder.exchangeExceptionOgnlExpression(remainder);
+        }
+
+        // headerAs
+        remainder = ifStartsWithReturnRemainder("headerAs", function);
+        if (remainder != null) {
+            String keyAndType = ObjectHelper.between(remainder, "(", ")");
+            if (keyAndType == null) {
+                throw new SimpleParserException("Valid syntax: ${headerAs(key, type)} was: " + function, token.getIndex());
+            }
+
+            String key = ObjectHelper.before(keyAndType, ",");
+            String type = ObjectHelper.after(keyAndType, ",");
+            if (ObjectHelper.isEmpty(key) || ObjectHelper.isEmpty(type)) {
+                throw new SimpleParserException("Valid syntax: ${headerAs(key, type)} was: " + function, token.getIndex());
+            }
+            key = StringHelper.removeQuotes(key);
+            type = StringHelper.removeQuotes(type);
+            return ExpressionBuilder.headerExpression(key, type);
+        }
+
+        // headers function
+        if ("in.headers".equals(function) || "headers".equals(function)) {
+            return ExpressionBuilder.headersExpression();
+        }
+
+        // in header function
+        remainder = ifStartsWithReturnRemainder("in.headers", function);
+        if (remainder == null) {
+            remainder = ifStartsWithReturnRemainder("in.header", function);
+        }
+        if (remainder == null) {
+            remainder = ifStartsWithReturnRemainder("headers", function);
+        }
+        if (remainder == null) {
+            remainder = ifStartsWithReturnRemainder("header", function);
+        }
+        if (remainder != null) {
+            // remove leading character (dot or ?)
+            remainder = remainder.substring(1);
+
+            // validate syntax
+            boolean invalid = OgnlHelper.isInvalidValidOgnlExpression(remainder);
+            if (invalid) {
+                throw new SimpleParserException("Valid syntax: ${header.name[key]} was: " + function, token.getIndex());
+            }
+
+            if (OgnlHelper.isValidOgnlExpression(remainder)) {
+                // ognl based header
+                return ExpressionBuilder.headersOgnlExpression(remainder);
+            } else {
+                // regular header
+                return ExpressionBuilder.headerExpression(remainder);
+            }
+        }
+
+        // out header function
+        remainder = ifStartsWithReturnRemainder("out.header.", function);
+        if (remainder == null) {
+            remainder = ifStartsWithReturnRemainder("out.headers.", function);
+        }
+        if (remainder != null) {
+            return ExpressionBuilder.outHeaderExpression(remainder);
+        }
+
+        // property
+        remainder = ifStartsWithReturnRemainder("property", function);
+        if (remainder != null) {
+            // remove leading character (dot or ?)
+            remainder = remainder.substring(1);
+
+            // validate syntax
+            boolean invalid = OgnlHelper.isInvalidValidOgnlExpression(remainder);
+            if (invalid) {
+                throw new SimpleParserException("Valid syntax: ${property.OGNL} was: " + function, token.getIndex());
+            }
+
+            if (OgnlHelper.isValidOgnlExpression(remainder)) {
+                // ognl based property
+                return ExpressionBuilder.propertyOgnlExpression(remainder);
+            } else {
+                // regular property
+                return ExpressionBuilder.propertyExpression(remainder);
+            }
+        }
+
+        // system property
+        remainder = ifStartsWithReturnRemainder("sys.", function);
+        if (remainder != null) {
+            return ExpressionBuilder.systemPropertyExpression(remainder);
+        }
+
+        // system property
+        remainder = ifStartsWithReturnRemainder("sysenv.", function);
+        if (remainder != null) {
+            return ExpressionBuilder.systemEnvironmentExpression(remainder);
+        }
+
+        // file: prefix
+        remainder = ifStartsWithReturnRemainder("file:", function);
+        if (remainder != null) {
+            Expression fileExpression = createSimpleFileExpression(remainder);
+            if (function != null) {
+                return fileExpression;
+            }
+        }
+
+        // date: prefix
+        remainder = ifStartsWithReturnRemainder("date:", function);
+        if (remainder != null) {
+            String[] parts = remainder.split(":");
+            if (parts.length < 2) {
+                throw new SimpleParserException("Valid syntax: ${date:command:pattern} was: " + function, token.getIndex());
+            }
+            String command = ObjectHelper.before(remainder, ":");
+            String pattern = ObjectHelper.after(remainder, ":");
+            return ExpressionBuilder.dateExpression(command, pattern);
+        }
+
+        // bean: prefix
+        remainder = ifStartsWithReturnRemainder("bean:", function);
+        if (remainder != null) {
+            return ExpressionBuilder.beanExpression(remainder);
+        }
+
+        // properties: prefix
+        remainder = ifStartsWithReturnRemainder("properties:", function);
+        if (remainder != null) {
+            String[] parts = remainder.split(":");
+            if (parts.length > 2) {
+                throw new SimpleParserException("Valid syntax: ${properties:[locations]:key} was: " + function, token.getIndex());
+            }
+
+            String locations = null;
+            String key = remainder;
+            if (parts.length == 2) {
+                locations = ObjectHelper.before(remainder, ":");
+                key = ObjectHelper.after(remainder, ":");
+            }
+            return ExpressionBuilder.propertiesComponentExpression(key, locations);
+        }
+
+        // ref: prefix
+        remainder = ifStartsWithReturnRemainder("ref:", function);
+        if (remainder != null) {
+            return ExpressionBuilder.refExpression(remainder);
+        }
+
+        if (strict) {
+            throw new SimpleParserException("Unknown function: " + function, token.getIndex());
+        } else {
+            return null;
+        }
+    }
+
+    private Expression createSimpleExpressionDirectly(String expression) {
+        if (ObjectHelper.isEqualToAny(expression, "body", "in.body")) {
+            return ExpressionBuilder.bodyExpression();
+        } else if (ObjectHelper.equal(expression, "out.body")) {
+            return ExpressionBuilder.outBodyExpression();
+        } else if (ObjectHelper.equal(expression, "id")) {
+            return ExpressionBuilder.messageIdExpression();
+        } else if (ObjectHelper.equal(expression, "exchangeId")) {
+            return ExpressionBuilder.exchangeIdExpression();
+        } else if (ObjectHelper.equal(expression, "exception")) {
+            return ExpressionBuilder.exchangeExceptionExpression();
+        } else if (ObjectHelper.equal(expression, "exception.message")) {
+            return ExpressionBuilder.exchangeExceptionMessageExpression();
+        } else if (ObjectHelper.equal(expression, "exception.stacktrace")) {
+            return ExpressionBuilder.exchangeExceptionStackTraceExpression();
+        } else if (ObjectHelper.equal(expression, "threadName")) {
+            return ExpressionBuilder.threadNameExpression();
+        }
+
+        return null;
+    }
+
+    private Expression createSimpleFileExpression(String remainder) {
+        if (ObjectHelper.equal(remainder, "name")) {
+            return ExpressionBuilder.fileNameExpression();
+        } else if (ObjectHelper.equal(remainder, "name.noext")) {
+            return ExpressionBuilder.fileNameNoExtensionExpression();
+        } else if (ObjectHelper.equal(remainder, "name.ext")) {
+            return ExpressionBuilder.fileExtensionExpression();
+        } else if (ObjectHelper.equal(remainder, "onlyname")) {
+            return ExpressionBuilder.fileOnlyNameExpression();
+        } else if (ObjectHelper.equal(remainder, "onlyname.noext")) {
+            return ExpressionBuilder.fileOnlyNameNoExtensionExpression();
+        } else if (ObjectHelper.equal(remainder, "ext")) {
+            return ExpressionBuilder.fileExtensionExpression();
+        } else if (ObjectHelper.equal(remainder, "parent")) {
+            return ExpressionBuilder.fileParentExpression();
+        } else if (ObjectHelper.equal(remainder, "path")) {
+            return ExpressionBuilder.filePathExpression();
+        } else if (ObjectHelper.equal(remainder, "absolute")) {
+            return ExpressionBuilder.fileAbsoluteExpression();
+        } else if (ObjectHelper.equal(remainder, "absolute.path")) {
+            return ExpressionBuilder.fileAbsolutePathExpression();
+        } else if (ObjectHelper.equal(remainder, "length") || ObjectHelper.equal(remainder, "size")) {
+            return ExpressionBuilder.fileSizeExpression();
+        } else if (ObjectHelper.equal(remainder, "modified")) {
+            return ExpressionBuilder.fileLastModifiedExpression();
+        }
+        throw new SimpleParserException("Unknown file language syntax: " + remainder, token.getIndex());
+    }
+
+    private String ifStartsWithReturnRemainder(String prefix, String text) {
+        if (text.startsWith(prefix)) {
+            String remainder = text.substring(prefix.length());
+            if (remainder.length() > 0) {
+                return remainder;
+            }
+        }
+        return null;
+    }
+
+}

Added: camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionStart.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionStart.java?rev=1167462&view=auto
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionStart.java (added)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionStart.java Sat Sep 10 05:43:14 2011
@@ -0,0 +1,57 @@
+/**
+ * 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.ast;
+
+import org.apache.camel.Expression;
+import org.apache.camel.language.simple.SimpleToken;
+
+/**
+ * Starts a function
+ */
+public class SimpleFunctionStart extends BaseSimpleNode implements BlockStart {
+
+    private LiteralNode literal;
+
+    public SimpleFunctionStart(SimpleToken token) {
+        super(token);
+    }
+
+    @Override
+    public String toString() {
+        // output a nice toString so it makes debugging easier as we can see the entire block
+        return "${" + literal + "}";
+    }
+
+    @Override
+    public Expression createExpression(String expression) {
+        SimpleFunctionExpression function = new SimpleFunctionExpression(this.getToken());
+        function.addText(literal.getText());
+        return function.createExpression(expression);
+    }
+
+    @Override
+    public boolean acceptAndAddNode(SimpleNode node) {
+        // only accept literals as it contains the text for the function
+        if (node instanceof LiteralNode) {
+            literal = (LiteralNode) node;
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+}

Added: camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/SimpleNode.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/SimpleNode.java?rev=1167462&view=auto
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/SimpleNode.java (added)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/SimpleNode.java Sat Sep 10 05:43:14 2011
@@ -0,0 +1,45 @@
+/**
+ * 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.ast;
+
+import org.apache.camel.Expression;
+import org.apache.camel.language.simple.SimpleParserException;
+import org.apache.camel.language.simple.SimpleToken;
+
+/**
+ * Represents a node in the Simple AST
+ */
+public interface SimpleNode {
+
+    /**
+     * Gets the token by which this model was based upon
+     *
+     * @return the token
+     */
+    SimpleToken getToken();
+
+    /**
+     * Creates a Camel {@link Expression} based on this model.
+     *
+     * @param expression the input string
+     * @return the created {@link Expression}
+     * @throws org.apache.camel.language.simple.SimpleParserException
+     *          should be thrown if error parsing the model
+     */
+    Expression createExpression(String expression) throws SimpleParserException;
+
+}

Added: camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/SingleQuoteEnd.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/SingleQuoteEnd.java?rev=1167462&view=auto
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/SingleQuoteEnd.java (added)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/SingleQuoteEnd.java Sat Sep 10 05:43:14 2011
@@ -0,0 +1,36 @@
+/**
+ * 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.ast;
+
+import org.apache.camel.Expression;
+import org.apache.camel.language.simple.SimpleToken;
+
+/**
+ * Ends a block enclosed by single quotes
+ */
+public class SingleQuoteEnd extends BaseSimpleNode implements BlockEnd {
+
+    public SingleQuoteEnd(SimpleToken token) {
+        super(token);
+    }
+
+    @Override
+    public Expression createExpression(String expression) {
+        return null;
+    }
+
+}

Added: camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/SingleQuoteStart.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/SingleQuoteStart.java?rev=1167462&view=auto
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/SingleQuoteStart.java (added)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/SingleQuoteStart.java Sat Sep 10 05:43:14 2011
@@ -0,0 +1,55 @@
+/**
+ * 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.ast;
+
+import org.apache.camel.Expression;
+import org.apache.camel.language.simple.SimpleToken;
+
+/**
+ * Starts a block enclosed by single quotes
+ */
+public class SingleQuoteStart extends BaseSimpleNode implements BlockStart {
+
+    private final CompositeNodes block;
+
+    public SingleQuoteStart(SimpleToken token) {
+        super(token);
+        this.block = new CompositeNodes(token);
+    }
+
+    @Override
+    public String toString() {
+        // output a nice toString so it makes debugging easier as we can see the entire block
+        return "'" + block + "'";
+    }
+
+    @Override
+    public Expression createExpression(String expression) {
+        if (block != null) {
+            return block.createExpression(expression);
+        } else {
+            return null;
+        }
+    }
+
+    @Override
+    public boolean acceptAndAddNode(SimpleNode node) {
+        block.addChild(node);
+        return true;
+    }
+
+}

Added: camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/UnaryExpression.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/UnaryExpression.java?rev=1167462&view=auto
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/UnaryExpression.java (added)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/UnaryExpression.java Sat Sep 10 05:43:14 2011
@@ -0,0 +1,121 @@
+/**
+ * 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.ast;
+
+import org.apache.camel.CamelExchangeException;
+import org.apache.camel.Exchange;
+import org.apache.camel.Expression;
+import org.apache.camel.language.simple.SimpleParserException;
+import org.apache.camel.language.simple.SimpleToken;
+import org.apache.camel.language.simple.UnaryOperatorType;
+import org.apache.camel.util.ObjectHelper;
+
+/**
+ * Represents an unary expression in the AST
+ */
+public class UnaryExpression extends BaseSimpleNode {
+
+    private UnaryOperatorType operator;
+    private SimpleNode left;
+
+    public UnaryExpression(SimpleToken token) {
+        super(token);
+        operator = UnaryOperatorType.asOperator(token.getText());
+    }
+
+    @Override
+    public String toString() {
+        if (left != null) {
+            return left + token.getText();
+        } else {
+            return token.getText();
+        }
+    }
+
+    /**
+     * Accepts the left node to this operator
+     *
+     * @param left  the left node to accept
+     */
+    public void acceptLeft(SimpleNode left) {
+        this.left = left;
+    }
+
+    public UnaryOperatorType getOperator() {
+        return operator;
+    }
+
+    @Override
+    public Expression createExpression(String expression) {
+        ObjectHelper.notNull(left, "left node", this);
+
+        final Expression leftExp = left.createExpression(expression);
+
+        if (operator == UnaryOperatorType.INC) {
+            return createIncExpression(leftExp);
+        } else if (operator == UnaryOperatorType.DEC) {
+            return createDecExpression(leftExp);
+        }
+
+        throw new SimpleParserException("Unknown unary operator " + operator, token.getIndex());
+    }
+
+    private Expression createIncExpression(final Expression leftExp) {
+        return new Expression() {
+            @Override
+            public <T> T evaluate(Exchange exchange, Class<T> type) {
+                Number num = leftExp.evaluate(exchange, Number.class);
+                if (num != null) {
+                    long val = num.longValue();
+                    val++;
+                    return exchange.getContext().getTypeConverter().convertTo(type, val);
+                }
+                // cannot convert the expression as a number
+                Exception cause = new CamelExchangeException("Cannot evaluate " + leftExp + " as a number", exchange);
+                throw ObjectHelper.wrapRuntimeCamelException(cause);
+            }
+
+            @Override
+            public String toString() {
+                return left + operator.toString();
+            }
+        };
+    }
+
+    private Expression createDecExpression(final Expression leftExp) {
+        return new Expression() {
+            @Override
+            public <T> T evaluate(Exchange exchange, Class<T> type) {
+                Number num = leftExp.evaluate(exchange, Number.class);
+                if (num != null) {
+                    long val = num.longValue();
+                    val--;
+                    return exchange.getContext().getTypeConverter().convertTo(type, val);
+                }
+                // cannot convert the expression as a number
+                Exception cause = new CamelExchangeException("Cannot evaluate " + leftExp + " as a number", exchange);
+                throw ObjectHelper.wrapRuntimeCamelException(cause);
+            }
+
+            @Override
+            public String toString() {
+                return left + operator.toString();
+            }
+        };
+    }
+
+}

Added: camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/package.html
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/package.html?rev=1167462&view=auto
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/package.html (added)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/package.html Sat Sep 10 05:43:14 2011
@@ -0,0 +1,25 @@
+<!--
+    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.
+-->
+<html>
+<head>
+</head>
+<body>
+
+AST for the Camel <a href="http://camel.apache.org/simple.html">Simple</a> language.
+
+</body>
+</html>

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/package.html
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/package.html?rev=1167462&r1=1167461&r2=1167462&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/package.html (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/package.html Sat Sep 10 05:43:14 2011
@@ -5,9 +5,9 @@
     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.

Modified: camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanParameterInvalidValueTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanParameterInvalidValueTest.java?rev=1167462&r1=1167461&r2=1167462&view=diff
==============================================================================
--- camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanParameterInvalidValueTest.java (original)
+++ camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanParameterInvalidValueTest.java Sat Sep 10 05:43:14 2011
@@ -79,7 +79,7 @@ public class BeanParameterInvalidValueTe
             fail("Should have thrown exception");
         } catch (CamelExecutionException e) {
             ExpressionEvaluationException cause = assertIsInstanceOf(ExpressionEvaluationException.class, e.getCause());
-            assertEquals("Illegal syntax: xxx", cause.getCause().getMessage());
+            assertTrue(cause.getCause().getMessage().startsWith("Unknown function: xxx at location 0"));
         }
 
         assertMockEndpointsSatisfied();

Modified: camel/trunk/camel-core/src/test/java/org/apache/camel/language/FileLanguageTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/language/FileLanguageTest.java?rev=1167462&r1=1167461&r2=1167462&view=diff
==============================================================================
--- camel/trunk/camel-core/src/test/java/org/apache/camel/language/FileLanguageTest.java (original)
+++ camel/trunk/camel-core/src/test/java/org/apache/camel/language/FileLanguageTest.java Sat Sep 10 05:43:14 2011
@@ -65,7 +65,7 @@ public class FileLanguageTest extends La
             assertExpression("${file:onlyName}", file.getName());
             fail("Should have thrown exception");
         } catch (ExpressionIllegalSyntaxException e) {
-            assertEquals("Illegal syntax: File language syntax: onlyName", e.getMessage());
+            assertTrue(e.getMessage().startsWith("Unknown file language syntax: onlyName at location 0"));
         }
     }
 
@@ -187,21 +187,21 @@ public class FileLanguageTest extends La
             assertExpression("${file.name}", "");
             fail("Should have thrown an exception");
         } catch (ExpressionIllegalSyntaxException e) {
-            assertEquals("Illegal syntax: file.name", e.getMessage());
+            assertTrue(e.getMessage().startsWith("Unknown function: file.name at location 0"));
         }
 
         try {
             assertExpression("hey ${xxx} how are you?", "");
             fail("Should have thrown an exception");
         } catch (ExpressionIllegalSyntaxException e) {
-            assertEquals("Illegal syntax: xxx", e.getMessage());
+            assertTrue(e.getMessage().startsWith("Unknown function: xxx at location 4"));
         }
 
         try {
             assertExpression("${xxx}", "");
             fail("Should have thrown an exception");
         } catch (ExpressionIllegalSyntaxException e) {
-            assertEquals("Illegal syntax: xxx", e.getMessage());
+            assertTrue(e.getMessage().startsWith("Unknown function: xxx at location 0"));
         }
     }
 



Mime
View raw message