001    /*******************************************************************************
002     * Portions created by Sebastian Thomschke are copyright (c) 2005-2012 Sebastian
003     * Thomschke.
004     * 
005     * All Rights Reserved. This program and the accompanying materials
006     * are made available under the terms of the Eclipse Public License v1.0
007     * which accompanies this distribution, and is available at
008     * http://www.eclipse.org/legal/epl-v10.html
009     * 
010     * Contributors:
011     *     Sebastian Thomschke - initial implementation.
012     *******************************************************************************/
013    package net.sf.oval.expression;
014    
015    import groovy.lang.Binding;
016    import groovy.lang.GroovyShell;
017    import groovy.lang.Script;
018    
019    import java.util.Map;
020    import java.util.Map.Entry;
021    
022    import net.sf.oval.exception.ExpressionEvaluationException;
023    import net.sf.oval.internal.Log;
024    import net.sf.oval.internal.util.ObjectCache;
025    import net.sf.oval.internal.util.ThreadLocalObjectCache;
026    
027    /**
028     * @author Sebastian Thomschke
029     */
030    public class ExpressionLanguageGroovyImpl implements ExpressionLanguage
031    {
032            private static final Log LOG = Log.getLog(ExpressionLanguageGroovyImpl.class);
033    
034            private static final GroovyShell GROOVY_SHELL = new GroovyShell();
035    
036            private final ThreadLocalObjectCache<String, Script> threadScriptCache = new ThreadLocalObjectCache<String, Script>();
037    
038            /**
039             * {@inheritDoc}
040             */
041            public Object evaluate(final String expression, final Map<String, ? > values) throws ExpressionEvaluationException
042            {
043                    LOG.debug("Evaluating Groovy expression: {1}", expression);
044                    try
045                    {
046                            final ObjectCache<String, Script> scriptCache = threadScriptCache.get();
047                            Script script = scriptCache.get(expression);
048                            if (script == null)
049                            {
050                                    script = GROOVY_SHELL.parse(expression);
051                                    scriptCache.put(expression, script);
052                            }
053    
054                            final Binding binding = new Binding();
055                            for (final Entry<String, ? > entry : values.entrySet())
056                                    binding.setVariable(entry.getKey(), entry.getValue());
057                            script.setBinding(binding);
058                            return script.run();
059                    }
060                    catch (final Exception ex)
061                    {
062                            throw new ExpressionEvaluationException("Evaluating script with Groovy failed.", ex);
063                    }
064            }
065    
066            /**
067             * {@inheritDoc}
068             */
069            public boolean evaluateAsBoolean(final String expression, final Map<String, ? > values)
070                            throws ExpressionEvaluationException
071            {
072                    final Object result = evaluate(expression, values);
073                    if (!(result instanceof Boolean))
074                            throw new ExpressionEvaluationException("The script must return a boolean value.");
075                    return (Boolean) result;
076            }
077    }