View Javadoc
1   /**
2    * Copyright 2005-2015 The Kuali Foundation
3    *
4    * Licensed under the Educational Community 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.opensource.org/licenses/ecl2.php
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.kuali.rice.krad.uif.view;
17  
18  import org.kuali.rice.krad.datadictionary.uif.UifDictionaryBean;
19  
20  import java.util.List;
21  import java.util.Map;
22  
23  /**
24   * Provides evaluation of expression language statements against a given context
25   *
26   * <p>
27   * Used within the UI framework to allow conditional logic to be configured through
28   * the XML which can alter the values of component properties
29   * </p>
30   *
31   * @author Kuali Rice Team (rice.collab@kuali.org)
32   */
33  public interface ExpressionEvaluator {
34  
35      /**
36       * Indicator that can be added to a property name to indicate the expression result should be added to the
37       * property (assumed to be a collection) instead of replaced
38       */
39      String EMBEDDED_PROPERTY_NAME_ADD_INDICATOR = ".add";
40  
41      /**
42       * Initializes the expression context for the given expression context object
43       *
44       * <p>
45       * The object given here will form the default context for expression terms (terms without any
46       * variable prefix)
47       * </p>
48       *
49       * @param contextObject instance of an Object
50       */
51      void initializeEvaluationContext(Object contextObject);
52  
53      /**
54       * Evaluates any el expressions that are found as a string property value
55       * for the object
56       *
57       * <p>
58       * Using reflection the properties for the object are retrieved and if of
59       * <code>String</code> type the corresponding value is retrieved. If the
60       * value is not empty and contains the el placeholder see
61       * {@link #containsElPlaceholder(String)} then the expression is evaluated
62       * using the given context object and parameters. The evaluated string is
63       * then set as the new property value, or in the case of a template
64       * (expression contained within a literal string), the expression part is
65       * replaced in the property value.
66       * </p>
67       *
68       * <p>
69       * In addition to evaluating any property expressions, any configured
70       * <code>PropertyReplacer</code> for the object are also evaluated and if a
71       * match occurs those property replacements are made
72       * </p>
73       *
74       * @param view view instance being rendered
75       * @param expressionConfigurable object whose properties should be checked for expressions
76       * and evaluated
77       * @param evaluationParameters map of parameters that may appear in expressions, the map
78       * key gives the parameter name that may appear in the expression, and the map value is the object that expression
79       * should evaluate against when that name is found
80       */
81      void evaluateExpressionsOnConfigurable(View view, UifDictionaryBean expressionConfigurable,
82              Map<String, Object> evaluationParameters);
83  
84      /**
85       * Evaluates the given expression template string against the context object
86       * and map of parameters
87       *
88       * <p>
89       * If the template string contains one or more el placeholders (see
90       * {@link #containsElPlaceholder(String)}), the expression contained within
91       * the placeholder will be evaluated and the corresponding value will be
92       * substituted back into the property value where the placeholder occurred.
93       * If no placeholders are found, the string will be returned unchanged
94       * </p>
95       *
96       * @param evaluationParameters map of parameters that may appear in expressions, the map
97       * key gives the parameter name that may appear in the expression, and the map value is the object that expression
98       * should evaluate against when that name is found
99       * @param expressionTemplate string that should be evaluated for el expressions
100      * @return String formed by replacing any el expressions in the original expression template with
101      *         their corresponding evaluation results
102      */
103     String evaluateExpressionTemplate(Map<String, Object> evaluationParameters, String expressionTemplate);
104 
105     /**
106      * Evaluates the configured expression for the given property name (if not exists) on the given configurable
107      *
108      * @param view view instance the configurable is associated with, used to adjust binding prefixes
109      * @param evaluationParameters map that will be exposed as EL parameters
110      * @param expressionConfigurable configurable object to pull and evaluate the expression on
111      * @param propertyName name of the property whose expression should be evaluated
112      * @param removeExpression boolean that indicates whether the expression should be removed after evaluation
113      */
114     void evaluatePropertyExpression(View view, Map<String, Object> evaluationParameters,
115             UifDictionaryBean expressionConfigurable, String propertyName, boolean removeExpression);
116 
117     /**
118      * Evaluates the given el expression against the content object and
119      * parameters, and returns the result of the evaluation
120      *
121      * <p>
122      * The given expression string is assumed to be one el expression and should
123      * not contain the el placeholders. The returned result depends on the
124      * evaluation and what type is returns, for instance a boolean will be
125      * return for a boolean expression, or a string for string expression
126      * </p>
127      *
128      * @param evaluationParameters map of parameters that may appear in expressions, the map
129      * key gives the parameter name that may appear in the expression, and the map value is the object that expression
130      * should evaluate against when that name is found
131      * @param expression el expression to evaluate
132      * @return Object result of the expression evaluation
133      */
134     Object evaluateExpression(Map<String, Object> evaluationParameters, String expression);
135 
136     /**
137      * Indicates whether or not the given string contains the el placeholder
138      * (begin and end delimiters)
139      *
140      * @param value String to check for contained placeholders
141      * @return boolean true if the string contains one or more placeholders, false if it contains none
142      * @see org.kuali.rice.krad.uif.UifConstants#EL_PLACEHOLDER_PREFIX
143      * @see org.kuali.rice.krad.uif.UifConstants#EL_PLACEHOLDER_SUFFIX
144      */
145     boolean containsElPlaceholder(String value);
146 
147     /**
148      * Adjusts the property expressions for a given object
149      *
150      * <p>
151      * The {@link org.kuali.rice.krad.uif.UifConstants#NO_BIND_ADJUST_PREFIX}  prefix will be removed
152      * as this is a placeholder indicating that the property is directly on the form.
153      * The {@link org.kuali.rice.krad.uif.UifConstants#FIELD_PATH_BIND_ADJUST_PREFIX} prefix will be replaced by
154      * the object's field path - this is only applicable to DataFields. The
155      * {@link org.kuali.rice.krad.uif.UifConstants#DEFAULT_PATH_BIND_ADJUST_PREFIX} prefix will be replaced
156      * by the view's default path if it is set.
157      * </p>
158      *
159      * @param view the parent view of the object
160      * @param object Object to adjust property expressions on
161      * @param expression The expression to adjust
162      * @return the adjusted expression String
163      */
164     String replaceBindingPrefixes(View view, Object object, String expression);
165 
166     /**
167      * Pulls expressions within the expressionConfigurable's expression graph and moves them to the property
168      * expressions
169      * map for the expressionConfigurable or a nested expressionConfigurable (for the case of nested expression property
170      * names)
171      *
172      * <p>
173      * Expressions that are configured on properties and pulled out by the {@link org.kuali.rice.krad.uif.util.UifBeanFactoryPostProcessor}
174      * and put in the {@link org.kuali.rice.krad.datadictionary.uif.UifDictionaryBean#getExpressionGraph()} for the bean
175      * that is
176      * at root (non nested) level. Before evaluating the expressions, they need to be moved to the
177      * {@link org.kuali.rice.krad.datadictionary.uif.UifDictionaryBean#getPropertyExpressions()} map for the
178      * expressionConfigurable that
179      * property
180      * is on.
181      * </p>
182      *
183      * @param expressionConfigurable expressionConfigurable instance to process expressions for
184      * @param buildRefreshGraphs indicates whether the expression graphs for component refresh should be built
185      */
186     void populatePropertyExpressionsFromGraph(UifDictionaryBean expressionConfigurable,
187             boolean buildRefreshGraphs);
188 
189     /**
190      * Takes in an expression and a list to be filled in with names(property names)
191      * of controls found in the expression.
192      *
193      * <p>This method returns a js expression which can
194      * be executed on the client to determine if the original exp was satisfied before
195      * interacting with the server - ie, this js expression is equivalent to the one passed in.</p>
196      *
197      * <p>There are limitations on the Spring expression language that can be used as this method.
198      * It is only used to parse expressions which are valid case statements for determining if
199      * some action/processing should be performed.  ONLY Properties, comparison operators, booleans,
200      * strings, matches expression, and boolean logic are supported.  Server constants and calls will be evaluated
201      * early.  The isValueEmpty, listContains, and emptyList custom KRAD functions, however, will be converted
202      * to a js equivalent function.  Properties must be a valid property on the form, and should have a visible control
203      * within the view. </p>
204      *
205      * <p>Example valid exp: "account.name == 'Account Name'"</p>
206      *
207      * @param exp the expression to convert to a js condition
208      * @param controlNames the list to populate with control names found in the expression (these may later be used
209      * to add js change handlers)
210      * @return the converted expression into an equivalent js condition
211      */
212     String parseExpression(String exp, List<String> controlNames, Map<String, Object> context);
213 
214     /**
215      * Find the control names (ie, propertyNames) used in the passed in expression
216      *
217      * @param exp the expression to search
218      * @return the list of control names found (ie, propertyNames)
219      */
220     List<String> findControlNamesInExpression(String exp);
221 }