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 }