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