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     */
017    package org.apache.camel.builder;
018    
019    import java.io.File;
020    import java.io.FileNotFoundException;
021    import java.io.InputStream;
022    import java.nio.channels.ReadableByteChannel;
023    import java.util.ArrayList;
024    import java.util.Collection;
025    import java.util.List;
026    import java.util.Scanner;
027    import java.util.regex.Pattern;
028    
029    import org.apache.camel.Exchange;
030    import org.apache.camel.Expression;
031    import org.apache.camel.Message;
032    import org.apache.camel.RuntimeCamelException;
033    
034    /**
035     * A helper class for working with <a href="http://activemq.apache.org/camel/expression.html">expressions</a>.
036     *
037     * @version $Revision: 51090 $
038     */
039    public final class ExpressionBuilder {
040    
041        /**
042         * Utility classes should not have a public constructor.
043         */
044        private ExpressionBuilder() {
045        }
046    
047        /**
048         * Returns an expression for the header value with the given name
049         *
050         * @param headerName the name of the header the expression will return
051         * @return an expression object which will return the header value
052         */
053        public static <E extends Exchange> Expression<E> headerExpression(final String headerName) {
054            return new Expression<E>() {
055                public Object evaluate(E exchange) {
056                    Object header = exchange.getIn().getHeader(headerName);
057                    if (header == null) {
058                        // lets try the exchange header
059                        header = exchange.getProperty(headerName);
060                    }
061                    return header;
062                }
063    
064                @Override
065                public String toString() {
066                    return "header(" + headerName + ")";
067                }
068            };
069        }
070    
071        /**
072         * Returns an expression for the inbound message headers
073         *
074         * @see Message#getHeaders()
075         * @return an expression object which will return the inbound headers
076         */
077        public static <E extends Exchange> Expression<E> headersExpression() {
078            return new Expression<E>() {
079                public Object evaluate(E exchange) {
080                    return exchange.getIn().getHeaders();
081                }
082    
083                @Override
084                public String toString() {
085                    return "headers";
086                }
087            };
088        }
089    
090        /**
091         * Returns an expression for the out header value with the given name
092         *
093         * @param headerName the name of the header the expression will return
094         * @return an expression object which will return the header value
095         */
096        public static <E extends Exchange> Expression<E> outHeaderExpression(final String headerName) {
097            return new Expression<E>() {
098                public Object evaluate(E exchange) {
099                    Message out = exchange.getOut(false);
100                    if (out == null) {
101                        return null;
102                    }
103                    Object header = out.getHeader(headerName);
104                    if (header == null) {
105                        // lets try the exchange header
106                        header = exchange.getProperty(headerName);
107                    }
108                    return header;
109                }
110    
111                @Override
112                public String toString() {
113                    return "outHeader(" + headerName + ")";
114                }
115            };
116        }
117    
118        /**
119         * Returns an expression for the outbound message headers
120         *
121         * @see Message#getHeaders()
122         * @return an expression object which will return the inbound headers
123         */
124        public static <E extends Exchange> Expression<E> outHeadersExpression() {
125            return new Expression<E>() {
126                public Object evaluate(E exchange) {
127                    return exchange.getOut().getHeaders();
128                }
129    
130                @Override
131                public String toString() {
132                    return "outHeaders";
133                }
134            };
135        }
136    
137        /**
138         * Returns an expression for the property value with the given name
139         *
140         * @see Exchange#getProperty(String)
141         * @param propertyName the name of the property the expression will return
142         * @return an expression object which will return the property value
143         */
144        public static <E extends Exchange> Expression<E> propertyExpression(final String propertyName) {
145            return new Expression<E>() {
146                public Object evaluate(E exchange) {
147                    return exchange.getProperty(propertyName);
148                }
149    
150                @Override
151                public String toString() {
152                    return "property(" + propertyName + ")";
153                }
154            };
155        }
156    
157    
158        /**
159         * Returns an expression for the property value with the given name
160         *
161         * @see Exchange#getProperties()
162         * @return an expression object which will return the properties
163         */
164        public static <E extends Exchange> Expression<E> propertiesExpression() {
165            return new Expression<E>() {
166                public Object evaluate(E exchange) {
167                    return exchange.getProperties();
168                }
169    
170                @Override
171                public String toString() {
172                    return "properties";
173                }
174            };
175        }
176    
177        /**
178         * Returns an expression for a system property value with the given name
179         *
180         * @param propertyName the name of the system property the expression will
181         *                return
182         * @return an expression object which will return the system property value
183         */
184        public static <E extends Exchange> Expression<E> systemPropertyExpression(final String propertyName) {
185            return systemPropertyExpression(propertyName, null);
186        }
187    
188        /**
189         * Returns an expression for a system property value with the given name
190         *
191         * @param propertyName the name of the system property the expression will
192         *                return
193         * @return an expression object which will return the system property value
194         */
195        public static <E extends Exchange> Expression<E> systemPropertyExpression(final String propertyName,
196                                                                                  final String defaultValue) {
197            return new Expression<E>() {
198                public Object evaluate(E exchange) {
199                    return System.getProperty(propertyName, defaultValue);
200                }
201    
202                @Override
203                public String toString() {
204                    return "systemProperty(" + propertyName + ")";
205                }
206            };
207        }
208    
209        /**
210         * Returns an expression for the constant value
211         *
212         * @param value the value the expression will return
213         * @return an expression object which will return the constant value
214         */
215        public static <E extends Exchange> Expression<E> constantExpression(final Object value) {
216            return new Expression<E>() {
217                public Object evaluate(E exchange) {
218                    return value;
219                }
220    
221                @Override
222                public String toString() {
223                    return "" + value;
224                }
225            };
226        }
227    
228        /**
229         * Returns the expression for the exchanges inbound message body
230         */
231        public static <E extends Exchange> Expression<E> bodyExpression() {
232            return new Expression<E>() {
233                public Object evaluate(E exchange) {
234                    return exchange.getIn().getBody();
235                }
236    
237                @Override
238                public String toString() {
239                    return "body";
240                }
241            };
242        }
243    
244        /**
245         * Returns the expression for the exchanges inbound message body converted
246         * to the given type
247         */
248        public static <E extends Exchange, T> Expression<E> bodyExpression(final Class<T> type) {
249            return new Expression<E>() {
250                public Object evaluate(E exchange) {
251                    return exchange.getIn().getBody(type);
252                }
253    
254                @Override
255                public String toString() {
256                    return "bodyAs[" + type.getName() + "]";
257                }
258            };
259        }
260    
261        /**
262         * Returns the expression for the out messages body
263         */
264        public static <E extends Exchange> Expression<E> outBodyExpression() {
265            return new Expression<E>() {
266                public Object evaluate(E exchange) {
267                    Message out = exchange.getOut(false);
268                    if (out == null) {
269                        return null;
270                    }
271                    return out.getBody();
272                }
273    
274                @Override
275                public String toString() {
276                    return "outBody";
277                }
278            };
279        }
280    
281        /**
282         * Returns the expression for the exchanges outbound message body converted
283         * to the given type
284         */
285        public static <E extends Exchange, T> Expression<E> outBodyExpression(final Class<T> type) {
286            return new Expression<E>() {
287                public Object evaluate(E exchange) {
288                    Message out = exchange.getOut(false);
289                    if (out == null) {
290                        return null;
291                    }
292                    return out.getBody(type);
293                }
294    
295                @Override
296                public String toString() {
297                    return "outBodyAs[" + type.getName() + "]";
298                }
299            };
300        }
301    
302        /**
303         * Returns the expression for the fault messages body
304         */
305        public static <E extends Exchange> Expression<E> faultBodyExpression() {
306            return new Expression<E>() {
307                public Object evaluate(E exchange) {
308                    return exchange.getFault().getBody();
309                }
310    
311                @Override
312                public String toString() {
313                    return "faultBody";
314                }
315            };
316        }
317    
318        /**
319         * Returns the expression for the exchanges fault message body converted
320         * to the given type
321         */
322        public static <E extends Exchange, T> Expression<E> faultBodyExpression(final Class<T> type) {
323            return new Expression<E>() {
324                public Object evaluate(E exchange) {
325                    return exchange.getFault().getBody(type);
326                }
327    
328                @Override
329                public String toString() {
330                    return "faultBodyAs[" + type.getName() + "]";
331                }
332            };
333        }
334    
335        /**
336         * Returns the expression for the exchange
337         */
338        public static <E extends Exchange> Expression<E> exchangeExpression() {
339            return new Expression<E>() {
340                public Object evaluate(E exchange) {
341                    return exchange;
342                }
343    
344                @Override
345                public String toString() {
346                    return "exchange";
347                }
348            };
349        }
350    
351        /**
352         * Returns the expression for the IN message
353         */
354        public static <E extends Exchange> Expression<E> inMessageExpression() {
355            return new Expression<E>() {
356                public Object evaluate(E exchange) {
357                    return exchange.getIn();
358                }
359    
360                @Override
361                public String toString() {
362                    return "inMessage";
363                }
364            };
365        }
366    
367        /**
368         * Returns the expression for the OUT message
369         */
370        public static <E extends Exchange> Expression<E> outMessageExpression() {
371            return new Expression<E>() {
372                public Object evaluate(E exchange) {
373                    return exchange.getOut();
374                }
375    
376                @Override
377                public String toString() {
378                    return "outMessage";
379                }
380            };
381        }
382    
383        /**
384         * Returns an expression which converts the given expression to the given
385         * type
386         */
387        public static <E extends Exchange> Expression<E> convertTo(final Expression expression, final Class type) {
388            return new Expression<E>() {
389                public Object evaluate(E exchange) {
390                    Object value = expression.evaluate(exchange);
391                    return exchange.getContext().getTypeConverter().convertTo(type, exchange, value);
392                }
393    
394                @Override
395                public String toString() {
396                    return "" + expression + ".convertTo(" + type.getName() + ".class)";
397                }
398            };
399        }
400    
401        /**
402         * Returns a tokenize expression which will tokenize the string with the
403         * given token
404         */
405        public static <E extends Exchange> Expression<E> tokenizeExpression(final Expression<E> expression,
406                                                                            final String token) {
407            return new Expression<E>() {
408                public Object evaluate(E exchange) {
409                    Object value = expression.evaluate(exchange);
410                    Scanner scanner = getScanner(exchange, value);
411                    scanner.useDelimiter(token);
412                    return scanner;
413                }
414    
415                @Override
416                public String toString() {
417                    return "tokenize(" + expression + ", " + token + ")";
418                }
419            };
420        }
421    
422        /**
423         * Returns a tokenize expression which will tokenize the string with the
424         * given regex
425         */
426        public static <E extends Exchange> Expression<E> regexTokenize(final Expression<E> expression,
427                                                                       final String regexTokenizer) {
428            final Pattern pattern = Pattern.compile(regexTokenizer);
429            return new Expression<E>() {
430                public Object evaluate(E exchange) {
431                    Object value = expression.evaluate(exchange);
432                    Scanner scanner = getScanner(exchange, value);
433                    scanner.useDelimiter(regexTokenizer);
434                    return scanner;
435                }
436    
437                @Override
438                public String toString() {
439                    return "regexTokenize(" + expression + ", " + pattern.pattern() + ")";
440                }
441            };
442        }
443    
444        private static Scanner getScanner(Exchange exchange, Object value) {
445            String charset = exchange.getProperty(Exchange.CHARSET_NAME, String.class);
446    
447            Scanner scanner = null;
448            if (value instanceof Readable) {
449                scanner = new Scanner((Readable)value);
450            } else if (value instanceof InputStream) {
451                scanner = charset == null ? new Scanner((InputStream)value)
452                    : new Scanner((InputStream)value, charset);
453            } else if (value instanceof File) {
454                try {
455                    scanner = charset == null ? new Scanner((File)value) : new Scanner((File)value, charset);
456                } catch (FileNotFoundException e) {
457                    throw new RuntimeCamelException(e);
458                }
459            } else if (value instanceof String) {
460                scanner = new Scanner((String)value);
461            } else if (value instanceof ReadableByteChannel) {
462                scanner = charset == null ? new Scanner((ReadableByteChannel)value)
463                    : new Scanner((ReadableByteChannel)value, charset);
464            }
465    
466            if (scanner == null) {
467                // value is not a suitable type, try to convert value to a string
468                String text = exchange.getContext().getTypeConverter().convertTo(String.class, exchange, value);
469                if (text != null) {
470                    scanner = new Scanner(text);
471                }
472            }
473            
474            if (scanner == null) {
475                scanner = new Scanner("");
476            }
477            return scanner;
478        }
479    
480        /**
481         * Transforms the expression into a String then performs the regex
482         * replaceAll to transform the String and return the result
483         */
484        public static <E extends Exchange> Expression<E> regexReplaceAll(final Expression<E> expression,
485                                                                         final String regex, final String replacement) {
486            final Pattern pattern = Pattern.compile(regex);
487            return new Expression<E>() {
488                public Object evaluate(E exchange) {
489                    String text = evaluateStringExpression(expression, exchange);
490                    if (text == null) {
491                        return null;
492                    }
493                    return pattern.matcher(text).replaceAll(replacement);
494                }
495    
496                @Override
497                public String toString() {
498                    return "regexReplaceAll(" + expression + ", " + pattern.pattern() + ")";
499                }
500            };
501        }
502    
503        /**
504         * Transforms the expression into a String then performs the regex
505         * replaceAll to transform the String and return the result
506         */
507        public static <E extends Exchange> Expression<E> regexReplaceAll(final Expression<E> expression,
508                                                                         String regex,
509                                                                         final Expression<E> replacementExpression) {
510            final Pattern pattern = Pattern.compile(regex);
511            return new Expression<E>() {
512                public Object evaluate(E exchange) {
513                    String text = evaluateStringExpression(expression, exchange);
514                    String replacement = evaluateStringExpression(replacementExpression, exchange);
515                    if (text == null || replacement == null) {
516                        return null;
517                    }
518                    return pattern.matcher(text).replaceAll(replacement);
519                }
520    
521                @Override
522                public String toString() {
523                    return "regexReplaceAll(" + expression + ", " + pattern.pattern() + ")";
524                }
525            };
526        }
527    
528        /**
529         * Appends the String evaluations of the two expressions together
530         */
531        public static <E extends Exchange> Expression<E> append(final Expression<E> left,
532                                                                final Expression<E> right) {
533            return new Expression<E>() {
534                public Object evaluate(E exchange) {
535                    return evaluateStringExpression(left, exchange) + evaluateStringExpression(right, exchange);
536                }
537    
538                @Override
539                public String toString() {
540                    return "append(" + left + ", " + right + ")";
541                }
542            };
543        }
544    
545        /**
546         * Evaluates the expression on the given exchange and returns the String
547         * representation
548         *
549         * @param expression the expression to evaluate
550         * @param exchange the exchange to use to evaluate the expression
551         * @return the String representation of the expression or null if it could
552         *         not be evaluated
553         */
554        public static <E extends Exchange> String evaluateStringExpression(Expression<E> expression, E exchange) {
555            Object value = expression.evaluate(exchange);
556            return exchange.getContext().getTypeConverter().convertTo(String.class, exchange, value);
557        }
558    
559        /**
560         * Returns an expression for the given system property
561         */
562        public static <E extends Exchange> Expression<E> systemProperty(final String name) {
563            return systemProperty(name, null);
564        }
565    
566        /**
567         * Returns an expression for the given system property
568         */
569        public static <E extends Exchange> Expression<E> systemProperty(final String name,
570                                                                        final String defaultValue) {
571            return new Expression<E>() {
572                public Object evaluate(E exchange) {
573                    return System.getProperty(name, defaultValue);
574                }
575            };
576        }
577    
578        /**
579         * Returns an expression which returns the string concatenation value of the various
580         * expressions
581         *
582         * @param expressions the expression to be concatenated dynamically
583         * @return an expression which when evaluated will return the concatenated values
584         */
585        public static <E extends Exchange> Expression<E> concatExpression(final Collection<Expression> expressions) {
586            return concatExpression(expressions, null);
587        }
588    
589        /**
590         * Returns an expression which returns the string concatenation value of the various
591         * expressions
592         *
593         * @param expressions the expression to be concatenated dynamically
594         * @param expression the text description of the expression
595         * @return an expression which when evaluated will return the concatenated values
596         */
597        public static <E extends Exchange> Expression<E> concatExpression(final Collection<Expression> expressions, final String expression) {
598            return new Expression<E>() {
599                public Object evaluate(E exchange) {
600                    StringBuffer buffer = new StringBuffer();
601                    for (Expression<E> expression : expressions) {
602                        String text = evaluateStringExpression(expression, exchange);
603                        if (text != null) {
604                            buffer.append(text);
605                        }
606                    }
607                    return buffer.toString();
608                }
609    
610                @Override
611                public String toString() {
612                    if (expression != null) {
613                        return expression;
614                    } else {
615                        return "concat" + expressions;
616                    }
617                }
618            };
619        }
620    
621        /**
622         * Returns an Expression for the inbound message id
623         */
624        public static <E extends Exchange> Expression<E> messageIdExpression() {
625            return new Expression<E>() {
626                public Object evaluate(E exchange) {
627                    return exchange.getIn().getMessageId();
628                }
629    
630                @Override
631                public String toString() {
632                    return "messageId";
633                }
634            };
635        }
636    
637    
638    }