Author: hadrian
Date: Tue Sep 23 16:09:33 2008
New Revision: 698396
URL: http://svn.apache.org/viewvc?rev=698396&view=rev
Log:
CAMEL-325. Support for loop.
Added:
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/model/LoopType.java
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/LoopProcessor.java
activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/LoopTest.java
Modified:
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/model/NodeFactory.java
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/model/ProcessorType.java
Added:
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/model/LoopType.java
URL:
http://svn.apache.org/viewvc/activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/model/LoopType.java?rev=698396&view=auto
==============================================================================
---
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/model/LoopType.java
(added)
+++
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/model/LoopType.java
Tue Sep 23 16:09:33 2008
@@ -0,0 +1,69 @@
+/**
+ * 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.model;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.apache.camel.Expression;
+import org.apache.camel.Processor;
+import org.apache.camel.model.language.ExpressionType;
+import org.apache.camel.processor.LoopProcessor;
+import org.apache.camel.spi.RouteContext;
+
+/**
+ * Represents an XML <loop/> element
+ *
+ * @version $Revision: $
+ */
[EMAIL PROTECTED](name = "loop")
[EMAIL PROTECTED](XmlAccessType.FIELD)
+public class LoopType extends ExpressionNode implements Block {
+ public LoopType() {
+ }
+
+ public LoopType(Expression expression) {
+ super(expression);
+ }
+
+ public LoopType(ExpressionType expression) {
+ super(expression);
+ }
+
+ public void setExpression(Expression<?> expr) {
+ if (expr != null) {
+ setExpression(new ExpressionType(expr));
+ }
+ }
+ @Override
+ public String toString() {
+ return "Loop[ " + getExpression() + " -> " + getOutputs() + "]";
+ }
+
+ @Override
+ public String getShortName() {
+ return "loop";
+ }
+
+ @Override
+ public Processor createProcessor(RouteContext routeContext) throws
Exception {
+ return new LoopProcessor(
+ getExpression().createExpression(routeContext),
+ routeContext.createProcessor(this));
+ }
+}
Modified:
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/model/NodeFactory.java
URL:
http://svn.apache.org/viewvc/activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/model/NodeFactory.java?rev=698396&r1=698395&r2=698396&view=diff
==============================================================================
---
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/model/NodeFactory.java
(original)
+++
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/model/NodeFactory.java
Tue Sep 23 16:09:33 2008
@@ -27,6 +27,10 @@
return new FilterType();
}
+ public LoopType createLoop() {
+ return new LoopType();
+ }
+
public RouteType createRoute() {
return new RouteType();
}
Modified:
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/model/ProcessorType.java
URL:
http://svn.apache.org/viewvc/activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/model/ProcessorType.java?rev=698396&r1=698395&r2=698396&view=diff
==============================================================================
---
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/model/ProcessorType.java
(original)
+++
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/model/ProcessorType.java
Tue Sep 23 16:09:33 2008
@@ -40,6 +40,7 @@
import org.apache.camel.Processor;
import org.apache.camel.Route;
import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.builder.Builder;
import org.apache.camel.builder.DataFormatClause;
import org.apache.camel.builder.DeadLetterChannelBuilder;
import org.apache.camel.builder.ErrorHandlerBuilder;
@@ -49,6 +50,7 @@
import org.apache.camel.builder.ProcessorBuilder;
import org.apache.camel.impl.DefaultCamelContext;
import org.apache.camel.model.dataformat.DataFormatType;
+import org.apache.camel.model.language.ConstantExpression;
import org.apache.camel.model.language.ExpressionType;
import org.apache.camel.model.language.LanguageExpression;
import org.apache.camel.processor.ConvertBodyProcessor;
@@ -836,7 +838,32 @@
return answer;
}
+ /**
+ * Creates a expression which must evaluate to an integer that determines
+ * how many times the exchange should be sent down the rest of the route.
+ *
+ * @return the clause used to create the loop expression
+ */
+ public ExpressionClause<LoopType> loop() {
+ LoopType loop = new LoopType();
+ addOutput(loop);
+ return ExpressionClause.createAndSetExpression(loop);
+ }
+ public LoopType loop(Expression<?> expression) {
+ LoopType loop = getNodeFactory().createLoop();
+ loop.setExpression(expression);
+ addOutput(loop);
+ return loop;
+ }
+
+ public LoopType loop(int count) {
+ LoopType loop = getNodeFactory().createLoop();
+ loop.setExpression(new ConstantExpression(Integer.toString(count)));
+ addOutput(loop);
+ return loop;
+ }
+
public Type throwFault(Throwable fault) {
ThrowFaultType answer = new ThrowFaultType();
answer.setFault(fault);
Added:
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/LoopProcessor.java
URL:
http://svn.apache.org/viewvc/activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/LoopProcessor.java?rev=698396&view=auto
==============================================================================
---
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/LoopProcessor.java
(added)
+++
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/LoopProcessor.java
Tue Sep 23 16:09:33 2008
@@ -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.processor;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Expression;
+import org.apache.camel.Processor;
+import org.apache.camel.util.ExchangeHelper;
+
+/**
+ * The processor which sends messages in a loop.
+ *
+ * @version $Revision: $
+ */
+public class LoopProcessor extends DelegateProcessor {
+ private Expression<Exchange> expression;
+
+ public LoopProcessor(Expression<Exchange> expression, Processor processor)
{
+ super(processor);
+ this.expression = expression;
+ }
+
+ @Override
+ public void process(Exchange exchange) throws Exception {
+ // Intermediate conversion to String is needed when direct conversion
to Integer is not available
+ // but evaluation result is a textual representation of a numeric
value.
+ String text = ExchangeHelper.convertToType(exchange, String.class,
expression.evaluate(exchange));
+ Integer value = ExchangeHelper.convertToType(exchange, Integer.class,
text);
+ int count = value != null ? value.intValue() : 0;
+ while (count-- > 0) {
+ super.process(exchange);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "Loop[for: " + expression + " times do: " + getProcessor() +
"]";
+ }
+
+ public Expression<Exchange> getExpression() {
+ return expression;
+ }
+}
Added:
activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/LoopTest.java
URL:
http://svn.apache.org/viewvc/activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/LoopTest.java?rev=698396&view=auto
==============================================================================
---
activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/LoopTest.java
(added)
+++
activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/LoopTest.java
Tue Sep 23 16:09:33 2008
@@ -0,0 +1,70 @@
+/**
+ * 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.processor;
+
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+
+/**
+ * @version $Revision: $
+ */
+public class LoopTest extends ContextTestSupport {
+ MockEndpoint resultEndpoint;
+
+ public void testCounterLoop() throws Exception {
+ performLoopTest("direct:a", 8);
+ }
+
+ public void testExpressionLoop() throws Exception {
+ performLoopTest("direct:b", 6);
+ }
+
+ public void testExpressionClauseLoop() throws Exception {
+ performLoopTest("direct:c", 4);
+ }
+
+ private void performLoopTest(String endpointUri, int expectedIterations)
throws InterruptedException {
+ resultEndpoint.expectedMessageCount(expectedIterations);
+ template.sendBodyAndHeader(endpointUri, "<hello
times='4'>world!</hello>", "loop", "6");
+ resultEndpoint.assertIsSatisfied();
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ resultEndpoint = resolveMandatoryEndpoint("mock:result",
MockEndpoint.class);
+ resultEndpoint.reset();
+ }
+
+ protected RouteBuilder createRouteBuilder() {
+ return new RouteBuilder() {
+ public void configure() {
+ // START SNIPPET: ex
+ from("direct:a").loop(8).to("mock:result");
+ // END SNIPPET: ex
+ // START SNIPPET: ex2
+ from("direct:b").loop(header("loop")).to("mock:result");
+ // END SNIPPET: ex2
+ // START SNIPPET: ex3
+
from("direct:c").loop().xpath("/hello/@times").to("mock:result");
+ // END SNIPPET: ex3
+ }
+ };
+ }
+}