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