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.builder.PredicateBuilder;
037    import org.apache.camel.impl.DefaultRouteContext;
038    import org.apache.camel.spi.Language;
039    import org.apache.camel.spi.RouteContext;
040    import org.apache.camel.util.CollectionStringBuffer;
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 $Revision: 751655 $
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        @XmlTransient
060        private Predicate predicate;
061        @XmlTransient
062        private Expression expressionValue;
063        @XmlTransient
064        private ExpressionDefinition expressionType;
065    
066        public ExpressionDefinition() {
067        }
068    
069        public ExpressionDefinition(String expression) {
070            this.expression = expression;
071        }
072    
073        public ExpressionDefinition(Predicate predicate) {
074            this.predicate = predicate;
075        }
076    
077        public ExpressionDefinition(Expression expression) {
078            this.expressionValue = expression;
079        }
080    
081        public static String getLabel(List<ExpressionDefinition> expressions) {
082            CollectionStringBuffer buffer = new CollectionStringBuffer();
083            for (ExpressionDefinition expression : expressions) {
084                buffer.append(expression.getLabel());
085            }
086            return buffer.toString();
087        }
088    
089        @Override
090        public String toString() {
091            StringBuilder sb = new StringBuilder();
092            if (getLanguage() != null) {
093                sb.append(getLanguage()).append("{");
094            }
095            if (getExpression() != null) {
096                sb.append(getExpression());
097            }
098            if (getPredicate() != null) {
099                sb.append(getPredicate().toString());
100            }
101            if (getExpressionValue() != null) {
102                sb.append(getExpressionValue().toString());
103            }
104            if (getLanguage() != null) {
105                sb.append("}");
106            }
107            return sb.toString();
108        }
109    
110        public Object evaluate(Exchange exchange) {
111            if (expressionValue == null) {
112                RouteContext routeContext = new DefaultRouteContext(exchange.getContext());
113                expressionValue = createExpression(routeContext);
114            }
115            ObjectHelper.notNull(expressionValue, "expressionValue");
116            return expressionValue.evaluate(exchange);
117        }
118    
119        public <T> T evaluate(Exchange exchange, Class<T> type) {
120            if (expressionValue == null) {
121                RouteContext routeContext = new DefaultRouteContext(exchange.getContext());
122                expressionValue = createExpression(routeContext);
123            }
124            ObjectHelper.notNull(expressionValue, "expressionValue");
125            return expressionValue.evaluate(exchange, type);
126        }
127    
128        public void assertMatches(String text, Exchange exchange) throws AssertionError {
129            if (!matches(exchange)) {
130                throw new AssertionError(text + getExpression() + " for exchange: " + exchange);
131            }
132        }
133    
134        public boolean matches(Exchange exchange) {
135            if (predicate == null) {
136                RouteContext routeContext = new DefaultRouteContext(exchange.getContext());
137                predicate = createPredicate(routeContext);
138            }
139            ObjectHelper.notNull(predicate, "predicate");
140            return predicate.matches(exchange);
141        }
142    
143        public String getLanguage() {
144            return "";
145        }
146    
147        public Predicate createPredicate(RouteContext routeContext) {
148            if (predicate == null) {
149                if (expressionType != null) {
150                    predicate = expressionType.createPredicate(routeContext);
151                } else if (expressionValue != null) {
152                    predicate = PredicateBuilder.toPredicate(expressionValue);
153                } else if (getExpression() != null) {
154                    ObjectHelper.notNull("language", getLanguage());
155                    CamelContext camelContext = routeContext.getCamelContext();
156                    Language language = camelContext.resolveLanguage(getLanguage());
157                    predicate = language.createPredicate(getExpression());
158                    configurePredicate(routeContext, predicate);
159                }
160            }
161            return predicate;
162        }
163    
164        public Expression createExpression(RouteContext routeContext) {
165            if (expressionValue == null) {
166                if (expressionType != null) {
167                    expressionValue = expressionType.createExpression(routeContext);
168                } else if (getExpression() != null) {
169                    ObjectHelper.notNull("language", getLanguage());
170                    CamelContext camelContext = routeContext.getCamelContext();
171                    Language language = camelContext.resolveLanguage(getLanguage());
172                    expressionValue = language.createExpression(getExpression());
173                    configureExpression(routeContext, expressionValue);
174                }
175            }
176            return expressionValue;
177        }
178    
179        public String getExpression() {
180            return expression;
181        }
182    
183        public void setExpression(String expression) {
184            this.expression = expression;
185        }
186    
187        /**
188         * Gets the value of the id property.
189         */
190        public String getId() {
191            return id;
192        }
193    
194        /**
195         * Sets the value of the id property.
196         */
197        public void setId(String value) {
198            this.id = value;
199        }
200    
201        public Predicate getPredicate() {
202            return predicate;
203        }
204    
205        public Expression getExpressionValue() {
206            return expressionValue;
207        }
208    
209        protected void setExpressionValue(Expression expressionValue) {
210            this.expressionValue = expressionValue;
211        }
212    
213        /**
214         * Returns some descriptive text to describe this node
215         */
216        public String getLabel() {
217            String language = getExpression();
218            if (ObjectHelper.isEmpty(language)) {
219                Predicate predicate = getPredicate();
220                if (predicate != null) {
221                    return predicate.toString();
222                }
223                Expression expressionValue = getExpressionValue();
224                if (expressionValue != null) {
225                    return expressionValue.toString();
226                }
227            } else {
228                return language;
229            }
230            return "";
231        }
232    
233        /**
234         * Allows derived classes to set a lazily created expressionType instance
235         * such as if using the {@link org.apache.camel.builder.ExpressionClause}
236         */
237        protected void setExpressionType(ExpressionDefinition expressionType) {
238            this.expressionType = expressionType;
239        }
240    
241        protected void configurePredicate(RouteContext routeContext, Predicate predicate) {
242        }
243    
244        protected void configureExpression(RouteContext routeContext, Expression expression) {
245        }
246    
247        /**
248         * Sets a named property on the object instance using introspection
249         */
250        protected void setProperty(Object bean, String name, Object value) {
251            try {
252                IntrospectionSupport.setProperty(bean, name, value);
253            } catch (Exception e) {
254                throw new IllegalArgumentException("Failed to set property " + name + " on " + bean
255                                                   + ". Reason: " + e, e);
256            }
257        }
258    }