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.Comparator;
021import java.util.List;
022
023import org.apache.camel.Exchange;
024import org.apache.camel.Expression;
025import org.apache.camel.Predicate;
026import org.apache.camel.builder.xml.Namespaces;
027import org.apache.camel.spi.NamespaceAware;
028import org.apache.camel.util.ExpressionToPredicateAdapter;
029
030/**
031 * A builder of expressions or predicates based on values.
032 * 
033 * @version 
034 */
035public class ValueBuilder implements Expression, Predicate {
036    private Expression expression;
037    private boolean not;
038
039    public ValueBuilder(Expression expression) {
040        this.expression = expression;
041    }
042
043    @Override
044    public <T> T evaluate(Exchange exchange, Class<T> type) {
045        return expression.evaluate(exchange, type);
046    }
047
048    @Override
049    public boolean matches(Exchange exchange) {
050        return PredicateBuilder.toPredicate(getExpression()).matches(exchange);
051    }
052
053    public Expression getExpression() {
054        return expression;
055    }
056
057    @Override
058    public String toString() {
059        return expression.toString();
060    }
061
062    // Predicate builders
063    // -------------------------------------------------------------------------
064
065    public Predicate matches(Expression expression) {
066        return onNewPredicate(ExpressionToPredicateAdapter.toPredicate(expression));
067    }
068
069    public ExpressionClause<Predicate> matches() {
070        return new ExpressionClause<Predicate>(onNewPredicate(ExpressionToPredicateAdapter.toPredicate(expression))); 
071    }
072
073    public Predicate isNotEqualTo(Object value) {
074        Expression right = asExpression(value);
075        return onNewPredicate(PredicateBuilder.isNotEqualTo(expression, right));
076    }
077
078    public Predicate isEqualTo(Object value) {
079        Expression right = asExpression(value);
080        return onNewPredicate(PredicateBuilder.isEqualTo(expression, right));
081    }
082
083    public Predicate isEqualToIgnoreCase(Object value) {
084        Expression right = asExpression(value);
085        return onNewPredicate(PredicateBuilder.isEqualToIgnoreCase(expression, right));
086    }
087
088    public Predicate isLessThan(Object value) {
089        Expression right = asExpression(value);
090        return onNewPredicate(PredicateBuilder.isLessThan(expression, right));
091    }
092
093    public Predicate isLessThanOrEqualTo(Object value) {
094        Expression right = asExpression(value);
095        return onNewPredicate(PredicateBuilder.isLessThanOrEqualTo(expression, right));
096    }
097
098    public Predicate isGreaterThan(Object value) {
099        Expression right = asExpression(value);
100        return onNewPredicate(PredicateBuilder.isGreaterThan(expression, right));
101    }
102
103    public Predicate isGreaterThanOrEqualTo(Object value) {
104        Expression right = asExpression(value);
105        return onNewPredicate(PredicateBuilder.isGreaterThanOrEqualTo(expression, right));
106    }
107
108    public Predicate isInstanceOf(Class<?> type) {
109        return onNewPredicate(PredicateBuilder.isInstanceOf(expression, type));
110    }
111
112    public Predicate isNull() {
113        return onNewPredicate(PredicateBuilder.isNull(expression));
114    }
115
116    public Predicate isNotNull() {
117        return onNewPredicate(PredicateBuilder.isNotNull(expression));
118    }
119   
120    public Predicate not(Predicate predicate) {
121        return onNewPredicate(PredicateBuilder.not(predicate));
122    }
123
124    public Predicate in(Object... values) {
125        List<Predicate> predicates = new ArrayList<Predicate>();
126        for (Object value : values) {
127            Expression right = asExpression(value);
128            right = ExpressionBuilder.convertToExpression(right, expression);
129            Predicate predicate = onNewPredicate(PredicateBuilder.isEqualTo(expression, right));
130            predicates.add(predicate);
131        }
132        return in(predicates.toArray(new Predicate[predicates.size()]));
133    }
134
135    public Predicate in(Predicate... predicates) {
136        return onNewPredicate(PredicateBuilder.in(predicates));
137    }
138
139    public Predicate startsWith(Object value) {
140        Expression right = asExpression(value);
141        return onNewPredicate(PredicateBuilder.startsWith(expression, right));
142    }
143
144    public Predicate endsWith(Object value) {
145        Expression right = asExpression(value);
146        return onNewPredicate(PredicateBuilder.endsWith(expression, right));
147    }
148
149    /**
150     * Create a predicate that the left hand expression contains the value of
151     * the right hand expression
152     * 
153     * @param value the element which is compared to be contained within this
154     *                expression
155     * @return a predicate which evaluates to true if the given value expression
156     *         is contained within this expression value
157     */
158    public Predicate contains(Object value) {
159        Expression right = asExpression(value);
160        return onNewPredicate(PredicateBuilder.contains(expression, right));
161    }
162
163    /**
164     * Creates a predicate which is true if this expression matches the given
165     * regular expression
166     * 
167     * @param regex the regular expression to match
168     * @return a predicate which evaluates to true if the expression matches the
169     *         regex
170     */
171    public Predicate regex(String regex) {
172        return onNewPredicate(PredicateBuilder.regex(expression, regex));
173    }
174
175    // Expression builders
176    // -------------------------------------------------------------------------
177
178    public ValueBuilder tokenize() {
179        return tokenize("\n");
180    }
181
182    public ValueBuilder tokenize(String token) {
183        Expression newExp = ExpressionBuilder.tokenizeExpression(expression, token);
184        return onNewValueBuilder(newExp);
185    }
186
187    public ValueBuilder tokenize(String token, int group, boolean skipFirst) {
188        Expression newExp = ExpressionBuilder.tokenizeExpression(expression, token);
189        if (group == 0 && skipFirst) {
190            // wrap in skip first (if group then it has its own skip first logic)
191            newExp = ExpressionBuilder.skipFirstExpression(newExp);
192        }
193        newExp = ExpressionBuilder.groupIteratorExpression(newExp, token, group, skipFirst);
194        return onNewValueBuilder(newExp);
195    }
196
197    public ValueBuilder tokenizeXML(String tagName, String inheritNamespaceTagName) {
198        Expression newExp = ExpressionBuilder.tokenizeXMLExpression(tagName, inheritNamespaceTagName);
199        return onNewValueBuilder(newExp);
200    }
201
202    public ValueBuilder xtokenize(String path, Namespaces namespaces) {
203        return xtokenize(path, 'i', namespaces);
204    }
205
206    public ValueBuilder xtokenize(String path, char mode, Namespaces namespaces) {
207        Expression newExp = ExpressionBuilder.tokenizeXMLAwareExpression(path, mode);
208        ((NamespaceAware)newExp).setNamespaces(namespaces.getNamespaces());
209        return onNewValueBuilder(newExp);
210    }
211
212    public ValueBuilder tokenizePair(String startToken, String endToken, boolean includeTokens) {
213        Expression newExp = ExpressionBuilder.tokenizePairExpression(startToken, endToken, includeTokens);
214        return onNewValueBuilder(newExp);
215    }
216
217    /**
218     * Tokenizes the string conversion of this expression using the given
219     * regular expression
220     */
221    public ValueBuilder regexTokenize(String regex) {
222        Expression newExp = ExpressionBuilder.regexTokenizeExpression(expression, regex);
223        return onNewValueBuilder(newExp);
224    }
225
226    /**
227     * Replaces all occurrences of the regular expression with the given
228     * replacement
229     */
230    public ValueBuilder regexReplaceAll(String regex, String replacement) {
231        Expression newExp = ExpressionBuilder.regexReplaceAll(expression, regex, replacement);
232        return onNewValueBuilder(newExp);
233    }
234
235    /**
236     * Replaces all occurrences of the regular expression with the given
237     * replacement
238     */
239    public ValueBuilder regexReplaceAll(String regex, Expression replacement) {
240        Expression newExp = ExpressionBuilder.regexReplaceAll(expression, regex, replacement);
241        return onNewValueBuilder(newExp);
242    }
243
244    /**
245     * Converts the current value to the given type using the registered type
246     * converters
247     * 
248     * @param type the type to convert the value to
249     * @return the current builder
250     */
251    public ValueBuilder convertTo(Class<?> type) {
252        Expression newExp = ExpressionBuilder.convertToExpression(expression, type);
253        return onNewValueBuilder(newExp);
254    }
255
256    /**
257     * Converts the current value to a String using the registered type converters
258     * 
259     * @return the current builder
260     */
261    public ValueBuilder convertToString() {
262        return convertTo(String.class);
263    }
264
265    /**
266     * Appends the string evaluation of this expression with the given value
267     *
268     * @param value the value or expression to append
269     * @return the current builder
270     */
271    public ValueBuilder append(Object value) {
272        Expression newExp = ExpressionBuilder.append(expression, asExpression(value));
273        return onNewValueBuilder(newExp);
274    }
275
276    /**
277     * Prepends the string evaluation of this expression with the given value
278     *
279     * @param value the value or expression to prepend
280     * @return the current builder
281     */
282    public ValueBuilder prepend(Object value) {
283        Expression newExp = ExpressionBuilder.prepend(expression, asExpression(value));
284        return onNewValueBuilder(newExp);
285    }
286
287    /**
288     * Sorts the current value using the given comparator. The current value must be convertable
289     * to a {@link List} to allow sorting using the comparator.
290     *
291     * @param comparator  the comparator used by sorting
292     * @return the current builder
293     */
294    public ValueBuilder sort(Comparator<?> comparator) {
295        Expression newExp = ExpressionBuilder.sortExpression(expression, comparator);
296        return onNewValueBuilder(newExp);
297    }
298
299    /**
300     * Invokes the method with the given name (supports OGNL syntax).
301     *
302     * @param methodName  name of method to invoke.
303     * @return the current builder
304     */
305    public ValueBuilder method(String methodName) {
306        Expression newExp = ExpressionBuilder.ognlExpression(expression, methodName);
307        return onNewValueBuilder(newExp);
308    }
309
310    /**
311     * Negates the built expression.
312     *
313     * @return the current builder
314     */
315    public ValueBuilder not() {
316        not = true;
317        return this;
318    }
319
320    // Implementation methods
321    // -------------------------------------------------------------------------
322
323    /**
324     * A strategy method to allow derived classes to deal with the newly created
325     * predicate in different ways
326     */
327    protected Predicate onNewPredicate(Predicate predicate) {
328        if (not) {
329            return PredicateBuilder.not(predicate);
330        } else {
331            return predicate;
332        }
333    }
334
335    protected Expression asExpression(Object value) {
336        if (value instanceof Expression) {
337            return (Expression)value;
338        } else {
339            return ExpressionBuilder.constantExpression(value);
340        }
341    }
342
343    protected ValueBuilder onNewValueBuilder(Expression exp) {
344        return new ValueBuilder(exp);
345    }
346}