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