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