Mark Estrada
Mark Estrada

Reputation: 9191

Dynamic expression evaluator at runtime

I have an app that I wanted to customize using some sort of expression evaluator. I wanted to change certain parts of the app without recompiling my code. I am thinking of using groovy expression.

Say for example, I have a feature that can be enabled/disabled by supplying expression:

In this case, this feature will be enabled

Example 1:
EXPRESSION : status = part-time || status = hourly
INPUT: status = part-time

In this case, this feature will be disabled

Example 2:
EXPRESSION : status = part-time || status = hourly
INPUT: status = permanent

Users are required to enter an expression and an Input. Expression should evaluate to a boolean expression

They can also change the expression and the program will pick up this by some evaluation. These expressions by the way are documented and is exposed by me to the user of my application

Example 3:
EXPRESSION : salary > 10000
INPUT: salary = 7000

I have seen a program before that does this and they say that they uses groovy under the hood. But I cannot get my head wrap around the concept.

Can somebody please give me an idea?

Upvotes: 5

Views: 2897

Answers (2)

Marmite Bomber
Marmite Bomber

Reputation: 21073

Alternative approach using evaluate. Your variables are defined in binding, evaluate contains the expression:

// setup binding
def emp = [status:'permanent', name:'Hugo']
def binding = new Binding()
binding.status = 'permanent'
binding.status2 = 'part-time'
binding.salary = 7000
binding.employee = emp
println binding.variables

// evaluate the script
def ret = new GroovyShell(binding).evaluate("status == 'part-time' || status == 'hourly'")
println ret

ret = new GroovyShell(binding).evaluate("status2 == 'part-time' || status2 == 'hourly'")
println ret

ret = new GroovyShell(binding).evaluate("salary > 10000")
println ret

ret = new GroovyShell(binding).evaluate("employee.status == 'permanent' || employee.status == 'hourly'")
println ret

returns

[status:permanent, status2:part-time, salary:7000, employee:[status:permanent, name:Hugo]]
false
true
false
true

Upvotes: 3

daggett
daggett

Reputation: 28564

the usual call of groovy script:

import groovy.lang.Binding;
import groovy.lang.Script;
import groovy.lang.GroovyShell;

Binding binding = new Binding();
binding.setProperty("status", "part-time");
GroovyShell shell = new GroovyShell(binding);
Script script = shell.parse(" status == 'part-time' || status == 'hourly' ");
Object result = script.run();

after run the binding will be populated with new values of the variables.

you can cache the parsed script (or class of the parsed script) because parsing/compiling is expensive process.

as alternative - the easiest script evaluation:

Object result = groovy.util.Eval.me("status", "part-time", 
    " status == 'part-time' || status == 'hourly' ");

Upvotes: 2

Related Questions