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.Collection; 020 021 import javax.xml.bind.annotation.XmlAccessType; 022 import javax.xml.bind.annotation.XmlAccessorType; 023 import javax.xml.bind.annotation.XmlAttribute; 024 import javax.xml.bind.annotation.XmlElement; 025 import javax.xml.bind.annotation.XmlRootElement; 026 import javax.xml.bind.annotation.XmlTransient; 027 028 import org.apache.camel.Endpoint; 029 import org.apache.camel.Exchange; 030 import org.apache.camel.Expression; 031 import org.apache.camel.Predicate; 032 import org.apache.camel.Processor; 033 import org.apache.camel.Route; 034 import org.apache.camel.builder.ExpressionClause; 035 import org.apache.camel.model.language.ExpressionType; 036 import org.apache.camel.processor.Aggregator; 037 import org.apache.camel.processor.aggregate.AggregationCollection; 038 import org.apache.camel.processor.aggregate.AggregationStrategy; 039 import org.apache.camel.processor.aggregate.UseLatestAggregationStrategy; 040 import org.apache.camel.spi.RouteContext; 041 042 /** 043 * Represents an XML <aggregator/> element 044 * 045 * @version $Revision: 61188 $ 046 */ 047 @XmlRootElement(name = "aggregator") 048 @XmlAccessorType(XmlAccessType.FIELD) 049 public class AggregatorType extends ExpressionNode { 050 @XmlTransient 051 private AggregationStrategy aggregationStrategy; 052 @XmlTransient 053 private AggregationCollection aggregationCollection; 054 @XmlAttribute(required = false) 055 private Integer batchSize; 056 @XmlAttribute(required = false) 057 private Integer outBatchSize; 058 @XmlAttribute(required = false) 059 private Long batchTimeout; 060 @XmlAttribute(required = false) 061 private String strategyRef; 062 @XmlAttribute(required = false) 063 private String collectionRef; 064 @XmlElement(name = "completedPredicate", required = false) 065 private ExpressionSubElementType completedPredicate; 066 067 public AggregatorType() { 068 } 069 070 public AggregatorType(Expression correlationExpression) { 071 super(correlationExpression); 072 } 073 074 public AggregatorType(ExpressionType correlationExpression) { 075 super(correlationExpression); 076 } 077 078 public AggregatorType(Expression correlationExpression, AggregationStrategy aggregationStrategy) { 079 super(correlationExpression); 080 this.aggregationStrategy = aggregationStrategy; 081 } 082 083 @Override 084 public String toString() { 085 return "Aggregator[" + getExpression() + " -> " + getOutputs() + "]"; 086 } 087 088 @Override 089 public String getShortName() { 090 return "aggregator"; 091 } 092 093 @SuppressWarnings("unchecked") 094 @Override 095 public void addRoutes(RouteContext routeContext, Collection<Route> routes) throws Exception { 096 final Aggregator aggregator = createAggregator(routeContext); 097 doAddRoute(routeContext, routes, aggregator); 098 } 099 100 private void doAddRoute(RouteContext routeContext, Collection<Route> routes, final Aggregator aggregator) 101 throws Exception { 102 Route route = new Route<Exchange>(aggregator.getEndpoint(), aggregator) { 103 @Override 104 public String toString() { 105 return "AggregatorRoute[" + getEndpoint() + " -> " + aggregator.getProcessor() + "]"; 106 } 107 }; 108 109 routes.add(route); 110 } 111 112 @Override 113 public Processor createProcessor(RouteContext routeContext) throws Exception { 114 final Aggregator aggregator = createAggregator(routeContext); 115 116 doAddRoute(routeContext, routeContext.getCamelContext().getRoutes(), aggregator); 117 routeContext.setIsRouteAdded(true); 118 return aggregator; 119 } 120 121 protected Aggregator createAggregator(RouteContext routeContext) throws Exception { 122 Endpoint from = routeContext.getEndpoint(); 123 final Processor processor = routeContext.createProcessor(this); 124 125 final Aggregator aggregator; 126 if (getAggregationCollection() == null) { 127 setAggregationCollection(createAggregationCollection(routeContext)); 128 } 129 130 if (aggregationCollection != null) { 131 // create the aggregator using the collection 132 // pre configure the collection if its expression and strategy is not set, then 133 // use the ones that is pre configured with this type 134 if (aggregationCollection.getCorrelationExpression() == null) { 135 aggregationCollection.setCorrelationExpression(getExpression()); 136 } 137 if (aggregationCollection.getAggregationStrategy() == null) { 138 AggregationStrategy strategy = createAggregationStrategy(routeContext); 139 aggregationCollection.setAggregationStrategy(strategy); 140 } 141 aggregator = new Aggregator(from, processor, aggregationCollection); 142 } else { 143 // create the aggregator using a default collection 144 AggregationStrategy strategy = createAggregationStrategy(routeContext); 145 146 Expression aggregateExpression = getExpression().createExpression(routeContext); 147 148 Predicate predicate = null; 149 if (getCompletedPredicate() != null) { 150 predicate = getCompletedPredicate().createPredicate(routeContext); 151 } 152 if (predicate != null) { 153 aggregator = new Aggregator(from, processor, aggregateExpression, strategy, predicate); 154 } else { 155 aggregator = new Aggregator(from, processor, aggregateExpression, strategy); 156 } 157 } 158 159 if (batchSize != null) { 160 aggregator.setBatchSize(batchSize); 161 } 162 163 if (batchTimeout != null) { 164 aggregator.setBatchTimeout(batchTimeout); 165 } 166 167 if (outBatchSize != null) { 168 aggregator.setOutBatchSize(outBatchSize); 169 } 170 171 return aggregator; 172 } 173 174 private AggregationStrategy createAggregationStrategy(RouteContext routeContext) { 175 AggregationStrategy strategy = getAggregationStrategy(); 176 if (strategy == null && strategyRef != null) { 177 strategy = routeContext.lookup(strategyRef, AggregationStrategy.class); 178 } 179 if (strategy == null) { 180 // fallback to use latest 181 strategy = new UseLatestAggregationStrategy(); 182 } 183 return strategy; 184 } 185 186 private AggregationCollection createAggregationCollection(RouteContext routeContext) { 187 AggregationCollection collection = getAggregationCollection(); 188 if (collection == null && collectionRef != null) { 189 collection = routeContext.lookup(collectionRef, AggregationCollection.class); 190 } 191 return collection; 192 } 193 194 public AggregationCollection getAggregationCollection() { 195 return aggregationCollection; 196 } 197 198 public void setAggregationCollection(AggregationCollection aggregationCollection) { 199 this.aggregationCollection = aggregationCollection; 200 } 201 202 public AggregationStrategy getAggregationStrategy() { 203 return aggregationStrategy; 204 } 205 206 public void setAggregationStrategy(AggregationStrategy aggregationStrategy) { 207 this.aggregationStrategy = aggregationStrategy; 208 } 209 210 public Integer getBatchSize() { 211 return batchSize; 212 } 213 214 public void setBatchSize(Integer batchSize) { 215 this.batchSize = batchSize; 216 } 217 218 public Integer getOutBatchSize() { 219 return outBatchSize; 220 } 221 222 public void setOutBatchSize(Integer outBatchSize) { 223 this.outBatchSize = outBatchSize; 224 } 225 226 public Long getBatchTimeout() { 227 return batchTimeout; 228 } 229 230 public void setBatchTimeout(Long batchTimeout) { 231 this.batchTimeout = batchTimeout; 232 } 233 234 public String getStrategyRef() { 235 return strategyRef; 236 } 237 238 public void setStrategyRef(String strategyRef) { 239 this.strategyRef = strategyRef; 240 } 241 242 public void setCompletedPredicate(ExpressionSubElementType completedPredicate) { 243 this.completedPredicate = completedPredicate; 244 } 245 246 public ExpressionSubElementType getCompletedPredicate() { 247 return completedPredicate; 248 } 249 250 // Fluent API 251 //------------------------------------------------------------------------- 252 public AggregatorType batchSize(int batchSize) { 253 setBatchSize(batchSize); 254 return this; 255 } 256 257 public AggregatorType outBatchSize(int batchSize) { 258 setOutBatchSize(batchSize); 259 return this; 260 } 261 262 public AggregatorType batchTimeout(long batchTimeout) { 263 setBatchTimeout(batchTimeout); 264 return this; 265 } 266 267 public AggregatorType aggregationCollection(AggregationCollection aggregationCollection) { 268 setAggregationCollection(aggregationCollection); 269 return this; 270 } 271 272 public AggregatorType aggregationStrategy(AggregationStrategy aggregationStrategy) { 273 setAggregationStrategy(aggregationStrategy); 274 return this; 275 } 276 277 public AggregatorType strategyRef(String strategyRef) { 278 setStrategyRef(strategyRef); 279 return this; 280 } 281 282 /** 283 * Sets the predicate used to determine if the aggregation is completed 284 * 285 * @return the clause used to create the predicate 286 */ 287 public ExpressionClause<AggregatorType> completedPredicate() { 288 checkNoCompletedPredicate(); 289 ExpressionClause<AggregatorType> clause = new ExpressionClause<AggregatorType>(this); 290 setCompletedPredicate(new ExpressionSubElementType((Expression)clause)); 291 return clause; 292 } 293 294 /** 295 * Sets the predicate used to determine if the aggregation is completed 296 */ 297 public AggregatorType completedPredicate(Predicate predicate) { 298 checkNoCompletedPredicate(); 299 setCompletedPredicate(new ExpressionSubElementType(predicate)); 300 return this; 301 } 302 303 protected void checkNoCompletedPredicate() { 304 if (getCompletedPredicate() != null) { 305 throw new IllegalArgumentException("There is already a completedPredicate defined for this aggregator: " + this); 306 } 307 } 308 }