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        return tokenize(token, "" + group, skipFirst);
189    }
190
191    public ValueBuilder tokenize(String token, String group, boolean skipFirst) {
192        Expression newExp = ExpressionBuilder.tokenizeExpression(expression, token);
193        if (group == null && skipFirst) {
194            // wrap in skip first (if group then it has its own skip first logic)
195            newExp = ExpressionBuilder.skipFirstExpression(newExp);
196        }
197        newExp = ExpressionBuilder.groupIteratorExpression(newExp, token, group, skipFirst);
198        return onNewValueBuilder(newExp);
199    }
200
201    public ValueBuilder tokenizeXML(String tagName, String inheritNamespaceTagName) {
202        Expression newExp = ExpressionBuilder.tokenizeXMLExpression(tagName, inheritNamespaceTagName);
203        return onNewValueBuilder(newExp);
204    }
205
206    public ValueBuilder xtokenize(String path, Namespaces namespaces) {
207        return xtokenize(path, 'i', namespaces);
208    }
209
210    public ValueBuilder xtokenize(String path, char mode, Namespaces namespaces) {
211        Expression newExp = ExpressionBuilder.tokenizeXMLAwareExpression(path, mode);
212        ((NamespaceAware)newExp).setNamespaces(namespaces.getNamespaces());
213        return onNewValueBuilder(newExp);
214    }
215
216    public ValueBuilder tokenizePair(String startToken, String endToken, boolean includeTokens) {
217        Expression newExp = ExpressionBuilder.tokenizePairExpression(startToken, endToken, includeTokens);
218        return onNewValueBuilder(newExp);
219    }
220
221    /**
222     * Tokenizes the string conversion of this expression using the given
223     * regular expression
224     */
225    public ValueBuilder regexTokenize(String regex) {
226        Expression newExp = ExpressionBuilder.regexTokenizeExpression(expression, regex);
227        return onNewValueBuilder(newExp);
228    }
229
230    /**
231     * Replaces all occurrences of the regular expression with the given
232     * replacement
233     */
234    public ValueBuilder regexReplaceAll(String regex, String replacement) {
235        Expression newExp = ExpressionBuilder.regexReplaceAll(expression, regex, replacement);
236        return onNewValueBuilder(newExp);
237    }
238
239    /**
240     * Replaces all occurrences of the regular expression with the given
241     * replacement
242     */
243    public ValueBuilder regexReplaceAll(String regex, Expression replacement) {
244        Expression newExp = ExpressionBuilder.regexReplaceAll(expression, regex, replacement);
245        return onNewValueBuilder(newExp);
246    }
247
248    /**
249     * Converts the current value to the given type using the registered type
250     * converters
251     * 
252     * @param type the type to convert the value to
253     * @return the current builder
254     */
255    public ValueBuilder convertTo(Class<?> type) {
256        Expression newExp = ExpressionBuilder.convertToExpression(expression, type);
257        return onNewValueBuilder(newExp);
258    }
259
260    /**
261     * Converts the current value to a String using the registered type converters
262     * 
263     * @return the current builder
264     */
265    public ValueBuilder convertToString() {
266        return convertTo(String.class);
267    }
268
269    /**
270     * Appends the string evaluation of this expression with the given value
271     *
272     * @param value the value or expression to append
273     * @return the current builder
274     */
275    public ValueBuilder append(Object value) {
276        Expression newExp = ExpressionBuilder.append(expression, asExpression(value));
277        return onNewValueBuilder(newExp);
278    }
279
280    /**
281     * Prepends the string evaluation of this expression with the given value
282     *
283     * @param value the value or expression to prepend
284     * @return the current builder
285     */
286    public ValueBuilder prepend(Object value) {
287        Expression newExp = ExpressionBuilder.prepend(expression, asExpression(value));
288        return onNewValueBuilder(newExp);
289    }
290
291    /**
292     * Sorts the current value using the given comparator. The current value must be convertable
293     * to a {@link List} to allow sorting using the comparator.
294     *
295     * @param comparator  the comparator used by sorting
296     * @return the current builder
297     */
298    public ValueBuilder sort(Comparator<?> comparator) {
299        Expression newExp = ExpressionBuilder.sortExpression(expression, comparator);
300        return onNewValueBuilder(newExp);
301    }
302
303    /**
304     * Invokes the method with the given name (supports OGNL syntax).
305     *
306     * @param methodName  name of method to invoke.
307     * @return the current builder
308     */
309    public ValueBuilder method(String methodName) {
310        Expression newExp = ExpressionBuilder.ognlExpression(expression, methodName);
311        return onNewValueBuilder(newExp);
312    }
313
314    /**
315     * Negates the built expression.
316     *
317     * @return the current builder
318     */
319    public ValueBuilder not() {
320        not = true;
321        return this;
322    }
323
324    // Implementation methods
325    // -------------------------------------------------------------------------
326
327    /**
328     * A strategy method to allow derived classes to deal with the newly created
329     * predicate in different ways
330     */
331    protected Predicate onNewPredicate(Predicate predicate) {
332        if (not) {
333            return PredicateBuilder.not(predicate);
334        } else {
335            return predicate;
336        }
337    }
338
339    protected Expression asExpression(Object value) {
340        if (value instanceof Expression) {
341            return (Expression)value;
342        } else {
343            return ExpressionBuilder.constantExpression(value);
344        }
345    }
346
347    protected ValueBuilder onNewValueBuilder(Expression exp) {
348        return new ValueBuilder(exp);
349    }
350}