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 }