Putting a simple expression language into java
Asked Answered
F

4

6

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 ?

Faqir answered 8/6, 2011 at 20:46 Comment(0)
A
8

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.

Aldous answered 8/6, 2011 at 20:55 Comment(2)
This might be the right solution, but I dont know Im struggling to get my head round this.Faqir
OK I will give more details in answerAldous
G
2

I'd look into FreeMarker. It is a templating engine. You can pass your string with the el constructs to Freemarker and give it the objects you want to bind to your string and it will give you a string back.

Geniagenial answered 8/6, 2011 at 20:51 Comment(1)
Maybe but I dont want to output something from Java, I want to go the other way, user enters an expression that is converted into java ( I think)Faqir
A
0

One option would be to use a parser generator.

ANTLR is one such tool for Java. If you're a novice at creating grammars, you'll find the grammar IDE ANTLRWorks useful.

Arak answered 8/6, 2011 at 20:50 Comment(1)
Could be, depending on your familiarity with grammars. Whether it's merited depends partly on the complexity of the grammar you want to support.Arak
S
0

I guess you are looking for a template engine

Strophanthus answered 8/6, 2011 at 20:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.