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