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 */
017package org.apache.camel.model;
018
019import java.util.function.Supplier;
020
021import javax.xml.bind.annotation.XmlAccessType;
022import javax.xml.bind.annotation.XmlAccessorType;
023import javax.xml.bind.annotation.XmlAttribute;
024import javax.xml.bind.annotation.XmlRootElement;
025import javax.xml.bind.annotation.XmlTransient;
026
027import org.apache.camel.AggregationStrategy;
028import org.apache.camel.model.language.ExpressionDefinition;
029import org.apache.camel.spi.Metadata;
030
031/**
032 * Enriches a message with data from a secondary resource
033 *
034 * @see org.apache.camel.processor.Enricher
035 */
036@Metadata(label = "eip,transformation")
037@XmlRootElement(name = "enrich")
038@XmlAccessorType(XmlAccessType.FIELD)
039public class EnrichDefinition extends ExpressionNode {
040    @XmlAttribute(name = "strategyRef")
041    private String aggregationStrategyRef;
042    @XmlAttribute(name = "strategyMethodName")
043    private String aggregationStrategyMethodName;
044    @XmlAttribute(name = "strategyMethodAllowNull")
045    private String aggregationStrategyMethodAllowNull;
046    @XmlAttribute
047    @Metadata(javaType = "java.lang.Boolean")
048    private String aggregateOnException;
049    @XmlTransient
050    private AggregationStrategy aggregationStrategy;
051    @XmlAttribute
052    @Metadata(javaType = "java.lang.Boolean")
053    private String shareUnitOfWork;
054    @XmlAttribute
055    @Metadata(javaType = "java.lang.Integer")
056    private String cacheSize;
057    @XmlAttribute
058    @Metadata(javaType = "java.lang.Boolean")
059    private String ignoreInvalidEndpoint;
060
061    public EnrichDefinition() {
062        this(null);
063    }
064
065    public EnrichDefinition(AggregationStrategy aggregationStrategy) {
066        this.aggregationStrategy = aggregationStrategy;
067    }
068
069    @Override
070    public String toString() {
071        return "Enrich[" + getExpression() + "]";
072    }
073
074    @Override
075    public String getShortName() {
076        return "enrich";
077    }
078
079    @Override
080    public String getLabel() {
081        return "enrich[" + getExpression() + "]";
082    }
083
084    // Fluent API
085    // -------------------------------------------------------------------------
086
087    /**
088     * Sets the AggregationStrategy to be used to merge the reply from the
089     * external service, into a single outgoing message. By default Camel will
090     * use the reply from the external service as outgoing message.
091     */
092    public EnrichDefinition aggregationStrategy(AggregationStrategy aggregationStrategy) {
093        setAggregationStrategy(aggregationStrategy);
094        return this;
095    }
096
097    /**
098     * Sets the AggregationStrategy to be used to merge the reply from the
099     * external service, into a single outgoing message. By default Camel will
100     * use the reply from the external service as outgoing message.
101     */
102    public EnrichDefinition aggregationStrategy(Supplier<AggregationStrategy> aggregationStrategy) {
103        setAggregationStrategy(aggregationStrategy.get());
104        return this;
105    }
106
107    /**
108     * Refers to an AggregationStrategy to be used to merge the reply from the
109     * external service, into a single outgoing message. By default Camel will
110     * use the reply from the external service as outgoing message.
111     */
112    public EnrichDefinition aggregationStrategyRef(String aggregationStrategyRef) {
113        setAggregationStrategyRef(aggregationStrategyRef);
114        return this;
115    }
116
117    /**
118     * This option can be used to explicit declare the method name to use, when
119     * using POJOs as the AggregationStrategy.
120     */
121    public EnrichDefinition aggregationStrategyMethodName(String aggregationStrategyMethodName) {
122        setAggregationStrategyMethodName(aggregationStrategyMethodName);
123        return this;
124    }
125
126    /**
127     * If this option is false then the aggregate method is not used if there
128     * was no data to enrich. If this option is true then null values is used as
129     * the oldExchange (when no data to enrich), when using POJOs as the
130     * AggregationStrategy.
131     */
132    public EnrichDefinition aggregationStrategyMethodAllowNull(boolean aggregationStrategyMethodAllowNull) {
133        setAggregationStrategyMethodAllowNull(Boolean.toString(aggregationStrategyMethodAllowNull));
134        return this;
135    }
136
137    /**
138     * If this option is false then the aggregate method is not used if there
139     * was an exception thrown while trying to retrieve the data to enrich from
140     * the resource. Setting this option to true allows end users to control
141     * what to do if there was an exception in the aggregate method. For example
142     * to suppress the exception or set a custom message body etc.
143     */
144    public EnrichDefinition aggregateOnException(boolean aggregateOnException) {
145        setAggregateOnException(Boolean.toString(aggregateOnException));
146        return this;
147    }
148
149    /**
150     * Shares the {@link org.apache.camel.spi.UnitOfWork} with the parent and
151     * the resource exchange. Enrich will by default not share unit of work
152     * between the parent exchange and the resource exchange. This means the
153     * resource exchange has its own individual unit of work.
154     */
155    public EnrichDefinition shareUnitOfWork() {
156        setShareUnitOfWork(Boolean.toString(true));
157        return this;
158    }
159
160    /**
161     * Sets the maximum size used by the
162     * {@link org.apache.camel.spi.ProducerCache} which is used to cache and
163     * reuse producer when uris are reused.
164     *
165     * Beware that when using dynamic endpoints then it affects how well the cache can be utilized.
166     * If each dynamic endpoint is unique then its best to turn of caching by setting this to -1, which
167     * allows Camel to not cache both the producers and endpoints; they are regarded as prototype scoped
168     * and will be stopped and discarded after use. This reduces memory usage as otherwise producers/endpoints
169     * are stored in memory in the caches.
170     *
171     * However if there are a high degree of dynamic endpoints that have been used before, then it can
172     * benefit to use the cache to reuse both producers and endpoints and therefore the cache size
173     * can be set accordingly or rely on the default size (1000).
174     *
175     * If there is a mix of unique and used before dynamic endpoints, then setting a reasonable cache size
176     * can help reduce memory usage to avoid storing too many non frequent used producers.
177     *
178     * @param cacheSize the cache size, use <tt>0</tt> for default cache size,
179     *            or <tt>-1</tt> to turn cache off.
180     * @return the builder
181     */
182    public EnrichDefinition cacheSize(int cacheSize) {
183        setCacheSize(Integer.toString(cacheSize));
184        return this;
185    }
186
187    /**
188     * Sets the maximum size used by the
189     * {@link org.apache.camel.spi.ProducerCache} which is used to cache and
190     * reuse producer when uris are reused.
191     *
192     * Beware that when using dynamic endpoints then it affects how well the cache can be utilized.
193     * If each dynamic endpoint is unique then its best to turn of caching by setting this to -1, which
194     * allows Camel to not cache both the producers and endpoints; they are regarded as prototype scoped
195     * and will be stopped and discarded after use. This reduces memory usage as otherwise producers/endpoints
196     * are stored in memory in the caches.
197     *
198     * However if there are a high degree of dynamic endpoints that have been used before, then it can
199     * benefit to use the cache to reuse both producers and endpoints and therefore the cache size
200     * can be set accordingly or rely on the default size (1000).
201     *
202     * If there is a mix of unique and used before dynamic endpoints, then setting a reasonable cache size
203     * can help reduce memory usage to avoid storing too many non frequent used producers.
204     *
205     * @param cacheSize the cache size, use <tt>0</tt> for default cache size,
206     *            or <tt>-1</tt> to turn cache off.
207     * @return the builder
208     */
209    public EnrichDefinition cacheSize(String cacheSize) {
210        setCacheSize(cacheSize);
211        return this;
212    }
213
214    /**
215     * Ignore the invalidate endpoint exception when try to create a producer
216     * with that endpoint
217     *
218     * @return the builder
219     */
220    public EnrichDefinition ignoreInvalidEndpoint() {
221        setIgnoreInvalidEndpoint(Boolean.toString(true));
222        return this;
223    }
224
225    // Properties
226    // -------------------------------------------------------------------------
227
228    /**
229     * Expression that computes the endpoint uri to use as the resource endpoint
230     * to enrich from
231     */
232    @Override
233    public void setExpression(ExpressionDefinition expression) {
234        // override to include javadoc what the expression is used for
235        super.setExpression(expression);
236    }
237
238    public String getAggregationStrategyRef() {
239        return aggregationStrategyRef;
240    }
241
242    public void setAggregationStrategyRef(String aggregationStrategyRef) {
243        this.aggregationStrategyRef = aggregationStrategyRef;
244    }
245
246    public String getAggregationStrategyMethodName() {
247        return aggregationStrategyMethodName;
248    }
249
250    public void setAggregationStrategyMethodName(String aggregationStrategyMethodName) {
251        this.aggregationStrategyMethodName = aggregationStrategyMethodName;
252    }
253
254    public String getAggregationStrategyMethodAllowNull() {
255        return aggregationStrategyMethodAllowNull;
256    }
257
258    public void setAggregationStrategyMethodAllowNull(String aggregationStrategyMethodAllowNull) {
259        this.aggregationStrategyMethodAllowNull = aggregationStrategyMethodAllowNull;
260    }
261
262    public AggregationStrategy getAggregationStrategy() {
263        return aggregationStrategy;
264    }
265
266    public void setAggregationStrategy(AggregationStrategy aggregationStrategy) {
267        this.aggregationStrategy = aggregationStrategy;
268    }
269
270    public String getAggregateOnException() {
271        return aggregateOnException;
272    }
273
274    public void setAggregateOnException(String aggregateOnException) {
275        this.aggregateOnException = aggregateOnException;
276    }
277
278    public String getShareUnitOfWork() {
279        return shareUnitOfWork;
280    }
281
282    public void setShareUnitOfWork(String shareUnitOfWork) {
283        this.shareUnitOfWork = shareUnitOfWork;
284    }
285
286    public String getCacheSize() {
287        return cacheSize;
288    }
289
290    public void setCacheSize(String cacheSize) {
291        this.cacheSize = cacheSize;
292    }
293
294    public String getIgnoreInvalidEndpoint() {
295        return ignoreInvalidEndpoint;
296    }
297
298    public void setIgnoreInvalidEndpoint(String ignoreInvalidEndpoint) {
299        this.ignoreInvalidEndpoint = ignoreInvalidEndpoint;
300    }
301}