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.LoggingLevel;
027import org.apache.camel.NoSuchEndpointException;
028import org.apache.camel.builder.xml.XPathBuilder;
029import org.apache.camel.model.ModelCamelContext;
030import org.apache.camel.model.language.ExchangePropertyExpression;
031import org.apache.camel.model.language.HeaderExpression;
032import org.apache.camel.model.language.JsonPathExpression;
033import org.apache.camel.util.ObjectHelper;
034import org.slf4j.Logger;
035import org.slf4j.LoggerFactory;
036
037/**
038 * Base class for implementation inheritance for different clauses in the <a
039 * href="http://camel.apache.org/dsl.html">Java DSL</a>
040 *
041 * @version
042 */
043public abstract class BuilderSupport {
044    private ModelCamelContext context;
045    private ErrorHandlerBuilder errorHandlerBuilder;
046
047    protected BuilderSupport() {
048    }
049
050    protected BuilderSupport(CamelContext context) {
051        this.context = context != null ? context.adapt(ModelCamelContext.class) : null;
052    }
053
054    // Builder methods
055    // -------------------------------------------------------------------------
056
057    /**
058     * Returns a value builder for the given header
059     */
060    public ValueBuilder header(String name) {
061        Expression exp = new HeaderExpression(name);
062        return new ValueBuilder(exp);
063    }
064
065    /**
066     *
067     * Returns a value builder for the given exchange property
068     * @deprecated use {@link #exchangeProperty(String)} instead
069     */
070    @Deprecated
071    public ValueBuilder property(String name) {
072        Expression exp = new ExchangePropertyExpression(name);
073        return new ValueBuilder(exp);
074    }
075
076    /**
077     * Returns a value builder for the given exchange property
078     */
079    public ValueBuilder exchangeProperty(String name) {
080        Expression exp = new ExchangePropertyExpression(name);
081        return new ValueBuilder(exp);
082    }
083
084    /**
085     * Returns a predicate and value builder for the inbound body on an exchange
086     */
087    public ValueBuilder body() {
088        return Builder.body();
089    }
090
091    /**
092     * Returns a predicate and value builder for the inbound message body as a
093     * specific type
094     *
095     * @deprecated use {@link #bodyAs(Class)}
096     */
097    @Deprecated
098    public <T> ValueBuilder body(Class<T> type) {
099        return bodyAs(type);
100    }
101
102    /**
103     * Returns a predicate and value builder for the inbound message body as a
104     * specific type
105     */
106    public <T> ValueBuilder bodyAs(Class<T> type) {
107        return Builder.bodyAs(type);
108    }
109
110    /**
111     * Returns a predicate and value builder for the outbound body on an
112     * exchange
113     *
114     * @deprecated use {@link #body()}
115     */
116    @Deprecated
117    public ValueBuilder outBody() {
118        return Builder.outBody();
119    }
120
121    /**
122     * Returns a predicate and value builder for the outbound message body as a
123     * specific type
124     *
125     * @deprecated use {@link #bodyAs(Class)}
126     */
127    @Deprecated
128    public <T> ValueBuilder outBody(Class<T> type) {
129        return Builder.outBodyAs(type);
130    }
131
132    /**
133     * Returns a predicate and value builder for the fault body on an
134     * exchange
135     */
136    public ValueBuilder faultBody() {
137        return Builder.faultBody();
138    }
139
140    /**
141     * Returns a predicate and value builder for the fault message body as a
142     * specific type
143     *
144     * @deprecated use {@link #bodyAs(Class)}
145     */
146    @Deprecated
147    public <T> ValueBuilder faultBodyAs(Class<T> type) {
148        return Builder.faultBodyAs(type);
149    }
150
151    /**
152     * Returns a value builder for the given system property
153     */
154    public ValueBuilder systemProperty(String name) {
155        return Builder.systemProperty(name);
156    }
157
158    /**
159     * Returns a value builder for the given system property
160     */
161    public ValueBuilder systemProperty(String name, String defaultValue) {
162        return Builder.systemProperty(name, defaultValue);
163    }
164
165    /**
166     * Returns a constant expression value builder
167     */
168    public ValueBuilder constant(Object value) {
169        return Builder.constant(value);
170    }
171
172    /**
173     * Returns a JSonPath expression value builder
174     */
175    public ValueBuilder jsonpath(String value) {
176        JsonPathExpression exp = new JsonPathExpression(value);
177        return new ValueBuilder(exp);
178    }
179
180    /**
181     * Returns a JSonPath expression value builder
182     *
183     * @param value      The JSonPath expression
184     * @param resultType The result type that the JSonPath expression will return.
185     */
186    public ValueBuilder jsonpath(String value, Class<?> resultType) {
187        JsonPathExpression exp = new JsonPathExpression(value);
188        exp.setResultType(resultType);
189        return new ValueBuilder(exp);
190    }
191
192    /**
193     * Returns a language expression value builder
194     */
195    public ValueBuilder language(String language, String expression) {
196        return Builder.language(language, expression);
197    }
198
199    /**
200     * Returns a simple expression value builder
201     */
202    public SimpleBuilder simple(String value) {
203        return SimpleBuilder.simple(value);
204    }
205
206    /**
207     * Returns a simple expression value builder
208     */
209    public SimpleBuilder simple(String value, Class<?> resultType) {
210        return SimpleBuilder.simple(value, resultType);
211    }
212
213    /**
214     * Returns a simple expression value builder, using String.format style
215     */
216    public SimpleBuilder simpleF(String format, Object...values) {
217        return SimpleBuilder.simpleF(format, values);
218    }
219
220    /**
221     * Returns a simple expression value builder, using String.format style
222     */
223    public SimpleBuilder simpleF(String format, Class<?> resultType, Object...values) {
224        return SimpleBuilder.simpleF(format, resultType, values);
225    }
226
227    /**
228     * Returns a xpath expression value builder
229     *
230     * @param value the XPath expression
231     * @return the builder
232     */
233    public XPathBuilder xpath(String value) {
234        return xpath(value, null);
235    }
236
237    /**
238     * Returns a xpath expression value builder
239     *
240     * @param value      the XPath expression
241     * @param resultType the result type that the XPath expression will return.
242     * @return the builder
243     */
244    public XPathBuilder xpath(String value, Class<?> resultType) {
245        // the value may contain property placeholders as it may be used directly from Java DSL
246        try {
247            value = getContext().resolvePropertyPlaceholders(value);
248        } catch (Exception e) {
249            throw ObjectHelper.wrapRuntimeCamelException(e);
250        }
251        return XPathBuilder.xpath(value, resultType);
252    }
253
254    /**
255     * Returns a <a href="http://camel.apache.org/bean-language.html">method call expression</a>
256     * value builder
257     * <p/>
258     * This method accepts dual parameters. Either an bean instance or a reference to a bean (String).
259     *
260     * @param beanOrBeanRef  either an instanceof a bean or a reference to bean to lookup in the Registry
261     * @return the builder
262     * @deprecated use {@link #method(Object)} instead
263     */
264    @Deprecated
265    public ValueBuilder bean(Object beanOrBeanRef) {
266        return bean(beanOrBeanRef, null);
267    }
268
269    /**
270     * Returns a <a href="http://camel.apache.org/bean-language.html">method call expression</a>
271     * value builder
272     * <p/>
273     * This method accepts dual parameters. Either an bean instance or a reference to a bean (String).
274     *
275     * @param beanOrBeanRef  either an instanceof a bean or a reference to bean to lookup in the Registry
276     * @param method   name of method to invoke
277     * @return the builder
278     * @deprecated use {@link #method(Object, String)} instead
279     */
280    @Deprecated
281    public ValueBuilder bean(Object beanOrBeanRef, String method) {
282        return Builder.bean(beanOrBeanRef, method);
283    }
284
285    /**
286     * Returns a <a href="http://camel.apache.org/bean-language.html">method call expression</a>
287     * value builder
288     *
289     * @param beanType the Class of the bean which we want to invoke
290     * @return the builder
291     * @deprecated use {@link #method(Class)} instead
292     */
293    @Deprecated
294    public ValueBuilder bean(Class<?> beanType) {
295        return Builder.bean(beanType);
296    }
297
298    /**
299     * Returns a <a href="http://camel.apache.org/bean-language.html">method call expression</a>
300     * value builder
301     *
302     * @param beanType the Class of the bean which we want to invoke
303     * @param method   name of method to invoke
304     * @return the builder
305     * @deprecated use {@link #method(Class, String)} instead
306     */
307    @Deprecated
308    public ValueBuilder bean(Class<?> beanType, String method) {
309        return Builder.bean(beanType, method);
310    }
311
312    /**
313     * Returns a <a href="http://camel.apache.org/bean-language.html">method call expression</a>
314     * value builder
315     * <p/>
316     * This method accepts dual parameters. Either an bean instance or a reference to a bean (String).
317     *
318     * @param beanOrBeanRef  either an instanceof a bean or a reference to bean to lookup in the Registry
319     * @return the builder
320     */
321    public ValueBuilder method(Object beanOrBeanRef) {
322        return method(beanOrBeanRef, null);
323    }
324
325    /**
326     * Returns a <a href="http://camel.apache.org/bean-language.html">method call expression</a>
327     * value builder
328     * <p/>
329     * This method accepts dual parameters. Either an bean instance or a reference to a bean (String).
330     *
331     * @param beanOrBeanRef  either an instanceof a bean or a reference to bean to lookup in the Registry
332     * @param method   name of method to invoke
333     * @return the builder
334     */
335    public ValueBuilder method(Object beanOrBeanRef, String method) {
336        return Builder.bean(beanOrBeanRef, method);
337    }
338
339    /**
340     * Returns a <a href="http://camel.apache.org/bean-language.html">method call expression</a>
341     * value builder
342     *
343     * @param beanType the Class of the bean which we want to invoke
344     * @return the builder
345     */
346    public ValueBuilder method(Class<?> beanType) {
347        return Builder.bean(beanType);
348    }
349
350    /**
351     * Returns a <a href="http://camel.apache.org/bean-language.html">method call expression</a>
352     * value builder
353     *
354     * @param beanType the Class of the bean which we want to invoke
355     * @param method   name of method to invoke
356     * @return the builder
357     */
358    public ValueBuilder method(Class<?> beanType, String method) {
359        return Builder.bean(beanType, method);
360    }
361
362    /**
363     * Returns an expression processing the exchange to the given endpoint uri
364     *
365     * @param uri endpoint uri to send the exchange to
366     * @return the builder
367     * @deprecated not in use, and not available in XML DSL
368     */
369    @Deprecated
370    public ValueBuilder sendTo(String uri) {
371        return Builder.sendTo(uri);
372    }
373
374    /**
375     * Returns an expression value builder that replaces all occurrences of the
376     * regular expression with the given replacement
377     */
378    public ValueBuilder regexReplaceAll(Expression content, String regex, String replacement) {
379        return Builder.regexReplaceAll(content, regex, replacement);
380    }
381
382    /**
383     * Returns an expression value builder that replaces all occurrences of the
384     * regular expression with the given replacement
385     */
386    public ValueBuilder regexReplaceAll(Expression content, String regex, Expression replacement) {
387        return Builder.regexReplaceAll(content, regex, replacement);
388    }
389
390    /**
391     * Returns a exception expression value builder
392     */
393    public ValueBuilder exceptionMessage() {
394        return Builder.exceptionMessage();
395    }
396
397    /**
398     * Resolves the given URI to an endpoint
399     *
400     * @param uri  the uri to resolve
401     * @throws NoSuchEndpointException if the endpoint URI could not be resolved
402     * @return the endpoint
403     */
404    public Endpoint endpoint(String uri) throws NoSuchEndpointException {
405        ObjectHelper.notNull(uri, "uri");
406        Endpoint endpoint = getContext().getEndpoint(uri);
407        if (endpoint == null) {
408            throw new NoSuchEndpointException(uri);
409        }
410        return endpoint;
411    }
412
413    /**
414     * Resolves the given URI to an endpoint of the specified type
415     *
416     * @param uri  the uri to resolve
417     * @param type the excepted type of the endpoint
418     * @throws NoSuchEndpointException if the endpoint URI could not be resolved
419     * @return the endpoint
420     */
421    public <T extends Endpoint> T endpoint(String uri, Class<T> type) throws NoSuchEndpointException {
422        ObjectHelper.notNull(uri, "uri");
423        T endpoint = getContext().getEndpoint(uri, type);
424        if (endpoint == null) {
425            throw new NoSuchEndpointException(uri);
426        }
427        return endpoint;
428    }
429
430    /**
431     * Resolves the list of URIs into a list of {@link Endpoint} instances
432     *
433     * @param uris  list of endpoints to resolve
434     * @throws NoSuchEndpointException if an endpoint URI could not be resolved
435     * @return list of endpoints
436     */
437    public List<Endpoint> endpoints(String... uris) throws NoSuchEndpointException {
438        List<Endpoint> endpoints = new ArrayList<>();
439        for (String uri : uris) {
440            endpoints.add(endpoint(uri));
441        }
442        return endpoints;
443    }
444
445    /**
446     * Helper method to create a list of {@link Endpoint} instances
447     *
448     * @param endpoints  endpoints
449     * @return list of the given endpoints
450     */
451    public List<Endpoint> endpoints(Endpoint... endpoints) {
452        List<Endpoint> answer = new ArrayList<>();
453        answer.addAll(Arrays.asList(endpoints));
454        return answer;
455    }
456
457    /**
458     * Creates a default <a href="http://camel.apache.org/error-handler.html">error handler</a>.
459     *
460     * @return the builder
461     */
462    public DefaultErrorHandlerBuilder defaultErrorHandler() {
463        return new DefaultErrorHandlerBuilder();
464    }
465
466    /**
467     * Creates a disabled <a href="http://camel.apache.org/error-handler.html">error handler</a>
468     * for removing the default error handler
469     *
470     * @return the builder
471     */
472    public NoErrorHandlerBuilder noErrorHandler() {
473        return new NoErrorHandlerBuilder();
474    }
475
476    /**
477     * Creates an <a href="http://camel.apache.org/error-handler.html">error handler</a>
478     * which just logs errors
479     *
480     * @return the builder
481     * @deprecated use dead letter channel with a log endpoint
482     */
483    @Deprecated
484    public LoggingErrorHandlerBuilder loggingErrorHandler() {
485        return new LoggingErrorHandlerBuilder();
486    }
487
488    /**
489     * Creates an <a href="http://camel.apache.org/error-handler.html">error handler</a>
490     * which just logs errors
491     *
492     * @return the builder
493     * @deprecated use dead letter channel with a log endpoint
494     */
495    @Deprecated
496    public LoggingErrorHandlerBuilder loggingErrorHandler(String log) {
497        return loggingErrorHandler(LoggerFactory.getLogger(log));
498    }
499
500    /**
501     * Creates an <a href="http://camel.apache.org/error-handler.html">error handler</a>
502     * which just logs errors
503     *
504     * @return the builder
505     * @deprecated use dead letter channel with a log endpoint
506     */
507    @Deprecated
508    public LoggingErrorHandlerBuilder loggingErrorHandler(Logger log) {
509        return new LoggingErrorHandlerBuilder(log);
510    }
511
512    /**
513     * Creates an <a href="http://camel.apache.org/error-handler.html">error handler</a>
514     * which just logs errors
515     *
516     * @return the builder
517     * @deprecated use dead letter channel with a log endpoint
518     */
519    @Deprecated
520    public LoggingErrorHandlerBuilder loggingErrorHandler(Logger log, LoggingLevel level) {
521        return new LoggingErrorHandlerBuilder(log, level);
522    }
523
524    /**
525     * <a href="http://camel.apache.org/dead-letter-channel.html">Dead Letter Channel EIP:</a>
526     * is a error handler for handling messages that could not be delivered to it's intended destination.
527     *
528     * @param deadLetterUri  uri to the dead letter endpoint storing dead messages
529     * @return the builder
530     */
531    public DeadLetterChannelBuilder deadLetterChannel(String deadLetterUri) {
532        return deadLetterChannel(endpoint(deadLetterUri));
533    }
534
535    /**
536     * <a href="http://camel.apache.org/dead-letter-channel.html">Dead Letter Channel EIP:</a>
537     * is a error handler for handling messages that could not be delivered to it's intended destination.
538     *
539     * @param deadLetterEndpoint  dead letter endpoint storing dead messages
540     * @return the builder
541     */
542    public DeadLetterChannelBuilder deadLetterChannel(Endpoint deadLetterEndpoint) {
543        return new DeadLetterChannelBuilder(deadLetterEndpoint);
544    }
545
546    // Properties
547    // -------------------------------------------------------------------------
548
549    public ModelCamelContext getContext() {
550        return context;
551    }
552
553    public void setContext(CamelContext context) {
554        ObjectHelper.notNull(context, "CamelContext", this);
555        this.context = context.adapt(ModelCamelContext.class);
556    }
557
558    public void setContext(ModelCamelContext context) {
559        ObjectHelper.notNull(context, "CamelContext", this);
560        this.context = context;
561    }
562
563    public ErrorHandlerBuilder getErrorHandlerBuilder() {
564        if (errorHandlerBuilder == null) {
565            errorHandlerBuilder = createErrorHandlerBuilder();
566        }
567        return errorHandlerBuilder;
568    }
569
570    protected ErrorHandlerBuilder createErrorHandlerBuilder() {
571        return new DefaultErrorHandlerBuilder();
572    }
573
574    /**
575     * Sets the error handler to use with processors created by this builder
576     */
577    public void setErrorHandlerBuilder(ErrorHandlerBuilder errorHandlerBuilder) {
578        this.errorHandlerBuilder = errorHandlerBuilder;
579    }
580
581}