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