001/** 002 * Copyright 2005-2018 The Kuali Foundation 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.kuali.rice.krad.uif.view; 017 018import org.kuali.rice.krad.datadictionary.uif.UifDictionaryBean; 019 020import java.util.List; 021import java.util.Map; 022 023/** 024 * Provides evaluation of expression language statements against a given context 025 * 026 * <p> 027 * Used within the UI framework to allow conditional logic to be configured through 028 * the XML which can alter the values of component properties 029 * </p> 030 * 031 * @author Kuali Rice Team (rice.collab@kuali.org) 032 */ 033public interface ExpressionEvaluator { 034 035 /** 036 * Indicator that can be added to a property name to indicate the expression result should be added to the 037 * property (assumed to be a collection) instead of replaced 038 */ 039 String EMBEDDED_PROPERTY_NAME_ADD_INDICATOR = ".add"; 040 041 /** 042 * Initializes the expression context for the given expression context object 043 * 044 * <p> 045 * The object given here will form the default context for expression terms (terms without any 046 * variable prefix) 047 * </p> 048 * 049 * @param contextObject instance of an Object 050 */ 051 void initializeEvaluationContext(Object contextObject); 052 053 /** 054 * Evaluates any el expressions that are found as a string property value 055 * for the object 056 * 057 * <p> 058 * Using reflection the properties for the object are retrieved and if of 059 * <code>String</code> type the corresponding value is retrieved. If the 060 * value is not empty and contains the el placeholder see 061 * {@link #containsElPlaceholder(String)} then the expression is evaluated 062 * using the given context object and parameters. The evaluated string is 063 * then set as the new property value, or in the case of a template 064 * (expression contained within a literal string), the expression part is 065 * replaced in the property value. 066 * </p> 067 * 068 * <p> 069 * In addition to evaluating any property expressions, any configured 070 * <code>PropertyReplacer</code> for the object are also evaluated and if a 071 * match occurs those property replacements are made 072 * </p> 073 * 074 * @param view view instance being rendered 075 * @param expressionConfigurable object whose properties should be checked for expressions 076 * and evaluated 077 * @param evaluationParameters map of parameters that may appear in expressions, the map 078 * key gives the parameter name that may appear in the expression, and the map value is the object that expression 079 * should evaluate against when that name is found 080 */ 081 void evaluateExpressionsOnConfigurable(View view, UifDictionaryBean expressionConfigurable, 082 Map<String, Object> evaluationParameters); 083 084 /** 085 * Evaluates the given expression template string against the context object 086 * and map of parameters 087 * 088 * <p> 089 * If the template string contains one or more el placeholders (see 090 * {@link #containsElPlaceholder(String)}), the expression contained within 091 * the placeholder will be evaluated and the corresponding value will be 092 * substituted back into the property value where the placeholder occurred. 093 * If no placeholders are found, the string will be returned unchanged 094 * </p> 095 * 096 * @param evaluationParameters map of parameters that may appear in expressions, the map 097 * key gives the parameter name that may appear in the expression, and the map value is the object that expression 098 * should evaluate against when that name is found 099 * @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}