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.Collections;
020import java.util.List;
021
022import javax.xml.bind.annotation.XmlAccessType;
023import javax.xml.bind.annotation.XmlAccessorType;
024import javax.xml.bind.annotation.XmlAttribute;
025import javax.xml.bind.annotation.XmlRootElement;
026
027import org.apache.camel.Expression;
028import org.apache.camel.model.language.ExpressionDefinition;
029import org.apache.camel.spi.Metadata;
030
031/**
032 * Routes messages based on dynamic rules
033 */
034@Metadata(label = "eip,endpoint,routing")
035@XmlRootElement(name = "dynamicRouter")
036@XmlAccessorType(XmlAccessType.FIELD)
037public class DynamicRouterDefinition<Type extends ProcessorDefinition<Type>> extends ExpressionNode {
038
039    public static final String DEFAULT_DELIMITER = ",";
040
041    @XmlAttribute
042    @Metadata(defaultValue = ",")
043    private String uriDelimiter;
044    @XmlAttribute
045    private String ignoreInvalidEndpoints;
046    @XmlAttribute
047    @Metadata(javaType = "java.lang.Integer")
048    private String cacheSize;
049
050    public DynamicRouterDefinition() {
051    }
052
053    public DynamicRouterDefinition(Expression expression) {
054        super(expression);
055    }
056
057    @Override
058    public String toString() {
059        return "DynamicRouter[" + getExpression() + "]";
060    }
061
062    @Override
063    public String getShortName() {
064        return "dynamicRouter";
065    }
066
067    @Override
068    public String getLabel() {
069        return "dynamicRouter[" + getExpression() + "]";
070    }
071
072    @Override
073    public List<ProcessorDefinition<?>> getOutputs() {
074        return Collections.emptyList();
075    }
076
077    /**
078     * Expression to call that returns the endpoint(s) to route to in the
079     * dynamic routing.
080     * <p/>
081     * <b>Important:</b> The expression will be called in a while loop fashion,
082     * until the expression returns <tt>null</tt> which means the dynamic router
083     * is finished.
084     */
085    @Override
086    public void setExpression(ExpressionDefinition expression) {
087        // override to include javadoc what the expression is used for
088        super.setExpression(expression);
089    }
090
091    public void setUriDelimiter(String uriDelimiter) {
092        this.uriDelimiter = uriDelimiter;
093    }
094
095    public String getUriDelimiter() {
096        return uriDelimiter;
097    }
098
099    public void setIgnoreInvalidEndpoints(String ignoreInvalidEndpoints) {
100        this.ignoreInvalidEndpoints = ignoreInvalidEndpoints;
101    }
102
103    public String getIgnoreInvalidEndpoints() {
104        return ignoreInvalidEndpoints;
105    }
106
107    // Fluent API
108    // -------------------------------------------------------------------------
109
110    public String getCacheSize() {
111        return cacheSize;
112    }
113
114    public void setCacheSize(String cacheSize) {
115        this.cacheSize = cacheSize;
116    }
117
118    @Override
119    @SuppressWarnings("unchecked")
120    public Type end() {
121        // allow end() to return to previous type so you can continue in the DSL
122        return (Type)super.end();
123    }
124
125    /**
126     * Ignore the invalidate endpoint exception when try to create a producer
127     * with that endpoint
128     *
129     * @return the builder
130     */
131    public DynamicRouterDefinition<Type> ignoreInvalidEndpoints() {
132        setIgnoreInvalidEndpoints(Boolean.toString(true));
133        return this;
134    }
135
136    /**
137     * Sets the uri delimiter to use
138     *
139     * @param uriDelimiter the delimiter
140     * @return the builder
141     */
142    public DynamicRouterDefinition<Type> uriDelimiter(String uriDelimiter) {
143        setUriDelimiter(uriDelimiter);
144        return this;
145    }
146
147    /**
148     * Sets the maximum size used by the
149     * {@link org.apache.camel.spi.ProducerCache} which is used to cache and
150     * reuse producers when using this dynamic router, when uris are reused.
151     *
152     * Beware that when using dynamic endpoints then it affects how well the cache can be utilized.
153     * If each dynamic endpoint is unique then its best to turn of caching by setting this to -1, which
154     * allows Camel to not cache both the producers and endpoints; they are regarded as prototype scoped
155     * and will be stopped and discarded after use. This reduces memory usage as otherwise producers/endpoints
156     * are stored in memory in the caches.
157     *
158     * However if there are a high degree of dynamic endpoints that have been used before, then it can
159     * benefit to use the cache to reuse both producers and endpoints and therefore the cache size
160     * can be set accordingly or rely on the default size (1000).
161     *
162     * If there is a mix of unique and used before dynamic endpoints, then setting a reasonable cache size
163     * can help reduce memory usage to avoid storing too many non frequent used producers.
164     *
165     * @param cacheSize the cache size, use <tt>0</tt> for default cache size,
166     *            or <tt>-1</tt> to turn cache off.
167     * @return the builder
168     */
169    public DynamicRouterDefinition<Type> cacheSize(int cacheSize) {
170        setCacheSize(Integer.toString(cacheSize));
171        return this;
172    }
173
174    /**
175     * Sets the maximum size used by the
176     * {@link org.apache.camel.spi.ProducerCache} which is used to cache and
177     * reuse producers when using this dynamic router, when uris are reused.
178     *
179     * Beware that when using dynamic endpoints then it affects how well the cache can be utilized.
180     * If each dynamic endpoint is unique then its best to turn of caching by setting this to -1, which
181     * allows Camel to not cache both the producers and endpoints; they are regarded as prototype scoped
182     * and will be stopped and discarded after use. This reduces memory usage as otherwise producers/endpoints
183     * are stored in memory in the caches.
184     *
185     * However if there are a high degree of dynamic endpoints that have been used before, then it can
186     * benefit to use the cache to reuse both producers and endpoints and therefore the cache size
187     * can be set accordingly or rely on the default size (1000).
188     *
189     * If there is a mix of unique and used before dynamic endpoints, then setting a reasonable cache size
190     * can help reduce memory usage to avoid storing too many non frequent used producers.
191     *
192     * @param cacheSize the cache size, use <tt>0</tt> for default cache size,
193     *            or <tt>-1</tt> to turn cache off.
194     * @return the builder
195     */
196    public DynamicRouterDefinition<Type> cacheSize(String cacheSize) {
197        setCacheSize(cacheSize);
198        return this;
199    }
200
201}