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.processor;
018    
019    
020    import static org.apache.camel.util.ObjectHelper.notNull;
021    
022    import java.util.ArrayList;
023    import java.util.Collections;
024    import java.util.Iterator;
025    import java.util.List;
026    import java.util.concurrent.ThreadPoolExecutor;
027    
028    import org.apache.camel.Exchange;
029    import org.apache.camel.Expression;
030    import org.apache.camel.Message;
031    import org.apache.camel.Processor;
032    import org.apache.camel.converter.ObjectConverter;
033    import org.apache.camel.processor.aggregate.AggregationStrategy;
034    import org.apache.camel.util.CollectionHelper;
035    
036    /**
037     * Implements a dynamic <a
038     * href="http://activemq.apache.org/camel/splitter.html">Splitter</a> pattern
039     * where an expression is evaluated to iterate through each of the parts of a
040     * message and then each part is then send to some endpoint.
041     *
042     * @version $Revision: 643855 $
043     */
044    public class Splitter extends MulticastProcessor implements Processor {
045        public static final String SPLIT_SIZE = "org.apache.camel.splitSize";
046        public static final String SPLIT_COUNTER = "org.apache.camel.splitCounter";
047    
048        private final Expression expression;
049    
050        public Splitter(Expression expression, Processor destination, AggregationStrategy aggregationStrategy) {
051            this(expression, destination, aggregationStrategy, false, null);
052        }
053    
054        public Splitter(Expression expression, Processor destination,
055                AggregationStrategy aggregationStrategy,
056                boolean parallelProcessing, ThreadPoolExecutor threadPoolExecutor) {
057            super(Collections.singleton(destination), aggregationStrategy, parallelProcessing, threadPoolExecutor);
058            
059            this.expression = expression;
060            notNull(expression, "expression");
061            notNull(destination, "destination");
062        }
063    
064        @Override
065        public String toString() {
066            return "Splitter[on: " + expression + " to: " + getProcessors().iterator().next() + " aggregate: " + getAggregationStrategy() + "]";
067        }
068    
069        @Override
070        protected List<ProcessorExchangePair> createProcessorExchangePairs(
071            Exchange exchange) {
072            Object value = expression.evaluate(exchange);
073            Integer collectionSize = CollectionHelper.size(value);
074            List<ProcessorExchangePair> result;
075            if (collectionSize != null) {
076                result = new ArrayList<ProcessorExchangePair>(collectionSize);
077            } else {
078                result = new ArrayList<ProcessorExchangePair>();
079            }
080            for (Iterator<Object> iter = ObjectConverter.iterator(value); iter.hasNext(); ) {
081                Object part = iter.next();
082                Exchange newExchange = exchange.copy();
083                Message in = newExchange.getIn();
084                in.setBody(part);
085                result.add(new ProcessorExchangePair(getProcessors().iterator().next(), newExchange));
086            }
087            return result;
088        }
089    
090        @Override
091        protected void updateNewExchange(Exchange exchange, int i, List<ProcessorExchangePair> allPairs) {
092            exchange.getIn().setHeader(SPLIT_COUNTER, i);
093            exchange.getIn().setHeader(SPLIT_SIZE, allPairs.size());
094        }
095    }