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    import java.util.ArrayList;
020    import java.util.List;
021    
022    import org.apache.camel.Exchange;
023    import org.apache.camel.Navigate;
024    import org.apache.camel.Predicate;
025    import org.apache.camel.Processor;
026    import org.apache.camel.impl.ServiceSupport;
027    import org.apache.camel.util.ServiceHelper;
028    
029    /**
030     * Implements a Choice structure where one or more predicates are used which if
031     * they are true their processors are used, with a default otherwise clause used
032     * if none match.
033     * 
034     * @version $Revision: 769303 $
035     */
036    public class ChoiceProcessor extends ServiceSupport implements Processor, Navigate<Processor> {
037        private final List<FilterProcessor> filters;
038        private final Processor otherwise;
039    
040        public ChoiceProcessor(List<FilterProcessor> filters, Processor otherwise) {
041            this.filters = filters;
042            this.otherwise = otherwise;
043        }
044    
045        public void process(Exchange exchange) throws Exception {
046            for (FilterProcessor filterProcessor : filters) {
047                Predicate predicate = filterProcessor.getPredicate();
048                if (predicate != null && predicate.matches(exchange)) {
049                    // process next will also take care (has not null test) if next was a stop().
050                    // stop() has no processor to execute, and thus we will end in a NPE 
051                    filterProcessor.processNext(exchange);
052                    return;
053                }
054            }
055            if (otherwise != null) {
056                otherwise.process(exchange);
057            }
058        }
059    
060        @Override
061        public String toString() {
062            StringBuilder builder = new StringBuilder("choice{");
063            boolean first = true;
064            for (FilterProcessor processor : filters) {
065                if (first) {
066                    first = false;
067                } else {
068                    builder.append(", ");
069                }
070                builder.append("when ");
071                builder.append(processor.getPredicate().toString());
072                builder.append(": ");
073                builder.append(processor.getProcessor());
074            }
075            if (otherwise != null) {
076                builder.append(", otherwise: ");
077                builder.append(otherwise);
078            }
079            builder.append("}");
080            return builder.toString();
081        }
082    
083        public List<FilterProcessor> getFilters() {
084            return filters;
085        }
086    
087        public Processor getOtherwise() {
088            return otherwise;
089        }
090    
091        public List<Processor> next() {
092            if (!hasNext()) {
093                return null;
094            }
095            List<Processor> answer = new ArrayList<Processor>();
096            if (filters != null) {
097                answer.addAll(filters);
098            }
099            if (otherwise != null) {
100                answer.add(otherwise);
101            }
102            return answer;
103        }
104    
105        public boolean hasNext() {
106            return otherwise != null || (filters != null && !filters.isEmpty());
107        }
108    
109        protected void doStart() throws Exception {
110            ServiceHelper.startServices(filters, otherwise);
111        }
112    
113        protected void doStop() throws Exception {
114            ServiceHelper.stopServices(otherwise, filters);
115        }
116    }