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.builder;
018
019import java.util.ArrayList;
020import java.util.Arrays;
021import java.util.List;
022
023import org.apache.camel.CamelContext;
024import org.apache.camel.Endpoint;
025import org.apache.camel.Expression;
026import org.apache.camel.NoSuchEndpointException;
027import org.apache.camel.RuntimeCamelException;
028import org.apache.camel.model.language.ExchangePropertyExpression;
029import org.apache.camel.model.language.HeaderExpression;
030import org.apache.camel.model.language.JsonPathExpression;
031import org.apache.camel.model.language.XPathExpression;
032import org.apache.camel.support.builder.Namespaces;
033import org.apache.camel.util.ObjectHelper;
034
035/**
036 * Base class for implementation inheritance for different clauses in the
037 * <a href="http://camel.apache.org/dsl.html">Java DSL</a>
038 */
039public abstract class BuilderSupport {
040    private CamelContext context;
041    private ErrorHandlerBuilder errorHandlerBuilder;
042
043    protected BuilderSupport() {
044    }
045
046    protected BuilderSupport(CamelContext context) {
047        this.context = context;
048    }
049
050    // Builder methods
051    // -------------------------------------------------------------------------
052
053    /**
054     * Returns a value builder for the given header
055     */
056    public ValueBuilder header(String name) {
057        Expression exp = new HeaderExpression(name);
058        return new ValueBuilder(exp);
059    }
060
061    /**
062     * Returns a value builder for the given exchange property
063     */
064    public ValueBuilder exchangeProperty(String name) {
065        Expression exp = new ExchangePropertyExpression(name);
066        return new ValueBuilder(exp);
067    }
068
069    /**
070     * Returns a predicate and value builder for the inbound body on an exchange
071     */
072    public ValueBuilder body() {
073        return Builder.body();
074    }
075
076    /**
077     * Returns a predicate and value builder for the inbound message body as a
078     * specific type
079     */
080    public <T> ValueBuilder bodyAs(Class<T> type) {
081        return Builder.bodyAs(type);
082    }
083
084    /**
085     * Returns a value builder for the given system property
086     */
087    public ValueBuilder systemProperty(String name) {
088        return Builder.systemProperty(name);
089    }
090
091    /**
092     * Returns a value builder for the given system property
093     */
094    public ValueBuilder systemProperty(String name, String defaultValue) {
095        return Builder.systemProperty(name, defaultValue);
096    }
097
098    /**
099     * Returns a constant expression value builder
100     */
101    public ValueBuilder constant(Object value) {
102        return Builder.constant(value);
103    }
104
105    /**
106     * Returns a JSonPath expression value builder
107     */
108    public ValueBuilder jsonpath(String value) {
109        JsonPathExpression exp = new JsonPathExpression(value);
110        return new ValueBuilder(exp);
111    }
112
113    /**
114     * Returns a JSonPath expression value builder
115     *
116     * @param value The JSonPath expression
117     * @param resultType The result type that the JSonPath expression will
118     *            return.
119     */
120    public ValueBuilder jsonpath(String value, Class<?> resultType) {
121        JsonPathExpression exp = new JsonPathExpression(value);
122        exp.setResultType(resultType);
123        return new ValueBuilder(exp);
124    }
125
126    /**
127     * Returns a simple expression value builder
128     */
129    public SimpleBuilder simple(String value) {
130        return SimpleBuilder.simple(value);
131    }
132
133    /**
134     * Returns a simple expression value builder
135     */
136    public SimpleBuilder simple(String value, Class<?> resultType) {
137        return SimpleBuilder.simple(value, resultType);
138    }
139
140    /**
141     * Returns a simple expression value builder, using String.format style
142     */
143    public SimpleBuilder simpleF(String format, Object... values) {
144        return SimpleBuilder.simpleF(format, values);
145    }
146
147    /**
148     * Returns a simple expression value builder, using String.format style
149     */
150    public SimpleBuilder simpleF(String format, Class<?> resultType, Object... values) {
151        return SimpleBuilder.simpleF(format, resultType, values);
152    }
153
154    /**
155     * Returns a xpath expression value builder
156     *
157     * @param value the XPath expression
158     * @return the builder
159     */
160    public ValueBuilder xpath(String value) {
161        return xpath(value, null, null);
162    }
163
164    /**
165     * Returns a xpath expression value builder
166     *
167     * @param value the XPath expression
168     * @param resultType the result type that the XPath expression will return.
169     * @return the builder
170     */
171    public ValueBuilder xpath(String value, Class<?> resultType) {
172        return xpath(value, resultType, null);
173    }
174
175    /**
176     * Returns a xpath expression value builder
177     *
178     * @param value the XPath expression
179     * @param namespaces namespace mappings
180     * @return the builder
181     */
182    public ValueBuilder xpath(String value, Namespaces namespaces) {
183        return xpath(value, null, namespaces);
184    }
185
186    /**
187     * Returns a xpath expression value builder
188     *
189     * @param value the XPath expression
190     * @param resultType the result type that the XPath expression will return.
191     * @param namespaces namespace mappings
192     * @return the builder
193     */
194    public ValueBuilder xpath(String value, Class<?> resultType, Namespaces namespaces) {
195        // the value may contain property placeholders as it may be used
196        // directly from Java DSL
197        try {
198            value = getContext().resolvePropertyPlaceholders(value);
199        } catch (Exception e) {
200            throw RuntimeCamelException.wrapRuntimeCamelException(e);
201        }
202        XPathExpression exp = new XPathExpression(value);
203        exp.setResultType(resultType);
204        if (namespaces != null) {
205            exp.setNamespaces(namespaces.getNamespaces());
206        }
207        return new ValueBuilder(exp);
208    }
209
210    /**
211     * Returns a <a href="http://camel.apache.org/bean-language.html">method
212     * call expression</a> value builder
213     * <p/>
214     * This method accepts dual parameters. Either an bean instance or a
215     * reference to a bean (String).
216     *
217     * @param beanOrBeanRef either an instanceof a bean or a reference to bean
218     *            to lookup in the Registry
219     * @return the builder
220     */
221    public ValueBuilder method(Object beanOrBeanRef) {
222        return method(beanOrBeanRef, null);
223    }
224
225    /**
226     * Returns a <a href="http://camel.apache.org/bean-language.html">method
227     * call expression</a> value builder
228     * <p/>
229     * This method accepts dual parameters. Either an bean instance or a
230     * reference to a bean (String).
231     *
232     * @param beanOrBeanRef either an instanceof a bean or a reference to bean
233     *            to lookup in the Registry
234     * @param method name of method to invoke
235     * @return the builder
236     */
237    public ValueBuilder method(Object beanOrBeanRef, String method) {
238        return Builder.bean(beanOrBeanRef, method);
239    }
240
241    /**
242     * Returns a <a href="http://camel.apache.org/bean-language.html">method
243     * call expression</a> value builder
244     *
245     * @param beanType the Class of the bean which we want to invoke
246     * @return the builder
247     */
248    public ValueBuilder method(Class<?> beanType) {
249        return Builder.bean(beanType);
250    }
251
252    /**
253     * Returns a <a href="http://camel.apache.org/bean-language.html">method
254     * call expression</a> value builder
255     *
256     * @param beanType the Class of the bean which we want to invoke
257     * @param method name of method to invoke
258     * @return the builder
259     */
260    public ValueBuilder method(Class<?> beanType, String method) {
261        return Builder.bean(beanType, method);
262    }
263
264    /**
265     * Returns an expression value builder that replaces all occurrences of the
266     * regular expression with the given replacement
267     */
268    public ValueBuilder regexReplaceAll(Expression content, String regex, String replacement) {
269        return Builder.regexReplaceAll(content, regex, replacement);
270    }
271
272    /**
273     * Returns an expression value builder that replaces all occurrences of the
274     * regular expression with the given replacement
275     */
276    public ValueBuilder regexReplaceAll(Expression content, String regex, Expression replacement) {
277        return Builder.regexReplaceAll(content, regex, replacement);
278    }
279
280    /**
281     * Returns a exception expression value builder
282     */
283    public ValueBuilder exceptionMessage() {
284        return Builder.exceptionMessage();
285    }
286
287    /**
288     * Resolves the given URI to an endpoint
289     *
290     * @param uri the uri to resolve
291     * @throws NoSuchEndpointException if the endpoint URI could not be resolved
292     * @return the endpoint
293     */
294    public Endpoint endpoint(String uri) throws NoSuchEndpointException {
295        ObjectHelper.notNull(uri, "uri");
296        Endpoint endpoint = getContext().getEndpoint(uri);
297        if (endpoint == null) {
298            throw new NoSuchEndpointException(uri);
299        }
300        return endpoint;
301    }
302
303    /**
304     * Resolves the given URI to an endpoint of the specified type
305     *
306     * @param uri the uri to resolve
307     * @param type the excepted type of the endpoint
308     * @throws NoSuchEndpointException if the endpoint URI could not be resolved
309     * @return the endpoint
310     */
311    public <T extends Endpoint> T endpoint(String uri, Class<T> type) throws NoSuchEndpointException {
312        ObjectHelper.notNull(uri, "uri");
313        T endpoint = getContext().getEndpoint(uri, type);
314        if (endpoint == null) {
315            throw new NoSuchEndpointException(uri);
316        }
317        return endpoint;
318    }
319
320    /**
321     * Resolves the list of URIs into a list of {@link Endpoint} instances
322     *
323     * @param uris list of endpoints to resolve
324     * @throws NoSuchEndpointException if an endpoint URI could not be resolved
325     * @return list of endpoints
326     */
327    public List<Endpoint> endpoints(String... uris) throws NoSuchEndpointException {
328        List<Endpoint> endpoints = new ArrayList<>();
329        for (String uri : uris) {
330            endpoints.add(endpoint(uri));
331        }
332        return endpoints;
333    }
334
335    /**
336     * Helper method to create a list of {@link Endpoint} instances
337     *
338     * @param endpoints endpoints
339     * @return list of the given endpoints
340     */
341    public List<Endpoint> endpoints(Endpoint... endpoints) {
342        List<Endpoint> answer = new ArrayList<>();
343        answer.addAll(Arrays.asList(endpoints));
344        return answer;
345    }
346
347    /**
348     * Creates a default
349     * <a href="http://camel.apache.org/error-handler.html">error handler</a>.
350     *
351     * @return the builder
352     */
353    public DefaultErrorHandlerBuilder defaultErrorHandler() {
354        return new DefaultErrorHandlerBuilder();
355    }
356
357    /**
358     * Creates a disabled
359     * <a href="http://camel.apache.org/error-handler.html">error handler</a>
360     * for removing the default error handler
361     *
362     * @return the builder
363     */
364    public NoErrorHandlerBuilder noErrorHandler() {
365        return new NoErrorHandlerBuilder();
366    }
367
368    /**
369     * <a href="http://camel.apache.org/dead-letter-channel.html">Dead Letter
370     * Channel EIP:</a> is a error handler for handling messages that could not
371     * be delivered to it's intended destination.
372     *
373     * @param deadLetterUri uri to the dead letter endpoint storing dead
374     *            messages
375     * @return the builder
376     */
377    public DeadLetterChannelBuilder deadLetterChannel(String deadLetterUri) {
378        return deadLetterChannel(endpoint(deadLetterUri));
379    }
380
381    /**
382     * <a href="http://camel.apache.org/dead-letter-channel.html">Dead Letter
383     * Channel EIP:</a> is a error handler for handling messages that could not
384     * be delivered to it's intended destination.
385     *
386     * @param deadLetterEndpoint dead letter endpoint storing dead messages
387     * @return the builder
388     */
389    public DeadLetterChannelBuilder deadLetterChannel(Endpoint deadLetterEndpoint) {
390        return new DeadLetterChannelBuilder(deadLetterEndpoint);
391    }
392
393    // Properties
394    // -------------------------------------------------------------------------
395
396    public CamelContext getContext() {
397        return context;
398    }
399
400    public void setContext(CamelContext context) {
401        ObjectHelper.notNull(context, "CamelContext", this);
402        this.context = context;
403    }
404
405    public ErrorHandlerBuilder getErrorHandlerBuilder() {
406        if (errorHandlerBuilder == null) {
407            errorHandlerBuilder = createErrorHandlerBuilder();
408        }
409        return errorHandlerBuilder;
410    }
411
412    protected ErrorHandlerBuilder createErrorHandlerBuilder() {
413        return new DefaultErrorHandlerBuilder();
414    }
415
416    /**
417     * Sets the error handler to use with processors created by this builder
418     */
419    public void setErrorHandlerBuilder(ErrorHandlerBuilder errorHandlerBuilder) {
420        this.errorHandlerBuilder = errorHandlerBuilder;
421    }
422
423}