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.Comparator;
024 import java.util.HashSet;
025 import java.util.LinkedList;
026 import java.util.List;
027 import java.util.Set;
028 import java.util.concurrent.Executor;
029
030 import javax.xml.bind.annotation.XmlAccessType;
031 import javax.xml.bind.annotation.XmlAccessorType;
032 import javax.xml.bind.annotation.XmlAttribute;
033 import javax.xml.bind.annotation.XmlTransient;
034
035 import org.apache.camel.CamelContext;
036 import org.apache.camel.CamelException;
037 import org.apache.camel.Endpoint;
038 import org.apache.camel.ExchangePattern;
039 import org.apache.camel.Expression;
040 import org.apache.camel.Predicate;
041 import org.apache.camel.Processor;
042 import org.apache.camel.Route;
043 import org.apache.camel.builder.DataFormatClause;
044 import org.apache.camel.builder.DeadLetterChannelBuilder;
045 import org.apache.camel.builder.ErrorHandlerBuilder;
046 import org.apache.camel.builder.ErrorHandlerBuilderRef;
047 import org.apache.camel.builder.ExpressionClause;
048 import org.apache.camel.builder.NoErrorHandlerBuilder;
049 import org.apache.camel.builder.ProcessorBuilder;
050 import org.apache.camel.model.dataformat.DataFormatDefinition;
051 import org.apache.camel.model.language.ConstantExpression;
052 import org.apache.camel.model.language.ExpressionDefinition;
053 import org.apache.camel.model.language.LanguageExpression;
054 import org.apache.camel.processor.DelegateProcessor;
055 import org.apache.camel.processor.Pipeline;
056 import org.apache.camel.processor.aggregate.AggregationCollection;
057 import org.apache.camel.processor.aggregate.AggregationStrategy;
058 import org.apache.camel.spi.DataFormat;
059 import org.apache.camel.spi.ErrorHandlerWrappingStrategy;
060 import org.apache.camel.spi.IdempotentRepository;
061 import org.apache.camel.spi.InterceptStrategy;
062 import org.apache.camel.spi.Policy;
063 import org.apache.camel.spi.RouteContext;
064 import org.apache.camel.util.ObjectHelper;
065 import org.apache.commons.logging.Log;
066 import org.apache.commons.logging.LogFactory;
067 import static org.apache.camel.builder.Builder.body;
068
069 /**
070 * Base class for processor types that most XML types extend.
071 *
072 * @version $Revision: 751648 $
073 */
074 @XmlAccessorType(XmlAccessType.PROPERTY)
075 public abstract class ProcessorDefinition<Type extends ProcessorDefinition> extends OptionalIdentifiedType<Type> implements Block {
076 private static final transient Log LOG = LogFactory.getLog(ProcessorDefinition.class);
077 private ErrorHandlerBuilder errorHandlerBuilder;
078 private Boolean inheritErrorHandlerFlag;
079 private NodeFactory nodeFactory;
080 private LinkedList<Block> blocks = new LinkedList<Block>();
081 private ProcessorDefinition parent;
082 private List<AbstractInterceptorDefinition> interceptors = new ArrayList<AbstractInterceptorDefinition>();
083 private String errorHandlerRef;
084
085 // else to use an optional attribute in JAXB2
086 public abstract List<ProcessorDefinition> 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<ProcessorDefinition> 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
119 *
120 * @param uri the endpoint to send to
121 * @return the builder
122 */
123 @SuppressWarnings("unchecked")
124 public Type to(String uri) {
125 addOutput(new ToDefinition(uri));
126 return (Type) this;
127 }
128
129
130 /**
131 * Sends the exchange to the given endpoint
132 *
133 * @param endpoint the endpoint to send to
134 * @return the builder
135 */
136 @SuppressWarnings("unchecked")
137 public Type to(Endpoint endpoint) {
138 addOutput(new ToDefinition(endpoint));
139 return (Type) this;
140 }
141
142 /**
143 * Sends the exchange with certain exchange pattern to the given endpoint
144 *
145 * @param pattern the pattern to use for the message exchange
146 * @param uri the endpoint to send to
147 * @return the builder
148 */
149 @SuppressWarnings("unchecked")
150 public Type to(ExchangePattern pattern, String uri) {
151 addOutput(new ToDefinition(uri, pattern));
152 return (Type) this;
153 }
154
155
156 /**
157 * Sends the exchange with certain exchange pattern to the given endpoint
158 *
159 * @param pattern the pattern to use for the message exchange
160 * @param endpoint the endpoint to send to
161 * @return the builder
162 */
163 @SuppressWarnings("unchecked")
164 public Type to(ExchangePattern pattern, Endpoint endpoint) {
165 addOutput(new ToDefinition(endpoint, pattern));
166 return (Type) this;
167 }
168
169 /**
170 * Sends the exchange to a list of endpoints
171 *
172 * @param uris list of endpoints to send to
173 * @return the builder
174 */
175 @SuppressWarnings("unchecked")
176 public Type to(String... uris) {
177 for (String uri : uris) {
178 addOutput(new ToDefinition(uri));
179 }
180 return (Type) this;
181 }
182
183
184 /**
185 * Sends the exchange to a list of endpoints
186 *
187 * @param endpoints list of endpoints to send to
188 * @return the builder
189 */
190 @SuppressWarnings("unchecked")
191 public Type to(Endpoint... endpoints) {
192 for (Endpoint endpoint : endpoints) {
193 addOutput(new ToDefinition(endpoint));
194 }
195 return (Type) this;
196 }
197
198 /**
199 * Sends the exchange to a list of endpoints
200 *
201 * @param endpoints list of endpoints to send to
202 * @return the builder
203 */
204 @SuppressWarnings("unchecked")
205 public Type to(Iterable<Endpoint> endpoints) {
206 for (Endpoint endpoint : endpoints) {
207 addOutput(new ToDefinition(endpoint));
208 }
209 return (Type) this;
210 }
211
212
213 /**
214 * Sends the exchange to a list of endpoints
215 *
216 * @param pattern the pattern to use for the message exchanges
217 * @param uris list of endpoints to send to
218 * @return the builder
219 */
220 @SuppressWarnings("unchecked")
221 public Type to(ExchangePattern pattern, String... uris) {
222 for (String uri : uris) {
223 addOutput(new ToDefinition(uri, pattern));
224 }
225 return (Type) this;
226 }
227
228 /**
229 * Sends the exchange to a list of endpoints
230 *
231 * @param pattern the pattern to use for the message exchanges
232 * @param endpoints list of endpoints to send to
233 * @return the builder
234 */
235 @SuppressWarnings("unchecked")
236 public Type to(ExchangePattern pattern, Endpoint... endpoints) {
237 for (Endpoint endpoint : endpoints) {
238 addOutput(new ToDefinition(endpoint, pattern));
239 }
240 return (Type) this;
241 }
242
243 /**
244 * Sends the exchange to a list of endpoints
245 *
246 * @param pattern the pattern to use for the message exchanges
247 * @param endpoints list of endpoints to send to
248 * @return the builder
249 */
250 @SuppressWarnings("unchecked")
251 public Type to(ExchangePattern pattern, Iterable<Endpoint> endpoints) {
252 for (Endpoint endpoint : endpoints) {
253 addOutput(new ToDefinition(endpoint, pattern));
254 }
255 return (Type) this;
256 }
257
258
259 /**
260 * <a href="http://camel.apache.org/exchange-pattern.html">ExchangePattern:</a>
261 * set the ExchangePattern {@link ExchangePattern} into the exchange
262 *
263 * @param exchangePattern instance of {@link ExchangePattern}
264 * @return the builder
265 */
266 @SuppressWarnings("unchecked")
267 public Type setExchangePattern(ExchangePattern exchangePattern) {
268 addOutput(new SetExchangePatternDefinition(exchangePattern));
269 return (Type) this;
270 }
271
272 /**
273 * <a href="http://camel.apache.org/exchange-pattern.html">ExchangePattern:</a>
274 * set the exchange's ExchangePattern {@link ExchangePattern} to be InOnly
275 *
276 *
277 * @return the builder
278 */
279 public Type inOnly() {
280 return setExchangePattern(ExchangePattern.InOnly);
281 }
282
283 /**
284 * Sends the message to the given endpoint using an
285 * <a href="http://camel.apache.org/event-message.html">Event Message</a> or
286 * <a href="http://camel.apache.org/exchange-pattern.html">InOnly exchange pattern</a>
287 *
288 * @param uri The endpoint uri which is used for sending the exchange
289 * @return the builder
290 */
291 public Type inOnly(String uri) {
292 return to(ExchangePattern.InOnly, uri);
293 }
294
295 /**
296 * Sends the message to the given endpoint using an
297 * <a href="http://camel.apache.org/event-message.html">Event Message</a> or
298 * <a href="http://camel.apache.org/exchange-pattern.html">InOnly exchange pattern</a>
299 *
300 * @param endpoint The endpoint which is used for sending the exchange
301 * @return the builder
302 */
303 public Type inOnly(Endpoint endpoint) {
304 return to(ExchangePattern.InOnly, endpoint);
305 }
306
307
308 /**
309 * Sends the message to the given endpoints using an
310 * <a href="http://camel.apache.org/event-message.html">Event Message</a> or
311 * <a href="http://camel.apache.org/exchange-pattern.html">InOnly exchange pattern</a>
312 *
313 * @param uris list of endpoints to send to
314 * @return the builder
315 */
316 public Type inOnly(String... uris) {
317 return to(ExchangePattern.InOnly, uris);
318 }
319
320
321 /**
322 * Sends the message to the given endpoints using an
323 * <a href="http://camel.apache.org/event-message.html">Event Message</a> or
324 * <a href="http://camel.apache.org/exchange-pattern.html">InOnly exchange pattern</a>
325 *
326 * @param endpoints list of endpoints to send to
327 * @return the builder
328 */
329 public Type inOnly(Endpoint... endpoints) {
330 return to(ExchangePattern.InOnly, endpoints);
331 }
332
333 /**
334 * Sends the message to the given endpoints using an
335 * <a href="http://camel.apache.org/event-message.html">Event Message</a> or
336 * <a href="http://camel.apache.org/exchange-pattern.html">InOnly exchange pattern</a>
337 *
338 * @param endpoints list of endpoints to send to
339 * @return the builder
340 */
341 public Type inOnly(Iterable<Endpoint> endpoints) {
342 return to(ExchangePattern.InOnly, endpoints);
343 }
344
345
346 /**
347 * <a href="http://camel.apache.org/exchange-pattern.html">ExchangePattern:</a>
348 * set the exchange's ExchangePattern {@link ExchangePattern} to be InOut
349 *
350 *
351 * @return the builder
352 */
353 public Type inOut() {
354 return setExchangePattern(ExchangePattern.InOut);
355 }
356
357 /**
358 * Sends the message to the given endpoint using an
359 * <a href="http://camel.apache.org/request-reply.html">Request Reply</a> or
360 * <a href="http://camel.apache.org/exchange-pattern.html">InOut exchange pattern</a>
361 *
362 * @param uri The endpoint uri which is used for sending the exchange
363 * @return the builder
364 */
365 public Type inOut(String uri) {
366 return to(ExchangePattern.InOut, uri);
367 }
368
369
370 /**
371 * Sends the message to the given endpoint using an
372 * <a href="http://camel.apache.org/request-reply.html">Request Reply</a> or
373 * <a href="http://camel.apache.org/exchange-pattern.html">InOut exchange pattern</a>
374 *
375 * @param endpoint The endpoint which is used for sending the exchange
376 * @return the builder
377 */
378 public Type inOut(Endpoint endpoint) {
379 return to(ExchangePattern.InOut, endpoint);
380 }
381
382 /**
383 * Sends the message to the given endpoints using an
384 * <a href="http://camel.apache.org/request-reply.html">Request Reply</a> or
385 * <a href="http://camel.apache.org/exchange-pattern.html">InOut exchange pattern</a>
386 *
387 * @param uris list of endpoints to send to
388 * @return the builder
389 */
390 public Type inOut(String... uris) {
391 return to(ExchangePattern.InOut, uris);
392 }
393
394
395 /**
396 * Sends the message to the given endpoints using an
397 * <a href="http://camel.apache.org/request-reply.html">Request Reply</a> or
398 * <a href="http://camel.apache.org/exchange-pattern.html">InOut exchange pattern</a>
399 *
400 * @param endpoints list of endpoints to send to
401 * @return the builder
402 */
403 public Type inOut(Endpoint... endpoints) {
404 return to(ExchangePattern.InOut, endpoints);
405 }
406
407 /**
408 * Sends the message to the given endpoints using an
409 * <a href="http://camel.apache.org/request-reply.html">Request Reply</a> or
410 * <a href="http://camel.apache.org/exchange-pattern.html">InOut exchange pattern</a>
411 *
412 * @param endpoints list of endpoints to send to
413 * @return the builder
414 */
415 public Type inOut(Iterable<Endpoint> endpoints) {
416 return to(ExchangePattern.InOut, endpoints);
417 }
418
419
420 /**
421 * <a href="http://camel.apache.org/multicast.html">Multicast EIP:</a>
422 * Multicasts messages to all its child outputs; so that each processor and
423 * destination gets a copy of the original message to avoid the processors
424 * interfering with each other.
425 *
426 * @return the builder
427 */
428 public MulticastDefinition multicast() {
429 MulticastDefinition answer = new MulticastDefinition();
430 addOutput(answer);
431 return answer;
432 }
433
434 /**
435 * <a href="http://camel.apache.org/multicast.html">Multicast EIP:</a>
436 * Multicasts messages to all its child outputs; so that each processor and
437 * destination gets a copy of the original message to avoid the processors
438 * interfering with each other.
439 *
440 * @param aggregationStrategy the strategy used to aggregate responses for
441 * every part
442 * @param parallelProcessing if is <tt>true</tt> camel will fork thread to call the endpoint producer
443 * @return the builder
444 */
445 public MulticastDefinition multicast(AggregationStrategy aggregationStrategy, boolean parallelProcessing) {
446 MulticastDefinition answer = new MulticastDefinition();
447 addOutput(answer);
448 answer.setAggregationStrategy(aggregationStrategy);
449 answer.setParallelProcessing(parallelProcessing);
450 return answer;
451 }
452
453 /**
454 * <a href="http://camel.apache.org/multicast.html">Multicast EIP:</a>
455 * Multicasts messages to all its child outputs; so that each processor and
456 * destination gets a copy of the original message to avoid the processors
457 * interfering with each other.
458 *
459 * @param aggregationStrategy the strategy used to aggregate responses for
460 * every part
461 * @return the builder
462 */
463 public MulticastDefinition multicast(AggregationStrategy aggregationStrategy) {
464 MulticastDefinition answer = new MulticastDefinition();
465 addOutput(answer);
466 answer.setAggregationStrategy(aggregationStrategy);
467 return answer;
468 }
469
470 /**
471 * <a href="http://camel.apache.org/pipes-nd-filters.html">Pipes and Filters EIP:</a>
472 * Creates a {@link Pipeline} of the list of endpoints so that the message
473 * will get processed by each endpoint in turn and for request/response the
474 * output of one endpoint will be the input of the next endpoint
475 *
476 * @param uris list of endpoints
477 * @return the builder
478 */
479 public Type pipeline(String... uris) {
480 return to(uris);
481 }
482
483 /**
484 * <a href="http://camel.apache.org/pipes-nd-filters.html">Pipes and Filters EIP:</a>
485 * Creates a {@link Pipeline} of the list of endpoints so that the message
486 * will get processed by each endpoint in turn and for request/response the
487 * output of one endpoint will be the input of the next endpoint
488 *
489 * @param endpoints list of endpoints
490 * @return the builder
491 */
492 public Type pipeline(Endpoint... endpoints) {
493 return to(endpoints);
494 }
495
496 /**
497 * <a href="http://camel.apache.org/pipes-nd-filters.html">Pipes and Filters EIP:</a>
498 * Creates a {@link Pipeline} of the list of endpoints so that the message
499 * will get processed by each endpoint in turn and for request/response the
500 * output of one endpoint will be the input of the next endpoint
501 *
502 * @param endpoints list of endpoints
503 * @return the builder
504 */
505 public Type pipeline(Collection<Endpoint> endpoints) {
506 return to(endpoints);
507 }
508
509 /**
510 * Ends the current block
511 *
512 * @return the builder
513 */
514 @SuppressWarnings("unchecked")
515 public ProcessorDefinition<? extends ProcessorDefinition> end() {
516 if (blocks.isEmpty()) {
517 if (parent == null) {
518 throw new IllegalArgumentException("Root node with no active block");
519 }
520 return parent;
521 }
522 popBlock();
523 return this;
524 }
525
526 /**
527 * Causes subsequent processors to be called asynchronously
528 *
529 * @param coreSize the number of threads that will be used to process
530 * messages in subsequent processors.
531 * @return a ThreadType builder that can be used to further configure the
532 * the thread pool.
533 */
534 public ThreadDefinition thread(int coreSize) {
535 ThreadDefinition answer = new ThreadDefinition(coreSize);
536 addOutput(answer);
537 return answer;
538 }
539
540 /**
541 * Causes subsequent processors to be called asynchronously
542 *
543 * @param executor the executor that will be used to process
544 * messages in subsequent processors.
545 * @return a ThreadType builder that can be used to further configure the
546 * the thread pool.
547 */
548 public ProcessorDefinition<Type> thread(Executor executor) {
549 ThreadDefinition answer = new ThreadDefinition(executor);
550 addOutput(answer);
551 return this;
552 }
553
554 /**
555 * <a href="http://camel.apache.org/idempotent-consumer.html">Idempotent consumer EIP:</a>
556 * Creates an {@link org.apache.camel.processor.idempotent.IdempotentConsumer IdempotentConsumer}
557 * to avoid duplicate messages
558 *
559 * @return the builder
560 */
561 public IdempotentConsumerDefinition idempotentConsumer() {
562 IdempotentConsumerDefinition answer = new IdempotentConsumerDefinition();
563 addOutput(answer);
564 return answer;
565 }
566
567 /**
568 * <a href="http://camel.apache.org/idempotent-consumer.html">Idempotent consumer EIP:</a>
569 * Creates an {@link org.apache.camel.processor.idempotent.IdempotentConsumer IdempotentConsumer}
570 * to avoid duplicate messages
571 *
572 * @param messageIdExpression expression to test of duplicate messages
573 * @param idempotentRepository the repository to use for duplicate chedck
574 * @return the builder
575 */
576 public IdempotentConsumerDefinition idempotentConsumer(Expression messageIdExpression,
577 IdempotentRepository idempotentRepository) {
578 IdempotentConsumerDefinition answer = new IdempotentConsumerDefinition(messageIdExpression, idempotentRepository);
579 addOutput(answer);
580 return answer;
581 }
582
583 /**
584 * <a href="http://camel.apache.org/idempotent-consumer.html">Idempotent consumer EIP:</a>
585 * Creates an {@link org.apache.camel.processor.idempotent.IdempotentConsumer IdempotentConsumer}
586 * to avoid duplicate messages
587 *
588 * @param idempotentRepository the repository to use for duplicate chedck
589 * @return the builder used to create the expression
590 */
591 public ExpressionClause<IdempotentConsumerDefinition> idempotentConsumer(IdempotentRepository idempotentRepository) {
592 IdempotentConsumerDefinition answer = new IdempotentConsumerDefinition();
593 answer.setMessageIdRepository(idempotentRepository);
594 addOutput(answer);
595 return ExpressionClause.createAndSetExpression(answer);
596 }
597
598 /**
599 * <a href="http://camel.apache.org/message-filter.html">Message Filter EIP:</a>
600 * Creates a predicate expression which only if it is <tt>true</tt> then the
601 * exchange is forwarded to the destination
602 *
603 * @return the clause used to create the filter expression
604 */
605 public ExpressionClause<FilterDefinition> filter() {
606 FilterDefinition filter = new FilterDefinition();
607 addOutput(filter);
608 return ExpressionClause.createAndSetExpression(filter);
609 }
610
611 /**
612 * <a href="http://camel.apache.org/message-filter.html">Message Filter EIP:</a>
613 * Creates a predicate which is applied and only if it is <tt>true</tt> then the
614 * exchange is forwarded to the destination
615 *
616 * @param predicate predicate to use
617 * @return the builder
618 */
619 public FilterDefinition filter(Predicate predicate) {
620 FilterDefinition filter = new FilterDefinition(predicate);
621 addOutput(filter);
622 return filter;
623 }
624
625 /**
626 * <a href="http://camel.apache.org/message-filter.html">Message Filter EIP:</a>
627 * Creates a predicate expression which only if it is <tt>true</tt> then the
628 * exchange is forwarded to the destination
629 *
630 * @param expression the predicate expression to use
631 * @return the builder
632 */
633 public FilterDefinition filter(ExpressionDefinition expression) {
634 FilterDefinition filter = getNodeFactory().createFilter();
635 filter.setExpression(expression);
636 addOutput(filter);
637 return filter;
638 }
639
640 /**
641 * <a href="http://camel.apache.org/message-filter.html">Message Filter EIP:</a>
642 * Creates a predicate language expression which only if it is <tt>true</tt> then the
643 * exchange is forwarded to the destination
644 *
645 * @param language language for expression
646 * @param expression the expression
647 * @return the builder
648 */
649 public FilterDefinition filter(String language, String expression) {
650 return filter(new LanguageExpression(language, expression));
651 }
652
653 /**
654 * <a href="http://camel.apache.org/load-balancer.html">Load Balancer EIP:</a>
655 * Creates a loadbalance
656 *
657 * @return the builder
658 */
659 public LoadBalanceDefinition loadBalance() {
660 LoadBalanceDefinition answer = new LoadBalanceDefinition();
661 addOutput(answer);
662 return answer;
663 }
664
665
666 /**
667 * <a href="http://camel.apache.org/content-based-router.html">Content Based Router EIP:</a>
668 * Creates a choice of one or more predicates with an otherwise clause
669 *
670 * @return the builder for a choice expression
671 */
672 public ChoiceDefinition choice() {
673 ChoiceDefinition answer = new ChoiceDefinition();
674 addOutput(answer);
675 return answer;
676 }
677
678 /**
679 * Creates a try/catch block
680 *
681 * @return the builder for a tryBlock expression
682 */
683 public TryDefinition tryBlock() {
684 TryDefinition answer = new TryDefinition();
685 addOutput(answer);
686 return answer;
687 }
688
689 /**
690 * <a href="http://camel.apache.org/recipient-list.html">Recipient List EIP:</a>
691 * Creates a dynamic recipient list allowing you to route messages to a number of dynamically specified recipients
692 *
693 * @param recipients expression to decide the destinations
694 * @return the builder
695 */
696 @SuppressWarnings("unchecked")
697 public Type recipientList(Expression recipients) {
698 RecipientListDefinition answer = new RecipientListDefinition(recipients);
699 addOutput(answer);
700 return (Type) this;
701 }
702
703 /**
704 * <a href="http://camel.apache.org/recipient-list.html">Recipient List EIP:</a>
705 * Creates a dynamic recipient list allowing you to route messages to a number of dynamically specified recipients
706 *
707 * @return the expression clause to configure the expression to decide the destinations
708 */
709 public ExpressionClause<ProcessorDefinition<Type>> recipientList() {
710 RecipientListDefinition answer = new RecipientListDefinition();
711 addOutput(answer);
712 ExpressionClause<ProcessorDefinition<Type>> clause = new ExpressionClause<ProcessorDefinition<Type>>(this);
713 answer.setExpression(clause);
714 return clause;
715 }
716
717 /**
718 * <a href="http://camel.apache.org/routing-slip.html">Routing Slip EIP:</a>
719 * Creates a routing slip allowing you to route a message consecutively through a series of processing
720 * steps where the sequence of steps is not known at design time and can vary for each message.
721 *
722 * @param header is the header that the {@link org.apache.camel.processor.RoutingSlip RoutingSlip}
723 * class will look in for the list of URIs to route the message to.
724 * @param uriDelimiter is the delimiter that will be used to split up
725 * the list of URIs in the routing slip.
726 * @return the buiider
727 */
728 @SuppressWarnings("unchecked")
729 public Type routingSlip(String header, String uriDelimiter) {
730 RoutingSlipDefinition answer = new RoutingSlipDefinition(header, uriDelimiter);
731 addOutput(answer);
732 return (Type) this;
733 }
734
735 /**
736 * <a href="http://camel.apache.org/routing-slip.html">Routing Slip EIP:</a>
737 * Creates a routing slip allowing you to route a message consecutively through a series of processing
738 * steps where the sequence of steps is not known at design time and can vary for each message.
739 * <p>
740 * The list of URIs will be split based on the default delimiter {@link RoutingSlipDefinition#DEFAULT_DELIMITER}
741 *
742 * @param header is the header that the {@link org.apache.camel.processor.RoutingSlip RoutingSlip}
743 * class will look in for the list of URIs to route the message to.
744 * @return the builder
745 */
746 @SuppressWarnings("unchecked")
747 public Type routingSlip(String header) {
748 RoutingSlipDefinition answer = new RoutingSlipDefinition(header);
749 addOutput(answer);
750 return (Type) this;
751 }
752
753 /**
754 * <a href="http://camel.apache.org/splitter.html">Splitter EIP:</a>
755 * Creates a splitter allowing you split a message into a number of pieces and process them individually.
756 * <p>
757 * This splitter responds with the latest message returned from destination
758 * endpoint.
759 *
760 * @return the expression clause builder for the expression on which to split
761 */
762 public ExpressionClause<SplitDefinition> split() {
763 SplitDefinition answer = new SplitDefinition();
764 addOutput(answer);
765 return ExpressionClause.createAndSetExpression(answer);
766 }
767
768 /**
769 * <a href="http://camel.apache.org/splitter.html">Splitter EIP:</a>
770 * Creates a splitter allowing you split a message into a number of pieces and process them individually.
771 * <p>
772 * This splitter responds with the latest message returned from destination
773 * endpoint.
774 *
775 * @param expression the expression on which to split the message
776 * @return the builder
777 */
778 public SplitDefinition split(Expression expression) {
779 SplitDefinition answer = new SplitDefinition(expression);
780 addOutput(answer);
781 return answer;
782 }
783
784 /**
785 * <a href="http://camel.apache.org/splitter.html">Splitter EIP:</a>
786 * Creates a splitter allowing you split a message into a number of pieces and process them individually.
787 * <p>
788 * The splitter responds with the answer produced by the given {@link AggregationStrategy}.
789 *
790 * @param expression the expression on which to split
791 * @param aggregationStrategy the strategy used to aggregate responses for every part
792 * @return the builder
793 */
794 public SplitDefinition split(Expression expression, AggregationStrategy aggregationStrategy) {
795 SplitDefinition answer = new SplitDefinition(expression);
796 addOutput(answer);
797 answer.setAggregationStrategy(aggregationStrategy);
798 return answer;
799 }
800
801 /**
802 * <a href="http://camel.apache.org/resequencer.html">Resequencer EIP:</a>
803 * Creates a resequencer allowing you to reorganize messages based on some comparator.
804 *
805 * @return the expression clause for the expressions on which to compare messages in order
806 */
807 public ExpressionClause<ResequenceDefinition> resequence() {
808 ResequenceDefinition answer = new ResequenceDefinition();
809 addOutput(answer);
810 ExpressionClause<ResequenceDefinition> clause = new ExpressionClause<ResequenceDefinition>(answer);
811 answer.expression(clause);
812 return clause;
813 }
814
815 /**
816 * <a href="http://camel.apache.org/resequencer.html">Resequencer EIP:</a>
817 * Creates a resequencer allowing you to reorganize messages based on some comparator.
818 *
819 * @param expression the expression on which to compare messages in order
820 * @return the builder
821 */
822 public ResequenceDefinition resequence(Expression expression) {
823 return resequence(Collections.<Expression>singletonList(expression));
824 }
825
826 /**
827 * <a href="http://camel.apache.org/resequencer.html">Resequencer EIP:</a>
828 * Creates a resequencer allowing you to reorganize messages based on some comparator.
829 *
830 * @param expressions the list of expressions on which to compare messages in order
831 * @return the builder
832 */
833 public ResequenceDefinition resequence(List<Expression> expressions) {
834 ResequenceDefinition answer = new ResequenceDefinition(expressions);
835 addOutput(answer);
836 return answer;
837 }
838
839 /**
840 * <a href="http://camel.apache.org/resequencer.html">Resequencer EIP:</a>
841 * Creates a splitter allowing you to reorganise messages based on some comparator.
842 *
843 * @param expressions the list of expressions on which to compare messages in order
844 * @return the builder
845 */
846 public ResequenceDefinition resequencer(Expression... expressions) {
847 List<Expression> list = new ArrayList<Expression>();
848 list.addAll(Arrays.asList(expressions));
849 return resequence(list);
850 }
851
852 /**
853 * <a href="http://camel.apache.org/aggregator.html">Aggregator EIP:</a>
854 * Creates an aggregator allowing you to combine a number of messages together into a single message.
855 *
856 * @return the expression clause to be used as builder to configure the correlation expression
857 */
858 public ExpressionClause<AggregateDefinition> aggregate() {
859 AggregateDefinition answer = new AggregateDefinition();
860 addOutput(answer);
861 return answer.createAndSetExpression();
862 }
863
864 /**
865 * <a href="http://camel.apache.org/aggregator.html">Aggregator EIP:</a>
866 * Creates an aggregator allowing you to combine a number of messages together into a single message.
867 *
868 * @param aggregationStrategy the strategy used for the aggregation
869 * @return the expression clause to be used as builder to configure the correlation expression
870 */
871 public ExpressionClause<AggregateDefinition> aggregate(AggregationStrategy aggregationStrategy) {
872 AggregateDefinition answer = new AggregateDefinition();
873 answer.setAggregationStrategy(aggregationStrategy);
874 addOutput(answer);
875 return answer.createAndSetExpression();
876 }
877
878 /**
879 * <a href="http://camel.apache.org/aggregator.html">Aggregator EIP:</a>
880 * Creates an aggregator allowing you to combine a number of messages together into a single message.
881 *
882 * @param aggregationCollection the collection used to perform the aggregation
883 * @return the builder
884 */
885 public AggregateDefinition aggregate(AggregationCollection aggregationCollection) {
886 AggregateDefinition answer = new AggregateDefinition();
887 answer.setAggregationCollection(aggregationCollection);
888 addOutput(answer);
889 return answer;
890 }
891
892 /**
893 * <a href="http://camel.apache.org/aggregator.html">Aggregator EIP:</a>
894 * Creates an aggregator allowing you to combine a number of messages together into a single message.
895 *
896 * @param correlationExpression the expression used to calculate the
897 * correlation key. For a JMS message this could be the
898 * expression <code>header("JMSDestination")</code> or
899 * <code>header("JMSCorrelationID")</code>
900 * @return the builder
901 */
902 public AggregateDefinition aggregate(Expression correlationExpression) {
903 AggregateDefinition answer = new AggregateDefinition(correlationExpression);
904 addOutput(answer);
905 return answer;
906 }
907
908 /**
909 * <a href="http://camel.apache.org/aggregator.html">Aggregator EIP:</a>
910 * Creates an aggregator allowing you to combine a number of messages together into a single message.
911 *
912 * @param correlationExpression the expression used to calculate the
913 * correlation key. For a JMS message this could be the
914 * expression <code>header("JMSDestination")</code> or
915 * <code>header("JMSCorrelationID")</code>
916 * @param aggregationStrategy the strategy used for the aggregation
917 * @return the builder
918 */
919 public AggregateDefinition aggregate(Expression correlationExpression, AggregationStrategy aggregationStrategy) {
920 AggregateDefinition answer = new AggregateDefinition(correlationExpression, aggregationStrategy);
921 addOutput(answer);
922 return answer;
923 }
924
925 /**
926 * <a href="http://camel.apache.org/delayer.html">Delayer EIP:</a>
927 * Creates a delayer allowing you to delay the delivery of messages to some destination.
928 *
929 * @param processAtExpression an expression to calculate the time at which the messages should be processed,
930 * should be convertable to long as time in millis
931 * @return the builder
932 */
933 public DelayDefinition delay(Expression processAtExpression) {
934 return delay(processAtExpression, 0L);
935 }
936
937 /**
938 * <a href="http://camel.apache.org/delayer.html">Delayer EIP:</a>
939 * Creates a delayer allowing you to delay the delivery of messages to some destination.
940 *
941 * @param processAtExpression an expression to calculate the time at which the messages should be processed,
942 * should be convertable to long as time in millis
943 * @param delay the delay in milliseconds which is added to the processAtExpression
944 * @return the builder
945 */
946 public DelayDefinition delay(Expression processAtExpression, long delay) {
947 DelayDefinition answer = new DelayDefinition(processAtExpression, delay);
948 addOutput(answer);
949 return answer;
950 }
951
952 /**
953 * <a href="http://camel.apache.org/delayer.html">Delayer EIP:</a>
954 * Creates a delayer allowing you to delay the delivery of messages to some destination.
955 *
956 * @return the expression clause to create the expression
957 */
958 public ExpressionClause<DelayDefinition> delay() {
959 DelayDefinition answer = new DelayDefinition();
960 addOutput(answer);
961 return ExpressionClause.createAndSetExpression(answer);
962 }
963
964 /**
965 * <a href="http://camel.apache.org/delayer.html">Delayer EIP:</a>
966 * Creates a delayer allowing you to delay the delivery of messages to some destination.
967 *
968 * @param delay the default delay in millis
969 * @return the builder
970 */
971 public DelayDefinition delay(long delay) {
972 return delay(null, delay);
973 }
974
975 /**
976 * <a href="http://camel.apache.org/throttler.html">Throttler EIP:</a>
977 * Creates a throttler allowing you to ensure that a specific endpoint does not get overloaded,
978 * or that we don't exceed an agreed SLA with some external service.
979 * <p/>
980 * Will default use a time period of 1 second, so setting the maximumRequestCount to eg 10
981 * will default ensure at most 10 messages per second.
982 *
983 * @param maximumRequestCount the maximum messages
984 * @return the builder
985 */
986 public ThrottleDefinition throttle(long maximumRequestCount) {
987 ThrottleDefinition answer = new ThrottleDefinition(maximumRequestCount);
988 addOutput(answer);
989 return answer;
990 }
991
992 /**
993 * <a href="http://camel.apache.org/loop.html">Loop EIP:</a>
994 * Creates a loop allowing to process the a message a number of times and possibly process them
995 * in a different way. Useful mostly for testing.
996 *
997 * @return the clause used to create the loop expression
998 */
999 public ExpressionClause<LoopDefinition> loop() {
1000 LoopDefinition loop = new LoopDefinition();
1001 addOutput(loop);
1002 return ExpressionClause.createAndSetExpression(loop);
1003 }
1004
1005 /**
1006 * <a href="http://camel.apache.org/loop.html">Loop EIP:</a>
1007 * Creates a loop allowing to process the a message a number of times and possibly process them
1008 * in a different way. Useful mostly for testing.
1009 *
1010 * @param expression the loop expression
1011 * @return the builder
1012 */
1013 public LoopDefinition loop(Expression expression) {
1014 LoopDefinition loop = getNodeFactory().createLoop();
1015 loop.setExpression(expression);
1016 addOutput(loop);
1017 return loop;
1018 }
1019
1020 /**
1021 * <a href="http://camel.apache.org/loop.html">Loop EIP:</a>
1022 * Creates a loop allowing to process the a message a number of times and possibly process them
1023 * in a different way. Useful mostly for testing.
1024 *
1025 * @param count the number of times
1026 * @return the builder
1027 */
1028 public LoopDefinition loop(int count) {
1029 LoopDefinition loop = getNodeFactory().createLoop();
1030 loop.setExpression(new ConstantExpression(Integer.toString(count)));
1031 addOutput(loop);
1032 return loop;
1033 }
1034
1035 /**
1036 * Creates a fault message based on the given throwable.
1037 *
1038 * @param fault the fault
1039 * @return the builder
1040 */
1041 @SuppressWarnings("unchecked")
1042 public Type throwFault(Throwable fault) {
1043 ThrowFaultDefinition answer = new ThrowFaultDefinition();
1044 answer.setFault(fault);
1045 addOutput(answer);
1046 return (Type) this;
1047 }
1048
1049 /**
1050 * Creates a fault message based on the given message.
1051 *
1052 * @param message the fault message
1053 * @return the builder
1054 */
1055 public Type throwFault(String message) {
1056 return throwFault(new CamelException(message));
1057 }
1058
1059 /**
1060 * <a href="http://camel.apache.org/wiretap.html">WireTap EIP:</a>
1061 * Sends messages to all its child outputs; so that each processor and
1062 * destination gets a copy of the original message to avoid the processors
1063 * interfering with each other using {@link ExchangePattern#InOnly}.
1064 *
1065 * @return the builder
1066 */
1067 @SuppressWarnings("unchecked")
1068 public Type wireTap(String uri) {
1069 WireTapDefinition answer = new WireTapDefinition();
1070 answer.setUri(uri);
1071 addOutput(answer);
1072 return (Type) this;
1073 }
1074
1075 /**
1076 * Intercepts outputs added to this node in the future (i.e. intercepts outputs added after this statement)
1077 *
1078 * @param ref a reference in the registry to lookup the interceptor that must be of type {@link DelegateProcessor}
1079 * @return the builder
1080 */
1081 @SuppressWarnings("unchecked")
1082 public Type interceptor(String ref) {
1083 InterceptorDefinition interceptor = new InterceptorDefinition(ref);
1084 intercept(interceptor);
1085 return (Type) this;
1086 }
1087
1088 /**
1089 * Intercepts outputs added to this node in the future (i.e. intercepts outputs added after this statement)
1090 *
1091 * @param refs a list of reference in the registry to lookup the interceptor that must
1092 * be of type {@link DelegateProcessor}
1093 * @return the builder
1094 */
1095 @SuppressWarnings("unchecked")
1096 public Type interceptors(String... refs) {
1097 for (String ref : refs) {
1098 interceptor(ref);
1099 }
1100 return (Type) this;
1101 }
1102
1103 /**
1104 * Intercepts outputs added to this node in the future (i.e. intercepts outputs added after this statement)
1105 *
1106 * @param interceptor the interceptor
1107 * @return the builder
1108 */
1109 @SuppressWarnings("unchecked")
1110 public Type intercept(DelegateProcessor interceptor) {
1111 intercept(new InterceptorDefinition(interceptor));
1112 return (Type) this;
1113 }
1114
1115 /**
1116 * Intercepts outputs added to this node in the future (i.e. intercepts outputs added after this statement)
1117 *
1118 * @return the intercept builder to configure
1119 */
1120 public InterceptDefinition intercept() {
1121 InterceptDefinition answer = new InterceptDefinition();
1122 addOutput(answer);
1123 return answer;
1124 }
1125
1126 /**
1127 * Intercepts outputs added to this node in the future (i.e. intercepts outputs added after this statement)
1128 *
1129 * @param interceptor the interceptor
1130 */
1131 public void intercept(AbstractInterceptorDefinition interceptor) {
1132 addOutput(interceptor);
1133 pushBlock(interceptor);
1134 }
1135
1136 /**
1137 * Adds an interceptor around the whole of this nodes processing
1138 *
1139 * @param interceptor the interceptor
1140 */
1141 public void addInterceptor(AbstractInterceptorDefinition interceptor) {
1142 interceptors.add(interceptor);
1143 }
1144
1145 /**
1146 * Adds an interceptor around the whole of this nodes processing
1147 *
1148 * @param interceptor the interceptor
1149 */
1150 public void addInterceptor(DelegateProcessor interceptor) {
1151 addInterceptor(new InterceptorDefinition(interceptor));
1152 }
1153
1154 /**
1155 * Pushes the given block on the stack as current block
1156 * @param block the block
1157 */
1158 public void pushBlock(Block block) {
1159 blocks.add(block);
1160 }
1161
1162 /**
1163 * Pops the block off the stack as current block
1164 * @return the block
1165 */
1166 public Block popBlock() {
1167 return blocks.isEmpty() ? null : blocks.removeLast();
1168 }
1169
1170 /**
1171 * Procceeds the given intercepted route.
1172 * <p/>
1173 * Proceed is used in conjunction with intercept where calling proceed will route the message through the
1174 * original route path from the point of interception. This can be used to implement the
1175 * <a href="http://www.enterpriseintegrationpatterns.com/Detour.html">detour</a> pattern.
1176 *
1177 * @return the builder
1178 * @see ProcessorDefinition#proceed()
1179 */
1180 @SuppressWarnings("unchecked")
1181 public Type proceed() {
1182 ProceedDefinition proceed = null;
1183 ProcessorDefinition currentProcessor = this;
1184
1185 if (currentProcessor instanceof InterceptDefinition) {
1186 proceed = ((InterceptDefinition) currentProcessor).getProceed();
1187 LOG.info("proceed() is the implied and hence not needed for an intercept()");
1188 }
1189 if (proceed == null) {
1190 for (ProcessorDefinition node = parent; node != null; node = node.getParent()) {
1191 if (node instanceof InterceptDefinition) {
1192 InterceptDefinition intercept = (InterceptDefinition)node;
1193 proceed = intercept.getProceed();
1194 break;
1195 }
1196 }
1197
1198 if (proceed == null) {
1199 throw new IllegalArgumentException("Cannot use proceed() without being within an intercept() block");
1200 }
1201
1202 }
1203
1204 addOutput(proceed);
1205 return (Type) this;
1206 }
1207
1208 /**
1209 * Stops the given intercepted route.
1210 * <p/>
1211 * As opposed to {@link #proceed()} calling stop will stop the message route and <b>not</b> continue
1212 * from the interepted origin.
1213 *
1214 * @return the builder
1215 * @see #proceed()
1216 */
1217 @SuppressWarnings("unchecked")
1218 public Type stop() {
1219 ProcessorDefinition currentProcessor = this;
1220
1221 if (currentProcessor instanceof InterceptDefinition) {
1222 ((InterceptDefinition) currentProcessor).stopIntercept();
1223 } else {
1224 ProcessorDefinition node;
1225 for (node = parent; node != null; node = node.getParent()) {
1226 if (node instanceof InterceptDefinition) {
1227 ((InterceptDefinition) node).stopIntercept();
1228 break;
1229 }
1230 }
1231 if (node == null) {
1232 throw new IllegalArgumentException("Cannot use stop() without being within an intercept() block");
1233 }
1234 }
1235
1236 return (Type) this;
1237 }
1238
1239 /**
1240 * <a href="http://camel.apache.org/exception-clause.html">Exception clause</a>
1241 * for cathing certain exceptions and handling them.
1242 *
1243 * @param exceptionType the exception to catch
1244 * @return the exception builder to configure
1245 */
1246 public OnExceptionDefinition onException(Class exceptionType) {
1247 OnExceptionDefinition answer = new OnExceptionDefinition(exceptionType);
1248 addOutput(answer);
1249 return answer;
1250 }
1251
1252 /**
1253 * Apply an interceptor route if the predicate is true.
1254 *
1255 * @param predicate the predicate to test
1256 * @return the choice builder to configure
1257 */
1258 public ChoiceDefinition intercept(Predicate predicate) {
1259 InterceptDefinition answer = new InterceptDefinition();
1260 addOutput(answer);
1261 return answer.when(predicate);
1262 }
1263
1264 /**
1265 * Creates a policy.
1266 * <p/>
1267 * Policy can be used for transactional policies.
1268 *
1269 * @return the policy builder to configure
1270 */
1271 public PolicyDefinition policies() {
1272 PolicyDefinition answer = new PolicyDefinition();
1273 addOutput(answer);
1274 return answer;
1275 }
1276
1277 /**
1278 * Apply a {@link Policy}.
1279 * <p/>
1280 * Policy can be used for transactional policies.
1281 *
1282 * @param policy the policy to apply
1283 * @return the policy builder to configure
1284 */
1285 public PolicyDefinition policy(Policy policy) {
1286 PolicyDefinition answer = new PolicyDefinition(policy);
1287 addOutput(answer);
1288 return answer;
1289 }
1290
1291 /**
1292 * Forces handling of faults as exceptions
1293 *
1294 * @return the current builder with the fault handler configured
1295 */
1296 @SuppressWarnings("unchecked")
1297 public Type handleFault() {
1298 intercept(new HandleFaultDefinition());
1299 return (Type) this;
1300 }
1301
1302 /**
1303 * Installs the given <a href="http://camel.apache.org/error-handler.html">error handler</a> builder.
1304 *
1305 * @param errorHandlerBuilder the error handler to be used by default for all child routes
1306 * @return the current builder with the error handler configured
1307 */
1308 @SuppressWarnings("unchecked")
1309 public Type errorHandler(ErrorHandlerBuilder errorHandlerBuilder) {
1310 setErrorHandlerBuilder(errorHandlerBuilder);
1311 return (Type) this;
1312 }
1313
1314 /**
1315 * Configures whether or not the <a href="http://camel.apache.org/error-handler.html">error handler</a>
1316 * is inherited by every processing node (or just the top most one)
1317 *
1318 * @param condition the flag as to whether error handlers should be inherited or not
1319 * @return the current builder
1320 */
1321 @SuppressWarnings("unchecked")
1322 public Type inheritErrorHandler(boolean condition) {
1323 setInheritErrorHandlerFlag(condition);
1324 return (Type) this;
1325 }
1326
1327 // Transformers
1328 // -------------------------------------------------------------------------
1329
1330 /**
1331 * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
1332 * Adds the custom processor to this destination which could be a final
1333 * destination, or could be a transformation in a pipeline
1334 *
1335 * @param processor the custom {@link Processor}
1336 * @return the builder
1337 */
1338 @SuppressWarnings("unchecked")
1339 public Type process(Processor processor) {
1340 ProcessDefinition answer = new ProcessDefinition(processor);
1341 addOutput(answer);
1342 return (Type) this;
1343 }
1344
1345 /**
1346 * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
1347 * Adds the custom processor reference to this destination which could be a final
1348 * destination, or could be a transformation in a pipeline
1349 *
1350 * @param ref reference to a {@link Processor} to lookup in the registry
1351 * @return the builder
1352 */
1353 @SuppressWarnings("unchecked")
1354 public Type processRef(String ref) {
1355 ProcessDefinition answer = new ProcessDefinition();
1356 answer.setRef(ref);
1357 addOutput(answer);
1358 return (Type) this;
1359 }
1360
1361 /**
1362 * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
1363 * Adds a bean which is invoked which could be a final destination, or could be a transformation in a pipeline
1364 *
1365 * @param bean the bean to invoke
1366 * @return the builder
1367 */
1368 @SuppressWarnings("unchecked")
1369 public Type bean(Object bean) {
1370 BeanDefinition answer = new BeanDefinition();
1371 answer.setBean(bean);
1372 addOutput(answer);
1373 return (Type) this;
1374 }
1375
1376 /**
1377 * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
1378 * Adds a bean which is invoked which could be a final destination, or could be a transformation in a pipeline
1379 *
1380 * @param bean the bean to invoke
1381 * @param method the method name to invoke on the bean (can be used to avoid ambiguty)
1382 * @return the builder
1383 */
1384 @SuppressWarnings("unchecked")
1385 public Type bean(Object bean, String method) {
1386 BeanDefinition answer = new BeanDefinition();
1387 answer.setBean(bean);
1388 answer.setMethod(method);
1389 addOutput(answer);
1390 return (Type) this;
1391 }
1392
1393 /**
1394 * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
1395 * Adds a bean which is invoked which could be a final destination, or could be a transformation in a pipeline
1396 *
1397 * @param beanType the bean class, Camel will instantiate an object at runtime
1398 * @return the builder
1399 */
1400 @SuppressWarnings("unchecked")
1401 public Type bean(Class beanType) {
1402 BeanDefinition answer = new BeanDefinition();
1403 answer.setBeanType(beanType);
1404 addOutput(answer);
1405 return (Type) this;
1406 }
1407
1408 /**
1409 * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
1410 * Adds a bean which is invoked which could be a final destination, or could be a transformation in a pipeline
1411 *
1412 * @param beanType the bean class, Camel will instantiate an object at runtime
1413 * @param method the method name to invoke on the bean (can be used to avoid ambiguty)
1414 * @return the builder
1415 */
1416 @SuppressWarnings("unchecked")
1417 public Type bean(Class beanType, String method) {
1418 BeanDefinition answer = new BeanDefinition();
1419 answer.setBeanType(beanType);
1420 answer.setMethod(method);
1421 addOutput(answer);
1422 return (Type) this;
1423 }
1424
1425 /**
1426 * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
1427 * Adds a bean which is invoked which could be a final destination, or could be a transformation in a pipeline
1428 *
1429 * @param ref reference to a bean to lookup in the registry
1430 * @return the builder
1431 */
1432 @SuppressWarnings("unchecked")
1433 public Type beanRef(String ref) {
1434 BeanDefinition answer = new BeanDefinition(ref);
1435 addOutput(answer);
1436 return (Type) this;
1437 }
1438
1439 /**
1440 * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
1441 * Adds a bean which is invoked which could be a final destination, or could be a transformation in a pipeline
1442 *
1443 * @param ref reference to a bean to lookup in the registry
1444 * @param method the method name to invoke on the bean (can be used to avoid ambiguty)
1445 * @return the builder
1446 */
1447 @SuppressWarnings("unchecked")
1448 public Type beanRef(String ref, String method) {
1449 BeanDefinition answer = new BeanDefinition(ref, method);
1450 addOutput(answer);
1451 return (Type) this;
1452 }
1453
1454 /**
1455 * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
1456 * Adds a processor which sets the body on the IN message
1457 *
1458 * @return a expression builder clause to set the body
1459 */
1460 public ExpressionClause<ProcessorDefinition<Type>> setBody() {
1461 ExpressionClause<ProcessorDefinition<Type>> clause = new ExpressionClause<ProcessorDefinition<Type>>(this);
1462 SetBodyDefinition answer = new SetBodyDefinition(clause);
1463 addOutput(answer);
1464 return clause;
1465 }
1466
1467 /**
1468 * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
1469 * Adds a processor which sets the body on the IN message
1470 *
1471 * @param expression the expression used to set the body
1472 * @return the builder
1473 */
1474 @SuppressWarnings("unchecked")
1475 public Type setBody(Expression expression) {
1476 SetBodyDefinition answer = new SetBodyDefinition(expression);
1477 addOutput(answer);
1478 return (Type) this;
1479 }
1480
1481 /**
1482 * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
1483 * Adds a processor which sets the body on the OUT message
1484 *
1485 * @param expression the expression used to set the body
1486 * @return the builder
1487 */
1488 @SuppressWarnings("unchecked")
1489 public Type transform(Expression expression) {
1490 TransformDefinition answer = new TransformDefinition(expression);
1491 addOutput(answer);
1492 return (Type) this;
1493 }
1494
1495 /**
1496 * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
1497 * Adds a processor which sets the body on the OUT message
1498 *
1499 * @return a expression builder clause to set the body
1500 */
1501 public ExpressionClause<ProcessorDefinition<Type>> transform() {
1502 ExpressionClause<ProcessorDefinition<Type>> clause = new ExpressionClause<ProcessorDefinition<Type>>((Type) this);
1503 TransformDefinition answer = new TransformDefinition(clause);
1504 addOutput(answer);
1505 return clause;
1506 }
1507
1508 /**
1509 * Adds a processor which sets the body on the FAULT message
1510 *
1511 * @param expression the expression used to set the body
1512 * @return the builder
1513 */
1514 public Type setFaultBody(Expression expression) {
1515 return process(ProcessorBuilder.setFaultBody(expression));
1516 }
1517
1518 /**
1519 * Adds a processor which sets the header on the IN message
1520 *
1521 * @param name the header name
1522 * @return a expression builder clause to set the header
1523 */
1524 public ExpressionClause<ProcessorDefinition<Type>> setHeader(String name) {
1525 ExpressionClause<ProcessorDefinition<Type>> clause = new ExpressionClause<ProcessorDefinition<Type>>(this);
1526 SetHeaderDefinition answer = new SetHeaderDefinition(name, clause);
1527 addOutput(answer);
1528 return clause;
1529 }
1530
1531 /**
1532 * Adds a processor which sets the header on the IN message
1533 *
1534 * @param name the header name
1535 * @param expression the expression used to set the header
1536 * @return the builder
1537 */
1538 @SuppressWarnings("unchecked")
1539 public Type setHeader(String name, Expression expression) {
1540 SetHeaderDefinition answer = new SetHeaderDefinition(name, expression);
1541 addOutput(answer);
1542 return (Type) this;
1543 }
1544
1545 /**
1546 * Adds a processor which sets the header on the OUT message
1547 *
1548 * @param name the header name
1549 * @return a expression builder clause to set the header
1550 */
1551 public ExpressionClause<ProcessorDefinition<Type>> setOutHeader(String name) {
1552 ExpressionClause<ProcessorDefinition<Type>> clause = new ExpressionClause<ProcessorDefinition<Type>>(this);
1553 SetOutHeaderDefinition answer = new SetOutHeaderDefinition(name, clause);
1554 addOutput(answer);
1555 return clause;
1556 }
1557
1558 /**
1559 * Adds a processor which sets the header on the OUT message
1560 *
1561 * @param name the header name
1562 * @param expression the expression used to set the header
1563 * @return the builder
1564 */
1565 @SuppressWarnings("unchecked")
1566 public Type setOutHeader(String name, Expression expression) {
1567 SetOutHeaderDefinition answer = new SetOutHeaderDefinition(name, expression);
1568 addOutput(answer);
1569 return (Type) this;
1570 }
1571
1572 /**
1573 * Adds a processor which sets the header on the FAULT message
1574 *
1575 * @param name the header name
1576 * @param expression the expression used to set the header
1577 * @return the builder
1578 */
1579 public Type setFaultHeader(String name, Expression expression) {
1580 return process(ProcessorBuilder.setFaultHeader(name, expression));
1581 }
1582
1583 /**
1584 * Adds a processor which sets the exchange property
1585 *
1586 * @param name the property name
1587 * @param expression the expression used to set the property
1588 * @return the builder
1589 */
1590 @SuppressWarnings("unchecked")
1591 public Type setProperty(String name, Expression expression) {
1592 SetPropertyDefinition answer = new SetPropertyDefinition(name, expression);
1593 addOutput(answer);
1594 return (Type) this;
1595 }
1596
1597
1598 /**
1599 * Adds a processor which sets the exchange property
1600 *
1601 * @param name the property name
1602 * @return a expression builder clause to set the property
1603 */
1604 public ExpressionClause<ProcessorDefinition<Type>> setProperty(String name) {
1605 ExpressionClause<ProcessorDefinition<Type>> clause = new ExpressionClause<ProcessorDefinition<Type>>(this);
1606 SetPropertyDefinition answer = new SetPropertyDefinition(name, clause);
1607 addOutput(answer);
1608 return clause;
1609 }
1610
1611 /**
1612 * Adds a processor which removes the header on the IN message
1613 *
1614 * @param name the header name
1615 * @return the builder
1616 */
1617 @SuppressWarnings("unchecked")
1618 public Type removeHeader(String name) {
1619 RemoveHeaderDefinition answer = new RemoveHeaderDefinition(name);
1620 addOutput(answer);
1621 return (Type) this;
1622 }
1623
1624 /**
1625 * Adds a processor which removes the header on the FAULT message
1626 *
1627 * @param name the header name
1628 * @return the builder
1629 */
1630 public Type removeFaultHeader(String name) {
1631 return process(ProcessorBuilder.removeFaultHeader(name));
1632 }
1633
1634 /**
1635 * Adds a processor which removes the exchange property
1636 *
1637 * @param name the property name
1638 * @return the builder
1639 */
1640 @SuppressWarnings("unchecked")
1641 public Type removeProperty(String name) {
1642 RemovePropertyDefinition answer = new RemovePropertyDefinition(name);
1643 addOutput(answer);
1644 return (Type) this;
1645 }
1646
1647 /**
1648 * Converts the IN message body to the specified type
1649 *
1650 * @param type the type to convert to
1651 * @return the builder
1652 */
1653 @SuppressWarnings("unchecked")
1654 public Type convertBodyTo(Class type) {
1655 addOutput(new ConvertBodyDefinition(type));
1656 return (Type) this;
1657 }
1658
1659 /**
1660 * Converts the IN message body to the specified class type
1661 *
1662 * @param typeString the type to convert to as a fully qualified classname
1663 * @return the builder
1664 */
1665 @SuppressWarnings("unchecked")
1666 public Type convertBodyTo(String typeString) {
1667 addOutput(new ConvertBodyDefinition(typeString));
1668 return (Type) this;
1669 }
1670
1671 /**
1672 * Sorts the IN message body using the given comparator.
1673 * The IN body mut be convertable to {@link List}.
1674 *
1675 * @param comparator the comparator to use for sorting
1676 * @return the builder
1677 */
1678 @SuppressWarnings("unchecked")
1679 public Type sortBody(Comparator comparator) {
1680 addOutput(new SortDefinition(body(), comparator));
1681 return (Type) this;
1682 }
1683
1684 /**
1685 * Sorts the IN message body using a default sorting based on toString representation.
1686 * The IN body mut be convertable to {@link List}.
1687 *
1688 * @return the builder
1689 */
1690 public Type sortBody() {
1691 return sortBody(null);
1692 }
1693
1694 /**
1695 * Sorts the expression using the given comparator
1696 *
1697 * @param expression the expression, must be convertable to {@link List}
1698 * @param comparator the comparator to use for sorting
1699 * @return the builder
1700 */
1701 @SuppressWarnings("unchecked")
1702 public Type sort(Expression expression, Comparator comparator) {
1703 addOutput(new SortDefinition(expression, comparator));
1704 return (Type) this;
1705 }
1706
1707 /**
1708 * Sorts the expression using a default sorting based on toString representation.
1709 *
1710 * @param expression the expression, must be convertable to {@link List}
1711 * @return the builder
1712 */
1713 public Type sort(Expression expression) {
1714 return sort(expression, null);
1715 }
1716
1717 /**
1718 * Enriches an exchange with additional data obtained from a
1719 * <code>resourceUri</code>.
1720 *
1721 * @param resourceUri
1722 * URI of resource endpoint for obtaining additional data.
1723 * @param aggregationStrategy
1724 * aggregation strategy to aggregate input data and additional
1725 * data.
1726 * @return this processor type
1727 * @see org.apache.camel.processor.Enricher
1728 */
1729 @SuppressWarnings("unchecked")
1730 public Type enrich(String resourceUri, AggregationStrategy aggregationStrategy) {
1731 addOutput(new EnrichDefinition(aggregationStrategy, resourceUri));
1732 return (Type)this;
1733 }
1734
1735 // DataFormat support
1736 // -------------------------------------------------------------------------
1737
1738 /**
1739 * <a href="http://camel.apache.org/data-format.html">DataFormat:</a>
1740 * Unmarshals the in body using a {@link DataFormat} expression to define
1741 * the format of the input message and the output will be set on the out message body.
1742 *
1743 * @return the expression to create the {@link DataFormat}
1744 */
1745 public DataFormatClause<ProcessorDefinition<Type>> unmarshal() {
1746 return new DataFormatClause<ProcessorDefinition<Type>>(this, DataFormatClause.Operation.Unmarshal);
1747 }
1748
1749 /**
1750 * <a href="http://camel.apache.org/data-format.html">DataFormat:</a>
1751 * Unmarshals the in body using the specified {@link DataFormat}
1752 * and sets the output on the out message body.
1753 *
1754 * @param dataFormatType the dataformat
1755 * @return the builder
1756 */
1757 @SuppressWarnings("unchecked")
1758 public Type unmarshal(DataFormatDefinition dataFormatType) {
1759 addOutput(new UnmarshalDefinition(dataFormatType));
1760 return (Type) this;
1761 }
1762
1763 /**
1764 * <a href="http://camel.apache.org/data-format.html">DataFormat:</a>
1765 * Unmarshals the in body using the specified {@link DataFormat}
1766 * and sets the output on the out message body.
1767 *
1768 * @param dataFormat the dataformat
1769 * @return the builder
1770 */
1771 public Type unmarshal(DataFormat dataFormat) {
1772 return unmarshal(new DataFormatDefinition(dataFormat));
1773 }
1774
1775 /**
1776 * <a href="http://camel.apache.org/data-format.html">DataFormat:</a>
1777 * Unmarshals the in body using the specified {@link DataFormat}
1778 * reference in the {@link org.apache.camel.spi.Registry} and sets
1779 * the output on the out message body.
1780 *
1781 * @param dataTypeRef reference to a {@link DataFormat} to lookup in the registry
1782 * @return the builder
1783 */
1784 @SuppressWarnings("unchecked")
1785 public Type unmarshal(String dataTypeRef) {
1786 addOutput(new UnmarshalDefinition(dataTypeRef));
1787 return (Type) this;
1788 }
1789
1790 /**
1791 * <a href="http://camel.apache.org/data-format.html">DataFormat:</a>
1792 * Marshals the in body using a {@link DataFormat} expression to define
1793 * the format of the output which will be added to the out body.
1794 *
1795 * @return the expression to create the {@link DataFormat}
1796 */
1797 public DataFormatClause<ProcessorDefinition<Type>> marshal() {
1798 return new DataFormatClause<ProcessorDefinition<Type>>(this, DataFormatClause.Operation.Marshal);
1799 }
1800
1801 /**
1802 * <a href="http://camel.apache.org/data-format.html">DataFormat:</a>
1803 * Marshals the in body using the specified {@link DataFormat}
1804 * and sets the output on the out message body.
1805 *
1806 * @param dataFormatType the dataformat
1807 * @return the builder
1808 */
1809 @SuppressWarnings("unchecked")
1810 public Type marshal(DataFormatDefinition dataFormatType) {
1811 addOutput(new MarshalDefinition(dataFormatType));
1812 return (Type) this;
1813 }
1814
1815 /**
1816 * <a href="http://camel.apache.org/data-format.html">DataFormat:</a>
1817 * Marshals the in body using the specified {@link DataFormat}
1818 * and sets the output on the out message body.
1819 *
1820 * @param dataFormat the dataformat
1821 * @return the builder
1822 */
1823 public Type marshal(DataFormat dataFormat) {
1824 return marshal(new DataFormatDefinition(dataFormat));
1825 }
1826
1827 /**
1828 * <a href="http://camel.apache.org/data-format.html">DataFormat:</a>
1829 * Marshals the in body the specified {@link DataFormat}
1830 * reference in the {@link org.apache.camel.spi.Registry} and sets
1831 * the output on the out message body.
1832 *
1833 * @param dataTypeRef reference to a {@link DataFormat} to lookup in the registry
1834 * @return the builder
1835 */
1836 @SuppressWarnings("unchecked")
1837 public Type marshal(String dataTypeRef) {
1838 addOutput(new MarshalDefinition(dataTypeRef));
1839 return (Type) this;
1840 }
1841
1842 // Properties
1843 // -------------------------------------------------------------------------
1844 @XmlTransient
1845 @SuppressWarnings("unchecked")
1846 public ProcessorDefinition<? extends ProcessorDefinition> getParent() {
1847 return parent;
1848 }
1849
1850 public void setParent(ProcessorDefinition<? extends ProcessorDefinition> parent) {
1851 this.parent = parent;
1852 }
1853
1854 @XmlTransient
1855 public ErrorHandlerBuilder getErrorHandlerBuilder() {
1856 if (errorHandlerBuilder == null) {
1857 errorHandlerBuilder = createErrorHandlerBuilder();
1858 }
1859 return errorHandlerBuilder;
1860 }
1861
1862 /**
1863 * Sets the error handler to use with processors created by this builder
1864 */
1865 public void setErrorHandlerBuilder(ErrorHandlerBuilder errorHandlerBuilder) {
1866 this.errorHandlerBuilder = errorHandlerBuilder;
1867 }
1868
1869 /**
1870 * Sets the error handler if one is not already set
1871 */
1872 protected void setErrorHandlerBuilderIfNull(ErrorHandlerBuilder errorHandlerBuilder) {
1873 if (this.errorHandlerBuilder == null) {
1874 setErrorHandlerBuilder(errorHandlerBuilder);
1875 }
1876 }
1877
1878 public String getErrorHandlerRef() {
1879 return errorHandlerRef;
1880 }
1881
1882 /**
1883 * Sets the bean ref name of the error handler builder to use on this route
1884 */
1885 @XmlAttribute(required = false)
1886 public void setErrorHandlerRef(String errorHandlerRef) {
1887 this.errorHandlerRef = errorHandlerRef;
1888 setErrorHandlerBuilder(new ErrorHandlerBuilderRef(errorHandlerRef));
1889 }
1890
1891 @XmlTransient
1892 public boolean isInheritErrorHandler() {
1893 return isInheritErrorHandler(getInheritErrorHandlerFlag());
1894 }
1895
1896 /**
1897 * Lets default the inherit value to be true if there is none specified
1898 */
1899 public static boolean isInheritErrorHandler(Boolean value) {
1900 return value == null || value;
1901 }
1902
1903 @XmlAttribute(name = "inheritErrorHandler", required = false)
1904 public Boolean getInheritErrorHandlerFlag() {
1905 return inheritErrorHandlerFlag;
1906 }
1907
1908 public void setInheritErrorHandlerFlag(Boolean inheritErrorHandlerFlag) {
1909 this.inheritErrorHandlerFlag = inheritErrorHandlerFlag;
1910 }
1911
1912 @XmlTransient
1913 public NodeFactory getNodeFactory() {
1914 if (nodeFactory == null) {
1915 nodeFactory = new NodeFactory();
1916 }
1917 return nodeFactory;
1918 }
1919
1920 public void setNodeFactory(NodeFactory nodeFactory) {
1921 this.nodeFactory = nodeFactory;
1922 }
1923
1924 /**
1925 * Returns a label to describe this node such as the expression if some kind of expression node
1926 */
1927 public String getLabel() {
1928 return "";
1929 }
1930
1931 // Implementation methods
1932 // -------------------------------------------------------------------------
1933
1934 /**
1935 * Creates the processor and wraps it in any necessary interceptors and
1936 * error handlers
1937 */
1938 protected Processor makeProcessor(RouteContext routeContext) throws Exception {
1939 Processor processor = createProcessor(routeContext);
1940 return wrapProcessor(routeContext, processor);
1941 }
1942
1943 /**
1944 * A strategy method which allows derived classes to wrap the child
1945 * processor in some kind of interceptor
1946 *
1947 * @param routeContext the route context
1948 * @param target the processor which can be wrapped
1949 * @return the original processor or a new wrapped interceptor
1950 * @throws Exception can be thrown in case of error
1951 */
1952 protected Processor wrapProcessorInInterceptors(RouteContext routeContext, Processor target) throws Exception {
1953 ObjectHelper.notNull(target, "target", this);
1954
1955 List<InterceptStrategy> strategies = new ArrayList<InterceptStrategy>();
1956 CamelContext camelContext = routeContext.getCamelContext();
1957 strategies.addAll(camelContext.getInterceptStrategies());
1958 strategies.addAll(routeContext.getInterceptStrategies());
1959 for (InterceptStrategy strategy : strategies) {
1960 if (strategy != null) {
1961 target = strategy.wrapProcessorInInterceptors(this, target);
1962 }
1963 }
1964
1965 List<AbstractInterceptorDefinition> list = routeContext.getRoute().getInterceptors();
1966 if (interceptors != null) {
1967 list.addAll(interceptors);
1968 }
1969 // lets reverse the list so we apply the inner interceptors first
1970 Collections.reverse(list);
1971 Set<Processor> interceptors = new HashSet<Processor>();
1972 interceptors.add(target);
1973 for (AbstractInterceptorDefinition interceptorType : list) {
1974 DelegateProcessor interceptor = interceptorType.createInterceptor(routeContext);
1975 if (!interceptors.contains(interceptor)) {
1976 interceptors.add(interceptor);
1977 if (interceptor.getProcessor() != null) {
1978 LOG.warn("Interceptor " + interceptor + " currently wraps target "
1979 + interceptor.getProcessor()
1980 + " is attempting to change target " + target
1981 + " new wrapping has been denied.");
1982 } else {
1983 interceptor.setProcessor(target);
1984 target = interceptor;
1985 }
1986 }
1987 }
1988 return target;
1989 }
1990
1991 /**
1992 * A strategy method to allow newly created processors to be wrapped in an
1993 * error handler.
1994 */
1995 protected Processor wrapInErrorHandler(RouteContext routeContext, Processor target) throws Exception {
1996 ObjectHelper.notNull(target, "target", this);
1997 ErrorHandlerWrappingStrategy strategy = routeContext.getErrorHandlerWrappingStrategy();
1998 if (strategy != null) {
1999 return strategy.wrapProcessorInErrorHandler(this, target);
2000 }
2001 return getErrorHandlerBuilder().createErrorHandler(routeContext, target);
2002 }
2003
2004 protected ErrorHandlerBuilder createErrorHandlerBuilder() {
2005 if (errorHandlerRef != null) {
2006 return new ErrorHandlerBuilderRef(errorHandlerRef);
2007 }
2008 if (isInheritErrorHandler()) {
2009 return new DeadLetterChannelBuilder();
2010 } else {
2011 return new NoErrorHandlerBuilder();
2012 }
2013 }
2014
2015 protected void configureChild(ProcessorDefinition output) {
2016 output.setNodeFactory(getNodeFactory());
2017 }
2018
2019 @SuppressWarnings("unchecked")
2020 public void addOutput(ProcessorDefinition processorType) {
2021 processorType.setParent(this);
2022 configureChild(processorType);
2023 if (blocks.isEmpty()) {
2024 getOutputs().add(processorType);
2025 } else {
2026 Block block = blocks.getLast();
2027 block.addOutput(processorType);
2028 }
2029 }
2030
2031 /**
2032 * Creates a new instance of some kind of composite processor which defaults
2033 * to using a {@link Pipeline} but derived classes could change the
2034 * behaviour
2035 */
2036 protected Processor createCompositeProcessor(RouteContext routeContext, List<Processor> list) {
2037 return new Pipeline(list);
2038 }
2039
2040 protected Processor createOutputsProcessor(RouteContext routeContext, Collection<ProcessorDefinition> outputs)
2041 throws Exception {
2042 List<Processor> list = new ArrayList<Processor>();
2043 for (ProcessorDefinition output : outputs) {
2044 Processor processor = output.createProcessor(routeContext);
2045 // if the ProceedType/StopType create processor is null we keep on going
2046 if ((output instanceof ProceedDefinition || output instanceof StopDefinition) && processor == null) {
2047 continue;
2048 }
2049 processor = output.wrapProcessorInInterceptors(routeContext, processor);
2050
2051 ProcessorDefinition currentProcessor = this;
2052 if (!(currentProcessor instanceof OnExceptionDefinition || currentProcessor instanceof TryDefinition)) {
2053 processor = output.wrapInErrorHandler(routeContext, processor);
2054 }
2055
2056 list.add(processor);
2057 }
2058 Processor processor = null;
2059 if (!list.isEmpty()) {
2060 if (list.size() == 1) {
2061 processor = list.get(0);
2062 } else {
2063 processor = createCompositeProcessor(routeContext, list);
2064 }
2065 }
2066 return processor;
2067 }
2068
2069 public void clearOutput() {
2070 getOutputs().clear();
2071 blocks.clear();
2072 }
2073 }