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 */
017package org.apache.camel.model;
018
019import java.util.ArrayList;
020import java.util.Arrays;
021import java.util.Collection;
022import java.util.Comparator;
023import java.util.HashMap;
024import java.util.Iterator;
025import java.util.LinkedList;
026import java.util.List;
027import java.util.Map;
028import java.util.concurrent.ExecutorService;
029import java.util.concurrent.TimeUnit;
030import java.util.concurrent.atomic.AtomicInteger;
031import java.util.function.Function;
032import java.util.function.Supplier;
033import javax.xml.bind.annotation.XmlAccessType;
034import javax.xml.bind.annotation.XmlAccessorType;
035import javax.xml.bind.annotation.XmlAnyAttribute;
036import javax.xml.bind.annotation.XmlAttribute;
037import javax.xml.bind.annotation.XmlTransient;
038import javax.xml.namespace.QName;
039
040import org.apache.camel.Channel;
041import org.apache.camel.Endpoint;
042import org.apache.camel.ErrorHandlerFactory;
043import org.apache.camel.Exchange;
044import org.apache.camel.ExchangePattern;
045import org.apache.camel.Expression;
046import org.apache.camel.LoggingLevel;
047import org.apache.camel.Predicate;
048import org.apache.camel.Processor;
049import org.apache.camel.Route;
050import org.apache.camel.builder.DataFormatClause;
051import org.apache.camel.builder.EnrichClause;
052import org.apache.camel.builder.ExpressionBuilder;
053import org.apache.camel.builder.ExpressionClause;
054import org.apache.camel.builder.ProcessClause;
055import org.apache.camel.builder.ProcessorBuilder;
056import org.apache.camel.model.cloud.ServiceCallDefinition;
057import org.apache.camel.model.language.ConstantExpression;
058import org.apache.camel.model.language.ExpressionDefinition;
059import org.apache.camel.model.language.LanguageExpression;
060import org.apache.camel.model.language.SimpleExpression;
061import org.apache.camel.model.rest.RestDefinition;
062import org.apache.camel.processor.InterceptEndpointProcessor;
063import org.apache.camel.processor.Pipeline;
064import org.apache.camel.processor.aggregate.AggregationStrategy;
065import org.apache.camel.processor.interceptor.DefaultChannel;
066import org.apache.camel.processor.interceptor.Delayer;
067import org.apache.camel.processor.interceptor.HandleFault;
068import org.apache.camel.processor.interceptor.StreamCaching;
069import org.apache.camel.processor.loadbalancer.LoadBalancer;
070import org.apache.camel.spi.AsEndpointUri;
071import org.apache.camel.spi.AsPredicate;
072import org.apache.camel.spi.DataFormat;
073import org.apache.camel.spi.IdAware;
074import org.apache.camel.spi.IdempotentRepository;
075import org.apache.camel.spi.InterceptStrategy;
076import org.apache.camel.spi.LifecycleStrategy;
077import org.apache.camel.spi.Policy;
078import org.apache.camel.spi.RouteContext;
079import org.apache.camel.support.ExpressionAdapter;
080import org.slf4j.Logger;
081import org.slf4j.LoggerFactory;
082
083/**
084 * Base class for processor types that most XML types extend.
085 *
086 * @version 
087 */
088@XmlAccessorType(XmlAccessType.FIELD)
089public abstract class ProcessorDefinition<Type extends ProcessorDefinition<Type>> extends OptionalIdentifiedDefinition<Type> implements Block, OtherAttributesAware {
090    @XmlTransient
091    private static final AtomicInteger COUNTER = new AtomicInteger();
092    @XmlTransient
093    protected final Logger log = LoggerFactory.getLogger(getClass());
094    @XmlAttribute
095    protected Boolean inheritErrorHandler;
096    @XmlTransient
097    private final LinkedList<Block> blocks = new LinkedList<Block>();
098    @XmlTransient
099    private ProcessorDefinition<?> parent;
100    @XmlTransient
101    private final List<InterceptStrategy> interceptStrategies = new ArrayList<InterceptStrategy>();
102    // use xs:any to support optional property placeholders
103    @XmlAnyAttribute
104    private Map<QName, Object> otherAttributes;
105    @XmlTransient
106    private final int index;
107
108    protected ProcessorDefinition() {
109        // every time we create a definition we should inc the COUNTER counter
110        index = COUNTER.getAndIncrement();
111    }
112
113    /**
114     * Gets the unique index number for when this {@link ProcessorDefinition} was created by its constructor.
115     * <p/>
116     * This can be used to know the order in which the definition was created when assembled as a route.
117     *
118     * @return the index number
119     */
120    public int getIndex() {
121        return index;
122    }
123
124    // else to use an optional attribute in JAXB2
125    public abstract List<ProcessorDefinition<?>> getOutputs();
126
127    public abstract boolean isOutputSupported();
128
129    /**
130     * Whether this definition can only be added as top-level directly on the route itself (such as onException,onCompletion,intercept, etc.)
131     * <p/>
132     * If trying to add a top-level only definition to a nested output would fail in the {@link #addOutput(ProcessorDefinition)}
133     * method.
134     */
135    public boolean isTopLevelOnly() {
136        return false;
137    }
138
139    /**
140     * Whether this model is abstract or not.
141     * <p/>
142     * An abstract model is something that is used for configuring cross cutting concerns such as
143     * error handling, transaction policies, interceptors etc.
144     * <p/>
145     * Regular definitions is what is part of the route, such as ToDefinition, WireTapDefinition and the likes.
146     * <p/>
147     * Will by default return <tt>false</tt> to indicate regular definition, so all the abstract definitions
148     * must override this method and return <tt>true</tt> instead.
149     * <p/>
150     * This information is used in camel-spring to let Camel work a bit on the model provided by JAXB from the
151     * Spring XML file. This is needed to handle those cross cutting concerns properly. The Java DSL does not
152     * have this issue as it can work this out directly using the fluent builder methods.
153     *
154     * @return <tt>true</tt> for abstract, otherwise <tt>false</tt> for regular.
155     */
156    public boolean isAbstract() {
157        return false;
158    }
159
160    /**
161     * Whether this definition is wrapping the entire output.
162     * <p/>
163     * When a definition is wrapping the entire output, the check to ensure
164     * that a route definition is empty should be done on the wrapped output.
165     *
166     * @return <tt>true</tt> when wrapping the entire output.
167     */
168    public boolean isWrappingEntireOutput() {
169        return false;
170    }
171
172    /**
173     * Override this in definition class and implement logic to create the processor
174     * based on the definition model.
175     */
176    public Processor createProcessor(RouteContext routeContext) throws Exception {
177        throw new UnsupportedOperationException("Not implemented yet for class: " + getClass().getName());
178    }
179
180    /**
181     * Prefer to use {#link #createChildProcessor}.
182     */
183    public Processor createOutputsProcessor(RouteContext routeContext) throws Exception {
184        Collection<ProcessorDefinition<?>> outputs = getOutputs();
185        return createOutputsProcessor(routeContext, outputs);
186    }
187
188    /**
189     * Creates the child processor (outputs) from the current definition
190     *
191     * @param routeContext   the route context
192     * @param mandatory      whether or not children is mandatory (ie the definition should have outputs)
193     * @return the created children, or <tt>null</tt> if definition had no output
194     * @throws Exception is thrown if error creating the child or if it was mandatory and there was no output defined on definition
195     */
196    public Processor createChildProcessor(RouteContext routeContext, boolean mandatory) throws Exception {
197        Processor children = null;
198        // at first use custom factory
199        if (routeContext.getCamelContext().getProcessorFactory() != null) {
200            children = routeContext.getCamelContext().getProcessorFactory().createChildProcessor(routeContext, this, mandatory);
201        }
202        // fallback to default implementation if factory did not create the child
203        if (children == null) {
204            children = createOutputsProcessor(routeContext);
205        }
206
207        if (children == null && mandatory) {
208            throw new IllegalArgumentException("Definition has no children on " + this);
209        }
210        return children;
211    }
212
213    @Override
214    public void addOutput(ProcessorDefinition<?> output) {
215        if (!blocks.isEmpty()) {
216            // let the Block deal with the output
217            Block block = blocks.getLast();
218            block.addOutput(output);
219            return;
220        }
221
222        // validate that top-level is only added on the route (eg top level)
223        boolean parentIsRoute = RouteDefinition.class.isAssignableFrom(this.getClass());
224        if (output.isTopLevelOnly() && !parentIsRoute) {
225            throw new IllegalArgumentException("The output must be added as top-level on the route. Try moving " + output + " to the top of route.");
226        }
227
228        output.setParent(this);
229        configureChild(output);
230        getOutputs().add(output);
231    }
232
233    public void clearOutput() {
234        getOutputs().clear();
235        blocks.clear();
236    }
237
238    public void addRoutes(RouteContext routeContext, Collection<Route> routes) throws Exception {
239        Processor processor = makeProcessor(routeContext);
240        if (processor == null) {
241            // no processor to add
242            return;
243        }
244
245        if (!routeContext.isRouteAdded()) {
246            boolean endpointInterceptor = false;
247
248            // are we routing to an endpoint interceptor, if so we should not add it as an event driven
249            // processor as we use the producer to trigger the interceptor
250            if (processor instanceof Channel) {
251                Channel channel = (Channel) processor;
252                Processor next = channel.getNextProcessor();
253                if (next instanceof InterceptEndpointProcessor) {
254                    endpointInterceptor = true;
255                }
256            }
257
258            // only add regular processors as event driven
259            if (endpointInterceptor) {
260                log.debug("Endpoint interceptor should not be added as an event driven consumer route: {}", processor);
261            } else {
262                log.trace("Adding event driven processor: {}", processor);
263                routeContext.addEventDrivenProcessor(processor);
264            }
265
266        }
267    }
268
269    /**
270     * Wraps the child processor in whatever necessary interceptors and error handlers
271     */
272    public Processor wrapProcessor(RouteContext routeContext, Processor processor) throws Exception {
273        // dont double wrap
274        if (processor instanceof Channel) {
275            return processor;
276        }
277        return wrapChannel(routeContext, processor, null);
278    }
279
280    protected Processor wrapChannel(RouteContext routeContext, Processor processor, ProcessorDefinition<?> child) throws Exception {
281        return wrapChannel(routeContext, processor, child, isInheritErrorHandler());
282    }
283
284    protected Processor wrapChannel(RouteContext routeContext, Processor processor, ProcessorDefinition<?> child, Boolean inheritErrorHandler) throws Exception {
285        // put a channel in between this and each output to control the route flow logic
286        ModelChannel channel = createChannel(routeContext);
287        channel.setNextProcessor(processor);
288
289        // add interceptor strategies to the channel must be in this order: camel context, route context, local
290        addInterceptStrategies(routeContext, channel, routeContext.getCamelContext().getInterceptStrategies());
291        addInterceptStrategies(routeContext, channel, routeContext.getInterceptStrategies());
292        addInterceptStrategies(routeContext, channel, this.getInterceptStrategies());
293
294        // must do this ugly cast to avoid compiler error on AIX/HP-UX
295        ProcessorDefinition<?> defn = (ProcessorDefinition<?>) this;
296
297        // set the child before init the channel
298        channel.setChildDefinition(child);
299        channel.initChannel(defn, routeContext);
300
301        // set the error handler, must be done after init as we can set the error handler as first in the chain
302        if (defn instanceof TryDefinition || defn instanceof CatchDefinition || defn instanceof FinallyDefinition) {
303            // do not use error handler for try .. catch .. finally blocks as it will handle errors itself
304            log.trace("{} is part of doTry .. doCatch .. doFinally so no error handler is applied", defn);
305        } else if (ProcessorDefinitionHelper.isParentOfType(TryDefinition.class, defn, true)
306                || ProcessorDefinitionHelper.isParentOfType(CatchDefinition.class, defn, true)
307                || ProcessorDefinitionHelper.isParentOfType(FinallyDefinition.class, defn, true)) {
308            // do not use error handler for try .. catch .. finally blocks as it will handle errors itself
309            // by checking that any of our parent(s) is not a try .. catch or finally type
310            log.trace("{} is part of doTry .. doCatch .. doFinally so no error handler is applied", defn);
311        } else if (defn instanceof OnExceptionDefinition || ProcessorDefinitionHelper.isParentOfType(OnExceptionDefinition.class, defn, true)) {
312            log.trace("{} is part of OnException so no error handler is applied", defn);
313            // do not use error handler for onExceptions blocks as it will handle errors itself
314        } else if (defn instanceof HystrixDefinition || ProcessorDefinitionHelper.isParentOfType(HystrixDefinition.class, defn, true)) {
315            log.trace("{} is part of HystrixCircuitBreaker so no error handler is applied", defn);
316            // do not use error handler for hystrixCircuitBreaker blocks as it will handle errors itself
317        } else if (defn instanceof MulticastDefinition) {
318            // do not use error handler for multicast as it offers fine grained error handlers for its outputs
319            // however if share unit of work is enabled, we need to wrap an error handler on the multicast parent
320            MulticastDefinition def = (MulticastDefinition) defn;
321            boolean isShareUnitOfWork = def.getShareUnitOfWork() != null && def.getShareUnitOfWork();
322            if (isShareUnitOfWork && child == null) {
323                // only wrap the parent (not the children of the multicast)
324                wrapChannelInErrorHandler(channel, routeContext, inheritErrorHandler);
325            } else {
326                log.trace("{} is part of multicast which have special error handling so no error handler is applied", defn);
327            }
328        } else {
329            // use error handler by default or if configured to do so
330            wrapChannelInErrorHandler(channel, routeContext, inheritErrorHandler);
331        }
332
333        // do post init at the end
334        channel.postInitChannel(defn, routeContext);
335        log.trace("{} wrapped in Channel: {}", defn, channel);
336
337        return channel;
338    }
339
340    /**
341     * Wraps the given channel in error handler (if error handler is inherited)
342     *
343     * @param channel             the channel
344     * @param routeContext        the route context
345     * @param inheritErrorHandler whether to inherit error handler
346     * @throws Exception can be thrown if failed to create error handler builder
347     */
348    private void wrapChannelInErrorHandler(Channel channel, RouteContext routeContext, Boolean inheritErrorHandler) throws Exception {
349        if (inheritErrorHandler == null || inheritErrorHandler) {
350            log.trace("{} is configured to inheritErrorHandler", this);
351            Processor output = channel.getOutput();
352            Processor errorHandler = wrapInErrorHandler(routeContext, output);
353            // set error handler on channel
354            channel.setErrorHandler(errorHandler);
355        } else {
356            log.debug("{} is configured to not inheritErrorHandler.", this);
357        }
358    }
359
360    /**
361     * Wraps the given output in an error handler
362     *
363     * @param routeContext the route context
364     * @param output the output
365     * @return the output wrapped with the error handler
366     * @throws Exception can be thrown if failed to create error handler builder
367     */
368    protected Processor wrapInErrorHandler(RouteContext routeContext, Processor output) throws Exception {
369        ErrorHandlerFactory builder = routeContext.getRoute().getErrorHandlerBuilder();
370        // create error handler
371        Processor errorHandler = builder.createErrorHandler(routeContext, output);
372
373        // invoke lifecycles so we can manage this error handler builder
374        for (LifecycleStrategy strategy : routeContext.getCamelContext().getLifecycleStrategies()) {
375            strategy.onErrorHandlerAdd(routeContext, errorHandler, builder);
376        }
377
378        return errorHandler;
379    }
380
381    /**
382     * Adds the given list of interceptors to the channel.
383     *
384     * @param routeContext  the route context
385     * @param channel       the channel to add strategies
386     * @param strategies    list of strategies to add.
387     */
388    protected void addInterceptStrategies(RouteContext routeContext, Channel channel, List<InterceptStrategy> strategies) {
389        for (InterceptStrategy strategy : strategies) {
390            if (!routeContext.isStreamCaching() && strategy instanceof StreamCaching) {
391                // stream cache is disabled so we should not add it
392                continue;
393            }
394            if (!routeContext.isHandleFault() && strategy instanceof HandleFault) {
395                // handle fault is disabled so we should not add it
396                continue;
397            }
398            if (strategy instanceof Delayer) {
399                if (routeContext.getDelayer() == null || routeContext.getDelayer() <= 0) {
400                    // delayer is disabled so we should not add it
401                    continue;
402                } else {
403                    // replace existing delayer as delayer have individual configuration
404                    Iterator<InterceptStrategy> it = channel.getInterceptStrategies().iterator();
405                    while (it.hasNext()) {
406                        InterceptStrategy existing = it.next();
407                        if (existing instanceof Delayer) {
408                            it.remove();
409                        }
410                    }
411                    // add the new correct delayer
412                    channel.addInterceptStrategy(strategy);
413                    continue;
414                }
415            }
416
417            // add strategy
418            channel.addInterceptStrategy(strategy);
419        }
420    }
421
422    /**
423     * Creates a new instance of some kind of composite processor which defaults
424     * to using a {@link Pipeline} but derived classes could change the behaviour
425     */
426    protected Processor createCompositeProcessor(RouteContext routeContext, List<Processor> list) throws Exception {
427        return Pipeline.newInstance(routeContext.getCamelContext(), list);
428    }
429
430    /**
431     * Creates a new instance of the {@link Channel}.
432     */
433    protected ModelChannel createChannel(RouteContext routeContext) throws Exception {
434        return new DefaultChannel();
435    }
436
437    protected Processor createOutputsProcessor(RouteContext routeContext, Collection<ProcessorDefinition<?>> outputs) throws Exception {
438        // We will save list of actions to restore the outputs back to the original state.
439        Runnable propertyPlaceholdersChangeReverter = ProcessorDefinitionHelper.createPropertyPlaceholdersChangeReverter();
440        try {
441            return createOutputsProcessorImpl(routeContext, outputs);
442        } finally {
443            propertyPlaceholdersChangeReverter.run();
444        }
445    }
446
447    protected Processor createOutputsProcessorImpl(RouteContext routeContext, Collection<ProcessorDefinition<?>> outputs) throws Exception {
448        List<Processor> list = new ArrayList<Processor>();
449        for (ProcessorDefinition<?> output : outputs) {
450
451            // allow any custom logic before we create the processor
452            output.preCreateProcessor();
453
454            // resolve properties before we create the processor
455            ProcessorDefinitionHelper.resolvePropertyPlaceholders(routeContext.getCamelContext(), output);
456
457            // resolve constant fields (eg Exchange.FILE_NAME)
458            ProcessorDefinitionHelper.resolveKnownConstantFields(output);
459
460            // also resolve properties and constant fields on embedded expressions
461            ProcessorDefinition<?> me = (ProcessorDefinition<?>) output;
462            if (me instanceof ExpressionNode) {
463                ExpressionNode exp = (ExpressionNode) me;
464                ExpressionDefinition expressionDefinition = exp.getExpression();
465                if (expressionDefinition != null) {
466                    // resolve properties before we create the processor
467                    ProcessorDefinitionHelper.resolvePropertyPlaceholders(routeContext.getCamelContext(), expressionDefinition);
468
469                    // resolve constant fields (eg Exchange.FILE_NAME)
470                    ProcessorDefinitionHelper.resolveKnownConstantFields(expressionDefinition);
471                }
472            }
473
474            Processor processor = createProcessor(routeContext, output);
475
476            // inject id
477            if (processor instanceof IdAware) {
478                String id = output.idOrCreate(routeContext.getCamelContext().getNodeIdFactory());
479                ((IdAware) processor).setId(id);
480            }
481
482            if (output instanceof Channel && processor == null) {
483                continue;
484            }
485
486            Processor channel = wrapChannel(routeContext, processor, output);
487            list.add(channel);
488        }
489
490        // if more than one output wrap than in a composite processor else just keep it as is
491        Processor processor = null;
492        if (!list.isEmpty()) {
493            if (list.size() == 1) {
494                processor = list.get(0);
495            } else {
496                processor = createCompositeProcessor(routeContext, list);
497            }
498        }
499
500        return processor;
501    }
502
503    protected Processor createProcessor(RouteContext routeContext, ProcessorDefinition<?> output) throws Exception {
504        Processor processor = null;
505        // at first use custom factory
506        if (routeContext.getCamelContext().getProcessorFactory() != null) {
507            processor = routeContext.getCamelContext().getProcessorFactory().createProcessor(routeContext, output);
508        }
509        // fallback to default implementation if factory did not create the processor
510        if (processor == null) {
511            processor = output.createProcessor(routeContext);
512        }
513        return processor;
514    }
515
516    /**
517     * Creates the processor and wraps it in any necessary interceptors and error handlers
518     */
519    protected Processor makeProcessor(RouteContext routeContext) throws Exception {
520        // We will save list of actions to restore the definition back to the original state.
521        Runnable propertyPlaceholdersChangeReverter = ProcessorDefinitionHelper.createPropertyPlaceholdersChangeReverter();
522        try {
523            return makeProcessorImpl(routeContext);
524        } finally {
525            // Lets restore
526            propertyPlaceholdersChangeReverter.run();
527        }
528    }
529
530    private Processor makeProcessorImpl(RouteContext routeContext) throws Exception {
531        Processor processor = null;
532
533        // allow any custom logic before we create the processor
534        preCreateProcessor();
535
536        // resolve properties before we create the processor
537        ProcessorDefinitionHelper.resolvePropertyPlaceholders(routeContext.getCamelContext(), this);
538
539        // resolve constant fields (eg Exchange.FILE_NAME)
540        ProcessorDefinitionHelper.resolveKnownConstantFields(this);
541
542        // also resolve properties and constant fields on embedded expressions
543        ProcessorDefinition<?> me = (ProcessorDefinition<?>) this;
544        if (me instanceof ExpressionNode) {
545            ExpressionNode exp = (ExpressionNode) me;
546            ExpressionDefinition expressionDefinition = exp.getExpression();
547            if (expressionDefinition != null) {
548                // resolve properties before we create the processor
549                ProcessorDefinitionHelper.resolvePropertyPlaceholders(routeContext.getCamelContext(), expressionDefinition);
550
551                // resolve constant fields (eg Exchange.FILE_NAME)
552                ProcessorDefinitionHelper.resolveKnownConstantFields(expressionDefinition);
553            }
554        }
555
556        // at first use custom factory
557        if (routeContext.getCamelContext().getProcessorFactory() != null) {
558            processor = routeContext.getCamelContext().getProcessorFactory().createProcessor(routeContext, this);
559        }
560        // fallback to default implementation if factory did not create the processor
561        if (processor == null) {
562            processor = createProcessor(routeContext);
563        }
564
565        // inject id
566        if (processor instanceof IdAware) {
567            String id = this.idOrCreate(routeContext.getCamelContext().getNodeIdFactory());
568            ((IdAware) processor).setId(id);
569        }
570
571        if (processor == null) {
572            // no processor to make
573            return null;
574        }
575        return wrapProcessor(routeContext, processor);
576    }
577
578    /**
579     * Strategy to execute any custom logic before the {@link Processor} is created.
580     */
581    protected void preCreateProcessor() {
582        // noop
583    }
584
585    /**
586     * Strategy for children to do any custom configuration
587     *
588     * @param output the child to be added as output to this
589     */
590    public void configureChild(ProcessorDefinition<?> output) {
591        // noop
592    }
593
594    // Fluent API
595    // -------------------------------------------------------------------------
596
597    /**
598     * Adds a placeholder for the given option
599     * <p/>
600     * Requires using the {@link org.apache.camel.component.properties.PropertiesComponent}
601     *
602     * @param option  the name of the option
603     * @param key     the placeholder key
604     * @return the builder
605     */
606    public Type placeholder(String option, String key) {
607        QName name = new QName(Constants.PLACEHOLDER_QNAME, option);
608        return attribute(name, key);
609    }
610
611    /**
612     * Adds an optional attribute
613     *
614     * @param name    the name of the attribute
615     * @param value   the value
616     * @return the builder
617     */
618    @SuppressWarnings("unchecked")
619    public Type attribute(QName name, Object value) {
620        if (otherAttributes == null) {
621            otherAttributes = new HashMap<QName, Object>();
622        }
623        otherAttributes.put(name, value);
624        return (Type) this;
625    }
626
627    /**
628     * Sends the exchange to the given endpoint
629     *
630     * @param uri  the endpoint to send to
631     * @return the builder
632     */
633    @SuppressWarnings("unchecked")
634    public Type to(@AsEndpointUri String uri) {
635        addOutput(new ToDefinition(uri));
636        return (Type) this;
637    }
638
639    /**
640     * Sends the exchange to the given dynamic endpoint
641     *
642     * @param uri  the dynamic endpoint to send to (resolved using simple language by default)
643     * @return the builder
644     */
645    @SuppressWarnings("unchecked")
646    public Type toD(@AsEndpointUri String uri) {
647        ToDynamicDefinition answer = new ToDynamicDefinition();
648        answer.setUri(uri);
649        addOutput(answer);
650        return (Type) this;
651    }
652
653    /**
654     * Sends the exchange to the given dynamic endpoint
655     *
656     * @param uri  the dynamic endpoint to send to (resolved using simple language by default)
657     * @return the builder
658     */
659    @SuppressWarnings("unchecked")
660    public Type toD(@AsEndpointUri String uri, boolean ignoreInvalidEndpoint) {
661        ToDynamicDefinition answer = new ToDynamicDefinition();
662        answer.setUri(uri);
663        answer.setIgnoreInvalidEndpoint(ignoreInvalidEndpoint);
664        addOutput(answer);
665        return (Type) this;
666    }
667
668    /**
669     * Sends the exchange to the given endpoint
670     *
671     * @param uri  the String formatted endpoint uri to send to
672     * @param args arguments for the string formatting of the uri
673     * @return the builder
674     */
675    @SuppressWarnings("unchecked")
676    public Type toF(@AsEndpointUri String uri, Object... args) {
677        addOutput(new ToDefinition(String.format(uri, args)));
678        return (Type) this;
679    }
680
681    /**
682     * Calls the service
683     *
684     * @return the builder
685     */
686    public ServiceCallDefinition serviceCall() {
687        ServiceCallDefinition answer = new ServiceCallDefinition();
688        addOutput(answer);
689        return answer;
690    }
691
692    /**
693     * Calls the service
694     *
695     * @param name the service name
696     * @return the builder
697     */
698    @SuppressWarnings("unchecked")
699    public Type serviceCall(String name) {
700        ServiceCallDefinition answer = new ServiceCallDefinition();
701        answer.setName(name);
702        addOutput(answer);
703        return (Type) this;
704    }
705
706    /**
707     * Calls the service
708     *
709     * @param name the service name
710     * @param uri  the endpoint uri to use for calling the service
711     * @return the builder
712     */
713    @SuppressWarnings("unchecked")
714    public Type serviceCall(String name, @AsEndpointUri String uri) {
715        ServiceCallDefinition answer = new ServiceCallDefinition();
716        answer.setName(name);
717        answer.setUri(uri);
718        addOutput(answer);
719        return (Type) this;
720    }
721
722    /**
723     * Sends the exchange to the given endpoint
724     *
725     * @param endpoint  the endpoint to send to
726     * @return the builder
727     */
728    @SuppressWarnings("unchecked")
729    public Type to(Endpoint endpoint) {
730        addOutput(new ToDefinition(endpoint));
731        return (Type) this;
732    }
733    
734    /**
735     * Sends the exchange with certain exchange pattern to the given endpoint
736     * <p/>
737     * Notice the existing MEP is preserved
738     *
739     * @param pattern the pattern to use for the message exchange
740     * @param uri  the endpoint to send to
741     * @return the builder
742     */
743    @SuppressWarnings("unchecked")
744    public Type to(ExchangePattern pattern, @AsEndpointUri String uri) {
745        addOutput(new ToDefinition(uri, pattern));
746        return (Type) this;
747    }   
748
749    /**
750     * Sends the exchange with certain exchange pattern to the given endpoint
751     * <p/>
752     * Notice the existing MEP is preserved
753     *
754     * @param pattern the pattern to use for the message exchange
755     * @param endpoint  the endpoint to send to
756     * @return the builder
757     */
758    @SuppressWarnings("unchecked")
759    public Type to(ExchangePattern pattern, Endpoint endpoint) {
760        addOutput(new ToDefinition(endpoint, pattern));
761        return (Type) this;
762    }
763
764    /**
765     * Sends the exchange to a list of endpoints
766     *
767     * @param uris  list of endpoints to send to
768     * @return the builder
769     */
770    @SuppressWarnings("unchecked")
771    public Type to(@AsEndpointUri String... uris) {
772        for (String uri : uris) {
773            addOutput(new ToDefinition(uri));
774        }
775        return (Type) this;
776    }
777
778    /**
779     * Sends the exchange to a list of endpoints
780     *
781     * @param endpoints  list of endpoints to send to
782     * @return the builder
783     */
784    @SuppressWarnings("unchecked")
785    public Type to(Endpoint... endpoints) {
786        for (Endpoint endpoint : endpoints) {
787            addOutput(new ToDefinition(endpoint));
788        }
789        return (Type) this;
790    }
791
792    /**
793     * Sends the exchange to a list of endpoints
794     *
795     * @param endpoints  list of endpoints to send to
796     * @return the builder
797     */
798    @SuppressWarnings("unchecked")
799    public Type to(Iterable<Endpoint> endpoints) {
800        for (Endpoint endpoint : endpoints) {
801            addOutput(new ToDefinition(endpoint));
802        }
803        return (Type) this;
804    }
805
806    /**
807     * Sends the exchange to a list of endpoints
808     * <p/>
809     * Notice the existing MEP is preserved
810     *
811     * @param pattern the pattern to use for the message exchanges
812     * @param uris  list of endpoints to send to
813     * @return the builder
814     */
815    @SuppressWarnings("unchecked")
816    public Type to(ExchangePattern pattern, @AsEndpointUri String... uris) {
817        for (String uri : uris) {
818            addOutput(new ToDefinition(uri, pattern));
819        }
820        return (Type) this;
821    }
822
823    /**
824     * Sends the exchange to a list of endpoints
825     * <p/>
826     * Notice the existing MEP is preserved
827     *
828     * @param pattern the pattern to use for the message exchanges
829     * @param endpoints  list of endpoints to send to
830     * @return the builder
831     */
832    @SuppressWarnings("unchecked")
833    public Type to(ExchangePattern pattern, Endpoint... endpoints) {
834        for (Endpoint endpoint : endpoints) {
835            addOutput(new ToDefinition(endpoint, pattern));
836        }
837        return (Type) this;
838    }
839
840    /**
841     * Sends the exchange to a list of endpoints
842     *
843     * @param pattern the pattern to use for the message exchanges
844     * @param endpoints  list of endpoints to send to
845     * @return the builder
846     */
847    @SuppressWarnings("unchecked")
848    public Type to(ExchangePattern pattern, Iterable<Endpoint> endpoints) {
849        for (Endpoint endpoint : endpoints) {
850            addOutput(new ToDefinition(endpoint, pattern));
851        }
852        return (Type) this;
853    }
854
855    /**
856     * <a href="http://camel.apache.org/exchange-pattern.html">ExchangePattern:</a>
857     * set the {@link ExchangePattern} into the {@link Exchange}.
858     * <p/>
859     * The pattern set on the {@link Exchange} will be changed from this point going foward.
860     *
861     * @param exchangePattern  instance of {@link ExchangePattern}
862     * @return the builder
863     */
864    @SuppressWarnings("unchecked")
865    public Type setExchangePattern(ExchangePattern exchangePattern) {
866        addOutput(new SetExchangePatternDefinition(exchangePattern));
867        return (Type) this;
868    }
869
870    /**
871     * <a href="http://camel.apache.org/exchange-pattern.html">ExchangePattern:</a>
872     * set the exchange's ExchangePattern {@link ExchangePattern} to be InOnly
873     * <p/>
874     * The pattern set on the {@link Exchange} will be changed from this point going foward.
875     *
876     * @return the builder
877     * @deprecated use {@link #setExchangePattern(org.apache.camel.ExchangePattern)} instead
878     */
879    @Deprecated
880    public Type inOnly() {
881        return setExchangePattern(ExchangePattern.InOnly);
882    }
883
884    /**
885     * Sends the message to the given endpoint using an
886     * <a href="http://camel.apache.org/event-message.html">Event Message</a> or
887     * <a href="http://camel.apache.org/exchange-pattern.html">InOnly exchange pattern</a>
888     * <p/>
889     * Notice the existing MEP is restored after the message has been sent to the given endpoint.
890     *
891     * @param uri The endpoint uri which is used for sending the exchange
892     * @return the builder
893     */
894    public Type inOnly(@AsEndpointUri String uri) {
895        return to(ExchangePattern.InOnly, uri);
896    }
897
898    /**
899     * Sends the message to the given endpoint using an
900     * <a href="http://camel.apache.org/event-message.html">Event Message</a> or 
901     * <a href="http://camel.apache.org/exchange-pattern.html">InOnly exchange pattern</a>
902     * <p/>
903     * Notice the existing MEP is restored after the message has been sent to the given endpoint.
904     *
905     * @param endpoint The endpoint which is used for sending the exchange
906     * @return the builder
907     */
908    public Type inOnly(Endpoint endpoint) {
909        return to(ExchangePattern.InOnly, endpoint);
910    }
911
912    /**
913     * Sends the message to the given endpoints using an
914     * <a href="http://camel.apache.org/event-message.html">Event Message</a> or
915     * <a href="http://camel.apache.org/exchange-pattern.html">InOnly exchange pattern</a>
916     * <p/>
917     * Notice the existing MEP is restored after the message has been sent to the given endpoint.
918     *
919     * @param uris  list of endpoints to send to
920     * @return the builder
921     */
922    public Type inOnly(@AsEndpointUri String... uris) {
923        return to(ExchangePattern.InOnly, uris);
924    }
925
926    /**
927     * Sends the message to the given endpoints using an
928     * <a href="http://camel.apache.org/event-message.html">Event Message</a> or
929     * <a href="http://camel.apache.org/exchange-pattern.html">InOnly exchange pattern</a>
930     * <p/>
931     * Notice the existing MEP is restored after the message has been sent to the given endpoint.
932     *
933     * @param endpoints  list of endpoints to send to
934     * @return the builder
935     */
936    public Type inOnly(@AsEndpointUri Endpoint... endpoints) {
937        return to(ExchangePattern.InOnly, endpoints);
938    }
939
940    /**
941     * Sends the message to the given endpoints using an
942     * <a href="http://camel.apache.org/event-message.html">Event Message</a> or
943     * <a href="http://camel.apache.org/exchange-pattern.html">InOnly exchange pattern</a>
944     * <p/>
945     * Notice the existing MEP is restored after the message has been sent to the given endpoint.
946     *
947     * @param endpoints  list of endpoints to send to
948     * @return the builder
949     */
950    public Type inOnly(Iterable<Endpoint> endpoints) {
951        return to(ExchangePattern.InOnly, endpoints);
952    }
953
954    /**
955     * <a href="http://camel.apache.org/exchange-pattern.html">ExchangePattern:</a>
956     * set the exchange's ExchangePattern {@link ExchangePattern} to be InOut
957     *
958     * @return the builder
959     * @deprecated use {@link #setExchangePattern(org.apache.camel.ExchangePattern)} instead
960     */
961    @Deprecated
962    public Type inOut() {
963        return setExchangePattern(ExchangePattern.InOut);
964    }
965
966    /**
967     * Sends the message to the given endpoint using an
968     * <a href="http://camel.apache.org/request-reply.html">Request Reply</a> or
969     * <a href="http://camel.apache.org/exchange-pattern.html">InOut exchange pattern</a>
970     * <p/>
971     * Notice the existing MEP is restored after the message has been sent to the given endpoint.
972     *
973     * @param uri The endpoint uri which is used for sending the exchange
974     * @return the builder
975     */
976    public Type inOut(@AsEndpointUri String uri) {
977        return to(ExchangePattern.InOut, uri);
978    }
979
980    /**
981     * Sends the message to the given endpoint using an
982     * <a href="http://camel.apache.org/request-reply.html">Request Reply</a> or
983     * <a href="http://camel.apache.org/exchange-pattern.html">InOut exchange pattern</a>
984     * <p/>
985     * Notice the existing MEP is restored after the message has been sent to the given endpoint.
986     *
987     * @param endpoint The endpoint which is used for sending the exchange
988     * @return the builder
989     */
990    public Type inOut(Endpoint endpoint) {
991        return to(ExchangePattern.InOut, endpoint);
992    }
993
994    /**
995     * Sends the message to the given endpoints using an
996     * <a href="http://camel.apache.org/request-reply.html">Request Reply</a> or
997     * <a href="http://camel.apache.org/exchange-pattern.html">InOut exchange pattern</a>
998     * <p/>
999     * Notice the existing MEP is restored after the message has been sent to the given endpoint.
1000     *
1001     * @param uris  list of endpoints to send to
1002     * @return the builder
1003     */
1004    public Type inOut(@AsEndpointUri String... uris) {
1005        return to(ExchangePattern.InOut, uris);
1006    }
1007
1008    /**
1009     * Sends the message to the given endpoints using an
1010     * <a href="http://camel.apache.org/request-reply.html">Request Reply</a> or
1011     * <a href="http://camel.apache.org/exchange-pattern.html">InOut exchange pattern</a>
1012     * <p/>
1013     * Notice the existing MEP is restored after the message has been sent to the given endpoint.
1014     *
1015     * @param endpoints  list of endpoints to send to
1016     * @return the builder
1017     */
1018    public Type inOut(Endpoint... endpoints) {
1019        return to(ExchangePattern.InOut, endpoints);
1020    }
1021
1022    /**
1023     * Sends the message to the given endpoints using an
1024     * <a href="http://camel.apache.org/request-reply.html">Request Reply</a> or
1025     * <a href="http://camel.apache.org/exchange-pattern.html">InOut exchange pattern</a>
1026     * <p/>
1027     * Notice the existing MEP is restored after the message has been sent to the given endpoint.
1028     *
1029     * @param endpoints  list of endpoints to send to
1030     * @return the builder
1031     */
1032    public Type inOut(Iterable<Endpoint> endpoints) {
1033        return to(ExchangePattern.InOut, endpoints);
1034    }
1035
1036    /**
1037     * Sets the id of this node.
1038     * <p/>
1039     * <b>Important:</b> If you want to set the id of the route,
1040     * then you <b>must</b> use {@link #routeId(String)} instead.
1041     *
1042     * @param id  the id
1043     * @return the builder
1044     */
1045    @SuppressWarnings("unchecked")
1046    public Type id(String id) {
1047        if (isOutputSupported() && getOutputs().isEmpty()) {
1048            // set id on this
1049            setId(id);
1050        } else {
1051            
1052            // set it on last output as this is what the user means to do
1053            // for Block(s) with non empty getOutputs() the id probably refers
1054            //  to the last definition in the current Block
1055            List<ProcessorDefinition<?>> outputs = getOutputs();
1056            if (!blocks.isEmpty()) {
1057                if (blocks.getLast() instanceof ProcessorDefinition) {
1058                    ProcessorDefinition<?> block = (ProcessorDefinition<?>)blocks.getLast();
1059                    if (!block.getOutputs().isEmpty()) {
1060                        outputs = block.getOutputs();
1061                    }
1062                }
1063            }
1064            if (!getOutputs().isEmpty()) {
1065                outputs.get(outputs.size() - 1).setId(id);
1066            } else {
1067                // the output could be empty
1068                setId(id);
1069            }
1070        }
1071
1072        return (Type) this;
1073    }
1074
1075    /**
1076     * Set the route id for this route.
1077     * <p/>
1078     * <b>Important: </b> Each route in the same {@link org.apache.camel.CamelContext} must have an <b>unique</b> route id.
1079     * If you use the API from {@link org.apache.camel.CamelContext} or {@link ModelCamelContext} to add routes, then any
1080     * new routes which has a route id that matches an old route, then the old route is replaced by the new route.
1081     *
1082     * @param id  the route id, should be unique
1083     * @return the builder
1084     */
1085    @SuppressWarnings("unchecked")
1086    public Type routeId(String id) {
1087        ProcessorDefinition<?> def = this;
1088
1089        RouteDefinition route = ProcessorDefinitionHelper.getRoute(def);
1090        if (route != null) {
1091            route.setId(id);
1092        }
1093
1094        return (Type) this;
1095    }
1096
1097    /**
1098     * Set the route description for this route
1099     *
1100     * @param description the route description
1101     * @return the builder
1102     */
1103    @SuppressWarnings("unchecked")
1104    public Type routeDescription(String description) {
1105        ProcessorDefinition<?> def = this;
1106
1107        RouteDefinition route = ProcessorDefinitionHelper.getRoute(def);
1108        if (route != null) {
1109            DescriptionDefinition desc = new DescriptionDefinition();
1110            desc.setText(description);
1111            route.setDescription(desc);
1112        }
1113
1114        return (Type) this;
1115    }
1116
1117    /**
1118     * <a href="http://camel.apache.org/multicast.html">Multicast EIP:</a>
1119     * Multicasts messages to all its child outputs; so that each processor and
1120     * destination gets a copy of the original message to avoid the processors
1121     * interfering with each other.
1122     *
1123     * @return the builder
1124     */
1125    public MulticastDefinition multicast() {
1126        MulticastDefinition answer = new MulticastDefinition();
1127        addOutput(answer);
1128        return answer;
1129    }
1130
1131    /**
1132     * <a href="http://camel.apache.org/multicast.html">Multicast EIP:</a>
1133     * Multicasts messages to all its child outputs; so that each processor and
1134     * destination gets a copy of the original message to avoid the processors
1135     * interfering with each other.
1136     *
1137     * @param aggregationStrategy the strategy used to aggregate responses for
1138     *          every part
1139     * @param parallelProcessing if is <tt>true</tt> camel will fork thread to call the endpoint producer
1140     * @return the builder
1141     */
1142    public MulticastDefinition multicast(AggregationStrategy aggregationStrategy, boolean parallelProcessing) {
1143        MulticastDefinition answer = new MulticastDefinition();
1144        addOutput(answer);
1145        answer.setAggregationStrategy(aggregationStrategy);
1146        answer.setParallelProcessing(parallelProcessing);
1147        return answer;
1148    }
1149
1150    /**
1151     * <a href="http://camel.apache.org/multicast.html">Multicast EIP:</a>
1152     * Multicasts messages to all its child outputs; so that each processor and
1153     * destination gets a copy of the original message to avoid the processors
1154     * interfering with each other.
1155     *
1156     * @param aggregationStrategy the strategy used to aggregate responses for every part
1157     * @return the builder
1158     */
1159    public MulticastDefinition multicast(AggregationStrategy aggregationStrategy) {
1160        MulticastDefinition answer = new MulticastDefinition();
1161        addOutput(answer);
1162        answer.setAggregationStrategy(aggregationStrategy);
1163        return answer;
1164    }
1165
1166    /**
1167     * <a href="http://camel.apache.org/pipes-nd-filters.html">Pipes and Filters EIP:</a>
1168     * Creates a {@link Pipeline} so that the message
1169     * will get processed by each endpoint in turn and for request/response the
1170     * output of one endpoint will be the input of the next endpoint
1171     *
1172     * @return the builder
1173     */
1174    public PipelineDefinition pipeline() {
1175        PipelineDefinition answer = new PipelineDefinition();
1176        addOutput(answer);
1177        return answer;
1178    }
1179
1180    /**
1181     * <a href="http://camel.apache.org/pipes-nd-filters.html">Pipes and Filters EIP:</a>
1182     * Creates a {@link Pipeline} of the list of endpoints so that the message
1183     * will get processed by each endpoint in turn and for request/response the
1184     * output of one endpoint will be the input of the next endpoint
1185     *
1186     * @param uris  list of endpoints
1187     * @return the builder
1188     */
1189    public Type pipeline(@AsEndpointUri String... uris) {
1190        PipelineDefinition answer = new PipelineDefinition();
1191        addOutput(answer);
1192        answer.to(uris);
1193        return (Type) this;
1194    }
1195
1196    /**
1197     * <a href="http://camel.apache.org/pipes-nd-filters.html">Pipes and Filters EIP:</a>
1198     * Creates a {@link Pipeline} of the list of endpoints so that the message
1199     * will get processed by each endpoint in turn and for request/response the
1200     * output of one endpoint will be the input of the next endpoint
1201     *
1202     * @param endpoints  list of endpoints
1203     * @return the builder
1204     */
1205    public Type pipeline(Endpoint... endpoints) {
1206        PipelineDefinition answer = new PipelineDefinition();
1207        addOutput(answer);
1208        answer.to(endpoints);
1209        return (Type) this;
1210    }
1211
1212    /**
1213     * <a href="http://camel.apache.org/pipes-nd-filters.html">Pipes and Filters EIP:</a>
1214     * Creates a {@link Pipeline} of the list of endpoints so that the message
1215     * will get processed by each endpoint in turn and for request/response the
1216     * output of one endpoint will be the input of the next endpoint
1217     *
1218     * @param endpoints  list of endpoints
1219     * @return the builder
1220     */
1221    public Type pipeline(Collection<Endpoint> endpoints) {
1222        PipelineDefinition answer = new PipelineDefinition();
1223        addOutput(answer);
1224        answer.to(endpoints);
1225        return (Type) this;
1226    }
1227
1228    /**
1229     * Continues processing the {@link org.apache.camel.Exchange} using asynchronous routing engine.
1230     *
1231     * @return the builder
1232     */
1233    public ThreadsDefinition threads() {
1234        ThreadsDefinition answer = new ThreadsDefinition();
1235        addOutput(answer);
1236        return answer;
1237    }
1238
1239    /**
1240     * Continues processing the {@link org.apache.camel.Exchange} using asynchronous routing engine.
1241     *
1242     * @param poolSize the core pool size
1243     * @return the builder
1244     */
1245    public ThreadsDefinition threads(int poolSize) {
1246        ThreadsDefinition answer = new ThreadsDefinition();
1247        answer.setPoolSize(poolSize);
1248        addOutput(answer);
1249        return answer;
1250    }
1251
1252    /**
1253     * Continues processing the {@link org.apache.camel.Exchange} using asynchronous routing engine.
1254     *
1255     * @param poolSize    the core pool size
1256     * @param maxPoolSize the maximum pool size
1257     * @return the builder
1258     */
1259    public ThreadsDefinition threads(int poolSize, int maxPoolSize) {
1260        ThreadsDefinition answer = new ThreadsDefinition();
1261        answer.setPoolSize(poolSize);
1262        answer.setMaxPoolSize(maxPoolSize);
1263        addOutput(answer);
1264        return answer;
1265    }
1266    
1267    /**
1268     * Continues processing the {@link org.apache.camel.Exchange} using asynchronous routing engine.
1269     *
1270     * @param poolSize    the core pool size
1271     * @param maxPoolSize the maximum pool size
1272     * @param threadName the thread pool name
1273     * @return the builder
1274     */
1275    public ThreadsDefinition threads(int poolSize, int maxPoolSize, String threadName) {
1276        ThreadsDefinition answer = new ThreadsDefinition();
1277        answer.setPoolSize(poolSize);
1278        answer.setMaxPoolSize(maxPoolSize);
1279        answer.setThreadName(threadName);
1280        addOutput(answer);
1281        return answer;
1282    }
1283
1284    /**
1285     * Wraps the sub route using AOP allowing you to do before and after work (AOP around).
1286     *
1287     * @return the builder
1288     * @deprecated to be removed in the near future. Instead you can use interceptors or processors to do AOP with Camel.
1289     */
1290    @Deprecated
1291    public AOPDefinition aop() {
1292        AOPDefinition answer = new AOPDefinition();
1293        addOutput(answer);
1294        return answer;
1295    }
1296
1297    /**
1298     * Ends the current block
1299     *
1300     * @return the builder
1301     */
1302    public ProcessorDefinition<?> end() {
1303        // must do this ugly cast to avoid compiler error on AIX/HP-UX
1304        ProcessorDefinition<?> defn = (ProcessorDefinition<?>) this;
1305        
1306        // when using choice .. when .. otherwise - doTry .. doCatch .. doFinally we should always
1307        // end the choice/try definition to avoid having to use 2 x end() in the route
1308        // this is counter intuitive for end users
1309        // TODO (camel-3.0): this should be done inside of TryDefinition or even better
1310        //  in Block(s) in general, but the api needs to be revisited for that.
1311        if (defn instanceof TryDefinition || defn instanceof ChoiceDefinition) {
1312            popBlock();
1313        }
1314
1315        if (blocks.isEmpty()) {
1316            if (parent == null) {
1317                return this.endParent();
1318            }
1319            return parent.endParent();
1320        }
1321        popBlock();
1322        return this.endParent();
1323    }
1324
1325    /**
1326     * Strategy to allow {@link ProcessorDefinition}s to have special logic when using end() in the DSL
1327     * to return back to the intended parent.
1328     * <p/>
1329     * For example a content based router we return back to the {@link ChoiceDefinition} when we end()
1330     * from a {@link WhenDefinition}.
1331     *
1332     * @return the end
1333     */
1334    public ProcessorDefinition<?> endParent() {
1335        return this;
1336    }
1337
1338    /**
1339     * Ends the current block and returns back to the {@link ChoiceDefinition choice()} DSL.
1340     * <p/>
1341     * <b>Important:</b> If you want to end the entire choice block, then use {@link #end()} instead.
1342     * The purpose of {@link #endChoice()} is to return <i>control</i> back to the {@link ChoiceDefinition choice()} DSL,
1343     * so you can add subsequent <tt>when</tt> and <tt>otherwise</tt> to the choice. There can be situations where
1344     * you would need to use {@link #endChoice()} often when you add additional EIPs inside the <tt>when</tt>'s, and
1345     * the DSL <t>looses</t> scope when using a regular {@link #end()}, and you would need to use this {@link #endChoice()}
1346     * to return back the scope to the {@link ChoiceDefinition choice()} DSL.
1347     * <p/>
1348     * For more details and examples see also this FAQ:
1349     * <a href="http://camel.apache.org/why-can-i-not-use-when-or-otherwise-in-a-java-camel-route.html">Why can I not use when or otherwise in a Java Camel route </a>.
1350     *
1351     * @return the choice builder
1352     */
1353    public ChoiceDefinition endChoice() {
1354        // are we nested choice?
1355        ProcessorDefinition<?> def = this;
1356        if (def.getParent() instanceof WhenDefinition) {
1357            return (ChoiceDefinition) def.getParent().getParent();
1358        }
1359
1360        // are we already a choice?
1361        if (def instanceof ChoiceDefinition) {
1362            return (ChoiceDefinition) def;
1363        }
1364
1365        // okay end this and get back to the choice
1366        def = end();
1367        if (def instanceof WhenDefinition) {
1368            return (ChoiceDefinition) def.getParent();
1369        } else if (def instanceof OtherwiseDefinition) {
1370            return (ChoiceDefinition) def.getParent();
1371        } else {
1372            return (ChoiceDefinition) def;
1373        }
1374    }
1375
1376    /**
1377     * Ends the current block and returns back to the {@link org.apache.camel.model.rest.RestDefinition rest()} DSL.
1378     *
1379     * @return the builder
1380     */
1381    public RestDefinition endRest() {
1382        ProcessorDefinition<?> def = this;
1383
1384        RouteDefinition route = ProcessorDefinitionHelper.getRoute(def);
1385        if (route != null) {
1386            return route.getRestDefinition();
1387        }
1388
1389        throw new IllegalArgumentException("Cannot find RouteDefinition to allow endRest");
1390    }
1391
1392    /**
1393     * Ends the current block and returns back to the {@link TryDefinition doTry()} DSL.
1394     *
1395     * @return the builder
1396     */
1397    public TryDefinition endDoTry() {
1398        ProcessorDefinition<?> def = this;
1399
1400        // are we already a try?
1401        if (def instanceof TryDefinition) {
1402            return (TryDefinition) def;
1403        }
1404
1405        // okay end this and get back to the try
1406        def = end();
1407        return (TryDefinition) def;
1408    }
1409
1410    /**
1411     * Ends the current block and returns back to the {@link HystrixDefinition hystrix()} DSL.
1412     *
1413     * @return the builder
1414     */
1415    public HystrixDefinition endHystrix() {
1416        ProcessorDefinition<?> def = this;
1417
1418        // are we already a try?
1419        if (def instanceof HystrixDefinition) {
1420            return (HystrixDefinition) def;
1421        }
1422
1423        // okay end this and get back to the try
1424        def = end();
1425        return (HystrixDefinition) def;
1426    }
1427
1428    /**
1429     * <a href="http://camel.apache.org/idempotent-consumer.html">Idempotent consumer EIP:</a>
1430     * Creates an {@link org.apache.camel.processor.idempotent.IdempotentConsumer IdempotentConsumer} using a fluent builder.
1431     */
1432    public ExpressionClause<IdempotentConsumerDefinition> idempotentConsumer() {
1433        IdempotentConsumerDefinition answer = new IdempotentConsumerDefinition();
1434        addOutput(answer);
1435
1436        return ExpressionClause.createAndSetExpression(answer);
1437    }
1438
1439    /**
1440     * <a href="http://camel.apache.org/idempotent-consumer.html">Idempotent consumer EIP:</a>
1441     * Creates an {@link org.apache.camel.processor.idempotent.IdempotentConsumer IdempotentConsumer}
1442     * to avoid duplicate messages
1443     *
1444     * @param messageIdExpression  expression to test of duplicate messages
1445     * @return the builder
1446     */
1447    public IdempotentConsumerDefinition idempotentConsumer(Expression messageIdExpression) {
1448        IdempotentConsumerDefinition answer = new IdempotentConsumerDefinition();
1449        answer.setExpression(ExpressionNodeHelper.toExpressionDefinition(messageIdExpression));
1450        addOutput(answer);
1451        return answer;
1452    }
1453
1454    /**
1455     * <a href="http://camel.apache.org/idempotent-consumer.html">Idempotent consumer EIP:</a>
1456     * Creates an {@link org.apache.camel.processor.idempotent.IdempotentConsumer IdempotentConsumer}
1457     * to avoid duplicate messages
1458     *
1459     * @param messageIdExpression  expression to test of duplicate messages
1460     * @param idempotentRepository  the repository to use for duplicate check
1461     * @return the builder
1462     */
1463    public IdempotentConsumerDefinition idempotentConsumer(Expression messageIdExpression, IdempotentRepository<?> idempotentRepository) {
1464        IdempotentConsumerDefinition answer = new IdempotentConsumerDefinition(messageIdExpression, idempotentRepository);
1465        addOutput(answer);
1466        return answer;
1467    }
1468
1469    /**
1470     * <a href="http://camel.apache.org/idempotent-consumer.html">Idempotent consumer EIP:</a>
1471     * Creates an {@link org.apache.camel.processor.idempotent.IdempotentConsumer IdempotentConsumer}
1472     * to avoid duplicate messages
1473     *
1474     * @param idempotentRepository the repository to use for duplicate check
1475     * @return the builder used to create the expression
1476     * @deprecated will be removed in Camel 3.0. Instead use any of the other methods
1477     */
1478    @Deprecated
1479    public ExpressionClause<IdempotentConsumerDefinition> idempotentConsumer(IdempotentRepository<?> idempotentRepository) {
1480        IdempotentConsumerDefinition answer = new IdempotentConsumerDefinition();
1481        answer.setMessageIdRepository(idempotentRepository);
1482        addOutput(answer);
1483        return ExpressionClause.createAndSetExpression(answer);
1484    }
1485
1486    /**
1487     * <a href="http://camel.apache.org/message-filter.html">Message Filter EIP:</a>
1488     * Creates a predicate expression which only if it is <tt>true</tt> then the
1489     * exchange is forwarded to the destination
1490     *
1491     * @return the clause used to create the filter expression
1492     */
1493    @AsPredicate
1494    public ExpressionClause<? extends FilterDefinition> filter() {
1495        FilterDefinition filter = new FilterDefinition();
1496        addOutput(filter);
1497        return ExpressionClause.createAndSetExpression(filter);
1498    }
1499
1500    /**
1501     * <a href="http://camel.apache.org/message-filter.html">Message Filter EIP:</a>
1502     * Creates a predicate which is applied and only if it is <tt>true</tt> then the
1503     * exchange is forwarded to the destination
1504     *
1505     * @param predicate  predicate to use
1506     * @return the builder 
1507     */
1508    public FilterDefinition filter(@AsPredicate Predicate predicate) {
1509        FilterDefinition filter = new FilterDefinition(predicate);
1510        addOutput(filter);
1511        return filter;
1512    }
1513
1514    /**
1515     * <a href="http://camel.apache.org/message-filter.html">Message Filter EIP:</a>
1516     * Creates a predicate expression which only if it is <tt>true</tt> then the
1517     * exchange is forwarded to the destination
1518     *
1519     * @param expression  the predicate expression to use
1520     * @return the builder
1521     */
1522    public FilterDefinition filter(@AsPredicate ExpressionDefinition expression) {
1523        FilterDefinition filter = new FilterDefinition(expression);
1524        addOutput(filter);
1525        return filter;
1526    }
1527
1528    /**
1529     * <a href="http://camel.apache.org/message-filter.html">Message Filter EIP:</a>
1530     * Creates a predicate language expression which only if it is <tt>true</tt> then the
1531     * exchange is forwarded to the destination
1532     *
1533     * @param language     language for expression
1534     * @param expression   the expression
1535     * @return the builder
1536     */
1537    public FilterDefinition filter(String language, @AsPredicate String expression) {
1538        return filter(new LanguageExpression(language, expression));
1539    }
1540    
1541    /**
1542     * Creates a validation expression which only if it is <tt>true</tt> then the
1543     * exchange is forwarded to the destination.
1544     * Otherwise a {@link org.apache.camel.processor.validation.PredicateValidationException} is thrown.
1545     *
1546     * @param expression  the expression
1547     * @return the builder
1548     */
1549    public ValidateDefinition validate(@AsPredicate Expression expression) {
1550        ValidateDefinition answer = new ValidateDefinition(expression);
1551        addOutput(answer);
1552        return answer;
1553    }
1554
1555    /**
1556     * Creates a validation expression which only if it is <tt>true</tt> then the
1557     * exchange is forwarded to the destination.
1558     * Otherwise a {@link org.apache.camel.processor.validation.PredicateValidationException} is thrown.
1559     *
1560     * @param predicate  the predicate
1561     * @return the builder
1562     */
1563    public ValidateDefinition validate(@AsPredicate Predicate predicate) {
1564        ValidateDefinition answer = new ValidateDefinition(predicate);
1565        addOutput(answer);
1566        return answer;
1567    }
1568
1569    /**
1570     * Creates a validation expression which only if it is <tt>true</tt> then the
1571     * exchange is forwarded to the destination.
1572     * Otherwise a {@link org.apache.camel.processor.validation.PredicateValidationException} is thrown.
1573     *
1574     * @return the builder
1575     */
1576    @AsPredicate
1577    public ExpressionClause<ValidateDefinition> validate() {
1578        ValidateDefinition answer = new ValidateDefinition();
1579        addOutput(answer);
1580        return ExpressionClause.createAndSetExpression(answer);
1581    }
1582
1583    /**
1584     * Creates a Hystrix Circuit Breaker EIP.
1585     * <p/>
1586     * This requires having camel-hystrix on the classpath.
1587     *
1588     * @return  the builder
1589     */
1590    public HystrixDefinition hystrix() {
1591        HystrixDefinition answer = new HystrixDefinition();
1592        addOutput(answer);
1593        return answer;
1594    }
1595
1596    /**
1597     * <a href="http://camel.apache.org/load-balancer.html">Load Balancer EIP:</a>
1598     * Creates a loadbalance
1599     *
1600     * @return  the builder
1601     */
1602    public LoadBalanceDefinition loadBalance() {
1603        LoadBalanceDefinition answer = new LoadBalanceDefinition();
1604        addOutput(answer);
1605        return answer;
1606    }
1607
1608    /**
1609     * <a href="http://camel.apache.org/load-balancer.html">Load Balancer EIP:</a>
1610     * Creates a loadbalance
1611     *
1612     * @param loadBalancer a custom load balancer to use
1613     * @return  the builder
1614     */
1615    public LoadBalanceDefinition loadBalance(LoadBalancer loadBalancer) {
1616        LoadBalanceDefinition answer = new LoadBalanceDefinition();
1617        addOutput(answer);
1618        return answer.loadBalance(loadBalancer);
1619    }
1620
1621    /**
1622     * Creates a log message to be logged at INFO level.
1623     *
1624     * @param message the log message, (you can use {@link org.apache.camel.language.simple.SimpleLanguage} syntax)
1625     * @return the builder
1626     */
1627    @SuppressWarnings("unchecked")
1628    public Type log(String message) {
1629        LogDefinition answer = new LogDefinition(message);
1630        addOutput(answer);
1631        return (Type) this;
1632    }
1633
1634    /**
1635     * Creates a log message to be logged at the given level.
1636     *
1637     * @param loggingLevel the logging level to use
1638     * @param message the log message, (you can use {@link org.apache.camel.language.simple.SimpleLanguage} syntax)
1639     * @return the builder
1640     */
1641    @SuppressWarnings("unchecked")
1642    public Type log(LoggingLevel loggingLevel, String message) {
1643        LogDefinition answer = new LogDefinition(message);
1644        answer.setLoggingLevel(loggingLevel);
1645        addOutput(answer);
1646        return (Type) this;
1647    }
1648
1649    /**
1650     * Creates a log message to be logged at the given level and name.
1651     *
1652     * @param loggingLevel the logging level to use
1653     * @param logName the log name to use
1654     * @param message the log message, (you can use {@link org.apache.camel.language.simple.SimpleLanguage} syntax)
1655     * @return the builder
1656     */
1657    @SuppressWarnings("unchecked")
1658    public Type log(LoggingLevel loggingLevel, String logName, String message) {
1659        LogDefinition answer = new LogDefinition(message);
1660        answer.setLoggingLevel(loggingLevel);
1661        answer.setLogName(logName);
1662        addOutput(answer);
1663        return (Type) this;
1664    }
1665
1666    /**
1667     * Creates a log message to be logged at the given level using provided logger.
1668     *
1669     * @param loggingLevel the logging level to use
1670     * @param logger the logger to use
1671     * @param message the log message, (you can use {@link org.apache.camel.language.simple.SimpleLanguage} syntax)
1672     * @return the builder
1673     */
1674    @SuppressWarnings("unchecked")
1675    public Type log(LoggingLevel loggingLevel, Logger logger, String message) {
1676        LogDefinition answer = new LogDefinition(message);
1677        answer.setLoggingLevel(loggingLevel);
1678        answer.setLogger(logger);
1679        addOutput(answer);
1680        return (Type) this;
1681    }
1682
1683    /**
1684     * Creates a log message to be logged at the given level and name.
1685     *
1686     *
1687     * @param loggingLevel the logging level to use
1688     * @param logName the log name to use
1689     * @param marker  log marker name
1690     * @param message the log message, (you can use {@link org.apache.camel.language.simple.SimpleLanguage} syntax)
1691     * @return the builder
1692     */
1693    @SuppressWarnings("unchecked")
1694    public Type log(LoggingLevel loggingLevel, String logName, String marker, String message) {
1695        LogDefinition answer = new LogDefinition(message);
1696        answer.setLoggingLevel(loggingLevel);
1697        answer.setLogName(logName);
1698        answer.setMarker(marker);
1699        addOutput(answer);
1700        return (Type) this;
1701    }
1702
1703    /**
1704     * Creates a log message to be logged at the given level using provided logger.
1705     *
1706     *
1707     * @param loggingLevel the logging level to use
1708     * @param logger the logger to use
1709     * @param marker  log marker name
1710     * @param message the log message, (you can use {@link org.apache.camel.language.simple.SimpleLanguage} syntax)
1711     * @return the builder
1712     */
1713    @SuppressWarnings("unchecked")
1714    public Type log(LoggingLevel loggingLevel, Logger logger, String marker, String message) {
1715        LogDefinition answer = new LogDefinition(message);
1716        answer.setLoggingLevel(loggingLevel);
1717        answer.setLogger(logger);
1718        answer.setMarker(marker);
1719        addOutput(answer);
1720        return (Type) this;
1721    }
1722
1723    /**
1724     * <a href="http://camel.apache.org/content-based-router.html">Content Based Router EIP:</a>
1725     * Creates a choice of one or more predicates with an otherwise clause
1726     *
1727     * @return the builder for a choice expression
1728     */
1729    public ChoiceDefinition choice() {
1730        ChoiceDefinition answer = new ChoiceDefinition();
1731        addOutput(answer);
1732        return answer;
1733    }
1734
1735    /**
1736     * Creates a try/catch block
1737     *
1738     * @return the builder for a tryBlock expression
1739     */
1740    public TryDefinition doTry() {
1741        TryDefinition answer = new TryDefinition();
1742        addOutput(answer);
1743        return answer;
1744    }
1745
1746    /**
1747     * <a href="http://camel.apache.org/recipient-list.html">Recipient List EIP:</a>
1748     * Creates a dynamic recipient list allowing you to route messages to a number of dynamically specified recipients.
1749     * <p/>
1750     * Will use comma as default delimiter.
1751     *
1752     * @param recipients expression to decide the destinations
1753     * @return the builder
1754     */
1755    public RecipientListDefinition<Type> recipientList(@AsEndpointUri Expression recipients) {
1756        RecipientListDefinition<Type> answer = new RecipientListDefinition<Type>(recipients);
1757        addOutput(answer);
1758        return answer;
1759    }
1760
1761    /**
1762     * <a href="http://camel.apache.org/recipient-list.html">Recipient List EIP:</a>
1763     * Creates a dynamic recipient list allowing you to route messages to a number of dynamically specified recipients
1764     *
1765     * @param recipients expression to decide the destinations
1766     * @param delimiter  a custom delimiter to use
1767     * @return the builder
1768     */
1769    public RecipientListDefinition<Type> recipientList(@AsEndpointUri Expression recipients, String delimiter) {
1770        RecipientListDefinition<Type> answer = new RecipientListDefinition<Type>(recipients);
1771        answer.setDelimiter(delimiter);
1772        addOutput(answer);
1773        return answer;
1774    }
1775
1776    /**
1777     * <a href="http://camel.apache.org/recipient-list.html">Recipient List EIP:</a>
1778     * Creates a dynamic recipient list allowing you to route messages to a number of dynamically specified recipients
1779     *
1780     * @param delimiter  a custom delimiter to use
1781     * @return the builder
1782     */
1783    @AsEndpointUri
1784    public ExpressionClause<RecipientListDefinition<Type>> recipientList(String delimiter) {
1785        RecipientListDefinition<Type> answer = new RecipientListDefinition<Type>();
1786        answer.setDelimiter(delimiter);
1787        addOutput(answer);
1788        return ExpressionClause.createAndSetExpression(answer);
1789    }
1790
1791    /**
1792     * <a href="http://camel.apache.org/recipient-list.html">Recipient List EIP:</a>
1793     * Creates a dynamic recipient list allowing you to route messages to a number of dynamically specified recipients
1794     *
1795     * @return the expression clause to configure the expression to decide the destinations
1796     */
1797    @AsEndpointUri
1798    public ExpressionClause<RecipientListDefinition<Type>> recipientList() {
1799        RecipientListDefinition<Type> answer = new RecipientListDefinition<Type>();
1800        addOutput(answer);
1801        return ExpressionClause.createAndSetExpression(answer);
1802    }
1803
1804    /**
1805     * <a href="http://camel.apache.org/routing-slip.html">Routing Slip EIP:</a>
1806     * Creates a routing slip allowing you to route a message consecutively through a series of processing
1807     * steps where the sequence of steps is not known at design time and can vary for each message.
1808     * <p/>
1809     * The route slip will be evaluated <i>once</i>, use {@link #dynamicRouter()} if you need even more dynamic routing.
1810     *
1811     * @param header  is the header that the {@link org.apache.camel.processor.RoutingSlip RoutingSlip}
1812     *                class will look in for the list of URIs to route the message to.
1813     * @param uriDelimiter  is the delimiter that will be used to split up
1814     *                      the list of URIs in the routing slip.
1815     * @return the builder
1816     * @deprecated prefer to use {@link #routingSlip(org.apache.camel.Expression, String)} instead
1817     */
1818    @Deprecated
1819    public Type routingSlip(String header, String uriDelimiter) {
1820        RoutingSlipDefinition<Type> answer = new RoutingSlipDefinition<Type>(header, uriDelimiter);
1821        addOutput(answer);
1822        return (Type) this;
1823    }
1824
1825    /**
1826     * <a href="http://camel.apache.org/routing-slip.html">Routing Slip EIP:</a>
1827     * Creates a routing slip allowing you to route a message consecutively through a series of processing
1828     * steps where the sequence of steps is not known at design time and can vary for each message.
1829     * <p/>
1830     * The list of URIs will be split based on the default delimiter {@link RoutingSlipDefinition#DEFAULT_DELIMITER}
1831     * <p/>
1832     * The route slip will be evaluated <i>once</i>, use {@link #dynamicRouter()} if you need even more dynamic routing.
1833     *
1834     * @param header  is the header that the {@link org.apache.camel.processor.RoutingSlip RoutingSlip}
1835     *                class will look in for the list of URIs to route the message to.
1836     * @return the builder
1837     * @deprecated prefer to use {@link #routingSlip(org.apache.camel.Expression)} instead
1838     */
1839    @Deprecated
1840    public Type routingSlip(String header) {
1841        RoutingSlipDefinition<Type> answer = new RoutingSlipDefinition<Type>(header);
1842        addOutput(answer);
1843        return (Type) this;
1844    }
1845    
1846    /**
1847     * <a href="http://camel.apache.org/routing-slip.html">Routing Slip EIP:</a>
1848     * Creates a routing slip allowing you to route a message consecutively through a series of processing
1849     * steps where the sequence of steps is not known at design time and can vary for each message.
1850     * <p/>
1851     * The route slip will be evaluated <i>once</i>, use {@link #dynamicRouter()} if you need even more dynamic routing.
1852     *
1853     * @param header  is the header that the {@link org.apache.camel.processor.RoutingSlip RoutingSlip}
1854     *                class will look in for the list of URIs to route the message to.
1855     * @param uriDelimiter  is the delimiter that will be used to split up
1856     *                      the list of URIs in the routing slip.
1857     * @param ignoreInvalidEndpoints if this parameter is true, routingSlip will ignore the endpoints which
1858     *                               cannot be resolved or a producer cannot be created or started 
1859     * @return the builder
1860     * @deprecated prefer to use {@link #routingSlip()} instead
1861     */
1862    @Deprecated
1863    public Type routingSlip(String header, String uriDelimiter, boolean ignoreInvalidEndpoints) {
1864        RoutingSlipDefinition<Type> answer = new RoutingSlipDefinition<Type>(header, uriDelimiter);
1865        answer.setIgnoreInvalidEndpoints(ignoreInvalidEndpoints);
1866        addOutput(answer);
1867        return (Type) this;
1868    }
1869
1870    /**
1871     * <a href="http://camel.apache.org/routing-slip.html">Routing Slip EIP:</a>
1872     * Creates a routing slip allowing you to route a message consecutively through a series of processing
1873     * steps where the sequence of steps is not known at design time and can vary for each message.
1874     * <p/>
1875     * The list of URIs will be split based on the default delimiter {@link RoutingSlipDefinition#DEFAULT_DELIMITER}
1876     * <p/>
1877     * The route slip will be evaluated <i>once</i>, use {@link #dynamicRouter()} if you need even more dynamic routing.
1878     *
1879     * @param header  is the header that the {@link org.apache.camel.processor.RoutingSlip RoutingSlip}
1880     *                class will look in for the list of URIs to route the message to.
1881     * @param ignoreInvalidEndpoints if this parameter is true, routingSlip will ignore the endpoints which
1882     *                               cannot be resolved or a producer cannot be created or started 
1883     * @return the builder
1884     * @deprecated prefer to use {@link #routingSlip()} instead
1885     */
1886    @Deprecated
1887    public Type routingSlip(String header, boolean ignoreInvalidEndpoints) {
1888        RoutingSlipDefinition<Type> answer = new RoutingSlipDefinition<Type>(header);
1889        answer.setIgnoreInvalidEndpoints(ignoreInvalidEndpoints);
1890        addOutput(answer);
1891        return (Type) this;
1892    }
1893    
1894    /**
1895     * <a href="http://camel.apache.org/routing-slip.html">Routing Slip EIP:</a>
1896     * Creates a routing slip allowing you to route a message consecutively through a series of processing
1897     * steps where the sequence of steps is not known at design time and can vary for each message.
1898     * <p/>
1899     * The route slip will be evaluated <i>once</i>, use {@link #dynamicRouter()} if you need even more dynamic routing.
1900     *
1901     * @param expression  to decide the destinations
1902     * @param uriDelimiter  is the delimiter that will be used to split up
1903     *                      the list of URIs in the routing slip.
1904     * @return the builder
1905     */
1906    public RoutingSlipDefinition<Type> routingSlip(@AsEndpointUri Expression expression, String uriDelimiter) {
1907        RoutingSlipDefinition<Type> answer = new RoutingSlipDefinition<Type>(expression, uriDelimiter);
1908        addOutput(answer);
1909        return answer;
1910    }
1911
1912    /**
1913     * <a href="http://camel.apache.org/routing-slip.html">Routing Slip EIP:</a>
1914     * Creates a routing slip allowing you to route a message consecutively through a series of processing
1915     * steps where the sequence of steps is not known at design time and can vary for each message.
1916     * <p/>
1917     * The list of URIs will be split based on the default delimiter {@link RoutingSlipDefinition#DEFAULT_DELIMITER}
1918     * <p/>
1919     * The route slip will be evaluated <i>once</i>, use {@link #dynamicRouter()} if you need even more dynamic routing.
1920     *
1921     * @param expression  to decide the destinations
1922     * @return the builder
1923     */
1924    public RoutingSlipDefinition<Type> routingSlip(@AsEndpointUri Expression expression) {
1925        RoutingSlipDefinition<Type> answer = new RoutingSlipDefinition<Type>(expression);
1926        addOutput(answer);
1927        return answer;
1928    }
1929    
1930    /**
1931     * <a href="http://camel.apache.org/routing-slip.html">Routing Slip EIP:</a>
1932     * Creates a routing slip allowing you to route a message consecutively through a series of processing
1933     * steps where the sequence of steps is not known at design time and can vary for each message.
1934     * <p/>
1935     * The list of URIs will be split based on the default delimiter {@link RoutingSlipDefinition#DEFAULT_DELIMITER}
1936     * <p/>
1937     * The route slip will be evaluated <i>once</i>, use {@link #dynamicRouter()} if you need even more dynamic routing.
1938     *
1939     * @return the expression clause to configure the expression to decide the destinations
1940     */
1941    public ExpressionClause<RoutingSlipDefinition<Type>> routingSlip() {
1942        RoutingSlipDefinition<Type> answer = new RoutingSlipDefinition<Type>();
1943        addOutput(answer);
1944        return ExpressionClause.createAndSetExpression(answer);
1945    }
1946
1947    /**
1948     * <a href="http://camel.apache.org/dynamic-router.html">Dynamic Router EIP:</a>
1949     * Creates a dynamic router allowing you to route a message consecutively through a series of processing
1950     * steps where the sequence of steps is not known at design time and can vary for each message.
1951     * <p/>
1952     * <br/><b>Important:</b> The expression will be invoked repeatedly until it returns <tt>null</tt>, so be sure it does that,
1953     * otherwise it will be invoked endlessly.
1954     *
1955     * @param expression  to decide the destinations, which will be invoked repeatedly
1956     *                    until it evaluates <tt>null</tt> to indicate no more destinations.
1957     * @return the builder
1958     */
1959    public DynamicRouterDefinition<Type> dynamicRouter(@AsEndpointUri Expression expression) {
1960        DynamicRouterDefinition<Type> answer = new DynamicRouterDefinition<Type>(expression);
1961        addOutput(answer);
1962        return answer;
1963    }
1964
1965    /**
1966     * <a href="http://camel.apache.org/dynamic-router.html">Dynamic Router EIP:</a>
1967     * Creates a dynamic router allowing you to route a message consecutively through a series of processing
1968     * steps where the sequence of steps is not known at design time and can vary for each message.
1969     * <p/>
1970     * <br/><b>Important:</b> The expression will be invoked repeatedly until it returns <tt>null</tt>, so be sure it does that,
1971     * otherwise it will be invoked endlessly.
1972     *
1973     * @return the expression clause to configure the expression to decide the destinations,
1974     * which will be invoked repeatedly until it evaluates <tt>null</tt> to indicate no more destinations.
1975     */
1976    @AsEndpointUri
1977    public ExpressionClause<DynamicRouterDefinition<Type>> dynamicRouter() {
1978        DynamicRouterDefinition<Type> answer = new DynamicRouterDefinition<Type>();
1979        addOutput(answer);
1980        return ExpressionClause.createAndSetExpression(answer);
1981    }
1982
1983    /**
1984     * <a href="http://camel.apache.org/sampling.html">Sampling Throttler</a>
1985     * Creates a sampling throttler allowing you to extract a sample of
1986     * exchanges from the traffic on a route. It is configured with a sampling
1987     * period, during which only a single exchange is allowed to pass through.
1988     * All other exchanges will be stopped.
1989     * <p/>
1990     * Default period is one second.
1991     *
1992     * @return the builder
1993     */
1994    public SamplingDefinition sample() {
1995        return sample(1, TimeUnit.SECONDS);
1996    }
1997
1998    /**
1999     * <a href="http://camel.apache.org/sampling.html">Sampling Throttler</a>
2000     * Creates a sampling throttler allowing you to extract a sample of exchanges
2001     * from the traffic through a route. It is configured with a sampling period
2002     * during which only a single exchange is allowed to pass through.
2003     * All other exchanges will be stopped.
2004     *
2005     * @param samplePeriod this is the sample interval, only one exchange is
2006     *            allowed through in this interval
2007     * @param unit this is the units for the samplePeriod e.g. Seconds
2008     * @return the builder
2009     */
2010    public SamplingDefinition sample(long samplePeriod, TimeUnit unit) {
2011        SamplingDefinition answer = new SamplingDefinition(samplePeriod, unit);
2012        addOutput(answer);
2013        return answer;
2014    }
2015
2016    /**
2017     * <a href="http://camel.apache.org/sampling.html">Sampling Throttler</a>
2018     * Creates a sampling throttler allowing you to extract a sample of exchanges
2019     * from the traffic through a route. It is configured with a sampling message frequency
2020     * during which only a single exchange is allowed to pass through.
2021     * All other exchanges will be stopped.
2022     *
2023     * @param messageFrequency this is the sample message frequency, only one exchange is 
2024     *              allowed through for this many messages received
2025     * @return the builder
2026     */
2027    public SamplingDefinition sample(long messageFrequency) {
2028        SamplingDefinition answer = new SamplingDefinition(messageFrequency);
2029        addOutput(answer);
2030        return answer;
2031    }
2032
2033    /**
2034     * <a href="http://camel.apache.org/splitter.html">Splitter EIP:</a>
2035     * Creates a splitter allowing you split a message into a number of pieces and process them individually.
2036     * <p>
2037     * This splitter responds with the original input message. You can use a custom {@link AggregationStrategy} to
2038     * control what to respond from the splitter.
2039     *
2040     * @return the expression clause builder for the expression on which to split
2041     */
2042    public ExpressionClause<SplitDefinition> split() {
2043        SplitDefinition answer = new SplitDefinition();
2044        addOutput(answer);
2045        return ExpressionClause.createAndSetExpression(answer);
2046    }
2047
2048    /**
2049     * <a href="http://camel.apache.org/splitter.html">Splitter EIP:</a>
2050     * Creates a splitter allowing you split a message into a number of pieces and process them individually.
2051     * <p>
2052     * This splitter responds with the original input message. You can use a custom {@link AggregationStrategy} to
2053     * control what to respond from the splitter.
2054     *
2055     * @param expression  the expression on which to split the message
2056     * @return the builder
2057     */
2058    public SplitDefinition split(Expression expression) {
2059        SplitDefinition answer = new SplitDefinition(expression);
2060        addOutput(answer);
2061        return answer;
2062    }
2063
2064    /**
2065     * <a href="http://camel.apache.org/splitter.html">Splitter EIP:</a>
2066     * Creates a splitter allowing you split a message into a number of pieces and process them individually.
2067     * <p>
2068     * The splitter responds with the answer produced by the given {@link AggregationStrategy}.
2069     *
2070     * @param expression  the expression on which to split
2071     * @param aggregationStrategy  the strategy used to aggregate responses for every part
2072     * @return the builder
2073     */
2074    public SplitDefinition split(Expression expression, AggregationStrategy aggregationStrategy) {
2075        SplitDefinition answer = new SplitDefinition(expression);
2076        addOutput(answer);
2077        answer.setAggregationStrategy(aggregationStrategy);
2078        return answer;
2079    }
2080
2081    /**
2082     * <a href="http://camel.apache.org/resequencer.html">Resequencer EIP:</a>
2083     * Creates a resequencer allowing you to reorganize messages based on some comparator.
2084     *
2085     * @return the expression clause for the expressions on which to compare messages in order
2086     */
2087    public ExpressionClause<ResequenceDefinition> resequence() {
2088        ResequenceDefinition answer = new ResequenceDefinition();
2089        ExpressionClause<ResequenceDefinition> clause = new ExpressionClause<ResequenceDefinition>(answer);
2090        answer.setExpression(clause);
2091        addOutput(answer);
2092        return clause;
2093    }
2094
2095    /**
2096     * <a href="http://camel.apache.org/resequencer.html">Resequencer EIP:</a>
2097     * Creates a resequencer allowing you to reorganize messages based on some comparator.
2098     *
2099     * @param expression the expression on which to compare messages in order
2100     * @return the builder
2101     */
2102    public ResequenceDefinition resequence(Expression expression) {
2103        ResequenceDefinition answer = new ResequenceDefinition(expression);
2104        addOutput(answer);
2105        return answer;
2106    }
2107
2108    /**
2109     * <a href="http://camel.apache.org/aggregator.html">Aggregator EIP:</a>
2110     * Creates an aggregator allowing you to combine a number of messages together into a single message.
2111     *
2112     * @return the expression clause to be used as builder to configure the correlation expression
2113     */
2114    public ExpressionClause<AggregateDefinition> aggregate() {
2115        AggregateDefinition answer = new AggregateDefinition();
2116        ExpressionClause<AggregateDefinition> clause = new ExpressionClause<AggregateDefinition>(answer);
2117        answer.setExpression(clause);
2118        addOutput(answer);
2119        return clause;
2120    }
2121
2122    /**
2123     * <a href="http://camel.apache.org/aggregator.html">Aggregator EIP:</a>
2124     * Creates an aggregator allowing you to combine a number of messages together into a single message.
2125     *
2126     * @param aggregationStrategy the strategy used for the aggregation
2127     * @return the expression clause to be used as builder to configure the correlation expression
2128     */
2129    public ExpressionClause<AggregateDefinition> aggregate(AggregationStrategy aggregationStrategy) {
2130        AggregateDefinition answer = new AggregateDefinition();
2131        ExpressionClause<AggregateDefinition> clause = new ExpressionClause<>(answer);
2132        answer.setExpression(clause);
2133        answer.setAggregationStrategy(aggregationStrategy);
2134        addOutput(answer);
2135        return clause;
2136    }
2137
2138    /**
2139     * <a href="http://camel.apache.org/aggregator.html">Aggregator EIP:</a>
2140     * Creates an aggregator allowing you to combine a number of messages together into a single message.
2141     *
2142     * @param correlationExpression the expression used to calculate the
2143     *                              correlation key. For a JMS message this could be the
2144     *                              expression <code>header("JMSDestination")</code> or
2145     *                              <code>header("JMSCorrelationID")</code>
2146     * @return the builder
2147     */
2148    public AggregateDefinition aggregate(Expression correlationExpression) {
2149        AggregateDefinition answer = new AggregateDefinition(correlationExpression);
2150        addOutput(answer);
2151        return answer;
2152    }
2153
2154    /**
2155     * <a href="http://camel.apache.org/aggregator.html">Aggregator EIP:</a>
2156     * Creates an aggregator allowing you to combine a number of messages together into a single message.
2157     *
2158     * @param correlationExpression the expression used to calculate the
2159     *                              correlation key. For a JMS message this could be the
2160     *                              expression <code>header("JMSDestination")</code> or
2161     *                              <code>header("JMSCorrelationID")</code>
2162     * @param aggregationStrategy the strategy used for the aggregation
2163     * @return the builder
2164     */
2165    public AggregateDefinition aggregate(Expression correlationExpression, AggregationStrategy aggregationStrategy) {
2166        AggregateDefinition answer = new AggregateDefinition(correlationExpression, aggregationStrategy);
2167        addOutput(answer);
2168        return answer;
2169    }
2170
2171    /**
2172     * <a href="http://camel.apache.org/delayer.html">Delayer EIP:</a>
2173     * Creates a delayer allowing you to delay the delivery of messages to some destination.
2174     *
2175     * @param delay  an expression to calculate the delay time in millis
2176     * @return the builder
2177     */
2178    public DelayDefinition delay(Expression delay) {
2179        DelayDefinition answer = new DelayDefinition(delay);
2180        addOutput(answer);
2181        return answer;
2182    }
2183
2184    /**
2185     * <a href="http://camel.apache.org/delayer.html">Delayer EIP:</a>
2186     * Creates a delayer allowing you to delay the delivery of messages to some destination.
2187     *
2188     * @return the expression clause to create the expression
2189     */
2190    public ExpressionClause<DelayDefinition> delay() {
2191        DelayDefinition answer = new DelayDefinition();
2192        addOutput(answer);
2193        return ExpressionClause.createAndSetExpression(answer);
2194    }
2195
2196    /**
2197     * <a href="http://camel.apache.org/delayer.html">Delayer EIP:</a>
2198     * Creates a delayer allowing you to delay the delivery of messages to some destination.
2199     *
2200     * @param delay  the delay in millis
2201     * @return the builder
2202     */
2203    public DelayDefinition delay(long delay) {
2204        return delay(ExpressionBuilder.constantExpression(delay));
2205    }
2206
2207    /**
2208     * <a href="http://camel.apache.org/throttler.html">Throttler EIP:</a>
2209     * Creates a throttler using a fluent builder. 
2210     *
2211     * @return the builder
2212     */
2213    public ExpressionClause<ThrottleDefinition> throttle() {
2214        ThrottleDefinition answer = new ThrottleDefinition();
2215        addOutput(answer);
2216
2217        return ExpressionClause.createAndSetExpression(answer);
2218    }
2219
2220    /**
2221     * <a href="http://camel.apache.org/throttler.html">Throttler EIP:</a>
2222     * Creates a throttler allowing you to ensure that a specific endpoint does not get overloaded,
2223     * or that we don't exceed an agreed SLA with some external service.
2224     * <p/>
2225     * Will default use a time period of 1 second, so setting the maximumRequestCount to eg 10
2226     * will default ensure at most 10 messages per second. 
2227     *
2228     * @param maximumRequestCount  the maximum messages 
2229     * @return the builder
2230     */
2231    public ThrottleDefinition throttle(long maximumRequestCount) {
2232        return throttle(ExpressionBuilder.constantExpression(maximumRequestCount));
2233    }
2234
2235    /**
2236     * <a href="http://camel.apache.org/throttler.html">Throttler EIP:</a>
2237     * Creates a throttler allowing you to ensure that a specific endpoint does not get overloaded,
2238     * or that we don't exceed an agreed SLA with some external service.
2239     * <p/>
2240     * Will default use a time period of 1 second, so setting the maximumRequestCount to eg 10
2241     * will default ensure at most 10 messages per second. 
2242     *
2243     * @param maximumRequestCount  an expression to calculate the maximum request count 
2244     * @return the builder
2245     */
2246    public ThrottleDefinition throttle(Expression maximumRequestCount) {
2247        ThrottleDefinition answer = new ThrottleDefinition(maximumRequestCount);
2248        addOutput(answer);
2249        return answer;
2250    }
2251    
2252    /**
2253     * <a href="http://camel.apache.org/loop.html">Loop EIP:</a>
2254     * Creates a loop allowing to process the a message a number of times and possibly process them
2255     * in a different way. Useful mostly for testing.
2256     *
2257     * @return the clause used to create the loop expression
2258     */
2259    public ExpressionClause<LoopDefinition> loop() {
2260        LoopDefinition loop = new LoopDefinition();
2261        addOutput(loop);
2262        return ExpressionClause.createAndSetExpression(loop);
2263    }
2264
2265    /**
2266     * <a href="http://camel.apache.org/loop.html">Loop EIP:</a>
2267     * Creates a loop allowing to process the a message a number of times and possibly process them
2268     * in a different way.
2269     *
2270     * @param expression the loop expression
2271     * @return the builder
2272     */
2273    public LoopDefinition loop(Expression expression) {
2274        LoopDefinition loop = new LoopDefinition(expression);
2275        addOutput(loop);
2276        return loop;
2277    }
2278
2279    /**
2280     * <a href="http://camel.apache.org/loop.html">Loop EIP:</a>
2281     * Creates a while loop allowing to process the a message while the predicate matches
2282     * and possibly process them in a different way.
2283     *
2284     * @param predicate the while loop predicate
2285     * @return the builder
2286     */
2287    public LoopDefinition loopDoWhile(@AsPredicate Predicate predicate) {
2288        LoopDefinition loop = new LoopDefinition(predicate);
2289        addOutput(loop);
2290        return loop;
2291    }
2292
2293    /**
2294     * <a href="http://camel.apache.org/loop.html">Loop EIP:</a>
2295     * Creates a loop allowing to process the a message a number of times and possibly process them
2296     * in a different way using a fluent builder.
2297     *
2298     * @return the builder
2299     */
2300    public ExpressionClause<LoopDefinition> loopDoWhile() {
2301        LoopDefinition loop = new LoopDefinition();
2302        loop.setDoWhile(true);
2303
2304        addOutput(loop);
2305
2306        return ExpressionClause.createAndSetExpression(loop);
2307    }
2308
2309    /**
2310     * <a href="http://camel.apache.org/loop.html">Loop EIP:</a>
2311     * Creates a loop allowing to process the a message a number of times and possibly process them
2312     * in a different way.
2313     *
2314     * @param count  the number of times
2315     * @return the builder
2316     */
2317    public LoopDefinition loop(int count) {
2318        LoopDefinition loop = new LoopDefinition(new ConstantExpression(Integer.toString(count)));
2319        addOutput(loop);
2320        return loop;
2321    }
2322
2323    /**
2324     * Sets the exception on the {@link org.apache.camel.Exchange}
2325     *
2326     * @param exception the exception to throw
2327     * @return the builder
2328     */
2329    public Type throwException(Exception exception) {
2330        ThrowExceptionDefinition answer = new ThrowExceptionDefinition();
2331        answer.setException(exception);
2332        addOutput(answer);
2333        return (Type) this;
2334    }
2335
2336    /**
2337     * Sets the exception on the {@link org.apache.camel.Exchange}
2338     *
2339     * @param type the exception class to use
2340     * @param message the given message as caused message (supports simple language)
2341     * @return the builder
2342     */
2343    public Type throwException(Class<? extends Exception> type, String message) {
2344        ThrowExceptionDefinition answer = new ThrowExceptionDefinition();
2345        answer.setExceptionClass(type);
2346        answer.setMessage(message);
2347        addOutput(answer);
2348        return (Type) this;
2349    }
2350
2351    /**
2352     * Marks the exchange for rollback only.
2353     * <p/>
2354     * Does <b>not</b> set any exception as opposed to {@link #rollback()} methods.
2355     *
2356     * @return the builder
2357     * @see #rollback()
2358     * @see #rollback(String)
2359     * @see #markRollbackOnlyLast()
2360     */
2361    public Type markRollbackOnly() {
2362        RollbackDefinition answer = new RollbackDefinition();
2363        answer.setMarkRollbackOnly(true);
2364        addOutput(answer);
2365        return (Type) this;
2366    }
2367
2368    /**
2369     * Marks the exchange for rollback only, but only for the last (current) transaction.
2370     * <p/>
2371     * A last rollback is used when you have nested transactions and only want the last local transaction to rollback,
2372     * where as the outer transaction can still be completed
2373     * <p/>
2374     * Does <b>not</b> set any exception as opposed to {@link #rollback()} methods.
2375     *
2376     * @return the builder
2377     * @see #rollback()
2378     * @see #rollback(String)
2379     * @see #markRollbackOnly()
2380     */
2381    public Type markRollbackOnlyLast() {
2382        RollbackDefinition answer = new RollbackDefinition();
2383        answer.setMarkRollbackOnlyLast(true);
2384        addOutput(answer);
2385        return (Type) this;
2386    }
2387
2388    /**
2389     * Marks the exchange for rollback only and sets an exception with a default message.
2390     * <p/>
2391     * This is done by setting a {@link org.apache.camel.RollbackExchangeException} on the Exchange
2392     * and mark it for rollback.
2393     *
2394     * @return the builder
2395     * @see #markRollbackOnly()
2396     */
2397    public Type rollback() {
2398        return rollback(null);
2399    }
2400
2401    /**
2402     * Marks the exchange for rollback and sets an exception with the provided message.
2403     * <p/>
2404     * This is done by setting a {@link org.apache.camel.RollbackExchangeException} on the Exchange
2405     * and mark it for rollback.
2406     *
2407     * @param message an optional message used for logging purpose why the rollback was triggered
2408     * @return the builder
2409     * @see #markRollbackOnly()
2410     */
2411    public Type rollback(String message) {
2412        RollbackDefinition answer = new RollbackDefinition(message);
2413        addOutput(answer);
2414        return (Type) this;
2415    }
2416
2417    /**
2418     * <a href="http://camel.apache.org/wiretap.html">WireTap EIP:</a>
2419     * Sends messages to all its child outputs; so that each processor and
2420     * destination gets a copy of the original message to avoid the processors
2421     * interfering with each other using {@link ExchangePattern#InOnly}.
2422     *
2423     * @param endpoint  the endpoint to wiretap to
2424     * @return the builder
2425     */
2426    public WireTapDefinition<Type> wireTap(Endpoint endpoint) {
2427        WireTapDefinition answer = new WireTapDefinition();
2428        answer.setUri(endpoint.getEndpointUri());
2429        addOutput(answer);
2430        return answer;
2431    }
2432
2433    /**
2434     * <a href="http://camel.apache.org/wiretap.html">WireTap EIP:</a>
2435     * Sends messages to all its child outputs; so that each processor and
2436     * destination gets a copy of the original message to avoid the processors
2437     * interfering with each other using {@link ExchangePattern#InOnly}.
2438     *
2439     * @param uri  the dynamic endpoint to wiretap to (resolved using simple language by default)
2440     * @return the builder
2441     */
2442    public WireTapDefinition<Type> wireTap(@AsEndpointUri String uri) {
2443        WireTapDefinition answer = new WireTapDefinition();
2444        answer.setUri(uri);
2445        addOutput(answer);
2446        return answer;
2447    }
2448
2449    /**
2450     * <a href="http://camel.apache.org/wiretap.html">WireTap EIP:</a>
2451     * Sends messages to all its child outputs; so that each processor and
2452     * destination gets a copy of the original message to avoid the processors
2453     * interfering with each other using {@link ExchangePattern#InOnly}.
2454     *
2455     * @param uri  the dynamic endpoint to wiretap to (resolved using simple language by default)
2456     * @param      executorService a custom {@link ExecutorService} to use as thread pool
2457     *             for sending tapped exchanges
2458     * @return the builder
2459     * @deprecated use the fluent builder from {@link WireTapDefinition}, will be removed in Camel 3.0
2460     */
2461    @Deprecated
2462    public WireTapDefinition<Type> wireTap(@AsEndpointUri String uri, ExecutorService executorService) {
2463        WireTapDefinition answer = new WireTapDefinition();
2464        answer.setUri(uri);
2465        answer.setExecutorService(executorService);
2466        addOutput(answer);
2467        return answer;
2468    }
2469
2470    /**
2471     * <a href="http://camel.apache.org/wiretap.html">WireTap EIP:</a>
2472     * Sends messages to all its child outputs; so that each processor and
2473     * destination gets a copy of the original message to avoid the processors
2474     * interfering with each other using {@link ExchangePattern#InOnly}.
2475     *
2476     * @param uri  the dynamic endpoint to wiretap to (resolved using simple language by default)
2477     * @param      executorServiceRef reference to lookup a custom {@link ExecutorService}
2478     *             to use as thread pool for sending tapped exchanges
2479     * @return the builder
2480     * @deprecated use the fluent builder from {@link WireTapDefinition}, will be removed in Camel 3.0
2481     */
2482    @Deprecated
2483    public WireTapDefinition<Type> wireTap(@AsEndpointUri String uri, String executorServiceRef) {
2484        WireTapDefinition answer = new WireTapDefinition();
2485        answer.setUri(uri);
2486        answer.setExecutorServiceRef(executorServiceRef);
2487        addOutput(answer);
2488        return answer;
2489    }
2490
2491    /**
2492     * <a href="http://camel.apache.org/wiretap.html">WireTap EIP:</a>
2493     * Sends a new {@link org.apache.camel.Exchange} to the destination
2494     * using {@link ExchangePattern#InOnly}.
2495     * <p/>
2496     * Will use a copy of the original Exchange which is passed in as argument
2497     * to the given expression
2498     *
2499     * @param uri  the dynamic endpoint to wiretap to (resolved using simple language by default)
2500     * @param body expression that creates the body to send
2501     * @return the builder
2502     * @deprecated use the fluent builder from {@link WireTapDefinition}, will be removed in Camel 3.0
2503     */
2504    @Deprecated
2505    public WireTapDefinition<Type> wireTap(@AsEndpointUri String uri, Expression body) {
2506        return wireTap(uri, true, body);
2507    }
2508
2509    /**
2510     * <a href="http://camel.apache.org/wiretap.html">WireTap EIP:</a>
2511     * Sends a new {@link org.apache.camel.Exchange} to the destination
2512     * using {@link ExchangePattern#InOnly}.
2513     *
2514     * @param uri  the dynamic endpoint to wiretap to (resolved using simple language by default)
2515     * @param copy whether or not use a copy of the original exchange or a new empty exchange
2516     * @return the builder
2517     * @deprecated use the fluent builder from {@link WireTapDefinition}, will be removed in Camel 3.0
2518     */
2519    @Deprecated
2520    public WireTapDefinition<Type> wireTap(@AsEndpointUri String uri, boolean copy) {
2521        WireTapDefinition answer = new WireTapDefinition();
2522        answer.setUri(uri);
2523        answer.setCopy(copy);
2524        addOutput(answer);
2525        return answer;
2526    }
2527
2528    /**
2529     * <a href="http://camel.apache.org/wiretap.html">WireTap EIP:</a>
2530     * Sends a new {@link org.apache.camel.Exchange} to the destination
2531     * using {@link ExchangePattern#InOnly}.
2532     *
2533     * @param uri  the dynamic endpoint to wiretap to (resolved using simple language by default)
2534     * @param copy whether or not use a copy of the original exchange or a new empty exchange
2535     * @param body expression that creates the body to send
2536     * @return the builder
2537     * @deprecated use the fluent builder from {@link WireTapDefinition}, will be removed in Camel 3.0
2538     */
2539    @Deprecated
2540    public WireTapDefinition<Type> wireTap(@AsEndpointUri String uri, boolean copy, Expression body) {
2541        WireTapDefinition answer = new WireTapDefinition();
2542        answer.setUri(uri);
2543        answer.setCopy(copy);
2544        answer.setNewExchangeExpression(new ExpressionSubElementDefinition(body));
2545        addOutput(answer);
2546        return answer;
2547    }
2548
2549    /**
2550     * <a href="http://camel.apache.org/wiretap.html">WireTap EIP:</a>
2551     * Sends a new {@link org.apache.camel.Exchange} to the destination
2552     * using {@link ExchangePattern#InOnly}.
2553     * <p/>
2554     * Will use a copy of the original Exchange which is passed in as argument
2555     * to the given processor
2556     *
2557     * @param uri  the dynamic endpoint to wiretap to (resolved using simple language by default)
2558     * @param processor  processor preparing the new exchange to send
2559     * @return the builder
2560     * @deprecated use the fluent builder from {@link WireTapDefinition}, will be removed in Camel 3.0
2561     */
2562    @Deprecated
2563    public WireTapDefinition<Type> wireTap(@AsEndpointUri String uri, Processor processor) {
2564        return wireTap(uri, true, processor);
2565    }
2566
2567    /**
2568     * <a href="http://camel.apache.org/wiretap.html">WireTap EIP:</a>
2569     * Sends a new {@link org.apache.camel.Exchange} to the destination
2570     * using {@link ExchangePattern#InOnly}.
2571     *
2572     * @param uri  the dynamic endpoint to wiretap to (resolved using simple language by default)
2573     * @param copy whether or not use a copy of the original exchange or a new empty exchange
2574     * @param processor  processor preparing the new exchange to send
2575     * @return the builder
2576     * @deprecated use the fluent builder from {@link WireTapDefinition}, will be removed in Camel 3.0
2577     */
2578    @Deprecated
2579    public WireTapDefinition<Type> wireTap(@AsEndpointUri String uri, boolean copy, Processor processor) {
2580        WireTapDefinition answer = new WireTapDefinition();
2581        answer.setUri(uri);
2582        answer.setCopy(copy);
2583        answer.setNewExchangeProcessor(processor);
2584        addOutput(answer);
2585        return answer;
2586    }
2587
2588    /**
2589     * Pushes the given block on the stack as current block
2590     *
2591     * @param block  the block
2592     */
2593    void pushBlock(Block block) {
2594        blocks.add(block);
2595    }
2596
2597    /**
2598     * Pops the block off the stack as current block
2599     *
2600     * @return the block
2601     */
2602    Block popBlock() {
2603        return blocks.isEmpty() ? null : blocks.removeLast();
2604    }
2605
2606    @SuppressWarnings("unchecked")
2607    public Type startupOrder(int startupOrder) {
2608        ProcessorDefinition<?> def = this;
2609
2610        RouteDefinition route = ProcessorDefinitionHelper.getRoute(def);
2611        if (route != null) {
2612            route.startupOrder(startupOrder);
2613        }
2614
2615        return (Type) this;
2616    }
2617
2618    /**
2619     * Stops continue routing the current {@link org.apache.camel.Exchange} and marks it as completed.
2620     *
2621     * @return the builder
2622     */
2623    @SuppressWarnings("unchecked")
2624    public Type stop() {
2625        StopDefinition stop = new StopDefinition();
2626        addOutput(stop);
2627        return (Type) this;
2628    }
2629
2630    /**
2631     * <a href="http://camel.apache.org/exception-clause.html">Exception clause</a>
2632     * for catching certain exceptions and handling them.
2633     *
2634     * @param exceptionType  the exception to catch
2635     * @return the exception builder to configure
2636     */
2637    public OnExceptionDefinition onException(Class<? extends Throwable> exceptionType) {
2638        OnExceptionDefinition answer = new OnExceptionDefinition(exceptionType);
2639        answer.setRouteScoped(true);
2640        addOutput(answer);
2641        return answer;
2642    }
2643
2644    /**
2645     * <a href="http://camel.apache.org/exception-clause.html">Exception clause</a>
2646     * for catching certain exceptions and handling them.
2647     *
2648     * @param exceptions list of exceptions to catch
2649     * @return the exception builder to configure
2650     */
2651    public OnExceptionDefinition onException(Class<? extends Throwable>... exceptions) {
2652        OnExceptionDefinition answer = new OnExceptionDefinition(Arrays.asList(exceptions));
2653        answer.setRouteScoped(true);
2654        addOutput(answer);
2655        return answer;
2656    }
2657
2658    /**
2659     * Apply a {@link Policy}.
2660     * <p/>
2661     * Policy can be used for transactional policies.
2662     *
2663     * @param policy  the policy to apply
2664     * @return the policy builder to configure
2665     */
2666    public PolicyDefinition policy(Policy policy) {
2667        PolicyDefinition answer = new PolicyDefinition(policy);
2668        addOutput(answer);
2669        return answer;
2670    }
2671
2672    /**
2673     * Apply a {@link Policy}.
2674     * <p/>
2675     * Policy can be used for transactional policies.
2676     *
2677     * @param ref  reference to lookup a policy in the registry
2678     * @return the policy builder to configure
2679     */
2680    public PolicyDefinition policy(String ref) {
2681        PolicyDefinition answer = new PolicyDefinition();
2682        answer.setRef(ref);
2683        addOutput(answer);
2684        return answer;
2685    }
2686
2687    /**
2688     * Marks this route as transacted and uses the default transacted policy found in the registry.
2689     *
2690     * @return the policy builder to configure
2691     */
2692    public TransactedDefinition transacted() {
2693        TransactedDefinition answer = new TransactedDefinition();
2694        addOutput(answer);
2695        return answer;
2696    }
2697
2698    /**
2699     * Marks this route as transacted.
2700     *
2701     * @param ref  reference to lookup a transacted policy in the registry
2702     * @return the policy builder to configure
2703     */
2704    public TransactedDefinition transacted(String ref) {
2705        TransactedDefinition answer = new TransactedDefinition();
2706        answer.setRef(ref);
2707        addOutput(answer);
2708        return answer;
2709    }
2710
2711    /**
2712     * Marks this route as participating to a saga.
2713     *
2714     * @return the saga definition
2715     */
2716    public SagaDefinition saga() {
2717        SagaDefinition answer = new SagaDefinition();
2718        addOutput(answer);
2719        return answer;
2720    }
2721
2722    // Transformers
2723    // -------------------------------------------------------------------------
2724
2725    /**
2726     * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
2727     * Adds the custom processor to this destination which could be a final
2728     * destination, or could be a transformation in a pipeline
2729     *
2730     * @param processor  the custom {@link Processor}
2731     * @return the builder
2732     */
2733    @SuppressWarnings("unchecked")
2734    public Type process(Processor processor) {
2735        ProcessDefinition answer = new ProcessDefinition(processor);
2736        addOutput(answer);
2737        return (Type) this;
2738    }
2739
2740    /**
2741     * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
2742     * Adds the custom processor reference to this destination which could be a final
2743     * destination, or could be a transformation in a pipeline
2744     *
2745     * @param ref   reference to a {@link Processor} to lookup in the registry
2746     * @return the builder
2747     */
2748    @SuppressWarnings("unchecked")
2749    public Type process(String ref) {
2750        ProcessDefinition answer = new ProcessDefinition();
2751        answer.setRef(ref);
2752        addOutput(answer);
2753        return (Type) this;
2754    }
2755
2756    /**
2757     * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
2758     * Adds the custom processor reference to this destination which could be a final
2759     * destination, or could be a transformation in a pipeline
2760     *
2761     * @param ref   reference to a {@link Processor} to lookup in the registry
2762     * @return the builder
2763     * @deprecated use {@link #process(String)}
2764     */
2765    @SuppressWarnings("unchecked")
2766    @Deprecated
2767    public Type processRef(String ref) {
2768        ProcessDefinition answer = new ProcessDefinition();
2769        answer.setRef(ref);
2770        addOutput(answer);
2771        return (Type) this;
2772    }
2773
2774    /**
2775     * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
2776     * Adds the custom processor using a fluent builder to this destination which could be a final
2777     * destination, or could be a transformation in a pipeline
2778     *
2779     * @return the builder
2780     */
2781    public ProcessClause<ProcessorDefinition<Type>> process() {
2782        ProcessClause<ProcessorDefinition<Type>> clause = new ProcessClause<>(this);
2783        ProcessDefinition answer = new ProcessDefinition(clause);
2784
2785        addOutput(answer);
2786        return clause;
2787    }
2788
2789    /**
2790     * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
2791     * Adds a bean which is invoked which could be a final destination, or could be a transformation in a pipeline
2792     *
2793     * @param bean  the bean to invoke, or a reference to a bean if the type is a String
2794     * @return the builder
2795     */
2796    @SuppressWarnings("unchecked")
2797    public Type bean(Object bean) {
2798        BeanDefinition answer = new BeanDefinition();
2799        if (bean instanceof String) {
2800            answer.setRef((String) bean);
2801        } else {
2802            answer.setBean(bean);
2803        }
2804        addOutput(answer);
2805        return (Type) this;
2806    }
2807
2808    /**
2809     * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
2810     * Adds a bean which is invoked which could be a final destination, or could be a transformation in a pipeline
2811     *
2812     * @param bean  the bean to invoke, or a reference to a bean if the type is a String
2813     * @param method  the method name to invoke on the bean (can be used to avoid ambiguity)
2814     * @return the builder
2815     */
2816    @SuppressWarnings("unchecked")
2817    public Type bean(Object bean, String method) {
2818        BeanDefinition answer = new BeanDefinition();
2819        if (bean instanceof String) {
2820            answer.setRef((String) bean);
2821        } else {
2822            answer.setBean(bean);
2823        }
2824        answer.setMethod(method);
2825        addOutput(answer);
2826        return (Type) this;
2827    }
2828    
2829    /**
2830     * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
2831     * Adds a bean which is invoked which could be a final destination, or could be a transformation in a pipeline
2832     *
2833     * @param bean  the bean to invoke, or a reference to a bean if the type is a String
2834     * @param cache  if enabled, Camel will cache the result of the first Registry look-up.
2835     *               Cache can be enabled if the bean in the Registry is defined as a singleton scope.
2836     *  the multi parameter
2837     * @return the builder
2838     */
2839    @SuppressWarnings("unchecked")
2840    public Type bean(Object bean, boolean cache) {
2841        BeanDefinition answer = new BeanDefinition();
2842        if (bean instanceof String) {
2843            answer.setRef((String) bean);
2844        } else {
2845            answer.setBean(bean);
2846        }
2847        answer.setCache(cache);
2848        addOutput(answer);
2849        return (Type) this;
2850    }
2851
2852    /**
2853     * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
2854     * Adds a bean which is invoked which could be a final destination, or could be a transformation in a pipeline
2855     *
2856     * @param bean  the bean to invoke, or a reference to a bean if the type is a String
2857     * @param method  the method name to invoke on the bean (can be used to avoid ambiguity)
2858     * @param cache  if enabled, Camel will cache the result of the first Registry look-up.
2859     *               Cache can be enabled if the bean in the Registry is defined as a singleton scope.
2860     *  the multi parameter
2861     * @return the builder
2862     */
2863    @SuppressWarnings("unchecked")
2864    public Type bean(Object bean, String method, boolean cache) {
2865        BeanDefinition answer = new BeanDefinition();
2866        if (bean instanceof String) {
2867            answer.setRef((String) bean);
2868        } else {
2869            answer.setBean(bean);
2870        }
2871        answer.setMethod(method);
2872        answer.setCache(cache);
2873        addOutput(answer);
2874        return (Type) this;
2875    }
2876
2877    /**
2878     * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
2879     * Adds a bean which is invoked which could be a final destination, or could be a transformation in a pipeline
2880     *
2881     * @param  beanType  the bean class, Camel will instantiate an object at runtime
2882     * @return the builder
2883     */
2884    @SuppressWarnings("unchecked")
2885    public Type bean(Class<?> beanType) {
2886        BeanDefinition answer = new BeanDefinition();
2887        answer.setBeanType(beanType);
2888        addOutput(answer);
2889        return (Type) this;
2890    }
2891
2892    /**
2893     * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
2894     * Adds a bean which is invoked which could be a final destination, or could be a transformation in a pipeline
2895     *
2896     * @param  beanType  the bean class, Camel will instantiate an object at runtime
2897     * @param method  the method name to invoke on the bean (can be used to avoid ambiguity)
2898     * @return the builder
2899     */
2900    @SuppressWarnings("unchecked")
2901    public Type bean(Class<?> beanType, String method) {
2902        BeanDefinition answer = new BeanDefinition();
2903        answer.setBeanType(beanType);
2904        answer.setMethod(method);
2905        addOutput(answer);
2906        return (Type) this;
2907    }
2908    
2909    /**
2910     * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
2911     * Adds a bean which is invoked which could be a final destination, or could be a transformation in a pipeline
2912     *
2913     * @param beanType  the bean class, Camel will instantiate an object at runtime
2914     * @param method  the method name to invoke on the bean (can be used to avoid ambiguity)
2915     * @param multiParameterArray if it is true, camel will treat the message body as an object array which holds
2916     *  the multi parameter 
2917     * @return the builder
2918     * @deprecated the option multiParameterArray is deprecated
2919     */
2920    @SuppressWarnings("unchecked")
2921    @Deprecated
2922    public Type bean(Class<?> beanType, String method, boolean multiParameterArray) {
2923        BeanDefinition answer = new BeanDefinition();
2924        answer.setBeanType(beanType);
2925        answer.setMethod(method);
2926        answer.setMultiParameterArray(multiParameterArray);
2927        addOutput(answer);
2928        return (Type) this;
2929    }
2930
2931    /**
2932     * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
2933     * Adds a bean which is invoked which could be a final destination, or could be a transformation in a pipeline
2934     *
2935     * @param beanType  the bean class, Camel will instantiate an object at runtime
2936     * @param method  the method name to invoke on the bean (can be used to avoid ambiguity)
2937     * @param multiParameterArray if it is true, camel will treat the message body as an object array which holds
2938     *  the multi parameter
2939     * @param cache  if enabled, Camel will cache the result of the first Registry look-up.
2940     *               Cache can be enabled if the bean in the Registry is defined as a singleton scope.
2941     * @return the builder
2942     * @deprecated the option multiParameterArray is deprecated
2943     */
2944    @SuppressWarnings("unchecked")
2945    @Deprecated
2946    public Type bean(Class<?> beanType, String method, boolean multiParameterArray, boolean cache) {
2947        BeanDefinition answer = new BeanDefinition();
2948        answer.setBeanType(beanType);
2949        answer.setMethod(method);
2950        answer.setMultiParameterArray(multiParameterArray);
2951        answer.setCache(cache);
2952        addOutput(answer);
2953        return (Type) this;
2954    }
2955
2956    /**
2957     * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
2958     * Adds a bean which is invoked which could be a final destination, or could be a transformation in a pipeline
2959     *
2960     * @param ref  reference to a bean to lookup in the registry
2961     * @return the builder
2962     * @deprecated use {@link #bean(Object)}
2963     */
2964    @SuppressWarnings("unchecked")
2965    @Deprecated
2966    public Type beanRef(String ref) {
2967        BeanDefinition answer = new BeanDefinition(ref);
2968        addOutput(answer);
2969        return (Type) this;
2970    }
2971    
2972    /**
2973     * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
2974     * Adds a bean which is invoked which could be a final destination, or could be a transformation in a pipeline
2975     *
2976     * @param ref  reference to a bean to lookup in the registry
2977     * @param method  the method name to invoke on the bean (can be used to avoid ambiguity)
2978     * @return the builder
2979     * @deprecated use {@link #bean(Object, String)}
2980     */
2981    @SuppressWarnings("unchecked")
2982    @Deprecated
2983    public Type beanRef(String ref, String method) {
2984        BeanDefinition answer = new BeanDefinition(ref, method);
2985        addOutput(answer);
2986        return (Type) this;
2987    }
2988
2989    /**
2990     * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
2991     * Adds a bean which is invoked which could be a final destination, or could be a transformation in a pipeline
2992     *
2993     * @param ref  reference to a bean to lookup in the registry
2994     * @param cache  if enabled, Camel will cache the result of the first Registry look-up.
2995     *               Cache can be enabled if the bean in the Registry is defined as a singleton scope.
2996     * @return the builder
2997     * @deprecated use {@link #bean(Object, String, boolean)}
2998     */
2999    @SuppressWarnings("unchecked")
3000    @Deprecated
3001    public Type beanRef(String ref, boolean cache) {
3002        BeanDefinition answer = new BeanDefinition(ref);
3003        answer.setCache(cache);
3004        addOutput(answer);
3005        return (Type) this;
3006    }
3007    
3008    /**
3009     * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
3010     * Adds a bean which is invoked which could be a final destination, or could be a transformation in a pipeline
3011     *
3012     * @param ref  reference to a bean to lookup in the registry
3013     * @param method  the method name to invoke on the bean (can be used to avoid ambiguity)
3014     * @param cache  if enabled, Camel will cache the result of the first Registry look-up.
3015     *               Cache can be enabled if the bean in the Registry is defined as a singleton scope.
3016     * @return the builder
3017     * @deprecated use {@link #bean(Object, String, boolean)}
3018     */
3019    @SuppressWarnings("unchecked")
3020    @Deprecated
3021    public Type beanRef(String ref, String method, boolean cache) {
3022        BeanDefinition answer = new BeanDefinition(ref, method);
3023        answer.setCache(cache);
3024        addOutput(answer);
3025        return (Type) this;
3026    }
3027
3028    /**
3029     * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
3030     * Adds a bean which is invoked which could be a final destination, or could be a transformation in a pipeline
3031     *
3032     * @param ref  reference to a bean to lookup in the registry
3033     * @param method  the method name to invoke on the bean (can be used to avoid ambiguity)
3034     * @param cache  if enabled, Camel will cache the result of the first Registry look-up.
3035     *               Cache can be enabled if the bean in the Registry is defined as a singleton scope.
3036     * @param multiParameterArray if it is true, camel will treat the message body as an object array which holds
3037     *               the multi parameter 
3038     * @return the builder
3039     * @deprecated the option multiParameterArray is deprecated
3040     */
3041    @SuppressWarnings("unchecked")
3042    @Deprecated
3043    public Type beanRef(String ref, String method, boolean cache, boolean multiParameterArray) {
3044        BeanDefinition answer = new BeanDefinition(ref, method);
3045        answer.setCache(cache);
3046        answer.setMultiParameterArray(multiParameterArray);
3047        addOutput(answer);
3048        return (Type) this;
3049    }
3050
3051    /**
3052     * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
3053     * Adds a processor which sets the body on the IN message
3054     *
3055     * @return a expression builder clause to set the body
3056     */
3057    public ExpressionClause<ProcessorDefinition<Type>> setBody() {
3058        ExpressionClause<ProcessorDefinition<Type>> clause = new ExpressionClause<ProcessorDefinition<Type>>(this);
3059        SetBodyDefinition answer = new SetBodyDefinition(clause);
3060        addOutput(answer);
3061        return clause;
3062    }
3063
3064    /**
3065     * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
3066     * Adds a processor which sets the body on the IN message
3067     *
3068     * @param expression   the expression used to set the body
3069     * @return the builder
3070     */
3071    @SuppressWarnings("unchecked")
3072    public Type setBody(Expression expression) {
3073        SetBodyDefinition answer = new SetBodyDefinition(expression);
3074        addOutput(answer);
3075        return (Type) this;
3076    }
3077
3078    /**
3079     * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
3080     * Adds a processor which sets the body on the IN message
3081     *
3082     * @param supplier   the supplier that provides a value to the IN message body
3083     * @return the builder
3084     */
3085    public <Result> Type setBody(Supplier<Result> supplier) {
3086        SetBodyDefinition answer = new SetBodyDefinition(new ExpressionAdapter() {
3087            @Override
3088            public Result evaluate(Exchange exchange) {
3089                return supplier.get();
3090            }
3091        });
3092        addOutput(answer);
3093        return (Type) this;
3094    }
3095
3096    /**
3097     * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
3098     * Adds a processor which sets the body on the IN message
3099     *
3100     * @param function   the function that provides a value to the IN message body
3101     * @return the builder
3102     */
3103    public <Result> Type setBody(Function<Exchange, Result> function) {
3104        SetBodyDefinition answer = new SetBodyDefinition(new ExpressionAdapter() {
3105            @Override
3106            public Result evaluate(Exchange exchange) {
3107                return function.apply(exchange);
3108            }
3109        });
3110        addOutput(answer);
3111        return (Type) this;
3112    }
3113
3114    /**
3115     * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
3116     * Adds a processor which sets the body on the OUT message
3117     *
3118     * @param expression   the expression used to set the body
3119     * @return the builder
3120     */
3121    @SuppressWarnings("unchecked")
3122    public Type transform(Expression expression) {
3123        TransformDefinition answer = new TransformDefinition(expression);
3124        addOutput(answer);
3125        return (Type) this;
3126    }
3127
3128    /**
3129     * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
3130     * Adds a processor which sets the body on the OUT message
3131     *
3132     * @return a expression builder clause to set the body
3133     */
3134    public ExpressionClause<ProcessorDefinition<Type>> transform() {
3135        ExpressionClause<ProcessorDefinition<Type>> clause =
3136            new ExpressionClause<ProcessorDefinition<Type>>((ProcessorDefinition<Type>) this);
3137        TransformDefinition answer = new TransformDefinition(clause);
3138        addOutput(answer);
3139        return clause;
3140    }
3141
3142    /**
3143     * Executes a script (do not change the message body).
3144     *
3145     * @param expression   the expression used as the script.
3146     * @return the builder
3147     */
3148    @SuppressWarnings("unchecked")
3149    public Type script(Expression expression) {
3150        ScriptDefinition answer = new ScriptDefinition(expression);
3151        addOutput(answer);
3152        return (Type) this;
3153    }
3154
3155    /**
3156     * Executes a script (do not change the message body).
3157     *
3158     * @return a expression builder clause to use as script.
3159     */
3160    public ExpressionClause<ProcessorDefinition<Type>> script() {
3161        ExpressionClause<ProcessorDefinition<Type>> clause =
3162                new ExpressionClause<ProcessorDefinition<Type>>((ProcessorDefinition<Type>) this);
3163        ScriptDefinition answer = new ScriptDefinition(clause);
3164        addOutput(answer);
3165        return clause;
3166    }
3167
3168    /**
3169     * Adds a processor which sets the body on the FAULT message
3170     *
3171     * @param expression   the expression used to set the body
3172     * @return the builder
3173     */
3174    public Type setFaultBody(Expression expression) {
3175        return process(ProcessorBuilder.setFaultBody(expression));
3176    }
3177
3178    /**
3179     * Adds a processor which sets the header on the IN message
3180     *
3181     * @param name  the header name
3182     * @return a expression builder clause to set the header
3183     */
3184    public ExpressionClause<ProcessorDefinition<Type>> setHeader(String name) {
3185        ExpressionClause<ProcessorDefinition<Type>> clause = new ExpressionClause<ProcessorDefinition<Type>>(this);
3186        SetHeaderDefinition answer = new SetHeaderDefinition(name, clause);
3187        addOutput(answer);
3188        return clause;
3189    }
3190
3191    /**
3192     * Adds a processor which sets the header on the IN message
3193     *
3194     * @param name  the header name
3195     * @param expression  the expression used to set the header
3196     * @return the builder
3197     */
3198    @SuppressWarnings("unchecked")
3199    public Type setHeader(String name, Expression expression) {
3200        SetHeaderDefinition answer = new SetHeaderDefinition(name, expression);
3201        addOutput(answer);
3202        return (Type) this;
3203    }
3204
3205    /**
3206     * Adds a processor which sets the header on the IN message
3207     *
3208     * @param name  the header name
3209     * @param supplier the supplier used to set the header
3210     * @return the builder
3211     */
3212    @SuppressWarnings("unchecked")
3213    public Type setHeader(String name, final Supplier<Object> supplier) {
3214        SetHeaderDefinition answer = new SetHeaderDefinition(name, new ExpressionAdapter() {
3215            @Override
3216            public Object evaluate(Exchange exchange) {
3217                return supplier.get();
3218            }
3219        });
3220
3221        addOutput(answer);
3222        return (Type) this;
3223    }
3224
3225    /**
3226     * Adds a processor which sets the header on the OUT message
3227     *
3228     * @param name  the header name
3229     * @return a expression builder clause to set the header
3230     * @deprecated use {@link #setHeader(String)}
3231     */
3232    @Deprecated
3233    public ExpressionClause<ProcessorDefinition<Type>> setOutHeader(String name) {
3234        ExpressionClause<ProcessorDefinition<Type>> clause = new ExpressionClause<ProcessorDefinition<Type>>(this);
3235        SetOutHeaderDefinition answer = new SetOutHeaderDefinition(name, clause);
3236        addOutput(answer);
3237        return clause;
3238    }
3239
3240    /**
3241     * Adds a processor which sets the header on the OUT message
3242     *
3243     * @param name  the header name
3244     * @param expression  the expression used to set the header
3245     * @return the builder
3246     * @deprecated use {@link #setHeader(String, org.apache.camel.Expression)}
3247     */
3248    @SuppressWarnings("unchecked")
3249    @Deprecated
3250    public Type setOutHeader(String name, Expression expression) {
3251        SetOutHeaderDefinition answer = new SetOutHeaderDefinition(name, expression);
3252        addOutput(answer);
3253        return (Type) this;
3254    }
3255
3256    /**
3257     * Adds a processor which sets the header on the FAULT message
3258     *
3259     * @param name  the header name
3260     * @param expression  the expression used to set the header
3261     * @return the builder
3262     * @deprecated use {@link #setHeader(String, org.apache.camel.Expression)}
3263     */
3264    @Deprecated
3265    public Type setFaultHeader(String name, Expression expression) {
3266        return process(ProcessorBuilder.setFaultHeader(name, expression));
3267    }
3268
3269    /**
3270     * Adds a processor which sets the exchange property
3271     *
3272     * @param name  the property name
3273     * @param expression  the expression used to set the property
3274     * @return the builder
3275     */
3276    @SuppressWarnings("unchecked")
3277    public Type setProperty(String name, Expression expression) {
3278        SetPropertyDefinition answer = new SetPropertyDefinition(name, expression);
3279        addOutput(answer);
3280        return (Type) this;
3281    }
3282
3283    /**
3284     * Adds a processor which sets the exchange property
3285     *
3286     * @param name  the property name
3287     * @return a expression builder clause to set the property
3288     */
3289    public ExpressionClause<ProcessorDefinition<Type>> setProperty(String name) {
3290        ExpressionClause<ProcessorDefinition<Type>> clause = new ExpressionClause<ProcessorDefinition<Type>>(this);
3291        SetPropertyDefinition answer = new SetPropertyDefinition(name, clause);
3292        addOutput(answer);
3293        return clause;
3294    }
3295
3296    /**
3297     * Adds a processor which removes the header on the IN message
3298     *
3299     * @param name  the header name
3300     * @return the builder
3301     */
3302    @SuppressWarnings("unchecked")
3303    public Type removeHeader(String name) {
3304        RemoveHeaderDefinition answer = new RemoveHeaderDefinition(name);
3305        addOutput(answer);
3306        return (Type) this;
3307    }
3308
3309    /**
3310     * Adds a processor which removes the headers on the IN message
3311     *
3312     * @param pattern  a pattern to match header names to be removed
3313     * @return the builder
3314     */
3315    @SuppressWarnings("unchecked")
3316    public Type removeHeaders(String pattern) {
3317        RemoveHeadersDefinition answer = new RemoveHeadersDefinition(pattern);
3318        addOutput(answer);
3319        return (Type) this;
3320    }
3321
3322    /**
3323     * Adds a processor which removes the headers on the IN message
3324     *
3325     * @param pattern  a pattern to match header names to be removed
3326     * @param excludePatterns one or more pattern of header names that should be excluded (= preserved)
3327     * @return the builder
3328     */
3329    @SuppressWarnings("unchecked")
3330    public Type removeHeaders(String pattern, String... excludePatterns) {
3331        RemoveHeadersDefinition answer = new RemoveHeadersDefinition(pattern, excludePatterns);
3332        addOutput(answer);
3333        return (Type) this;
3334    }
3335
3336    /**
3337     * Adds a processor which removes the header on the FAULT message
3338     *
3339     * @param name  the header name
3340     * @return the builder
3341     * @deprecated will be removed in the near future. Instead use {@link #removeHeader(String)}
3342     */
3343    @Deprecated
3344    public Type removeFaultHeader(String name) {
3345        return process(ProcessorBuilder.removeFaultHeader(name));
3346    }
3347
3348    /**
3349     * Adds a processor which removes the exchange property
3350     *
3351     * @param name  the property name
3352     * @return the builder
3353     */
3354    @SuppressWarnings("unchecked")
3355    public Type removeProperty(String name) {
3356        RemovePropertyDefinition answer = new RemovePropertyDefinition(name);
3357        addOutput(answer);
3358        return (Type) this;
3359    }
3360    
3361    /**
3362     * Adds a processor which removes the properties in the exchange
3363     *
3364     * @param pattern a pattern to match properties names to be removed
3365     * @return the builder
3366     */
3367    @SuppressWarnings("unchecked")
3368    public Type removeProperties(String pattern) {
3369        RemovePropertiesDefinition answer = new RemovePropertiesDefinition(pattern);
3370        addOutput(answer);
3371        return (Type) this;
3372    }
3373
3374    /**
3375     * Adds a processor which removes the properties in the exchange
3376     *
3377     * @param pattern a pattern to match properties names to be removed
3378     * @param excludePatterns one or more pattern of properties names that should be excluded (= preserved)
3379     * @return the builder
3380     */
3381    @SuppressWarnings("unchecked")
3382    public Type removeProperties(String pattern, String... excludePatterns) {
3383        RemovePropertiesDefinition answer = new RemovePropertiesDefinition(pattern, excludePatterns);
3384        addOutput(answer);
3385        return (Type) this;
3386    }
3387
3388    /**
3389     * Converts the IN message body to the specified type
3390     *
3391     * @param type the type to convert to
3392     * @return the builder
3393     */
3394    @SuppressWarnings("unchecked")
3395    public Type convertBodyTo(Class<?> type) {
3396        addOutput(new ConvertBodyDefinition(type));
3397        return (Type) this;
3398    }
3399    
3400    /**
3401     * Converts the IN message body to the specified type
3402     *
3403     * @param type the type to convert to
3404     * @param charset the charset to use by type converters (not all converters support specifc charset)
3405     * @return the builder
3406     */
3407    @SuppressWarnings("unchecked")
3408    public Type convertBodyTo(Class<?> type, String charset) {
3409        addOutput(new ConvertBodyDefinition(type, charset));
3410        return (Type) this;
3411    }
3412
3413    /**
3414     * Sorts the expression using a default sorting based on toString representation.
3415     *
3416     * @param expression  the expression, must be convertable to {@link List}
3417     * @return the builder
3418     */
3419    public Type sort(Expression expression) {
3420        return sort(expression, null);
3421    }
3422
3423    /**
3424     * Sorts the expression using the given comparator
3425     *
3426     * @param expression  the expression, must be convertable to {@link List}
3427     * @param comparator  the comparator to use for sorting
3428     * @return the builder
3429     */
3430    @SuppressWarnings("unchecked")
3431    public <T> Type sort(Expression expression, Comparator<T> comparator) {
3432        addOutput(new SortDefinition<T>(expression, comparator));
3433        return (Type) this;
3434    }
3435
3436    /**
3437     * Sorts the expression
3438     *
3439     * @return the builder
3440     */
3441    public <T> ExpressionClause<SortDefinition<T>> sort() {
3442        SortDefinition<T> answer = new SortDefinition<T>();
3443        addOutput(answer);
3444        return ExpressionClause.createAndSetExpression(answer);
3445    }
3446
3447    /**
3448     * The <a href="http://camel.apache.org/claim-check.html">Claim Check EIP</a>
3449     * allows you to replace message content with a claim check (a unique key),
3450     * which can be used to retrieve the message content at a later time.
3451     */
3452    public ClaimCheckDefinition claimCheck() {
3453        ClaimCheckDefinition answer = new ClaimCheckDefinition();
3454        addOutput(answer);
3455        return answer;
3456    }
3457
3458    /**
3459     * The <a href="http://camel.apache.org/claim-check.html">Claim Check EIP</a>
3460     * allows you to replace message content with a claim check (a unique key),
3461     * which can be used to retrieve the message content at a later time.
3462     *
3463     * @param operation the claim check operation to use.
3464     */
3465    public Type claimCheck(ClaimCheckOperation operation) {
3466        ClaimCheckDefinition answer = new ClaimCheckDefinition();
3467        answer.setOperation(operation);
3468        addOutput(answer);
3469        return (Type) this;
3470    }
3471
3472    /**
3473     * The <a href="http://camel.apache.org/claim-check.html">Claim Check EIP</a>
3474     * allows you to replace message content with a claim check (a unique key),
3475     * which can be used to retrieve the message content at a later time.
3476     *
3477     * @param operation the claim check operation to use.
3478     * @param key       the unique key to use for the get and set operations, can be <tt>null</tt> for push/pop operations
3479     */
3480    public Type claimCheck(ClaimCheckOperation operation, String key) {
3481        return claimCheck(operation, key, null);
3482    }
3483
3484    /**
3485     * The <a href="http://camel.apache.org/claim-check.html">Claim Check EIP</a>
3486     * allows you to replace message content with a claim check (a unique key),
3487     * which can be used to retrieve the message content at a later time.
3488     *
3489     * @param operation the claim check operation to use.
3490     * @param key       the unique key to use for the get and set operations, can be <tt>null</tt> for push/pop operations
3491     * @param filter    describes what data to include/exclude when merging data back when using get or pop operations.
3492     */
3493    public Type claimCheck(ClaimCheckOperation operation, String key, String filter) {
3494        ClaimCheckDefinition answer = new ClaimCheckDefinition();
3495        answer.setOperation(operation);
3496        answer.setKey(key);
3497        answer.setFilter(filter);
3498        addOutput(answer);
3499        return (Type) this;
3500    }
3501
3502    /**
3503     * The <a href="http://camel.apache.org/content-enricher.html">Content Enricher EIP</a>
3504     * enriches an exchange with additional data obtained from a <code>resourceUri</code>.
3505     * <p/>
3506     * The difference between this and {@link #pollEnrich(String)} is that this uses a producer
3507     * to obatin the additional data, where as pollEnrich uses a polling consumer.
3508     *
3509     * @param resourceUri           URI of resource endpoint for obtaining additional data.
3510     * @return the builder
3511     * @see org.apache.camel.processor.Enricher
3512     */
3513    public Type enrich(@AsEndpointUri String resourceUri) {
3514        return enrich(resourceUri, null);
3515    }
3516
3517    /**
3518     * The <a href="http://camel.apache.org/content-enricher.html">Content Enricher EIP</a>
3519     * enriches an exchange with additional data obtained from a <code>resourceUri</code>.
3520     * 
3521     * @param resourceUri           URI of resource endpoint for obtaining additional data.
3522     * @param aggregationStrategy   aggregation strategy to aggregate input data and additional data.
3523     * @return the builder
3524     * @see org.apache.camel.processor.Enricher
3525     */
3526    public Type enrich(@AsEndpointUri String resourceUri, AggregationStrategy aggregationStrategy) {
3527        return enrich(resourceUri, aggregationStrategy, false);
3528    }
3529
3530    /**
3531     * The <a href="http://camel.apache.org/content-enricher.html">Content Enricher EIP</a>
3532     * enriches an exchange with additional data obtained from a <code>resourceUri</code> and 
3533     * with an aggregation strategy created using a fluent builder.
3534     *     
3535     * <blockquote><pre>{@code
3536     * fom("direct:start")
3537     *     .enrichWith("direct:resource")
3538     *         .body(String.class, (o, n) -> n + o);
3539     * }</pre></blockquote>
3540     *
3541     * @param resourceUri           URI of resource endpoint for obtaining additional data.
3542     * @return the builder
3543     * @see org.apache.camel.processor.Enricher
3544     */
3545    public EnrichClause<ProcessorDefinition<Type>> enrichWith(@AsEndpointUri String resourceUri) {
3546        EnrichClause<ProcessorDefinition<Type>> clause = new EnrichClause<>(this);
3547        enrich(resourceUri, clause);
3548        return clause;
3549    }
3550
3551    /**
3552     * The <a href="http://camel.apache.org/content-enricher.html">Content Enricher EIP</a>
3553     * enriches an exchange with additional data obtained from a <code>resourceUri</code> and 
3554     * with an aggregation strategy created using a fluent builder.
3555     */
3556    public EnrichClause<ProcessorDefinition<Type>> enrichWith(@AsEndpointUri String resourceUri, boolean aggregateOnException) {
3557        EnrichClause<ProcessorDefinition<Type>> clause = new EnrichClause<>(this);
3558        enrich(resourceUri, clause, aggregateOnException, false);
3559        return clause;
3560    }
3561
3562    /**
3563     * The <a href="http://camel.apache.org/content-enricher.html">Content Enricher EIP</a>
3564     * enriches an exchange with additional data obtained from a <code>resourceUri</code> and 
3565     * with an aggregation strategy created using a fluent builder.
3566     */
3567    public EnrichClause<ProcessorDefinition<Type>> enrichWith(@AsEndpointUri String resourceUri, boolean aggregateOnException, boolean shareUnitOfWork) {
3568        EnrichClause<ProcessorDefinition<Type>> clause = new EnrichClause<>(this);
3569        enrich(resourceUri, clause, aggregateOnException, shareUnitOfWork);
3570        return clause;
3571    }
3572
3573    /**
3574     * The <a href="http://camel.apache.org/content-enricher.html">Content Enricher EIP</a>
3575     * enriches an exchange with additional data obtained from a <code>resourceUri</code>.
3576     *
3577     * @param resourceUri           URI of resource endpoint for obtaining additional data.
3578     * @param aggregationStrategy   aggregation strategy to aggregate input data and additional data.
3579     * @param aggregateOnException   whether to call {@link org.apache.camel.processor.aggregate.AggregationStrategy#aggregate(org.apache.camel.Exchange, org.apache.camel.Exchange)} if
3580     *                               an exception was thrown.
3581     * @return the builder
3582     * @see org.apache.camel.processor.Enricher
3583     */
3584    public Type enrich(@AsEndpointUri String resourceUri, AggregationStrategy aggregationStrategy, boolean aggregateOnException) {
3585        return enrich(resourceUri, aggregationStrategy, aggregateOnException, false);
3586    }
3587
3588    /**
3589     * The <a href="http://camel.apache.org/content-enricher.html">Content Enricher EIP</a>
3590     * enriches an exchange with additional data obtained from a <code>resourceUri</code>.
3591     *
3592     * @param resourceUri           URI of resource endpoint for obtaining additional data.
3593     * @param aggregationStrategy   aggregation strategy to aggregate input data and additional data.
3594     * @param aggregateOnException  whether to call {@link org.apache.camel.processor.aggregate.AggregationStrategy#aggregate(org.apache.camel.Exchange, org.apache.camel.Exchange)} if
3595     *                              an exception was thrown.
3596     * @param shareUnitOfWork       whether to share unit of work
3597     * @return the builder
3598     * @see org.apache.camel.processor.Enricher
3599     */
3600    @SuppressWarnings("unchecked")
3601    public Type enrich(@AsEndpointUri String resourceUri, AggregationStrategy aggregationStrategy, boolean aggregateOnException, boolean shareUnitOfWork) {
3602        EnrichDefinition answer = new EnrichDefinition();
3603        answer.setExpression(new ConstantExpression(resourceUri));
3604        answer.setAggregationStrategy(aggregationStrategy);
3605        answer.setAggregateOnException(aggregateOnException);
3606        answer.setShareUnitOfWork(shareUnitOfWork);
3607        addOutput(answer);
3608        return (Type) this;
3609    }
3610
3611    /**
3612     * The <a href="http://camel.apache.org/content-enricher.html">Content Enricher EIP</a>
3613     * enriches an exchange with additional data obtained from a <code>resourceUri</code>.
3614     * <p/>
3615     * The difference between this and {@link #pollEnrich(String)} is that this uses a producer
3616     * to obtain the additional data, where as pollEnrich uses a polling consumer.
3617     *
3618     * @param resourceRef            Reference of resource endpoint for obtaining additional data.
3619     * @param aggregationStrategyRef Reference of aggregation strategy to aggregate input data and additional data.
3620     * @return the builder
3621     * @see org.apache.camel.processor.Enricher
3622     * @deprecated use enrich with a <tt>ref:id</tt> as the resourceUri parameter.
3623     */
3624    @Deprecated
3625    public Type enrichRef(String resourceRef, String aggregationStrategyRef) {
3626        return enrichRef(resourceRef, aggregationStrategyRef, false);
3627    }
3628
3629    /**
3630     * The <a href="http://camel.apache.org/content-enricher.html">Content Enricher EIP</a>
3631     * enriches an exchange with additional data obtained from a <code>resourceUri</code>.
3632     * <p/>
3633     * The difference between this and {@link #pollEnrich(String)} is that this uses a producer
3634     * to obtain the additional data, where as pollEnrich uses a polling consumer.
3635     *
3636     * @param resourceRef            Reference of resource endpoint for obtaining additional data.
3637     * @param aggregationStrategyRef Reference of aggregation strategy to aggregate input data and additional data.
3638     * @param aggregateOnException   whether to call {@link org.apache.camel.processor.aggregate.AggregationStrategy#aggregate(org.apache.camel.Exchange, org.apache.camel.Exchange)} if
3639     *                               an exception was thrown.
3640     * @return the builder
3641     * @see org.apache.camel.processor.Enricher
3642     * @deprecated use enrich with a <tt>ref:id</tt> as the resourceUri parameter.
3643     */
3644    @Deprecated
3645    public Type enrichRef(String resourceRef, String aggregationStrategyRef, boolean aggregateOnException) {
3646        return enrichRef(resourceRef, aggregationStrategyRef, false, false);
3647    }
3648
3649    /**
3650     * The <a href="http://camel.apache.org/content-enricher.html">Content Enricher EIP</a>
3651     * enriches an exchange with additional data obtained from a <code>resourceUri</code>.
3652     * <p/>
3653     * The difference between this and {@link #pollEnrich(String)} is that this uses a producer
3654     * to obtain the additional data, where as pollEnrich uses a polling consumer.
3655     *
3656     * @param resourceRef            Reference of resource endpoint for obtaining additional data.
3657     * @param aggregationStrategyRef Reference of aggregation strategy to aggregate input data and additional data.
3658     * @param aggregateOnException   whether to call {@link org.apache.camel.processor.aggregate.AggregationStrategy#aggregate(org.apache.camel.Exchange, org.apache.camel.Exchange)} if
3659     *                               an exception was thrown.
3660     * @param shareUnitOfWork        whether to share unit of work
3661     * @return the builder
3662     * @see org.apache.camel.processor.Enricher
3663     * @deprecated use enrich with a <tt>ref:id</tt> as the resourceUri parameter.
3664     */
3665    @Deprecated
3666    @SuppressWarnings("unchecked")
3667    public Type enrichRef(String resourceRef, String aggregationStrategyRef, boolean aggregateOnException, boolean shareUnitOfWork) {
3668        EnrichDefinition answer = new EnrichDefinition();
3669        answer.setExpression(new SimpleExpression("ref:" + resourceRef));
3670        answer.setAggregationStrategyRef(aggregationStrategyRef);
3671        answer.setAggregateOnException(aggregateOnException);
3672        answer.setShareUnitOfWork(shareUnitOfWork);
3673        addOutput(answer);
3674        return (Type) this;
3675    }
3676
3677    /**
3678     * The <a href="http://camel.apache.org/content-enricher.html">Content Enricher EIP</a>
3679     * enriches an exchange with additional data obtained from a <code>resourceUri</code>.
3680     * <p/>
3681     * The difference between this and {@link #pollEnrich(String)} is that this uses a producer
3682     * to obtain the additional data, where as pollEnrich uses a polling consumer.
3683     *
3684     * @return a expression builder clause to set the expression to use for computing the endpoint to use
3685     * @see org.apache.camel.processor.PollEnricher
3686     */
3687    @AsEndpointUri
3688    public ExpressionClause<EnrichDefinition> enrich() {
3689        EnrichDefinition answer = new EnrichDefinition();
3690        addOutput(answer);
3691        return ExpressionClause.createAndSetExpression(answer);
3692    }
3693
3694    /**
3695     * The <a href="http://camel.apache.org/content-enricher.html">Content Enricher EIP</a>
3696     * enriches an exchange with additional data obtained from a <code>resourceUri</code>
3697     * using a {@link org.apache.camel.PollingConsumer} to poll the endpoint.
3698     * <p/>
3699     * The difference between this and {@link #enrich(String)} is that this uses a consumer
3700     * to obtain the additional data, where as enrich uses a producer.
3701     * <p/>
3702     * This method will <tt>block</tt> until data is available, use the method with timeout if you do not
3703     * want to risk waiting a long time before data is available from the resourceUri.
3704     *
3705     * @param resourceUri           URI of resource endpoint for obtaining additional data.
3706     * @return the builder
3707     * @see org.apache.camel.processor.PollEnricher
3708     */
3709    public Type pollEnrich(@AsEndpointUri String resourceUri) {
3710        return pollEnrich(resourceUri, null);
3711    }
3712
3713    /**
3714     * The <a href="http://camel.apache.org/content-enricher.html">Content Enricher EIP</a>
3715     * enriches an exchange with additional data obtained from a <code>resourceUri</code>
3716     * using a {@link org.apache.camel.PollingConsumer} to poll the endpoint.
3717     * <p/>
3718     * The difference between this and {@link #enrich(String)} is that this uses a consumer
3719     * to obtain the additional data, where as enrich uses a producer.
3720     * <p/>
3721     * This method will <b>block</b> until data is available, use the method with timeout if you do not
3722     * want to risk waiting a long time before data is available from the resourceUri.
3723     *
3724     * @param resourceUri           URI of resource endpoint for obtaining additional data.
3725     * @param aggregationStrategy   aggregation strategy to aggregate input data and additional data.
3726     * @return the builder
3727     * @see org.apache.camel.processor.PollEnricher
3728     */
3729    public Type pollEnrich(@AsEndpointUri String resourceUri, AggregationStrategy aggregationStrategy) {
3730        return pollEnrich(resourceUri, -1, aggregationStrategy);
3731    }
3732
3733    /**
3734     * The <a href="http://camel.apache.org/content-enricher.html">Content Enricher EIP</a>
3735     * enriches an exchange with additional data obtained from a <code>resourceUri</code>
3736     * using a {@link org.apache.camel.PollingConsumer} to poll the endpoint.
3737     * <p/>
3738     * The difference between this and {@link #enrich(String)} is that this uses a consumer
3739     * to obtain the additional data, where as enrich uses a producer.
3740     * <p/>
3741     * The timeout controls which operation to use on {@link org.apache.camel.PollingConsumer}.
3742     * If timeout is negative, we use <tt>receive</tt>. If timeout is 0 then we use <tt>receiveNoWait</tt>
3743     * otherwise we use <tt>receive(timeout)</tt>.
3744     *
3745     * @param resourceUri           URI of resource endpoint for obtaining additional data.
3746     * @param timeout               timeout in millis to wait at most for data to be available.
3747     * @param aggregationStrategy   aggregation strategy to aggregate input data and additional data.
3748     * @return the builder
3749     * @see org.apache.camel.processor.PollEnricher
3750     */
3751    public Type pollEnrich(@AsEndpointUri String resourceUri, long timeout, AggregationStrategy aggregationStrategy) {
3752        return pollEnrich(resourceUri, timeout, aggregationStrategy, false);
3753    }
3754
3755    /**
3756     * The <a href="http://camel.apache.org/content-enricher.html">Content Enricher EIP</a>
3757     * enriches an exchange with additional data obtained from a <code>resourceUri</code>
3758     * using a {@link org.apache.camel.PollingConsumer} to poll the endpoint.
3759     * <p/>
3760     * The difference between this and {@link #enrich(String)} is that this uses a consumer
3761     * to obtain the additional data, where as enrich uses a producer.
3762     * <p/>
3763     * The timeout controls which operation to use on {@link org.apache.camel.PollingConsumer}.
3764     * If timeout is negative, we use <tt>receive</tt>. If timeout is 0 then we use <tt>receiveNoWait</tt>
3765     * otherwise we use <tt>receive(timeout)</tt>.
3766     *
3767     * @param resourceUri            URI of resource endpoint for obtaining additional data.
3768     * @param timeout                timeout in millis to wait at most for data to be available.
3769     * @param aggregationStrategyRef Reference of aggregation strategy to aggregate input data and additional data.
3770     * @return the builder
3771     * @see org.apache.camel.processor.PollEnricher
3772     */
3773    public Type pollEnrich(@AsEndpointUri String resourceUri, long timeout, String aggregationStrategyRef) {
3774        return pollEnrich(resourceUri, timeout, aggregationStrategyRef, false);
3775    }
3776
3777    /**
3778     * The <a href="http://camel.apache.org/content-enricher.html">Content Enricher EIP</a>
3779     * enriches an exchange with additional data obtained from a <code>resourceUri</code> 
3780     * and with an aggregation strategy created using a fluent builder using 
3781     * a {@link org.apache.camel.PollingConsumer} to poll the endpoint.
3782     */
3783    public EnrichClause<ProcessorDefinition<Type>> pollEnrichWith(@AsEndpointUri String resourceUri) {
3784        EnrichClause<ProcessorDefinition<Type>> clause = new EnrichClause<>(this);
3785        pollEnrich(resourceUri, -1, clause, false);
3786        return clause;
3787    }
3788
3789    /**
3790     * The <a href="http://camel.apache.org/content-enricher.html">Content Enricher EIP</a>
3791     * enriches an exchange with additional data obtained from a <code>resourceUri</code> 
3792     * and with an aggregation strategy created using a fluent builder using 
3793     * a {@link org.apache.camel.PollingConsumer} to poll the endpoint.
3794     */
3795    public EnrichClause<ProcessorDefinition<Type>> pollEnrichWith(@AsEndpointUri String resourceUri, long timeout) {
3796        EnrichClause<ProcessorDefinition<Type>> clause = new EnrichClause<>(this);
3797        pollEnrich(resourceUri, timeout, clause, false);
3798        return clause;
3799    }
3800
3801    /**
3802     * The <a href="http://camel.apache.org/content-enricher.html">Content Enricher EIP</a>
3803     * enriches an exchange with additional data obtained from a <code>resourceUri</code> 
3804     * and with an aggregation strategy created using a fluent builder using 
3805     * a {@link org.apache.camel.PollingConsumer} to poll the endpoint.
3806     */
3807    public EnrichClause<ProcessorDefinition<Type>> pollEnrichWith(@AsEndpointUri String resourceUri, long timeout, boolean aggregateOnException) {
3808        EnrichClause<ProcessorDefinition<Type>> clause = new EnrichClause<>(this);
3809        pollEnrich(resourceUri, timeout, clause, aggregateOnException);
3810        return clause;
3811    }
3812
3813    /**
3814     * The <a href="http://camel.apache.org/content-enricher.html">Content Enricher EIP</a>
3815     * enriches an exchange with additional data obtained from a <code>resourceUri</code>
3816     * using a {@link org.apache.camel.PollingConsumer} to poll the endpoint.
3817     * <p/>
3818     * The difference between this and {@link #enrich(String)} is that this uses a consumer
3819     * to obtain the additional data, where as enrich uses a producer.
3820     * <p/>
3821     * The timeout controls which operation to use on {@link org.apache.camel.PollingConsumer}.
3822     * If timeout is negative, we use <tt>receive</tt>. If timeout is 0 then we use <tt>receiveNoWait</tt>
3823     * otherwise we use <tt>receive(timeout)</tt>.
3824     *
3825     * @param resourceUri           URI of resource endpoint for obtaining additional data.
3826     * @param timeout               timeout in millis to wait at most for data to be available.
3827     * @param aggregationStrategy   aggregation strategy to aggregate input data and additional data.
3828     * @param aggregateOnException  whether to call {@link org.apache.camel.processor.aggregate.AggregationStrategy#aggregate(org.apache.camel.Exchange, org.apache.camel.Exchange)} if
3829     *                              an exception was thrown.
3830     * @return the builder
3831     * @see org.apache.camel.processor.PollEnricher
3832     */
3833    @SuppressWarnings("unchecked")
3834    public Type pollEnrich(@AsEndpointUri String resourceUri, long timeout, AggregationStrategy aggregationStrategy, boolean aggregateOnException) {
3835        PollEnrichDefinition pollEnrich = new PollEnrichDefinition();
3836        pollEnrich.setExpression(new ConstantExpression(resourceUri));
3837        pollEnrich.setTimeout(timeout);
3838        pollEnrich.setAggregationStrategy(aggregationStrategy);
3839        pollEnrich.setAggregateOnException(aggregateOnException);
3840        addOutput(pollEnrich);
3841        return (Type) this;
3842    }
3843
3844    /**
3845     * The <a href="http://camel.apache.org/content-enricher.html">Content Enricher EIP</a>
3846     * enriches an exchange with additional data obtained from a <code>resourceUri</code>
3847     * using a {@link org.apache.camel.PollingConsumer} to poll the endpoint.
3848     * <p/>
3849     * The difference between this and {@link #enrich(String)} is that this uses a consumer
3850     * to obtain the additional data, where as enrich uses a producer.
3851     * <p/>
3852     * The timeout controls which operation to use on {@link org.apache.camel.PollingConsumer}.
3853     * If timeout is negative, we use <tt>receive</tt>. If timeout is 0 then we use <tt>receiveNoWait</tt>
3854     * otherwise we use <tt>receive(timeout)</tt>.
3855     *
3856     * @param resourceUri            URI of resource endpoint for obtaining additional data.
3857     * @param timeout                timeout in millis to wait at most for data to be available.
3858     * @param aggregationStrategyRef Reference of aggregation strategy to aggregate input data and additional data.
3859     * @param aggregateOnException   whether to call {@link org.apache.camel.processor.aggregate.AggregationStrategy#aggregate(org.apache.camel.Exchange, org.apache.camel.Exchange)} if
3860     *                               an exception was thrown.
3861     * @return the builder
3862     * @see org.apache.camel.processor.PollEnricher
3863     */
3864    @SuppressWarnings("unchecked")
3865    public Type pollEnrich(@AsEndpointUri String resourceUri, long timeout, String aggregationStrategyRef, boolean aggregateOnException) {
3866        PollEnrichDefinition pollEnrich = new PollEnrichDefinition();
3867        pollEnrich.setExpression(new ConstantExpression(resourceUri));
3868        pollEnrich.setTimeout(timeout);
3869        pollEnrich.setAggregationStrategyRef(aggregationStrategyRef);
3870        pollEnrich.setAggregateOnException(aggregateOnException);
3871        addOutput(pollEnrich);
3872        return (Type) this;
3873    }
3874
3875    /**
3876     * The <a href="http://camel.apache.org/content-enricher.html">Content Enricher EIP</a>
3877     * enriches an exchange with additional data obtained from a <code>resourceUri</code>
3878     * using a {@link org.apache.camel.PollingConsumer} to poll the endpoint.
3879     * <p/>
3880     * The difference between this and {@link #enrich(String)} is that this uses a consumer
3881     * to obtain the additional data, where as enrich uses a producer.
3882     * <p/>
3883     * The timeout controls which operation to use on {@link org.apache.camel.PollingConsumer}.
3884     * If timeout is negative, we use <tt>receive</tt>. If timeout is 0 then we use <tt>receiveNoWait</tt>
3885     * otherwise we use <tt>receive(timeout)</tt>.
3886     *
3887     * @param resourceUri           URI of resource endpoint for obtaining additional data.
3888     * @param timeout               timeout in millis to wait at most for data to be available.
3889     * @return the builder
3890     * @see org.apache.camel.processor.PollEnricher
3891     */
3892    public Type pollEnrich(@AsEndpointUri String resourceUri, long timeout) {
3893        return pollEnrich(resourceUri, timeout, (String) null);
3894    }
3895
3896    /**
3897     * The <a href="http://camel.apache.org/content-enricher.html">Content Enricher EIP</a>
3898     * enriches an exchange with additional data obtained from a <code>resourceUri</code>
3899     * using a {@link org.apache.camel.PollingConsumer} to poll the endpoint.
3900     * <p/>
3901     * The difference between this and {@link #enrich(String)} is that this uses a consumer
3902     * to obtain the additional data, where as enrich uses a producer.
3903     * <p/>
3904     * The timeout controls which operation to use on {@link org.apache.camel.PollingConsumer}.
3905     * If timeout is negative, we use <tt>receive</tt>. If timeout is 0 then we use <tt>receiveNoWait</tt>
3906     * otherwise we use <tt>receive(timeout)</tt>.
3907     *
3908     * @param resourceRef            Reference of resource endpoint for obtaining additional data.
3909     * @param timeout                timeout in millis to wait at most for data to be available.
3910     * @param aggregationStrategyRef Reference of aggregation strategy to aggregate input data and additional data.
3911     * @return the builder
3912     * @see org.apache.camel.processor.PollEnricher
3913     * @deprecated use pollEnrich with a <tt>ref:id</tt> as the resourceUri parameter.
3914     */
3915    @Deprecated
3916    @SuppressWarnings("unchecked")
3917    public Type pollEnrichRef(String resourceRef, long timeout, String aggregationStrategyRef) {
3918        PollEnrichDefinition pollEnrich = new PollEnrichDefinition();
3919        pollEnrich.setExpression(new SimpleExpression("ref:" + resourceRef));
3920        pollEnrich.setTimeout(timeout);
3921        pollEnrich.setAggregationStrategyRef(aggregationStrategyRef);
3922        addOutput(pollEnrich);
3923        return (Type) this;
3924    }
3925
3926    /**
3927     * The <a href="http://camel.apache.org/content-enricher.html">Content Enricher EIP</a>
3928     * enriches an exchange with additional data obtained from a <code>resourceUri</code>
3929     * using a {@link org.apache.camel.PollingConsumer} to poll the endpoint.
3930     * <p/>
3931     * The difference between this and {@link #enrich(String)} is that this uses a consumer
3932     * to obtain the additional data, where as enrich uses a producer.
3933     * <p/>
3934     * The timeout controls which operation to use on {@link org.apache.camel.PollingConsumer}.
3935     * If timeout is negative, we use <tt>receive</tt>. If timeout is 0 then we use <tt>receiveNoWait</tt>
3936     * otherwise we use <tt>receive(timeout)</tt>.
3937     *
3938     * @param resourceRef            Reference of resource endpoint for obtaining additional data.
3939     * @param timeout                timeout in millis to wait at most for data to be available.
3940     * @param aggregationStrategyRef Reference of aggregation strategy to aggregate input data and additional data.
3941     * @param aggregateOnException   whether to call {@link org.apache.camel.processor.aggregate.AggregationStrategy#aggregate(org.apache.camel.Exchange, org.apache.camel.Exchange)} if
3942     *                               an exception was thrown.
3943     * @return the builder
3944     * @see org.apache.camel.processor.PollEnricher
3945     * @deprecated use pollEnrich with a <tt>ref:id</tt> as the resourceUri parameter.
3946     */
3947    @Deprecated
3948    @SuppressWarnings("unchecked")
3949    public Type pollEnrichRef(String resourceRef, long timeout, String aggregationStrategyRef, boolean aggregateOnException) {
3950        PollEnrichDefinition pollEnrich = new PollEnrichDefinition();
3951        pollEnrich.setExpression(new SimpleExpression("ref:" + resourceRef));
3952        pollEnrich.setTimeout(timeout);
3953        pollEnrich.setAggregationStrategyRef(aggregationStrategyRef);
3954        pollEnrich.setAggregateOnException(aggregateOnException);
3955        addOutput(pollEnrich);
3956        return (Type) this;
3957    }
3958
3959    /**
3960     * The <a href="http://camel.apache.org/content-enricher.html">Content Enricher EIP</a>
3961     * enriches an exchange with additional data obtained from a <code>resourceUri</code>
3962     * using a {@link org.apache.camel.PollingConsumer} to poll the endpoint.
3963     * <p/>
3964     * The difference between this and {@link #enrich(String)} is that this uses a consumer
3965     * to obtain the additional data, where as enrich uses a producer.
3966     * <p/>
3967     * The timeout controls which operation to use on {@link org.apache.camel.PollingConsumer}.
3968     * If timeout is negative, we use <tt>receive</tt>. If timeout is 0 then we use <tt>receiveNoWait</tt>
3969     * otherwise we use <tt>receive(timeout)</tt>.
3970     *
3971     * @param expression             to use an expression to dynamically compute the endpoint to poll from
3972     * @param timeout                timeout in millis to wait at most for data to be available.
3973     * @param aggregationStrategyRef Reference of aggregation strategy to aggregate input data and additional data.
3974     * @param aggregateOnException   whether to call {@link org.apache.camel.processor.aggregate.AggregationStrategy#aggregate(org.apache.camel.Exchange, org.apache.camel.Exchange)} if
3975     *                               an exception was thrown.
3976     * @return the builder
3977     * @see org.apache.camel.processor.PollEnricher
3978     */
3979    @SuppressWarnings("unchecked")
3980    public Type pollEnrich(@AsEndpointUri Expression expression, long timeout, String aggregationStrategyRef, boolean aggregateOnException) {
3981        PollEnrichDefinition pollEnrich = new PollEnrichDefinition();
3982        pollEnrich.setExpression(new ExpressionDefinition(expression));
3983        pollEnrich.setTimeout(timeout);
3984        pollEnrich.setAggregationStrategyRef(aggregationStrategyRef);
3985        pollEnrich.setAggregateOnException(aggregateOnException);
3986        addOutput(pollEnrich);
3987        return (Type) this;
3988    }
3989
3990    /**
3991     * The <a href="http://camel.apache.org/content-enricher.html">Content Enricher EIP</a>
3992     * enriches an exchange with additional data obtained from a <code>resourceUri</code>
3993     * using a {@link org.apache.camel.PollingConsumer} to poll the endpoint.
3994     * <p/>
3995     * The difference between this and {@link #enrich(String)} is that this uses a consumer
3996     * to obtain the additional data, where as enrich uses a producer.
3997     * <p/>
3998     * The timeout controls which operation to use on {@link org.apache.camel.PollingConsumer}.
3999     * If timeout is negative, we use <tt>receive</tt>. If timeout is 0 then we use <tt>receiveNoWait</tt>
4000     * otherwise we use <tt>receive(timeout)</tt>.
4001     *
4002     * @return a expression builder clause to set the expression to use for computing the endpoint to poll from
4003     * @see org.apache.camel.processor.PollEnricher
4004     */
4005    @AsEndpointUri
4006    public ExpressionClause<PollEnrichDefinition> pollEnrich() {
4007        PollEnrichDefinition answer = new PollEnrichDefinition();
4008        addOutput(answer);
4009        return ExpressionClause.createAndSetExpression(answer);
4010    }
4011
4012    /**
4013     * Adds a onComplection {@link org.apache.camel.spi.Synchronization} hook that invoke this route as
4014     * a callback when the {@link org.apache.camel.Exchange} has finished being processed.
4015     * The hook invoke callbacks for either onComplete or onFailure.
4016     * <p/>
4017     * Will by default always trigger when the {@link org.apache.camel.Exchange} is complete
4018     * (either with success or failed).
4019     * <br/>
4020     * You can limit the callback to either onComplete or onFailure but invoking the nested
4021     * builder method.
4022     * <p/>
4023     * For onFailure the caused exception is stored as a property on the {@link org.apache.camel.Exchange}
4024     * with the key {@link org.apache.camel.Exchange#EXCEPTION_CAUGHT}.
4025     *
4026     * @return the builder
4027     */
4028    public OnCompletionDefinition onCompletion() {
4029        OnCompletionDefinition answer = new OnCompletionDefinition();
4030        // we must remove all existing on completion definition (as they are global)
4031        // and thus we are the only one as route scoped should override any global scoped
4032        answer.removeAllOnCompletionDefinition(this);
4033        popBlock();
4034        addOutput(answer);
4035        pushBlock(answer);
4036        return answer;
4037    }
4038
4039    // DataFormat support
4040    // -------------------------------------------------------------------------
4041
4042    /**
4043     * <a href="http://camel.apache.org/data-format.html">DataFormat:</a>
4044     * Unmarshals the in body using a {@link DataFormat} expression to define
4045     * the format of the input message and the output will be set on the out message body.
4046     *
4047     * @return the expression to create the {@link DataFormat}
4048     */
4049    public DataFormatClause<ProcessorDefinition<Type>> unmarshal() {
4050        return new DataFormatClause<ProcessorDefinition<Type>>(this, DataFormatClause.Operation.Unmarshal);
4051    }
4052
4053    /**
4054     * <a href="http://camel.apache.org/data-format.html">DataFormat:</a>
4055     * Unmarshals the in body using the specified {@link DataFormat}
4056     * and sets the output on the out message body.
4057     *
4058     * @param dataFormatType  the dataformat
4059     * @return the builder
4060     */
4061    @SuppressWarnings("unchecked")
4062    public Type unmarshal(DataFormatDefinition dataFormatType) {
4063        addOutput(new UnmarshalDefinition(dataFormatType));
4064        return (Type) this;
4065    }
4066
4067    /**
4068     * <a href="http://camel.apache.org/data-format.html">DataFormat:</a>
4069     * Unmarshals the in body using the specified {@link DataFormat}
4070     * and sets the output on the out message body.
4071     *
4072     * @param dataFormat  the dataformat
4073     * @return the builder
4074     */
4075    public Type unmarshal(DataFormat dataFormat) {
4076        return unmarshal(new DataFormatDefinition(dataFormat));
4077    }
4078
4079    /**
4080     * <a href="http://camel.apache.org/data-format.html">DataFormat:</a>
4081     * Unmarshals the in body using the specified {@link DataFormat}
4082     * reference in the {@link org.apache.camel.spi.Registry} and sets
4083     * the output on the out message body.
4084     *
4085     * @param dataTypeRef  reference to a {@link DataFormat} to lookup in the registry
4086     * @return the builder
4087     */
4088    @SuppressWarnings("unchecked")
4089    public Type unmarshal(String dataTypeRef) {
4090        addOutput(new UnmarshalDefinition(dataTypeRef));
4091        return (Type) this;
4092    }
4093
4094    /**
4095     * <a href="http://camel.apache.org/data-format.html">DataFormat:</a>
4096     * Marshals the in body using a {@link DataFormat} expression to define
4097     * the format of the output which will be added to the out body.
4098     *
4099     * @return the expression to create the {@link DataFormat}
4100     */
4101    public DataFormatClause<ProcessorDefinition<Type>> marshal() {
4102        return new DataFormatClause<ProcessorDefinition<Type>>(this, DataFormatClause.Operation.Marshal);
4103    }
4104
4105    /**
4106     * <a href="http://camel.apache.org/data-format.html">DataFormat:</a>
4107     * Marshals the in body using the specified {@link DataFormat}
4108     * and sets the output on the out message body.
4109     *
4110     * @param dataFormatType  the dataformat
4111     * @return the builder
4112     */
4113    @SuppressWarnings("unchecked")
4114    public Type marshal(DataFormatDefinition dataFormatType) {
4115        addOutput(new MarshalDefinition(dataFormatType));
4116        return (Type) this;
4117    }
4118
4119    /**
4120     * <a href="http://camel.apache.org/data-format.html">DataFormat:</a>
4121     * Marshals the in body using the specified {@link DataFormat}
4122     * and sets the output on the out message body.
4123     *
4124     * @param dataFormat  the dataformat
4125     * @return the builder
4126     */
4127    public Type marshal(DataFormat dataFormat) {
4128        return marshal(new DataFormatDefinition(dataFormat));
4129    }
4130
4131    /**
4132     * <a href="http://camel.apache.org/data-format.html">DataFormat:</a>
4133     * Marshals the in body the specified {@link DataFormat}
4134     * reference in the {@link org.apache.camel.spi.Registry} and sets
4135     * the output on the out message body.
4136     *
4137     * @param dataTypeRef  reference to a {@link DataFormat} to lookup in the registry
4138     * @return the builder
4139     */
4140    @SuppressWarnings("unchecked")
4141    public Type marshal(String dataTypeRef) {
4142        addOutput(new MarshalDefinition(dataTypeRef));
4143        return (Type) this;
4144    }
4145
4146    /**
4147     * Sets whether or not to inherit the configured error handler.
4148     * <br/>
4149     * The default value is <tt>true</tt>.
4150     * <p/>
4151     * You can use this to disable using the inherited error handler for a given
4152     * DSL such as a load balancer where you want to use a custom error handler strategy.
4153     *
4154     * @param inheritErrorHandler whether to not to inherit the error handler for this node
4155     * @return the builder
4156     */
4157    @SuppressWarnings("unchecked")
4158    public Type inheritErrorHandler(boolean inheritErrorHandler) {
4159        // set on last output
4160        int size = getOutputs().size();
4161        if (size == 0) {
4162            // if no outputs then configure this DSL
4163            setInheritErrorHandler(inheritErrorHandler);
4164        } else {
4165            // configure on last output as its the intended
4166            ProcessorDefinition<?> output = getOutputs().get(size - 1);
4167            if (output != null) {
4168                output.setInheritErrorHandler(inheritErrorHandler);
4169            }
4170        }
4171        return (Type) this;
4172    }
4173
4174    // Properties
4175    // -------------------------------------------------------------------------
4176    public ProcessorDefinition<?> getParent() {
4177        return parent;
4178    }
4179
4180    public void setParent(ProcessorDefinition<?> parent) {
4181        this.parent = parent;
4182    }
4183
4184    public List<InterceptStrategy> getInterceptStrategies() {
4185        return interceptStrategies;
4186    }
4187
4188    public void addInterceptStrategy(InterceptStrategy strategy) {
4189        this.interceptStrategies.add(strategy);
4190    }
4191
4192    public Boolean isInheritErrorHandler() {
4193        return inheritErrorHandler;
4194    }
4195
4196    public void setInheritErrorHandler(Boolean inheritErrorHandler) {
4197        this.inheritErrorHandler = inheritErrorHandler;
4198    }
4199
4200    @Override
4201    public Map<QName, Object> getOtherAttributes() {
4202        return otherAttributes;
4203    }
4204
4205    @Override
4206    public void setOtherAttributes(Map<QName, Object> otherAttributes) {
4207        this.otherAttributes = otherAttributes;
4208    }
4209
4210    /**
4211     * Returns a label to describe this node such as the expression if some kind of expression node
4212     */
4213    public String getLabel() {
4214        return "";
4215    }
4216}