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.Iterator;
025    import java.util.LinkedList;
026    import java.util.List;
027    import java.util.concurrent.TimeUnit;
028    
029    import javax.xml.bind.annotation.XmlAccessType;
030    import javax.xml.bind.annotation.XmlAccessorType;
031    import javax.xml.bind.annotation.XmlTransient;
032    
033    import org.apache.camel.Channel;
034    import org.apache.camel.Endpoint;
035    import org.apache.camel.ExchangePattern;
036    import org.apache.camel.Expression;
037    import org.apache.camel.LoggingLevel;
038    import org.apache.camel.Predicate;
039    import org.apache.camel.Processor;
040    import org.apache.camel.Route;
041    import org.apache.camel.builder.DataFormatClause;
042    import org.apache.camel.builder.ErrorHandlerBuilder;
043    import org.apache.camel.builder.ErrorHandlerBuilderRef;
044    import org.apache.camel.builder.ExpressionBuilder;
045    import org.apache.camel.builder.ExpressionClause;
046    import org.apache.camel.builder.ProcessorBuilder;
047    import org.apache.camel.language.simple.SimpleLanguage;
048    import org.apache.camel.model.language.ConstantExpression;
049    import org.apache.camel.model.language.ExpressionDefinition;
050    import org.apache.camel.model.language.LanguageExpression;
051    import org.apache.camel.processor.DefaultChannel;
052    import org.apache.camel.processor.InterceptEndpointProcessor;
053    import org.apache.camel.processor.Pipeline;
054    import org.apache.camel.processor.aggregate.AggregationCollection;
055    import org.apache.camel.processor.aggregate.AggregationStrategy;
056    import org.apache.camel.processor.interceptor.Delayer;
057    import org.apache.camel.processor.interceptor.HandleFault;
058    import org.apache.camel.processor.interceptor.StreamCaching;
059    import org.apache.camel.processor.loadbalancer.LoadBalancer;
060    import org.apache.camel.spi.DataFormat;
061    import org.apache.camel.spi.IdempotentRepository;
062    import org.apache.camel.spi.InterceptStrategy;
063    import org.apache.camel.spi.LifecycleStrategy;
064    import org.apache.camel.spi.Policy;
065    import org.apache.camel.spi.RouteContext;
066    import org.apache.camel.spi.TransactedPolicy;
067    import org.apache.commons.logging.Log;
068    import org.apache.commons.logging.LogFactory;
069    
070    import static org.apache.camel.builder.Builder.body;
071    
072    /**
073     * Base class for processor types that most XML types extend.
074     *
075     * @version $Revision: 896185 $
076     */
077    @XmlAccessorType(XmlAccessType.PROPERTY)
078    public abstract class ProcessorDefinition<Type extends ProcessorDefinition> extends OptionalIdentifiedDefinition implements Block {
079        protected final transient Log log = LogFactory.getLog(getClass());
080        protected ErrorHandlerBuilder errorHandlerBuilder;
081        protected String errorHandlerRef;
082        private NodeFactory nodeFactory;
083        private final LinkedList<Block> blocks = new LinkedList<Block>();
084        private ProcessorDefinition<?> parent;
085        private final List<InterceptStrategy> interceptStrategies = new ArrayList<InterceptStrategy>();
086    
087        // else to use an optional attribute in JAXB2
088        public abstract List<ProcessorDefinition> getOutputs();
089    
090        /**
091         * Whether this model is abstract or not.
092         * <p/>
093         * An abstract model is something that is used for configuring cross cutting concerns such as
094         * error handling, transaction policies, interceptors etc.
095         * <p/>
096         * Regular definitions is what is part of the route, such as ToDefinition, WireTapDefinition and the likes.
097         * <p/>
098         * Will by default return <tt>false</tt> to indicate regular definition, so all the abstract definitions
099         * must override this method and return <tt>true</tt> instead.
100         * <p/>
101         * This information is used in camel-spring to let Camel work a bit on the model provided by JAXB from the
102         * Spring XML file. This is needed to handle those cross cutting concerns properly. The Java DSL does not
103         * have this issue as it can work this out directly using the fluent builder methods.
104         *
105         * @return <tt>true</tt> for abstract, otherwise <tt>false</tt> for regular.
106         */
107        public boolean isAbstract() {
108            return false;
109        }
110    
111        public Processor createProcessor(RouteContext routeContext) throws Exception {
112            throw new UnsupportedOperationException("Not implemented yet for class: " + getClass().getName());
113        }
114    
115        public Processor createOutputsProcessor(RouteContext routeContext) throws Exception {
116            Collection<ProcessorDefinition> outputs = getOutputs();
117            return createOutputsProcessor(routeContext, outputs);
118        }
119    
120        public void addOutput(ProcessorDefinition processorType) {
121            processorType.setParent(this);
122            configureChild(processorType);
123            if (blocks.isEmpty()) {
124                getOutputs().add(processorType);
125            } else {
126                Block block = blocks.getLast();
127                block.addOutput(processorType);
128            }
129        }
130    
131        public void clearOutput() {
132            getOutputs().clear();
133            blocks.clear();
134        }
135    
136        public void addRoutes(RouteContext routeContext, Collection<Route> routes) throws Exception {
137            Processor processor = makeProcessor(routeContext);
138            if (processor == null) {
139                // no processor to add
140                return;
141            }
142    
143            if (!routeContext.isRouteAdded()) {
144                boolean endpointInterceptor = false;
145    
146                // are we routing to an endpoint interceptor, if so we should not add it as an event driven
147                // processor as we use the producer to trigger the interceptor
148                if (processor instanceof Channel) {
149                    Channel channel = (Channel) processor;
150                    Processor next = channel.getNextProcessor();
151                    if (next instanceof InterceptEndpointProcessor) {
152                        endpointInterceptor = true;
153                    }
154                }
155    
156                // only add regular processors as event driven
157                if (endpointInterceptor) {
158                    if (log.isDebugEnabled()) {
159                        log.debug("Endpoint interceptor should not be added as an event driven consumer route: " + processor);
160                    }
161                } else {
162                    if (log.isTraceEnabled()) {
163                        log.trace("Adding event driven processor: " + processor);
164                    }
165                    routeContext.addEventDrivenProcessor(processor);
166                }
167    
168            }
169        }
170    
171        /**
172         * Wraps the child processor in whatever necessary interceptors and error handlers
173         */
174        public Processor wrapProcessor(RouteContext routeContext, Processor processor) throws Exception {
175            // dont double wrap
176            if (processor instanceof Channel) {
177                return processor;
178            }
179            return wrapChannel(routeContext, processor, null);
180        }
181    
182        protected Processor wrapChannel(RouteContext routeContext, Processor processor, ProcessorDefinition child) throws Exception {
183            // put a channel in between this and each output to control the route flow logic
184            Channel channel = createChannel(routeContext);
185            channel.setNextProcessor(processor);
186    
187            // add interceptor strategies to the channel must be in this order: camel context, route context, local
188            addInterceptStrategies(routeContext, channel, routeContext.getCamelContext().getInterceptStrategies());
189            addInterceptStrategies(routeContext, channel, routeContext.getInterceptStrategies());
190            if (routeContext.getManagedInterceptStrategy() != null) {
191                channel.addInterceptStrategy(routeContext.getManagedInterceptStrategy());
192            }
193            addInterceptStrategies(routeContext, channel, this.getInterceptStrategies());
194    
195            // must do this ugly cast to avoid compiler error on HP-UX
196            ProcessorDefinition defn = (ProcessorDefinition) this;
197    
198            // set the child before init the channel
199            channel.setChildDefinition(child);
200            channel.initChannel(defn, routeContext);
201    
202            // set the error handler, must be done after init as we can set the error handler as first in the chain
203            if (defn instanceof TryDefinition || defn instanceof CatchDefinition || defn instanceof FinallyDefinition) {
204                // do not use error handler for try .. catch .. finally blocks as it will handle errors itself
205                return channel;
206            } else if (defn instanceof MulticastDefinition || defn instanceof RecipientListDefinition) {
207                // do not use error handler for multicast or recipientlist based as it offers fine grained error handlers for its outputs
208                return channel;
209            } else {
210                // regular definition so add the error handler
211                Processor output = channel.getOutput();
212                Processor errorHandler = wrapInErrorHandler(routeContext, getErrorHandlerBuilder(), output);
213                // set error handler on channel
214                channel.setErrorHandler(errorHandler);
215    
216                return channel;
217            }
218        }
219    
220        /**
221         * Wraps the given output in an error handler
222         *
223         * @param routeContext the route context
224         * @param output the output
225         * @return the output wrapped with the error handler
226         * @throws Exception can be thrown if failed to create error handler builder
227         */
228        protected Processor wrapInErrorHandler(RouteContext routeContext, ErrorHandlerBuilder builder, Processor output) throws Exception {
229            // create error handler
230            Processor errorHandler = builder.createErrorHandler(routeContext, output);
231    
232            // invoke lifecycles so we can manage this error handler builder
233            for (LifecycleStrategy strategy : routeContext.getCamelContext().getLifecycleStrategies()) {
234                strategy.onErrorHandlerAdd(routeContext, errorHandler, builder);
235            }
236    
237            return errorHandler;
238        }
239    
240        /**
241         * Adds the given list of interceptors to the channel.
242         *
243         * @param routeContext  the route context
244         * @param channel       the channel to add strategies
245         * @param strategies    list of strategies to add.
246         */
247        protected void addInterceptStrategies(RouteContext routeContext, Channel channel, List<InterceptStrategy> strategies) {
248            for (InterceptStrategy strategy : strategies) {
249                if (!routeContext.isStreamCaching() && strategy instanceof StreamCaching) {
250                    // stream cache is disabled so we should not add it
251                    continue;
252                }
253                if (!routeContext.isHandleFault() && strategy instanceof HandleFault) {
254                    // handle fault is disabled so we should not add it
255                    continue;
256                }
257                if (strategy instanceof Delayer) {
258                    if (routeContext.getDelayer() == null || routeContext.getDelayer() <= 0) {
259                        // delayer is disabled so we should not add it
260                        continue;
261                    } else {
262                        // replace existing delayer as delayer have individual configuration
263                        Iterator<InterceptStrategy> it = channel.getInterceptStrategies().iterator();
264                        while (it.hasNext()) {
265                            InterceptStrategy existing = it.next();
266                            if (existing instanceof Delayer) {
267                                it.remove();
268                            }
269                        }
270                        // add the new correct delayer
271                        channel.addInterceptStrategy(strategy);
272                        continue;
273                    }
274                }
275    
276                // add strategy
277                channel.addInterceptStrategy(strategy);
278            }
279        }
280    
281        /**
282         * Creates a new instance of some kind of composite processor which defaults
283         * to using a {@link Pipeline} but derived classes could change the behaviour
284         */
285        protected Processor createCompositeProcessor(RouteContext routeContext, List<Processor> list) throws Exception {
286            return new Pipeline(list);
287        }
288    
289        /**
290         * Creates a new instance of the {@link Channel}.
291         */
292        protected Channel createChannel(RouteContext routeContext) throws Exception {
293            return new DefaultChannel();
294        }
295    
296        protected Processor createOutputsProcessor(RouteContext routeContext, Collection<ProcessorDefinition> outputs) throws Exception {
297            List<Processor> list = new ArrayList<Processor>();
298            for (ProcessorDefinition<?> output : outputs) {
299                Processor processor = output.createProcessor(routeContext);
300                if (output instanceof Channel && processor == null) {
301                    continue;
302                }
303    
304                Processor channel = wrapChannel(routeContext, processor, output);
305                list.add(channel);
306            }
307    
308            // if more than one output wrap than in a composite processor else just keep it as is
309            Processor processor = null;
310            if (!list.isEmpty()) {
311                if (list.size() == 1) {
312                    processor = list.get(0);
313                } else {
314                    processor = createCompositeProcessor(routeContext, list);
315                }
316            }
317    
318            return processor;
319        }
320    
321        /**
322         * Creates the processor and wraps it in any necessary interceptors and error handlers
323         */
324        protected Processor makeProcessor(RouteContext routeContext) throws Exception {
325            Processor processor = createProcessor(routeContext);
326            if (processor == null) {
327                // no processor to make
328                return null;
329            }
330            return wrapProcessor(routeContext, processor);
331        }
332    
333        protected ErrorHandlerBuilder createErrorHandlerBuilder() {
334            if (errorHandlerRef != null) {
335                return new ErrorHandlerBuilderRef(errorHandlerRef);
336            }
337    
338            // return a reference to the default error handler
339            return new ErrorHandlerBuilderRef(ErrorHandlerBuilderRef.DEFAULT_ERROR_HANDLER_BUILDER);
340        }
341    
342        protected void configureChild(ProcessorDefinition output) {
343            output.setNodeFactory(getNodeFactory());
344            output.setErrorHandlerBuilder(getErrorHandlerBuilder());
345        }
346    
347        // Fluent API
348        // -------------------------------------------------------------------------
349    
350        /**
351         * Sends the exchange to the given endpoint
352         *
353         * @param uri  the endpoint to send to
354         * @return the builder
355         */
356        @SuppressWarnings("unchecked")
357        public Type to(String uri) {
358            addOutput(new ToDefinition(uri));
359            return (Type) this;
360        }   
361        
362        /**
363         * Sends the exchange to the given endpoint
364         *
365         * @param uri  the String formatted endpoint uri to send to
366         * @param args arguments for the string formatting of the uri
367         * @return the builder
368         */
369        @SuppressWarnings("unchecked")
370        public Type toF(String uri, Object... args) {
371            addOutput(new ToDefinition(String.format(uri, args)));
372            return (Type) this;
373        }
374    
375    
376        /**
377         * Sends the exchange to the given endpoint
378         *
379         * @param endpoint  the endpoint to send to
380         * @return the builder
381         */
382        @SuppressWarnings("unchecked")
383        public Type to(Endpoint endpoint) {
384            addOutput(new ToDefinition(endpoint));
385            return (Type) this;
386        }
387        
388        /**
389         * Sends the exchange with certain exchange pattern to the given endpoint
390         *
391         * @param pattern the pattern to use for the message exchange
392         * @param uri  the endpoint to send to
393         * @return the builder
394         */
395        @SuppressWarnings("unchecked")
396        public Type to(ExchangePattern pattern, String uri) {
397            addOutput(new ToDefinition(uri, pattern));
398            return (Type) this;
399        }   
400        
401    
402        /**
403         * Sends the exchange with certain exchange pattern to the given endpoint
404         *
405         * @param pattern the pattern to use for the message exchange
406         * @param endpoint  the endpoint to send to
407         * @return the builder
408         */
409        @SuppressWarnings("unchecked")
410        public Type to(ExchangePattern pattern, Endpoint endpoint) {
411            addOutput(new ToDefinition(endpoint, pattern));
412            return (Type) this;
413        }
414    
415        /**
416         * Sends the exchange to a list of endpoints
417         *
418         * @param uris  list of endpoints to send to
419         * @return the builder
420         */
421        @SuppressWarnings("unchecked")
422        public Type to(String... uris) {
423            for (String uri : uris) {
424                addOutput(new ToDefinition(uri));
425            }
426            return (Type) this;
427        }
428    
429    
430        /**
431         * Sends the exchange to a list of endpoints
432         *
433         * @param endpoints  list of endpoints to send to
434         * @return the builder
435         */
436        @SuppressWarnings("unchecked")
437        public Type to(Endpoint... endpoints) {
438            for (Endpoint endpoint : endpoints) {
439                addOutput(new ToDefinition(endpoint));
440            }
441            return (Type) this;
442        }
443    
444        /**
445         * Sends the exchange to a list of endpoints
446         *
447         * @param endpoints  list of endpoints to send to
448         * @return the builder
449         */
450        @SuppressWarnings("unchecked")
451        public Type to(Iterable<Endpoint> endpoints) {
452            for (Endpoint endpoint : endpoints) {
453                addOutput(new ToDefinition(endpoint));
454            }
455            return (Type) this;
456        }
457        
458        
459        /**
460         * Sends the exchange to a list of endpoints
461         *
462         * @param pattern the pattern to use for the message exchanges
463         * @param uris  list of endpoints to send to
464         * @return the builder
465         */
466        @SuppressWarnings("unchecked")
467        public Type to(ExchangePattern pattern, String... uris) {
468            for (String uri : uris) {
469                addOutput(new ToDefinition(uri, pattern));
470            }
471            return (Type) this;
472        }
473    
474        /**
475         * Sends the exchange to a list of endpoints
476         *
477         * @param pattern the pattern to use for the message exchanges
478         * @param endpoints  list of endpoints to send to
479         * @return the builder
480         */
481        @SuppressWarnings("unchecked")
482        public Type to(ExchangePattern pattern, Endpoint... endpoints) {
483            for (Endpoint endpoint : endpoints) {
484                addOutput(new ToDefinition(endpoint, pattern));
485            }
486            return (Type) this;
487        }
488    
489        /**
490         * Sends the exchange to a list of endpoints
491         *
492         * @param pattern the pattern to use for the message exchanges
493         * @param endpoints  list of endpoints to send to
494         * @return the builder
495         */
496        @SuppressWarnings("unchecked")
497        public Type to(ExchangePattern pattern, Iterable<Endpoint> endpoints) {
498            for (Endpoint endpoint : endpoints) {
499                addOutput(new ToDefinition(endpoint, pattern));
500            }
501            return (Type) this;
502        }
503    
504        /**
505         * Sends the exchange to the given endpoint using synchronous mode.
506         *
507         * @param uri  the endpoint to send to
508         * @return the builder
509         * @see org.apache.camel.AsyncProcessor
510         */
511        public ToDefinition toAsync(String uri) {
512            ToDefinition answer = new ToDefinition(uri);
513            answer.setAsync(true);
514            addOutput(answer);
515            // must push a block so we have a child route for the async reply
516            // routing which is separated from the caller route
517            pushBlock(answer);
518            return answer;
519        }
520    
521        /**
522         * Sends the exchange to the given endpoint using synchronous mode.
523         *
524         * @param uri  the endpoint to send to
525         * @param poolSize the core pool size
526         * @return the builder
527         * @see org.apache.camel.AsyncProcessor
528         */
529        public ToDefinition toAsync(String uri, int poolSize) {
530            ToDefinition answer = new ToDefinition(uri);
531            answer.setAsync(true);
532            answer.setPoolSize(poolSize);
533            addOutput(answer);
534            // must push a block so we have a child route for the async reply
535            // routing which is separated from the caller route
536            pushBlock(answer);
537            return answer;
538        }
539    
540        /**
541         * Sends the exchange to the given endpoint using synchronous mode.
542         *
543         * @param endpoint  the endpoint to send to
544         * @return the builder
545         * @see org.apache.camel.AsyncProcessor
546         */
547        public ToDefinition toAsync(Endpoint endpoint) {
548            ToDefinition answer = new ToDefinition(endpoint);
549            answer.setAsync(true);
550            addOutput(answer);
551            // must push a block so we have a child route for the async reply
552            // routing which is separated from the caller route
553            pushBlock(answer);
554            return answer;
555        }
556    
557        /**
558         * Sends the exchange to the given endpoint using synchronous mode.
559         *
560         * @param endpoint  the endpoint to send to
561         * @param poolSize the core pool size
562         * @return the builder
563         * @see org.apache.camel.AsyncProcessor
564         */
565        public ToDefinition toAsync(Endpoint endpoint, int poolSize) {
566            ToDefinition answer = new ToDefinition(endpoint);
567            answer.setAsync(true);
568            answer.setPoolSize(poolSize);
569            addOutput(answer);
570            // must push a block so we have a child route for the async reply
571            // routing which is separated from the caller route
572            pushBlock(answer);
573            return answer;
574        }
575    
576        /**
577         * <a href="http://camel.apache.org/exchange-pattern.html">ExchangePattern:</a>
578         * set the ExchangePattern {@link ExchangePattern} into the exchange
579         *
580         * @param exchangePattern  instance of {@link ExchangePattern}
581         * @return the builder
582         */
583        @SuppressWarnings("unchecked")
584        public Type setExchangePattern(ExchangePattern exchangePattern) {
585            addOutput(new SetExchangePatternDefinition(exchangePattern));
586            return (Type) this;
587        }
588    
589        /**
590         * <a href="http://camel.apache.org/exchange-pattern.html">ExchangePattern:</a>
591         * set the exchange's ExchangePattern {@link ExchangePattern} to be InOnly
592         *
593         *
594         * @return the builder
595         */
596        public Type inOnly() {
597            return setExchangePattern(ExchangePattern.InOnly);
598        }
599    
600        /**
601         * Sends the message to the given endpoint using an
602         * <a href="http://camel.apache.org/event-message.html">Event Message</a> or
603         * <a href="http://camel.apache.org/exchange-pattern.html">InOnly exchange pattern</a>
604         *
605         * @param uri The endpoint uri which is used for sending the exchange
606         * @return the builder
607         */
608        public Type inOnly(String uri) {
609            return to(ExchangePattern.InOnly, uri);
610        }
611    
612        /**
613         * Sends the message to the given endpoint using an
614         * <a href="http://camel.apache.org/event-message.html">Event Message</a> or 
615         * <a href="http://camel.apache.org/exchange-pattern.html">InOnly exchange pattern</a>
616         *
617         * @param endpoint The endpoint which is used for sending the exchange
618         * @return the builder
619         */
620        public Type inOnly(Endpoint endpoint) {
621            return to(ExchangePattern.InOnly, endpoint);
622        }
623    
624    
625        /**
626         * Sends the message to the given endpoints using an
627         * <a href="http://camel.apache.org/event-message.html">Event Message</a> or
628         * <a href="http://camel.apache.org/exchange-pattern.html">InOnly exchange pattern</a>
629         *
630         * @param uris  list of endpoints to send to
631         * @return the builder
632         */
633        public Type inOnly(String... uris) {
634            return to(ExchangePattern.InOnly, uris);
635        }
636    
637    
638        /**
639         * Sends the message to the given endpoints using an
640         * <a href="http://camel.apache.org/event-message.html">Event Message</a> or
641         * <a href="http://camel.apache.org/exchange-pattern.html">InOnly exchange pattern</a>
642         *
643         * @param endpoints  list of endpoints to send to
644         * @return the builder
645         */
646        public Type inOnly(Endpoint... endpoints) {
647            return to(ExchangePattern.InOnly, endpoints);
648        }
649    
650        /**
651         * Sends the message to the given endpoints using an
652         * <a href="http://camel.apache.org/event-message.html">Event Message</a> or
653         * <a href="http://camel.apache.org/exchange-pattern.html">InOnly exchange pattern</a>
654         *
655         * @param endpoints  list of endpoints to send to
656         * @return the builder
657         */
658        public Type inOnly(Iterable<Endpoint> endpoints) {
659            return to(ExchangePattern.InOnly, endpoints);
660        }
661    
662    
663        /**
664         * <a href="http://camel.apache.org/exchange-pattern.html">ExchangePattern:</a>
665         * set the exchange's ExchangePattern {@link ExchangePattern} to be InOut
666         *
667         *
668         * @return the builder
669         */
670        public Type inOut() {
671            return setExchangePattern(ExchangePattern.InOut);
672        }
673    
674        /**
675         * Sends the message to the given endpoint using an
676         * <a href="http://camel.apache.org/request-reply.html">Request Reply</a> or
677         * <a href="http://camel.apache.org/exchange-pattern.html">InOut exchange pattern</a>
678         *
679         * @param uri The endpoint uri which is used for sending the exchange
680         * @return the builder
681         */
682        public Type inOut(String uri) {
683            return to(ExchangePattern.InOut, uri);
684        }
685    
686    
687        /**
688         * Sends the message to the given endpoint using an
689         * <a href="http://camel.apache.org/request-reply.html">Request Reply</a> or
690         * <a href="http://camel.apache.org/exchange-pattern.html">InOut exchange pattern</a>
691         *
692         * @param endpoint The endpoint which is used for sending the exchange
693         * @return the builder
694         */
695        public Type inOut(Endpoint endpoint) {
696            return to(ExchangePattern.InOut, endpoint);
697        }
698    
699        /**
700         * Sends the message to the given endpoints using an
701         * <a href="http://camel.apache.org/request-reply.html">Request Reply</a> or
702         * <a href="http://camel.apache.org/exchange-pattern.html">InOut exchange pattern</a>
703         *
704         * @param uris  list of endpoints to send to
705         * @return the builder
706         */
707        public Type inOut(String... uris) {
708            return to(ExchangePattern.InOut, uris);
709        }
710    
711    
712        /**
713         * Sends the message to the given endpoints using an
714         * <a href="http://camel.apache.org/request-reply.html">Request Reply</a> or
715         * <a href="http://camel.apache.org/exchange-pattern.html">InOut exchange pattern</a>
716         *
717         * @param endpoints  list of endpoints to send to
718         * @return the builder
719         */
720        public Type inOut(Endpoint... endpoints) {
721            return to(ExchangePattern.InOut, endpoints);
722        }
723    
724        /**
725         * Sends the message to the given endpoints using an
726         * <a href="http://camel.apache.org/request-reply.html">Request Reply</a> or
727         * <a href="http://camel.apache.org/exchange-pattern.html">InOut exchange pattern</a>
728         *
729         * @param endpoints  list of endpoints to send to
730         * @return the builder
731         */
732        public Type inOut(Iterable<Endpoint> endpoints) {
733            return to(ExchangePattern.InOut, endpoints);
734        }
735    
736        /**
737         * Sets the id of this node
738         *
739         * @param id  the id
740         * @return the builder
741         */
742        @SuppressWarnings("unchecked")
743        public Type id(String id) {
744            if (getOutputs().isEmpty()) {
745                // set id on this
746                setId(id);
747            } else {
748                // set it on last output as this is what the user means to do
749                getOutputs().get(getOutputs().size() - 1).setId(id);
750            }
751    
752            return (Type) this;
753        }
754    
755        /**
756         * Set the route id for this route
757         *
758         * @param id  the route id
759         * @return the builder
760         */
761        @SuppressWarnings("unchecked")
762        public Type routeId(String id) {
763            ProcessorDefinition def = this;
764    
765            RouteDefinition route = ProcessorDefinitionHelper.getRoute(def);
766            if (route != null) {
767                route.setId(id);
768            }
769    
770            return (Type) this;
771        }
772    
773        /**
774         * <a href="http://camel.apache.org/multicast.html">Multicast EIP:</a>
775         * Multicasts messages to all its child outputs; so that each processor and
776         * destination gets a copy of the original message to avoid the processors
777         * interfering with each other.
778         *
779         * @return the builder
780         */
781        public MulticastDefinition multicast() {
782            MulticastDefinition answer = new MulticastDefinition();
783            addOutput(answer);
784            return answer;
785        }
786    
787        /**
788         * <a href="http://camel.apache.org/multicast.html">Multicast EIP:</a>
789         * Multicasts messages to all its child outputs; so that each processor and
790         * destination gets a copy of the original message to avoid the processors
791         * interfering with each other.
792         *
793         * @param aggregationStrategy the strategy used to aggregate responses for
794         *          every part
795         * @param parallelProcessing if is <tt>true</tt> camel will fork thread to call the endpoint producer
796         * @return the builder
797         */
798        public MulticastDefinition multicast(AggregationStrategy aggregationStrategy, boolean parallelProcessing) {
799            MulticastDefinition answer = new MulticastDefinition();
800            addOutput(answer);
801            answer.setAggregationStrategy(aggregationStrategy);
802            answer.setParallelProcessing(parallelProcessing);
803            return answer;
804        }
805    
806        /**
807         * <a href="http://camel.apache.org/multicast.html">Multicast EIP:</a>
808         * Multicasts messages to all its child outputs; so that each processor and
809         * destination gets a copy of the original message to avoid the processors
810         * interfering with each other.
811         *
812         * @param aggregationStrategy the strategy used to aggregate responses for
813         *          every part
814         * @return the builder
815         */
816        public MulticastDefinition multicast(AggregationStrategy aggregationStrategy) {
817            MulticastDefinition answer = new MulticastDefinition();
818            addOutput(answer);
819            answer.setAggregationStrategy(aggregationStrategy);
820            return answer;
821        }
822    
823        /**
824         * <a href="http://camel.apache.org/pipes-nd-filters.html">Pipes and Filters EIP:</a>
825         * Creates a {@link Pipeline} so that the message
826         * will get processed by each endpoint in turn and for request/response the
827         * output of one endpoint will be the input of the next endpoint
828         *
829         * @return the builder
830         */
831        public PipelineDefinition pipeline() {
832            PipelineDefinition answer = new PipelineDefinition();
833            addOutput(answer);
834            return answer;
835        }
836    
837        /**
838         * <a href="http://camel.apache.org/pipes-nd-filters.html">Pipes and Filters EIP:</a>
839         * Creates a {@link Pipeline} of the list of endpoints so that the message
840         * will get processed by each endpoint in turn and for request/response the
841         * output of one endpoint will be the input of the next endpoint
842         *
843         * @param uris  list of endpoints
844         * @return the builder
845         */
846        public Type pipeline(String... uris) {
847            return to(uris);
848        }
849    
850        /**
851         * <a href="http://camel.apache.org/pipes-nd-filters.html">Pipes and Filters EIP:</a>
852         * Creates a {@link Pipeline} of the list of endpoints so that the message
853         * will get processed by each endpoint in turn and for request/response the
854         * output of one endpoint will be the input of the next endpoint
855         *
856         * @param endpoints  list of endpoints
857         * @return the builder
858         */
859        public Type pipeline(Endpoint... endpoints) {
860            return to(endpoints);
861        }
862    
863        /**
864         * <a href="http://camel.apache.org/pipes-nd-filters.html">Pipes and Filters EIP:</a>
865         * Creates a {@link Pipeline} of the list of endpoints so that the message
866         * will get processed by each endpoint in turn and for request/response the
867         * output of one endpoint will be the input of the next endpoint
868         *
869         * @param endpoints  list of endpoints
870         * @return the builder
871         */
872        public Type pipeline(Collection<Endpoint> endpoints) {
873            return to(endpoints);
874        }
875    
876        /**
877         * Leverages a thread pool for multi threading processing exchanges.
878         * <p/>
879         * The caller thread will either wait for the async route
880         * to complete or imeddiately continue. If continue the OUT message will
881         * contain a {@link java.util.concurrent.Future} handle so you can get the real response
882         * later using this handle.
883         * <p/>
884         * Will default <tt>Always</tt> wait for the async route to complete, but this behavior can be overriden by:
885         * <ul>
886         *   <li>Configuring the <tt>waitForTaskToComplete</tt> option</li>
887         *   <li>Provide an IN header with the key {@link org.apache.camel.Exchange#ASYNC_WAIT} with the
888         * value containing a type {@link org.apache.camel.WaitForTaskToComplete}. The header will take precedence, if provided.</li>
889         * </ul>
890         *
891         * @return the builder
892         */
893        public ThreadsDefinition threads() {
894            ThreadsDefinition answer = new ThreadsDefinition();
895            addOutput(answer);
896            return answer;
897        }
898    
899        /**
900         * Leverages a thread pool for multi threading processing exchanges.
901         * <p/>
902         * See {@link #threads()} for more details.
903         *
904         * @param poolSize the core pool size
905         * @return the builder
906         */
907        public ThreadsDefinition threads(int poolSize) {
908            ThreadsDefinition answer = threads();
909            answer.setPoolSize(poolSize);
910            return answer;
911        }
912    
913        /**
914         * Wraps the sub route using AOP allowing you to do before and after work (AOP around).
915         *
916         * @return the builder
917         */
918        public AOPDefinition aop() {
919            AOPDefinition answer = new AOPDefinition();
920            addOutput(answer);
921            return answer;
922        }
923    
924        /**
925         * Ends the current block
926         *
927         * @return the builder
928         */
929        @SuppressWarnings("unchecked")
930        public ProcessorDefinition end() {
931            // when using doTry .. doCatch .. doFinally we should always
932            // end the try definition to avoid having to use 2 x end() in the route
933            // this is counter intuitive for end users
934            ProcessorDefinition defn = (ProcessorDefinition) this;
935            if (defn instanceof TryDefinition) {
936                popBlock();
937            }
938    
939            if (blocks.isEmpty()) {
940                if (parent == null) {
941                    return this; 
942                }
943                return parent;
944            }
945            popBlock();
946            return this;
947        }
948    
949        /**
950         * <a href="http://camel.apache.org/idempotent-consumer.html">Idempotent consumer EIP:</a>
951         * Creates an {@link org.apache.camel.processor.idempotent.IdempotentConsumer IdempotentConsumer}
952         * to avoid duplicate messages
953         *      
954         * @return the builder
955         */
956        public IdempotentConsumerDefinition idempotentConsumer() {
957            IdempotentConsumerDefinition answer = new IdempotentConsumerDefinition();
958            addOutput(answer);
959            return answer;
960        }
961    
962        /**
963         * <a href="http://camel.apache.org/idempotent-consumer.html">Idempotent consumer EIP:</a>
964         * Creates an {@link org.apache.camel.processor.idempotent.IdempotentConsumer IdempotentConsumer}
965         * to avoid duplicate messages
966         *
967         * @param messageIdExpression  expression to test of duplicate messages
968         * @param idempotentRepository  the repository to use for duplicate chedck
969         * @return the builder
970         */
971        public IdempotentConsumerDefinition idempotentConsumer(Expression messageIdExpression, IdempotentRepository<?> idempotentRepository) {
972            IdempotentConsumerDefinition answer = new IdempotentConsumerDefinition(messageIdExpression, idempotentRepository);
973            addOutput(answer);
974            return answer;
975        }
976    
977        /**
978         * <a href="http://camel.apache.org/idempotent-consumer.html">Idempotent consumer EIP:</a>
979         * Creates an {@link org.apache.camel.processor.idempotent.IdempotentConsumer IdempotentConsumer}
980         * to avoid duplicate messages
981         *
982         * @param idempotentRepository the repository to use for duplicate chedck
983         * @return the builder used to create the expression
984         */
985        public ExpressionClause<IdempotentConsumerDefinition> idempotentConsumer(IdempotentRepository<?> idempotentRepository) {
986            IdempotentConsumerDefinition answer = new IdempotentConsumerDefinition();
987            answer.setMessageIdRepository(idempotentRepository);
988            addOutput(answer);
989            return ExpressionClause.createAndSetExpression(answer);
990        }
991    
992        /**
993         * <a href="http://camel.apache.org/message-filter.html">Message Filter EIP:</a>
994         * Creates a predicate expression which only if it is <tt>true</tt> then the
995         * exchange is forwarded to the destination
996         *
997         * @return the clause used to create the filter expression
998         */
999        public ExpressionClause<FilterDefinition> filter() {
1000            FilterDefinition filter = new FilterDefinition();
1001            addOutput(filter);
1002            return ExpressionClause.createAndSetExpression(filter);
1003        }
1004    
1005        /**
1006         * <a href="http://camel.apache.org/message-filter.html">Message Filter EIP:</a>
1007         * Creates a predicate which is applied and only if it is <tt>true</tt> then the
1008         * exchange is forwarded to the destination
1009         *
1010         * @param predicate  predicate to use
1011         * @return the builder 
1012         */
1013        public FilterDefinition filter(Predicate predicate) {
1014            FilterDefinition filter = new FilterDefinition(predicate);
1015            addOutput(filter);
1016            return filter;
1017        }
1018    
1019        /**
1020         * <a href="http://camel.apache.org/message-filter.html">Message Filter EIP:</a>
1021         * Creates a predicate expression which only if it is <tt>true</tt> then the
1022         * exchange is forwarded to the destination
1023         *
1024         * @param expression  the predicate expression to use
1025         * @return the builder
1026         */
1027        public FilterDefinition filter(ExpressionDefinition expression) {
1028            FilterDefinition filter = getNodeFactory().createFilter();
1029            filter.setExpression(expression);
1030            addOutput(filter);
1031            return filter;
1032        }
1033    
1034        /**
1035         * <a href="http://camel.apache.org/message-filter.html">Message Filter EIP:</a>
1036         * Creates a predicate language expression which only if it is <tt>true</tt> then the
1037         * exchange is forwarded to the destination
1038         *
1039         * @param language     language for expression
1040         * @param expression   the expression
1041         * @return the builder
1042         */
1043        public FilterDefinition filter(String language, String expression) {
1044            return filter(new LanguageExpression(language, expression));
1045        }
1046    
1047        /**
1048         * <a href="http://camel.apache.org/load-balancer.html">Load Balancer EIP:</a>
1049         * Creates a loadbalance
1050         *
1051         * @return  the builder
1052         */
1053        public LoadBalanceDefinition loadBalance() {
1054            LoadBalanceDefinition answer = new LoadBalanceDefinition();
1055            addOutput(answer);
1056            return answer;
1057        }
1058    
1059        /**
1060         * <a href="http://camel.apache.org/load-balancer.html">Load Balancer EIP:</a>
1061         * Creates a loadbalance
1062         *
1063         * @param loadBalancer a custom load balancer to use
1064         * @return  the builder
1065         */
1066        public LoadBalanceDefinition loadBalance(LoadBalancer loadBalancer) {
1067            LoadBalanceDefinition answer = new LoadBalanceDefinition();
1068            addOutput(answer);
1069            return answer.loadBalance(loadBalancer);
1070        }
1071    
1072        /**
1073         * Creates a log message to be logged at INFO level.
1074         *
1075         * @param message the log message, (you can use {@link org.apache.camel.language.simple.SimpleLanguage} syntax)
1076         * @return the builder
1077         */
1078        @SuppressWarnings("unchecked")
1079        public Type log(String message) {
1080            LogDefinition answer = new LogDefinition(message);
1081            addOutput(answer);
1082            return (Type) this;
1083        }
1084    
1085        /**
1086         * Creates a log message to be logged at the given level.
1087         *
1088         * @param loggingLevel the logging level to use
1089         * @param message the log message, (you can use {@link org.apache.camel.language.simple.SimpleLanguage} syntax)
1090         * @return the builder
1091         */
1092        @SuppressWarnings("unchecked")
1093        public Type log(LoggingLevel loggingLevel, String message) {
1094            LogDefinition answer = new LogDefinition(message);
1095            answer.setLoggingLevel(loggingLevel);
1096            addOutput(answer);
1097            return (Type) this;
1098        }
1099    
1100        /**
1101         * Creates a log message to be logged at the given level and name.
1102         *
1103         * @param loggingLevel the logging level to use
1104         * @param logName the log name to use
1105         * @param message the log message, (you can use {@link org.apache.camel.language.simple.SimpleLanguage} syntax)
1106         * @return the builder
1107         */
1108        @SuppressWarnings("unchecked")
1109        public Type log(LoggingLevel loggingLevel, String logName, String message) {
1110            LogDefinition answer = new LogDefinition(message);
1111            answer.setLoggingLevel(loggingLevel);
1112            answer.setLogName(logName);
1113            addOutput(answer);
1114            return (Type) this;
1115        }
1116    
1117        /**
1118         * <a href="http://camel.apache.org/content-based-router.html">Content Based Router EIP:</a>
1119         * Creates a choice of one or more predicates with an otherwise clause
1120         *
1121         * @return the builder for a choice expression
1122         */
1123        public ChoiceDefinition choice() {
1124            ChoiceDefinition answer = new ChoiceDefinition();
1125            addOutput(answer);
1126            return answer;
1127        }
1128    
1129        /**
1130         * Creates a try/catch block
1131         *
1132         * @return the builder for a tryBlock expression
1133         */
1134        public TryDefinition doTry() {
1135            TryDefinition answer = new TryDefinition();
1136            addOutput(answer);
1137            return answer;
1138        }
1139    
1140        /**
1141         * <a href="http://camel.apache.org/recipient-list.html">Recipient List EIP:</a>
1142         * Creates a dynamic recipient list allowing you to route messages to a number of dynamically specified recipients.
1143         * <p/>
1144         * Will use comma as default delimiter.
1145         *
1146         * @param recipients expression to decide the destinations
1147         * @return the builder
1148         */
1149        @SuppressWarnings("unchecked")
1150        public RecipientListDefinition recipientList(Expression recipients) {
1151            RecipientListDefinition answer = new RecipientListDefinition(recipients);
1152            addOutput(answer);
1153            return answer;
1154        }
1155    
1156        /**
1157         * <a href="http://camel.apache.org/recipient-list.html">Recipient List EIP:</a>
1158         * Creates a dynamic recipient list allowing you to route messages to a number of dynamically specified recipients
1159         *
1160         * @param recipients expression to decide the destinations
1161         * @param delimiter  a custom delimiter to use
1162         * @return the builder
1163         */
1164        @SuppressWarnings("unchecked")
1165        public RecipientListDefinition recipientList(Expression recipients, String delimiter) {
1166            RecipientListDefinition answer = new RecipientListDefinition(recipients);
1167            answer.setDelimiter(delimiter);
1168            addOutput(answer);
1169            return answer;
1170        }
1171    
1172        /**
1173         * <a href="http://camel.apache.org/recipient-list.html">Recipient List EIP:</a>
1174         * Creates a dynamic recipient list allowing you to route messages to a number of dynamically specified recipients
1175         *
1176         * @return the expression clause to configure the expression to decide the destinations
1177         */
1178        public ExpressionClause<RecipientListDefinition> recipientList() {
1179            RecipientListDefinition answer = new RecipientListDefinition();
1180            addOutput(answer);
1181            return ExpressionClause.createAndSetExpression(answer);
1182        }
1183    
1184        /**
1185         * <a href="http://camel.apache.org/routing-slip.html">Routing Slip EIP:</a>
1186         * Creates a routing slip allowing you to route a message consecutively through a series of processing
1187         * steps where the sequence of steps is not known at design time and can vary for each message.
1188         *
1189         * @param header  is the header that the {@link org.apache.camel.processor.RoutingSlip RoutingSlip}
1190         *                class will look in for the list of URIs to route the message to.
1191         * @param uriDelimiter  is the delimiter that will be used to split up
1192         *                      the list of URIs in the routing slip.
1193         * @return the builder
1194         */
1195        @SuppressWarnings("unchecked")
1196        public Type routingSlip(String header, String uriDelimiter) {
1197            RoutingSlipDefinition answer = new RoutingSlipDefinition(header, uriDelimiter);
1198            addOutput(answer);
1199            return (Type) this;
1200        }
1201    
1202        /**
1203         * <a href="http://camel.apache.org/routing-slip.html">Routing Slip EIP:</a>
1204         * Creates a routing slip allowing you to route a message consecutively through a series of processing
1205         * steps where the sequence of steps is not known at design time and can vary for each message.
1206         * <p>
1207         * The list of URIs will be split based on the default delimiter {@link RoutingSlipDefinition#DEFAULT_DELIMITER}
1208         *
1209         * @param header  is the header that the {@link org.apache.camel.processor.RoutingSlip RoutingSlip}
1210         *                class will look in for the list of URIs to route the message to.
1211         * @return the builder
1212         */
1213        @SuppressWarnings("unchecked")
1214        public Type routingSlip(String header) {
1215            RoutingSlipDefinition answer = new RoutingSlipDefinition(header);
1216            addOutput(answer);
1217            return (Type) this;
1218        }
1219    
1220        /**
1221         * <a href="http://camel.apache.org/sampling.html">Sampling Throttler</a>
1222         * Creates a sampling throttler allowing you to extract a sample of
1223         * exchanges from the traffic on a route. It is configured with a sampling
1224         * period, during which only a single exchange is allowed to pass through.
1225         * All other exchanges will be stopped.
1226         * <p/>
1227         * Default period is one second.
1228         *
1229         * @return the builder
1230         */
1231        public SamplingDefinition sample() {
1232            return sample(1, TimeUnit.SECONDS);
1233        }
1234    
1235        /**
1236         * <a href="http://camel.apache.org/sampling.html">Sampling Throttler</a>
1237         * Creates a sampling throttler allowing you to extract a sample of exchanges
1238         * from the traffic through a route. It is configured with a sampling period
1239         * during which only a single exchange is allowed to pass through.
1240         * All other exchanges will be stopped.
1241         *
1242         * @param samplePeriod this is the sample interval, only one exchange is
1243         *            allowed through in this interval
1244         * @param unit this is the units for the samplePeriod e.g. Seconds
1245         * @return the builder
1246         */
1247        public SamplingDefinition sample(long samplePeriod, TimeUnit unit) {
1248            SamplingDefinition answer = new SamplingDefinition(samplePeriod, unit);
1249            addOutput(answer);
1250            return answer;
1251        }
1252    
1253        /**
1254         * <a href="http://camel.apache.org/splitter.html">Splitter EIP:</a>
1255         * Creates a splitter allowing you split a message into a number of pieces and process them individually.
1256         * <p>
1257         * This splitter responds with the latest message returned from destination
1258         * endpoint.
1259         *
1260         * @return the expression clause builder for the expression on which to split
1261         */
1262        public ExpressionClause<SplitDefinition> split() {
1263            SplitDefinition answer = new SplitDefinition();
1264            addOutput(answer);
1265            return ExpressionClause.createAndSetExpression(answer);
1266        }
1267    
1268        /**
1269         * <a href="http://camel.apache.org/splitter.html">Splitter EIP:</a>
1270         * Creates a splitter allowing you split a message into a number of pieces and process them individually.
1271         * <p>
1272         * This splitter responds with the latest message returned from destination
1273         * endpoint.
1274         *
1275         * @param expression  the expression on which to split the message
1276         * @return the builder
1277         */
1278        public SplitDefinition split(Expression expression) {
1279            SplitDefinition answer = new SplitDefinition(expression);
1280            addOutput(answer);
1281            return answer;
1282        }
1283    
1284        /**
1285         * <a href="http://camel.apache.org/splitter.html">Splitter EIP:</a>
1286         * Creates a splitter allowing you split a message into a number of pieces and process them individually.
1287         * <p>
1288         * The splitter responds with the answer produced by the given {@link AggregationStrategy}.
1289         *
1290         * @param expression  the expression on which to split
1291         * @param aggregationStrategy  the strategy used to aggregate responses for every part
1292         * @return the builder
1293         */
1294        public SplitDefinition split(Expression expression, AggregationStrategy aggregationStrategy) {
1295            SplitDefinition answer = new SplitDefinition(expression);
1296            addOutput(answer);
1297            answer.setAggregationStrategy(aggregationStrategy);
1298            return answer;
1299        }
1300    
1301        /**
1302         * <a href="http://camel.apache.org/resequencer.html">Resequencer EIP:</a>
1303         * Creates a resequencer allowing you to reorganize messages based on some comparator.
1304         *
1305         * @return the expression clause for the expressions on which to compare messages in order
1306         */
1307        public ExpressionClause<ResequenceDefinition> resequence() {
1308            ResequenceDefinition answer = new ResequenceDefinition();
1309            addOutput(answer);
1310            ExpressionClause<ResequenceDefinition> clause = new ExpressionClause<ResequenceDefinition>(answer);
1311            answer.expression(clause);
1312            return clause;
1313        }
1314    
1315        /**
1316         * <a href="http://camel.apache.org/resequencer.html">Resequencer EIP:</a>
1317         * Creates a resequencer allowing you to reorganize messages based on some comparator.
1318         *
1319         * @param expression the expression on which to compare messages in order
1320         * @return the builder
1321         */
1322        public ResequenceDefinition resequence(Expression expression) {
1323            return resequence(Collections.<Expression>singletonList(expression));
1324        }
1325    
1326        /**
1327         * <a href="http://camel.apache.org/resequencer.html">Resequencer EIP:</a>
1328         * Creates a resequencer allowing you to reorganize messages based on some comparator.
1329         *
1330         * @param expressions the list of expressions on which to compare messages in order
1331         * @return the builder
1332         */
1333        public ResequenceDefinition resequence(List<Expression> expressions) {
1334            ResequenceDefinition answer = new ResequenceDefinition(expressions);
1335            addOutput(answer);
1336            return answer;
1337        }
1338    
1339        /**
1340         * <a href="http://camel.apache.org/resequencer.html">Resequencer EIP:</a>
1341         * Creates a splitter allowing you to reorganise messages based on some comparator.
1342         *
1343         * @param expressions the list of expressions on which to compare messages in order
1344         * @return the builder
1345         */
1346        public ResequenceDefinition resequencer(Expression... expressions) {
1347            List<Expression> list = new ArrayList<Expression>();
1348            list.addAll(Arrays.asList(expressions));
1349            return resequence(list);
1350        }
1351    
1352        /**
1353         * <a href="http://camel.apache.org/aggregator.html">Aggregator EIP:</a>
1354         * Creates an aggregator allowing you to combine a number of messages together into a single message.
1355         *
1356         * @return the expression clause to be used as builder to configure the correlation expression
1357         */
1358        public ExpressionClause<AggregateDefinition> aggregate() {
1359            AggregateDefinition answer = new AggregateDefinition();
1360            addOutput(answer);
1361            return answer.createAndSetExpression();
1362        }
1363    
1364        /**
1365         * <a href="http://camel.apache.org/aggregator.html">Aggregator EIP:</a>
1366         * Creates an aggregator allowing you to combine a number of messages together into a single message.
1367         *
1368         * @param aggregationStrategy the strategy used for the aggregation
1369         * @return the expression clause to be used as builder to configure the correlation expression
1370         */
1371        public ExpressionClause<AggregateDefinition> aggregate(AggregationStrategy aggregationStrategy) {
1372            AggregateDefinition answer = new AggregateDefinition();
1373            answer.setAggregationStrategy(aggregationStrategy);
1374            addOutput(answer);
1375            return answer.createAndSetExpression();
1376        }
1377    
1378        /**
1379         * <a href="http://camel.apache.org/aggregator.html">Aggregator EIP:</a>
1380         * Creates an aggregator allowing you to combine a number of messages together into a single message.
1381         *
1382         * @param aggregationCollection the collection used to perform the aggregation
1383         * @return the builder
1384         */
1385        public AggregateDefinition aggregate(AggregationCollection aggregationCollection) {
1386            AggregateDefinition answer = new AggregateDefinition();
1387            answer.setAggregationCollection(aggregationCollection);
1388            addOutput(answer);
1389            return answer;
1390        }
1391    
1392        /**
1393         * <a href="http://camel.apache.org/aggregator.html">Aggregator EIP:</a>
1394         * Creates an aggregator allowing you to combine a number of messages together into a single message.
1395         *
1396         * @param correlationExpression the expression used to calculate the
1397         *                              correlation key. For a JMS message this could be the
1398         *                              expression <code>header("JMSDestination")</code> or
1399         *                              <code>header("JMSCorrelationID")</code>
1400         * @return the builder
1401         */
1402        public AggregateDefinition aggregate(Expression correlationExpression) {
1403            AggregateDefinition answer = new AggregateDefinition(correlationExpression);
1404            addOutput(answer);
1405            return answer;
1406        }
1407    
1408        /**
1409         * <a href="http://camel.apache.org/aggregator.html">Aggregator EIP:</a>
1410         * Creates an aggregator allowing you to combine a number of messages together into a single message.
1411         *
1412         * @param correlationExpression the expression used to calculate the
1413         *                              correlation key. For a JMS message this could be the
1414         *                              expression <code>header("JMSDestination")</code> or
1415         *                              <code>header("JMSCorrelationID")</code>
1416         * @param aggregationStrategy the strategy used for the aggregation
1417         * @return the builder
1418         */
1419        public AggregateDefinition aggregate(Expression correlationExpression, AggregationStrategy aggregationStrategy) {
1420            AggregateDefinition answer = new AggregateDefinition(correlationExpression, aggregationStrategy);
1421            addOutput(answer);
1422            return answer;
1423        }
1424    
1425        /**
1426         * <a href="http://camel.apache.org/delayer.html">Delayer EIP:</a>
1427         * Creates a delayer allowing you to delay the delivery of messages to some destination.
1428         *
1429         * @param delay  an expression to calculate the delay time in millis
1430         * @return the builder
1431         */
1432        public DelayDefinition delay(Expression delay) {
1433            DelayDefinition answer = new DelayDefinition(delay);
1434            addOutput(answer);
1435            return answer;
1436        }
1437    
1438        /**
1439         * <a href="http://camel.apache.org/delayer.html">Delayer EIP:</a>
1440         * Creates a delayer allowing you to delay the delivery of messages to some destination.
1441         *
1442         * @return the expression clause to create the expression
1443         */
1444        public ExpressionClause<DelayDefinition> delay() {
1445            DelayDefinition answer = new DelayDefinition();
1446            addOutput(answer);
1447            return ExpressionClause.createAndSetExpression(answer);
1448        }
1449    
1450        /**
1451         * <a href="http://camel.apache.org/delayer.html">Delayer EIP:</a>
1452         * Creates a delayer allowing you to delay the delivery of messages to some destination.
1453         *
1454         * @param delay  the delay in millis
1455         * @return the builder
1456         */
1457        public DelayDefinition delay(long delay) {
1458            return delay(ExpressionBuilder.constantExpression(delay));
1459        }
1460    
1461        /**
1462         * <a href="http://camel.apache.org/throttler.html">Throttler EIP:</a>
1463         * Creates a throttler allowing you to ensure that a specific endpoint does not get overloaded,
1464         * or that we don't exceed an agreed SLA with some external service.
1465         * <p/>
1466         * Will default use a time period of 1 second, so setting the maximumRequestCount to eg 10
1467         * will default ensure at most 10 messages per second. 
1468         *
1469         * @param maximumRequestCount  the maximum messages 
1470         * @return the builder
1471         */
1472        public ThrottleDefinition throttle(long maximumRequestCount) {
1473            ThrottleDefinition answer = new ThrottleDefinition(maximumRequestCount);
1474            addOutput(answer);
1475            return answer;
1476        }
1477    
1478        /**
1479         * <a href="http://camel.apache.org/loop.html">Loop EIP:</a>
1480         * Creates a loop allowing to process the a message a number of times and possibly process them
1481         * in a different way. Useful mostly for testing.
1482         *
1483         * @return the clause used to create the loop expression
1484         */
1485        public ExpressionClause<LoopDefinition> loop() {
1486            LoopDefinition loop = new LoopDefinition();
1487            addOutput(loop);
1488            return ExpressionClause.createAndSetExpression(loop);
1489        }
1490    
1491        /**
1492         * <a href="http://camel.apache.org/loop.html">Loop EIP:</a>
1493         * Creates a loop allowing to process the a message a number of times and possibly process them
1494         * in a different way. Useful mostly for testing.
1495         *
1496         * @param expression the loop expression
1497         * @return the builder
1498         */
1499        public LoopDefinition loop(Expression expression) {
1500            LoopDefinition loop = getNodeFactory().createLoop();
1501            loop.setExpression(expression);
1502            addOutput(loop);
1503            return loop;
1504        }
1505    
1506        /**
1507         * <a href="http://camel.apache.org/loop.html">Loop EIP:</a>
1508         * Creates a loop allowing to process the a message a number of times and possibly process them
1509         * in a different way. Useful mostly for testing.
1510         *
1511         * @param count  the number of times
1512         * @return the builder
1513         */
1514        public LoopDefinition loop(int count) {
1515            LoopDefinition loop = getNodeFactory().createLoop();
1516            loop.setExpression(new ConstantExpression(Integer.toString(count)));
1517            addOutput(loop);
1518            return loop;
1519        }
1520    
1521        /**
1522         * Sets the exception on the {@link org.apache.camel.Exchange}
1523         *
1524         * @param exception the exception to throw
1525         * @return the builder
1526         */
1527        @SuppressWarnings("unchecked")
1528        public Type throwException(Exception exception) {
1529            ThrowExceptionDefinition answer = new ThrowExceptionDefinition();
1530            answer.setException(exception);
1531            addOutput(answer);
1532            return (Type) this;
1533        }
1534    
1535        /**
1536         * Marks the exchange for rollback only.
1537         * <p/>
1538         * Does <b>not</b> set any exception as opposed to {@link #rollback()} methods.
1539         *
1540         * @return the builder
1541         * @see #rollback()
1542         * @see #rollback(String)
1543         * @see #markRollbackOnlyLast()
1544         */
1545        @SuppressWarnings("unchecked")
1546        public Type markRollbackOnly() {
1547            RollbackDefinition answer = new RollbackDefinition();
1548            answer.setMarkRollbackOnly(true);
1549            addOutput(answer);
1550            return (Type) this;
1551        }
1552    
1553        /**
1554         * Marks the exchange for rollback only, but only for the last (current) transaction.
1555         * <p/>
1556         * A last rollback is used when you have nested transactions and only want the last local transaction to rollback,
1557         * where as the outer transaction can still be completed
1558         * <p/>
1559         * Does <b>not</b> set any exception as opposed to {@link #rollback()} methods.
1560         *
1561         * @return the builder
1562         * @see #rollback()
1563         * @see #rollback(String)
1564         * @see #markRollbackOnly()
1565         */
1566        @SuppressWarnings("unchecked")
1567        public Type markRollbackOnlyLast() {
1568            RollbackDefinition answer = new RollbackDefinition();
1569            answer.setMarkRollbackOnlyLast(true);
1570            addOutput(answer);
1571            return (Type) this;
1572        }
1573    
1574        /**
1575         * Marks the exchange for rollback only and sets an exception with a default message.
1576         * <p/>
1577         * This is done by setting a {@link org.apache.camel.RollbackExchangeException} on the Exchange
1578         * and mark it for rollback.
1579         *
1580         * @return the builder
1581         * @see #markRollbackOnly()
1582         */
1583        @SuppressWarnings("unchecked")
1584        public Type rollback() {
1585            return rollback(null);
1586        }
1587    
1588        /**
1589         * Marks the exchange for rollback and sets an exception with the provided message.
1590         * <p/>
1591         * This is done by setting a {@link org.apache.camel.RollbackExchangeException} on the Exchange
1592         * and mark it for rollback.
1593         *
1594         * @param message an optional message used for logging purpose why the rollback was triggered
1595         * @return the builder
1596         * @see #markRollbackOnly()
1597         */
1598        @SuppressWarnings("unchecked")
1599        public Type rollback(String message) {
1600            RollbackDefinition answer = new RollbackDefinition(message);
1601            addOutput(answer);
1602            return (Type) this;
1603        }
1604    
1605        /**
1606         * <a href="http://camel.apache.org/wiretap.html">WireTap EIP:</a>
1607         * Sends messages to all its child outputs; so that each processor and
1608         * destination gets a copy of the original message to avoid the processors
1609         * interfering with each other using {@link ExchangePattern#InOnly}.
1610         *
1611         * @return the builder
1612         */
1613        @SuppressWarnings("unchecked")
1614        public Type wireTap(String uri) {
1615            WireTapDefinition answer = new WireTapDefinition();
1616            answer.setUri(uri);
1617            addOutput(answer);
1618            return (Type) this;
1619        }
1620    
1621        /**
1622         * <a href="http://camel.apache.org/wiretap.html">WireTap EIP:</a>
1623         * Sends a new {@link org.apache.camel.Exchange} to the destination
1624         * using {@link ExchangePattern#InOnly}.
1625         *
1626         * @param uri  the destination
1627         * @param body expression that creates the body to send
1628         * @return the builder
1629         */
1630        @SuppressWarnings("unchecked")
1631        public Type wireTap(String uri, Expression body) {
1632            WireTapDefinition answer = new WireTapDefinition();
1633            answer.setUri(uri);
1634            answer.setNewExchangeExpression(body);
1635            addOutput(answer);
1636            return (Type) this;
1637        }
1638    
1639        /**
1640         * <a href="http://camel.apache.org/wiretap.html">WireTap EIP:</a>
1641         * Sends a new {@link org.apache.camel.Exchange} to the destination
1642         * using {@link ExchangePattern#InOnly}.
1643         *
1644         * @param uri  the destination
1645         * @param processor  processor preparing the new exchange to send
1646         * @return the builder
1647         */
1648        @SuppressWarnings("unchecked")
1649        public Type wireTap(String uri, Processor processor) {
1650            WireTapDefinition answer = new WireTapDefinition();
1651            answer.setUri(uri);
1652            answer.setNewExchangeProcessor(processor);
1653            addOutput(answer);
1654            return (Type) this;
1655        }
1656    
1657        /**
1658         * Pushes the given block on the stack as current block
1659         * @param block  the block
1660         */
1661        void pushBlock(Block block) {
1662            blocks.add(block);
1663        }
1664    
1665        /**
1666         * Pops the block off the stack as current block
1667         * @return the block
1668         */
1669        Block popBlock() {
1670            return blocks.isEmpty() ? null : blocks.removeLast();
1671        }
1672    
1673        /**
1674         * Stops continue routing the current {@link org.apache.camel.Exchange} and marks it as completed.
1675         *
1676         * @return the builder
1677         */
1678        @SuppressWarnings("unchecked")
1679        public Type stop() {
1680            StopDefinition stop = new StopDefinition();
1681            addOutput(stop);
1682            return (Type) this;
1683        }
1684    
1685        /**
1686         * <a href="http://camel.apache.org/exception-clause.html">Exception clause</a>
1687         * for cathing certain exceptions and handling them.
1688         *
1689         * @param exceptionType  the exception to catch
1690         * @return the exception builder to configure
1691         */
1692        public OnExceptionDefinition onException(Class exceptionType) {
1693            OnExceptionDefinition answer = new OnExceptionDefinition(exceptionType);
1694            addOutput(answer);
1695            return answer;
1696        }
1697    
1698        /**
1699         * Apply a {@link Policy}.
1700         * <p/>
1701         * Policy can be used for transactional policies.
1702         *
1703         * @param policy  the policy to apply
1704         * @return the policy builder to configure
1705         */
1706        public PolicyDefinition policy(Policy policy) {
1707            PolicyDefinition answer = new PolicyDefinition(policy);
1708            addOutput(answer);
1709            return answer;
1710        }
1711    
1712        /**
1713         * Apply a {@link Policy}.
1714         * <p/>
1715         * Policy can be used for transactional policies.
1716         *
1717         * @param ref  reference to lookup a policy in the registry
1718         * @return the policy builder to configure
1719         */
1720        public PolicyDefinition policy(String ref) {
1721            PolicyDefinition answer = new PolicyDefinition();
1722            answer.setRef(ref);
1723            addOutput(answer);
1724            return answer;
1725        }
1726    
1727        /**
1728         * Marks this route as transacted and uses the default transacted policy found in the registry.
1729         *
1730         * @return the policy builder to configure
1731         */
1732        public PolicyDefinition transacted() {
1733            PolicyDefinition answer = new PolicyDefinition();
1734            answer.setType(TransactedPolicy.class);
1735            addOutput(answer);
1736            return answer;
1737        }
1738    
1739        /**
1740         * Marks this route as transacted.
1741         *
1742         * @param ref  reference to lookup a transacted policy in the registry
1743         * @return the policy builder to configure
1744         */
1745        public PolicyDefinition transacted(String ref) {
1746            PolicyDefinition answer = new PolicyDefinition();
1747            answer.setType(TransactedPolicy.class);
1748            answer.setRef(ref);
1749            addOutput(answer);
1750            return answer;
1751        }
1752    
1753        // Transformers
1754        // -------------------------------------------------------------------------
1755    
1756        /**
1757         * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
1758         * Adds the custom processor to this destination which could be a final
1759         * destination, or could be a transformation in a pipeline
1760         *
1761         * @param processor  the custom {@link Processor}
1762         * @return the builder
1763         */
1764        @SuppressWarnings("unchecked")
1765        public Type process(Processor processor) {
1766            ProcessDefinition answer = new ProcessDefinition(processor);
1767            addOutput(answer);
1768            return (Type) this;
1769        }
1770    
1771        /**
1772         * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
1773         * Adds the custom processor reference to this destination which could be a final
1774         * destination, or could be a transformation in a pipeline
1775         *
1776         * @param ref   reference to a {@link Processor} to lookup in the registry
1777         * @return the builder
1778         */
1779        @SuppressWarnings("unchecked")
1780        public Type processRef(String ref) {
1781            ProcessDefinition answer = new ProcessDefinition();
1782            answer.setRef(ref);
1783            addOutput(answer);
1784            return (Type) this;
1785        }
1786    
1787        /**
1788         * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
1789         * Adds a bean which is invoked which could be a final destination, or could be a transformation in a pipeline
1790         *
1791         * @param bean  the bean to invoke
1792         * @return the builder
1793         */
1794        @SuppressWarnings("unchecked")
1795        public Type bean(Object bean) {
1796            BeanDefinition answer = new BeanDefinition();
1797            answer.setBean(bean);
1798            addOutput(answer);
1799            return (Type) this;
1800        }
1801    
1802        /**
1803         * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
1804         * Adds a bean which is invoked which could be a final destination, or could be a transformation in a pipeline
1805         *
1806         * @param bean  the bean to invoke
1807         * @param method  the method name to invoke on the bean (can be used to avoid ambiguty)
1808         * @return the builder
1809         */
1810        @SuppressWarnings("unchecked")
1811        public Type bean(Object bean, String method) {
1812            BeanDefinition answer = new BeanDefinition();
1813            answer.setBean(bean);
1814            answer.setMethod(method);
1815            addOutput(answer);
1816            return (Type) this;
1817        }
1818    
1819        /**
1820         * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
1821         * Adds a bean which is invoked which could be a final destination, or could be a transformation in a pipeline
1822         *
1823         * @param  beanType  the bean class, Camel will instantiate an object at runtime
1824         * @return the builder
1825         */
1826        @SuppressWarnings("unchecked")
1827        public Type bean(Class beanType) {
1828            BeanDefinition answer = new BeanDefinition();
1829            answer.setBeanType(beanType);
1830            addOutput(answer);
1831            return (Type) this;
1832        }
1833    
1834        /**
1835         * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
1836         * Adds a bean which is invoked which could be a final destination, or could be a transformation in a pipeline
1837         *
1838         * @param  beanType  the bean class, Camel will instantiate an object at runtime
1839         * @param method  the method name to invoke on the bean (can be used to avoid ambiguty)
1840         * @return the builder
1841         */
1842        @SuppressWarnings("unchecked")
1843        public Type bean(Class beanType, String method) {
1844            BeanDefinition answer = new BeanDefinition();
1845            answer.setBeanType(beanType);
1846            answer.setMethod(method);
1847            addOutput(answer);
1848            return (Type) this;
1849        }
1850    
1851        /**
1852         * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
1853         * Adds a bean which is invoked which could be a final destination, or could be a transformation in a pipeline
1854         *
1855         * @param ref  reference to a bean to lookup in the registry
1856         * @return the builder
1857         */
1858        @SuppressWarnings("unchecked")
1859        public Type beanRef(String ref) {
1860            BeanDefinition answer = new BeanDefinition(ref);
1861            addOutput(answer);
1862            return (Type) this;
1863        }
1864    
1865        /**
1866         * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
1867         * Adds a bean which is invoked which could be a final destination, or could be a transformation in a pipeline
1868         *
1869         * @param ref  reference to a bean to lookup in the registry
1870         * @param method  the method name to invoke on the bean (can be used to avoid ambiguty)
1871         * @return the builder
1872         */
1873        @SuppressWarnings("unchecked")
1874        public Type beanRef(String ref, String method) {
1875            BeanDefinition answer = new BeanDefinition(ref, method);
1876            addOutput(answer);
1877            return (Type) this;
1878        }
1879    
1880        /**
1881         * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
1882         * Adds a processor which sets the body on the IN message
1883         *
1884         * @return a expression builder clause to set the body
1885         */
1886        public ExpressionClause<ProcessorDefinition<Type>> setBody() {
1887            ExpressionClause<ProcessorDefinition<Type>> clause = new ExpressionClause<ProcessorDefinition<Type>>(this);
1888            SetBodyDefinition answer = new SetBodyDefinition(clause);
1889            addOutput(answer);
1890            return clause;
1891        }
1892    
1893        /**
1894         * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
1895         * Adds a processor which sets the body on the IN message
1896         *
1897         * @param expression   the expression used to set the body
1898         * @return the builder
1899         */
1900        @SuppressWarnings("unchecked")
1901        public Type setBody(Expression expression) {
1902            SetBodyDefinition answer = new SetBodyDefinition(expression);
1903            addOutput(answer);
1904            return (Type) this;
1905        }
1906    
1907        /**
1908         * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
1909         * Adds a processor which sets the body on the OUT message
1910         *
1911         * @param expression   the expression used to set the body
1912         * @return the builder
1913         */
1914        @SuppressWarnings("unchecked")
1915        public Type transform(Expression expression) {
1916            TransformDefinition answer = new TransformDefinition(expression);
1917            addOutput(answer);
1918            return (Type) this;
1919        }
1920    
1921        /**
1922         * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
1923         * Adds a processor which sets the body on the OUT message
1924         *
1925         * @return a expression builder clause to set the body
1926         */
1927        public ExpressionClause<ProcessorDefinition<Type>> transform() {
1928            ExpressionClause<ProcessorDefinition<Type>> clause = 
1929                new ExpressionClause<ProcessorDefinition<Type>>((ProcessorDefinition<Type>) this);
1930            TransformDefinition answer = new TransformDefinition(clause);
1931            addOutput(answer);
1932            return clause;
1933        }
1934    
1935        /**
1936         * Adds a processor which sets the body on the FAULT message
1937         *
1938         * @param expression   the expression used to set the body
1939         * @return the builder
1940         */
1941        public Type setFaultBody(Expression expression) {
1942            return process(ProcessorBuilder.setFaultBody(expression));
1943        }
1944    
1945        /**
1946         * Adds a processor which sets the header on the IN message
1947         *
1948         * @param name  the header name
1949         * @return a expression builder clause to set the header
1950         */
1951        public ExpressionClause<ProcessorDefinition<Type>> setHeader(String name) {
1952            ExpressionClause<ProcessorDefinition<Type>> clause = new ExpressionClause<ProcessorDefinition<Type>>(this);
1953            SetHeaderDefinition answer = new SetHeaderDefinition(name, clause);
1954            addOutput(answer);
1955            return clause;
1956        }
1957    
1958        /**
1959         * Adds a processor which sets the header on the IN message
1960         *
1961         * @param name  the header name
1962         * @param expression  the expression used to set the header
1963         * @return the builder
1964         */
1965        @SuppressWarnings("unchecked")
1966        public Type setHeader(String name, Expression expression) {
1967            SetHeaderDefinition answer = new SetHeaderDefinition(name, expression);
1968            addOutput(answer);
1969            return (Type) this;
1970        }
1971    
1972        /**
1973         * Adds a processor which sets the header on the OUT message
1974         *
1975         * @param name  the header name
1976         * @return a expression builder clause to set the header
1977         */
1978        public ExpressionClause<ProcessorDefinition<Type>> setOutHeader(String name) {
1979            ExpressionClause<ProcessorDefinition<Type>> clause = new ExpressionClause<ProcessorDefinition<Type>>(this);
1980            SetOutHeaderDefinition answer = new SetOutHeaderDefinition(name, clause);
1981            addOutput(answer);
1982            return clause;
1983        }
1984    
1985        /**
1986         * Adds a processor which sets the header on the OUT message
1987         *
1988         * @param name  the header name
1989         * @param expression  the expression used to set the header
1990         * @return the builder
1991         */
1992        @SuppressWarnings("unchecked")
1993        public Type setOutHeader(String name, Expression expression) {
1994            SetOutHeaderDefinition answer = new SetOutHeaderDefinition(name, expression);
1995            addOutput(answer);
1996            return (Type) this;
1997        }
1998    
1999        /**
2000         * Adds a processor which sets the header on the FAULT message
2001         *
2002         * @param name  the header name
2003         * @param expression  the expression used to set the header
2004         * @return the builder
2005         */
2006        public Type setFaultHeader(String name, Expression expression) {
2007            return process(ProcessorBuilder.setFaultHeader(name, expression));
2008        }
2009    
2010        /**
2011         * Adds a processor which sets the exchange property
2012         *
2013         * @param name  the property name
2014         * @param expression  the expression used to set the property
2015         * @return the builder
2016         */
2017        @SuppressWarnings("unchecked")
2018        public Type setProperty(String name, Expression expression) {
2019            SetPropertyDefinition answer = new SetPropertyDefinition(name, expression);
2020            addOutput(answer);
2021            return (Type) this;
2022        }
2023    
2024    
2025        /**
2026         * Adds a processor which sets the exchange property
2027         *
2028         * @param name  the property name
2029         * @return a expression builder clause to set the property
2030         */
2031        public ExpressionClause<ProcessorDefinition<Type>> setProperty(String name) {
2032            ExpressionClause<ProcessorDefinition<Type>> clause = new ExpressionClause<ProcessorDefinition<Type>>(this);
2033            SetPropertyDefinition answer = new SetPropertyDefinition(name, clause);
2034            addOutput(answer);
2035            return clause;
2036        }
2037    
2038        /**
2039         * Adds a processor which removes the header on the IN message
2040         *
2041         * @param name  the header name
2042         * @return the builder
2043         */
2044        @SuppressWarnings("unchecked")
2045        public Type removeHeader(String name) {
2046            RemoveHeaderDefinition answer = new RemoveHeaderDefinition(name);
2047            addOutput(answer);
2048            return (Type) this;
2049        }
2050    
2051        /**
2052         * Adds a processor which removes the header on the FAULT message
2053         *
2054         * @param name  the header name
2055         * @return the builder
2056         */
2057        public Type removeFaultHeader(String name) {
2058            return process(ProcessorBuilder.removeFaultHeader(name));
2059        }
2060    
2061        /**
2062         * Adds a processor which removes the exchange property
2063         *
2064         * @param name  the property name
2065         * @return the builder
2066         */
2067        @SuppressWarnings("unchecked")
2068        public Type removeProperty(String name) {
2069            RemovePropertyDefinition answer = new RemovePropertyDefinition(name);
2070            addOutput(answer);
2071            return (Type) this;
2072        }
2073    
2074        /**
2075         * Converts the IN message body to the specified type
2076         *
2077         * @param type the type to convert to
2078         * @return the builder
2079         */
2080        @SuppressWarnings("unchecked")
2081        public Type convertBodyTo(Class type) {
2082            addOutput(new ConvertBodyDefinition(type));
2083            return (Type) this;
2084        }
2085        
2086        /**
2087         * Converts the IN message body to the specified type
2088         *
2089         * @param type the type to convert to
2090         * @param charset the charset to use by type converters (not all converters support specifc charset)
2091         * @return the builder
2092         */
2093        @SuppressWarnings("unchecked")
2094        public Type convertBodyTo(Class type, String charset) {
2095            addOutput(new ConvertBodyDefinition(type, charset));
2096            return (Type) this;
2097        }
2098    
2099        /**
2100         * Sorts the IN message body using the given comparator.
2101         * The IN body mut be convertable to {@link List}.
2102         *
2103         * @param comparator  the comparator to use for sorting
2104         * @return the builder
2105         */
2106        @SuppressWarnings("unchecked")
2107        public Type sortBody(Comparator comparator) {
2108            addOutput(new SortDefinition(body(), comparator));
2109            return (Type) this;
2110        }
2111    
2112        /**
2113         * Sorts the IN message body using a default sorting based on toString representation.
2114         * The IN body mut be convertable to {@link List}.
2115         *
2116         * @return the builder
2117         */
2118        public Type sortBody() {
2119            return sortBody(null);
2120        }
2121    
2122        /**
2123         * Sorts the expression using the given comparator
2124         *
2125         * @param expression  the expression, must be convertable to {@link List}
2126         * @param comparator  the comparator to use for sorting
2127         * @return the builder
2128         */
2129        @SuppressWarnings("unchecked")
2130        public Type sort(Expression expression, Comparator comparator) {
2131            addOutput(new SortDefinition(expression, comparator));
2132            return (Type) this;
2133        }
2134    
2135        /**
2136         * Sorts the expression using a default sorting based on toString representation. 
2137         *
2138         * @param expression  the expression, must be convertable to {@link List}
2139         * @return the builder
2140         */
2141        public Type sort(Expression expression) {
2142            return sort(expression, null);
2143        }
2144    
2145        /**
2146         * The <a href="http://camel.apache.org/content-enricher.html">Content Enricher EIP</a>
2147         * enriches an exchange with additional data obtained from a <code>resourceUri</code>.
2148         * 
2149         * @param resourceUri           URI of resource endpoint for obtaining additional data.
2150         * @param aggregationStrategy   aggregation strategy to aggregate input data and additional data.
2151         * @return the builder
2152         * @see org.apache.camel.processor.Enricher
2153         */
2154        @SuppressWarnings("unchecked")
2155        public Type enrich(String resourceUri, AggregationStrategy aggregationStrategy) {
2156            addOutput(new EnrichDefinition(aggregationStrategy, resourceUri));
2157            return (Type) this;
2158        }
2159    
2160        /**
2161         * The <a href="http://camel.apache.org/content-enricher.html">Content Enricher EIP</a>
2162         * enriches an exchange with additional data obtained from a <code>resourceUri</code>.
2163         * <p/>
2164         * The difference between this and {@link #pollEnrich(String)} is that this uses a producer
2165         * to obatin the additional data, where as pollEnrich uses a polling consumer.
2166         *
2167         * @param resourceUri           URI of resource endpoint for obtaining additional data.
2168         * @return the builder
2169         * @see org.apache.camel.processor.Enricher
2170         */
2171        @SuppressWarnings("unchecked")
2172        public Type enrich(String resourceUri) {
2173            addOutput(new EnrichDefinition(resourceUri));
2174            return (Type) this;
2175        }
2176    
2177        /**
2178         * The <a href="http://camel.apache.org/content-enricher.html">Content Enricher EIP</a>
2179         * enriches an exchange with additional data obtained from a <code>resourceUri</code>.
2180         * <p/>
2181         * The difference between this and {@link #pollEnrich(String)} is that this uses a producer
2182         * to obatin the additional data, where as pollEnrich uses a polling consumer.
2183         *
2184         * @param resourceRef            Reference of resource endpoint for obtaining additional data.
2185         * @param aggregationStrategyRef Reference of aggregation strategy to aggregate input data and additional data.
2186         * @return the builder
2187         * @see org.apache.camel.processor.Enricher
2188         */
2189        @SuppressWarnings("unchecked")
2190        public Type enrichRef(String resourceRef, String aggregationStrategyRef) {
2191            EnrichDefinition enrich = new EnrichDefinition();
2192            enrich.setResourceRef(resourceRef);
2193            enrich.setAggregationStrategyRef(aggregationStrategyRef);
2194            addOutput(enrich);
2195            return (Type) this;
2196        }
2197    
2198        /**
2199         * The <a href="http://camel.apache.org/content-enricher.html">Content Enricher EIP</a>
2200         * enriches an exchange with additional data obtained from a <code>resourceUri</code>
2201         * using a {@link org.apache.camel.PollingConsumer} to poll the endpoint.
2202         * <p/>
2203         * The difference between this and {@link #enrich(String)} is that this uses a consumer
2204         * to obatin the additional data, where as enrich uses a producer.
2205         * <p/>
2206         * This method will block until data is avialable, use the method with timeout if you do not
2207         * want to risk waiting a long time before data is available from the resourceUri.
2208         *
2209         * @param resourceUri           URI of resource endpoint for obtaining additional data.
2210         * @return the builder
2211         * @see org.apache.camel.processor.PollEnricher
2212         */
2213        @SuppressWarnings("unchecked")
2214        public Type pollEnrich(String resourceUri) {
2215            addOutput(new PollEnrichDefinition(null, resourceUri, 0));
2216            return (Type) this;
2217        }
2218    
2219        /**
2220         * The <a href="http://camel.apache.org/content-enricher.html">Content Enricher EIP</a>
2221         * enriches an exchange with additional data obtained from a <code>resourceUri</code>
2222         * using a {@link org.apache.camel.PollingConsumer} to poll the endpoint.
2223         * <p/>
2224         * The difference between this and {@link #enrich(String)} is that this uses a consumer
2225         * to obatin the additional data, where as enrich uses a producer.
2226         * <p/>
2227         * This method will block until data is avialable, use the method with timeout if you do not
2228         * want to risk waiting a long time before data is available from the resourceUri.
2229         *
2230         * @param resourceUri           URI of resource endpoint for obtaining additional data.
2231         * @param aggregationStrategy   aggregation strategy to aggregate input data and additional data.
2232         * @return the builder
2233         * @see org.apache.camel.processor.PollEnricher
2234         */
2235        @SuppressWarnings("unchecked")
2236        public Type pollEnrich(String resourceUri, AggregationStrategy aggregationStrategy) {
2237            addOutput(new PollEnrichDefinition(aggregationStrategy, resourceUri, 0));
2238            return (Type) this;
2239        }
2240    
2241        /**
2242         * The <a href="http://camel.apache.org/content-enricher.html">Content Enricher EIP</a>
2243         * enriches an exchange with additional data obtained from a <code>resourceUri</code>
2244         * using a {@link org.apache.camel.PollingConsumer} to poll the endpoint.
2245         * <p/>
2246         * The difference between this and {@link #enrich(String)} is that this uses a consumer
2247         * to obatin the additional data, where as enrich uses a producer.
2248         * <p/>
2249         * The timeout controls which operation to use on {@link org.apache.camel.PollingConsumer}.
2250         * If timeout is negative, we use <tt>receive</tt>. If timeout is 0 then we use <tt>receiveNoWait</tt>
2251         * otherwise we use <tt>receive(timeout)</tt>.
2252         *
2253         * @param resourceUri           URI of resource endpoint for obtaining additional data.
2254         * @param timeout               timeout in millis to wait at most for data to be available.
2255         * @param aggregationStrategy   aggregation strategy to aggregate input data and additional data.
2256         * @return the builder
2257         * @see org.apache.camel.processor.PollEnricher
2258         */
2259        @SuppressWarnings("unchecked")
2260        public Type pollEnrich(String resourceUri, long timeout, AggregationStrategy aggregationStrategy) {
2261            addOutput(new PollEnrichDefinition(aggregationStrategy, resourceUri, timeout));
2262            return (Type) this;
2263        }
2264    
2265        /**
2266         * The <a href="http://camel.apache.org/content-enricher.html">Content Enricher EIP</a>
2267         * enriches an exchange with additional data obtained from a <code>resourceUri</code>
2268         * using a {@link org.apache.camel.PollingConsumer} to poll the endpoint.
2269         * <p/>
2270         * The difference between this and {@link #enrich(String)} is that this uses a consumer
2271         * to obatin the additional data, where as enrich uses a producer.
2272         * <p/>
2273         * The timeout controls which operation to use on {@link org.apache.camel.PollingConsumer}.
2274         * If timeout is negative, we use <tt>receive</tt>. If timeout is 0 then we use <tt>receiveNoWait</tt>
2275         * otherwise we use <tt>receive(timeout)</tt>.
2276         *
2277         * @param resourceUri           URI of resource endpoint for obtaining additional data.
2278         * @param timeout               timeout in millis to wait at most for data to be available.
2279         * @return the builder
2280         * @see org.apache.camel.processor.PollEnricher
2281         */
2282        @SuppressWarnings("unchecked")
2283        public Type pollEnrich(String resourceUri, long timeout) {
2284            addOutput(new PollEnrichDefinition(null, resourceUri, timeout));
2285            return (Type) this;
2286        }
2287    
2288        /**
2289         * The <a href="http://camel.apache.org/content-enricher.html">Content Enricher EIP</a>
2290         * enriches an exchange with additional data obtained from a <code>resourceUri</code>
2291         * using a {@link org.apache.camel.PollingConsumer} to poll the endpoint.
2292         * <p/>
2293         * The difference between this and {@link #enrich(String)} is that this uses a consumer
2294         * to obatin the additional data, where as enrich uses a producer.
2295         * <p/>
2296         * The timeout controls which operation to use on {@link org.apache.camel.PollingConsumer}.
2297         * If timeout is negative, we use <tt>receive</tt>. If timeout is 0 then we use <tt>receiveNoWait</tt>
2298         * otherwise we use <tt>receive(timeout)</tt>.
2299         *
2300         * @param resourceRef            Reference of resource endpoint for obtaining additional data.
2301         * @param timeout                timeout in millis to wait at most for data to be available.
2302         * @param aggregationStrategyRef Reference of aggregation strategy to aggregate input data and additional data.
2303         * @return the builder
2304         * @see org.apache.camel.processor.PollEnricher
2305         */
2306        @SuppressWarnings("unchecked")
2307        public Type pollEnrichRef(String resourceRef, long timeout, String aggregationStrategyRef) {
2308            PollEnrichDefinition pollEnrich = new PollEnrichDefinition();
2309            pollEnrich.setResourceRef(resourceRef);
2310            pollEnrich.setTimeout(timeout);
2311            pollEnrich.setAggregationStrategyRef(aggregationStrategyRef);
2312            addOutput(pollEnrich);
2313            return (Type) this;
2314        }
2315    
2316        /**
2317         * Adds a onComplection {@link org.apache.camel.spi.Synchronization} hook that invoke this route as
2318         * a callback when the {@link org.apache.camel.Exchange} has finished being processed.
2319         * The hook invoke callbacks for either onComplete or onFailure.
2320         * <p/>
2321         * Will by default always trigger when the {@link org.apache.camel.Exchange} is complete
2322         * (either with success or failed).
2323         * <br/>
2324         * You can limit the callback to either onComplete or onFailure but invoking the nested
2325         * builder method.
2326         * <p/>
2327         * For onFailure the caused exception is stored as a property on the {@link org.apache.camel.Exchange}
2328         * with the key {@link org.apache.camel.Exchange#EXCEPTION_CAUGHT}.
2329         *
2330         * @return the builder
2331         */
2332        @SuppressWarnings("unchecked")
2333        public OnCompletionDefinition onCompletion() {
2334            OnCompletionDefinition answer = new OnCompletionDefinition();
2335            // we must remove all existing on completion definition (as they are global)
2336            // and thus we are the only one as route scoped should override any global scoped
2337            answer.removeAllOnCompletionDefinition(this);
2338            popBlock();
2339            addOutput(answer);
2340            pushBlock(answer);
2341            return answer;
2342        }
2343    
2344        // DataFormat support
2345        // -------------------------------------------------------------------------
2346    
2347        /**
2348         * <a href="http://camel.apache.org/data-format.html">DataFormat:</a>
2349         * Unmarshals the in body using a {@link DataFormat} expression to define
2350         * the format of the input message and the output will be set on the out message body.
2351         *
2352         * @return the expression to create the {@link DataFormat}
2353         */
2354        public DataFormatClause<ProcessorDefinition<Type>> unmarshal() {
2355            return new DataFormatClause<ProcessorDefinition<Type>>(this, DataFormatClause.Operation.Unmarshal);
2356        }
2357    
2358        /**
2359         * <a href="http://camel.apache.org/data-format.html">DataFormat:</a>
2360         * Unmarshals the in body using the specified {@link DataFormat}
2361         * and sets the output on the out message body.
2362         *
2363         * @param dataFormatType  the dataformat
2364         * @return the builder
2365         */
2366        @SuppressWarnings("unchecked")
2367        public Type unmarshal(DataFormatDefinition dataFormatType) {
2368            addOutput(new UnmarshalDefinition(dataFormatType));
2369            return (Type) this;
2370        }
2371    
2372        /**
2373         * <a href="http://camel.apache.org/data-format.html">DataFormat:</a>
2374         * Unmarshals the in body using the specified {@link DataFormat}
2375         * and sets the output on the out message body.
2376         *
2377         * @param dataFormat  the dataformat
2378         * @return the builder
2379         */
2380        public Type unmarshal(DataFormat dataFormat) {
2381            return unmarshal(new DataFormatDefinition(dataFormat));
2382        }
2383    
2384        /**
2385         * <a href="http://camel.apache.org/data-format.html">DataFormat:</a>
2386         * Unmarshals the in body using the specified {@link DataFormat}
2387         * reference in the {@link org.apache.camel.spi.Registry} and sets
2388         * the output on the out message body.
2389         *
2390         * @param dataTypeRef  reference to a {@link DataFormat} to lookup in the registry
2391         * @return the builder
2392         */
2393        @SuppressWarnings("unchecked")
2394        public Type unmarshal(String dataTypeRef) {
2395            addOutput(new UnmarshalDefinition(dataTypeRef));
2396            return (Type) this;
2397        }
2398    
2399        /**
2400         * <a href="http://camel.apache.org/data-format.html">DataFormat:</a>
2401         * Marshals the in body using a {@link DataFormat} expression to define
2402         * the format of the output which will be added to the out body.
2403         *
2404         * @return the expression to create the {@link DataFormat}
2405         */
2406        public DataFormatClause<ProcessorDefinition<Type>> marshal() {
2407            return new DataFormatClause<ProcessorDefinition<Type>>(this, DataFormatClause.Operation.Marshal);
2408        }
2409    
2410        /**
2411         * <a href="http://camel.apache.org/data-format.html">DataFormat:</a>
2412         * Marshals the in body using the specified {@link DataFormat}
2413         * and sets the output on the out message body.
2414         *
2415         * @param dataFormatType  the dataformat
2416         * @return the builder
2417         */
2418        @SuppressWarnings("unchecked")
2419        public Type marshal(DataFormatDefinition dataFormatType) {
2420            addOutput(new MarshalDefinition(dataFormatType));
2421            return (Type) this;
2422        }
2423    
2424        /**
2425         * <a href="http://camel.apache.org/data-format.html">DataFormat:</a>
2426         * Marshals the in body using the specified {@link DataFormat}
2427         * and sets the output on the out message body.
2428         *
2429         * @param dataFormat  the dataformat
2430         * @return the builder
2431         */
2432        public Type marshal(DataFormat dataFormat) {
2433            return marshal(new DataFormatDefinition(dataFormat));
2434        }
2435    
2436        /**
2437         * <a href="http://camel.apache.org/data-format.html">DataFormat:</a>
2438         * Marshals the in body the specified {@link DataFormat}
2439         * reference in the {@link org.apache.camel.spi.Registry} and sets
2440         * the output on the out message body.
2441         *
2442         * @param dataTypeRef  reference to a {@link DataFormat} to lookup in the registry
2443         * @return the builder
2444         */
2445        @SuppressWarnings("unchecked")
2446        public Type marshal(String dataTypeRef) {
2447            addOutput(new MarshalDefinition(dataTypeRef));
2448            return (Type) this;
2449        }
2450    
2451        // Properties
2452        // -------------------------------------------------------------------------
2453        @XmlTransient
2454        public ProcessorDefinition getParent() {
2455            return parent;
2456        }
2457    
2458        public void setParent(ProcessorDefinition parent) {
2459            this.parent = parent;
2460        }
2461    
2462        @XmlTransient
2463        public ErrorHandlerBuilder getErrorHandlerBuilder() {
2464            if (errorHandlerBuilder == null) {
2465                errorHandlerBuilder = createErrorHandlerBuilder();
2466            }
2467            return errorHandlerBuilder;
2468        }
2469    
2470        /**
2471         * Sets the error handler to use with processors created by this builder
2472         */
2473        public void setErrorHandlerBuilder(ErrorHandlerBuilder errorHandlerBuilder) {
2474            this.errorHandlerBuilder = errorHandlerBuilder;
2475        }
2476    
2477        @XmlTransient
2478        public NodeFactory getNodeFactory() {
2479            if (nodeFactory == null) {
2480                nodeFactory = new NodeFactory();
2481            }
2482            return nodeFactory;
2483        }
2484    
2485        public void setNodeFactory(NodeFactory nodeFactory) {
2486            this.nodeFactory = nodeFactory;
2487        }
2488    
2489        @XmlTransient
2490        public List<InterceptStrategy> getInterceptStrategies() {
2491            return interceptStrategies;
2492        }
2493    
2494        public void addInterceptStrategy(InterceptStrategy strategy) {
2495            this.interceptStrategies.add(strategy);
2496        }
2497    
2498        /**
2499         * Returns a label to describe this node such as the expression if some kind of expression node
2500         */
2501        public String getLabel() {
2502            return "";
2503        }
2504    
2505    }