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