001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.expression;
016    
017    import com.liferay.portal.kernel.expression.Expression;
018    import com.liferay.portal.kernel.expression.ExpressionEvaluationException;
019    import com.liferay.portal.kernel.expression.VariableDependencies;
020    import com.liferay.portal.kernel.util.MathUtil;
021    
022    import java.util.ArrayList;
023    import java.util.HashMap;
024    import java.util.List;
025    import java.util.Map;
026    import java.util.TreeMap;
027    
028    import org.codehaus.janino.ExpressionEvaluator;
029    
030    /**
031     * @author Miguel Angelo Caldas Gallindo
032     */
033    public class ExpressionImpl<T> implements Expression<T> {
034    
035            public ExpressionImpl(String expressionString, Class<T> expressionClass) {
036                    _expressionString = expressionString;
037                    _expressionClass = expressionClass;
038    
039                    List<String> variableNames = _variableNamesExtractor.extract(
040                            expressionString);
041    
042                    for (String variableName : variableNames) {
043                            Variable variable = new Variable(variableName);
044    
045                            _variables.put(variableName, variable);
046                    }
047            }
048    
049            @Override
050            public T evaluate() throws ExpressionEvaluationException {
051                    try {
052                            ExpressionEvaluator expressionEvaluator = new ExpressionEvaluator();
053    
054                            expressionEvaluator.setExpressionType(_expressionClass);
055                            expressionEvaluator.setExtendedClass(MathUtil.class);
056                            expressionEvaluator.setParameters(
057                                    getVariableNames(), getVariableClasses());
058    
059                            expressionEvaluator.cook(_expressionString);
060    
061                            return (T)expressionEvaluator.evaluate(getVariableValues());
062                    }
063                    catch (Exception e) {
064                            throw new ExpressionEvaluationException(e);
065                    }
066            }
067    
068            @Override
069            public Map<String, VariableDependencies> getVariableDependenciesMap() {
070                    Map<String, VariableDependencies> variableDependenciesMap =
071                            new HashMap<String, VariableDependencies>();
072    
073                    for (Variable variable : _variables.values()) {
074                            populateVariableDependenciesMap(variable, variableDependenciesMap);
075                    }
076    
077                    return variableDependenciesMap;
078            }
079    
080            @Override
081            public void setBooleanVariableValue(
082                    String variableName, Boolean variableValue) {
083    
084                    setVariableValue(variableName, variableValue, Boolean.class);
085            }
086    
087            @Override
088            public void setDoubleVariableValue(
089                    String variableName, Double variableValue) {
090    
091                    setVariableValue(variableName, variableValue, Double.class);
092            }
093    
094            @Override
095            public void setExpressionStringVariableValue(
096                    String variableName, String variableValue, Class<?> variableClass) {
097    
098                    Variable variable = _variables.get(variableName);
099    
100                    if (variable == null) {
101                            return;
102                    }
103    
104                    variable.setExpressionString(variableValue);
105                    variable.setVariableClass(variableClass);
106            }
107    
108            @Override
109            public void setFloatVariableValue(
110                    String variableName, Float variableValue) {
111    
112                    setVariableValue(variableName, variableValue, Float.class);
113            }
114    
115            @Override
116            public void setIntegerVariableValue(
117                    String variableName, Integer variableValue) {
118    
119                    setVariableValue(variableName, variableValue, Integer.class);
120            }
121    
122            @Override
123            public void setLongVariableValue(String variableName, Long variableValue) {
124                    setVariableValue(variableName, variableValue, Long.class);
125            }
126    
127            @Override
128            public void setStringVariableValue(
129                    String variableName, String variableValue) {
130    
131                    setVariableValue(variableName, variableValue, String.class);
132            }
133    
134            @Override
135            public void setVariableValue(
136                    String variableName, Object variableValue, Class<?> variableClass) {
137    
138                    Variable variable = _variables.get(variableName);
139    
140                    if (variable == null) {
141                            return;
142                    }
143    
144                    variable.setValue(variableValue);
145                    variable.setVariableClass(variableClass);
146            }
147    
148            protected <V> Expression<V> getExpression(
149                            String expressionString, Class<V> expressionType)
150                    throws ExpressionEvaluationException {
151    
152                    Expression<V> expression = new ExpressionImpl<V>(
153                            expressionString, expressionType);
154    
155                    List<String> variableNames = _variableNamesExtractor.extract(
156                            expressionString);
157    
158                    for (String variableName : variableNames) {
159                            Variable variable = _variables.get(variableName);
160    
161                            expression.setVariableValue(
162                                    variableName, getVariableValue(variable),
163                                    variable.getVariableClass());
164                    }
165    
166                    return expression;
167            }
168    
169            protected Expression<?> getExpression(Variable variable)
170                    throws ExpressionEvaluationException {
171    
172                    if (variable.getExpressionString() == null) {
173                            return null;
174                    }
175    
176                    Expression<?> expression = getExpression(
177                            variable.getExpressionString(), variable.getVariableClass());
178    
179                    return expression;
180            }
181    
182            protected Class<?>[] getVariableClasses() {
183                    List<Class<?>> variableClasses = new ArrayList<Class<?>>();
184    
185                    for (Variable variable : _variables.values()) {
186                            variableClasses.add(variable.getVariableClass());
187                    }
188    
189                    return variableClasses.toArray(new Class<?>[variableClasses.size()]);
190            }
191    
192            protected String[] getVariableNames() {
193                    List<String> variableNames = new ArrayList<String>();
194    
195                    for (Variable variable : _variables.values()) {
196                            variableNames.add(variable.getName());
197                    }
198    
199                    return variableNames.toArray(new String[variableNames.size()]);
200            }
201    
202            protected Object getVariableValue(Variable variable)
203                    throws ExpressionEvaluationException {
204    
205                    Object variableValue = _variableValues.get(variable.getName());
206    
207                    if (variableValue != null) {
208                            return variableValue;
209                    }
210    
211                    Expression<?> expression = getExpression(variable);
212    
213                    if (expression == null) {
214                            return variable.getValue();
215                    }
216    
217                    variableValue = expression.evaluate();
218    
219                    _variableValues.put(variable.getName(), variableValue);
220    
221                    return variableValue;
222            }
223    
224            protected Object[] getVariableValues()
225                    throws ExpressionEvaluationException {
226    
227                    List<Object> variableValues = new ArrayList<Object>();
228    
229                    for (Variable variable : _variables.values()) {
230                            Object variableValue = getVariableValue(variable);
231    
232                            variableValues.add(variableValue);
233                    }
234    
235                    return variableValues.toArray(new Object[variableValues.size()]);
236            }
237    
238            protected VariableDependencies populateVariableDependenciesMap(
239                    Variable variable,
240                    Map<String, VariableDependencies> variableDependenciesMap) {
241    
242                    VariableDependencies variableDependencies = variableDependenciesMap.get(
243                            variable.getName());
244    
245                    if (variableDependencies != null) {
246                            return variableDependencies;
247                    }
248    
249                    variableDependencies = new VariableDependencies(variable.getName());
250    
251                    if (variable.getExpressionString() != null) {
252                            List<String> variableNames = _variableNamesExtractor.extract(
253                                    variable.getExpressionString());
254    
255                            for (String variableName : variableNames) {
256                                    VariableDependencies variableVariableDependencies =
257                                            populateVariableDependenciesMap(
258                                                    _variables.get(variableName), variableDependenciesMap);
259    
260                                    variableVariableDependencies.addAffectedVariable(
261                                            variableDependencies.getVariableName());
262                                    variableDependencies.addRequiredVariable(
263                                            variableVariableDependencies.getVariableName());
264                            }
265                    }
266    
267                    variableDependenciesMap.put(variable.getName(), variableDependencies);
268    
269                    return variableDependencies;
270            }
271    
272            private final Class<?> _expressionClass;
273            private final String _expressionString;
274            private final VariableNamesExtractor _variableNamesExtractor =
275                    new VariableNamesExtractor();
276            private final Map<String, Variable> _variables =
277                    new TreeMap<String, Variable>();
278            private final Map<String, Object> _variableValues =
279                    new HashMap<String, Object>();
280    
281    }