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