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