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                // resolve properties before we create the processor
373                resolvePropertyPlaceholders(routeContext, output);
374    
375                Processor processor = null;
376                // at first use custom factory
377                if (routeContext.getCamelContext().getProcessorFactory() != null) {
378                    processor = routeContext.getCamelContext().getProcessorFactory().createProcessor(routeContext, output);
379                }
380                // fallback to default implementation if factory did not create the processor
381                if (processor == null) {
382                    processor = output.createProcessor(routeContext);
383                }
384    
385                if (output instanceof Channel && processor == null) {
386                    continue;
387                }
388    
389                Processor channel = wrapChannel(routeContext, processor, output);
390                list.add(channel);
391            }
392    
393            // if more than one output wrap than in a composite processor else just keep it as is
394            Processor processor = null;
395            if (!list.isEmpty()) {
396                if (list.size() == 1) {
397                    processor = list.get(0);
398                } else {
399                    processor = createCompositeProcessor(routeContext, list);
400                }
401            }
402    
403            return processor;
404        }
405    
406        /**
407         * Creates the processor and wraps it in any necessary interceptors and error handlers
408         */
409        protected Processor makeProcessor(RouteContext routeContext) throws Exception {
410            Processor processor = null;
411    
412            // allow any custom logic before we create the processor
413            preCreateProcessor();
414    
415            // resolve properties before we create the processor
416            resolvePropertyPlaceholders(routeContext, this);
417    
418            // resolve constant fields (eg Exchange.FILE_NAME)
419            resolveKnownConstantFields(this);
420    
421            // also resolve properties and constant fields on embedded expressions
422            ProcessorDefinition<?> me = (ProcessorDefinition<?>) this;
423            if (me instanceof ExpressionNode) {
424                ExpressionNode exp = (ExpressionNode) me;
425                ExpressionDefinition expressionDefinition = exp.getExpression();
426                if (expressionDefinition != null) {
427                    // resolve properties before we create the processor
428                    resolvePropertyPlaceholders(routeContext, expressionDefinition);
429    
430                    // resolve constant fields (eg Exchange.FILE_NAME)
431                    resolveKnownConstantFields(expressionDefinition);
432                }
433            }
434    
435            // at first use custom factory
436            if (routeContext.getCamelContext().getProcessorFactory() != null) {
437                processor = routeContext.getCamelContext().getProcessorFactory().createProcessor(routeContext, this);
438            }
439            // fallback to default implementation if factory did not create the processor
440            if (processor == null) {
441                processor = createProcessor(routeContext);
442            }
443    
444            if (processor == null) {
445                // no processor to make
446                return null;
447            }
448            return wrapProcessor(routeContext, processor);
449        }
450    
451        /**
452         * Inspects the given definition and resolves any property placeholders from its properties.
453         * <p/>
454         * This implementation will check all the getter/setter pairs on this instance and for all the values
455         * (which is a String type) will be property placeholder resolved.
456         *
457         * @param routeContext the route context
458         * @param definition   the definition
459         * @throws Exception is thrown if property placeholders was used and there was an error resolving them
460         * @see org.apache.camel.CamelContext#resolvePropertyPlaceholders(String)
461         * @see org.apache.camel.component.properties.PropertiesComponent
462         */
463        protected void resolvePropertyPlaceholders(RouteContext routeContext, Object definition) throws Exception {
464            log.trace("Resolving property placeholders for: {}", definition);
465    
466            // find all getter/setter which we can use for property placeholders
467            Map<String, Object> properties = new HashMap<String, Object>();
468            IntrospectionSupport.getProperties(definition, properties, null);
469    
470            ProcessorDefinition<?> processorDefinition = null;
471            if (definition instanceof ProcessorDefinition) {
472                processorDefinition = (ProcessorDefinition<?>) definition;
473            }
474            // include additional properties which have the Camel placeholder QName
475            // and when the definition parameter is this (otherAttributes belong to this)
476            if (processorDefinition != null && processorDefinition.getOtherAttributes() != null) {
477                for (Object key : processorDefinition.getOtherAttributes().keySet()) {
478                    QName qname = (QName) key;
479                    if (Constants.PLACEHOLDER_QNAME.equals(qname.getNamespaceURI())) {
480                        String local = qname.getLocalPart();
481                        Object value = processorDefinition.getOtherAttributes().get(key);
482                        if (value != null && value instanceof String) {
483                            // value must be enclosed with placeholder tokens
484                            String s = (String) value;
485                            String prefixToken = routeContext.getCamelContext().getPropertyPrefixToken();
486                            String suffixToken = routeContext.getCamelContext().getPropertySuffixToken();
487                            if (prefixToken == null) {
488                                throw new IllegalArgumentException("Property with name [" + local + "] uses property placeholders; however, no properties component is configured.");
489                            }
490                            
491                            if (!s.startsWith(prefixToken)) {
492                                s = prefixToken + s;
493                            }
494                            if (!s.endsWith(suffixToken)) {
495                                s = s + suffixToken;
496                            }
497                            value = s;
498                        }
499                        properties.put(local, value);
500                    }
501                }
502            }
503    
504            if (!properties.isEmpty()) {
505                log.trace("There are {} properties on: {}", properties.size(), definition);
506                // lookup and resolve properties for String based properties
507                for (Map.Entry<String, Object> entry : properties.entrySet()) {
508                    // the name is always a String
509                    String name = entry.getKey();
510                    Object value = entry.getValue();
511                    if (value instanceof String) {
512                        // value must be a String, as a String is the key for a property placeholder
513                        String text = (String) value;
514                        text = routeContext.getCamelContext().resolvePropertyPlaceholders(text);
515                        if (text != value) {
516                            // invoke setter as the text has changed
517                            boolean changed = IntrospectionSupport.setProperty(routeContext.getCamelContext().getTypeConverter(), definition, name, text);
518                            if (!changed) {
519                                throw new IllegalArgumentException("No setter to set property: " + name + " to: " + text + " on: " + definition);
520                            }
521                            if (log.isDebugEnabled()) {
522                                log.debug("Changed property [{}] from: {} to: {}", new Object[]{name, value, text});
523                            }
524                        }
525                    }
526                }
527            }
528        }
529    
530        /**
531         * Inspects the given definition and resolves known fields
532         * <p/>
533         * This implementation will check all the getter/setter pairs on this instance and for all the values
534         * (which is a String type) will check if it refers to a known field (such as on Exchange).
535         *
536         * @param definition   the definition
537         */
538        protected void resolveKnownConstantFields(Object definition) throws Exception {
539            log.trace("Resolving known fields for: {}", definition);
540    
541            // find all String getter/setter
542            Map<String, Object> properties = new HashMap<String, Object>();
543            IntrospectionSupport.getProperties(definition, properties, null);
544    
545            if (!properties.isEmpty()) {
546                log.trace("There are {} properties on: {}", properties.size(), definition);
547    
548                // lookup and resolve known constant fields for String based properties
549                for (Map.Entry<String, Object> entry : properties.entrySet()) {
550                    String name = entry.getKey();
551                    Object value = entry.getValue();
552                    if (value instanceof String) {
553                        // we can only resolve String typed values
554                        String text = (String) value;
555    
556                        // is the value a known field (currently we only support constants from Exchange.class)
557                        if (text.startsWith("Exchange.")) {
558                            String field = ObjectHelper.after(text, "Exchange.");
559                            String constant = ObjectHelper.lookupConstantFieldValue(Exchange.class, field);
560                            if (constant != null) {
561                                // invoke setter as the text has changed
562                                IntrospectionSupport.setProperty(definition, name, constant);
563                                if (log.isDebugEnabled()) {
564                                    log.debug("Changed property [{}] from: {} to: {}", new Object[]{name, value, constant});
565                                }
566                            } else {
567                                throw new IllegalArgumentException("Constant field with name: " + field + " not found on Exchange.class");
568                            }
569                        }
570                    }
571                }
572            }
573        }
574    
575        /**
576         * Strategy to execute any custom logic before the {@link Processor} is created.
577         */
578        protected void preCreateProcessor() {
579            // noop
580        }
581    
582        /**
583         * Strategy for children to do any custom configuration
584         *
585         * @param output the child to be added as output to this
586         */
587        protected void configureChild(ProcessorDefinition<?> output) {
588            // noop
589        }
590    
591        // Fluent API
592        // -------------------------------------------------------------------------
593    
594        /**
595         * Adds a placeholder for the given option
596         * <p/>
597         * Requires using the {@link org.apache.camel.component.properties.PropertiesComponent}
598         *
599         * @param option  the name of the option
600         * @param key     the placeholder key
601         * @return the builder
602         */
603        public Type placeholder(String option, String key) {
604            QName name = new QName(Constants.PLACEHOLDER_QNAME, option);
605            return attribute(name, key);
606        }
607    
608        /**
609         * Adds an optional attribute
610         *
611         * @param name    the name of the attribute
612         * @param value   the value
613         * @return the builder
614         */
615        @SuppressWarnings("unchecked")
616        public Type attribute(QName name, Object value) {
617            if (otherAttributes == null) {
618                otherAttributes = new HashMap<QName, Object>();
619            }
620            otherAttributes.put(name, value);
621            return (Type) this;
622        }
623    
624        /**
625         * Sends the exchange to the given endpoint
626         *
627         * @param uri  the endpoint to send to
628         * @return the builder
629         */
630        @SuppressWarnings("unchecked")
631        public Type to(String uri) {
632            addOutput(new ToDefinition(uri));
633            return (Type) this;
634        }   
635        
636        /**
637         * Sends the exchange to the given endpoint
638         *
639         * @param uri  the String formatted endpoint uri to send to
640         * @param args arguments for the string formatting of the uri
641         * @return the builder
642         */
643        @SuppressWarnings("unchecked")
644        public Type toF(String uri, Object... args) {
645            addOutput(new ToDefinition(String.format(uri, args)));
646            return (Type) this;
647        }
648    
649        /**
650         * Sends the exchange to the given endpoint
651         *
652         * @param endpoint  the endpoint to send to
653         * @return the builder
654         */
655        @SuppressWarnings("unchecked")
656        public Type to(Endpoint endpoint) {
657            addOutput(new ToDefinition(endpoint));
658            return (Type) this;
659        }
660        
661        /**
662         * Sends the exchange with certain exchange pattern to the given endpoint
663         * <p/>
664         * Notice the existing MEP is preserved
665         *
666         * @param pattern the pattern to use for the message exchange
667         * @param uri  the endpoint to send to
668         * @return the builder
669         */
670        @SuppressWarnings("unchecked")
671        public Type to(ExchangePattern pattern, String uri) {
672            addOutput(new ToDefinition(uri, pattern));
673            return (Type) this;
674        }   
675    
676        /**
677         * Sends the exchange with certain exchange pattern to the given endpoint
678         * <p/>
679         * Notice the existing MEP is preserved
680         *
681         * @param pattern the pattern to use for the message exchange
682         * @param endpoint  the endpoint to send to
683         * @return the builder
684         */
685        @SuppressWarnings("unchecked")
686        public Type to(ExchangePattern pattern, Endpoint endpoint) {
687            addOutput(new ToDefinition(endpoint, pattern));
688            return (Type) this;
689        }
690    
691        /**
692         * Sends the exchange to a list of endpoints
693         *
694         * @param uris  list of endpoints to send to
695         * @return the builder
696         */
697        @SuppressWarnings("unchecked")
698        public Type to(String... uris) {
699            for (String uri : uris) {
700                addOutput(new ToDefinition(uri));
701            }
702            return (Type) this;
703        }
704    
705        /**
706         * Sends the exchange to a list of endpoints
707         *
708         * @param endpoints  list of endpoints to send to
709         * @return the builder
710         */
711        @SuppressWarnings("unchecked")
712        public Type to(Endpoint... endpoints) {
713            for (Endpoint endpoint : endpoints) {
714                addOutput(new ToDefinition(endpoint));
715            }
716            return (Type) this;
717        }
718    
719        /**
720         * Sends the exchange to a list of endpoints
721         *
722         * @param endpoints  list of endpoints to send to
723         * @return the builder
724         */
725        @SuppressWarnings("unchecked")
726        public Type to(Iterable<Endpoint> endpoints) {
727            for (Endpoint endpoint : endpoints) {
728                addOutput(new ToDefinition(endpoint));
729            }
730            return (Type) this;
731        }
732    
733        /**
734         * Sends the exchange to a list of endpoints
735         * <p/>
736         * Notice the existing MEP is preserved
737         *
738         * @param pattern the pattern to use for the message exchanges
739         * @param uris  list of endpoints to send to
740         * @return the builder
741         */
742        @SuppressWarnings("unchecked")
743        public Type to(ExchangePattern pattern, String... uris) {
744            for (String uri : uris) {
745                addOutput(new ToDefinition(uri, pattern));
746            }
747            return (Type) this;
748        }
749    
750        /**
751         * Sends the exchange to a list of endpoints
752         * <p/>
753         * Notice the existing MEP is preserved
754         *
755         * @param pattern the pattern to use for the message exchanges
756         * @param endpoints  list of endpoints to send to
757         * @return the builder
758         */
759        @SuppressWarnings("unchecked")
760        public Type to(ExchangePattern pattern, Endpoint... endpoints) {
761            for (Endpoint endpoint : endpoints) {
762                addOutput(new ToDefinition(endpoint, pattern));
763            }
764            return (Type) this;
765        }
766    
767        /**
768         * Sends the exchange to a list of endpoints
769         *
770         * @param pattern the pattern to use for the message exchanges
771         * @param endpoints  list of endpoints to send to
772         * @return the builder
773         */
774        @SuppressWarnings("unchecked")
775        public Type to(ExchangePattern pattern, Iterable<Endpoint> endpoints) {
776            for (Endpoint endpoint : endpoints) {
777                addOutput(new ToDefinition(endpoint, pattern));
778            }
779            return (Type) this;
780        }
781    
782        /**
783         * <a href="http://camel.apache.org/exchange-pattern.html">ExchangePattern:</a>
784         * set the {@link ExchangePattern} into the {@link Exchange}.
785         * <p/>
786         * The pattern set on the {@link Exchange} will
787         *
788         * @param exchangePattern  instance of {@link ExchangePattern}
789         * @return the builder
790         */
791        @SuppressWarnings("unchecked")
792        public Type setExchangePattern(ExchangePattern exchangePattern) {
793            addOutput(new SetExchangePatternDefinition(exchangePattern));
794            return (Type) this;
795        }
796    
797        /**
798         * <a href="http://camel.apache.org/exchange-pattern.html">ExchangePattern:</a>
799         * set the exchange's ExchangePattern {@link ExchangePattern} to be InOnly
800         *
801         * @return the builder
802         * @deprecated use {@link #setExchangePattern(org.apache.camel.ExchangePattern)} instead
803         */
804        @Deprecated
805        public Type inOnly() {
806            return setExchangePattern(ExchangePattern.InOnly);
807        }
808    
809        /**
810         * Sends the message to the given endpoint using an
811         * <a href="http://camel.apache.org/event-message.html">Event Message</a> or
812         * <a href="http://camel.apache.org/exchange-pattern.html">InOnly exchange pattern</a>
813         * <p/>
814         * Notice the existing MEP is restored after the message has been sent to the given endpoint.
815         *
816         * @param uri The endpoint uri which is used for sending the exchange
817         * @return the builder
818         */
819        public Type inOnly(String uri) {
820            return to(ExchangePattern.InOnly, uri);
821        }
822    
823        /**
824         * Sends the message to the given endpoint using an
825         * <a href="http://camel.apache.org/event-message.html">Event Message</a> or 
826         * <a href="http://camel.apache.org/exchange-pattern.html">InOnly exchange pattern</a>
827         * <p/>
828         * Notice the existing MEP is restored after the message has been sent to the given endpoint.
829         *
830         * @param endpoint The endpoint which is used for sending the exchange
831         * @return the builder
832         */
833        public Type inOnly(Endpoint endpoint) {
834            return to(ExchangePattern.InOnly, endpoint);
835        }
836    
837        /**
838         * Sends the message to the given endpoints using an
839         * <a href="http://camel.apache.org/event-message.html">Event Message</a> or
840         * <a href="http://camel.apache.org/exchange-pattern.html">InOnly exchange pattern</a>
841         * <p/>
842         * Notice the existing MEP is restored after the message has been sent to the given endpoint.
843         *
844         * @param uris  list of endpoints to send to
845         * @return the builder
846         */
847        public Type inOnly(String... uris) {
848            return to(ExchangePattern.InOnly, uris);
849        }
850    
851        /**
852         * Sends the message to the given endpoints using an
853         * <a href="http://camel.apache.org/event-message.html">Event Message</a> or
854         * <a href="http://camel.apache.org/exchange-pattern.html">InOnly exchange pattern</a>
855         * <p/>
856         * Notice the existing MEP is restored after the message has been sent to the given endpoint.
857         *
858         * @param endpoints  list of endpoints to send to
859         * @return the builder
860         */
861        public Type inOnly(Endpoint... endpoints) {
862            return to(ExchangePattern.InOnly, endpoints);
863        }
864    
865        /**
866         * Sends the message to the given endpoints using an
867         * <a href="http://camel.apache.org/event-message.html">Event Message</a> or
868         * <a href="http://camel.apache.org/exchange-pattern.html">InOnly exchange pattern</a>
869         * <p/>
870         * Notice the existing MEP is restored after the message has been sent to the given endpoint.
871         *
872         * @param endpoints  list of endpoints to send to
873         * @return the builder
874         */
875        public Type inOnly(Iterable<Endpoint> endpoints) {
876            return to(ExchangePattern.InOnly, endpoints);
877        }
878    
879        /**
880         * <a href="http://camel.apache.org/exchange-pattern.html">ExchangePattern:</a>
881         * set the exchange's ExchangePattern {@link ExchangePattern} to be InOut
882         *
883         * @return the builder
884         * @deprecated use {@link #setExchangePattern(org.apache.camel.ExchangePattern)} instead
885         */
886        @Deprecated
887        public Type inOut() {
888            return setExchangePattern(ExchangePattern.InOut);
889        }
890    
891        /**
892         * Sends the message to the given endpoint using an
893         * <a href="http://camel.apache.org/request-reply.html">Request Reply</a> or
894         * <a href="http://camel.apache.org/exchange-pattern.html">InOut exchange pattern</a>
895         * <p/>
896         * Notice the existing MEP is restored after the message has been sent to the given endpoint.
897         *
898         * @param uri The endpoint uri which is used for sending the exchange
899         * @return the builder
900         */
901        public Type inOut(String uri) {
902            return to(ExchangePattern.InOut, uri);
903        }
904    
905        /**
906         * Sends the message to the given endpoint using an
907         * <a href="http://camel.apache.org/request-reply.html">Request Reply</a> or
908         * <a href="http://camel.apache.org/exchange-pattern.html">InOut exchange pattern</a>
909         * <p/>
910         * Notice the existing MEP is restored after the message has been sent to the given endpoint.
911         *
912         * @param endpoint The endpoint which is used for sending the exchange
913         * @return the builder
914         */
915        public Type inOut(Endpoint endpoint) {
916            return to(ExchangePattern.InOut, endpoint);
917        }
918    
919        /**
920         * Sends the message to the given endpoints using an
921         * <a href="http://camel.apache.org/request-reply.html">Request Reply</a> or
922         * <a href="http://camel.apache.org/exchange-pattern.html">InOut exchange pattern</a>
923         * <p/>
924         * Notice the existing MEP is restored after the message has been sent to the given endpoint.
925         *
926         * @param uris  list of endpoints to send to
927         * @return the builder
928         */
929        public Type inOut(String... uris) {
930            return to(ExchangePattern.InOut, uris);
931        }
932    
933        /**
934         * Sends the message to the given endpoints using an
935         * <a href="http://camel.apache.org/request-reply.html">Request Reply</a> or
936         * <a href="http://camel.apache.org/exchange-pattern.html">InOut exchange pattern</a>
937         * <p/>
938         * Notice the existing MEP is restored after the message has been sent to the given endpoint.
939         *
940         * @param endpoints  list of endpoints to send to
941         * @return the builder
942         */
943        public Type inOut(Endpoint... endpoints) {
944            return to(ExchangePattern.InOut, endpoints);
945        }
946    
947        /**
948         * Sends the message to the given endpoints using an
949         * <a href="http://camel.apache.org/request-reply.html">Request Reply</a> or
950         * <a href="http://camel.apache.org/exchange-pattern.html">InOut exchange pattern</a>
951         * <p/>
952         * Notice the existing MEP is restored after the message has been sent to the given endpoint.
953         *
954         * @param endpoints  list of endpoints to send to
955         * @return the builder
956         */
957        public Type inOut(Iterable<Endpoint> endpoints) {
958            return to(ExchangePattern.InOut, endpoints);
959        }
960    
961        /**
962         * Sets the id of this node
963         *
964         * @param id  the id
965         * @return the builder
966         */
967        @SuppressWarnings("unchecked")
968        public Type id(String id) {
969            if (getOutputs().isEmpty()) {
970                // set id on this
971                setId(id);
972            } else {
973                // set it on last output as this is what the user means to do
974                // for Block(s) with non empty getOutputs() the id probably refers
975                //  to the last definition in the current Block
976                List<ProcessorDefinition<?>> outputs = getOutputs();
977                if (!blocks.isEmpty()) {
978                    if (blocks.getLast() instanceof ProcessorDefinition) {
979                        ProcessorDefinition<?> block = (ProcessorDefinition<?>)blocks.getLast();
980                        if (!block.getOutputs().isEmpty()) {
981                            outputs = block.getOutputs();
982                        }
983                    }
984                }
985                outputs.get(outputs.size() - 1).setId(id);
986            }
987    
988            return (Type) this;
989        }
990    
991        /**
992         * Set the route id for this route.
993         * <p/>
994         * <b>Important: </b> Each route in the same {@link org.apache.camel.CamelContext} must have an <b>unique</b> route id.
995         * If you use the API from {@link org.apache.camel.CamelContext} or {@link ModelCamelContext} to add routes, then any
996         * new routes which has a route id that matches an old route, then the old route is replaced by the new route.
997         *
998         * @param id  the route id, should be unique
999         * @return the builder
1000         */
1001        @SuppressWarnings("unchecked")
1002        public Type routeId(String id) {
1003            ProcessorDefinition<?> def = this;
1004    
1005            RouteDefinition route = ProcessorDefinitionHelper.getRoute(def);
1006            if (route != null) {
1007                route.setId(id);
1008            }
1009    
1010            return (Type) this;
1011        }
1012    
1013        /**
1014         * <a href="http://camel.apache.org/multicast.html">Multicast EIP:</a>
1015         * Multicasts messages to all its child outputs; so that each processor and
1016         * destination gets a copy of the original message to avoid the processors
1017         * interfering with each other.
1018         *
1019         * @return the builder
1020         */
1021        public MulticastDefinition multicast() {
1022            MulticastDefinition answer = new MulticastDefinition();
1023            addOutput(answer);
1024            return answer;
1025        }
1026    
1027        /**
1028         * <a href="http://camel.apache.org/multicast.html">Multicast EIP:</a>
1029         * Multicasts messages to all its child outputs; so that each processor and
1030         * destination gets a copy of the original message to avoid the processors
1031         * interfering with each other.
1032         *
1033         * @param aggregationStrategy the strategy used to aggregate responses for
1034         *          every part
1035         * @param parallelProcessing if is <tt>true</tt> camel will fork thread to call the endpoint producer
1036         * @return the builder
1037         */
1038        public MulticastDefinition multicast(AggregationStrategy aggregationStrategy, boolean parallelProcessing) {
1039            MulticastDefinition answer = new MulticastDefinition();
1040            addOutput(answer);
1041            answer.setAggregationStrategy(aggregationStrategy);
1042            answer.setParallelProcessing(parallelProcessing);
1043            return answer;
1044        }
1045    
1046        /**
1047         * <a href="http://camel.apache.org/multicast.html">Multicast EIP:</a>
1048         * Multicasts messages to all its child outputs; so that each processor and
1049         * destination gets a copy of the original message to avoid the processors
1050         * interfering with each other.
1051         *
1052         * @param aggregationStrategy the strategy used to aggregate responses for every part
1053         * @return the builder
1054         */
1055        public MulticastDefinition multicast(AggregationStrategy aggregationStrategy) {
1056            MulticastDefinition answer = new MulticastDefinition();
1057            addOutput(answer);
1058            answer.setAggregationStrategy(aggregationStrategy);
1059            return answer;
1060        }
1061    
1062        /**
1063         * <a href="http://camel.apache.org/pipes-nd-filters.html">Pipes and Filters EIP:</a>
1064         * Creates a {@link Pipeline} so that the message
1065         * will get processed by each endpoint in turn and for request/response the
1066         * output of one endpoint will be the input of the next endpoint
1067         *
1068         * @return the builder
1069         */
1070        public PipelineDefinition pipeline() {
1071            PipelineDefinition answer = new PipelineDefinition();
1072            addOutput(answer);
1073            return answer;
1074        }
1075    
1076        /**
1077         * <a href="http://camel.apache.org/pipes-nd-filters.html">Pipes and Filters EIP:</a>
1078         * Creates a {@link Pipeline} of the list of endpoints so that the message
1079         * will get processed by each endpoint in turn and for request/response the
1080         * output of one endpoint will be the input of the next endpoint
1081         *
1082         * @param uris  list of endpoints
1083         * @return the builder
1084         */
1085        public Type pipeline(String... uris) {
1086            return to(uris);
1087        }
1088    
1089        /**
1090         * <a href="http://camel.apache.org/pipes-nd-filters.html">Pipes and Filters EIP:</a>
1091         * Creates a {@link Pipeline} of the list of endpoints so that the message
1092         * will get processed by each endpoint in turn and for request/response the
1093         * output of one endpoint will be the input of the next endpoint
1094         *
1095         * @param endpoints  list of endpoints
1096         * @return the builder
1097         */
1098        public Type pipeline(Endpoint... endpoints) {
1099            return to(endpoints);
1100        }
1101    
1102        /**
1103         * <a href="http://camel.apache.org/pipes-nd-filters.html">Pipes and Filters EIP:</a>
1104         * Creates a {@link Pipeline} of the list of endpoints so that the message
1105         * will get processed by each endpoint in turn and for request/response the
1106         * output of one endpoint will be the input of the next endpoint
1107         *
1108         * @param endpoints  list of endpoints
1109         * @return the builder
1110         */
1111        public Type pipeline(Collection<Endpoint> endpoints) {
1112            return to(endpoints);
1113        }
1114    
1115        /**
1116         * Continues processing the {@link org.apache.camel.Exchange} using asynchronous routing engine.
1117         *
1118         * @return the builder
1119         */
1120        public ThreadsDefinition threads() {
1121            ThreadsDefinition answer = new ThreadsDefinition();
1122            addOutput(answer);
1123            return answer;
1124        }
1125    
1126        /**
1127         * Continues processing the {@link org.apache.camel.Exchange} using asynchronous routing engine.
1128         *
1129         * @param poolSize the core pool size
1130         * @return the builder
1131         */
1132        public ThreadsDefinition threads(int poolSize) {
1133            ThreadsDefinition answer = new ThreadsDefinition();
1134            answer.setPoolSize(poolSize);
1135            addOutput(answer);
1136            return answer;
1137        }
1138    
1139        /**
1140         * Continues processing the {@link org.apache.camel.Exchange} using asynchronous routing engine.
1141         *
1142         * @param poolSize    the core pool size
1143         * @param maxPoolSize the maximum pool size
1144         * @return the builder
1145         */
1146        public ThreadsDefinition threads(int poolSize, int maxPoolSize) {
1147            ThreadsDefinition answer = new ThreadsDefinition();
1148            answer.setPoolSize(poolSize);
1149            answer.setMaxPoolSize(maxPoolSize);
1150            addOutput(answer);
1151            return answer;
1152        }
1153        
1154        /**
1155         * Continues processing the {@link org.apache.camel.Exchange} using asynchronous routing engine.
1156         *
1157         * @param poolSize    the core pool size
1158         * @param maxPoolSize the maximum pool size
1159         * @param threadName the thread pool name
1160         * @return the builder
1161         */
1162        public ThreadsDefinition threads(int poolSize, int maxPoolSize, String threadName) {
1163            ThreadsDefinition answer = new ThreadsDefinition();
1164            answer.setPoolSize(poolSize);
1165            answer.setMaxPoolSize(maxPoolSize);
1166            answer.setThreadName(threadName);
1167            addOutput(answer);
1168            return answer;
1169        }
1170    
1171        /**
1172         * Wraps the sub route using AOP allowing you to do before and after work (AOP around).
1173         *
1174         * @return the builder
1175         * @deprecated to be removed in the near future. Instead you can use interceptors or processors to do AOP with Camel.
1176         */
1177        @Deprecated
1178        public AOPDefinition aop() {
1179            AOPDefinition answer = new AOPDefinition();
1180            addOutput(answer);
1181            return answer;
1182        }
1183    
1184        /**
1185         * Ends the current block
1186         *
1187         * @return the builder
1188         */
1189        public ProcessorDefinition<?> end() {
1190            // must do this ugly cast to avoid compiler error on AIX/HP-UX
1191            ProcessorDefinition<?> defn = (ProcessorDefinition<?>) this;
1192            
1193            // when using doTry .. doCatch .. doFinally we should always
1194            // end the try definition to avoid having to use 2 x end() in the route
1195            // this is counter intuitive for end users
1196            // TODO (camel-3.0): this should be done inside of TryDefinition or even better
1197            //  in Block(s) in general, but the api needs to be revisited for that.
1198            if (defn instanceof TryDefinition || defn instanceof ChoiceDefinition) {
1199                popBlock();
1200            }
1201    
1202            if (blocks.isEmpty()) {
1203                if (parent == null) {
1204                    return this.endParent();
1205                }
1206                return parent.endParent();
1207            }
1208            popBlock();
1209            return this.endParent();
1210        }
1211    
1212        /**
1213         * Strategy to allow {@link ProcessorDefinition}s to have special logic when using end() in the DSL
1214         * to return back to the intended parent.
1215         * <p/>
1216         * For example a content based router we return back to the {@link ChoiceDefinition} when we end()
1217         * from a {@link WhenDefinition}.
1218         *
1219         * @return the end
1220         */
1221        public ProcessorDefinition<?> endParent() {
1222            return this;
1223        }
1224    
1225        /**
1226         * Ends the current block and returns back to the {@link ChoiceDefinition choice()} DSL.
1227         *
1228         * @return the builder
1229         */
1230        public ChoiceDefinition endChoice() {
1231            ProcessorDefinition<?> def = end();
1232            if (def instanceof WhenDefinition) {
1233                return (ChoiceDefinition) def.getParent();
1234            } else if (def instanceof OtherwiseDefinition) {
1235                return (ChoiceDefinition) def.getParent();
1236            } else {
1237                return (ChoiceDefinition) def;
1238            }
1239        }
1240    
1241        /**
1242         * Ends the current block and returns back to the {@link TryDefinition doTry()} DSL.
1243         *
1244         * @return the builder
1245         */
1246        public TryDefinition endDoTry() {
1247            return (TryDefinition) end();
1248        }
1249    
1250        /**
1251         * <a href="http://camel.apache.org/idempotent-consumer.html">Idempotent consumer EIP:</a>
1252         * Creates an {@link org.apache.camel.processor.idempotent.IdempotentConsumer IdempotentConsumer}
1253         * to avoid duplicate messages
1254         *
1255         * @param messageIdExpression  expression to test of duplicate messages
1256         * @return the builder
1257         */
1258        public IdempotentConsumerDefinition idempotentConsumer(Expression messageIdExpression) {
1259            IdempotentConsumerDefinition answer = new IdempotentConsumerDefinition();
1260            answer.setExpression(new ExpressionDefinition(messageIdExpression));
1261            addOutput(answer);
1262            return answer;
1263        }
1264    
1265        /**
1266         * <a href="http://camel.apache.org/idempotent-consumer.html">Idempotent consumer EIP:</a>
1267         * Creates an {@link org.apache.camel.processor.idempotent.IdempotentConsumer IdempotentConsumer}
1268         * to avoid duplicate messages
1269         *
1270         * @param messageIdExpression  expression to test of duplicate messages
1271         * @param idempotentRepository  the repository to use for duplicate check
1272         * @return the builder
1273         */
1274        public IdempotentConsumerDefinition idempotentConsumer(Expression messageIdExpression, IdempotentRepository<?> idempotentRepository) {
1275            IdempotentConsumerDefinition answer = new IdempotentConsumerDefinition(messageIdExpression, idempotentRepository);
1276            addOutput(answer);
1277            return answer;
1278        }
1279    
1280        /**
1281         * <a href="http://camel.apache.org/idempotent-consumer.html">Idempotent consumer EIP:</a>
1282         * Creates an {@link org.apache.camel.processor.idempotent.IdempotentConsumer IdempotentConsumer}
1283         * to avoid duplicate messages
1284         *
1285         * @param idempotentRepository the repository to use for duplicate check
1286         * @return the builder used to create the expression
1287         * @deprecated will be removed in Camel 3.0. Instead use any of the other methods
1288         */
1289        @Deprecated
1290        public ExpressionClause<IdempotentConsumerDefinition> idempotentConsumer(IdempotentRepository<?> idempotentRepository) {
1291            IdempotentConsumerDefinition answer = new IdempotentConsumerDefinition();
1292            answer.setMessageIdRepository(idempotentRepository);
1293            addOutput(answer);
1294            return ExpressionClause.createAndSetExpression(answer);
1295        }
1296    
1297        /**
1298         * <a href="http://camel.apache.org/message-filter.html">Message Filter EIP:</a>
1299         * Creates a predicate expression which only if it is <tt>true</tt> then the
1300         * exchange is forwarded to the destination
1301         *
1302         * @return the clause used to create the filter expression
1303         */
1304        public ExpressionClause<? extends FilterDefinition> filter() {
1305            FilterDefinition filter = new FilterDefinition();
1306            addOutput(filter);
1307            return ExpressionClause.createAndSetExpression(filter);
1308        }
1309    
1310        /**
1311         * <a href="http://camel.apache.org/message-filter.html">Message Filter EIP:</a>
1312         * Creates a predicate which is applied and only if it is <tt>true</tt> then the
1313         * exchange is forwarded to the destination
1314         *
1315         * @param predicate  predicate to use
1316         * @return the builder 
1317         */
1318        public FilterDefinition filter(Predicate predicate) {
1319            FilterDefinition filter = new FilterDefinition(predicate);
1320            addOutput(filter);
1321            return filter;
1322        }
1323    
1324        /**
1325         * <a href="http://camel.apache.org/message-filter.html">Message Filter EIP:</a>
1326         * Creates a predicate expression which only if it is <tt>true</tt> then the
1327         * exchange is forwarded to the destination
1328         *
1329         * @param expression  the predicate expression to use
1330         * @return the builder
1331         */
1332        public FilterDefinition filter(ExpressionDefinition expression) {
1333            FilterDefinition filter = getNodeFactory().createFilter();
1334            filter.setExpression(expression);
1335            addOutput(filter);
1336            return filter;
1337        }
1338    
1339        /**
1340         * <a href="http://camel.apache.org/message-filter.html">Message Filter EIP:</a>
1341         * Creates a predicate language expression which only if it is <tt>true</tt> then the
1342         * exchange is forwarded to the destination
1343         *
1344         * @param language     language for expression
1345         * @param expression   the expression
1346         * @return the builder
1347         */
1348        public FilterDefinition filter(String language, String expression) {
1349            return filter(new LanguageExpression(language, expression));
1350        }
1351        
1352        /**
1353         * Creates a validation expression which only if it is <tt>true</tt> then the
1354         * exchange is forwarded to the destination.
1355         * Otherwise a {@link org.apache.camel.processor.validation.PredicateValidationException} is thrown.
1356         *
1357         * @param expression  the expression
1358         * @return the builder
1359         */
1360        public ValidateDefinition validate(Expression expression) {
1361            ValidateDefinition answer = new ValidateDefinition();
1362            answer.setExpression(new ExpressionDefinition(expression));
1363            addOutput(answer);
1364            return answer;
1365        }
1366    
1367        /**
1368         * Creates a validation expression which only if it is <tt>true</tt> then the
1369         * exchange is forwarded to the destination.
1370         * Otherwise a {@link org.apache.camel.processor.validation.PredicateValidationException} is thrown.
1371         *
1372         * @param predicate  the predicate
1373         * @return the builder
1374         */
1375        public ValidateDefinition validate(Predicate predicate) {
1376            ValidateDefinition answer = new ValidateDefinition();
1377            answer.setExpression(new ExpressionDefinition(predicate));
1378            addOutput(answer);
1379            return answer;
1380        }
1381    
1382        /**
1383         * Creates a validation expression which only if it is <tt>true</tt> then the
1384         * exchange is forwarded to the destination.
1385         * Otherwise a {@link org.apache.camel.processor.validation.PredicateValidationException} is thrown.
1386         *
1387         * @return the builder
1388         */
1389        public ExpressionClause<ValidateDefinition> validate() {
1390            ValidateDefinition answer = new ValidateDefinition();
1391            addOutput(answer);
1392            return ExpressionClause.createAndSetExpression(answer);
1393        }
1394        /**
1395         * <a href="http://camel.apache.org/load-balancer.html">Load Balancer EIP:</a>
1396         * Creates a loadbalance
1397         *
1398         * @return  the builder
1399         */
1400        public LoadBalanceDefinition loadBalance() {
1401            LoadBalanceDefinition answer = new LoadBalanceDefinition();
1402            addOutput(answer);
1403            return answer;
1404        }
1405    
1406        /**
1407         * <a href="http://camel.apache.org/load-balancer.html">Load Balancer EIP:</a>
1408         * Creates a loadbalance
1409         *
1410         * @param loadBalancer a custom load balancer to use
1411         * @return  the builder
1412         */
1413        public LoadBalanceDefinition loadBalance(LoadBalancer loadBalancer) {
1414            LoadBalanceDefinition answer = new LoadBalanceDefinition();
1415            addOutput(answer);
1416            return answer.loadBalance(loadBalancer);
1417        }
1418    
1419        /**
1420         * Creates a log message to be logged at INFO level.
1421         *
1422         * @param message the log message, (you can use {@link org.apache.camel.language.simple.SimpleLanguage} syntax)
1423         * @return the builder
1424         */
1425        @SuppressWarnings("unchecked")
1426        public Type log(String message) {
1427            LogDefinition answer = new LogDefinition(message);
1428            addOutput(answer);
1429            return (Type) this;
1430        }
1431    
1432        /**
1433         * Creates a log message to be logged at the given level.
1434         *
1435         * @param loggingLevel the logging level to use
1436         * @param message the log message, (you can use {@link org.apache.camel.language.simple.SimpleLanguage} syntax)
1437         * @return the builder
1438         */
1439        @SuppressWarnings("unchecked")
1440        public Type log(LoggingLevel loggingLevel, String message) {
1441            LogDefinition answer = new LogDefinition(message);
1442            answer.setLoggingLevel(loggingLevel);
1443            addOutput(answer);
1444            return (Type) this;
1445        }
1446    
1447        /**
1448         * Creates a log message to be logged at the given level and name.
1449         *
1450         * @param loggingLevel the logging level to use
1451         * @param logName the log name to use
1452         * @param message the log message, (you can use {@link org.apache.camel.language.simple.SimpleLanguage} syntax)
1453         * @return the builder
1454         */
1455        @SuppressWarnings("unchecked")
1456        public Type log(LoggingLevel loggingLevel, String logName, String message) {
1457            LogDefinition answer = new LogDefinition(message);
1458            answer.setLoggingLevel(loggingLevel);
1459            answer.setLogName(logName);
1460            addOutput(answer);
1461            return (Type) this;
1462        }
1463    
1464        /**
1465         * Creates a log message to be logged at the given level and name.
1466         *
1467         *
1468         * @param loggingLevel the logging level to use
1469         * @param logName the log name to use
1470         * @param marker  log marker name
1471         * @param message the log message, (you can use {@link org.apache.camel.language.simple.SimpleLanguage} syntax)
1472         * @return the builder
1473         */
1474        @SuppressWarnings("unchecked")
1475        public Type log(LoggingLevel loggingLevel, String logName, String marker, String message) {
1476            LogDefinition answer = new LogDefinition(message);
1477            answer.setLoggingLevel(loggingLevel);
1478            answer.setLogName(logName);
1479            answer.setMarker(marker);
1480            addOutput(answer);
1481            return (Type) this;
1482        }
1483    
1484        /**
1485         * <a href="http://camel.apache.org/content-based-router.html">Content Based Router EIP:</a>
1486         * Creates a choice of one or more predicates with an otherwise clause
1487         *
1488         * @return the builder for a choice expression
1489         */
1490        public ChoiceDefinition choice() {
1491            ChoiceDefinition answer = new ChoiceDefinition();
1492            addOutput(answer);
1493            return answer;
1494        }
1495    
1496        /**
1497         * Creates a try/catch block
1498         *
1499         * @return the builder for a tryBlock expression
1500         */
1501        public TryDefinition doTry() {
1502            TryDefinition answer = new TryDefinition();
1503            addOutput(answer);
1504            return answer;
1505        }
1506    
1507        /**
1508         * <a href="http://camel.apache.org/recipient-list.html">Recipient List EIP:</a>
1509         * Creates a dynamic recipient list allowing you to route messages to a number of dynamically specified recipients.
1510         * <p/>
1511         * Will use comma as default delimiter.
1512         *
1513         * @param recipients expression to decide the destinations
1514         * @return the builder
1515         */
1516        public RecipientListDefinition<Type> recipientList(Expression recipients) {
1517            RecipientListDefinition<Type> answer = new RecipientListDefinition<Type>(recipients);
1518            addOutput(answer);
1519            return answer;
1520        }
1521    
1522        /**
1523         * <a href="http://camel.apache.org/recipient-list.html">Recipient List EIP:</a>
1524         * Creates a dynamic recipient list allowing you to route messages to a number of dynamically specified recipients
1525         *
1526         * @param recipients expression to decide the destinations
1527         * @param delimiter  a custom delimiter to use
1528         * @return the builder
1529         */
1530        public RecipientListDefinition<Type> recipientList(Expression recipients, String delimiter) {
1531            RecipientListDefinition<Type> answer = new RecipientListDefinition<Type>(recipients);
1532            answer.setDelimiter(delimiter);
1533            addOutput(answer);
1534            return answer;
1535        }
1536    
1537        /**
1538         * <a href="http://camel.apache.org/recipient-list.html">Recipient List EIP:</a>
1539         * Creates a dynamic recipient list allowing you to route messages to a number of dynamically specified recipients
1540         *
1541         * @return the expression clause to configure the expression to decide the destinations
1542         */
1543        public ExpressionClause<RecipientListDefinition<Type>> recipientList() {
1544            RecipientListDefinition<Type> answer = new RecipientListDefinition<Type>();
1545            addOutput(answer);
1546            return ExpressionClause.createAndSetExpression(answer);
1547        }
1548    
1549        /**
1550         * <a href="http://camel.apache.org/routing-slip.html">Routing Slip EIP:</a>
1551         * Creates a routing slip allowing you to route a message consecutively through a series of processing
1552         * steps where the sequence of steps is not known at design time and can vary for each message.
1553         * <p/>
1554         * The route slip will be evaluated <i>once</i>, use {@link #dynamicRouter()} if you need even more dynamic routing.
1555         *
1556         * @param header  is the header that the {@link org.apache.camel.processor.RoutingSlip RoutingSlip}
1557         *                class will look in for the list of URIs to route the message to.
1558         * @param uriDelimiter  is the delimiter that will be used to split up
1559         *                      the list of URIs in the routing slip.
1560         * @return the builder
1561         * @deprecated prefer to use {@link #routingSlip(org.apache.camel.Expression, String)} instead
1562         */
1563        @SuppressWarnings("unchecked")
1564        @Deprecated
1565        public Type routingSlip(String header, String uriDelimiter) {
1566            RoutingSlipDefinition<Type> answer = new RoutingSlipDefinition<Type>(header, uriDelimiter);
1567            addOutput(answer);
1568            return (Type) this;
1569        }
1570    
1571        /**
1572         * <a href="http://camel.apache.org/routing-slip.html">Routing Slip EIP:</a>
1573         * Creates a routing slip allowing you to route a message consecutively through a series of processing
1574         * steps where the sequence of steps is not known at design time and can vary for each message.
1575         * <p/>
1576         * The list of URIs will be split based on the default delimiter {@link RoutingSlipDefinition#DEFAULT_DELIMITER}
1577         * <p/>
1578         * The route slip will be evaluated <i>once</i>, use {@link #dynamicRouter()} if you need even more dynamic routing.
1579         *
1580         * @param header  is the header that the {@link org.apache.camel.processor.RoutingSlip RoutingSlip}
1581         *                class will look in for the list of URIs to route the message to.
1582         * @return the builder
1583         * @deprecated prefer to use {@link #routingSlip(org.apache.camel.Expression)} instead
1584         */
1585        @SuppressWarnings("unchecked")
1586        @Deprecated
1587        public Type routingSlip(String header) {
1588            RoutingSlipDefinition<Type> answer = new RoutingSlipDefinition<Type>(header);
1589            addOutput(answer);
1590            return (Type) this;
1591        }
1592        
1593        /**
1594         * <a href="http://camel.apache.org/routing-slip.html">Routing Slip EIP:</a>
1595         * Creates a routing slip allowing you to route a message consecutively through a series of processing
1596         * steps where the sequence of steps is not known at design time and can vary for each message.
1597         * <p/>
1598         * The route slip will be evaluated <i>once</i>, use {@link #dynamicRouter()} if you need even more dynamic routing.
1599         *
1600         * @param header  is the header that the {@link org.apache.camel.processor.RoutingSlip RoutingSlip}
1601         *                class will look in for the list of URIs to route the message to.
1602         * @param uriDelimiter  is the delimiter that will be used to split up
1603         *                      the list of URIs in the routing slip.
1604         * @param ignoreInvalidEndpoints if this parameter is true, routingSlip will ignore the endpoints which
1605         *                               cannot be resolved or a producer cannot be created or started 
1606         * @return the builder
1607         * @deprecated prefer to use {@link #routingSlip()} instead
1608         */
1609        @SuppressWarnings("unchecked")
1610        @Deprecated
1611        public Type routingSlip(String header, String uriDelimiter, boolean ignoreInvalidEndpoints) {
1612            RoutingSlipDefinition<Type> answer = new RoutingSlipDefinition<Type>(header, uriDelimiter);
1613            answer.setIgnoreInvalidEndpoints(ignoreInvalidEndpoints);
1614            addOutput(answer);
1615            return (Type) this;
1616        }
1617    
1618        /**
1619         * <a href="http://camel.apache.org/routing-slip.html">Routing Slip EIP:</a>
1620         * Creates a routing slip allowing you to route a message consecutively through a series of processing
1621         * steps where the sequence of steps is not known at design time and can vary for each message.
1622         * <p/>
1623         * The list of URIs will be split based on the default delimiter {@link RoutingSlipDefinition#DEFAULT_DELIMITER}
1624         * <p/>
1625         * The route slip will be evaluated <i>once</i>, use {@link #dynamicRouter()} if you need even more dynamic routing.
1626         *
1627         * @param header  is the header that the {@link org.apache.camel.processor.RoutingSlip RoutingSlip}
1628         *                class will look in for the list of URIs to route the message to.
1629         * @param ignoreInvalidEndpoints if this parameter is true, routingSlip will ignore the endpoints which
1630         *                               cannot be resolved or a producer cannot be created or started 
1631         * @return the builder
1632         * @deprecated prefer to use {@link #routingSlip()} instead
1633         */
1634        @SuppressWarnings("unchecked")
1635        @Deprecated
1636        public Type routingSlip(String header, boolean ignoreInvalidEndpoints) {
1637            RoutingSlipDefinition<Type> answer = new RoutingSlipDefinition<Type>(header);
1638            answer.setIgnoreInvalidEndpoints(ignoreInvalidEndpoints);
1639            addOutput(answer);
1640            return (Type) this;
1641        }
1642        
1643        /**
1644         * <a href="http://camel.apache.org/routing-slip.html">Routing Slip EIP:</a>
1645         * Creates a routing slip allowing you to route a message consecutively through a series of processing
1646         * steps where the sequence of steps is not known at design time and can vary for each message.
1647         * <p/>
1648         * The route slip will be evaluated <i>once</i>, use {@link #dynamicRouter()} if you need even more dynamic routing.
1649         *
1650         * @param expression  to decide the destinations
1651         * @param uriDelimiter  is the delimiter that will be used to split up
1652         *                      the list of URIs in the routing slip.
1653         * @return the builder
1654         */
1655        public RoutingSlipDefinition<Type> routingSlip(Expression expression, String uriDelimiter) {
1656            RoutingSlipDefinition<Type> answer = new RoutingSlipDefinition<Type>(expression, uriDelimiter);
1657            addOutput(answer);
1658            return answer;
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 expression  to decide the destinations
1671         * @return the builder
1672         */
1673        public RoutingSlipDefinition<Type> routingSlip(Expression expression) {
1674            RoutingSlipDefinition<Type> answer = new RoutingSlipDefinition<Type>(expression);
1675            addOutput(answer);
1676            return answer;
1677        }
1678        
1679        /**
1680         * <a href="http://camel.apache.org/routing-slip.html">Routing Slip EIP:</a>
1681         * Creates a routing slip allowing you to route a message consecutively through a series of processing
1682         * steps where the sequence of steps is not known at design time and can vary for each message.
1683         * <p/>
1684         * The list of URIs will be split based on the default delimiter {@link RoutingSlipDefinition#DEFAULT_DELIMITER}
1685         * <p/>
1686         * The route slip will be evaluated <i>once</i>, use {@link #dynamicRouter()} if you need even more dynamic routing.
1687         *
1688         * @return the expression clause to configure the expression to decide the destinations
1689         */
1690        public ExpressionClause<RoutingSlipDefinition<Type>> routingSlip() {
1691            RoutingSlipDefinition<Type> answer = new RoutingSlipDefinition<Type>();
1692            addOutput(answer);
1693            return ExpressionClause.createAndSetExpression(answer);
1694        }
1695    
1696        /**
1697         * <a href="http://camel.apache.org/dynamic-router.html">Dynamic Router EIP:</a>
1698         * Creates a dynamic router allowing you to route a message consecutively through a series of processing
1699         * steps where the sequence of steps is not known at design time and can vary for each message.
1700         * <p/>
1701         * <br/><b>Important:</b> The expression will be invoked repeatedly until it returns <tt>null</tt>, so be sure it does that,
1702         * otherwise it will be invoked endlessly.
1703         *
1704         * @param expression  to decide the destinations, which will be invoked repeatedly
1705         *                    until it evaluates <tt>null</tt> to indicate no more destinations.
1706         * @return the builder
1707         */
1708        public DynamicRouterDefinition<Type> dynamicRouter(Expression expression) {
1709            DynamicRouterDefinition<Type> answer = new DynamicRouterDefinition<Type>(expression);
1710            addOutput(answer);
1711            return answer;
1712        }
1713    
1714        /**
1715         * <a href="http://camel.apache.org/dynamic-router.html">Dynamic Router EIP:</a>
1716         * Creates a dynamic router allowing you to route a message consecutively through a series of processing
1717         * steps where the sequence of steps is not known at design time and can vary for each message.
1718         * <p/>
1719         * <br/><b>Important:</b> The expression will be invoked repeatedly until it returns <tt>null</tt>, so be sure it does that,
1720         * otherwise it will be invoked endlessly.
1721         *
1722         * @return the expression clause to configure the expression to decide the destinations,
1723         * which will be invoked repeatedly until it evaluates <tt>null</tt> to indicate no more destinations.
1724         */
1725        public ExpressionClause<DynamicRouterDefinition<Type>> dynamicRouter() {
1726            DynamicRouterDefinition<Type> answer = new DynamicRouterDefinition<Type>();
1727            addOutput(answer);
1728            return ExpressionClause.createAndSetExpression(answer);
1729        }
1730    
1731        /**
1732         * <a href="http://camel.apache.org/sampling.html">Sampling Throttler</a>
1733         * Creates a sampling throttler allowing you to extract a sample of
1734         * exchanges from the traffic on a route. It is configured with a sampling
1735         * period, during which only a single exchange is allowed to pass through.
1736         * All other exchanges will be stopped.
1737         * <p/>
1738         * Default period is one second.
1739         *
1740         * @return the builder
1741         */
1742        public SamplingDefinition sample() {
1743            return sample(1, TimeUnit.SECONDS);
1744        }
1745    
1746        /**
1747         * <a href="http://camel.apache.org/sampling.html">Sampling Throttler</a>
1748         * Creates a sampling throttler allowing you to extract a sample of exchanges
1749         * from the traffic through a route. It is configured with a sampling period
1750         * during which only a single exchange is allowed to pass through.
1751         * All other exchanges will be stopped.
1752         *
1753         * @param samplePeriod this is the sample interval, only one exchange is
1754         *            allowed through in this interval
1755         * @param unit this is the units for the samplePeriod e.g. Seconds
1756         * @return the builder
1757         */
1758        public SamplingDefinition sample(long samplePeriod, TimeUnit unit) {
1759            SamplingDefinition answer = new SamplingDefinition(samplePeriod, unit);
1760            addOutput(answer);
1761            return answer;
1762        }
1763    
1764        /**
1765         * <a href="http://camel.apache.org/sampling.html">Sampling Throttler</a>
1766         * Creates a sampling throttler allowing you to extract a sample of exchanges
1767         * from the traffic through a route. It is configured with a sampling message frequency
1768         * during which only a single exchange is allowed to pass through.
1769         * All other exchanges will be stopped.
1770         *
1771         * @param messageFrequency this is the sample message frequency, only one exchange is 
1772         *              allowed through for this many messages received
1773         * @return the builder
1774         */
1775        public SamplingDefinition sample(long messageFrequency) {
1776            SamplingDefinition answer = new SamplingDefinition(messageFrequency);
1777            addOutput(answer);
1778            return answer;
1779        }
1780    
1781        /**
1782         * <a href="http://camel.apache.org/splitter.html">Splitter EIP:</a>
1783         * Creates a splitter allowing you split a message into a number of pieces and process them individually.
1784         * <p>
1785         * This splitter responds with the original input message. You can use a custom {@link AggregationStrategy} to
1786         * control what to respond from the splitter.
1787         *
1788         * @return the expression clause builder for the expression on which to split
1789         */
1790        public ExpressionClause<SplitDefinition> split() {
1791            SplitDefinition answer = new SplitDefinition();
1792            addOutput(answer);
1793            return ExpressionClause.createAndSetExpression(answer);
1794        }
1795    
1796        /**
1797         * <a href="http://camel.apache.org/splitter.html">Splitter EIP:</a>
1798         * Creates a splitter allowing you split a message into a number of pieces and process them individually.
1799         * <p>
1800         * This splitter responds with the original input message. You can use a custom {@link AggregationStrategy} to
1801         * control what to respond from the splitter.
1802         *
1803         * @param expression  the expression on which to split the message
1804         * @return the builder
1805         */
1806        public SplitDefinition split(Expression expression) {
1807            SplitDefinition answer = new SplitDefinition(expression);
1808            addOutput(answer);
1809            return answer;
1810        }
1811    
1812        /**
1813         * <a href="http://camel.apache.org/splitter.html">Splitter EIP:</a>
1814         * Creates a splitter allowing you split a message into a number of pieces and process them individually.
1815         * <p>
1816         * The splitter responds with the answer produced by the given {@link AggregationStrategy}.
1817         *
1818         * @param expression  the expression on which to split
1819         * @param aggregationStrategy  the strategy used to aggregate responses for every part
1820         * @return the builder
1821         */
1822        public SplitDefinition split(Expression expression, AggregationStrategy aggregationStrategy) {
1823            SplitDefinition answer = new SplitDefinition(expression);
1824            addOutput(answer);
1825            answer.setAggregationStrategy(aggregationStrategy);
1826            return answer;
1827        }
1828    
1829        /**
1830         * <a href="http://camel.apache.org/resequencer.html">Resequencer EIP:</a>
1831         * Creates a resequencer allowing you to reorganize messages based on some comparator.
1832         *
1833         * @return the expression clause for the expressions on which to compare messages in order
1834         */
1835        public ExpressionClause<ResequenceDefinition> resequence() {
1836            ResequenceDefinition answer = new ResequenceDefinition();
1837            ExpressionClause<ResequenceDefinition> clause = new ExpressionClause<ResequenceDefinition>(answer);
1838            answer.setExpression(clause);
1839            addOutput(answer);
1840            return clause;
1841        }
1842    
1843        /**
1844         * <a href="http://camel.apache.org/resequencer.html">Resequencer EIP:</a>
1845         * Creates a resequencer allowing you to reorganize messages based on some comparator.
1846         *
1847         * @param expression the expression on which to compare messages in order
1848         * @return the builder
1849         */
1850        public ResequenceDefinition resequence(Expression expression) {
1851            ResequenceDefinition answer = new ResequenceDefinition();
1852            answer.setExpression(new ExpressionDefinition(expression));
1853            addOutput(answer);
1854            return answer;
1855        }
1856    
1857        /**
1858         * <a href="http://camel.apache.org/aggregator.html">Aggregator EIP:</a>
1859         * Creates an aggregator allowing you to combine a number of messages together into a single message.
1860         *
1861         * @return the expression clause to be used as builder to configure the correlation expression
1862         */
1863        public ExpressionClause<AggregateDefinition> aggregate() {
1864            AggregateDefinition answer = new AggregateDefinition();
1865            ExpressionClause<AggregateDefinition> clause = new ExpressionClause<AggregateDefinition>(answer);
1866            answer.setExpression(clause);
1867            addOutput(answer);
1868            return clause;
1869        }
1870    
1871        /**
1872         * <a href="http://camel.apache.org/aggregator.html">Aggregator EIP:</a>
1873         * Creates an aggregator allowing you to combine a number of messages together into a single message.
1874         *
1875         * @param aggregationStrategy the strategy used for the aggregation
1876         * @return the expression clause to be used as builder to configure the correlation expression
1877         */
1878        public ExpressionClause<AggregateDefinition> aggregate(AggregationStrategy aggregationStrategy) {
1879            AggregateDefinition answer = new AggregateDefinition();
1880            ExpressionClause<AggregateDefinition> clause = new ExpressionClause<AggregateDefinition>(answer);
1881            answer.setExpression(clause);
1882            answer.setAggregationStrategy(aggregationStrategy);
1883            addOutput(answer);
1884            return clause;
1885        }
1886    
1887        /**
1888         * <a href="http://camel.apache.org/aggregator.html">Aggregator EIP:</a>
1889         * Creates an aggregator allowing you to combine a number of messages together into a single message.
1890         *
1891         * @param correlationExpression the expression used to calculate the
1892         *                              correlation key. For a JMS message this could be the
1893         *                              expression <code>header("JMSDestination")</code> or
1894         *                              <code>header("JMSCorrelationID")</code>
1895         * @return the builder
1896         */
1897        public AggregateDefinition aggregate(Expression correlationExpression) {
1898            AggregateDefinition answer = new AggregateDefinition(correlationExpression);
1899            addOutput(answer);
1900            return answer;
1901        }
1902    
1903        /**
1904         * <a href="http://camel.apache.org/aggregator.html">Aggregator EIP:</a>
1905         * Creates an aggregator allowing you to combine a number of messages together into a single message.
1906         *
1907         * @param correlationExpression the expression used to calculate the
1908         *                              correlation key. For a JMS message this could be the
1909         *                              expression <code>header("JMSDestination")</code> or
1910         *                              <code>header("JMSCorrelationID")</code>
1911         * @param aggregationStrategy the strategy used for the aggregation
1912         * @return the builder
1913         */
1914        public AggregateDefinition aggregate(Expression correlationExpression, AggregationStrategy aggregationStrategy) {
1915            AggregateDefinition answer = new AggregateDefinition(correlationExpression, aggregationStrategy);
1916            addOutput(answer);
1917            return answer;
1918        }
1919    
1920        /**
1921         * <a href="http://camel.apache.org/delayer.html">Delayer EIP:</a>
1922         * Creates a delayer allowing you to delay the delivery of messages to some destination.
1923         *
1924         * @param delay  an expression to calculate the delay time in millis
1925         * @return the builder
1926         */
1927        public DelayDefinition delay(Expression delay) {
1928            DelayDefinition answer = new DelayDefinition(delay);
1929            addOutput(answer);
1930            return answer;
1931        }
1932    
1933        /**
1934         * <a href="http://camel.apache.org/delayer.html">Delayer EIP:</a>
1935         * Creates a delayer allowing you to delay the delivery of messages to some destination.
1936         *
1937         * @return the expression clause to create the expression
1938         */
1939        public ExpressionClause<DelayDefinition> delay() {
1940            DelayDefinition answer = new DelayDefinition();
1941            addOutput(answer);
1942            return ExpressionClause.createAndSetExpression(answer);
1943        }
1944    
1945        /**
1946         * <a href="http://camel.apache.org/delayer.html">Delayer EIP:</a>
1947         * Creates a delayer allowing you to delay the delivery of messages to some destination.
1948         *
1949         * @param delay  the delay in millis
1950         * @return the builder
1951         */
1952        public DelayDefinition delay(long delay) {
1953            return delay(ExpressionBuilder.constantExpression(delay));
1954        }
1955    
1956        /**
1957         * <a href="http://camel.apache.org/throttler.html">Throttler EIP:</a>
1958         * Creates a throttler allowing you to ensure that a specific endpoint does not get overloaded,
1959         * or that we don't exceed an agreed SLA with some external service.
1960         * <p/>
1961         * Will default use a time period of 1 second, so setting the maximumRequestCount to eg 10
1962         * will default ensure at most 10 messages per second. 
1963         *
1964         * @param maximumRequestCount  the maximum messages 
1965         * @return the builder
1966         */
1967        public ThrottleDefinition throttle(long maximumRequestCount) {
1968            return throttle(ExpressionBuilder.constantExpression(maximumRequestCount));
1969        }
1970    
1971        /**
1972         * <a href="http://camel.apache.org/throttler.html">Throttler EIP:</a>
1973         * Creates a throttler allowing you to ensure that a specific endpoint does not get overloaded,
1974         * or that we don't exceed an agreed SLA with some external service.
1975         * <p/>
1976         * Will default use a time period of 1 second, so setting the maximumRequestCount to eg 10
1977         * will default ensure at most 10 messages per second. 
1978         *
1979         * @param maximumRequestCount  an expression to calculate the maximum request count 
1980         * @return the builder
1981         */
1982        public ThrottleDefinition throttle(Expression maximumRequestCount) {
1983            ThrottleDefinition answer = new ThrottleDefinition(maximumRequestCount);
1984            addOutput(answer);
1985            return answer;
1986        }
1987        
1988        /**
1989         * <a href="http://camel.apache.org/loop.html">Loop EIP:</a>
1990         * Creates a loop allowing to process the a message a number of times and possibly process them
1991         * in a different way. Useful mostly for testing.
1992         *
1993         * @return the clause used to create the loop expression
1994         */
1995        public ExpressionClause<LoopDefinition> loop() {
1996            LoopDefinition loop = new LoopDefinition();
1997            addOutput(loop);
1998            return ExpressionClause.createAndSetExpression(loop);
1999        }
2000    
2001        /**
2002         * <a href="http://camel.apache.org/loop.html">Loop EIP:</a>
2003         * Creates a loop allowing to process the a message a number of times and possibly process them
2004         * in a different way. Useful mostly for testing.
2005         *
2006         * @param expression the loop expression
2007         * @return the builder
2008         */
2009        public LoopDefinition loop(Expression expression) {
2010            LoopDefinition loop = getNodeFactory().createLoop();
2011            loop.setExpression(expression);
2012            addOutput(loop);
2013            return loop;
2014        }
2015    
2016        /**
2017         * <a href="http://camel.apache.org/loop.html">Loop EIP:</a>
2018         * Creates a loop allowing to process the a message a number of times and possibly process them
2019         * in a different way. Useful mostly for testing.
2020         *
2021         * @param count  the number of times
2022         * @return the builder
2023         */
2024        public LoopDefinition loop(int count) {
2025            LoopDefinition loop = getNodeFactory().createLoop();
2026            loop.setExpression(new ConstantExpression(Integer.toString(count)));
2027            addOutput(loop);
2028            return loop;
2029        }
2030    
2031        /**
2032         * Sets the exception on the {@link org.apache.camel.Exchange}
2033         *
2034         * @param exception the exception to throw
2035         * @return the builder
2036         */
2037        @SuppressWarnings("unchecked")
2038        public Type throwException(Exception exception) {
2039            ThrowExceptionDefinition answer = new ThrowExceptionDefinition();
2040            answer.setException(exception);
2041            addOutput(answer);
2042            return (Type) this;
2043        }
2044    
2045        /**
2046         * Marks the exchange for rollback only.
2047         * <p/>
2048         * Does <b>not</b> set any exception as opposed to {@link #rollback()} methods.
2049         *
2050         * @return the builder
2051         * @see #rollback()
2052         * @see #rollback(String)
2053         * @see #markRollbackOnlyLast()
2054         */
2055        @SuppressWarnings("unchecked")
2056        public Type markRollbackOnly() {
2057            RollbackDefinition answer = new RollbackDefinition();
2058            answer.setMarkRollbackOnly(true);
2059            addOutput(answer);
2060            return (Type) this;
2061        }
2062    
2063        /**
2064         * Marks the exchange for rollback only, but only for the last (current) transaction.
2065         * <p/>
2066         * A last rollback is used when you have nested transactions and only want the last local transaction to rollback,
2067         * where as the outer transaction can still be completed
2068         * <p/>
2069         * Does <b>not</b> set any exception as opposed to {@link #rollback()} methods.
2070         *
2071         * @return the builder
2072         * @see #rollback()
2073         * @see #rollback(String)
2074         * @see #markRollbackOnly()
2075         */
2076        @SuppressWarnings("unchecked")
2077        public Type markRollbackOnlyLast() {
2078            RollbackDefinition answer = new RollbackDefinition();
2079            answer.setMarkRollbackOnlyLast(true);
2080            addOutput(answer);
2081            return (Type) this;
2082        }
2083    
2084        /**
2085         * Marks the exchange for rollback only and sets an exception with a default message.
2086         * <p/>
2087         * This is done by setting a {@link org.apache.camel.RollbackExchangeException} on the Exchange
2088         * and mark it for rollback.
2089         *
2090         * @return the builder
2091         * @see #markRollbackOnly()
2092         */
2093        public Type rollback() {
2094            return rollback(null);
2095        }
2096    
2097        /**
2098         * Marks the exchange for rollback and sets an exception with the provided message.
2099         * <p/>
2100         * This is done by setting a {@link org.apache.camel.RollbackExchangeException} on the Exchange
2101         * and mark it for rollback.
2102         *
2103         * @param message an optional message used for logging purpose why the rollback was triggered
2104         * @return the builder
2105         * @see #markRollbackOnly()
2106         */
2107        @SuppressWarnings("unchecked")
2108        public Type rollback(String message) {
2109            RollbackDefinition answer = new RollbackDefinition(message);
2110            addOutput(answer);
2111            return (Type) this;
2112        }
2113    
2114        /**
2115         * <a href="http://camel.apache.org/wiretap.html">WireTap EIP:</a>
2116         * Sends messages to all its child outputs; so that each processor and
2117         * destination gets a copy of the original message to avoid the processors
2118         * interfering with each other using {@link ExchangePattern#InOnly}.
2119         *
2120         * @param uri  the destination
2121         * @return the builder
2122         */
2123        public WireTapDefinition<Type> wireTap(String uri) {
2124            WireTapDefinition<Type> answer = new WireTapDefinition<Type>();
2125            answer.setUri(uri);
2126            addOutput(answer);
2127            return answer;
2128        }
2129    
2130        /**
2131         * <a href="http://camel.apache.org/wiretap.html">WireTap EIP:</a>
2132         * Sends messages to all its child outputs; so that each processor and
2133         * destination gets a copy of the original message to avoid the processors
2134         * interfering with each other using {@link ExchangePattern#InOnly}.
2135         *
2136         * @param uri  the destination
2137         * @param      executorService a custom {@link ExecutorService} to use as thread pool
2138         *             for sending tapped exchanges
2139         * @return the builder
2140         * @deprecated use the fluent builder from {@link WireTapDefinition}, will be removed in Camel 3.0
2141         */
2142        @Deprecated
2143        public WireTapDefinition<Type> wireTap(String uri, ExecutorService executorService) {
2144            WireTapDefinition<Type> answer = new WireTapDefinition<Type>();
2145            answer.setUri(uri);
2146            answer.setExecutorService(executorService);
2147            addOutput(answer);
2148            return answer;
2149        }
2150    
2151        /**
2152         * <a href="http://camel.apache.org/wiretap.html">WireTap EIP:</a>
2153         * Sends messages to all its child outputs; so that each processor and
2154         * destination gets a copy of the original message to avoid the processors
2155         * interfering with each other using {@link ExchangePattern#InOnly}.
2156         *
2157         * @param uri  the destination
2158         * @param      executorServiceRef reference to lookup a custom {@link ExecutorService}
2159         *             to use as thread pool for sending tapped exchanges
2160         * @return the builder
2161         * @deprecated use the fluent builder from {@link WireTapDefinition}, will be removed in Camel 3.0
2162         */
2163        @Deprecated
2164        public WireTapDefinition<Type> wireTap(String uri, String executorServiceRef) {
2165            WireTapDefinition<Type> answer = new WireTapDefinition<Type>();
2166            answer.setUri(uri);
2167            answer.setExecutorServiceRef(executorServiceRef);
2168            addOutput(answer);
2169            return answer;
2170        }
2171    
2172        /**
2173         * <a href="http://camel.apache.org/wiretap.html">WireTap EIP:</a>
2174         * Sends a new {@link org.apache.camel.Exchange} to the destination
2175         * using {@link ExchangePattern#InOnly}.
2176         * <p/>
2177         * Will use a copy of the original Exchange which is passed in as argument
2178         * to the given expression
2179         *
2180         * @param uri  the destination
2181         * @param body expression that creates the body to send
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, Expression body) {
2187            return wireTap(uri, true, body);
2188        }
2189    
2190        /**
2191         * <a href="http://camel.apache.org/wiretap.html">WireTap EIP:</a>
2192         * Sends a new {@link org.apache.camel.Exchange} to the destination
2193         * using {@link ExchangePattern#InOnly}.
2194         *
2195         * @param uri  the destination
2196         * @param copy whether or not use a copy of the original exchange or a new empty exchange
2197         * @param body expression that creates the body to send
2198         * @return the builder
2199         * @deprecated use the fluent builder from {@link WireTapDefinition}, will be removed in Camel 3.0
2200         */
2201        @Deprecated
2202        public WireTapDefinition<Type> wireTap(String uri, boolean copy, Expression body) {
2203            WireTapDefinition<Type> answer = new WireTapDefinition<Type>();
2204            answer.setUri(uri);
2205            answer.setCopy(copy);
2206            answer.setNewExchangeExpression(body);
2207            addOutput(answer);
2208            return answer;
2209        }
2210    
2211        /**
2212         * <a href="http://camel.apache.org/wiretap.html">WireTap EIP:</a>
2213         * Sends a new {@link org.apache.camel.Exchange} to the destination
2214         * using {@link ExchangePattern#InOnly}.
2215         * <p/>
2216         * Will use a copy of the original Exchange which is passed in as argument
2217         * to the given processor
2218         *
2219         * @param uri  the destination
2220         * @param processor  processor preparing the new exchange to send
2221         * @return the builder
2222         * @deprecated use the fluent builder from {@link WireTapDefinition}, will be removed in Camel 3.0
2223         */
2224        @Deprecated
2225        public WireTapDefinition<Type> wireTap(String uri, Processor processor) {
2226            return wireTap(uri, true, processor);
2227        }
2228    
2229        /**
2230         * <a href="http://camel.apache.org/wiretap.html">WireTap EIP:</a>
2231         * Sends a new {@link org.apache.camel.Exchange} to the destination
2232         * using {@link ExchangePattern#InOnly}.
2233         *
2234         * @param uri  the destination
2235         * @param copy whether or not use a copy of the original exchange or a new empty exchange
2236         * @param processor  processor preparing the new exchange to send
2237         * @return the builder
2238         * @deprecated use the fluent builder from {@link WireTapDefinition}, will be removed in Camel 3.0
2239         */
2240        @Deprecated
2241        public WireTapDefinition<Type> wireTap(String uri, boolean copy, Processor processor) {
2242            WireTapDefinition<Type> answer = new WireTapDefinition<Type>();
2243            answer.setUri(uri);
2244            answer.setCopy(copy);
2245            answer.setNewExchangeProcessor(processor);
2246            addOutput(answer);
2247            return answer;
2248        }
2249    
2250        /**
2251         * Pushes the given block on the stack as current block
2252         *
2253         * @param block  the block
2254         */
2255        void pushBlock(Block block) {
2256            blocks.add(block);
2257        }
2258    
2259        /**
2260         * Pops the block off the stack as current block
2261         *
2262         * @return the block
2263         */
2264        Block popBlock() {
2265            return blocks.isEmpty() ? null : blocks.removeLast();
2266        }
2267    
2268        /**
2269         * Stops continue routing the current {@link org.apache.camel.Exchange} and marks it as completed.
2270         *
2271         * @return the builder
2272         */
2273        @SuppressWarnings("unchecked")
2274        public Type stop() {
2275            StopDefinition stop = new StopDefinition();
2276            addOutput(stop);
2277            return (Type) this;
2278        }
2279    
2280        /**
2281         * <a href="http://camel.apache.org/exception-clause.html">Exception clause</a>
2282         * for catching certain exceptions and handling them.
2283         *
2284         * @param exceptionType  the exception to catch
2285         * @return the exception builder to configure
2286         */
2287        public OnExceptionDefinition onException(Class<? extends Throwable> exceptionType) {
2288            OnExceptionDefinition answer = new OnExceptionDefinition(exceptionType);
2289            addOutput(answer);
2290            return answer;
2291        }
2292    
2293        /**
2294         * <a href="http://camel.apache.org/exception-clause.html">Exception clause</a>
2295         * for catching certain exceptions and handling them.
2296         *
2297         * @param exceptions list of exceptions to catch
2298         * @return the exception builder to configure
2299         */
2300        public OnExceptionDefinition onException(Class<? extends Throwable>... exceptions) {
2301            OnExceptionDefinition answer = new OnExceptionDefinition(Arrays.asList(exceptions));
2302            addOutput(answer);
2303            return answer;
2304        }
2305    
2306        /**
2307         * Apply a {@link Policy}.
2308         * <p/>
2309         * Policy can be used for transactional policies.
2310         *
2311         * @param policy  the policy to apply
2312         * @return the policy builder to configure
2313         */
2314        public PolicyDefinition policy(Policy policy) {
2315            PolicyDefinition answer = new PolicyDefinition(policy);
2316            addOutput(answer);
2317            return answer;
2318        }
2319    
2320        /**
2321         * Apply a {@link Policy}.
2322         * <p/>
2323         * Policy can be used for transactional policies.
2324         *
2325         * @param ref  reference to lookup a policy in the registry
2326         * @return the policy builder to configure
2327         */
2328        public PolicyDefinition policy(String ref) {
2329            PolicyDefinition answer = new PolicyDefinition();
2330            answer.setRef(ref);
2331            addOutput(answer);
2332            return answer;
2333        }
2334    
2335        /**
2336         * Marks this route as transacted and uses the default transacted policy found in the registry.
2337         *
2338         * @return the policy builder to configure
2339         */
2340        public PolicyDefinition transacted() {
2341            PolicyDefinition answer = new PolicyDefinition();
2342            answer.setType(TransactedPolicy.class);
2343            addOutput(answer);
2344            return answer;
2345        }
2346    
2347        /**
2348         * Marks this route as transacted.
2349         *
2350         * @param ref  reference to lookup a transacted policy in the registry
2351         * @return the policy builder to configure
2352         */
2353        public PolicyDefinition transacted(String ref) {
2354            PolicyDefinition answer = new PolicyDefinition();
2355            answer.setType(TransactedPolicy.class);
2356            answer.setRef(ref);
2357            addOutput(answer);
2358            return answer;
2359        }
2360    
2361        // Transformers
2362        // -------------------------------------------------------------------------
2363    
2364        /**
2365         * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
2366         * Adds the custom processor to this destination which could be a final
2367         * destination, or could be a transformation in a pipeline
2368         *
2369         * @param processor  the custom {@link Processor}
2370         * @return the builder
2371         */
2372        @SuppressWarnings("unchecked")
2373        public Type process(Processor processor) {
2374            ProcessDefinition answer = new ProcessDefinition(processor);
2375            addOutput(answer);
2376            return (Type) this;
2377        }
2378    
2379        /**
2380         * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
2381         * Adds the custom processor reference to this destination which could be a final
2382         * destination, or could be a transformation in a pipeline
2383         *
2384         * @param ref   reference to a {@link Processor} to lookup in the registry
2385         * @return the builder
2386         */
2387        @SuppressWarnings("unchecked")
2388        public Type processRef(String ref) {
2389            ProcessDefinition answer = new ProcessDefinition();
2390            answer.setRef(ref);
2391            addOutput(answer);
2392            return (Type) this;
2393        }
2394    
2395        /**
2396         * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
2397         * Adds a bean which is invoked which could be a final destination, or could be a transformation in a pipeline
2398         *
2399         * @param bean  the bean to invoke
2400         * @return the builder
2401         */
2402        @SuppressWarnings("unchecked")
2403        public Type bean(Object bean) {
2404            BeanDefinition answer = new BeanDefinition();
2405            answer.setBean(bean);
2406            addOutput(answer);
2407            return (Type) this;
2408        }
2409    
2410        /**
2411         * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
2412         * Adds a bean which is invoked which could be a final destination, or could be a transformation in a pipeline
2413         *
2414         * @param bean  the bean to invoke
2415         * @param method  the method name to invoke on the bean (can be used to avoid ambiguity)
2416         * @return the builder
2417         */
2418        @SuppressWarnings("unchecked")
2419        public Type bean(Object bean, String method) {
2420            BeanDefinition answer = new BeanDefinition();
2421            answer.setBean(bean);
2422            answer.setMethod(method);
2423            addOutput(answer);
2424            return (Type) this;
2425        }
2426    
2427        /**
2428         * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
2429         * Adds a bean which is invoked which could be a final destination, or could be a transformation in a pipeline
2430         *
2431         * @param  beanType  the bean class, Camel will instantiate an object at runtime
2432         * @return the builder
2433         */
2434        @SuppressWarnings("unchecked")
2435        public Type bean(Class<?> beanType) {
2436            BeanDefinition answer = new BeanDefinition();
2437            answer.setBeanType(beanType);
2438            addOutput(answer);
2439            return (Type) this;
2440        }
2441    
2442        /**
2443         * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
2444         * Adds a bean which is invoked which could be a final destination, or could be a transformation in a pipeline
2445         *
2446         * @param  beanType  the bean class, Camel will instantiate an object at runtime
2447         * @param method  the method name to invoke on the bean (can be used to avoid ambiguity)
2448         * @return the builder
2449         */
2450        @SuppressWarnings("unchecked")
2451        public Type bean(Class<?> beanType, String method) {
2452            BeanDefinition answer = new BeanDefinition();
2453            answer.setBeanType(beanType);
2454            answer.setMethod(method);
2455            addOutput(answer);
2456            return (Type) this;
2457        }
2458    
2459        /**
2460         * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
2461         * Adds a bean which is invoked which could be a final destination, or could be a transformation in a pipeline
2462         *
2463         * @param ref  reference to a bean to lookup in the registry
2464         * @return the builder
2465         */
2466        @SuppressWarnings("unchecked")
2467        public Type beanRef(String ref) {
2468            BeanDefinition answer = new BeanDefinition(ref);
2469            addOutput(answer);
2470            return (Type) this;
2471        }
2472    
2473        /**
2474         * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
2475         * Adds a bean which is invoked which could be a final destination, or could be a transformation in a pipeline
2476         *
2477         * @param ref  reference to a bean to lookup in the registry
2478         * @param method  the method name to invoke on the bean (can be used to avoid ambiguity)
2479         * @return the builder
2480         */
2481        @SuppressWarnings("unchecked")
2482        public Type beanRef(String ref, String method) {
2483            BeanDefinition answer = new BeanDefinition(ref, method);
2484            addOutput(answer);
2485            return (Type) this;
2486        }
2487    
2488        /**
2489         * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
2490         * Adds a processor which sets the body on the IN message
2491         *
2492         * @return a expression builder clause to set the body
2493         */
2494        public ExpressionClause<ProcessorDefinition<Type>> setBody() {
2495            ExpressionClause<ProcessorDefinition<Type>> clause = new ExpressionClause<ProcessorDefinition<Type>>(this);
2496            SetBodyDefinition answer = new SetBodyDefinition(clause);
2497            addOutput(answer);
2498            return clause;
2499        }
2500    
2501        /**
2502         * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
2503         * Adds a processor which sets the body on the IN message
2504         *
2505         * @param expression   the expression used to set the body
2506         * @return the builder
2507         */
2508        @SuppressWarnings("unchecked")
2509        public Type setBody(Expression expression) {
2510            SetBodyDefinition answer = new SetBodyDefinition(expression);
2511            addOutput(answer);
2512            return (Type) this;
2513        }
2514    
2515        /**
2516         * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
2517         * Adds a processor which sets the body on the OUT message
2518         *
2519         * @param expression   the expression used to set the body
2520         * @return the builder
2521         */
2522        @SuppressWarnings("unchecked")
2523        public Type transform(Expression expression) {
2524            TransformDefinition answer = new TransformDefinition(expression);
2525            addOutput(answer);
2526            return (Type) this;
2527        }
2528    
2529        /**
2530         * <a href="http://camel.apache.org/message-translator.html">Message Translator EIP:</a>
2531         * Adds a processor which sets the body on the OUT message
2532         *
2533         * @return a expression builder clause to set the body
2534         */
2535        public ExpressionClause<ProcessorDefinition<Type>> transform() {
2536            ExpressionClause<ProcessorDefinition<Type>> clause = 
2537                new ExpressionClause<ProcessorDefinition<Type>>((ProcessorDefinition<Type>) this);
2538            TransformDefinition answer = new TransformDefinition(clause);
2539            addOutput(answer);
2540            return clause;
2541        }
2542    
2543        /**
2544         * Adds a processor which sets the body on the FAULT message
2545         *
2546         * @param expression   the expression used to set the body
2547         * @return the builder
2548         */
2549        public Type setFaultBody(Expression expression) {
2550            return process(ProcessorBuilder.setFaultBody(expression));
2551        }
2552    
2553        /**
2554         * Adds a processor which sets the header on the IN message
2555         *
2556         * @param name  the header name
2557         * @return a expression builder clause to set the header
2558         */
2559        public ExpressionClause<ProcessorDefinition<Type>> setHeader(String name) {
2560            ExpressionClause<ProcessorDefinition<Type>> clause = new ExpressionClause<ProcessorDefinition<Type>>(this);
2561            SetHeaderDefinition answer = new SetHeaderDefinition(name, clause);
2562            addOutput(answer);
2563            return clause;
2564        }
2565    
2566        /**
2567         * Adds a processor which sets the header on the IN message
2568         *
2569         * @param name  the header name
2570         * @param expression  the expression used to set the header
2571         * @return the builder
2572         */
2573        @SuppressWarnings("unchecked")
2574        public Type setHeader(String name, Expression expression) {
2575            SetHeaderDefinition answer = new SetHeaderDefinition(name, expression);
2576            addOutput(answer);
2577            return (Type) this;
2578        }
2579    
2580        /**
2581         * Adds a processor which sets the header on the OUT message
2582         *
2583         * @param name  the header name
2584         * @return a expression builder clause to set the header
2585         * @deprecated use {@link #setHeader(String)}
2586         */
2587        @Deprecated
2588        public ExpressionClause<ProcessorDefinition<Type>> setOutHeader(String name) {
2589            ExpressionClause<ProcessorDefinition<Type>> clause = new ExpressionClause<ProcessorDefinition<Type>>(this);
2590            SetOutHeaderDefinition answer = new SetOutHeaderDefinition(name, clause);
2591            addOutput(answer);
2592            return clause;
2593        }
2594    
2595        /**
2596         * Adds a processor which sets the header on the OUT message
2597         *
2598         * @param name  the header name
2599         * @param expression  the expression used to set the header
2600         * @return the builder
2601         * @deprecated use {@link #setHeader(String, org.apache.camel.Expression)}
2602         */
2603        @SuppressWarnings("unchecked")
2604        @Deprecated
2605        public Type setOutHeader(String name, Expression expression) {
2606            SetOutHeaderDefinition answer = new SetOutHeaderDefinition(name, expression);
2607            addOutput(answer);
2608            return (Type) this;
2609        }
2610    
2611        /**
2612         * Adds a processor which sets the header on the FAULT message
2613         *
2614         * @param name  the header name
2615         * @param expression  the expression used to set the header
2616         * @return the builder
2617         * @deprecated use {@link #setHeader(String, org.apache.camel.Expression)}
2618         */
2619        @Deprecated
2620        public Type setFaultHeader(String name, Expression expression) {
2621            return process(ProcessorBuilder.setFaultHeader(name, expression));
2622        }
2623    
2624        /**
2625         * Adds a processor which sets the exchange property
2626         *
2627         * @param name  the property name
2628         * @param expression  the expression used to set the property
2629         * @return the builder
2630         */
2631        @SuppressWarnings("unchecked")
2632        public Type setProperty(String name, Expression expression) {
2633            SetPropertyDefinition answer = new SetPropertyDefinition(name, expression);
2634            addOutput(answer);
2635            return (Type) this;
2636        }
2637    
2638        /**
2639         * Adds a processor which sets the exchange property
2640         *
2641         * @param name  the property name
2642         * @return a expression builder clause to set the property
2643         */
2644        public ExpressionClause<ProcessorDefinition<Type>> setProperty(String name) {
2645            ExpressionClause<ProcessorDefinition<Type>> clause = new ExpressionClause<ProcessorDefinition<Type>>(this);
2646            SetPropertyDefinition answer = new SetPropertyDefinition(name, clause);
2647            addOutput(answer);
2648            return clause;
2649        }
2650    
2651        /**
2652         * Adds a processor which removes the header on the IN message
2653         *
2654         * @param name  the header name
2655         * @return the builder
2656         */
2657        @SuppressWarnings("unchecked")
2658        public Type removeHeader(String name) {
2659            RemoveHeaderDefinition answer = new RemoveHeaderDefinition(name);
2660            addOutput(answer);
2661            return (Type) this;
2662        }
2663    
2664        /**
2665         * Adds a processor which removes the headers on the IN message
2666         *
2667         * @param pattern  a pattern to match header names to be removed
2668         * @return the builder
2669         */
2670        @SuppressWarnings("unchecked")
2671        public Type removeHeaders(String pattern) {
2672            RemoveHeadersDefinition answer = new RemoveHeadersDefinition(pattern);
2673            addOutput(answer);
2674            return (Type) this;
2675        }
2676    
2677        /**
2678         * Adds a processor which removes the headers on the IN message
2679         *
2680         * @param pattern  a pattern to match header names to be removed
2681         * @param excludePatterns one or more pattern of header names that should be excluded (= preserved)
2682         * @return the builder
2683         */
2684        @SuppressWarnings("unchecked")
2685        public Type removeHeaders(String pattern, String... excludePatterns) {
2686            RemoveHeadersDefinition answer = new RemoveHeadersDefinition(pattern, excludePatterns);
2687            addOutput(answer);
2688            return (Type) this;
2689        }
2690    
2691        /**
2692         * Adds a processor which removes the header on the FAULT message
2693         *
2694         * @param name  the header name
2695         * @return the builder
2696         * @deprecated will be removed in the near future. Instead use {@link #removeHeader(String)}
2697         */
2698        @Deprecated
2699        public Type removeFaultHeader(String name) {
2700            return process(ProcessorBuilder.removeFaultHeader(name));
2701        }
2702    
2703        /**
2704         * Adds a processor which removes the exchange property
2705         *
2706         * @param name  the property name
2707         * @return the builder
2708         */
2709        @SuppressWarnings("unchecked")
2710        public Type removeProperty(String name) {
2711            RemovePropertyDefinition answer = new RemovePropertyDefinition(name);
2712            addOutput(answer);
2713            return (Type) this;
2714        }
2715    
2716        /**
2717         * Converts the IN message body to the specified type
2718         *
2719         * @param type the type to convert to
2720         * @return the builder
2721         */
2722        @SuppressWarnings("unchecked")
2723        public Type convertBodyTo(Class<?> type) {
2724            addOutput(new ConvertBodyDefinition(type));
2725            return (Type) this;
2726        }
2727        
2728        /**
2729         * Converts the IN message body to the specified type
2730         *
2731         * @param type the type to convert to
2732         * @param charset the charset to use by type converters (not all converters support specifc charset)
2733         * @return the builder
2734         */
2735        @SuppressWarnings("unchecked")
2736        public Type convertBodyTo(Class<?> type, String charset) {
2737            addOutput(new ConvertBodyDefinition(type, charset));
2738            return (Type) this;
2739        }
2740    
2741        /**
2742         * Sorts the expression using a default sorting based on toString representation.
2743         *
2744         * @param expression  the expression, must be convertable to {@link List}
2745         * @return the builder
2746         */
2747        public Type sort(Expression expression) {
2748            return sort(expression, null);
2749        }
2750    
2751        /**
2752         * Sorts the expression using the given comparator
2753         *
2754         * @param expression  the expression, must be convertable to {@link List}
2755         * @param comparator  the comparator to use for sorting
2756         * @return the builder
2757         */
2758        @SuppressWarnings("unchecked")
2759        public <T> Type sort(Expression expression, Comparator<T> comparator) {
2760            addOutput(new SortDefinition<T>(expression, comparator));
2761            return (Type) this;
2762        }
2763    
2764        /**
2765         * Sorts the expression
2766         *
2767         * @return the builder
2768         */
2769        public <T> ExpressionClause<SortDefinition<T>> sort() {
2770            SortDefinition<T> answer = new SortDefinition<T>();
2771            addOutput(answer);
2772            return ExpressionClause.createAndSetExpression(answer);
2773        }
2774    
2775        /**
2776         * The <a href="http://camel.apache.org/content-enricher.html">Content Enricher EIP</a>
2777         * enriches an exchange with additional data obtained from a <code>resourceUri</code>.
2778         * 
2779         * @param resourceUri           URI of resource endpoint for obtaining additional data.
2780         * @param aggregationStrategy   aggregation strategy to aggregate input data and additional data.
2781         * @return the builder
2782         * @see org.apache.camel.processor.Enricher
2783         */
2784        @SuppressWarnings("unchecked")
2785        public Type enrich(String resourceUri, AggregationStrategy aggregationStrategy) {
2786            addOutput(new EnrichDefinition(aggregationStrategy, resourceUri));
2787            return (Type) this;
2788        }
2789    
2790        /**
2791         * The <a href="http://camel.apache.org/content-enricher.html">Content Enricher EIP</a>
2792         * enriches an exchange with additional data obtained from a <code>resourceUri</code>.
2793         * <p/>
2794         * The difference between this and {@link #pollEnrich(String)} is that this uses a producer
2795         * to obatin the additional data, where as pollEnrich uses a polling consumer.
2796         *
2797         * @param resourceUri           URI of resource endpoint for obtaining additional data.
2798         * @return the builder
2799         * @see org.apache.camel.processor.Enricher
2800         */
2801        @SuppressWarnings("unchecked")
2802        public Type enrich(String resourceUri) {
2803            addOutput(new EnrichDefinition(resourceUri));
2804            return (Type) this;
2805        }
2806    
2807        /**
2808         * The <a href="http://camel.apache.org/content-enricher.html">Content Enricher EIP</a>
2809         * enriches an exchange with additional data obtained from a <code>resourceUri</code>.
2810         * <p/>
2811         * The difference between this and {@link #pollEnrich(String)} is that this uses a producer
2812         * to obtain the additional data, where as pollEnrich uses a polling consumer.
2813         *
2814         * @param resourceRef            Reference of resource endpoint for obtaining additional data.
2815         * @param aggregationStrategyRef Reference of aggregation strategy to aggregate input data and additional data.
2816         * @return the builder
2817         * @see org.apache.camel.processor.Enricher
2818         */
2819        @SuppressWarnings("unchecked")
2820        public Type enrichRef(String resourceRef, String aggregationStrategyRef) {
2821            EnrichDefinition enrich = new EnrichDefinition();
2822            enrich.setResourceRef(resourceRef);
2823            enrich.setAggregationStrategyRef(aggregationStrategyRef);
2824            addOutput(enrich);
2825            return (Type) this;
2826        }
2827    
2828        /**
2829         * The <a href="http://camel.apache.org/content-enricher.html">Content Enricher EIP</a>
2830         * enriches an exchange with additional data obtained from a <code>resourceUri</code>
2831         * using a {@link org.apache.camel.PollingConsumer} to poll the endpoint.
2832         * <p/>
2833         * The difference between this and {@link #enrich(String)} is that this uses a consumer
2834         * to obtain the additional data, where as enrich uses a producer.
2835         * <p/>
2836         * This method will <tt>block</tt> until data is available, use the method with timeout if you do not
2837         * want to risk waiting a long time before data is available from the resourceUri.
2838         *
2839         * @param resourceUri           URI of resource endpoint for obtaining additional data.
2840         * @return the builder
2841         * @see org.apache.camel.processor.PollEnricher
2842         */
2843        @SuppressWarnings("unchecked")
2844        public Type pollEnrich(String resourceUri) {
2845            addOutput(new PollEnrichDefinition(null, resourceUri, -1, false));
2846            return (Type) this;
2847        }
2848    
2849        /**
2850         * The <a href="http://camel.apache.org/content-enricher.html">Content Enricher EIP</a>
2851         * enriches an exchange with additional data obtained from a <code>resourceUri</code>
2852         * using a {@link org.apache.camel.PollingConsumer} to poll the endpoint.
2853         * <p/>
2854         * The difference between this and {@link #enrich(String)} is that this uses a consumer
2855         * to obtain the additional data, where as enrich uses a producer.
2856         * <p/>
2857         * This method will not wait for data to become available, use the method with an explicit timeout
2858         * if you want to wait for data for a period of time from the resourceUri.
2859         *
2860         * @param resourceUri           URI of resource endpoint for obtaining additional data.
2861         * @param pollMultiple           if enabled will poll for all Exchanges available on the endpoint
2862         * @return the builder
2863         * @see org.apache.camel.processor.PollEnricher
2864         */
2865        @SuppressWarnings("unchecked")
2866        public Type pollEnrich(String resourceUri, boolean pollMultiple) {
2867            addOutput(new PollEnrichDefinition(null, resourceUri, 0, pollMultiple));
2868            return (Type) this;
2869        }
2870    
2871        /**
2872         * The <a href="http://camel.apache.org/content-enricher.html">Content Enricher EIP</a>
2873         * enriches an exchange with additional data obtained from a <code>resourceUri</code>
2874         * using a {@link org.apache.camel.PollingConsumer} to poll the endpoint.
2875         * <p/>
2876         * The difference between this and {@link #enrich(String)} is that this uses a consumer
2877         * to obtain the additional data, where as enrich uses a producer.
2878         * <p/>
2879         * This method will <tt>block</tt> until data is available, use the method with timeout if you do not
2880         * want to risk waiting a long time before data is available from the resourceUri.
2881         *
2882         * @param resourceUri           URI of resource endpoint for obtaining additional data.
2883         * @param timeout               timeout in millis to wait at most for data to be available.
2884         * @param pollMultiple           if enabled will poll for all Exchanges available on the endpoint
2885         * @return the builder
2886         * @see org.apache.camel.processor.PollEnricher
2887         */
2888        @SuppressWarnings("unchecked")
2889        public Type pollEnrich(String resourceUri, long timeout, boolean pollMultiple) {
2890            addOutput(new PollEnrichDefinition(null, resourceUri, timeout, pollMultiple));
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, false));
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, false));
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, false));
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    }