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