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.Collections;
023    import java.util.HashSet;
024    import java.util.LinkedList;
025    import java.util.List;
026    import java.util.Set;
027    import java.util.concurrent.ThreadPoolExecutor;
028    
029    import javax.xml.bind.annotation.XmlAccessType;
030    import javax.xml.bind.annotation.XmlAccessorType;
031    import javax.xml.bind.annotation.XmlAttribute;
032    import javax.xml.bind.annotation.XmlTransient;
033    
034    import org.apache.camel.CamelContext;
035    import org.apache.camel.CamelException;
036    import org.apache.camel.Endpoint;
037    import org.apache.camel.Exchange;
038    import org.apache.camel.Expression;
039    import org.apache.camel.Predicate;
040    import org.apache.camel.Processor;
041    import org.apache.camel.Route;
042    import org.apache.camel.builder.DataFormatClause;
043    import org.apache.camel.builder.DeadLetterChannelBuilder;
044    import org.apache.camel.builder.ErrorHandlerBuilder;
045    import org.apache.camel.builder.ErrorHandlerBuilderRef;
046    import org.apache.camel.builder.ExpressionClause;
047    import org.apache.camel.builder.NoErrorHandlerBuilder;
048    import org.apache.camel.builder.ProcessorBuilder;
049    import org.apache.camel.impl.DefaultCamelContext;
050    import org.apache.camel.model.dataformat.DataFormatType;
051    import org.apache.camel.model.language.ConstantExpression;
052    import org.apache.camel.model.language.ExpressionType;
053    import org.apache.camel.model.language.LanguageExpression;
054    import org.apache.camel.processor.ConvertBodyProcessor;
055    import org.apache.camel.processor.DelegateProcessor;
056    import org.apache.camel.processor.Pipeline;
057    import org.apache.camel.processor.aggregate.AggregationCollection;
058    import org.apache.camel.processor.aggregate.AggregationStrategy;
059    import org.apache.camel.processor.idempotent.MessageIdRepository;
060    import org.apache.camel.spi.DataFormat;
061    import org.apache.camel.spi.ErrorHandlerWrappingStrategy;
062    import org.apache.camel.spi.InterceptStrategy;
063    import org.apache.camel.spi.Policy;
064    import org.apache.camel.spi.RouteContext;
065    import org.apache.commons.logging.Log;
066    import org.apache.commons.logging.LogFactory;
067    
068    /**
069     * Base class for processor types that most XML types extend.
070     *
071     * @version $Revision: 61170 $
072     */
073    @XmlAccessorType(XmlAccessType.PROPERTY)
074    public abstract class ProcessorType<Type extends ProcessorType> extends OptionalIdentifiedType<Type> implements Block {
075        public static final String DEFAULT_TRACE_CATEGORY = "org.apache.camel.TRACE";
076        private static final transient Log LOG = LogFactory.getLog(ProcessorType.class);
077        private ErrorHandlerBuilder errorHandlerBuilder;
078        private Boolean inheritErrorHandlerFlag;
079        private NodeFactory nodeFactory;
080        private LinkedList<Block> blocks = new LinkedList<Block>();
081        private ProcessorType<? extends ProcessorType> parent;
082        private List<InterceptorType> interceptors = new ArrayList<InterceptorType>();
083        private String errorHandlerRef;
084    
085        // else to use an optional attribute in JAXB2
086        public abstract List<ProcessorType<?>> getOutputs();
087    
088    
089        public Processor createProcessor(RouteContext routeContext) throws Exception {
090            throw new UnsupportedOperationException("Not implemented yet for class: " + getClass().getName());
091        }
092    
093        public Processor createOutputsProcessor(RouteContext routeContext) throws Exception {
094            Collection<ProcessorType<?>> outputs = getOutputs();
095            return createOutputsProcessor(routeContext, outputs);
096        }
097    
098        public void addRoutes(RouteContext routeContext, Collection<Route> routes) throws Exception {
099            Processor processor = makeProcessor(routeContext);
100            if (!routeContext.isRouteAdded()) {
101                routeContext.addEventDrivenProcessor(processor);
102            }
103        }
104    
105        /**
106         * Wraps the child processor in whatever necessary interceptors and error
107         * handlers
108         */
109        public Processor wrapProcessor(RouteContext routeContext, Processor processor) throws Exception {
110            processor = wrapProcessorInInterceptors(routeContext, processor);
111            return wrapInErrorHandler(routeContext, processor);
112        }
113    
114        // Fluent API
115        // -------------------------------------------------------------------------
116    
117        /**
118         * Sends the exchange to the given endpoint URI
119         */
120        public Type to(String uri) {
121            addOutput(new ToType(uri));
122            return (Type) this;
123        }
124    
125        /**
126         * Sends the exchange to the given endpoint
127         */
128        public Type to(Endpoint endpoint) {
129            addOutput(new ToType(endpoint));
130            return (Type) this;
131        }
132    
133        /**
134         * Sends the exchange to a list of endpoints
135         */
136        public Type to(String... uris) {
137            for (String uri : uris) {
138                addOutput(new ToType(uri));
139            }
140            return (Type) this;
141        }
142    
143        /**
144         * Sends the exchange to a list of endpoints
145         */
146        public Type to(Endpoint... endpoints) {
147            for (Endpoint endpoint : endpoints) {
148                addOutput(new ToType(endpoint));
149            }
150            return (Type) this;
151        }
152    
153        /**
154         * Sends the exchange to a list of endpoint
155         */
156        public Type to(Collection<Endpoint> endpoints) {
157            for (Endpoint endpoint : endpoints) {
158                addOutput(new ToType(endpoint));
159            }
160            return (Type) this;
161        }
162    
163        /**
164         * Multicasts messages to all its child outputs; so that each processor and
165         * destination gets a copy of the original message to avoid the processors
166         * interfering with each other.
167         */
168        public MulticastType multicast() {
169            MulticastType answer = new MulticastType();
170            addOutput(answer);
171            return answer;
172        }
173    
174        /**
175         * Multicasts messages to all its child outputs; so that each processor and
176         * destination gets a copy of the original message to avoid the processors
177         * interfering with each other.
178         * @param aggregationStrategy the strategy used to aggregate responses for
179         *          every part
180         * @param parallelProcessing if is <tt>true</tt> camel will fork thread to call the endpoint producer
181         * @return the multicast type
182         */
183        public MulticastType multicast(AggregationStrategy aggregationStrategy, boolean parallelProcessing) {
184            MulticastType answer = new MulticastType();
185            addOutput(answer);
186            answer.setAggregationStrategy(aggregationStrategy);
187            answer.setParallelProcessing(parallelProcessing);
188            return answer;
189        }
190    
191        /**
192         * Multicasts messages to all its child outputs; so that each processor and
193         * destination gets a copy of the original message to avoid the processors
194         * interfering with each other.
195         * @param aggregationStrategy the strategy used to aggregate responses for
196         *          every part
197         * @return the multicast type
198         */
199        public MulticastType multicast(AggregationStrategy aggregationStrategy) {
200            MulticastType answer = new MulticastType();
201            addOutput(answer);
202            answer.setAggregationStrategy(aggregationStrategy);
203            return answer;
204        }
205    
206        /**
207         * Creates a {@link Pipeline} of the list of endpoints so that the message
208         * will get processed by each endpoint in turn and for request/response the
209         * output of one endpoint will be the input of the next endpoint
210         */
211        public Type pipeline(String... uris) {
212            // TODO pipeline v mulicast
213            return to(uris);
214        }
215    
216        /**
217         * Creates a {@link Pipeline} of the list of endpoints so that the message
218         * will get processed by each endpoint in turn and for request/response the
219         * output of one endpoint will be the input of the next endpoint
220         */
221        public Type pipeline(Endpoint... endpoints) {
222            // TODO pipeline v mulicast
223            return to(endpoints);
224        }
225    
226        /**
227         * Creates a {@link Pipeline} of the list of endpoints so that the message
228         * will get processed by each endpoint in turn and for request/response the
229         * output of one endpoint will be the input of the next endpoint
230         */
231        public Type pipeline(Collection<Endpoint> endpoints) {
232            // TODO pipeline v mulicast
233            return to(endpoints);
234        }
235    
236        /**
237         * Ends the current block
238         */
239        public ProcessorType<? extends ProcessorType> end() {
240            if (blocks.isEmpty()) {
241                if (parent == null) {
242                    throw new IllegalArgumentException("Root node with no active block");
243                }
244                return parent;
245            }
246            popBlock();
247            return this;
248        }
249    
250        /**
251         * Causes subsequent processors to be called asynchronously
252         *
253         * @param coreSize the number of threads that will be used to process
254         *                 messages in subsequent processors.
255         * @return a ThreadType builder that can be used to further configure the
256         *         the thread pool.
257         */
258        public ThreadType thread(int coreSize) {
259            ThreadType answer = new ThreadType(coreSize);
260            addOutput(answer);
261            return answer;
262        }
263    
264        /**
265         * Causes subsequent processors to be called asynchronously
266         *
267         * @param executor the executor that will be used to process
268         *                 messages in subsequent processors.
269         * @return a ThreadType builder that can be used to further configure the
270         *         the thread pool.
271         */
272        public ProcessorType<Type> thread(ThreadPoolExecutor executor) {
273            ThreadType answer = new ThreadType(executor);
274            addOutput(answer);
275            return this;
276        }
277    
278        /**
279         * Creates an {@link org.apache.camel.processor.idempotent.IdempotentConsumer}
280         * to avoid duplicate messages
281         */
282        public IdempotentConsumerType idempotentConsumer(Expression messageIdExpression,
283                MessageIdRepository messageIdRepository) {
284            IdempotentConsumerType answer = new IdempotentConsumerType(messageIdExpression, messageIdRepository);
285            addOutput(answer);
286            return answer;
287        }
288    
289        /**
290         * Creates an {@link org.apache.camel.processor.idempotent.IdempotentConsumer}
291         * to avoid duplicate messages
292         *
293         * @return the builder used to create the expression
294         */
295        public ExpressionClause<IdempotentConsumerType> idempotentConsumer(MessageIdRepository messageIdRepository) {
296            IdempotentConsumerType answer = new IdempotentConsumerType();
297            answer.setMessageIdRepository(messageIdRepository);
298            addOutput(answer);
299            return ExpressionClause.createAndSetExpression(answer);
300        }
301    
302        /**
303         * Creates a predicate expression which only if it is true then the
304         * exchange is forwarded to the destination
305         *
306         * @return the clause used to create the filter expression
307         */
308        public ExpressionClause<FilterType> filter() {
309            FilterType filter = new FilterType();
310            addOutput(filter);
311            return ExpressionClause.createAndSetExpression(filter);
312        }
313    
314        /**
315         * Creates a predicate which is applied and only if it is true then the
316         * exchange is forwarded to the destination
317         *
318         * @return the builder for a predicate
319         */
320        public FilterType filter(Predicate predicate) {
321            FilterType filter = new FilterType(predicate);
322            addOutput(filter);
323            return filter;
324        }
325    
326        public FilterType filter(ExpressionType expression) {
327            FilterType filter = getNodeFactory().createFilter();
328            filter.setExpression(expression);
329            addOutput(filter);
330            return filter;
331        }
332    
333        public FilterType filter(String language, String expression) {
334            return filter(new LanguageExpression(language, expression));
335        }
336    
337        public LoadBalanceType loadBalance() {
338            LoadBalanceType answer = new LoadBalanceType();
339            addOutput(answer);
340            return answer;
341        }
342    
343    
344        /**
345         * Creates a choice of one or more predicates with an otherwise clause
346         *
347         * @return the builder for a choice expression
348         */
349        public ChoiceType choice() {
350            ChoiceType answer = new ChoiceType();
351            addOutput(answer);
352            return answer;
353        }
354    
355        /**
356         * Creates a try/catch block
357         *
358         * @return the builder for a tryBlock expression
359         */
360        public TryType tryBlock() {
361            TryType answer = new TryType();
362            addOutput(answer);
363            return answer;
364        }
365    
366        /**
367         * Creates a dynamic <a
368         * href="http://activemq.apache.org/camel/recipient-list.html">Recipient
369         * List</a> pattern.
370         *
371         * @param recipients is the builder of the expression used in the
372         *                    {@link org.apache.camel.processor.RecipientList}
373         *                    to decide the destinations
374         */
375        public Type recipientList(Expression recipients) {
376            RecipientListType answer = new RecipientListType(recipients);
377            addOutput(answer);
378            return (Type) this;
379        }
380    
381        /**
382         * Creates a dynamic <a
383         * href="http://activemq.apache.org/camel/recipient-list.html">Recipient
384         * List</a> pattern.
385         *
386         * @return the expression clause for the expression used in the
387         *                    {@link org.apache.camel.processor.RecipientList}
388         *                    to decide the destinations
389         */
390        public ExpressionClause<ProcessorType<Type>> recipientList() {
391            RecipientListType answer = new RecipientListType();
392            addOutput(answer);
393            ExpressionClause<ProcessorType<Type>> clause = new ExpressionClause<ProcessorType<Type>>((Type) this);
394            answer.setExpression(clause);
395            return clause;
396        }
397    
398        /**
399         * Creates a <a
400         * href="http://activemq.apache.org/camel/routing-slip.html">Routing
401         * Slip</a> pattern.
402         *
403         * @param header is the header that the {@link org.apache.camel.processor.RoutingSlip RoutingSlip}
404         * class will look in for the list of URIs to route the message to.
405         * @param uriDelimiter is the delimiter that will be used to split up
406         * the list of URIs in the routing slip.
407         */
408        public Type routingSlip(String header, String uriDelimiter) {
409            RoutingSlipType answer = new RoutingSlipType(header, uriDelimiter);
410            addOutput(answer);
411            return (Type) this;
412        }
413    
414        /**
415         * Creates a <a
416         * href="http://activemq.apache.org/camel/routing-slip.html">Routing
417         * Slip</a> pattern.
418         *
419         * @param header is the header that the {@link org.apache.camel.processor.RoutingSlip RoutingSlip}
420         * class will look in for the list of URIs to route the message to. The list of URIs
421         * will be split based on the default delimiter
422         * {@link RoutingSlipType#DEFAULT_DELIMITER}.
423         */
424        public Type routingSlip(String header) {
425            RoutingSlipType answer = new RoutingSlipType(header);
426            addOutput(answer);
427            return (Type) this;
428        }
429    
430        /**
431         * Creates a <a
432         * href="http://activemq.apache.org/camel/routing-slip.html">Routing
433         * Slip</a> pattern with the default header {@link RoutingSlipType#ROUTING_SLIP_HEADER}.
434         * The list of URIs in the header will be split based on the default delimiter
435         * {@link RoutingSlipType#DEFAULT_DELIMITER}.
436         */
437        public Type routingSlip() {
438            RoutingSlipType answer = new RoutingSlipType();
439            addOutput(answer);
440            return (Type) this;
441        }
442    
443        /**
444         * Creates the <a
445         * href="http://activemq.apache.org/camel/splitter.html">Splitter</a>
446         * pattern where an expression is evaluated to iterate through each of the
447         * parts of a message and then each part is then send to some endpoint.
448         * This splitter responds with the latest message returned from destination
449         * endpoint.
450         *
451         * @param recipients the expression on which to split
452         * @return the builder
453         */
454        public SplitterType splitter(Expression recipients) {
455            SplitterType answer = new SplitterType(recipients);
456            addOutput(answer);
457            return answer;
458        }
459    
460        /**
461         * Creates the <a
462         * href="http://activemq.apache.org/camel/splitter.html">Splitter</a>
463         * pattern where an expression is evaluated to iterate through each of the
464         * parts of a message and then each part is then send to some endpoint.
465         * This splitter responds with the latest message returned from destination
466         * endpoint.
467         *
468         * @return the expression clause for the expression on which to split
469         */
470        public ExpressionClause<SplitterType> splitter() {
471            SplitterType answer = new SplitterType();
472            addOutput(answer);
473            return ExpressionClause.createAndSetExpression(answer);
474        }
475    
476        /**
477         * Creates the <a
478         * href="http://activemq.apache.org/camel/splitter.html">Splitter</a>
479         * pattern where an expression is evaluated to iterate through each of the
480         * parts of a message and then each part is then send to some endpoint.
481         * Answer from the splitter is produced using given {@link AggregationStrategy}
482         * @param partsExpression the expression on which to split
483         * @param aggregationStrategy the strategy used to aggregate responses for
484         *          every part
485         * @return the builder
486         */
487        public SplitterType splitter(Expression partsExpression, AggregationStrategy aggregationStrategy) {
488            SplitterType answer = new SplitterType(partsExpression);
489            addOutput(answer);
490            answer.setAggregationStrategy(aggregationStrategy);
491            return answer;
492        }
493    
494        /**
495         * Creates the <a
496         * href="http://activemq.apache.org/camel/splitter.html">Splitter</a>
497         * pattern where an expression is evaluated to iterate through each of the
498         * parts of a message and then each part is then send to some endpoint.
499         * Answer from the splitter is produced using given {@link AggregationStrategy}
500         * @param aggregationStrategy the strategy used to aggregate responses for
501         *          every part
502         * @return the expression clause for the expression on which to split
503         */
504        public ExpressionClause<SplitterType> splitter(AggregationStrategy aggregationStrategy) {
505            SplitterType answer = new SplitterType();
506            addOutput(answer);
507            answer.setAggregationStrategy(aggregationStrategy);
508            return ExpressionClause.createAndSetExpression(answer);
509        }
510    
511        /**
512         * Creates the <a
513         * href="http://activemq.apache.org/camel/splitter.html">Splitter</a>
514         * pattern where an expression is evaluated to iterate through each of the
515         * parts of a message and then each part is then send to some endpoint.
516         * This splitter responds with the latest message returned from destination
517         * endpoint.
518         *
519         * @param recipients the expression on which to split
520         * @param parallelProcessing if is <tt>true</tt> camel will fork thread to call the endpoint producer
521         * @return the builder
522         */
523        public SplitterType splitter(Expression recipients, boolean parallelProcessing) {
524            SplitterType answer = new SplitterType(recipients);
525            addOutput(answer);
526            answer.setParallelProcessing(parallelProcessing);
527            return answer;
528        }
529    
530        /**
531         * Creates the <a
532         * href="http://activemq.apache.org/camel/splitter.html">Splitter</a>
533         * pattern where an expression is evaluated to iterate through each of the
534         * parts of a message and then each part is then send to some endpoint.
535         * This splitter responds with the latest message returned from destination
536         * endpoint.
537         *
538         * @param recipients the expression on which to split
539         * @param parallelProcessing if is <tt>true</tt> camel will fork thread to call the endpoint producer
540         * @param threadPoolExecutor override the default {@link ThreadPoolExecutor} 
541         * @return the builder
542         */
543        public SplitterType splitter(Expression recipients, boolean parallelProcessing, ThreadPoolExecutor threadPoolExecutor) {
544            SplitterType answer = new SplitterType(recipients);
545            addOutput(answer);
546            answer.setParallelProcessing(parallelProcessing);
547            answer.setThreadPoolExecutor(threadPoolExecutor);
548            return answer;
549        }    
550        
551        /**
552         * Creates the <a
553         * href="http://activemq.apache.org/camel/splitter.html">Splitter</a>
554         * pattern where an expression is evaluated to iterate through each of the
555         * parts of a message and then each part is then send to some endpoint.
556         * This splitter responds with the latest message returned from destination
557         * endpoint.
558         *
559         * @param parallelProcessing if is <tt>true</tt> camel will fork thread to call the endpoint producer
560         * @return the expression clause for the expression on which to split
561         */
562        public ExpressionClause<SplitterType> splitter(boolean parallelProcessing) {
563            SplitterType answer = new SplitterType();
564            addOutput(answer);
565            answer.setParallelProcessing(parallelProcessing);
566            return ExpressionClause.createAndSetExpression(answer);
567        }
568    
569        /**
570         * Creates the <a
571         * href="http://activemq.apache.org/camel/splitter.html">Splitter</a>
572         * pattern where an expression is evaluated to iterate through each of the
573         * parts of a message and then each part is then send to some endpoint.
574         * This splitter responds with the latest message returned from destination
575         * endpoint.
576         *
577         * @param parallelProcessing if is <tt>true</tt> camel will fork thread to call the endpoint producer
578         * @param threadPoolExecutor override the default {@link ThreadPoolExecutor} 
579         * @return the expression clause for the expression on which to split
580         */
581        public ExpressionClause<SplitterType> splitter(boolean parallelProcessing, ThreadPoolExecutor threadPoolExecutor) {
582            SplitterType answer = new SplitterType();
583            addOutput(answer);
584            answer.setParallelProcessing(parallelProcessing);
585            answer.setThreadPoolExecutor(threadPoolExecutor);
586            return ExpressionClause.createAndSetExpression(answer);
587        }    
588        
589        /**
590         * Creates the <a
591         * href="http://activemq.apache.org/camel/splitter.html">Splitter</a>
592         * pattern where an expression is evaluated to iterate through each of the
593         * parts of a message and then each part is then send to some endpoint.
594         * Answer from the splitter is produced using given {@link AggregationStrategy}
595         * @param partsExpression the expression on which to split
596         * @param aggregationStrategy the strategy used to aggregate responses for
597         *          every part
598         * @param parallelProcessing if is <tt>true</tt> camel will fork thread to call the endpoint producer
599         * @return the builder
600         */
601        public SplitterType splitter(Expression partsExpression,
602                AggregationStrategy aggregationStrategy, boolean parallelProcessing) {
603            SplitterType answer = new SplitterType(partsExpression);
604            addOutput(answer);
605            answer.setAggregationStrategy(aggregationStrategy);
606            answer.setParallelProcessing(parallelProcessing);
607            return answer;
608        }
609    
610        /**
611         * Creates the <a
612         * href="http://activemq.apache.org/camel/splitter.html">Splitter</a>
613         * pattern where an expression is evaluated to iterate through each of the
614         * parts of a message and then each part is then send to some endpoint.
615         * Answer from the splitter is produced using given {@link AggregationStrategy}
616         * @param partsExpression the expression on which to split
617         * @param aggregationStrategy the strategy used to aggregate responses for
618         *          every part
619         * @param parallelProcessing if is <tt>true</tt> camel will fork thread to call the endpoint producer
620         * @param threadPoolExecutor override the default {@link ThreadPoolExecutor} 
621         * @return the builder
622         */
623        public SplitterType splitter(Expression partsExpression,
624                AggregationStrategy aggregationStrategy, boolean parallelProcessing, ThreadPoolExecutor threadPoolExecutor) {
625            SplitterType answer = new SplitterType(partsExpression);
626            addOutput(answer);
627            answer.setAggregationStrategy(aggregationStrategy);
628            answer.setParallelProcessing(parallelProcessing);
629            answer.setThreadPoolExecutor(threadPoolExecutor);        
630            return answer;
631        }    
632        
633        /**
634         * Creates the <a
635         * href="http://activemq.apache.org/camel/splitter.html">Splitter</a>
636         * pattern where an expression is evaluated to iterate through each of the
637         * parts of a message and then each part is then send to some endpoint.
638         * Answer from the splitter is produced using given {@link AggregationStrategy}
639         * @param aggregationStrategy the strategy used to aggregate responses for
640         *          every part
641         * @param parallelProcessing if is <tt>true</tt> camel will fork thread to call the endpoint producer
642         * @return the expression clause for the expression on which to split
643         */
644        public ExpressionClause<SplitterType> splitter(AggregationStrategy aggregationStrategy, boolean parallelProcessing) {
645            SplitterType answer = new SplitterType();
646            addOutput(answer);
647            answer.setAggregationStrategy(aggregationStrategy);
648            answer.setParallelProcessing(parallelProcessing);
649            return ExpressionClause.createAndSetExpression(answer);
650        }
651    
652        /**
653         * Creates the <a
654         * href="http://activemq.apache.org/camel/splitter.html">Splitter</a>
655         * pattern where an expression is evaluated to iterate through each of the
656         * parts of a message and then each part is then send to some endpoint.
657         * Answer from the splitter is produced using given {@link AggregationStrategy}
658         * @param aggregationStrategy the strategy used to aggregate responses for
659         *          every part
660         * @param parallelProcessing if is <tt>true</tt> camel will fork thread to call the endpoint producer
661         * @param threadPoolExecutor override the default {@link ThreadPoolExecutor} 
662         * @return the expression clause for the expression on which to split
663         */
664        public ExpressionClause<SplitterType> splitter(AggregationStrategy aggregationStrategy, boolean parallelProcessing, ThreadPoolExecutor threadPoolExecutor) {
665            SplitterType answer = new SplitterType();
666            addOutput(answer);
667            answer.setAggregationStrategy(aggregationStrategy);
668            answer.setParallelProcessing(parallelProcessing);
669            answer.setThreadPoolExecutor(threadPoolExecutor);           
670            return ExpressionClause.createAndSetExpression(answer);
671        }   
672        
673        /**
674         * Creates the <a
675         * href="http://activemq.apache.org/camel/resequencer.html">Resequencer</a>
676         * pattern where a list of expressions are evaluated to be able to compare
677         * the message exchanges to reorder them. e.g. you may wish to sort by some
678         * headers
679         *
680         * @return the expression clause for the expressions on which to compare messages in order
681         */
682        public ExpressionClause<ResequencerType> resequencer() {
683            ResequencerType answer = new ResequencerType();
684            addOutput(answer);
685            ExpressionClause<ResequencerType> clause = new ExpressionClause<ResequencerType>(answer);
686            answer.expression(clause);
687            return clause;
688        }
689    
690        /**
691         * Creates the <a
692         * href="http://activemq.apache.org/camel/resequencer.html">Resequencer</a>
693         * pattern where an expression is evaluated to be able to compare the
694         * message exchanges to reorder them. e.g. you may wish to sort by some
695         * header
696         *
697         * @param expression the expression on which to compare messages in order
698         * @return the builder
699         */
700        public ResequencerType resequencer(Expression<Exchange> expression) {
701            return resequencer(Collections.<Expression>singletonList(expression));
702        }
703    
704        /**
705         * Creates the <a
706         * href="http://activemq.apache.org/camel/resequencer.html">Resequencer</a>
707         * pattern where a list of expressions are evaluated to be able to compare
708         * the message exchanges to reorder them. e.g. you may wish to sort by some
709         * headers
710         *
711         * @param expressions the expressions on which to compare messages in order
712         * @return the builder
713         */
714        public ResequencerType resequencer(List<Expression> expressions) {
715            ResequencerType answer = new ResequencerType(expressions);
716            addOutput(answer);
717            return answer;
718        }
719    
720        /**
721         * Creates the <a
722         * href="http://activemq.apache.org/camel/resequencer.html">Resequencer</a>
723         * pattern where a list of expressions are evaluated to be able to compare
724         * the message exchanges to reorder them. e.g. you may wish to sort by some
725         * headers
726         *
727         * @param expressions the expressions on which to compare messages in order
728         * @return the builder
729         */
730        public ResequencerType resequencer(Expression... expressions) {
731            List<Expression> list = new ArrayList<Expression>();
732            list.addAll(Arrays.asList(expressions));
733            return resequencer(list);
734        }
735    
736        /**
737         * Creates an <a
738         * href="http://activemq.apache.org/camel/aggregator.html">Aggregator</a>
739         * pattern where a batch of messages are processed (up to a maximum amount
740         * or until some timeout is reached) and messages for the same correlation
741         * key are combined together using some kind of {@link AggregationStrategy}
742         * (by default the latest message is used) to compress many message exchanges
743         * into a smaller number of exchanges.
744         * <p/>
745         * A good example of this is stock market data; you may be receiving 30,000
746         * messages/second and you may want to throttle it right down so that multiple
747         * messages for the same stock are combined (or just the latest message is used
748         * and older prices are discarded). Another idea is to combine line item messages
749         * together into a single invoice message.
750         */
751        public ExpressionClause<AggregatorType> aggregator() {
752            if (!getOutputs().isEmpty()) {
753                throw new IllegalArgumentException("Aggregator must be the only output added to the route: " + this);
754            }
755            AggregatorType answer = new AggregatorType();
756            addOutput(answer);
757            return ExpressionClause.createAndSetExpression(answer);
758        }
759    
760        /**
761         * Creates an <a
762         * href="http://activemq.apache.org/camel/aggregator.html">Aggregator</a>
763         * pattern where a batch of messages are processed (up to a maximum amount
764         * or until some timeout is reached) and messages for the same correlation
765         * key are combined together using some kind of {@link AggregationStrategy}
766         * (by default the latest message is used) to compress many message exchanges
767         * into a smaller number of exchanges.
768         * <p/>
769         * A good example of this is stock market data; you may be receiving 30,000
770         * messages/second and you may want to throttle it right down so that multiple
771         * messages for the same stock are combined (or just the latest message is used
772         * and older prices are discarded). Another idea is to combine line item messages
773         * together into a single invoice message.
774         *
775         * @param aggregationStrategy the strategy used for the aggregation
776         */
777        public ExpressionClause<AggregatorType> aggregator(AggregationStrategy aggregationStrategy) {
778            if (!getOutputs().isEmpty()) {
779                throw new IllegalArgumentException("Aggregator must be the only output added to the route: " + this);
780            }
781            AggregatorType answer = new AggregatorType();
782            answer.setAggregationStrategy(aggregationStrategy);
783            addOutput(answer);
784            return ExpressionClause.createAndSetExpression(answer);
785        }
786    
787        /**
788         * Creates an <a
789         * href="http://activemq.apache.org/camel/aggregator.html">Aggregator</a>
790         * pattern using a custom aggregation collection implementation. The aggregation collection must
791         * be configued with the strategy and correlation expression that this aggregator should use.
792         * This avoids duplicating this configuration on both the collection and the aggregator itself.
793         *
794         * @param aggregationCollection the collection used to perform the aggregation
795         */
796        public AggregatorType aggregator(AggregationCollection aggregationCollection) {
797            if (!getOutputs().isEmpty()) {
798                throw new IllegalArgumentException("Aggregator must be the only output added to the route: " + this);
799            }
800            AggregatorType answer = new AggregatorType();
801            answer.setAggregationCollection(aggregationCollection);
802            addOutput(answer);
803            return answer;
804        }
805    
806        /**
807         * Creates an <a
808         * href="http://activemq.apache.org/camel/aggregator.html">Aggregator</a>
809         * pattern where a batch of messages are processed (up to a maximum amount
810         * or until some timeout is reached) and messages for the same correlation
811         * key are combined together using some kind of {@link AggregationStrategy}
812         * (by default the latest message is used) to compress many message exchanges
813         * into a smaller number of exchanges.
814         * <p/>
815         * A good example of this is stock market data; you may be receiving 30,000
816         * messages/second and you may want to throttle it right down so that multiple
817         * messages for the same stock are combined (or just the latest message is used
818         * and older prices are discarded). Another idea is to combine line item messages
819         * together into a single invoice message.
820         *
821         * @param correlationExpression the expression used to calculate the
822         *                              correlation key. For a JMS message this could be the
823         *                              expression <code>header("JMSDestination")</code> or
824         *                              <code>header("JMSCorrelationID")</code>
825         */
826        public AggregatorType aggregator(Expression correlationExpression) {
827            if (!getOutputs().isEmpty()) {
828                throw new IllegalArgumentException("Aggregator must be the only output added to the route: " + this);
829            }
830            AggregatorType answer = new AggregatorType(correlationExpression);
831            addOutput(answer);
832            return answer;
833        }
834    
835        /**
836         * Creates an <a
837         * href="http://activemq.apache.org/camel/aggregator.html">Aggregator</a>
838         * pattern where a batch of messages are processed (up to a maximum amount
839         * or until some timeout is reached) and messages for the same correlation
840         * key are combined together using some kind of {@link AggregationStrategy}
841         * (by default the latest message is used) to compress many message exchanges
842         * into a smaller number of exchanges.
843         * <p/>
844         * A good example of this is stock market data; you may be receiving 30,000
845         * messages/second and you may want to throttle it right down so that multiple
846         * messages for the same stock are combined (or just the latest message is used
847         * and older prices are discarded). Another idea is to combine line item messages
848         * together into a single invoice message.
849         *
850         * @param correlationExpression the expression used to calculate the
851         *                              correlation key. For a JMS message this could be the
852         *                              expression <code>header("JMSDestination")</code> or
853         *                              <code>header("JMSCorrelationID")</code>
854         */
855        public AggregatorType aggregator(Expression correlationExpression, AggregationStrategy aggregationStrategy) {
856            if (!getOutputs().isEmpty()) {
857                throw new IllegalArgumentException("Aggregator must be the only output added to the route: " + this);
858            }
859            AggregatorType answer = new AggregatorType(correlationExpression, aggregationStrategy);
860            addOutput(answer);
861            return answer;
862        }
863    
864        /**
865         * Creates the <a
866         * href="http://activemq.apache.org/camel/delayer.html">Delayer</a> pattern
867         * where an expression is used to calculate the time which the message will
868         * be dispatched on
869         *
870         * @param processAtExpression an expression to calculate the time at which
871         *                            the messages should be processed
872         * @return the builder
873         */
874        public DelayerType delayer(Expression<Exchange> processAtExpression) {
875            return delayer(processAtExpression, 0L);
876        }
877    
878        /**
879         * Creates the <a
880         * href="http://activemq.apache.org/camel/delayer.html">Delayer</a> pattern
881         * where an expression is used to calculate the time which the message will
882         * be dispatched on
883         *
884         * @param processAtExpression an expression to calculate the time at which
885         *                            the messages should be processed
886         * @param delay               the delay in milliseconds which is added to the
887         *                            processAtExpression to determine the time the message
888         *                            should be processed
889         * @return the builder
890         */
891        public DelayerType delayer(Expression<Exchange> processAtExpression, long delay) {
892            DelayerType answer = new DelayerType(processAtExpression, delay);
893            addOutput(answer);
894            return answer;
895        }
896    
897        /**
898         * Creates the <a
899         * href="http://activemq.apache.org/camel/delayer.html">Delayer</a> pattern
900         * where an expression is used to calculate the time which the message will
901         * be dispatched on
902         * @return the expression clause to create the expression
903         */
904        public ExpressionClause<DelayerType> delayer() {
905            DelayerType answer = new DelayerType();
906            addOutput(answer);
907            return ExpressionClause.createAndSetExpression(answer);
908        }
909    
910        /**
911         * Creates the <a
912         * href="http://activemq.apache.org/camel/delayer.html">Delayer</a> pattern
913         * where a fixed amount of milliseconds are used to delay processing of a
914         * message exchange
915         *
916         * @param delay the default delay in milliseconds
917         * @return the builder
918         */
919        public DelayerType delayer(long delay) {
920            return delayer(null, delay);
921        }
922    
923        /**
924         * Creates the <a
925         * href="http://activemq.apache.org/camel/delayer.html">Delayer</a> pattern
926         * where an expression is used to calculate the time which the message will
927         * be dispatched on
928         *
929         * @return the builder
930         */
931        public ThrottlerType throttler(long maximumRequestCount) {
932            ThrottlerType answer = new ThrottlerType(maximumRequestCount);
933            addOutput(answer);
934            return answer;
935        }
936    
937        /**
938         * Creates a expression which must evaluate to an integer that determines
939         * how many times the exchange should be sent down the rest of the route.
940         *
941         * @return the clause used to create the loop expression
942         */
943        public ExpressionClause<LoopType> loop() {
944            LoopType loop = new LoopType();
945            addOutput(loop);
946            return ExpressionClause.createAndSetExpression(loop);
947        }
948    
949        public LoopType loop(Expression<?> expression) {
950            LoopType loop = getNodeFactory().createLoop();
951            loop.setExpression(expression);
952            addOutput(loop);
953            return loop;
954        }
955    
956        public LoopType loop(int count) {
957            LoopType loop = getNodeFactory().createLoop();
958            loop.setExpression(new ConstantExpression(Integer.toString(count)));
959            addOutput(loop);
960            return loop;
961        }
962    
963        public Type throwFault(Throwable fault) {
964            ThrowFaultType answer = new ThrowFaultType();
965            answer.setFault(fault);
966            addOutput(answer);
967            return (Type) this;
968        }
969    
970        public Type throwFault(String message) {
971            return throwFault(new CamelException(message));
972        }
973    
974        /**
975         * Intercepts outputs added to this node in the future (i.e. intercepts outputs added after this statement)
976         */
977        public Type interceptor(String ref) {
978            InterceptorRef interceptor = new InterceptorRef(ref);
979            intercept(interceptor);
980            return (Type) this;
981        }
982    
983        /**
984         * Intercepts outputs added to this node in the future (i.e. intercepts outputs added after this statement)
985         */
986        public Type intercept(DelegateProcessor interceptor) {
987            intercept(new InterceptorRef(interceptor));
988            //lastInterceptor = interceptor;
989            return (Type) this;
990        }
991    
992        /**
993         * Intercepts outputs added to this node in the future (i.e. intercepts outputs added after this statement)
994         */
995        public InterceptType intercept() {
996            InterceptType answer = new InterceptType();
997            addOutput(answer);
998            return answer;
999        }
1000    
1001        /**
1002         * Intercepts outputs added to this node in the future (i.e. intercepts outputs added after this statement)
1003         */
1004        public void intercept(InterceptorType interceptor) {
1005            addOutput(interceptor);
1006            pushBlock(interceptor);
1007        }
1008    
1009        /**
1010         * Adds an interceptor around the whole of this nodes processing
1011         *
1012         * @param interceptor
1013         */
1014        public void addInterceptor(InterceptorType interceptor) {
1015            interceptors.add(interceptor);
1016        }
1017    
1018        /**
1019         * Adds an interceptor around the whole of this nodes processing
1020         *
1021         * @param interceptor
1022         */
1023        public void addInterceptor(DelegateProcessor interceptor) {
1024            addInterceptor(new InterceptorRef(interceptor));
1025        }
1026    
1027        public void pushBlock(Block block) {
1028            blocks.add(block);
1029        }
1030    
1031        public Block popBlock() {
1032            return blocks.isEmpty() ? null : blocks.removeLast();
1033        }
1034    
1035        public Type proceed() {
1036            ProceedType proceed = null;
1037            ProcessorType currentProcessor = this;
1038    
1039            if (currentProcessor instanceof InterceptType) {
1040                proceed = ((InterceptType) currentProcessor).getProceed();
1041                LOG.info("proceed() is the implied and hence not needed for an intercept()");
1042            }
1043            if (proceed == null) {
1044                for (ProcessorType node = parent; node != null; node = node.getParent()) {
1045                    if (node instanceof InterceptType) {
1046                        InterceptType intercept = (InterceptType)node;
1047                        proceed = intercept.getProceed();
1048                        break;
1049                    }
1050                }
1051    
1052                if (proceed == null) {
1053                    throw new IllegalArgumentException("Cannot use proceed() without being within an intercept() block");
1054                }
1055    
1056            }
1057    
1058            addOutput(proceed);
1059            return (Type) this;
1060        }
1061    
1062        public Type stop() {
1063            ProcessorType currentProcessor = this;
1064    
1065            if (currentProcessor instanceof InterceptType) {
1066                ((InterceptType) currentProcessor).stopIntercept();
1067            } else {
1068                ProcessorType node;
1069                for (node = parent; node != null; node = node.getParent()) {
1070                    if (node instanceof InterceptType) {
1071                        ((InterceptType) node).stopIntercept();
1072                        break;
1073                    }
1074                }
1075                if (node == null) {
1076                    throw new IllegalArgumentException("Cannot use stop() without being within an intercept() block");
1077                }
1078            }
1079    
1080            return (Type) this;
1081        }
1082    
1083        /**
1084         * Catches an exception type.
1085         *
1086         * @deprecated Please use {@link #onException(Class)} instead. Will be removed in Camel 2.0.
1087         */
1088        public ExceptionType exception(Class exceptionType) {
1089            return onException(exceptionType);
1090        }
1091    
1092        /**
1093         * Catches an exception type.
1094         */
1095        public ExceptionType onException(Class exceptionType) {
1096            ExceptionType answer = new ExceptionType(exceptionType);
1097            addOutput(answer);
1098            return answer;
1099        }
1100    
1101        /**
1102         * Apply an interceptor route if the predicate is true
1103         */
1104        public ChoiceType intercept(Predicate predicate) {
1105            InterceptType answer = new InterceptType();
1106            addOutput(answer);
1107            return answer.when(predicate);
1108        }
1109    
1110        public Type interceptors(String... refs) {
1111            for (String ref : refs) {
1112                interceptor(ref);
1113            }
1114            return (Type) this;
1115        }
1116    
1117        /**
1118         * Trace logs the exchange before it goes to the next processing step using
1119         * the {@link #DEFAULT_TRACE_CATEGORY} logging category.
1120         *
1121         * @deprecated Please use <a href="http://activemq.apache.org/camel/tracer.html>Tracer Support</a>
1122         * instead. Will be removed in Camel 2.0.
1123         */
1124        public Type trace() {
1125            return trace(DEFAULT_TRACE_CATEGORY);
1126        }
1127    
1128        /**
1129         * Trace logs the exchange before it goes to the next processing step using
1130         * the specified logging category.
1131         *
1132         * @param category the logging category trace messages will sent to.
1133         *
1134         * @deprecated Please use <a href="http://activemq.apache.org/camel/tracer.html>Tracer Support</a>
1135         * instead. Will be removed in Camel 2.0.
1136         */
1137        public Type trace(String category) {
1138            final Log log = LogFactory.getLog(category);
1139            return intercept(new DelegateProcessor() {
1140                @Override
1141                public void process(Exchange exchange) throws Exception {
1142                    log.trace(exchange);
1143                    processNext(exchange);
1144                }
1145            });
1146        }
1147    
1148        public PolicyRef policies() {
1149            PolicyRef answer = new PolicyRef();
1150            addOutput(answer);
1151            return answer;
1152        }
1153    
1154        public PolicyRef policy(Policy policy) {
1155            PolicyRef answer = new PolicyRef(policy);
1156            addOutput(answer);
1157            return answer;
1158        }
1159    
1160        /**
1161         * Forces handling of faults as exceptions
1162         *
1163         * @return the current builder with the fault handler configured
1164         */
1165        public Type handleFault() {
1166            intercept(new HandleFaultType());
1167            return (Type) this;
1168        }
1169    
1170        /**
1171         * Installs the given error handler builder
1172         *
1173         * @param errorHandlerBuilder the error handler to be used by default for
1174         *                            all child routes
1175         * @return the current builder with the error handler configured
1176         */
1177        public Type errorHandler(ErrorHandlerBuilder errorHandlerBuilder) {
1178            setErrorHandlerBuilder(errorHandlerBuilder);
1179            return (Type) this;
1180        }
1181    
1182        /**
1183         * Configures whether or not the error handler is inherited by every
1184         * processing node (or just the top most one)
1185         *
1186         * @param condition the flag as to whether error handlers should be
1187         *                  inherited or not
1188         * @return the current builder
1189         */
1190        public Type inheritErrorHandler(boolean condition) {
1191            setInheritErrorHandlerFlag(condition);
1192            return (Type) this;
1193        }
1194    
1195        // Transformers
1196        // -------------------------------------------------------------------------
1197    
1198        /**
1199         * Adds the custom processor to this destination which could be a final
1200         * destination, or could be a transformation in a pipeline
1201         */
1202        public Type process(Processor processor) {
1203            ProcessorRef answer = new ProcessorRef(processor);
1204            addOutput(answer);
1205            return (Type) this;
1206        }
1207    
1208        /**
1209         * Adds the custom processor reference to this destination which could be a final
1210         * destination, or could be a transformation in a pipeline
1211         */
1212        public Type processRef(String ref) {
1213            ProcessorRef answer = new ProcessorRef();
1214            answer.setRef(ref);
1215            addOutput(answer);
1216            return (Type) this;
1217        }
1218    
1219        /**
1220         * Adds a bean which is invoked which could be a final destination, or could
1221         * be a transformation in a pipeline
1222         */
1223        public Type bean(Object bean) {
1224            BeanRef answer = new BeanRef();
1225            answer.setBean(bean);
1226            addOutput(answer);
1227            return (Type) this;
1228        }
1229    
1230        /**
1231         * Adds a bean and method which is invoked which could be a final
1232         * destination, or could be a transformation in a pipeline
1233         */
1234        public Type bean(Object bean, String method) {
1235            BeanRef answer = new BeanRef();
1236            answer.setBean(bean);
1237            answer.setMethod(method);
1238            addOutput(answer);
1239            return (Type) this;
1240        }
1241    
1242        /**
1243         * Adds a bean by type which is invoked which could be a final destination, or could
1244         * be a transformation in a pipeline
1245         */
1246        public Type bean(Class beanType) {
1247            BeanRef answer = new BeanRef();
1248            answer.setBeanType(beanType);
1249            addOutput(answer);
1250            return (Type) this;
1251        }
1252    
1253        /**
1254         * Adds a bean type and method which is invoked which could be a final
1255         * destination, or could be a transformation in a pipeline
1256         */
1257        public Type bean(Class beanType, String method) {
1258            BeanRef answer = new BeanRef();
1259            answer.setBeanType(beanType);
1260            answer.setMethod(method);
1261            addOutput(answer);
1262            return (Type) this;
1263        }
1264    
1265        /**
1266         * Adds a bean which is invoked which could be a final destination, or could
1267         * be a transformation in a pipeline
1268         */
1269        public Type beanRef(String ref) {
1270            BeanRef answer = new BeanRef(ref);
1271            addOutput(answer);
1272            return (Type) this;
1273        }
1274    
1275        /**
1276         * Adds a bean and method which is invoked which could be a final
1277         * destination, or could be a transformation in a pipeline
1278         */
1279        public Type beanRef(String ref, String method) {
1280            BeanRef answer = new BeanRef(ref, method);
1281            addOutput(answer);
1282            return (Type) this;
1283        }
1284    
1285        /**
1286         * Adds a processor which sets the body on the IN message
1287         */
1288        public ExpressionClause<ProcessorType<Type>> setBody() {
1289            ExpressionClause<ProcessorType<Type>> clause = new ExpressionClause<ProcessorType<Type>>((Type) this);
1290            SetBodyType answer = new SetBodyType(clause);
1291            addOutput(answer);
1292            return clause;
1293        }
1294    
1295        /**
1296         * Adds a processor which sets the body on the IN message
1297         */
1298        public Type setBody(Expression expression) {
1299            SetBodyType answer = new SetBodyType(expression);
1300            addOutput(answer);
1301            return (Type) this;
1302        }
1303    
1304        /**
1305         * Adds a processor which sets the body on the OUT message
1306         *
1307         * @deprecated Please use {@link #transform(Expression)} instead. Will be removed in Camel 2.0.
1308         */
1309        @Deprecated
1310        public Type setOutBody(Expression expression) {
1311            return transform(expression);
1312        }
1313    
1314        /**
1315         * Adds a processor which sets the body on the OUT message
1316         *
1317         * @deprecated Please use {@link #transform()} instead. Will be removed in Camel 2.0.
1318         */
1319        @Deprecated
1320        public ExpressionClause<ProcessorType<Type>> setOutBody() {
1321            return transform();
1322        }
1323    
1324        /**
1325         * Adds a processor which sets the body on the OUT message
1326         */
1327        public Type transform(Expression expression) {
1328            TransformType answer = new TransformType(expression);
1329            addOutput(answer);
1330            return (Type) this;
1331        }
1332    
1333        /**
1334         * Adds a processor which sets the body on the OUT message
1335         */
1336        public ExpressionClause<ProcessorType<Type>> transform() {
1337            ExpressionClause<ProcessorType<Type>> clause = new ExpressionClause<ProcessorType<Type>>((Type) this);
1338            TransformType answer = new TransformType(clause);
1339            addOutput(answer);
1340            return clause;
1341        }
1342    
1343        /**
1344         * Adds a processor which sets the body on the FAULT message
1345         */
1346        public Type setFaultBody(Expression expression) {
1347            return process(ProcessorBuilder.setFaultBody(expression));
1348        }
1349    
1350        /**
1351         * Adds a processor which sets the header on the IN message
1352         */
1353        public ExpressionClause<ProcessorType<Type>> setHeader(String name) {
1354            ExpressionClause<ProcessorType<Type>> clause = new ExpressionClause<ProcessorType<Type>>((Type) this);
1355            SetHeaderType answer = new SetHeaderType(name, clause);
1356            addOutput(answer);
1357            return clause;
1358        }
1359    
1360        /**
1361         * Adds a processor which sets the header on the IN message
1362         */
1363        public Type setHeader(String name, Expression expression) {
1364            SetHeaderType answer = new SetHeaderType(name, expression);
1365            addOutput(answer);
1366            return (Type) this;
1367        }
1368    
1369        /**
1370         * Adds a processor which sets the header on the IN message to the given value
1371         * @deprecated Please use {@link #setHeader(String, Expression)} instead. Will be removed in Camel 2.0.
1372         */
1373        public Type setHeader(String name, String value) {
1374            SetHeaderType answer = new SetHeaderType(name, value);
1375            addOutput(answer);
1376            return (Type) this;
1377        }
1378    
1379        /**
1380         * Adds a processor which sets the header on the OUT message
1381         */
1382        public ExpressionClause<ProcessorType<Type>> setOutHeader(String name) {
1383            ExpressionClause<ProcessorType<Type>> clause = new ExpressionClause<ProcessorType<Type>>((Type) this);
1384            SetOutHeaderType answer = new SetOutHeaderType(name, clause);
1385            addOutput(answer);
1386            return clause;
1387        }
1388    
1389        /**
1390         * Adds a processor which sets the header on the OUT message
1391         */
1392        public Type setOutHeader(String name, Expression expression) {
1393            SetOutHeaderType answer = new SetOutHeaderType(name, expression);
1394            addOutput(answer);
1395            return (Type) this;
1396        }
1397    
1398        /**
1399         * Adds a processor which sets the header on the FAULT message
1400         */
1401        public Type setFaultHeader(String name, Expression expression) {
1402            return process(ProcessorBuilder.setFaultHeader(name, expression));
1403        }
1404    
1405        /**
1406         * Adds a processor which sets the exchange property
1407         */
1408        public Type setProperty(String name, Expression expression) {
1409            SetPropertyType answer = new SetPropertyType(name, expression);
1410            addOutput(answer);
1411            return (Type) this;
1412        }
1413    
1414    
1415        /**
1416         * Adds a processor which sets the exchange property
1417         */
1418        public ExpressionClause<ProcessorType<Type>> setProperty(String name) {
1419            ExpressionClause<ProcessorType<Type>> clause = new ExpressionClause<ProcessorType<Type>>((Type) this);
1420            SetPropertyType answer = new SetPropertyType(name, clause);
1421            addOutput(answer);
1422            return clause;
1423        }
1424    
1425        /**
1426         * Adds a processor which removes the header on the IN message
1427         */
1428        public Type removeHeader(String name) {
1429            RemoveHeaderType answer = new RemoveHeaderType(name);
1430            addOutput(answer);
1431            return (Type) this;
1432        }
1433    
1434        /**
1435         * Adds a processor which removes the header on the FAULT message
1436         */
1437        public Type removeFaultHeader(String name) {
1438            return process(ProcessorBuilder.removeFaultHeader(name));
1439        }
1440    
1441        /**
1442         * Adds a processor which removes the exchange property
1443         */
1444        public Type removeProperty(String name) {
1445            RemovePropertyType answer = new RemovePropertyType(name);
1446            addOutput(answer);
1447            return (Type) this;
1448        }
1449    
1450        /**
1451         * Converts the IN message body to the specified type
1452         */
1453        public Type convertBodyTo(Class type) {
1454            addOutput(new ConvertBodyType(type));
1455            return (Type) this;
1456        }
1457        
1458        /**
1459         * Converts the IN message body to the specified class type
1460         */
1461        public Type convertBodyTo(String typeString) {
1462            addOutput(new ConvertBodyType(typeString));
1463            return (Type) this;
1464        }
1465    
1466        /**
1467         * Converts the OUT message body to the specified type
1468         *
1469         * @deprecated Please use {@link #convertBodyTo(Class)} instead. Will be removed in Camel 2.0.
1470         */
1471        @Deprecated
1472        public Type convertOutBodyTo(Class type) {
1473            return process(new ConvertBodyProcessor(type));
1474        }
1475    
1476        /**
1477         * Converts the FAULT message body to the specified type
1478         *
1479         * @deprecated Please use {@link #convertBodyTo(Class)} instead. Will be removed in Camel 2.0.
1480         */
1481        @Deprecated
1482        public Type convertFaultBodyTo(Class type) {
1483            return process(new ConvertBodyProcessor(type));
1484        }
1485    
1486        // DataFormat support
1487        // -------------------------------------------------------------------------
1488    
1489        /**
1490         * Unmarshals the in body using a {@link DataFormat} expression to define
1491         * the format of the input message and the output will be set on the out message body.
1492         *
1493         * @return the expression to create the {@link DataFormat}
1494         */
1495        public DataFormatClause<ProcessorType<Type>> unmarshal() {
1496            return new DataFormatClause<ProcessorType<Type>>(this, DataFormatClause.Operation.Unmarshal);
1497        }
1498    
1499        /**
1500         * Unmarshals the in body using the specified {@link DataFormat}
1501         * and sets the output on the out message body.
1502         *
1503         * @return this object
1504         */
1505        public Type unmarshal(DataFormatType dataFormatType) {
1506            addOutput(new UnmarshalType(dataFormatType));
1507            return (Type) this;
1508        }
1509    
1510        /**
1511         * Unmarshals the in body using the specified {@link DataFormat}
1512         * and sets the output on the out message body.
1513         *
1514         * @return this object
1515         */
1516        public Type unmarshal(DataFormat dataFormat) {
1517            return unmarshal(new DataFormatType(dataFormat));
1518        }
1519    
1520        /**
1521         * Unmarshals the in body using the specified {@link DataFormat}
1522         * reference in the {@link org.apache.camel.spi.Registry} and sets
1523         * the output on the out message body.
1524         *
1525         * @return this object
1526         */
1527        public Type unmarshal(String dataTypeRef) {
1528            addOutput(new UnmarshalType(dataTypeRef));
1529            return (Type) this;
1530        }
1531    
1532        /**
1533         * Marshals the in body using a {@link DataFormat} expression to define
1534         * the format of the output which will be added to the out body.
1535         *
1536         * @return the expression to create the {@link DataFormat}
1537         */
1538        public DataFormatClause<ProcessorType<Type>> marshal() {
1539            return new DataFormatClause<ProcessorType<Type>>(this, DataFormatClause.Operation.Marshal);
1540        }
1541    
1542        /**
1543         * Marshals the in body using the specified {@link DataFormat}
1544         * and sets the output on the out message body.
1545         *
1546         * @return this object
1547         */
1548        public Type marshal(DataFormatType dataFormatType) {
1549            addOutput(new MarshalType(dataFormatType));
1550            return (Type) this;
1551        }
1552    
1553        /**
1554         * Marshals the in body using the specified {@link DataFormat}
1555         * and sets the output on the out message body.
1556         *
1557         * @return this object
1558         */
1559        public Type marshal(DataFormat dataFormat) {
1560            return marshal(new DataFormatType(dataFormat));
1561        }
1562    
1563        /**
1564         * Marshals the in body the specified {@link DataFormat}
1565         * reference in the {@link org.apache.camel.spi.Registry} and sets
1566         * the output on the out message body.
1567         *
1568         * @return this object
1569         */
1570        public Type marshal(String dataTypeRef) {
1571            addOutput(new MarshalType(dataTypeRef));
1572            return (Type) this;
1573        }
1574    
1575        // Properties
1576        // -------------------------------------------------------------------------
1577        @XmlTransient
1578        public ProcessorType<? extends ProcessorType> getParent() {
1579            return parent;
1580        }
1581    
1582        public void setParent(ProcessorType<? extends ProcessorType> parent) {
1583            this.parent = parent;
1584        }
1585    
1586        @XmlTransient
1587        public ErrorHandlerBuilder getErrorHandlerBuilder() {
1588            if (errorHandlerBuilder == null) {
1589                errorHandlerBuilder = createErrorHandlerBuilder();
1590            }
1591            return errorHandlerBuilder;
1592        }
1593    
1594        /**
1595         * Sets the error handler to use with processors created by this builder
1596         */
1597        public void setErrorHandlerBuilder(ErrorHandlerBuilder errorHandlerBuilder) {
1598            this.errorHandlerBuilder = errorHandlerBuilder;
1599        }
1600    
1601        /**
1602         * Sets the error handler if one is not already set
1603         */
1604        protected void setErrorHandlerBuilderIfNull(ErrorHandlerBuilder errorHandlerBuilder) {
1605            if (this.errorHandlerBuilder == null) {
1606                setErrorHandlerBuilder(errorHandlerBuilder);
1607            }
1608        }
1609    
1610        public String getErrorHandlerRef() {
1611            return errorHandlerRef;
1612        }
1613    
1614        /**
1615         * Sets the bean ref name of the error handler builder to use on this route
1616         */
1617        @XmlAttribute(required = false)
1618        public void setErrorHandlerRef(String errorHandlerRef) {
1619            this.errorHandlerRef = errorHandlerRef;
1620            setErrorHandlerBuilder(new ErrorHandlerBuilderRef(errorHandlerRef));
1621        }
1622    
1623        @XmlTransient
1624        public boolean isInheritErrorHandler() {
1625            return isInheritErrorHandler(getInheritErrorHandlerFlag());
1626        }
1627    
1628        /**
1629         * Lets default the inherit value to be true if there is none specified
1630         */
1631        public static boolean isInheritErrorHandler(Boolean value) {
1632            return value == null || value.booleanValue();
1633        }
1634    
1635        @XmlAttribute(name = "inheritErrorHandler", required = false)
1636        public Boolean getInheritErrorHandlerFlag() {
1637            return inheritErrorHandlerFlag;
1638        }
1639    
1640        public void setInheritErrorHandlerFlag(Boolean inheritErrorHandlerFlag) {
1641            this.inheritErrorHandlerFlag = inheritErrorHandlerFlag;
1642        }
1643    
1644        @XmlTransient
1645        public NodeFactory getNodeFactory() {
1646            if (nodeFactory == null) {
1647                nodeFactory = new NodeFactory();
1648            }
1649            return nodeFactory;
1650        }
1651    
1652        public void setNodeFactory(NodeFactory nodeFactory) {
1653            this.nodeFactory = nodeFactory;
1654        }
1655    
1656        /**
1657         * Returns a label to describe this node such as the expression if some kind of expression node
1658         */
1659        public String getLabel() {
1660            return "";
1661        }
1662    
1663        // Implementation methods
1664        // -------------------------------------------------------------------------
1665    
1666        /**
1667         * Creates the processor and wraps it in any necessary interceptors and
1668         * error handlers
1669         */
1670        protected Processor makeProcessor(RouteContext routeContext) throws Exception {
1671            Processor processor = createProcessor(routeContext);
1672            return wrapProcessor(routeContext, processor);
1673        }
1674    
1675        /**
1676         * A strategy method which allows derived classes to wrap the child
1677         * processor in some kind of interceptor
1678         *
1679         * @param routeContext
1680         * @param target       the processor which can be wrapped
1681         * @return the original processor or a new wrapped interceptor
1682         */
1683        protected Processor wrapProcessorInInterceptors(RouteContext routeContext, Processor target) throws Exception {
1684            // The target is required.
1685            if (target == null) {
1686                throw new IllegalArgumentException("target not provided on node: " + this);
1687            }
1688    
1689            List<InterceptStrategy> strategies = new ArrayList<InterceptStrategy>();
1690            CamelContext camelContext = routeContext.getCamelContext();
1691            if (camelContext instanceof DefaultCamelContext) {
1692                DefaultCamelContext defaultCamelContext = (DefaultCamelContext) camelContext;
1693                strategies.addAll(defaultCamelContext.getInterceptStrategies());
1694            }
1695            strategies.addAll(routeContext.getInterceptStrategies());
1696            for (InterceptStrategy strategy : strategies) {
1697                if (strategy != null) {
1698                    target = strategy.wrapProcessorInInterceptors(this, target);
1699                }
1700            }
1701    
1702            List<InterceptorType> list = routeContext.getRoute().getInterceptors();
1703            if (interceptors != null) {
1704                list.addAll(interceptors);
1705            }
1706            // lets reverse the list so we apply the inner interceptors first
1707            Collections.reverse(list);
1708            Set<Processor> interceptors = new HashSet<Processor>();
1709            interceptors.add(target);
1710            for (InterceptorType interceptorType : list) {
1711                DelegateProcessor interceptor = interceptorType.createInterceptor(routeContext);
1712                if (!interceptors.contains(interceptor)) {
1713                    interceptors.add(interceptor);
1714                    if (interceptor.getProcessor() != null) {
1715                        LOG.warn("Interceptor " + interceptor + " currently wraps target "
1716                                + interceptor.getProcessor()
1717                                + " is attempting to change target " + target
1718                                + " new wrapping has been denied.");
1719                    } else {
1720                        interceptor.setProcessor(target);
1721                        target = interceptor;
1722                    }
1723                }
1724            }
1725            return target;
1726        }
1727    
1728        /**
1729         * A strategy method to allow newly created processors to be wrapped in an
1730         * error handler.
1731         */
1732        protected Processor wrapInErrorHandler(RouteContext routeContext, Processor target) throws Exception {
1733            // The target is required.
1734            if (target == null) {
1735                throw new IllegalArgumentException("target not provided on node: " + this);
1736            }
1737    
1738            ErrorHandlerWrappingStrategy strategy = routeContext.getErrorHandlerWrappingStrategy();
1739    
1740            if (strategy != null) {
1741                return strategy.wrapProcessorInErrorHandler(routeContext, this, target);
1742            }
1743    
1744            return getErrorHandlerBuilder().createErrorHandler(routeContext, target);
1745        }
1746    
1747        protected ErrorHandlerBuilder createErrorHandlerBuilder() {
1748            if (errorHandlerRef != null) {
1749                return new ErrorHandlerBuilderRef(errorHandlerRef);
1750            }
1751            if (isInheritErrorHandler()) {
1752                return new DeadLetterChannelBuilder();
1753            } else {
1754                return new NoErrorHandlerBuilder();
1755            }
1756        }
1757    
1758        protected void configureChild(ProcessorType output) {
1759            output.setNodeFactory(getNodeFactory());
1760        }
1761    
1762        public void addOutput(ProcessorType processorType) {
1763            processorType.setParent(this);
1764            configureChild(processorType);
1765            if (blocks.isEmpty()) {
1766                getOutputs().add(processorType);
1767            } else {
1768                Block block = blocks.getLast();
1769                block.addOutput(processorType);
1770            }
1771        }
1772    
1773        /**
1774         * Creates a new instance of some kind of composite processor which defaults
1775         * to using a {@link Pipeline} but derived classes could change the
1776         * behaviour
1777         */
1778        protected Processor createCompositeProcessor(RouteContext routeContext, List<Processor> list) {
1779            // return new MulticastProcessor(list);
1780            return new Pipeline(list);
1781        }
1782    
1783        protected Processor createOutputsProcessor(RouteContext routeContext, Collection<ProcessorType<?>> outputs)
1784            throws Exception {
1785            List<Processor> list = new ArrayList<Processor>();
1786            for (ProcessorType output : outputs) {
1787                Processor processor = output.createProcessor(routeContext);
1788                // if the ProceedType create processor is null we keep on going
1789                if (output instanceof ProceedType && processor == null) {
1790                    continue;
1791                }
1792                processor = output.wrapProcessorInInterceptors(routeContext, processor);
1793    
1794                ProcessorType currentProcessor = this;
1795                if (!(currentProcessor instanceof ExceptionType || currentProcessor instanceof TryType)) {
1796                    processor = output.wrapInErrorHandler(routeContext, processor);
1797                }
1798    
1799                list.add(processor);
1800            }
1801            Processor processor = null;
1802            if (!list.isEmpty()) {
1803                if (list.size() == 1) {
1804                    processor = list.get(0);
1805                } else {
1806                    processor = createCompositeProcessor(routeContext, list);
1807                }
1808            }
1809            return processor;
1810        }
1811    
1812        public void clearOutput() {
1813            getOutputs().clear();
1814            blocks.clear();
1815        }
1816    }