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