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