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