1. /*
  2. * Copyright 2002,2004 The Apache Software Foundation.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package org.apache.commons.jexl;
  17. import java.util.ArrayList;
  18. import java.util.List;
  19. import org.apache.commons.jexl.parser.SimpleNode;
  20. /**
  21. * Instances of ExpressionImpl are created by the {@link ExpressionFactory},
  22. * and this is the default implementation of the {@link Expression} interface.
  23. *
  24. * @author <a href="mailto:geirm@apache.org">Geir Magnusson Jr.</a>
  25. * @version $Id: ExpressionImpl.java,v 1.11 2004/08/23 14:00:11 dion Exp $
  26. */
  27. class ExpressionImpl implements Expression
  28. {
  29. protected List preResolvers;
  30. protected List postResolvers;
  31. /**
  32. * Original expression - this is just a 'snippet', not a valid
  33. * statement (i.e. foo.bar() vs foo.bar();
  34. */
  35. protected String expression;
  36. /**
  37. * The resulting AST we can call value() on
  38. */
  39. protected SimpleNode node;
  40. /**
  41. * do not let this be generally instantiated with a 'new'
  42. */
  43. ExpressionImpl(String expr, SimpleNode ref)
  44. {
  45. expression = expr;
  46. node = ref;
  47. }
  48. /**
  49. * Evaluate the expression and return the value.
  50. *
  51. * Before JEXL evaluates the expression, any pre-resolvers will be called.
  52. * If the pre-resolver provides a value, it is returned.
  53. * If JEXL evaluates the expression as null, post-resolvers are called
  54. * and any resulting value returned.
  55. *
  56. * @param context Context containing objects/data used for evaluation
  57. * @return value of expression
  58. */
  59. public Object evaluate(JexlContext context)
  60. throws Exception
  61. {
  62. Object val = null;
  63. /*
  64. * if we have pre resolvers, give them a wack
  65. */
  66. if (preResolvers != null)
  67. {
  68. val = tryResolver(preResolvers, context);
  69. if (val != JexlExprResolver.NO_VALUE)
  70. {
  71. return val;
  72. }
  73. }
  74. val = node.value(context);
  75. /*
  76. * if null, call post resolvers
  77. */
  78. if (val == null && postResolvers != null)
  79. {
  80. val = tryResolver(postResolvers, context);
  81. if (val != JexlExprResolver.NO_VALUE)
  82. {
  83. return val;
  84. }
  85. }
  86. return val;
  87. }
  88. /**
  89. * Tries the resolvers in the given resolverlist against the context
  90. *
  91. * @param resolverList list of JexlExprResolvers
  92. * @param context JexlContext to use for evauluation
  93. * @return value (including null) or JexlExprResolver.NO_VALUE
  94. */
  95. protected Object tryResolver(List resolverList, JexlContext context)
  96. {
  97. Object val = JexlExprResolver.NO_VALUE;
  98. String expr = getExpression();
  99. for (int i = 0; i < resolverList.size(); i++)
  100. {
  101. JexlExprResolver jer = (JexlExprResolver) resolverList.get(i);
  102. val = jer.evaluate(context, expr);
  103. /*
  104. * as long as it's not NO_VALUE, return it
  105. */
  106. if (val != JexlExprResolver.NO_VALUE)
  107. {
  108. return val;
  109. }
  110. }
  111. return val;
  112. }
  113. /**
  114. * returns original expression string
  115. */
  116. public String getExpression()
  117. {
  118. return expression;
  119. }
  120. public void addPreResolver(JexlExprResolver resolver)
  121. {
  122. if (preResolvers == null)
  123. {
  124. preResolvers = new ArrayList();
  125. }
  126. preResolvers.add(resolver);
  127. }
  128. /**
  129. * allows addition of a resolver to allow custom interdiction of
  130. * expression evaluation
  131. *
  132. * @param resolver resolver to be called if Jexl expression evaluated to null
  133. */
  134. public void addPostResolver(JexlExprResolver resolver)
  135. {
  136. if (postResolvers == null)
  137. {
  138. postResolvers = new ArrayList();
  139. }
  140. postResolvers.add(resolver);
  141. }
  142. }