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 org.apache.camel.CamelContext;
020import org.apache.camel.CamelExecutionException;
021import org.apache.camel.Exchange;
022import org.apache.camel.Expression;
023import org.apache.camel.Predicate;
024import org.apache.camel.language.simple.Simple;
025import org.apache.camel.spi.ExpressionResultTypeAware;
026import org.apache.camel.spi.Language;
027import org.apache.camel.spi.PropertyConfigurer;
028import org.apache.camel.support.PredicateToExpressionAdapter;
029import org.apache.camel.support.ScriptHelper;
030import org.apache.camel.support.component.PropertyConfigurerSupport;
031
032/**
033 * Creates an {@link Simple} language builder.
034 * <p/>
035 * This builder is available in the Java DSL from the {@link RouteBuilder} which
036 * means that using simple language for {@link Expression}s or
037 * {@link Predicate}s is very easy with the help of this builder.
038 */
039public class SimpleBuilder implements Predicate, Expression, ExpressionResultTypeAware, PropertyConfigurer {
040
041    private final String text;
042    private Class<?> resultType;
043    // cache the expression/predicate
044    private volatile Expression expression;
045    private volatile Predicate predicate;
046
047    public SimpleBuilder(String text) {
048        this.text = text;
049    }
050
051    public static SimpleBuilder simple(String text) {
052        return new SimpleBuilder(text);
053    }
054
055    public static SimpleBuilder simple(String text, Class<?> resultType) {
056        SimpleBuilder answer = simple(text);
057        answer.setResultType(resultType);
058        return answer;
059    }
060
061    public static SimpleBuilder simpleF(String formatText, Object... values) {
062        return simple(String.format(formatText, values));
063    }
064
065    public static SimpleBuilder simpleF(String formatText, Class<?> resultType, Object... values) {
066        return simple(String.format(formatText, values), resultType);
067    }
068
069    @Override
070    public boolean configure(CamelContext camelContext, Object target, String name, Object value, boolean ignoreCase) {
071        if (target != this) {
072            throw new IllegalStateException("Can only configure our own instance !");
073        }
074        switch (ignoreCase ? name.toLowerCase() : name) {
075            case "resulttype":
076            case "resultType":
077                setResultType(PropertyConfigurerSupport.property(camelContext, Class.class, value)); return true;
078            default:
079                return false;
080        }
081    }
082
083    public String getText() {
084        return text;
085    }
086
087    @Override
088    public String getExpressionText() {
089        return getText();
090    }
091
092    @Override
093    public Class<?> getResultType() {
094        return resultType;
095    }
096
097    public void setResultType(Class<?> resultType) {
098        this.resultType = resultType;
099    }
100
101    public SimpleBuilder resultType(Class<?> resultType) {
102        setResultType(resultType);
103        return this;
104    }
105
106    @Override
107    public boolean matches(Exchange exchange) {
108        if (predicate == null) {
109            predicate = createPredicate(exchange);
110        }
111        return predicate.matches(exchange);
112    }
113
114    @Override
115    public <T> T evaluate(Exchange exchange, Class<T> type) {
116        if (expression == null) {
117            expression = createExpression(exchange);
118        }
119        return expression.evaluate(exchange, type);
120    }
121
122    private Predicate createPredicate(Exchange exchange) {
123        try {
124            // resolve property placeholders
125            String resolve = exchange.getContext().resolvePropertyPlaceholders(text);
126            // and optional it be refer to an external script on the
127            // file/classpath
128            resolve = ScriptHelper.resolveOptionalExternalScript(exchange.getContext(), exchange, resolve);
129            Language simple = exchange.getContext().resolveLanguage("simple");
130            return simple.createPredicate(resolve);
131        } catch (Exception e) {
132            throw CamelExecutionException.wrapCamelExecutionException(exchange, e);
133        }
134    }
135
136    private Expression createExpression(Exchange exchange) {
137        try {
138            // resolve property placeholders
139            String resolve = exchange.getContext().resolvePropertyPlaceholders(text);
140            // and optional it be refer to an external script on the
141            // file/classpath
142            resolve = ScriptHelper.resolveOptionalExternalScript(exchange.getContext(), exchange, resolve);
143            Language simple = exchange.getContext().resolveLanguage("simple");
144            return createSimpleExpression(simple, resolve, resultType);
145        } catch (Exception e) {
146            throw CamelExecutionException.wrapCamelExecutionException(exchange, e);
147        }
148    }
149
150    private static Expression createSimpleExpression(Language simple, String expression, Class<?> resultType) {
151        if (resultType == Boolean.class || resultType == boolean.class) {
152            // if its a boolean as result then its a predicate
153            Predicate predicate = simple.createPredicate(expression);
154            return PredicateToExpressionAdapter.toExpression(predicate);
155        } else {
156            Expression exp = simple.createExpression(expression);
157            if (resultType != null) {
158                exp = ExpressionBuilder.convertToExpression(exp, resultType);
159            }
160            return exp;
161        }
162    }
163
164    @Override
165    public String toString() {
166        return "Simple: " + text;
167    }
168
169}