/** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.camel.groovy.extend; import java.lang.reflect.Method; import groovy.lang.Closure; import org.apache.camel.Exchange; import org.apache.camel.Expression; import org.apache.camel.Predicate; import org.apache.camel.Processor; import org.apache.camel.builder.DataFormatClause; import org.apache.camel.builder.ExpressionClause; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.groovy.dataformat.XmlParserDataFormat; import org.apache.camel.groovy.dataformat.XmlSlurperDataFormat; import org.apache.camel.model.AggregateDefinition; import org.apache.camel.model.CatchDefinition; import org.apache.camel.model.ChoiceDefinition; import org.apache.camel.model.DataFormatDefinition; import org.apache.camel.model.DelayDefinition; import org.apache.camel.model.DynamicRouterDefinition; import org.apache.camel.model.FilterDefinition; import org.apache.camel.model.IdempotentConsumerDefinition; import org.apache.camel.model.InterceptDefinition; import org.apache.camel.model.InterceptSendToEndpointDefinition; import org.apache.camel.model.LoopDefinition; import org.apache.camel.model.MulticastDefinition; import org.apache.camel.model.OnCompletionDefinition; import org.apache.camel.model.OnExceptionDefinition; import org.apache.camel.model.ProcessorDefinition; import org.apache.camel.model.RecipientListDefinition; import org.apache.camel.model.ResequenceDefinition; import org.apache.camel.model.RoutingSlipDefinition; import org.apache.camel.model.SplitDefinition; import org.apache.camel.model.ThrottleDefinition; import org.apache.camel.model.TryDefinition; import org.apache.camel.model.WireTapDefinition; import org.apache.camel.processor.aggregate.AggregationStrategy; import org.apache.camel.spi.IdempotentRepository; import org.apache.camel.support.ExpressionSupport; /** * Extension class containing static methods that mainly allow to use Closures * instead of Predicates, Expressions, Processors, or AggregationStrategies */ public final class CamelGroovyMethods { private CamelGroovyMethods() { // Utility Class } // Extension Methods that use Closures to encapsulate logic public static ProcessorDefinition<?> process(ProcessorDefinition<?> self, Closure<?> processorLogic) { return self.process(toProcessor(processorLogic)); } public WireTapDefinition<?> newExchange(WireTapDefinition<?> self, Closure<?> processorLogic) { return self.newExchange(toProcessor(processorLogic)); } public static OnExceptionDefinition onRedelivery(OnExceptionDefinition self, Closure<Exchange> processorLogic) { return self.onRedelivery(toProcessor(processorLogic)); } public static ProcessorDefinition<?> enrich(ProcessorDefinition<?> self, String resourceUri, Closure<Exchange> aggregationLogic) { return self.enrich(resourceUri, toAggregationStrategy(aggregationLogic)); } public static ProcessorDefinition<?> pollEnrich(ProcessorDefinition<?> self, String resourceUri, Closure<Exchange> aggregationLogic) { return self.pollEnrich(resourceUri, toAggregationStrategy(aggregationLogic)); } public static ProcessorDefinition<?> pollEnrich(ProcessorDefinition<?> self, String resourceUri, long timeout, Closure<Exchange> aggregationLogic) { return self.pollEnrich(resourceUri, timeout, toAggregationStrategy(aggregationLogic)); } public static MulticastDefinition aggregationStrategy(MulticastDefinition self, Closure<Exchange> aggregationLogic) { return self.aggregationStrategy(toAggregationStrategy(aggregationLogic)); } public static RecipientListDefinition<?> aggregationStrategy(RecipientListDefinition<?> self, Closure<Exchange> aggregationLogic) { return self.aggregationStrategy(toAggregationStrategy(aggregationLogic)); } public static SplitDefinition aggregationStrategy(SplitDefinition self, Closure<Exchange> aggregationLogic) { return self.aggregationStrategy(toAggregationStrategy(aggregationLogic)); } public static AggregateDefinition aggregationStrategy(AggregateDefinition self, Closure<Exchange> aggregationLogic) { return self.aggregationStrategy(toAggregationStrategy(aggregationLogic)); } public static MulticastDefinition onPrepare(MulticastDefinition self, Closure<Exchange> processorLogic) { return self.onPrepare(toProcessor(processorLogic)); } public static RecipientListDefinition<?> onPrepare(RecipientListDefinition<?> self, Closure<Exchange> processorLogic) { return self.onPrepare(toProcessor(processorLogic)); } public static SplitDefinition onPrepare(SplitDefinition self, Closure<Exchange> processorLogic) { return self.onPrepare(toProcessor(processorLogic)); } public static WireTapDefinition<?> onPrepare(WireTapDefinition<?> self, Closure<Exchange> processorLogic) { return self.onPrepare(toProcessor(processorLogic)); } // Extension Methods that use Closures as expressions public static ProcessorDefinition<?> script(ProcessorDefinition<?> self, Closure<?> expression) { return self.script(toExpression(expression)); } public static ProcessorDefinition<?> transform(ProcessorDefinition<?> self, Closure<?> expression) { return self.transform(toExpression(expression)); } public static ProcessorDefinition<?> setProperty(ProcessorDefinition<?> self, String name, Closure<?> expression) { return self.setProperty(name, toExpression(expression)); } public static ProcessorDefinition<?> setHeader(ProcessorDefinition<?> self, String name, Closure<?> expression) { return self.setHeader(name, toExpression(expression)); } public static ProcessorDefinition<?> setBody(ProcessorDefinition<?> self, Closure<?> expression) { return self.setBody(toExpression(expression)); } public static ProcessorDefinition<?> setFaultBody(ProcessorDefinition<?> self, Closure<?> expression) { return self.setFaultBody(toExpression(expression)); } public static ProcessorDefinition<?> sort(ProcessorDefinition<?> self, Closure<?> expression) { return self.sort(toExpression(expression)); } public static IdempotentConsumerDefinition idempotentConsumer(ProcessorDefinition<?> self, Closure<?> expression) { return self.idempotentConsumer(toExpression(expression)); } public static IdempotentConsumerDefinition idempotentConsumer(ProcessorDefinition<?> self, IdempotentRepository<?> rep, Closure<?> expression) { return self.idempotentConsumer(toExpression(expression), rep); } public static RecipientListDefinition<?> recipientList(ProcessorDefinition<?> self, Closure<?> recipients) { return self.recipientList(toExpression(recipients)); } public static RecipientListDefinition<?> recipientList(ProcessorDefinition<?> self, String delimiter, Closure<?> recipients) { return self.recipientList(toExpression(recipients), delimiter); } public static RoutingSlipDefinition<?> routingSlip(ProcessorDefinition<?> self, Closure<?> recipients) { return self.routingSlip(toExpression(recipients)); } public static RoutingSlipDefinition<?> routingSlip(ProcessorDefinition<?> self, String delimiter, Closure<?> recipients) { return self.routingSlip(toExpression(recipients), delimiter); } public static DynamicRouterDefinition<?> dynamicRouter(ProcessorDefinition<?> self, Closure<?> expression) { return self.dynamicRouter(toExpression(expression)); } public static SplitDefinition split(ProcessorDefinition<?> self, Closure<?> expression) { return self.split(toExpression(expression)); } public static ResequenceDefinition resequence(ProcessorDefinition<?> self, Closure<?> expression) { return self.resequence(toExpression(expression)); } public static AggregateDefinition aggregate(ProcessorDefinition<?> self, Closure<?> correlationExpression) { return self.aggregate(toExpression(correlationExpression)); } public static AggregateDefinition completionSize(AggregateDefinition self, Closure<?> expression) { return self.completionSize(toExpression(expression)); } public static AggregateDefinition completionTimeout(AggregateDefinition self, Closure<?> expression) { return self.completionTimeout(toExpression(expression)); } public static DelayDefinition delay(ProcessorDefinition<?> self, Closure<?> expression) { return self.delay(toExpression(expression)); } public static ThrottleDefinition throttle(ProcessorDefinition<?> self, Closure<?> expression) { return self.throttle(toExpression(expression)); } public static LoopDefinition loop(ProcessorDefinition<?> self, Closure<?> expression) { return self.loop(toExpression(expression)); } public static WireTapDefinition<?> newExchangeBody(WireTapDefinition<?> self, Closure<?> expression) { return self.newExchangeBody(toExpression(expression)); } public static WireTapDefinition<?> newExchangeHeader(WireTapDefinition<?> self, String header, Closure<?> expression) { return self.newExchangeHeader(header, toExpression(expression)); } // Extension Methods that use Closures as predicates public static FilterDefinition filter(ProcessorDefinition<?> self, Closure<?> predicate) { return self.filter(toExpression(predicate)); } public static ProcessorDefinition<?> validate(ProcessorDefinition<?> self, Closure<?> predicate) { return self.validate((Predicate) toExpression(predicate)); } public static ChoiceDefinition when(ChoiceDefinition self, Closure<?> predicate) { return self.when(toExpression(predicate)); } public static TryDefinition onWhen(TryDefinition self, Closure<?> predicate) { return self.onWhen(toExpression(predicate)); } public static OnExceptionDefinition onWhen(OnExceptionDefinition self, Closure<?> predicate) { return self.onWhen(toExpression(predicate)); } public static OnExceptionDefinition handled(OnExceptionDefinition self, Closure<?> predicate) { return self.handled((Predicate) toExpression(predicate)); } public static OnExceptionDefinition continued(OnExceptionDefinition self, Closure<?> predicate) { return self.continued((Predicate) toExpression(predicate)); } public static OnExceptionDefinition retryWhile(OnExceptionDefinition self, Closure<?> predicate) { return self.retryWhile(toExpression(predicate)); } public static OnCompletionDefinition onWhen(OnCompletionDefinition self, Closure<?> predicate) { return self.onWhen(toExpression(predicate)); } public static CatchDefinition onWhen(CatchDefinition self, Closure<?> predicate) { return self.onWhen(toExpression(predicate)); } public static AggregateDefinition completionPredicate(AggregateDefinition self, Closure<?> predicate) { return self.completionPredicate(toExpression(predicate)); } public static InterceptDefinition when(InterceptDefinition self, Closure<?> predicate) { return self.when(toExpression(predicate)); } public static InterceptSendToEndpointDefinition when(InterceptSendToEndpointDefinition self, Closure<?> predicate) { return self.when(toExpression(predicate)); } // Bridging generic attribution of expressions, predicates etc. public static AggregationStrategy aggregator(RouteBuilder self, Closure<Exchange> aggregationLogic) { return toAggregationStrategy(aggregationLogic); } public static Expression expression(RouteBuilder self, Closure<?> expression) { return toExpression(expression); } public static Predicate predicate(RouteBuilder self, Closure<?> predicate) { return toExpression(predicate); } public static Processor processor(RouteBuilder self, Closure<Exchange> processor) { return toProcessor(processor); } public static <T> T expression(ExpressionClause<T> self, Closure<?> expression) { return self.expression(toExpression(expression)); } // Private Helpers static ExpressionSupport toExpression(final Closure<?> closure) { return new ClosureExpression(closure); } static Processor toProcessor(final Closure<?> closure) { return new ClosureProcessor(closure); } static AggregationStrategy toAggregationStrategy(final Closure<Exchange> closure) { return new ClosureAggregationStrategy(closure); } // Groovy-specific data formats public static ProcessorDefinition<?> gnode(DataFormatClause<?> self, boolean namespaceAware) { return dataFormat(self, parser(namespaceAware)); } public static ProcessorDefinition<?> gnode(DataFormatClause<?> self) { return gnode(self, true); } public static ProcessorDefinition<?> gpath(DataFormatClause<?> self, boolean namespaceAware) { return dataFormat(self, slurper(namespaceAware)); } public static ProcessorDefinition<?> gpath(DataFormatClause<?> self) { return gpath(self, true); } private static DataFormatDefinition slurper(boolean namespaceAware) { return new DataFormatDefinition(new XmlSlurperDataFormat(namespaceAware)); } private static DataFormatDefinition parser(boolean namespaceAware) { return new DataFormatDefinition(new XmlParserDataFormat(namespaceAware)); } // DataFormatClause.dataFormat(DataFormatDefinition) is private... private static ProcessorDefinition<?> dataFormat(DataFormatClause<?> self, DataFormatDefinition format) { try { Method m = self.getClass().getDeclaredMethod("dataFormat", DataFormatDefinition.class); m.setAccessible(true); return (ProcessorDefinition<?>) m.invoke(self, format); } catch (Exception e) { throw new IllegalArgumentException("Unknown DataFormat operation", e); } } }