Author: davsclaus Date: Sat Sep 10 07:38:56 2011 New Revision: 1167474 URL: http://svn.apache.org/viewvc?rev=1167474&view=rev Log: CAMEL-3619: Improved simple language with syntax parser and ast.
Added: camel/trunk/camel-core/src/test/java/org/apache/camel/language/simple/SimpleDecHeaderTest.java camel/trunk/camel-core/src/test/java/org/apache/camel/language/simple/SimpleIncHeaderTest.java Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/BaseSimpleParser.java camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/UnaryExpression.java camel/trunk/camel-core/src/test/java/org/apache/camel/language/simple/SimpleParserExpressionTest.java Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/BaseSimpleParser.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/BaseSimpleParser.java?rev=1167474&r1=1167473&r2=1167474&view=diff ============================================================================== --- camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/BaseSimpleParser.java (original) +++ camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/BaseSimpleParser.java Sat Sep 10 07:38:56 2011 @@ -104,8 +104,8 @@ public abstract class BaseSimpleParser { * as child to the given block. This is done to have the AST graph updated and prepared properly. * <p/> * So when the AST node is later used to create the {@link org.apache.camel.Predicate}s - * to be used by Camel then the AST graph has a linked and prepared - * graph of nodes which represent the input expression. + * or {@link org.apache.camel.Expression}s to be used by Camel then the AST graph + * has a linked and prepared graph of nodes which represent the input expression. */ protected void prepareBlocks() { List<SimpleNode> answer = new ArrayList<SimpleNode>(); @@ -123,7 +123,7 @@ public abstract class BaseSimpleParser { Block top = stack.pop(); answer.add(top); } else { - // if there is a model on the stack then it should accept the child model + // if there is a block on the stack then it should accept the child token Block block = stack.isEmpty() ? null : stack.peek(); if (block != null) { if (!block.acceptAndAddNode(token)) { @@ -149,8 +149,8 @@ public abstract class BaseSimpleParser { * to have the AST graph updated and prepared properly. * <p/> * So when the AST node is later used to create the {@link org.apache.camel.Predicate}s - * to be used by Camel then the AST graph has a linked and prepared - * graph of nodes which represent the input expression. + * or {@link org.apache.camel.Expression}s to be used by Camel then the AST graph + * has a linked and prepared graph of nodes which represent the input expression. */ protected void prepareUnaryExpressions() { Stack<SimpleNode> stack = new Stack<SimpleNode>(); @@ -226,4 +226,5 @@ public abstract class BaseSimpleParser { nextToken(); } } + } Modified: 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=1167474&r1=1167473&r2=1167474&view=diff ============================================================================== --- camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/UnaryExpression.java (original) +++ camel/trunk/camel-core/src/main/java/org/apache/camel/language/simple/ast/UnaryExpression.java Sat Sep 10 07:38:56 2011 @@ -19,6 +19,7 @@ package org.apache.camel.language.simple import org.apache.camel.CamelExchangeException; import org.apache.camel.Exchange; import org.apache.camel.Expression; +import org.apache.camel.NoTypeConversionAvailableException; import org.apache.camel.language.simple.SimpleParserException; import org.apache.camel.language.simple.SimpleToken; import org.apache.camel.language.simple.UnaryOperatorType; @@ -82,7 +83,17 @@ public class UnaryExpression extends Bas if (num != null) { long val = num.longValue(); val++; - return exchange.getContext().getTypeConverter().convertTo(type, val); + + // convert value back to same type as input as we want to preserve type + Object left = leftExp.evaluate(exchange, Object.class); + try { + left = exchange.getContext().getTypeConverter().mandatoryConvertTo(left.getClass(), exchange, val); + } catch (NoTypeConversionAvailableException e) { + throw ObjectHelper.wrapRuntimeCamelException(e); + } + + // and return the result + return exchange.getContext().getTypeConverter().convertTo(type, left); } // cannot convert the expression as a number Exception cause = new CamelExchangeException("Cannot evaluate " + leftExp + " as a number", exchange); @@ -104,7 +115,17 @@ public class UnaryExpression extends Bas if (num != null) { long val = num.longValue(); val--; - return exchange.getContext().getTypeConverter().convertTo(type, val); + + // convert value back to same type as input as we want to preserve type + Object left = leftExp.evaluate(exchange, Object.class); + try { + left = exchange.getContext().getTypeConverter().mandatoryConvertTo(left.getClass(), exchange, val); + } catch (NoTypeConversionAvailableException e) { + throw ObjectHelper.wrapRuntimeCamelException(e); + } + + // and return the result + return exchange.getContext().getTypeConverter().convertTo(type, left); } // cannot convert the expression as a number Exception cause = new CamelExchangeException("Cannot evaluate " + leftExp + " as a number", exchange); Added: camel/trunk/camel-core/src/test/java/org/apache/camel/language/simple/SimpleDecHeaderTest.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/language/simple/SimpleDecHeaderTest.java?rev=1167474&view=auto ============================================================================== --- camel/trunk/camel-core/src/test/java/org/apache/camel/language/simple/SimpleDecHeaderTest.java (added) +++ camel/trunk/camel-core/src/test/java/org/apache/camel/language/simple/SimpleDecHeaderTest.java Sat Sep 10 07:38:56 2011 @@ -0,0 +1,50 @@ +/** + * 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 org.apache.camel.ContextTestSupport; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.mock.MockEndpoint; + +/** + * + */ +public class SimpleDecHeaderTest extends ContextTestSupport { + + public void testDecHeader() throws Exception { + MockEndpoint mock = getMockEndpoint("mock:result"); + mock.expectedMessageCount(1); + mock.message(0).header("myCounter").isInstanceOf(Integer.class); + mock.message(0).header("myCounter").isEqualTo(122); + + template.sendBodyAndHeader("direct:start", "Hello World", "myCounter", 123); + + assertMockEndpointsSatisfied(); + } + + @Override + protected RouteBuilder createRouteBuilder() throws Exception { + return new RouteBuilder() { + @Override + public void configure() throws Exception { + from("direct:start") + .setHeader("myCounter", simple("${header.myCounter}--")) + .to("mock:result"); + } + }; + } +} Added: camel/trunk/camel-core/src/test/java/org/apache/camel/language/simple/SimpleIncHeaderTest.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/language/simple/SimpleIncHeaderTest.java?rev=1167474&view=auto ============================================================================== --- camel/trunk/camel-core/src/test/java/org/apache/camel/language/simple/SimpleIncHeaderTest.java (added) +++ camel/trunk/camel-core/src/test/java/org/apache/camel/language/simple/SimpleIncHeaderTest.java Sat Sep 10 07:38:56 2011 @@ -0,0 +1,50 @@ +/** + * 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 org.apache.camel.ContextTestSupport; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.mock.MockEndpoint; + +/** + * + */ +public class SimpleIncHeaderTest extends ContextTestSupport { + + public void testIncHeader() throws Exception { + MockEndpoint mock = getMockEndpoint("mock:result"); + mock.expectedMessageCount(1); + mock.message(0).header("myCounter").isInstanceOf(Integer.class); + mock.message(0).header("myCounter").isEqualTo(124); + + template.sendBodyAndHeader("direct:start", "Hello World", "myCounter", 123); + + assertMockEndpointsSatisfied(); + } + + @Override + protected RouteBuilder createRouteBuilder() throws Exception { + return new RouteBuilder() { + @Override + public void configure() throws Exception { + from("direct:start") + .setHeader("myCounter", simple("${header.myCounter}++")) + .to("mock:result"); + } + }; + } +} Modified: camel/trunk/camel-core/src/test/java/org/apache/camel/language/simple/SimpleParserExpressionTest.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/language/simple/SimpleParserExpressionTest.java?rev=1167474&r1=1167473&r2=1167474&view=diff ============================================================================== --- camel/trunk/camel-core/src/test/java/org/apache/camel/language/simple/SimpleParserExpressionTest.java (original) +++ camel/trunk/camel-core/src/test/java/org/apache/camel/language/simple/SimpleParserExpressionTest.java Sat Sep 10 07:38:56 2011 @@ -99,6 +99,22 @@ public class SimpleParserExpressionTest assertEquals("121", exp.evaluate(exchange, String.class)); } + public void testSimpleUnaryIncInt() throws Exception { + exchange.getIn().setBody(122); + SimpleExpressionParser parser = new SimpleExpressionParser("${body}++"); + Expression exp = parser.parseExpression(); + + assertEquals(Integer.valueOf(123), exp.evaluate(exchange, Integer.class)); + } + + public void testSimpleUnaryDecInt() throws Exception { + exchange.getIn().setBody(122); + SimpleExpressionParser parser = new SimpleExpressionParser("${body}--"); + Expression exp = parser.parseExpression(); + + assertEquals(Integer.valueOf(121), exp.evaluate(exchange, Integer.class)); + } + public void testSimpleEscape() throws Exception { exchange.getIn().setBody("World"); // we escape the $ which mean it will not be a function