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