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