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.Collection; 021 import java.util.List; 022 023 import javax.xml.bind.annotation.XmlElement; 024 import javax.xml.bind.annotation.XmlElementRef; 025 import javax.xml.bind.annotation.XmlRootElement; 026 import javax.xml.bind.annotation.XmlTransient; 027 028 import org.apache.camel.Exchange; 029 import org.apache.camel.Expression; 030 import org.apache.camel.Processor; 031 import org.apache.camel.Route; 032 import org.apache.camel.model.config.BatchResequencerConfig; 033 import org.apache.camel.model.config.StreamResequencerConfig; 034 import org.apache.camel.model.language.ExpressionType; 035 import org.apache.camel.processor.Resequencer; 036 import org.apache.camel.processor.StreamResequencer; 037 import org.apache.camel.spi.RouteContext; 038 039 /** 040 * Represents an XML <resequencer/> element 041 * 042 * @version $Revision: 43540 $ 043 */ 044 @XmlRootElement(name = "resequencer") 045 public class ResequencerType extends ProcessorType<ProcessorType> { 046 @XmlElementRef 047 private List<ExpressionType> expressions = new ArrayList<ExpressionType>(); 048 @XmlElementRef 049 private List<ProcessorType<?>> outputs = new ArrayList<ProcessorType<?>>(); 050 // Binding annotation at setter 051 private BatchResequencerConfig batchConfig; 052 // Binding annotation at setter 053 private StreamResequencerConfig streamConfig; 054 @XmlTransient 055 private List<Expression> expressionList; 056 057 public ResequencerType() { 058 this(null); 059 } 060 061 public ResequencerType(List<Expression> expressions) { 062 this.expressionList = expressions; 063 this.batch(); 064 } 065 066 @Override 067 public String getShortName() { 068 return "resequencer"; 069 } 070 071 /** 072 * Configures the stream-based resequencing algorithm using the default 073 * configuration. 074 * 075 * @return <code>this</code> instance. 076 */ 077 public ResequencerType stream() { 078 return stream(StreamResequencerConfig.getDefault()); 079 } 080 081 /** 082 * Configures the batch-based resequencing algorithm using the default 083 * configuration. 084 * 085 * @return <code>this</code> instance. 086 */ 087 public ResequencerType batch() { 088 return batch(BatchResequencerConfig.getDefault()); 089 } 090 091 /** 092 * Configures the stream-based resequencing algorithm using the given 093 * {@link StreamResequencerConfig}. 094 * 095 * @return <code>this</code> instance. 096 */ 097 public ResequencerType stream(StreamResequencerConfig config) { 098 this.streamConfig = config; 099 this.batchConfig = null; 100 return this; 101 } 102 103 /** 104 * Configures the batch-based resequencing algorithm using the given 105 * {@link BatchResequencerConfig}. 106 * 107 * @return <code>this</code> instance. 108 */ 109 public ResequencerType batch(BatchResequencerConfig config) { 110 this.batchConfig = config; 111 this.streamConfig = null; 112 return this; 113 } 114 115 public ResequencerType expression(ExpressionType expression) { 116 expressions.add(expression); 117 return this; 118 } 119 120 @Override 121 public String toString() { 122 return "Resequencer[ " + getExpressions() + " -> " + getOutputs() + "]"; 123 } 124 125 @Override 126 public String getLabel() { 127 return ExpressionType.getLabel(getExpressions()); 128 } 129 130 public List<ExpressionType> getExpressions() { 131 return expressions; 132 } 133 134 public List<ProcessorType<?>> getOutputs() { 135 return outputs; 136 } 137 138 public void setOutputs(List<ProcessorType<?>> outputs) { 139 this.outputs = outputs; 140 } 141 142 public BatchResequencerConfig getBatchConfig() { 143 return batchConfig; 144 } 145 146 public BatchResequencerConfig getBatchConfig(BatchResequencerConfig defaultConfig) { 147 return batchConfig; 148 } 149 150 public StreamResequencerConfig getStreamConfig() { 151 return streamConfig; 152 } 153 154 @XmlElement(name = "batch-config", required = false) 155 public void setBatchConfig(BatchResequencerConfig batchConfig) { 156 // TODO: find out how to have these two within an <xsd:choice> 157 batch(batchConfig); 158 } 159 160 @XmlElement(name = "stream-config", required = false) 161 public void setStreamConfig(StreamResequencerConfig streamConfig) { 162 // TODO: find out how to have these two within an <xsd:choice> 163 stream(streamConfig); 164 } 165 166 @Override 167 public Processor createProcessor(RouteContext routeContext) throws Exception { 168 if (batchConfig != null) { 169 return createBatchResequencer(routeContext, batchConfig); 170 } else { 171 // streamConfig should be non-null if batchConfig is null 172 return createStreamResequencer(routeContext, streamConfig); 173 } 174 } 175 176 @Override 177 public void addRoutes(RouteContext routeContext, Collection<Route> routes) throws Exception { 178 if (batchConfig != null) { 179 routes.add(createBatchResequencerRoute(routeContext)); 180 } else { 181 // StreamResequencer created via createProcessor method 182 super.addRoutes(routeContext, routes); 183 } 184 } 185 186 private Route<? extends Exchange> createBatchResequencerRoute(RouteContext routeContext) throws Exception { 187 final Resequencer resequencer = createBatchResequencer(routeContext, batchConfig); 188 return new Route(routeContext.getEndpoint(), resequencer) { 189 @Override 190 public String toString() { 191 return "BatchResequencerRoute[" + getEndpoint() + " -> " + resequencer.getProcessor() + "]"; 192 } 193 }; 194 } 195 196 protected Resequencer createBatchResequencer(RouteContext routeContext, 197 BatchResequencerConfig config) throws Exception { 198 Processor processor = routeContext.createProcessor(this); 199 Resequencer resequencer = new Resequencer(routeContext.getEndpoint(), 200 processor, resolveExpressionList(routeContext)); 201 resequencer.setBatchSize(config.getBatchSize()); 202 resequencer.setBatchTimeout(config.getBatchTimeout()); 203 return resequencer; 204 } 205 206 protected StreamResequencer createStreamResequencer(RouteContext routeContext, 207 StreamResequencerConfig config) throws Exception { 208 config.getComparator().setExpressions(resolveExpressionList(routeContext)); 209 Processor processor = routeContext.createProcessor(this); 210 StreamResequencer resequencer = new StreamResequencer(processor, 211 config.getComparator(), config.getCapacity()); 212 resequencer.setTimeout(config.getTimeout()); 213 return resequencer; 214 215 } 216 217 private List<Expression> resolveExpressionList(RouteContext routeContext) { 218 if (expressionList == null) { 219 expressionList = new ArrayList<Expression>(); 220 for (ExpressionType expression : expressions) { 221 expressionList.add(expression.createExpression(routeContext)); 222 } 223 } 224 if (expressionList.isEmpty()) { 225 throw new IllegalArgumentException("No expressions configured for: " + this); 226 } 227 return expressionList; 228 } 229 }