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