001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.camel.model;
018
019 import java.util.ArrayList;
020 import java.util.Arrays;
021 import java.util.Collection;
022 import java.util.Collections;
023 import java.util.HashSet;
024 import java.util.LinkedList;
025 import java.util.List;
026 import java.util.Set;
027 import java.util.concurrent.ThreadPoolExecutor;
028
029 import javax.xml.bind.annotation.XmlAccessType;
030 import javax.xml.bind.annotation.XmlAccessorType;
031 import javax.xml.bind.annotation.XmlAttribute;
032 import javax.xml.bind.annotation.XmlTransient;
033
034 import org.apache.camel.CamelContext;
035 import org.apache.camel.CamelException;
036 import org.apache.camel.Endpoint;
037 import org.apache.camel.Exchange;
038 import org.apache.camel.Expression;
039 import org.apache.camel.Predicate;
040 import org.apache.camel.Processor;
041 import org.apache.camel.Route;
042 import org.apache.camel.builder.DataFormatClause;
043 import org.apache.camel.builder.DeadLetterChannelBuilder;
044 import org.apache.camel.builder.ErrorHandlerBuilder;
045 import org.apache.camel.builder.ErrorHandlerBuilderRef;
046 import org.apache.camel.builder.ExpressionClause;
047 import org.apache.camel.builder.NoErrorHandlerBuilder;
048 import org.apache.camel.builder.ProcessorBuilder;
049 import org.apache.camel.impl.DefaultCamelContext;
050 import org.apache.camel.model.dataformat.DataFormatType;
051 import org.apache.camel.model.language.ConstantExpression;
052 import org.apache.camel.model.language.ExpressionType;
053 import org.apache.camel.model.language.LanguageExpression;
054 import org.apache.camel.processor.ConvertBodyProcessor;
055 import org.apache.camel.processor.DelegateProcessor;
056 import org.apache.camel.processor.Pipeline;
057 import org.apache.camel.processor.aggregate.AggregationCollection;
058 import org.apache.camel.processor.aggregate.AggregationStrategy;
059 import org.apache.camel.processor.idempotent.MessageIdRepository;
060 import org.apache.camel.spi.DataFormat;
061 import org.apache.camel.spi.ErrorHandlerWrappingStrategy;
062 import org.apache.camel.spi.InterceptStrategy;
063 import org.apache.camel.spi.Policy;
064 import org.apache.camel.spi.RouteContext;
065 import org.apache.commons.logging.Log;
066 import org.apache.commons.logging.LogFactory;
067
068 /**
069 * Base class for processor types that most XML types extend.
070 *
071 * @version $Revision: 61170 $
072 */
073 @XmlAccessorType(XmlAccessType.PROPERTY)
074 public abstract class ProcessorType<Type extends ProcessorType> extends OptionalIdentifiedType<Type> implements Block {
075 public static final String DEFAULT_TRACE_CATEGORY = "org.apache.camel.TRACE";
076 private static final transient Log LOG = LogFactory.getLog(ProcessorType.class);
077 private ErrorHandlerBuilder errorHandlerBuilder;
078 private Boolean inheritErrorHandlerFlag;
079 private NodeFactory nodeFactory;
080 private LinkedList<Block> blocks = new LinkedList<Block>();
081 private ProcessorType<? extends ProcessorType> parent;
082 private List<InterceptorType> interceptors = new ArrayList<InterceptorType>();
083 private String errorHandlerRef;
084
085 // else to use an optional attribute in JAXB2
086 public abstract List<ProcessorType<?>> getOutputs();
087
088
089 public Processor createProcessor(RouteContext routeContext) throws Exception {
090 throw new UnsupportedOperationException("Not implemented yet for class: " + getClass().getName());
091 }
092
093 public Processor createOutputsProcessor(RouteContext routeContext) throws Exception {
094 Collection<ProcessorType<?>> outputs = getOutputs();
095 return createOutputsProcessor(routeContext, outputs);
096 }
097
098 public void addRoutes(RouteContext routeContext, Collection<Route> routes) throws Exception {
099 Processor processor = makeProcessor(routeContext);
100 if (!routeContext.isRouteAdded()) {
101 routeContext.addEventDrivenProcessor(processor);
102 }
103 }
104
105 /**
106 * Wraps the child processor in whatever necessary interceptors and error
107 * handlers
108 */
109 public Processor wrapProcessor(RouteContext routeContext, Processor processor) throws Exception {
110 processor = wrapProcessorInInterceptors(routeContext, processor);
111 return wrapInErrorHandler(routeContext, processor);
112 }
113
114 // Fluent API
115 // -------------------------------------------------------------------------
116
117 /**
118 * Sends the exchange to the given endpoint URI
119 */
120 public Type to(String uri) {
121 addOutput(new ToType(uri));
122 return (Type) this;
123 }
124
125 /**
126 * Sends the exchange to the given endpoint
127 */
128 public Type to(Endpoint endpoint) {
129 addOutput(new ToType(endpoint));
130 return (Type) this;
131 }
132
133 /**
134 * Sends the exchange to a list of endpoints
135 */
136 public Type to(String... uris) {
137 for (String uri : uris) {
138 addOutput(new ToType(uri));
139 }
140 return (Type) this;
141 }
142
143 /**
144 * Sends the exchange to a list of endpoints
145 */
146 public Type to(Endpoint... endpoints) {
147 for (Endpoint endpoint : endpoints) {
148 addOutput(new ToType(endpoint));
149 }
150 return (Type) this;
151 }
152
153 /**
154 * Sends the exchange to a list of endpoint
155 */
156 public Type to(Collection<Endpoint> endpoints) {
157 for (Endpoint endpoint : endpoints) {
158 addOutput(new ToType(endpoint));
159 }
160 return (Type) this;
161 }
162
163 /**
164 * Multicasts messages to all its child outputs; so that each processor and
165 * destination gets a copy of the original message to avoid the processors
166 * interfering with each other.
167 */
168 public MulticastType multicast() {
169 MulticastType answer = new MulticastType();
170 addOutput(answer);
171 return answer;
172 }
173
174 /**
175 * Multicasts messages to all its child outputs; so that each processor and
176 * destination gets a copy of the original message to avoid the processors
177 * interfering with each other.
178 * @param aggregationStrategy the strategy used to aggregate responses for
179 * every part
180 * @param parallelProcessing if is <tt>true</tt> camel will fork thread to call the endpoint producer
181 * @return the multicast type
182 */
183 public MulticastType multicast(AggregationStrategy aggregationStrategy, boolean parallelProcessing) {
184 MulticastType answer = new MulticastType();
185 addOutput(answer);
186 answer.setAggregationStrategy(aggregationStrategy);
187 answer.setParallelProcessing(parallelProcessing);
188 return answer;
189 }
190
191 /**
192 * Multicasts messages to all its child outputs; so that each processor and
193 * destination gets a copy of the original message to avoid the processors
194 * interfering with each other.
195 * @param aggregationStrategy the strategy used to aggregate responses for
196 * every part
197 * @return the multicast type
198 */
199 public MulticastType multicast(AggregationStrategy aggregationStrategy) {
200 MulticastType answer = new MulticastType();
201 addOutput(answer);
202 answer.setAggregationStrategy(aggregationStrategy);
203 return answer;
204 }
205
206 /**
207 * Creates a {@link Pipeline} of the list of endpoints so that the message
208 * will get processed by each endpoint in turn and for request/response the
209 * output of one endpoint will be the input of the next endpoint
210 */
211 public Type pipeline(String... uris) {
212 // TODO pipeline v mulicast
213 return to(uris);
214 }
215
216 /**
217 * Creates a {@link Pipeline} of the list of endpoints so that the message
218 * will get processed by each endpoint in turn and for request/response the
219 * output of one endpoint will be the input of the next endpoint
220 */
221 public Type pipeline(Endpoint... endpoints) {
222 // TODO pipeline v mulicast
223 return to(endpoints);
224 }
225
226 /**
227 * Creates a {@link Pipeline} of the list of endpoints so that the message
228 * will get processed by each endpoint in turn and for request/response the
229 * output of one endpoint will be the input of the next endpoint
230 */
231 public Type pipeline(Collection<Endpoint> endpoints) {
232 // TODO pipeline v mulicast
233 return to(endpoints);
234 }
235
236 /**
237 * Ends the current block
238 */
239 public ProcessorType<? extends ProcessorType> end() {
240 if (blocks.isEmpty()) {
241 if (parent == null) {
242 throw new IllegalArgumentException("Root node with no active block");
243 }
244 return parent;
245 }
246 popBlock();
247 return this;
248 }
249
250 /**
251 * Causes subsequent processors to be called asynchronously
252 *
253 * @param coreSize the number of threads that will be used to process
254 * messages in subsequent processors.
255 * @return a ThreadType builder that can be used to further configure the
256 * the thread pool.
257 */
258 public ThreadType thread(int coreSize) {
259 ThreadType answer = new ThreadType(coreSize);
260 addOutput(answer);
261 return answer;
262 }
263
264 /**
265 * Causes subsequent processors to be called asynchronously
266 *
267 * @param executor the executor that will be used to process
268 * messages in subsequent processors.
269 * @return a ThreadType builder that can be used to further configure the
270 * the thread pool.
271 */
272 public ProcessorType<Type> thread(ThreadPoolExecutor executor) {
273 ThreadType answer = new ThreadType(executor);
274 addOutput(answer);
275 return this;
276 }
277
278 /**
279 * Creates an {@link org.apache.camel.processor.idempotent.IdempotentConsumer}
280 * to avoid duplicate messages
281 */
282 public IdempotentConsumerType idempotentConsumer(Expression messageIdExpression,
283 MessageIdRepository messageIdRepository) {
284 IdempotentConsumerType answer = new IdempotentConsumerType(messageIdExpression, messageIdRepository);
285 addOutput(answer);
286 return answer;
287 }
288
289 /**
290 * Creates an {@link org.apache.camel.processor.idempotent.IdempotentConsumer}
291 * to avoid duplicate messages
292 *
293 * @return the builder used to create the expression
294 */
295 public ExpressionClause<IdempotentConsumerType> idempotentConsumer(MessageIdRepository messageIdRepository) {
296 IdempotentConsumerType answer = new IdempotentConsumerType();
297 answer.setMessageIdRepository(messageIdRepository);
298 addOutput(answer);
299 return ExpressionClause.createAndSetExpression(answer);
300 }
301
302 /**
303 * Creates a predicate expression which only if it is true then the
304 * exchange is forwarded to the destination
305 *
306 * @return the clause used to create the filter expression
307 */
308 public ExpressionClause<FilterType> filter() {
309 FilterType filter = new FilterType();
310 addOutput(filter);
311 return ExpressionClause.createAndSetExpression(filter);
312 }
313
314 /**
315 * Creates a predicate which is applied and only if it is true then the
316 * exchange is forwarded to the destination
317 *
318 * @return the builder for a predicate
319 */
320 public FilterType filter(Predicate predicate) {
321 FilterType filter = new FilterType(predicate);
322 addOutput(filter);
323 return filter;
324 }
325
326 public FilterType filter(ExpressionType expression) {
327 FilterType filter = getNodeFactory().createFilter();
328 filter.setExpression(expression);
329 addOutput(filter);
330 return filter;
331 }
332
333 public FilterType filter(String language, String expression) {
334 return filter(new LanguageExpression(language, expression));
335 }
336
337 public LoadBalanceType loadBalance() {
338 LoadBalanceType answer = new LoadBalanceType();
339 addOutput(answer);
340 return answer;
341 }
342
343
344 /**
345 * Creates a choice of one or more predicates with an otherwise clause
346 *
347 * @return the builder for a choice expression
348 */
349 public ChoiceType choice() {
350 ChoiceType answer = new ChoiceType();
351 addOutput(answer);
352 return answer;
353 }
354
355 /**
356 * Creates a try/catch block
357 *
358 * @return the builder for a tryBlock expression
359 */
360 public TryType tryBlock() {
361 TryType answer = new TryType();
362 addOutput(answer);
363 return answer;
364 }
365
366 /**
367 * Creates a dynamic <a
368 * href="http://activemq.apache.org/camel/recipient-list.html">Recipient
369 * List</a> pattern.
370 *
371 * @param recipients is the builder of the expression used in the
372 * {@link org.apache.camel.processor.RecipientList}
373 * to decide the destinations
374 */
375 public Type recipientList(Expression recipients) {
376 RecipientListType answer = new RecipientListType(recipients);
377 addOutput(answer);
378 return (Type) this;
379 }
380
381 /**
382 * Creates a dynamic <a
383 * href="http://activemq.apache.org/camel/recipient-list.html">Recipient
384 * List</a> pattern.
385 *
386 * @return the expression clause for the expression used in the
387 * {@link org.apache.camel.processor.RecipientList}
388 * to decide the destinations
389 */
390 public ExpressionClause<ProcessorType<Type>> recipientList() {
391 RecipientListType answer = new RecipientListType();
392 addOutput(answer);
393 ExpressionClause<ProcessorType<Type>> clause = new ExpressionClause<ProcessorType<Type>>((Type) this);
394 answer.setExpression(clause);
395 return clause;
396 }
397
398 /**
399 * Creates a <a
400 * href="http://activemq.apache.org/camel/routing-slip.html">Routing
401 * Slip</a> pattern.
402 *
403 * @param header is the header that the {@link org.apache.camel.processor.RoutingSlip RoutingSlip}
404 * class will look in for the list of URIs to route the message to.
405 * @param uriDelimiter is the delimiter that will be used to split up
406 * the list of URIs in the routing slip.
407 */
408 public Type routingSlip(String header, String uriDelimiter) {
409 RoutingSlipType answer = new RoutingSlipType(header, uriDelimiter);
410 addOutput(answer);
411 return (Type) this;
412 }
413
414 /**
415 * Creates a <a
416 * href="http://activemq.apache.org/camel/routing-slip.html">Routing
417 * Slip</a> pattern.
418 *
419 * @param header is the header that the {@link org.apache.camel.processor.RoutingSlip RoutingSlip}
420 * class will look in for the list of URIs to route the message to. The list of URIs
421 * will be split based on the default delimiter
422 * {@link RoutingSlipType#DEFAULT_DELIMITER}.
423 */
424 public Type routingSlip(String header) {
425 RoutingSlipType answer = new RoutingSlipType(header);
426 addOutput(answer);
427 return (Type) this;
428 }
429
430 /**
431 * Creates a <a
432 * href="http://activemq.apache.org/camel/routing-slip.html">Routing
433 * Slip</a> pattern with the default header {@link RoutingSlipType#ROUTING_SLIP_HEADER}.
434 * The list of URIs in the header will be split based on the default delimiter
435 * {@link RoutingSlipType#DEFAULT_DELIMITER}.
436 */
437 public Type routingSlip() {
438 RoutingSlipType answer = new RoutingSlipType();
439 addOutput(answer);
440 return (Type) this;
441 }
442
443 /**
444 * Creates the <a
445 * href="http://activemq.apache.org/camel/splitter.html">Splitter</a>
446 * pattern where an expression is evaluated to iterate through each of the
447 * parts of a message and then each part is then send to some endpoint.
448 * This splitter responds with the latest message returned from destination
449 * endpoint.
450 *
451 * @param recipients the expression on which to split
452 * @return the builder
453 */
454 public SplitterType splitter(Expression recipients) {
455 SplitterType answer = new SplitterType(recipients);
456 addOutput(answer);
457 return answer;
458 }
459
460 /**
461 * Creates the <a
462 * href="http://activemq.apache.org/camel/splitter.html">Splitter</a>
463 * pattern where an expression is evaluated to iterate through each of the
464 * parts of a message and then each part is then send to some endpoint.
465 * This splitter responds with the latest message returned from destination
466 * endpoint.
467 *
468 * @return the expression clause for the expression on which to split
469 */
470 public ExpressionClause<SplitterType> splitter() {
471 SplitterType answer = new SplitterType();
472 addOutput(answer);
473 return ExpressionClause.createAndSetExpression(answer);
474 }
475
476 /**
477 * Creates the <a
478 * href="http://activemq.apache.org/camel/splitter.html">Splitter</a>
479 * pattern where an expression is evaluated to iterate through each of the
480 * parts of a message and then each part is then send to some endpoint.
481 * Answer from the splitter is produced using given {@link AggregationStrategy}
482 * @param partsExpression the expression on which to split
483 * @param aggregationStrategy the strategy used to aggregate responses for
484 * every part
485 * @return the builder
486 */
487 public SplitterType splitter(Expression partsExpression, AggregationStrategy aggregationStrategy) {
488 SplitterType answer = new SplitterType(partsExpression);
489 addOutput(answer);
490 answer.setAggregationStrategy(aggregationStrategy);
491 return answer;
492 }
493
494 /**
495 * Creates the <a
496 * href="http://activemq.apache.org/camel/splitter.html">Splitter</a>
497 * pattern where an expression is evaluated to iterate through each of the
498 * parts of a message and then each part is then send to some endpoint.
499 * Answer from the splitter is produced using given {@link AggregationStrategy}
500 * @param aggregationStrategy the strategy used to aggregate responses for
501 * every part
502 * @return the expression clause for the expression on which to split
503 */
504 public ExpressionClause<SplitterType> splitter(AggregationStrategy aggregationStrategy) {
505 SplitterType answer = new SplitterType();
506 addOutput(answer);
507 answer.setAggregationStrategy(aggregationStrategy);
508 return ExpressionClause.createAndSetExpression(answer);
509 }
510
511 /**
512 * Creates the <a
513 * href="http://activemq.apache.org/camel/splitter.html">Splitter</a>
514 * pattern where an expression is evaluated to iterate through each of the
515 * parts of a message and then each part is then send to some endpoint.
516 * This splitter responds with the latest message returned from destination
517 * endpoint.
518 *
519 * @param recipients the expression on which to split
520 * @param parallelProcessing if is <tt>true</tt> camel will fork thread to call the endpoint producer
521 * @return the builder
522 */
523 public SplitterType splitter(Expression recipients, boolean parallelProcessing) {
524 SplitterType answer = new SplitterType(recipients);
525 addOutput(answer);
526 answer.setParallelProcessing(parallelProcessing);
527 return answer;
528 }
529
530 /**
531 * Creates the <a
532 * href="http://activemq.apache.org/camel/splitter.html">Splitter</a>
533 * pattern where an expression is evaluated to iterate through each of the
534 * parts of a message and then each part is then send to some endpoint.
535 * This splitter responds with the latest message returned from destination
536 * endpoint.
537 *
538 * @param recipients the expression on which to split
539 * @param parallelProcessing if is <tt>true</tt> camel will fork thread to call the endpoint producer
540 * @param threadPoolExecutor override the default {@link ThreadPoolExecutor}
541 * @return the builder
542 */
543 public SplitterType splitter(Expression recipients, boolean parallelProcessing, ThreadPoolExecutor threadPoolExecutor) {
544 SplitterType answer = new SplitterType(recipients);
545 addOutput(answer);
546 answer.setParallelProcessing(parallelProcessing);
547 answer.setThreadPoolExecutor(threadPoolExecutor);
548 return answer;
549 }
550
551 /**
552 * Creates the <a
553 * href="http://activemq.apache.org/camel/splitter.html">Splitter</a>
554 * pattern where an expression is evaluated to iterate through each of the
555 * parts of a message and then each part is then send to some endpoint.
556 * This splitter responds with the latest message returned from destination
557 * endpoint.
558 *
559 * @param parallelProcessing if is <tt>true</tt> camel will fork thread to call the endpoint producer
560 * @return the expression clause for the expression on which to split
561 */
562 public ExpressionClause<SplitterType> splitter(boolean parallelProcessing) {
563 SplitterType answer = new SplitterType();
564 addOutput(answer);
565 answer.setParallelProcessing(parallelProcessing);
566 return ExpressionClause.createAndSetExpression(answer);
567 }
568
569 /**
570 * Creates the <a
571 * href="http://activemq.apache.org/camel/splitter.html">Splitter</a>
572 * pattern where an expression is evaluated to iterate through each of the
573 * parts of a message and then each part is then send to some endpoint.
574 * This splitter responds with the latest message returned from destination
575 * endpoint.
576 *
577 * @param parallelProcessing if is <tt>true</tt> camel will fork thread to call the endpoint producer
578 * @param threadPoolExecutor override the default {@link ThreadPoolExecutor}
579 * @return the expression clause for the expression on which to split
580 */
581 public ExpressionClause<SplitterType> splitter(boolean parallelProcessing, ThreadPoolExecutor threadPoolExecutor) {
582 SplitterType answer = new SplitterType();
583 addOutput(answer);
584 answer.setParallelProcessing(parallelProcessing);
585 answer.setThreadPoolExecutor(threadPoolExecutor);
586 return ExpressionClause.createAndSetExpression(answer);
587 }
588
589 /**
590 * Creates the <a
591 * href="http://activemq.apache.org/camel/splitter.html">Splitter</a>
592 * pattern where an expression is evaluated to iterate through each of the
593 * parts of a message and then each part is then send to some endpoint.
594 * Answer from the splitter is produced using given {@link AggregationStrategy}
595 * @param partsExpression the expression on which to split
596 * @param aggregationStrategy the strategy used to aggregate responses for
597 * every part
598 * @param parallelProcessing if is <tt>true</tt> camel will fork thread to call the endpoint producer
599 * @return the builder
600 */
601 public SplitterType splitter(Expression partsExpression,
602 AggregationStrategy aggregationStrategy, boolean parallelProcessing) {
603 SplitterType answer = new SplitterType(partsExpression);
604 addOutput(answer);
605 answer.setAggregationStrategy(aggregationStrategy);
606 answer.setParallelProcessing(parallelProcessing);
607 return answer;
608 }
609
610 /**
611 * Creates the <a
612 * href="http://activemq.apache.org/camel/splitter.html">Splitter</a>
613 * pattern where an expression is evaluated to iterate through each of the
614 * parts of a message and then each part is then send to some endpoint.
615 * Answer from the splitter is produced using given {@link AggregationStrategy}
616 * @param partsExpression the expression on which to split
617 * @param aggregationStrategy the strategy used to aggregate responses for
618 * every part
619 * @param parallelProcessing if is <tt>true</tt> camel will fork thread to call the endpoint producer
620 * @param threadPoolExecutor override the default {@link ThreadPoolExecutor}
621 * @return the builder
622 */
623 public SplitterType splitter(Expression partsExpression,
624 AggregationStrategy aggregationStrategy, boolean parallelProcessing, ThreadPoolExecutor threadPoolExecutor) {
625 SplitterType answer = new SplitterType(partsExpression);
626 addOutput(answer);
627 answer.setAggregationStrategy(aggregationStrategy);
628 answer.setParallelProcessing(parallelProcessing);
629 answer.setThreadPoolExecutor(threadPoolExecutor);
630 return answer;
631 }
632
633 /**
634 * Creates the <a
635 * href="http://activemq.apache.org/camel/splitter.html">Splitter</a>
636 * pattern where an expression is evaluated to iterate through each of the
637 * parts of a message and then each part is then send to some endpoint.
638 * Answer from the splitter is produced using given {@link AggregationStrategy}
639 * @param aggregationStrategy the strategy used to aggregate responses for
640 * every part
641 * @param parallelProcessing if is <tt>true</tt> camel will fork thread to call the endpoint producer
642 * @return the expression clause for the expression on which to split
643 */
644 public ExpressionClause<SplitterType> splitter(AggregationStrategy aggregationStrategy, boolean parallelProcessing) {
645 SplitterType answer = new SplitterType();
646 addOutput(answer);
647 answer.setAggregationStrategy(aggregationStrategy);
648 answer.setParallelProcessing(parallelProcessing);
649 return ExpressionClause.createAndSetExpression(answer);
650 }
651
652 /**
653 * Creates the <a
654 * href="http://activemq.apache.org/camel/splitter.html">Splitter</a>
655 * pattern where an expression is evaluated to iterate through each of the
656 * parts of a message and then each part is then send to some endpoint.
657 * Answer from the splitter is produced using given {@link AggregationStrategy}
658 * @param aggregationStrategy the strategy used to aggregate responses for
659 * every part
660 * @param parallelProcessing if is <tt>true</tt> camel will fork thread to call the endpoint producer
661 * @param threadPoolExecutor override the default {@link ThreadPoolExecutor}
662 * @return the expression clause for the expression on which to split
663 */
664 public ExpressionClause<SplitterType> splitter(AggregationStrategy aggregationStrategy, boolean parallelProcessing, ThreadPoolExecutor threadPoolExecutor) {
665 SplitterType answer = new SplitterType();
666 addOutput(answer);
667 answer.setAggregationStrategy(aggregationStrategy);
668 answer.setParallelProcessing(parallelProcessing);
669 answer.setThreadPoolExecutor(threadPoolExecutor);
670 return ExpressionClause.createAndSetExpression(answer);
671 }
672
673 /**
674 * Creates the <a
675 * href="http://activemq.apache.org/camel/resequencer.html">Resequencer</a>
676 * pattern where a list of expressions are evaluated to be able to compare
677 * the message exchanges to reorder them. e.g. you may wish to sort by some
678 * headers
679 *
680 * @return the expression clause for the expressions on which to compare messages in order
681 */
682 public ExpressionClause<ResequencerType> resequencer() {
683 ResequencerType answer = new ResequencerType();
684 addOutput(answer);
685 ExpressionClause<ResequencerType> clause = new ExpressionClause<ResequencerType>(answer);
686 answer.expression(clause);
687 return clause;
688 }
689
690 /**
691 * Creates the <a
692 * href="http://activemq.apache.org/camel/resequencer.html">Resequencer</a>
693 * pattern where an expression is evaluated to be able to compare the
694 * message exchanges to reorder them. e.g. you may wish to sort by some
695 * header
696 *
697 * @param expression the expression on which to compare messages in order
698 * @return the builder
699 */
700 public ResequencerType resequencer(Expression<Exchange> expression) {
701 return resequencer(Collections.<Expression>singletonList(expression));
702 }
703
704 /**
705 * Creates the <a
706 * href="http://activemq.apache.org/camel/resequencer.html">Resequencer</a>
707 * pattern where a list of expressions are evaluated to be able to compare
708 * the message exchanges to reorder them. e.g. you may wish to sort by some
709 * headers
710 *
711 * @param expressions the expressions on which to compare messages in order
712 * @return the builder
713 */
714 public ResequencerType resequencer(List<Expression> expressions) {
715 ResequencerType answer = new ResequencerType(expressions);
716 addOutput(answer);
717 return answer;
718 }
719
720 /**
721 * Creates the <a
722 * href="http://activemq.apache.org/camel/resequencer.html">Resequencer</a>
723 * pattern where a list of expressions are evaluated to be able to compare
724 * the message exchanges to reorder them. e.g. you may wish to sort by some
725 * headers
726 *
727 * @param expressions the expressions on which to compare messages in order
728 * @return the builder
729 */
730 public ResequencerType resequencer(Expression... expressions) {
731 List<Expression> list = new ArrayList<Expression>();
732 list.addAll(Arrays.asList(expressions));
733 return resequencer(list);
734 }
735
736 /**
737 * Creates an <a
738 * href="http://activemq.apache.org/camel/aggregator.html">Aggregator</a>
739 * pattern where a batch of messages are processed (up to a maximum amount
740 * or until some timeout is reached) and messages for the same correlation
741 * key are combined together using some kind of {@link AggregationStrategy}
742 * (by default the latest message is used) to compress many message exchanges
743 * into a smaller number of exchanges.
744 * <p/>
745 * A good example of this is stock market data; you may be receiving 30,000
746 * messages/second and you may want to throttle it right down so that multiple
747 * messages for the same stock are combined (or just the latest message is used
748 * and older prices are discarded). Another idea is to combine line item messages
749 * together into a single invoice message.
750 */
751 public ExpressionClause<AggregatorType> aggregator() {
752 if (!getOutputs().isEmpty()) {
753 throw new IllegalArgumentException("Aggregator must be the only output added to the route: " + this);
754 }
755 AggregatorType answer = new AggregatorType();
756 addOutput(answer);
757 return ExpressionClause.createAndSetExpression(answer);
758 }
759
760 /**
761 * Creates an <a
762 * href="http://activemq.apache.org/camel/aggregator.html">Aggregator</a>
763 * pattern where a batch of messages are processed (up to a maximum amount
764 * or until some timeout is reached) and messages for the same correlation
765 * key are combined together using some kind of {@link AggregationStrategy}
766 * (by default the latest message is used) to compress many message exchanges
767 * into a smaller number of exchanges.
768 * <p/>
769 * A good example of this is stock market data; you may be receiving 30,000
770 * messages/second and you may want to throttle it right down so that multiple
771 * messages for the same stock are combined (or just the latest message is used
772 * and older prices are discarded). Another idea is to combine line item messages
773 * together into a single invoice message.
774 *
775 * @param aggregationStrategy the strategy used for the aggregation
776 */
777 public ExpressionClause<AggregatorType> aggregator(AggregationStrategy aggregationStrategy) {
778 if (!getOutputs().isEmpty()) {
779 throw new IllegalArgumentException("Aggregator must be the only output added to the route: " + this);
780 }
781 AggregatorType answer = new AggregatorType();
782 answer.setAggregationStrategy(aggregationStrategy);
783 addOutput(answer);
784 return ExpressionClause.createAndSetExpression(answer);
785 }
786
787 /**
788 * Creates an <a
789 * href="http://activemq.apache.org/camel/aggregator.html">Aggregator</a>
790 * pattern using a custom aggregation collection implementation. The aggregation collection must
791 * be configued with the strategy and correlation expression that this aggregator should use.
792 * This avoids duplicating this configuration on both the collection and the aggregator itself.
793 *
794 * @param aggregationCollection the collection used to perform the aggregation
795 */
796 public AggregatorType aggregator(AggregationCollection aggregationCollection) {
797 if (!getOutputs().isEmpty()) {
798 throw new IllegalArgumentException("Aggregator must be the only output added to the route: " + this);
799 }
800 AggregatorType answer = new AggregatorType();
801 answer.setAggregationCollection(aggregationCollection);
802 addOutput(answer);
803 return answer;
804 }
805
806 /**
807 * Creates an <a
808 * href="http://activemq.apache.org/camel/aggregator.html">Aggregator</a>
809 * pattern where a batch of messages are processed (up to a maximum amount
810 * or until some timeout is reached) and messages for the same correlation
811 * key are combined together using some kind of {@link AggregationStrategy}
812 * (by default the latest message is used) to compress many message exchanges
813 * into a smaller number of exchanges.
814 * <p/>
815 * A good example of this is stock market data; you may be receiving 30,000
816 * messages/second and you may want to throttle it right down so that multiple
817 * messages for the same stock are combined (or just the latest message is used
818 * and older prices are discarded). Another idea is to combine line item messages
819 * together into a single invoice message.
820 *
821 * @param correlationExpression the expression used to calculate the
822 * correlation key. For a JMS message this could be the
823 * expression <code>header("JMSDestination")</code> or
824 * <code>header("JMSCorrelationID")</code>
825 */
826 public AggregatorType aggregator(Expression correlationExpression) {
827 if (!getOutputs().isEmpty()) {
828 throw new IllegalArgumentException("Aggregator must be the only output added to the route: " + this);
829 }
830 AggregatorType answer = new AggregatorType(correlationExpression);
831 addOutput(answer);
832 return answer;
833 }
834
835 /**
836 * Creates an <a
837 * href="http://activemq.apache.org/camel/aggregator.html">Aggregator</a>
838 * pattern where a batch of messages are processed (up to a maximum amount
839 * or until some timeout is reached) and messages for the same correlation
840 * key are combined together using some kind of {@link AggregationStrategy}
841 * (by default the latest message is used) to compress many message exchanges
842 * into a smaller number of exchanges.
843 * <p/>
844 * A good example of this is stock market data; you may be receiving 30,000
845 * messages/second and you may want to throttle it right down so that multiple
846 * messages for the same stock are combined (or just the latest message is used
847 * and older prices are discarded). Another idea is to combine line item messages
848 * together into a single invoice message.
849 *
850 * @param correlationExpression the expression used to calculate the
851 * correlation key. For a JMS message this could be the
852 * expression <code>header("JMSDestination")</code> or
853 * <code>header("JMSCorrelationID")</code>
854 */
855 public AggregatorType aggregator(Expression correlationExpression, AggregationStrategy aggregationStrategy) {
856 if (!getOutputs().isEmpty()) {
857 throw new IllegalArgumentException("Aggregator must be the only output added to the route: " + this);
858 }
859 AggregatorType answer = new AggregatorType(correlationExpression, aggregationStrategy);
860 addOutput(answer);
861 return answer;
862 }
863
864 /**
865 * Creates the <a
866 * href="http://activemq.apache.org/camel/delayer.html">Delayer</a> pattern
867 * where an expression is used to calculate the time which the message will
868 * be dispatched on
869 *
870 * @param processAtExpression an expression to calculate the time at which
871 * the messages should be processed
872 * @return the builder
873 */
874 public DelayerType delayer(Expression<Exchange> processAtExpression) {
875 return delayer(processAtExpression, 0L);
876 }
877
878 /**
879 * Creates the <a
880 * href="http://activemq.apache.org/camel/delayer.html">Delayer</a> pattern
881 * where an expression is used to calculate the time which the message will
882 * be dispatched on
883 *
884 * @param processAtExpression an expression to calculate the time at which
885 * the messages should be processed
886 * @param delay the delay in milliseconds which is added to the
887 * processAtExpression to determine the time the message
888 * should be processed
889 * @return the builder
890 */
891 public DelayerType delayer(Expression<Exchange> processAtExpression, long delay) {
892 DelayerType answer = new DelayerType(processAtExpression, delay);
893 addOutput(answer);
894 return answer;
895 }
896
897 /**
898 * Creates the <a
899 * href="http://activemq.apache.org/camel/delayer.html">Delayer</a> pattern
900 * where an expression is used to calculate the time which the message will
901 * be dispatched on
902 * @return the expression clause to create the expression
903 */
904 public ExpressionClause<DelayerType> delayer() {
905 DelayerType answer = new DelayerType();
906 addOutput(answer);
907 return ExpressionClause.createAndSetExpression(answer);
908 }
909
910 /**
911 * Creates the <a
912 * href="http://activemq.apache.org/camel/delayer.html">Delayer</a> pattern
913 * where a fixed amount of milliseconds are used to delay processing of a
914 * message exchange
915 *
916 * @param delay the default delay in milliseconds
917 * @return the builder
918 */
919 public DelayerType delayer(long delay) {
920 return delayer(null, delay);
921 }
922
923 /**
924 * Creates the <a
925 * href="http://activemq.apache.org/camel/delayer.html">Delayer</a> pattern
926 * where an expression is used to calculate the time which the message will
927 * be dispatched on
928 *
929 * @return the builder
930 */
931 public ThrottlerType throttler(long maximumRequestCount) {
932 ThrottlerType answer = new ThrottlerType(maximumRequestCount);
933 addOutput(answer);
934 return answer;
935 }
936
937 /**
938 * Creates a expression which must evaluate to an integer that determines
939 * how many times the exchange should be sent down the rest of the route.
940 *
941 * @return the clause used to create the loop expression
942 */
943 public ExpressionClause<LoopType> loop() {
944 LoopType loop = new LoopType();
945 addOutput(loop);
946 return ExpressionClause.createAndSetExpression(loop);
947 }
948
949 public LoopType loop(Expression<?> expression) {
950 LoopType loop = getNodeFactory().createLoop();
951 loop.setExpression(expression);
952 addOutput(loop);
953 return loop;
954 }
955
956 public LoopType loop(int count) {
957 LoopType loop = getNodeFactory().createLoop();
958 loop.setExpression(new ConstantExpression(Integer.toString(count)));
959 addOutput(loop);
960 return loop;
961 }
962
963 public Type throwFault(Throwable fault) {
964 ThrowFaultType answer = new ThrowFaultType();
965 answer.setFault(fault);
966 addOutput(answer);
967 return (Type) this;
968 }
969
970 public Type throwFault(String message) {
971 return throwFault(new CamelException(message));
972 }
973
974 /**
975 * Intercepts outputs added to this node in the future (i.e. intercepts outputs added after this statement)
976 */
977 public Type interceptor(String ref) {
978 InterceptorRef interceptor = new InterceptorRef(ref);
979 intercept(interceptor);
980 return (Type) this;
981 }
982
983 /**
984 * Intercepts outputs added to this node in the future (i.e. intercepts outputs added after this statement)
985 */
986 public Type intercept(DelegateProcessor interceptor) {
987 intercept(new InterceptorRef(interceptor));
988 //lastInterceptor = interceptor;
989 return (Type) this;
990 }
991
992 /**
993 * Intercepts outputs added to this node in the future (i.e. intercepts outputs added after this statement)
994 */
995 public InterceptType intercept() {
996 InterceptType answer = new InterceptType();
997 addOutput(answer);
998 return answer;
999 }
1000
1001 /**
1002 * Intercepts outputs added to this node in the future (i.e. intercepts outputs added after this statement)
1003 */
1004 public void intercept(InterceptorType interceptor) {
1005 addOutput(interceptor);
1006 pushBlock(interceptor);
1007 }
1008
1009 /**
1010 * Adds an interceptor around the whole of this nodes processing
1011 *
1012 * @param interceptor
1013 */
1014 public void addInterceptor(InterceptorType interceptor) {
1015 interceptors.add(interceptor);
1016 }
1017
1018 /**
1019 * Adds an interceptor around the whole of this nodes processing
1020 *
1021 * @param interceptor
1022 */
1023 public void addInterceptor(DelegateProcessor interceptor) {
1024 addInterceptor(new InterceptorRef(interceptor));
1025 }
1026
1027 public void pushBlock(Block block) {
1028 blocks.add(block);
1029 }
1030
1031 public Block popBlock() {
1032 return blocks.isEmpty() ? null : blocks.removeLast();
1033 }
1034
1035 public Type proceed() {
1036 ProceedType proceed = null;
1037 ProcessorType currentProcessor = this;
1038
1039 if (currentProcessor instanceof InterceptType) {
1040 proceed = ((InterceptType) currentProcessor).getProceed();
1041 LOG.info("proceed() is the implied and hence not needed for an intercept()");
1042 }
1043 if (proceed == null) {
1044 for (ProcessorType node = parent; node != null; node = node.getParent()) {
1045 if (node instanceof InterceptType) {
1046 InterceptType intercept = (InterceptType)node;
1047 proceed = intercept.getProceed();
1048 break;
1049 }
1050 }
1051
1052 if (proceed == null) {
1053 throw new IllegalArgumentException("Cannot use proceed() without being within an intercept() block");
1054 }
1055
1056 }
1057
1058 addOutput(proceed);
1059 return (Type) this;
1060 }
1061
1062 public Type stop() {
1063 ProcessorType currentProcessor = this;
1064
1065 if (currentProcessor instanceof InterceptType) {
1066 ((InterceptType) currentProcessor).stopIntercept();
1067 } else {
1068 ProcessorType node;
1069 for (node = parent; node != null; node = node.getParent()) {
1070 if (node instanceof InterceptType) {
1071 ((InterceptType) node).stopIntercept();
1072 break;
1073 }
1074 }
1075 if (node == null) {
1076 throw new IllegalArgumentException("Cannot use stop() without being within an intercept() block");
1077 }
1078 }
1079
1080 return (Type) this;
1081 }
1082
1083 /**
1084 * Catches an exception type.
1085 *
1086 * @deprecated Please use {@link #onException(Class)} instead. Will be removed in Camel 2.0.
1087 */
1088 public ExceptionType exception(Class exceptionType) {
1089 return onException(exceptionType);
1090 }
1091
1092 /**
1093 * Catches an exception type.
1094 */
1095 public ExceptionType onException(Class exceptionType) {
1096 ExceptionType answer = new ExceptionType(exceptionType);
1097 addOutput(answer);
1098 return answer;
1099 }
1100
1101 /**
1102 * Apply an interceptor route if the predicate is true
1103 */
1104 public ChoiceType intercept(Predicate predicate) {
1105 InterceptType answer = new InterceptType();
1106 addOutput(answer);
1107 return answer.when(predicate);
1108 }
1109
1110 public Type interceptors(String... refs) {
1111 for (String ref : refs) {
1112 interceptor(ref);
1113 }
1114 return (Type) this;
1115 }
1116
1117 /**
1118 * Trace logs the exchange before it goes to the next processing step using
1119 * the {@link #DEFAULT_TRACE_CATEGORY} logging category.
1120 *
1121 * @deprecated Please use <a href="http://activemq.apache.org/camel/tracer.html>Tracer Support</a>
1122 * instead. Will be removed in Camel 2.0.
1123 */
1124 public Type trace() {
1125 return trace(DEFAULT_TRACE_CATEGORY);
1126 }
1127
1128 /**
1129 * Trace logs the exchange before it goes to the next processing step using
1130 * the specified logging category.
1131 *
1132 * @param category the logging category trace messages will sent to.
1133 *
1134 * @deprecated Please use <a href="http://activemq.apache.org/camel/tracer.html>Tracer Support</a>
1135 * instead. Will be removed in Camel 2.0.
1136 */
1137 public Type trace(String category) {
1138 final Log log = LogFactory.getLog(category);
1139 return intercept(new DelegateProcessor() {
1140 @Override
1141 public void process(Exchange exchange) throws Exception {
1142 log.trace(exchange);
1143 processNext(exchange);
1144 }
1145 });
1146 }
1147
1148 public PolicyRef policies() {
1149 PolicyRef answer = new PolicyRef();
1150 addOutput(answer);
1151 return answer;
1152 }
1153
1154 public PolicyRef policy(Policy policy) {
1155 PolicyRef answer = new PolicyRef(policy);
1156 addOutput(answer);
1157 return answer;
1158 }
1159
1160 /**
1161 * Forces handling of faults as exceptions
1162 *
1163 * @return the current builder with the fault handler configured
1164 */
1165 public Type handleFault() {
1166 intercept(new HandleFaultType());
1167 return (Type) this;
1168 }
1169
1170 /**
1171 * Installs the given error handler builder
1172 *
1173 * @param errorHandlerBuilder the error handler to be used by default for
1174 * all child routes
1175 * @return the current builder with the error handler configured
1176 */
1177 public Type errorHandler(ErrorHandlerBuilder errorHandlerBuilder) {
1178 setErrorHandlerBuilder(errorHandlerBuilder);
1179 return (Type) this;
1180 }
1181
1182 /**
1183 * Configures whether or not the error handler is inherited by every
1184 * processing node (or just the top most one)
1185 *
1186 * @param condition the flag as to whether error handlers should be
1187 * inherited or not
1188 * @return the current builder
1189 */
1190 public Type inheritErrorHandler(boolean condition) {
1191 setInheritErrorHandlerFlag(condition);
1192 return (Type) this;
1193 }
1194
1195 // Transformers
1196 // -------------------------------------------------------------------------
1197
1198 /**
1199 * Adds the custom processor to this destination which could be a final
1200 * destination, or could be a transformation in a pipeline
1201 */
1202 public Type process(Processor processor) {
1203 ProcessorRef answer = new ProcessorRef(processor);
1204 addOutput(answer);
1205 return (Type) this;
1206 }
1207
1208 /**
1209 * Adds the custom processor reference to this destination which could be a final
1210 * destination, or could be a transformation in a pipeline
1211 */
1212 public Type processRef(String ref) {
1213 ProcessorRef answer = new ProcessorRef();
1214 answer.setRef(ref);
1215 addOutput(answer);
1216 return (Type) this;
1217 }
1218
1219 /**
1220 * Adds a bean which is invoked which could be a final destination, or could
1221 * be a transformation in a pipeline
1222 */
1223 public Type bean(Object bean) {
1224 BeanRef answer = new BeanRef();
1225 answer.setBean(bean);
1226 addOutput(answer);
1227 return (Type) this;
1228 }
1229
1230 /**
1231 * Adds a bean and method which is invoked which could be a final
1232 * destination, or could be a transformation in a pipeline
1233 */
1234 public Type bean(Object bean, String method) {
1235 BeanRef answer = new BeanRef();
1236 answer.setBean(bean);
1237 answer.setMethod(method);
1238 addOutput(answer);
1239 return (Type) this;
1240 }
1241
1242 /**
1243 * Adds a bean by type which is invoked which could be a final destination, or could
1244 * be a transformation in a pipeline
1245 */
1246 public Type bean(Class beanType) {
1247 BeanRef answer = new BeanRef();
1248 answer.setBeanType(beanType);
1249 addOutput(answer);
1250 return (Type) this;
1251 }
1252
1253 /**
1254 * Adds a bean type and method which is invoked which could be a final
1255 * destination, or could be a transformation in a pipeline
1256 */
1257 public Type bean(Class beanType, String method) {
1258 BeanRef answer = new BeanRef();
1259 answer.setBeanType(beanType);
1260 answer.setMethod(method);
1261 addOutput(answer);
1262 return (Type) this;
1263 }
1264
1265 /**
1266 * Adds a bean which is invoked which could be a final destination, or could
1267 * be a transformation in a pipeline
1268 */
1269 public Type beanRef(String ref) {
1270 BeanRef answer = new BeanRef(ref);
1271 addOutput(answer);
1272 return (Type) this;
1273 }
1274
1275 /**
1276 * Adds a bean and method which is invoked which could be a final
1277 * destination, or could be a transformation in a pipeline
1278 */
1279 public Type beanRef(String ref, String method) {
1280 BeanRef answer = new BeanRef(ref, method);
1281 addOutput(answer);
1282 return (Type) this;
1283 }
1284
1285 /**
1286 * Adds a processor which sets the body on the IN message
1287 */
1288 public ExpressionClause<ProcessorType<Type>> setBody() {
1289 ExpressionClause<ProcessorType<Type>> clause = new ExpressionClause<ProcessorType<Type>>((Type) this);
1290 SetBodyType answer = new SetBodyType(clause);
1291 addOutput(answer);
1292 return clause;
1293 }
1294
1295 /**
1296 * Adds a processor which sets the body on the IN message
1297 */
1298 public Type setBody(Expression expression) {
1299 SetBodyType answer = new SetBodyType(expression);
1300 addOutput(answer);
1301 return (Type) this;
1302 }
1303
1304 /**
1305 * Adds a processor which sets the body on the OUT message
1306 *
1307 * @deprecated Please use {@link #transform(Expression)} instead. Will be removed in Camel 2.0.
1308 */
1309 @Deprecated
1310 public Type setOutBody(Expression expression) {
1311 return transform(expression);
1312 }
1313
1314 /**
1315 * Adds a processor which sets the body on the OUT message
1316 *
1317 * @deprecated Please use {@link #transform()} instead. Will be removed in Camel 2.0.
1318 */
1319 @Deprecated
1320 public ExpressionClause<ProcessorType<Type>> setOutBody() {
1321 return transform();
1322 }
1323
1324 /**
1325 * Adds a processor which sets the body on the OUT message
1326 */
1327 public Type transform(Expression expression) {
1328 TransformType answer = new TransformType(expression);
1329 addOutput(answer);
1330 return (Type) this;
1331 }
1332
1333 /**
1334 * Adds a processor which sets the body on the OUT message
1335 */
1336 public ExpressionClause<ProcessorType<Type>> transform() {
1337 ExpressionClause<ProcessorType<Type>> clause = new ExpressionClause<ProcessorType<Type>>((Type) this);
1338 TransformType answer = new TransformType(clause);
1339 addOutput(answer);
1340 return clause;
1341 }
1342
1343 /**
1344 * Adds a processor which sets the body on the FAULT message
1345 */
1346 public Type setFaultBody(Expression expression) {
1347 return process(ProcessorBuilder.setFaultBody(expression));
1348 }
1349
1350 /**
1351 * Adds a processor which sets the header on the IN message
1352 */
1353 public ExpressionClause<ProcessorType<Type>> setHeader(String name) {
1354 ExpressionClause<ProcessorType<Type>> clause = new ExpressionClause<ProcessorType<Type>>((Type) this);
1355 SetHeaderType answer = new SetHeaderType(name, clause);
1356 addOutput(answer);
1357 return clause;
1358 }
1359
1360 /**
1361 * Adds a processor which sets the header on the IN message
1362 */
1363 public Type setHeader(String name, Expression expression) {
1364 SetHeaderType answer = new SetHeaderType(name, expression);
1365 addOutput(answer);
1366 return (Type) this;
1367 }
1368
1369 /**
1370 * Adds a processor which sets the header on the IN message to the given value
1371 * @deprecated Please use {@link #setHeader(String, Expression)} instead. Will be removed in Camel 2.0.
1372 */
1373 public Type setHeader(String name, String value) {
1374 SetHeaderType answer = new SetHeaderType(name, value);
1375 addOutput(answer);
1376 return (Type) this;
1377 }
1378
1379 /**
1380 * Adds a processor which sets the header on the OUT message
1381 */
1382 public ExpressionClause<ProcessorType<Type>> setOutHeader(String name) {
1383 ExpressionClause<ProcessorType<Type>> clause = new ExpressionClause<ProcessorType<Type>>((Type) this);
1384 SetOutHeaderType answer = new SetOutHeaderType(name, clause);
1385 addOutput(answer);
1386 return clause;
1387 }
1388
1389 /**
1390 * Adds a processor which sets the header on the OUT message
1391 */
1392 public Type setOutHeader(String name, Expression expression) {
1393 SetOutHeaderType answer = new SetOutHeaderType(name, expression);
1394 addOutput(answer);
1395 return (Type) this;
1396 }
1397
1398 /**
1399 * Adds a processor which sets the header on the FAULT message
1400 */
1401 public Type setFaultHeader(String name, Expression expression) {
1402 return process(ProcessorBuilder.setFaultHeader(name, expression));
1403 }
1404
1405 /**
1406 * Adds a processor which sets the exchange property
1407 */
1408 public Type setProperty(String name, Expression expression) {
1409 SetPropertyType answer = new SetPropertyType(name, expression);
1410 addOutput(answer);
1411 return (Type) this;
1412 }
1413
1414
1415 /**
1416 * Adds a processor which sets the exchange property
1417 */
1418 public ExpressionClause<ProcessorType<Type>> setProperty(String name) {
1419 ExpressionClause<ProcessorType<Type>> clause = new ExpressionClause<ProcessorType<Type>>((Type) this);
1420 SetPropertyType answer = new SetPropertyType(name, clause);
1421 addOutput(answer);
1422 return clause;
1423 }
1424
1425 /**
1426 * Adds a processor which removes the header on the IN message
1427 */
1428 public Type removeHeader(String name) {
1429 RemoveHeaderType answer = new RemoveHeaderType(name);
1430 addOutput(answer);
1431 return (Type) this;
1432 }
1433
1434 /**
1435 * Adds a processor which removes the header on the FAULT message
1436 */
1437 public Type removeFaultHeader(String name) {
1438 return process(ProcessorBuilder.removeFaultHeader(name));
1439 }
1440
1441 /**
1442 * Adds a processor which removes the exchange property
1443 */
1444 public Type removeProperty(String name) {
1445 RemovePropertyType answer = new RemovePropertyType(name);
1446 addOutput(answer);
1447 return (Type) this;
1448 }
1449
1450 /**
1451 * Converts the IN message body to the specified type
1452 */
1453 public Type convertBodyTo(Class type) {
1454 addOutput(new ConvertBodyType(type));
1455 return (Type) this;
1456 }
1457
1458 /**
1459 * Converts the IN message body to the specified class type
1460 */
1461 public Type convertBodyTo(String typeString) {
1462 addOutput(new ConvertBodyType(typeString));
1463 return (Type) this;
1464 }
1465
1466 /**
1467 * Converts the OUT message body to the specified type
1468 *
1469 * @deprecated Please use {@link #convertBodyTo(Class)} instead. Will be removed in Camel 2.0.
1470 */
1471 @Deprecated
1472 public Type convertOutBodyTo(Class type) {
1473 return process(new ConvertBodyProcessor(type));
1474 }
1475
1476 /**
1477 * Converts the FAULT message body to the specified type
1478 *
1479 * @deprecated Please use {@link #convertBodyTo(Class)} instead. Will be removed in Camel 2.0.
1480 */
1481 @Deprecated
1482 public Type convertFaultBodyTo(Class type) {
1483 return process(new ConvertBodyProcessor(type));
1484 }
1485
1486 // DataFormat support
1487 // -------------------------------------------------------------------------
1488
1489 /**
1490 * Unmarshals the in body using a {@link DataFormat} expression to define
1491 * the format of the input message and the output will be set on the out message body.
1492 *
1493 * @return the expression to create the {@link DataFormat}
1494 */
1495 public DataFormatClause<ProcessorType<Type>> unmarshal() {
1496 return new DataFormatClause<ProcessorType<Type>>(this, DataFormatClause.Operation.Unmarshal);
1497 }
1498
1499 /**
1500 * Unmarshals the in body using the specified {@link DataFormat}
1501 * and sets the output on the out message body.
1502 *
1503 * @return this object
1504 */
1505 public Type unmarshal(DataFormatType dataFormatType) {
1506 addOutput(new UnmarshalType(dataFormatType));
1507 return (Type) this;
1508 }
1509
1510 /**
1511 * Unmarshals the in body using the specified {@link DataFormat}
1512 * and sets the output on the out message body.
1513 *
1514 * @return this object
1515 */
1516 public Type unmarshal(DataFormat dataFormat) {
1517 return unmarshal(new DataFormatType(dataFormat));
1518 }
1519
1520 /**
1521 * Unmarshals the in body using the specified {@link DataFormat}
1522 * reference in the {@link org.apache.camel.spi.Registry} and sets
1523 * the output on the out message body.
1524 *
1525 * @return this object
1526 */
1527 public Type unmarshal(String dataTypeRef) {
1528 addOutput(new UnmarshalType(dataTypeRef));
1529 return (Type) this;
1530 }
1531
1532 /**
1533 * Marshals the in body using a {@link DataFormat} expression to define
1534 * the format of the output which will be added to the out body.
1535 *
1536 * @return the expression to create the {@link DataFormat}
1537 */
1538 public DataFormatClause<ProcessorType<Type>> marshal() {
1539 return new DataFormatClause<ProcessorType<Type>>(this, DataFormatClause.Operation.Marshal);
1540 }
1541
1542 /**
1543 * Marshals the in body using the specified {@link DataFormat}
1544 * and sets the output on the out message body.
1545 *
1546 * @return this object
1547 */
1548 public Type marshal(DataFormatType dataFormatType) {
1549 addOutput(new MarshalType(dataFormatType));
1550 return (Type) this;
1551 }
1552
1553 /**
1554 * Marshals the in body using the specified {@link DataFormat}
1555 * and sets the output on the out message body.
1556 *
1557 * @return this object
1558 */
1559 public Type marshal(DataFormat dataFormat) {
1560 return marshal(new DataFormatType(dataFormat));
1561 }
1562
1563 /**
1564 * Marshals the in body the specified {@link DataFormat}
1565 * reference in the {@link org.apache.camel.spi.Registry} and sets
1566 * the output on the out message body.
1567 *
1568 * @return this object
1569 */
1570 public Type marshal(String dataTypeRef) {
1571 addOutput(new MarshalType(dataTypeRef));
1572 return (Type) this;
1573 }
1574
1575 // Properties
1576 // -------------------------------------------------------------------------
1577 @XmlTransient
1578 public ProcessorType<? extends ProcessorType> getParent() {
1579 return parent;
1580 }
1581
1582 public void setParent(ProcessorType<? extends ProcessorType> parent) {
1583 this.parent = parent;
1584 }
1585
1586 @XmlTransient
1587 public ErrorHandlerBuilder getErrorHandlerBuilder() {
1588 if (errorHandlerBuilder == null) {
1589 errorHandlerBuilder = createErrorHandlerBuilder();
1590 }
1591 return errorHandlerBuilder;
1592 }
1593
1594 /**
1595 * Sets the error handler to use with processors created by this builder
1596 */
1597 public void setErrorHandlerBuilder(ErrorHandlerBuilder errorHandlerBuilder) {
1598 this.errorHandlerBuilder = errorHandlerBuilder;
1599 }
1600
1601 /**
1602 * Sets the error handler if one is not already set
1603 */
1604 protected void setErrorHandlerBuilderIfNull(ErrorHandlerBuilder errorHandlerBuilder) {
1605 if (this.errorHandlerBuilder == null) {
1606 setErrorHandlerBuilder(errorHandlerBuilder);
1607 }
1608 }
1609
1610 public String getErrorHandlerRef() {
1611 return errorHandlerRef;
1612 }
1613
1614 /**
1615 * Sets the bean ref name of the error handler builder to use on this route
1616 */
1617 @XmlAttribute(required = false)
1618 public void setErrorHandlerRef(String errorHandlerRef) {
1619 this.errorHandlerRef = errorHandlerRef;
1620 setErrorHandlerBuilder(new ErrorHandlerBuilderRef(errorHandlerRef));
1621 }
1622
1623 @XmlTransient
1624 public boolean isInheritErrorHandler() {
1625 return isInheritErrorHandler(getInheritErrorHandlerFlag());
1626 }
1627
1628 /**
1629 * Lets default the inherit value to be true if there is none specified
1630 */
1631 public static boolean isInheritErrorHandler(Boolean value) {
1632 return value == null || value.booleanValue();
1633 }
1634
1635 @XmlAttribute(name = "inheritErrorHandler", required = false)
1636 public Boolean getInheritErrorHandlerFlag() {
1637 return inheritErrorHandlerFlag;
1638 }
1639
1640 public void setInheritErrorHandlerFlag(Boolean inheritErrorHandlerFlag) {
1641 this.inheritErrorHandlerFlag = inheritErrorHandlerFlag;
1642 }
1643
1644 @XmlTransient
1645 public NodeFactory getNodeFactory() {
1646 if (nodeFactory == null) {
1647 nodeFactory = new NodeFactory();
1648 }
1649 return nodeFactory;
1650 }
1651
1652 public void setNodeFactory(NodeFactory nodeFactory) {
1653 this.nodeFactory = nodeFactory;
1654 }
1655
1656 /**
1657 * Returns a label to describe this node such as the expression if some kind of expression node
1658 */
1659 public String getLabel() {
1660 return "";
1661 }
1662
1663 // Implementation methods
1664 // -------------------------------------------------------------------------
1665
1666 /**
1667 * Creates the processor and wraps it in any necessary interceptors and
1668 * error handlers
1669 */
1670 protected Processor makeProcessor(RouteContext routeContext) throws Exception {
1671 Processor processor = createProcessor(routeContext);
1672 return wrapProcessor(routeContext, processor);
1673 }
1674
1675 /**
1676 * A strategy method which allows derived classes to wrap the child
1677 * processor in some kind of interceptor
1678 *
1679 * @param routeContext
1680 * @param target the processor which can be wrapped
1681 * @return the original processor or a new wrapped interceptor
1682 */
1683 protected Processor wrapProcessorInInterceptors(RouteContext routeContext, Processor target) throws Exception {
1684 // The target is required.
1685 if (target == null) {
1686 throw new IllegalArgumentException("target not provided on node: " + this);
1687 }
1688
1689 List<InterceptStrategy> strategies = new ArrayList<InterceptStrategy>();
1690 CamelContext camelContext = routeContext.getCamelContext();
1691 if (camelContext instanceof DefaultCamelContext) {
1692 DefaultCamelContext defaultCamelContext = (DefaultCamelContext) camelContext;
1693 strategies.addAll(defaultCamelContext.getInterceptStrategies());
1694 }
1695 strategies.addAll(routeContext.getInterceptStrategies());
1696 for (InterceptStrategy strategy : strategies) {
1697 if (strategy != null) {
1698 target = strategy.wrapProcessorInInterceptors(this, target);
1699 }
1700 }
1701
1702 List<InterceptorType> list = routeContext.getRoute().getInterceptors();
1703 if (interceptors != null) {
1704 list.addAll(interceptors);
1705 }
1706 // lets reverse the list so we apply the inner interceptors first
1707 Collections.reverse(list);
1708 Set<Processor> interceptors = new HashSet<Processor>();
1709 interceptors.add(target);
1710 for (InterceptorType interceptorType : list) {
1711 DelegateProcessor interceptor = interceptorType.createInterceptor(routeContext);
1712 if (!interceptors.contains(interceptor)) {
1713 interceptors.add(interceptor);
1714 if (interceptor.getProcessor() != null) {
1715 LOG.warn("Interceptor " + interceptor + " currently wraps target "
1716 + interceptor.getProcessor()
1717 + " is attempting to change target " + target
1718 + " new wrapping has been denied.");
1719 } else {
1720 interceptor.setProcessor(target);
1721 target = interceptor;
1722 }
1723 }
1724 }
1725 return target;
1726 }
1727
1728 /**
1729 * A strategy method to allow newly created processors to be wrapped in an
1730 * error handler.
1731 */
1732 protected Processor wrapInErrorHandler(RouteContext routeContext, Processor target) throws Exception {
1733 // The target is required.
1734 if (target == null) {
1735 throw new IllegalArgumentException("target not provided on node: " + this);
1736 }
1737
1738 ErrorHandlerWrappingStrategy strategy = routeContext.getErrorHandlerWrappingStrategy();
1739
1740 if (strategy != null) {
1741 return strategy.wrapProcessorInErrorHandler(routeContext, this, target);
1742 }
1743
1744 return getErrorHandlerBuilder().createErrorHandler(routeContext, target);
1745 }
1746
1747 protected ErrorHandlerBuilder createErrorHandlerBuilder() {
1748 if (errorHandlerRef != null) {
1749 return new ErrorHandlerBuilderRef(errorHandlerRef);
1750 }
1751 if (isInheritErrorHandler()) {
1752 return new DeadLetterChannelBuilder();
1753 } else {
1754 return new NoErrorHandlerBuilder();
1755 }
1756 }
1757
1758 protected void configureChild(ProcessorType output) {
1759 output.setNodeFactory(getNodeFactory());
1760 }
1761
1762 public void addOutput(ProcessorType processorType) {
1763 processorType.setParent(this);
1764 configureChild(processorType);
1765 if (blocks.isEmpty()) {
1766 getOutputs().add(processorType);
1767 } else {
1768 Block block = blocks.getLast();
1769 block.addOutput(processorType);
1770 }
1771 }
1772
1773 /**
1774 * Creates a new instance of some kind of composite processor which defaults
1775 * to using a {@link Pipeline} but derived classes could change the
1776 * behaviour
1777 */
1778 protected Processor createCompositeProcessor(RouteContext routeContext, List<Processor> list) {
1779 // return new MulticastProcessor(list);
1780 return new Pipeline(list);
1781 }
1782
1783 protected Processor createOutputsProcessor(RouteContext routeContext, Collection<ProcessorType<?>> outputs)
1784 throws Exception {
1785 List<Processor> list = new ArrayList<Processor>();
1786 for (ProcessorType output : outputs) {
1787 Processor processor = output.createProcessor(routeContext);
1788 // if the ProceedType create processor is null we keep on going
1789 if (output instanceof ProceedType && processor == null) {
1790 continue;
1791 }
1792 processor = output.wrapProcessorInInterceptors(routeContext, processor);
1793
1794 ProcessorType currentProcessor = this;
1795 if (!(currentProcessor instanceof ExceptionType || currentProcessor instanceof TryType)) {
1796 processor = output.wrapInErrorHandler(routeContext, processor);
1797 }
1798
1799 list.add(processor);
1800 }
1801 Processor processor = null;
1802 if (!list.isEmpty()) {
1803 if (list.size() == 1) {
1804 processor = list.get(0);
1805 } else {
1806 processor = createCompositeProcessor(routeContext, list);
1807 }
1808 }
1809 return processor;
1810 }
1811
1812 public void clearOutput() {
1813 getOutputs().clear();
1814 blocks.clear();
1815 }
1816 }