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.Map;
020
021import org.apache.camel.CamelContext;
022import org.apache.camel.Expression;
023import org.apache.camel.ExpressionFactory;
024import org.apache.camel.model.language.ConstantExpression;
025import org.apache.camel.model.language.ExchangePropertyExpression;
026import org.apache.camel.model.language.GroovyExpression;
027import org.apache.camel.model.language.HeaderExpression;
028import org.apache.camel.model.language.Hl7TerserExpression;
029import org.apache.camel.model.language.JsonPathExpression;
030import org.apache.camel.model.language.LanguageExpression;
031import org.apache.camel.model.language.MethodCallExpression;
032import org.apache.camel.model.language.MvelExpression;
033import org.apache.camel.model.language.OgnlExpression;
034import org.apache.camel.model.language.RefExpression;
035import org.apache.camel.model.language.SimpleExpression;
036import org.apache.camel.model.language.SpELExpression;
037import org.apache.camel.model.language.TokenizerExpression;
038import org.apache.camel.model.language.XMLTokenizerExpression;
039import org.apache.camel.model.language.XPathExpression;
040import org.apache.camel.model.language.XQueryExpression;
041import org.apache.camel.support.builder.Namespaces;
042
043/**
044 * A support class for building expression clauses.
045 */
046public class ExpressionClauseSupport<T> {
047
048    // Implementation detail: We must use the specific model.language.xxx
049    // classes to make the DSL use these specific types
050    // which ensures that the route model dumped as XML uses these types, eg
051    // <header> instead of <language name="header"> etc.
052
053    private T result;
054    private Expression expressionValue;
055    private ExpressionFactory expressionType;
056
057    public ExpressionClauseSupport(T result) {
058        this.result = result;
059    }
060
061    // Helper expressions
062    // -------------------------------------------------------------------------
063
064    /**
065     * Specify an {@link org.apache.camel.Expression} instance
066     */
067    public T expression(Expression expression) {
068        setExpressionValue(expression);
069        if (expression instanceof ExpressionFactory) {
070            setExpressionType((ExpressionFactory)expression);
071        }
072        return result;
073    }
074
075    /**
076     * Specify an {@link ExpressionFactory} instance
077     */
078    public T language(ExpressionFactory expression) {
079        setExpressionType(expression);
080        return result;
081    }
082
083    /**
084     * Specify the constant expression value. <b>Important:</b> this is a fixed
085     * constant value that is only set once during starting up the route, do not
086     * use this if you want dynamic values during routing.
087     */
088    public T constant(Object value) {
089        if (value instanceof String) {
090            return expression(new ConstantExpression((String)value));
091        } else {
092            return expression(ExpressionBuilder.constantExpression(value));
093        }
094    }
095
096    /**
097     * An expression of the exchange
098     */
099    public T exchange() {
100        return expression(ExpressionBuilder.exchangeExpression());
101    }
102
103    /**
104     * An expression of an inbound message
105     */
106    public T inMessage() {
107        return expression(ExpressionBuilder.inMessageExpression());
108    }
109
110    /**
111     * An expression of an inbound message body
112     */
113    public T body() {
114        // reuse simple as this allows the model to represent this as a known
115        // JAXB type
116        return expression(new SimpleExpression("${body}"));
117    }
118
119    /**
120     * An expression of an inbound message body converted to the expected type
121     */
122    public T body(Class<?> expectedType) {
123        return expression(ExpressionBuilder.bodyExpression(expectedType));
124    }
125
126    /**
127     * An expression of an inbound message header of the given name
128     */
129    public T header(String name) {
130        return expression(new HeaderExpression(name));
131    }
132
133    /**
134     * An expression of the inbound headers
135     */
136    public T headers() {
137        return expression(ExpressionBuilder.headersExpression());
138    }
139
140    /**
141     * An expression of the exchange pattern
142     */
143    public T exchangePattern() {
144        return expression(ExpressionBuilder.exchangePatternExpression());
145    }
146
147    /**
148     * An expression of an exchange property of the given name
149     */
150    public T exchangeProperty(String name) {
151        return expression(new ExchangePropertyExpression(name));
152    }
153
154    /**
155     * An expression of the exchange properties
156     */
157    public T exchangeProperties() {
158        return expression(ExpressionBuilder.exchangePropertiesExpression());
159    }
160
161    // Languages
162    // -------------------------------------------------------------------------
163
164    /**
165     * Evaluates an expression using the <a
166     * href="http://camel.apache.org/bean-language.html>bean language</a> which
167     * basically means the bean is invoked to determine the expression value.
168     *
169     * @param bean the name of the bean looked up the registry
170     * @return the builder to continue processing the DSL
171     */
172    public T method(String bean) {
173        return expression(new MethodCallExpression(bean));
174    }
175
176    /**
177     * Evaluates an expression using the <a
178     * href="http://camel.apache.org/bean-language.html>bean language</a> which
179     * basically means the bean is invoked to determine the expression value.
180     *
181     * @param instance the instance of the bean
182     * @return the builder to continue processing the DSL
183     */
184    public T method(Object instance) {
185        return expression(new MethodCallExpression(instance));
186    }
187
188    /**
189     * Evaluates an expression using the <a
190     * href="http://camel.apache.org/bean-language.html>bean language</a> which
191     * basically means the bean is invoked to determine the expression value.
192     *
193     * @param beanType the Class of the bean which we want to invoke
194     * @return the builder to continue processing the DSL
195     */
196    public T method(Class<?> beanType) {
197        return expression(new MethodCallExpression(beanType));
198    }
199
200    /**
201     * Evaluates an expression using the <a
202     * href="http://camel.apache.org/bean-language.html>bean language</a> which
203     * basically means the bean is invoked to determine the expression value.
204     *
205     * @param bean the name of the bean looked up the registry
206     * @param method the name of the method to invoke on the bean
207     * @return the builder to continue processing the DSL
208     */
209    public T method(String bean, String method) {
210        return expression(new MethodCallExpression(bean, method));
211    }
212
213    /**
214     * Evaluates an expression using the <a
215     * href="http://camel.apache.org/bean-language.html>bean language</a> which
216     * basically means the bean is invoked to determine the expression value.
217     *
218     * @param instance the instance of the bean
219     * @param method the name of the method to invoke on the bean
220     * @return the builder to continue processing the DSL
221     */
222    public T method(Object instance, String method) {
223        return expression(new MethodCallExpression(instance, method));
224    }
225
226    /**
227     * Evaluates an expression using the <a
228     * href="http://camel.apache.org/bean-language.html>bean language</a> which
229     * basically means the bean is invoked to determine the expression value.
230     *
231     * @param beanType the Class of the bean which we want to invoke
232     * @param method the name of the method to invoke on the bean
233     * @return the builder to continue processing the DSL
234     */
235    public T method(Class<?> beanType, String method) {
236        return expression(new MethodCallExpression(beanType, method));
237    }
238
239    /**
240     * Evaluates a <a href="http://camel.apache.org/groovy.html">Groovy
241     * expression</a>
242     *
243     * @param text the expression to be evaluated
244     * @return the builder to continue processing the DSL
245     */
246    public T groovy(String text) {
247        return expression(new GroovyExpression(text));
248    }
249
250    /**
251     * Evaluates a <a href="http://camel.apache.org/jsonpath.html">Json Path
252     * expression</a>
253     *
254     * @param text the expression to be evaluated
255     * @return the builder to continue processing the DSL
256     */
257    public T jsonpath(String text) {
258        return jsonpath(text, false);
259    }
260
261    /**
262     * Evaluates a <a href="http://camel.apache.org/jsonpath.html">Json Path
263     * expression</a>
264     *
265     * @param text the expression to be evaluated
266     * @param suppressExceptions whether to suppress exceptions such as
267     *            PathNotFoundException
268     * @return the builder to continue processing the DSL
269     */
270    public T jsonpath(String text, boolean suppressExceptions) {
271        JsonPathExpression expression = new JsonPathExpression(text);
272        expression.setSuppressExceptions(suppressExceptions);
273        return expression(expression);
274    }
275
276    /**
277     * Evaluates a <a href="http://camel.apache.org/jsonpath.html">Json Path
278     * expression</a>
279     *
280     * @param text the expression to be evaluated
281     * @param suppressExceptions whether to suppress exceptions such as
282     *            PathNotFoundException
283     * @param allowSimple whether to allow in inlined simple exceptions in the
284     *            json path expression
285     * @return the builder to continue processing the DSL
286     */
287    public T jsonpath(String text, boolean suppressExceptions, boolean allowSimple) {
288        JsonPathExpression expression = new JsonPathExpression(text);
289        expression.setSuppressExceptions(suppressExceptions);
290        expression.setAllowSimple(allowSimple);
291        return expression(expression);
292    }
293
294    /**
295     * Evaluates a <a href="http://camel.apache.org/jsonpath.html">Json Path
296     * expression</a>
297     *
298     * @param text the expression to be evaluated
299     * @param resultType the return type expected by the expression
300     * @return the builder to continue processing the DSL
301     */
302    public T jsonpath(String text, Class<?> resultType) {
303        JsonPathExpression expression = new JsonPathExpression(text);
304        expression.setResultType(resultType);
305        setExpressionType(expression);
306        return result;
307    }
308
309    /**
310     * Evaluates a <a href="http://camel.apache.org/jsonpath.html">Json Path
311     * expression</a>
312     *
313     * @param text the expression to be evaluated
314     * @param suppressExceptions whether to suppress exceptions such as
315     *            PathNotFoundException
316     * @param resultType the return type expected by the expression
317     * @return the builder to continue processing the DSL
318     */
319    public T jsonpath(String text, boolean suppressExceptions, Class<?> resultType) {
320        JsonPathExpression expression = new JsonPathExpression(text);
321        expression.setSuppressExceptions(suppressExceptions);
322        expression.setResultType(resultType);
323        setExpressionType(expression);
324        return result;
325    }
326
327    /**
328     * Evaluates a <a href="http://camel.apache.org/jsonpath.html">Json Path
329     * expression</a>
330     *
331     * @param text the expression to be evaluated
332     * @param suppressExceptions whether to suppress exceptions such as
333     *            PathNotFoundException
334     * @param allowSimple whether to allow in inlined simple exceptions in the
335     *            json path expression
336     * @param resultType the return type expected by the expression
337     * @return the builder to continue processing the DSL
338     */
339    public T jsonpath(String text, boolean suppressExceptions, boolean allowSimple, Class<?> resultType) {
340        JsonPathExpression expression = new JsonPathExpression(text);
341        expression.setSuppressExceptions(suppressExceptions);
342        expression.setAllowSimple(allowSimple);
343        expression.setResultType(resultType);
344        setExpressionType(expression);
345        return result;
346    }
347
348    /**
349     * Evaluates a <a href="http://camel.apache.org/jsonpath.html">Json Path
350     * expression</a>
351     *
352     * @param text the expression to be evaluated
353     * @param suppressExceptions whether to suppress exceptions such as
354     *            PathNotFoundException
355     * @param allowSimple whether to allow in inlined simple exceptions in the
356     *            json path expression
357     * @param resultType the return type expected by the expression
358     * @param headerName the name of the header to apply the expression to
359     * @return the builder to continue processing the DSL
360     */
361    public T jsonpath(String text, boolean suppressExceptions, boolean allowSimple, Class<?> resultType, String headerName) {
362        JsonPathExpression expression = new JsonPathExpression(text);
363        expression.setSuppressExceptions(suppressExceptions);
364        expression.setAllowSimple(allowSimple);
365        expression.setResultType(resultType);
366        expression.setHeaderName(headerName);
367        setExpressionType(expression);
368        return result;
369    }
370
371    /**
372     * Evaluates a <a href="http://camel.apache.org/jsonpath.html">Json Path
373     * expression</a> with writeAsString enabled.
374     *
375     * @param text the expression to be evaluated
376     * @return the builder to continue processing the DSL
377     */
378    public T jsonpathWriteAsString(String text) {
379        return jsonpathWriteAsString(text, false);
380    }
381
382    /**
383     * Evaluates a <a href="http://camel.apache.org/jsonpath.html">Json Path
384     * expression</a> with writeAsString enabled.
385     *
386     * @param text the expression to be evaluated
387     * @param suppressExceptions whether to suppress exceptions such as
388     *            PathNotFoundException
389     * @return the builder to continue processing the DSL
390     */
391    public T jsonpathWriteAsString(String text, boolean suppressExceptions) {
392        JsonPathExpression expression = new JsonPathExpression(text);
393        expression.setWriteAsString(true);
394        expression.setSuppressExceptions(suppressExceptions);
395        return expression(expression);
396    }
397
398    /**
399     * Evaluates a <a href="http://camel.apache.org/jsonpath.html">Json Path
400     * expression</a> with writeAsString enabled.
401     *
402     * @param text the expression to be evaluated
403     * @param suppressExceptions whether to suppress exceptions such as
404     *            PathNotFoundException
405     * @param allowSimple whether to allow in inlined simple exceptions in the
406     *            json path expression
407     * @return the builder to continue processing the DSL
408     */
409    public T jsonpathWriteAsString(String text, boolean suppressExceptions, boolean allowSimple) {
410        JsonPathExpression expression = new JsonPathExpression(text);
411        expression.setWriteAsString(true);
412        expression.setSuppressExceptions(suppressExceptions);
413        expression.setAllowSimple(allowSimple);
414        return expression(expression);
415    }
416
417    /**
418     * Evaluates a <a href="http://camel.apache.org/jsonpath.html">Json Path
419     * expression</a> with writeAsString enabled.
420     *
421     * @param text the expression to be evaluated
422     * @param suppressExceptions whether to suppress exceptions such as
423     *            PathNotFoundException
424     * @param allowSimple whether to allow in inlined simple exceptions in the
425     *            json path expression
426     * @param headerName the name of the header to apply the expression to
427     * @return the builder to continue processing the DSL
428     */
429    public T jsonpathWriteAsString(String text, boolean suppressExceptions, boolean allowSimple, String headerName) {
430        JsonPathExpression expression = new JsonPathExpression(text);
431        expression.setWriteAsString(true);
432        expression.setSuppressExceptions(suppressExceptions);
433        expression.setAllowSimple(allowSimple);
434        expression.setHeaderName(headerName);
435        return expression(expression);
436    }
437
438    /**
439     * Evaluates an <a href="http://camel.apache.org/ognl.html">OGNL
440     * expression</a>
441     *
442     * @param text the expression to be evaluated
443     * @return the builder to continue processing the DSL
444     */
445    public T ognl(String text) {
446        return expression(new OgnlExpression(text));
447    }
448
449    /**
450     * Evaluates a <a href="http://camel.apache.org/mvel.html">MVEL
451     * expression</a>
452     *
453     * @param text the expression to be evaluated
454     * @return the builder to continue processing the DSL
455     */
456    public T mvel(String text) {
457        return expression(new MvelExpression(text));
458    }
459
460    /**
461     * Evaluates a {@link Expression} by looking up existing {@link Expression}
462     * from the {@link org.apache.camel.spi.Registry}
463     *
464     * @param ref refers to the expression to be evaluated
465     * @return the builder to continue processing the DSL
466     */
467    public T ref(String ref) {
468        return expression(new RefExpression(ref));
469    }
470
471    /**
472     * Evaluates an <a href="http://camel.apache.org/spel.html">SpEL
473     * expression</a>
474     *
475     * @param text the expression to be evaluated
476     * @return the builder to continue processing the DSL
477     */
478    public T spel(String text) {
479        return expression(new SpELExpression(text));
480    }
481
482    /**
483     * Evaluates a <a href="http://camel.apache.org/simple.html">Simple
484     * expression</a>
485     *
486     * @param text the expression to be evaluated
487     * @return the builder to continue processing the DSL
488     */
489    public T simple(String text) {
490        return expression(new SimpleExpression(text));
491    }
492
493    /**
494     * Evaluates a <a href="http://camel.apache.org/simple.html">Simple
495     * expression</a>
496     *
497     * @param text the expression to be evaluated
498     * @param resultType the result type
499     * @return the builder to continue processing the DSL
500     */
501    public T simple(String text, Class<?> resultType) {
502        SimpleExpression expression = new SimpleExpression(text);
503        expression.setResultType(resultType);
504        setExpressionType(expression);
505        return result;
506    }
507
508    /**
509     * Evaluates an <a href="http://camel.apache.org/hl7.html">HL7 Terser
510     * expression</a>
511     *
512     * @param text the expression to be evaluated
513     * @return the builder to continue processing the DSL
514     */
515    public T hl7terser(String text) {
516        return expression(new Hl7TerserExpression(text));
517    }
518
519    /**
520     * Evaluates a token expression on the message body
521     *
522     * @param token the token
523     * @return the builder to continue processing the DSL
524     */
525    public T tokenize(String token) {
526        return tokenize(token, null, false);
527    }
528
529    /**
530     * Evaluates a token expression on the message body
531     *
532     * @param token the token
533     * @param group to group by the given number
534     * @return the builder to continue processing the DSL
535     */
536    public T tokenize(String token, int group) {
537        return tokenize(token, null, false, group);
538    }
539
540    /**
541     * Evaluates a token expression on the message body
542     *
543     * @param token the token
544     * @param group to group by the given number
545     * @param skipFirst whether to skip the very first element
546     * @return the builder to continue processing the DSL
547     */
548    public T tokenize(String token, int group, boolean skipFirst) {
549        return tokenize(token, null, false, group, skipFirst);
550    }
551
552    /**
553     * Evaluates a token expression on the message body
554     *
555     * @param token the token
556     * @param regex whether the token is a regular expression or not
557     * @return the builder to continue processing the DSL
558     */
559    public T tokenize(String token, boolean regex) {
560        return tokenize(token, null, regex);
561    }
562
563    /**
564     * Evaluates a token expression on the message body
565     *
566     * @param token the token
567     * @param regex whether the token is a regular expression or not
568     * @param group to group by the given number
569     * @return the builder to continue processing the DSL
570     */
571    public T tokenize(String token, boolean regex, int group) {
572        return tokenize(token, null, regex, group);
573    }
574
575    /**
576     * Evaluates a token expression on the given header
577     *
578     * @param token the token
579     * @param headerName name of header to tokenize
580     * @return the builder to continue processing the DSL
581     */
582    public T tokenize(String token, String headerName) {
583        return tokenize(token, headerName, false);
584    }
585
586    /**
587     * Evaluates a token expression on the given header
588     *
589     * @param token the token
590     * @param headerName name of header to tokenize
591     * @param regex whether the token is a regular expression or not
592     * @return the builder to continue processing the DSL
593     */
594    public T tokenize(String token, String headerName, boolean regex) {
595        TokenizerExpression expression = new TokenizerExpression();
596        expression.setToken(token);
597        expression.setHeaderName(headerName);
598        expression.setRegex(regex);
599        setExpressionType(expression);
600        return result;
601    }
602
603    /**
604     * Evaluates a token expression on the given header
605     *
606     * @param token the token
607     * @param headerName name of header to tokenize
608     * @param regex whether the token is a regular expression or not
609     * @param group to group by number of parts
610     * @return the builder to continue processing the DSL
611     */
612    public T tokenize(String token, String headerName, boolean regex, int group) {
613        return tokenize(token, headerName, regex, group, false);
614    }
615
616    /**
617     * Evaluates a token expression on the given header
618     *
619     * @param token the token
620     * @param headerName name of header to tokenize
621     * @param regex whether the token is a regular expression or not
622     * @param skipFirst whether to skip the very first element
623     * @return the builder to continue processing the DSL
624     */
625    public T tokenize(String token, String headerName, boolean regex, boolean skipFirst) {
626        TokenizerExpression expression = new TokenizerExpression();
627        expression.setToken(token);
628        expression.setHeaderName(headerName);
629        expression.setRegex(regex);
630        expression.setSkipFirst(skipFirst);
631        setExpressionType(expression);
632        return result;
633    }
634
635    /**
636     * Evaluates a token expression on the given header
637     *
638     * @param token the token
639     * @param headerName name of header to tokenize
640     * @param regex whether the token is a regular expression or not
641     * @param group to group by number of parts
642     * @param skipFirst whether to skip the very first element
643     * @return the builder to continue processing the DSL
644     */
645    public T tokenize(String token, String headerName, boolean regex, int group, boolean skipFirst) {
646        return tokenize(token, headerName, regex, "" + group, skipFirst);
647    }
648
649    /**
650     * Evaluates a token expression on the given header
651     *
652     * @param token the token
653     * @param headerName name of header to tokenize
654     * @param regex whether the token is a regular expression or not
655     * @param group to group by number of parts
656     * @param skipFirst whether to skip the very first element
657     * @return the builder to continue processing the DSL
658     */
659    public T tokenize(String token, String headerName, boolean regex, String group, boolean skipFirst) {
660        return tokenize(token, headerName, regex, group, null, skipFirst);
661    }
662
663    /**
664     * Evaluates a token expression on the given header
665     *
666     * @param token the token
667     * @param headerName name of header to tokenize
668     * @param regex whether the token is a regular expression or not
669     * @param group to group by number of parts
670     * @param groupDelimiter delimiter to use when grouping
671     * @param skipFirst whether to skip the very first element
672     * @return the builder to continue processing the DSL
673     */
674    public T tokenize(String token, String headerName, boolean regex, String group, String groupDelimiter, boolean skipFirst) {
675        TokenizerExpression expression = new TokenizerExpression();
676        expression.setToken(token);
677        expression.setHeaderName(headerName);
678        expression.setRegex(regex);
679        expression.setGroup(group);
680        expression.setGroupDelimiter(groupDelimiter);
681        expression.setSkipFirst(skipFirst);
682        setExpressionType(expression);
683        return result;
684    }
685
686    /**
687     * Evaluates a token pair expression on the message body
688     *
689     * @param startToken the start token
690     * @param endToken the end token
691     * @param includeTokens whether to include tokens
692     * @return the builder to continue processing the DSL
693     */
694    public T tokenizePair(String startToken, String endToken, boolean includeTokens) {
695        TokenizerExpression expression = new TokenizerExpression();
696        expression.setToken(startToken);
697        expression.setEndToken(endToken);
698        expression.setIncludeTokens(includeTokens);
699        setExpressionType(expression);
700        return result;
701    }
702
703    /**
704     * Evaluates a token pair expression on the message body with XML content
705     *
706     * @param tagName the tag name of the child nodes to tokenize
707     * @param inheritNamespaceTagName optional parent or root tag name that
708     *            contains namespace(s) to inherit
709     * @param group to group by the given number
710     * @return the builder to continue processing the DSL
711     */
712    public T tokenizeXMLPair(String tagName, String inheritNamespaceTagName, int group) {
713        return tokenizeXMLPair(tagName, inheritNamespaceTagName, "" + group);
714    }
715
716    /**
717     * Evaluates a token pair expression on the message body with XML content
718     *
719     * @param tagName the tag name of the child nodes to tokenize
720     * @param inheritNamespaceTagName optional parent or root tag name that
721     *            contains namespace(s) to inherit
722     * @param group to group by the given number
723     * @return the builder to continue processing the DSL
724     */
725    public T tokenizeXMLPair(String tagName, String inheritNamespaceTagName, String group) {
726        TokenizerExpression expression = new TokenizerExpression();
727        expression.setToken(tagName);
728        expression.setInheritNamespaceTagName(inheritNamespaceTagName);
729        expression.setXml(true);
730        expression.setGroup(group);
731        setExpressionType(expression);
732        return result;
733    }
734
735    /**
736     * Evaluates an XML token expression on the message body with XML content
737     * 
738     * @param path the xpath like path notation specifying the child nodes to
739     *            tokenize
740     * @param mode one of 'i', 'w', or 'u' to inject the namespaces to the
741     *            token, to wrap the token with its ancestor contet, or to
742     *            unwrap to its element child
743     * @param namespaces the namespace map to the namespace bindings
744     * @param group to group by the given number
745     * @return the builder to continue processing the DSL
746     */
747    public T xtokenize(String path, char mode, Namespaces namespaces, int group) {
748        XMLTokenizerExpression expression = new XMLTokenizerExpression(path);
749        expression.setMode(Character.toString(mode));
750        expression.setNamespaces(namespaces.getNamespaces());
751
752        if (group > 0) {
753            expression.setGroup(group);
754        }
755        setExpressionType(expression);
756        return result;
757    }
758
759    /**
760     * Evaluates an <a href="http://camel.apache.org/xpath.html">XPath
761     * expression</a>
762     *
763     * @param text the expression to be evaluated
764     * @return the builder to continue processing the DSL
765     */
766    public T xpath(String text) {
767        return expression(new XPathExpression(text));
768    }
769
770    /**
771     * Evaluates an <a href="http://camel.apache.org/xpath.html">XPath
772     * expression</a> on the supplied header name's contents
773     * 
774     * @param text the expression to be evaluated
775     * @param headerName the name of the header to apply the expression to
776     * @return the builder to continue processing the DSL
777     */
778    public T xpath(String text, String headerName) {
779        XPathExpression expression = new XPathExpression(text);
780        expression.setHeaderName(headerName);
781        return expression(expression);
782    }
783
784    /**
785     * Evaluates an <a href="http://camel.apache.org/xpath.html">XPath
786     * expression</a> with the specified result type
787     *
788     * @param text the expression to be evaluated
789     * @param resultType the return type expected by the expression
790     * @return the builder to continue processing the DSL
791     */
792    public T xpath(String text, Class<?> resultType) {
793        XPathExpression expression = new XPathExpression(text);
794        expression.setResultType(resultType);
795        setExpressionType(expression);
796        return result;
797    }
798
799    /**
800     * Evaluates an <a href="http://camel.apache.org/xpath.html">XPath
801     * expression</a> with the specified result type on the supplied header
802     * name's contents
803     *
804     * @param text the expression to be evaluated
805     * @param resultType the return type expected by the expression
806     * @param headerName the name of the header to apply the expression to
807     * @return the builder to continue processing the DSL
808     */
809    public T xpath(String text, Class<?> resultType, String headerName) {
810        XPathExpression expression = new XPathExpression(text);
811        expression.setHeaderName(headerName);
812        setExpressionType(expression);
813        return result;
814    }
815
816    /**
817     * Evaluates an <a href="http://camel.apache.org/xpath.html">XPath
818     * expression</a> with the specified result type and set of namespace
819     * prefixes and URIs
820     *
821     * @param text the expression to be evaluated
822     * @param resultType the return type expected by the expression
823     * @param namespaces the namespace prefix and URIs to use
824     * @return the builder to continue processing the DSL
825     */
826    public T xpath(String text, Class<?> resultType, Namespaces namespaces) {
827        return xpath(text, resultType, namespaces.getNamespaces());
828    }
829
830    /**
831     * Evaluates an <a href="http://camel.apache.org/xpath.html">XPath
832     * expression</a> with the specified result type and set of namespace
833     * prefixes and URIs on the supplied header name's contents
834     *
835     * @param text the expression to be evaluated
836     * @param resultType the return type expected by the expression
837     * @param namespaces the namespace prefix and URIs to use
838     * @param headerName the name of the header to apply the expression to
839     * @return the builder to continue processing the DSL
840     */
841    public T xpath(String text, Class<?> resultType, Namespaces namespaces, String headerName) {
842        XPathExpression expression = new XPathExpression(text);
843        expression.setResultType(resultType);
844        expression.setNamespaces(namespaces.getNamespaces());
845        expression.setHeaderName(headerName);
846        setExpressionType(expression);
847        return result;
848    }
849
850    /**
851     * Evaluates an <a href="http://camel.apache.org/xpath.html">XPath
852     * expression</a> with the specified result type and set of namespace
853     * prefixes and URIs
854     *
855     * @param text the expression to be evaluated
856     * @param resultType the return type expected by the expression
857     * @param namespaces the namespace prefix and URIs to use
858     * @return the builder to continue processing the DSL
859     */
860    public T xpath(String text, Class<?> resultType, Map<String, String> namespaces) {
861        XPathExpression expression = new XPathExpression(text);
862        expression.setResultType(resultType);
863        expression.setNamespaces(namespaces);
864        setExpressionType(expression);
865        return result;
866    }
867
868    /**
869     * Evaluates an <a href="http://camel.apache.org/xpath.html">XPath
870     * expression</a> with the specified set of namespace prefixes and URIs
871     *
872     * @param text the expression to be evaluated
873     * @param namespaces the namespace prefix and URIs to use
874     * @return the builder to continue processing the DSL
875     */
876    public T xpath(String text, Namespaces namespaces) {
877        return xpath(text, namespaces.getNamespaces());
878    }
879
880    /**
881     * Evaluates an <a href="http://camel.apache.org/xpath.html">XPath
882     * expression</a> with the specified set of namespace prefixes and URIs
883     *
884     * @param text the expression to be evaluated
885     * @param namespaces the namespace prefix and URIs to use
886     * @return the builder to continue processing the DSL
887     */
888    public T xpath(String text, Map<String, String> namespaces) {
889        XPathExpression expression = new XPathExpression(text);
890        expression.setNamespaces(namespaces);
891        setExpressionType(expression);
892        return result;
893    }
894
895    /**
896     * Evaluates an <a href="http://camel.apache.org/xquery.html">XQuery
897     * expression</a>
898     *
899     * @param text the expression to be evaluated
900     * @return the builder to continue processing the DSL
901     */
902    public T xquery(String text) {
903        return expression(new XQueryExpression(text));
904    }
905
906    /**
907     * Evaluates an <a href="http://camel.apache.org/xquery.html">XQuery
908     * expression</a>
909     * 
910     * @param text the expression to be evaluated
911     * @param headerName the name of the header to apply the expression to
912     * @return the builder to continue processing the DSL
913     */
914    public T xquery(String text, String headerName) {
915        XQueryExpression expression = new XQueryExpression(text);
916        expression.setHeaderName(headerName);
917        return expression(expression);
918    }
919
920    /**
921     * Evaluates an <a href="http://camel.apache.org/xquery.html">XQuery
922     * expression</a> with the specified result type
923     *
924     * @param text the expression to be evaluated
925     * @param resultType the return type expected by the expression
926     * @return the builder to continue processing the DSL
927     */
928    public T xquery(String text, Class<?> resultType) {
929        XQueryExpression expression = new XQueryExpression(text);
930        expression.setResultType(resultType);
931        setExpressionType(expression);
932        return result;
933    }
934
935    /**
936     * Evaluates an <a href="http://camel.apache.org/xquery.html">XQuery
937     * expression</a> with the specified result type
938     *
939     * @param text the expression to be evaluated
940     * @param resultType the return type expected by the expression
941     * @param headerName the name of the header to apply the expression to
942     * @return the builder to continue processing the DSL
943     */
944    public T xquery(String text, Class<?> resultType, String headerName) {
945        XQueryExpression expression = new XQueryExpression(text);
946        expression.setHeaderName(headerName);
947        setExpressionType(expression);
948        return result;
949    }
950
951    /**
952     * Evaluates an <a href="http://camel.apache.org/xquery.html">XQuery
953     * expression</a> with the specified result type and set of namespace
954     * prefixes and URIs
955     *
956     * @param text the expression to be evaluated
957     * @param resultType the return type expected by the expression
958     * @param namespaces the namespace prefix and URIs to use
959     * @return the builder to continue processing the DSL
960     */
961    public T xquery(String text, Class<?> resultType, Namespaces namespaces) {
962        return xquery(text, resultType, namespaces.getNamespaces());
963    }
964
965    /**
966     * Evaluates an <a href="http://camel.apache.org/xquery.html">XQuery
967     * expression</a> with the specified result type and set of namespace
968     * prefixes and URIs
969     *
970     * @param text the expression to be evaluated
971     * @param resultType the return type expected by the expression
972     * @param namespaces the namespace prefix and URIs to use
973     * @param headerName the name of the header to apply the expression to
974     * @return the builder to continue processing the DSL
975     */
976    public T xquery(String text, Class<?> resultType, Namespaces namespaces, String headerName) {
977        XQueryExpression expression = new XQueryExpression(text);
978        expression.setResultType(resultType);
979        expression.setNamespaces(namespaces.getNamespaces());
980        expression.setHeaderName(headerName);
981        setExpressionType(expression);
982        return result;
983    }
984
985    /**
986     * Evaluates an <a href="http://camel.apache.org/xquery.html">XQuery
987     * expression</a> with the specified result type and set of namespace
988     * prefixes and URIs
989     *
990     * @param text the expression to be evaluated
991     * @param resultType the return type expected by the expression
992     * @param namespaces the namespace prefix and URIs to use
993     * @return the builder to continue processing the DSL
994     */
995    public T xquery(String text, Class<?> resultType, Map<String, String> namespaces) {
996        XQueryExpression expression = new XQueryExpression(text);
997        expression.setResultType(resultType);
998        expression.setNamespaces(namespaces);
999        setExpressionType(expression);
1000        return result;
1001    }
1002
1003    /**
1004     * Evaluates an <a href="http://camel.apache.org/xquery.html">XQuery
1005     * expression</a> with the specified set of namespace prefixes and URIs
1006     *
1007     * @param text the expression to be evaluated
1008     * @param namespaces the namespace prefix and URIs to use
1009     * @return the builder to continue processing the DSL
1010     */
1011    public T xquery(String text, Namespaces namespaces) {
1012        return xquery(text, namespaces.getNamespaces());
1013    }
1014
1015    /**
1016     * Evaluates an <a href="http://camel.apache.org/xquery.html">XQuery
1017     * expression</a> with the specified set of namespace prefixes and URIs
1018     *
1019     * @param text the expression to be evaluated
1020     * @param namespaces the namespace prefix and URIs to use
1021     * @return the builder to continue processing the DSL
1022     */
1023    public T xquery(String text, Map<String, String> namespaces) {
1024        XQueryExpression expression = new XQueryExpression(text);
1025        expression.setNamespaces(namespaces);
1026        setExpressionType(expression);
1027        return result;
1028    }
1029
1030    /**
1031     * Evaluates a given language name with the expression text
1032     *
1033     * @param language the name of the language
1034     * @param expression the expression in the given language
1035     * @return the builder to continue processing the DSL
1036     */
1037    public T language(String language, String expression) {
1038        LanguageExpression exp = new LanguageExpression(language, expression);
1039        setExpressionType(exp);
1040        return result;
1041    }
1042
1043    // Properties
1044    // -------------------------------------------------------------------------
1045
1046    public Expression getExpressionValue() {
1047        return expressionValue;
1048    }
1049
1050    public void setExpressionValue(Expression expressionValue) {
1051        this.expressionValue = expressionValue;
1052    }
1053
1054    public ExpressionFactory getExpressionType() {
1055        return expressionType;
1056    }
1057
1058    public void setExpressionType(ExpressionFactory expressionType) {
1059        this.expressionType = expressionType;
1060    }
1061
1062    protected Expression createExpression(CamelContext camelContext) {
1063        if (getExpressionValue() == null) {
1064            if (getExpressionType() != null) {
1065                setExpressionValue(getExpressionType().createExpression(camelContext));
1066            } else {
1067                throw new IllegalStateException("No expression value configured");
1068            }
1069        }
1070        return getExpressionValue();
1071    }
1072
1073    protected void configureExpression(CamelContext camelContext, Expression expression) {
1074        // noop
1075    }
1076
1077}