Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Putting a simple expression language into java

Im my Java application, users can specify how to name their files from a series of metadata fields. i.e

%artist% - %album% - %disctotal%

My code then parses these fields and renames file accoringly. But I want the user to be able to use an 'expression languge' so they can say things like:

$if(%disctotal% >= 01,%discno%) 

Use ifelse, compare length and case and so on.

I dont want to write this from scratch, is there something that offers me this that I can just plugin to my code?

EDIT:I think Ive had some good replies, but my knowledge is letting me down. Lets simplify the issue I want the user to be able to write

$if(%disctotal% >= 01,%discno%)

into a field in a gui.

Then later on in my Java code I want to be able to apply this expression to a set of files, so for each file I have the value of disctotal, and discno but I want to be able to convert the expression into something like

if(discTotal >=1) { return discNo } else { return "" }

What I dont want to do is have to write the code that recognises the string (" $if(%disctotal% >= 01,%discno%)" is an if statement because this is akward to do.

Then expanding on this I would like the expression to allow things such as capitalizing oof fields, checking lengths of fields and so on.

Alternatively: Perhaps it should work this way, the user enters the expression, then at a later date for each file the Java code replaces each variable with the real value

i.e $if(%disctotal% >= 01,%discno%) -> $if(2 >= 01,1)

then this is passed to the exopression language to parse and give a result,

Is this the Javascript idea ?

like image 282
Paul Taylor Avatar asked Jun 08 '11 20:06

Paul Taylor


1 Answers

How about using the JavaScript engine that is bundled with Java 1.6?

You can see how you would pass in all the parameters:

ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("JavaScript");
engine.put("artist", artist);
...

You would read back the value using

ScriptEngine.get(...)

The final bit of glue would be to surround the user's expression with a function declaration, and write an expression that calls the function and assigns the result to a well known variable.

So to start experimenting, lets have a function to test expressions out:

private static void printResult(final ScriptEngine jsEngine, String name, String expr) throws ScriptException {
    Object result = jsEngine.eval(expr);
    System.out.println(name + " result: " + result + "; expr: " + expr);
}

Now let's call it:

public static void main(String[] args) throws Exception {
    ScriptEngineManager sem = new ScriptEngineManager();
    ScriptEngine jsEngine = sem.getEngineByName("JavaScript");
    printResult(jsEngine, "Hello World", "'Hello World'");
    printResult(jsEngine, "Simple Math", "123 + 456");
}

This produces:

Hello World result: Hello World; expr: 'Hello World'
Simple Math result: 579.0; expr: 123 + 456

Now lets try with your usecase:

public static void main(String[] args) throws Exception {
    ScriptEngineManager sem = new ScriptEngineManager();
    ScriptEngine jsEngine = sem.getEngineByName("JavaScript");

    String expr = "artist + '-' + album + (disktotal > 1 ? ('-D' + diskno) : '')";

    jsEngine.put("artist", "U2");
    jsEngine.put("album", "The Joshua Tree");
    jsEngine.put("disktotal", 1);
    jsEngine.put("diskno", 1);
    printResult(jsEngine, "Single Disk", expr);

    jsEngine.put("artist", "Tori Amos");
    jsEngine.put("album", "To Venus and Back");
    jsEngine.put("disktotal", 2);
    jsEngine.put("diskno", 2);
    printResult(jsEngine, "Muti-Disk", expr);
}

Produces result:

Single Disk result: U2-The Joshua Tree; expr: ...
Muti-Disk result: Tori Amos-To Venus and Back-D2; expr: ...

Notice how Tori's has 'D2' at the end.

like image 85
Dilum Ranatunga Avatar answered Oct 08 '22 16:10

Dilum Ranatunga