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.impl.RouteContext;
036 import org.apache.camel.model.language.ExpressionType;
037 import org.apache.camel.processor.Aggregator;
038 import org.apache.camel.processor.aggregate.AggregationCollection;
039 import org.apache.camel.processor.aggregate.AggregationStrategy;
040 import org.apache.camel.processor.aggregate.UseLatestAggregationStrategy;
041
042 /**
043 * @version $Revision: 36321 $
044 */
045 @XmlRootElement(name = "aggregator")
046 @XmlAccessorType(XmlAccessType.FIELD)
047 public class AggregatorType extends ExpressionNode {
048 @XmlTransient
049 private AggregationStrategy aggregationStrategy;
050 @XmlTransient
051 private AggregationCollection aggregationCollection;
052 @XmlAttribute(required = false)
053 private Integer batchSize;
054 @XmlAttribute(required = false)
055 private Long batchTimeout;
056 @XmlAttribute(required = false)
057 private String strategyRef;
058 @XmlElement(name = "completedPredicate", required = false)
059 private CompletedPredicate completedPredicate;
060
061 public AggregatorType() {
062 }
063
064 public AggregatorType(Expression correlationExpression) {
065 super(correlationExpression);
066 }
067
068 public AggregatorType(ExpressionType correlationExpression) {
069 super(correlationExpression);
070 }
071
072 public AggregatorType(Expression correlationExpression, AggregationStrategy aggregationStrategy) {
073 super(correlationExpression);
074 this.aggregationStrategy = aggregationStrategy;
075 }
076
077 @Override
078 public String toString() {
079 return "Aggregator[ " + getExpression() + " -> " + getOutputs() + "]";
080 }
081
082 @SuppressWarnings("unchecked")
083 @Override
084 public void addRoutes(RouteContext routeContext, Collection<Route> routes) throws Exception {
085 Endpoint from = routeContext.getEndpoint();
086 final Processor processor = routeContext.createProcessor(this);
087
088 final Aggregator service;
089 if (aggregationCollection != null) {
090 service = new Aggregator(from, processor, aggregationCollection);
091 } else {
092 AggregationStrategy strategy = getAggregationStrategy();
093 if (strategy == null && strategyRef != null) {
094 strategy = routeContext.lookup(strategyRef, AggregationStrategy.class);
095 }
096 if (strategy == null) {
097 strategy = new UseLatestAggregationStrategy();
098 }
099 Expression aggregateExpression = getExpression().createExpression(routeContext);
100
101 Predicate predicate = null;
102 if (completedPredicate != null) {
103 predicate = completedPredicate.createPredicate(routeContext);
104 }
105 if (predicate != null) {
106 service = new Aggregator(from, processor, aggregateExpression, strategy, predicate);
107 } else {
108 service = new Aggregator(from, processor, aggregateExpression, strategy);
109 }
110 }
111
112 if (batchSize != null) {
113 service.setBatchSize(batchSize);
114 }
115 if (batchTimeout != null) {
116 service.setBatchTimeout(batchTimeout);
117 }
118
119 Route route = new Route<Exchange>(from, service) {
120 @Override
121 public String toString() {
122 return "AggregatorRoute[" + getEndpoint() + " -> " + processor + "]";
123 }
124 };
125
126 routes.add(route);
127 }
128
129 public AggregationCollection getAggregationCollection() {
130 return aggregationCollection;
131 }
132
133 public void setAggregationCollection(AggregationCollection aggregationCollection) {
134 this.aggregationCollection = aggregationCollection;
135 }
136
137 public AggregationStrategy getAggregationStrategy() {
138 return aggregationStrategy;
139 }
140
141 public void setAggregationStrategy(AggregationStrategy aggregationStrategy) {
142 this.aggregationStrategy = aggregationStrategy;
143 }
144
145 public Integer getBatchSize() {
146 return batchSize;
147 }
148
149 public void setBatchSize(Integer batchSize) {
150 this.batchSize = batchSize;
151 }
152
153 public Long getBatchTimeout() {
154 return batchTimeout;
155 }
156
157 public void setBatchTimeout(Long batchTimeout) {
158 this.batchTimeout = batchTimeout;
159 }
160
161 public String getStrategyRef() {
162 return strategyRef;
163 }
164
165 public void setStrategyRef(String strategyRef) {
166 this.strategyRef = strategyRef;
167 }
168
169 public CompletedPredicate getCompletePredicate() {
170 return completedPredicate;
171 }
172
173 public void setCompletePredicate(CompletedPredicate completedPredicate) {
174 this.completedPredicate = completedPredicate;
175 }
176
177 // Fluent API
178 //-------------------------------------------------------------------------
179 public AggregatorType batchSize(int batchSize) {
180 setBatchSize(batchSize);
181 return this;
182 }
183
184 public AggregatorType batchTimeout(long batchTimeout) {
185 setBatchTimeout(batchTimeout);
186 return this;
187 }
188
189 /**
190 * Sets the predicate used to determine if the aggregation is completed
191 *
192 * @return the clause used to create the predicate
193 */
194 public ExpressionClause<AggregatorType> completedPredicate() {
195 checkNoCompletedPredicate();
196 ExpressionClause<AggregatorType> clause = new ExpressionClause<AggregatorType>(this);
197 completedPredicate = new CompletedPredicate(clause);
198 return clause;
199 }
200
201 /**
202 * Sets the predicate used to determine if the aggregation is completed
203 */
204 public AggregatorType completedPredicate(Predicate predicate) {
205 checkNoCompletedPredicate();
206 completedPredicate = new CompletedPredicate(predicate);
207 return this;
208 }
209
210 protected void checkNoCompletedPredicate() {
211 if (completedPredicate != null) {
212 throw new IllegalArgumentException("There already is a completedPredicate defined for this aggregator: " + this);
213 }
214 }
215 }