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: 788621 $
035 */
036 public class ChoiceProcessor extends ServiceSupport implements Processor, Navigate<Processor>, Traceable {
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 String getTraceLabel() {
084 return "Choice";
085 }
086
087 public List<FilterProcessor> getFilters() {
088 return filters;
089 }
090
091 public Processor getOtherwise() {
092 return otherwise;
093 }
094
095 public List<Processor> next() {
096 if (!hasNext()) {
097 return null;
098 }
099 List<Processor> answer = new ArrayList<Processor>();
100 if (filters != null) {
101 answer.addAll(filters);
102 }
103 if (otherwise != null) {
104 answer.add(otherwise);
105 }
106 return answer;
107 }
108
109 public boolean hasNext() {
110 return otherwise != null || (filters != null && !filters.isEmpty());
111 }
112
113 protected void doStart() throws Exception {
114 ServiceHelper.startServices(filters, otherwise);
115 }
116
117 protected void doStop() throws Exception {
118 ServiceHelper.stopServices(otherwise, filters);
119 }
120 }