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