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: 43862 $ 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 Long batchTimeout; 058 @XmlAttribute(required = false) 059 private String strategyRef; 060 @XmlElement(name = "completedPredicate", required = false) 061 private CompletedPredicate completedPredicate; 062 063 public AggregatorType() { 064 } 065 066 public AggregatorType(Expression correlationExpression) { 067 super(correlationExpression); 068 } 069 070 public AggregatorType(ExpressionType correlationExpression) { 071 super(correlationExpression); 072 } 073 074 public AggregatorType(Expression correlationExpression, AggregationStrategy aggregationStrategy) { 075 super(correlationExpression); 076 this.aggregationStrategy = aggregationStrategy; 077 } 078 079 @Override 080 public String toString() { 081 return "Aggregator[ " + getExpression() + " -> " + getOutputs() + "]"; 082 } 083 084 @Override 085 public String getShortName() { 086 return "aggregator"; 087 } 088 089 @SuppressWarnings("unchecked") 090 @Override 091 public void addRoutes(RouteContext routeContext, Collection<Route> routes) throws Exception { 092 final Aggregator aggregator = createAggregator(routeContext); 093 doAddRoute(routeContext, routes, aggregator); 094 } 095 096 private void doAddRoute(RouteContext routeContext, Collection<Route> routes, final Aggregator aggregator) 097 throws Exception { 098 Route route = new Route<Exchange>(aggregator.getEndpoint(), aggregator) { 099 @Override 100 public String toString() { 101 return "AggregatorRoute[" + getEndpoint() + " -> " + aggregator.getProcessor() + "]"; 102 } 103 }; 104 105 routes.add(route); 106 } 107 108 @Override 109 public Processor createProcessor(RouteContext routeContext) throws Exception { 110 final Aggregator aggregator = createAggregator(routeContext); 111 112 doAddRoute(routeContext, routeContext.getCamelContext().getRoutes(), aggregator); 113 routeContext.setIsRouteAdded(true); 114 return aggregator; 115 } 116 117 protected Aggregator createAggregator(RouteContext routeContext) throws Exception { 118 Endpoint from = routeContext.getEndpoint(); 119 final Processor processor = routeContext.createProcessor(this); 120 121 final Aggregator aggregator; 122 if (aggregationCollection != null) { 123 aggregator = new Aggregator(from, processor, aggregationCollection); 124 } else { 125 AggregationStrategy strategy = getAggregationStrategy(); 126 if (strategy == null && strategyRef != null) { 127 strategy = routeContext.lookup(strategyRef, AggregationStrategy.class); 128 } 129 if (strategy == null) { 130 strategy = new UseLatestAggregationStrategy(); 131 } 132 Expression aggregateExpression = getExpression().createExpression(routeContext); 133 134 Predicate predicate = null; 135 if (completedPredicate != null) { 136 predicate = completedPredicate.createPredicate(routeContext); 137 } 138 if (predicate != null) { 139 aggregator = new Aggregator(from, processor, aggregateExpression, strategy, predicate); 140 } else { 141 aggregator = new Aggregator(from, processor, aggregateExpression, strategy); 142 } 143 } 144 145 if (batchSize != null) { 146 aggregator.setBatchSize(batchSize); 147 } 148 149 if (batchTimeout != null) { 150 aggregator.setBatchTimeout(batchTimeout); 151 } 152 153 return aggregator; 154 } 155 public AggregationCollection getAggregationCollection() { 156 return aggregationCollection; 157 } 158 159 public void setAggregationCollection(AggregationCollection aggregationCollection) { 160 this.aggregationCollection = aggregationCollection; 161 } 162 163 public AggregationStrategy getAggregationStrategy() { 164 return aggregationStrategy; 165 } 166 167 public void setAggregationStrategy(AggregationStrategy aggregationStrategy) { 168 this.aggregationStrategy = aggregationStrategy; 169 } 170 171 public Integer getBatchSize() { 172 return batchSize; 173 } 174 175 public void setBatchSize(Integer batchSize) { 176 this.batchSize = batchSize; 177 } 178 179 public Long getBatchTimeout() { 180 return batchTimeout; 181 } 182 183 public void setBatchTimeout(Long batchTimeout) { 184 this.batchTimeout = batchTimeout; 185 } 186 187 public String getStrategyRef() { 188 return strategyRef; 189 } 190 191 public void setStrategyRef(String strategyRef) { 192 this.strategyRef = strategyRef; 193 } 194 195 public CompletedPredicate getCompletePredicate() { 196 return completedPredicate; 197 } 198 199 public void setCompletePredicate(CompletedPredicate completedPredicate) { 200 this.completedPredicate = completedPredicate; 201 } 202 203 // Fluent API 204 //------------------------------------------------------------------------- 205 public AggregatorType batchSize(int batchSize) { 206 setBatchSize(batchSize); 207 return this; 208 } 209 210 public AggregatorType batchTimeout(long batchTimeout) { 211 setBatchTimeout(batchTimeout); 212 return this; 213 } 214 215 /** 216 * Sets the predicate used to determine if the aggregation is completed 217 * 218 * @return the clause used to create the predicate 219 */ 220 public ExpressionClause<AggregatorType> completedPredicate() { 221 checkNoCompletedPredicate(); 222 ExpressionClause<AggregatorType> clause = new ExpressionClause<AggregatorType>(this); 223 completedPredicate = new CompletedPredicate(clause); 224 return clause; 225 } 226 227 /** 228 * Sets the predicate used to determine if the aggregation is completed 229 */ 230 public AggregatorType completedPredicate(Predicate predicate) { 231 checkNoCompletedPredicate(); 232 completedPredicate = new CompletedPredicate(predicate); 233 return this; 234 } 235 236 protected void checkNoCompletedPredicate() { 237 if (completedPredicate != null) { 238 throw new IllegalArgumentException("There already is a completedPredicate defined for this aggregator: " + this); 239 } 240 } 241 }