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.model.language;
018    
019    import java.util.List;
020    
021    import javax.xml.bind.annotation.XmlAccessType;
022    import javax.xml.bind.annotation.XmlAccessorType;
023    import javax.xml.bind.annotation.XmlAttribute;
024    import javax.xml.bind.annotation.XmlID;
025    import javax.xml.bind.annotation.XmlRootElement;
026    import javax.xml.bind.annotation.XmlTransient;
027    import javax.xml.bind.annotation.XmlType;
028    import javax.xml.bind.annotation.XmlValue;
029    import javax.xml.bind.annotation.adapters.CollapsedStringAdapter;
030    import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
031    
032    import org.apache.camel.CamelContext;
033    import org.apache.camel.Exchange;
034    import org.apache.camel.Expression;
035    import org.apache.camel.Predicate;
036    import org.apache.camel.spi.Language;
037    import org.apache.camel.spi.Required;
038    import org.apache.camel.spi.RouteContext;
039    import org.apache.camel.util.CollectionStringBuffer;
040    import org.apache.camel.util.ExpressionToPredicateAdapter;
041    import org.apache.camel.util.IntrospectionSupport;
042    import org.apache.camel.util.ObjectHelper;
043    
044    /**
045     * A useful base class for an expression
046     *
047     * @version 
048     */
049    @XmlRootElement
050    @XmlType(name = "expression")
051    @XmlAccessorType(XmlAccessType.FIELD)
052    public class ExpressionDefinition implements Expression, Predicate {
053        @XmlAttribute
054        @XmlJavaTypeAdapter(CollapsedStringAdapter.class)
055        @XmlID
056        private String id;
057        @XmlValue
058        private String expression;
059        @XmlAttribute
060        private Boolean trim;
061        @XmlTransient
062        private Predicate predicate;
063        @XmlTransient
064        private Expression expressionValue;
065        @XmlTransient
066        private ExpressionDefinition expressionType;
067    
068        public ExpressionDefinition() {
069        }
070    
071        public ExpressionDefinition(String expression) {
072            this.expression = expression;
073        }
074    
075        public ExpressionDefinition(Predicate predicate) {
076            this.predicate = predicate;
077        }
078    
079        public ExpressionDefinition(Expression expression) {
080            this.expressionValue = expression;
081        }
082    
083        public static String getLabel(List<ExpressionDefinition> expressions) {
084            CollectionStringBuffer buffer = new CollectionStringBuffer();
085            for (ExpressionDefinition expression : expressions) {
086                buffer.append(expression.getLabel());
087            }
088            return buffer.toString();
089        }
090    
091        @Override
092        public String toString() {
093            StringBuilder sb = new StringBuilder();
094            if (getLanguage() != null) {
095                sb.append(getLanguage()).append("{");
096            }
097            if (getPredicate() != null) {
098                sb.append(getPredicate().toString());
099            }
100            if (getExpressionValue() != null) {
101                sb.append(getExpressionValue().toString());
102            }
103            if (getPredicate() == null && getExpressionValue() == null && getExpression() != null) {
104                sb.append(getExpression());
105            }
106            if (getLanguage() != null) {
107                sb.append("}");
108            }
109            return sb.toString();
110        }
111    
112        public Object evaluate(Exchange exchange) {
113            return evaluate(exchange, Object.class);
114        }
115    
116        public <T> T evaluate(Exchange exchange, Class<T> type) {
117            if (expressionValue == null) {
118                expressionValue = createExpression(exchange.getContext());
119            }
120            ObjectHelper.notNull(expressionValue, "expressionValue");
121            return expressionValue.evaluate(exchange, type);
122        }
123    
124        public void assertMatches(String text, Exchange exchange) throws AssertionError {
125            if (!matches(exchange)) {
126                throw new AssertionError(text + getExpression() + " for exchange: " + exchange);
127            }
128        }
129    
130        public boolean matches(Exchange exchange) {
131            if (predicate == null) {
132                predicate = createPredicate(exchange.getContext());
133            }
134            ObjectHelper.notNull(predicate, "predicate");
135            return predicate.matches(exchange);
136        }
137    
138        public String getLanguage() {
139            return "";
140        }
141    
142        public final Predicate createPredicate(RouteContext routeContext) {
143            return createPredicate(routeContext.getCamelContext());
144        }
145    
146        public Predicate createPredicate(CamelContext camelContext) {
147            if (predicate == null) {
148                if (getExpressionType() != null) {
149                    predicate = getExpressionType().createPredicate(camelContext);
150                } else if (getExpressionValue() != null) {
151                    predicate = new ExpressionToPredicateAdapter(getExpressionValue());
152                } else if (getExpression() != null) {
153                    ObjectHelper.notNull("language", getLanguage());
154                    Language language = camelContext.resolveLanguage(getLanguage());
155                    String exp = getExpression();
156                    // trim if configured to trim
157                    if (exp != null && isTrim()) {
158                        exp = exp.trim();
159                    }
160                    predicate = language.createPredicate(exp);
161                    configurePredicate(camelContext, predicate);
162                }
163            }
164            return predicate;
165        }
166    
167        public final Expression createExpression(RouteContext routeContext) {
168            return createExpression(routeContext.getCamelContext());
169        }
170    
171        public Expression createExpression(CamelContext camelContext) {
172            if (getExpressionValue() == null) {
173                if (getExpressionType() != null) {
174                    setExpressionValue(getExpressionType().createExpression(camelContext));
175                } else if (getExpression() != null) {
176                    ObjectHelper.notNull("language", getLanguage());
177                    Language language = camelContext.resolveLanguage(getLanguage());
178                    String exp = getExpression();
179                    // trim if configured to trim
180                    if (exp != null && isTrim()) {
181                        exp = exp.trim();
182                    }
183                    setExpressionValue(language.createExpression(exp));
184                    configureExpression(camelContext, getExpressionValue());
185                }
186            }
187            return getExpressionValue();
188        }
189    
190        public String getExpression() {
191            return expression;
192        }
193    
194        @Required
195        public void setExpression(String expression) {
196            this.expression = expression;
197        }
198    
199        /**
200         * Gets the value of the id property.
201         */
202        public String getId() {
203            return id;
204        }
205    
206        /**
207         * Sets the value of the id property.
208         */
209        public void setId(String value) {
210            this.id = value;
211        }
212    
213        public Predicate getPredicate() {
214            return predicate;
215        }
216    
217        public Expression getExpressionValue() {
218            return expressionValue;
219        }
220    
221        protected void setExpressionValue(Expression expressionValue) {
222            this.expressionValue = expressionValue;
223        }
224    
225        public ExpressionDefinition getExpressionType() {
226            return expressionType;
227        }
228    
229        public Boolean getTrim() {
230            return trim;
231        }
232    
233        public void setTrim(Boolean trim) {
234            this.trim = trim;
235        }
236    
237        public boolean isTrim() {
238            // trim by default
239            return trim == null || trim;
240        }
241    
242        /**
243         * Returns some descriptive text to describe this node
244         */
245        public String getLabel() {
246            Predicate predicate = getPredicate();
247            if (predicate != null) {
248                return predicate.toString();
249            }
250            Expression expressionValue = getExpressionValue();
251            if (expressionValue != null) {
252                return expressionValue.toString();
253            }
254    
255            String exp = getExpression();
256            return exp != null ? exp : "";
257        }
258    
259        /**
260         * Allows derived classes to set a lazily created expressionType instance
261         * such as if using the {@link org.apache.camel.builder.ExpressionClause}
262         */
263        protected void setExpressionType(ExpressionDefinition expressionType) {
264            this.expressionType = expressionType;
265        }
266    
267        protected void configurePredicate(CamelContext camelContext, Predicate predicate) {
268        }
269    
270        protected void configureExpression(CamelContext camelContext, Expression expression) {
271        }
272    
273        /**
274         * Sets a named property on the object instance using introspection
275         */
276        protected void setProperty(Object bean, String name, Object value) {
277            try {
278                IntrospectionSupport.setProperty(bean, name, value);
279            } catch (Exception e) {
280                throw new IllegalArgumentException("Failed to set property " + name + " on " + bean
281                                                   + ". Reason: " + e, e);
282            }
283        }
284    }