Question

In this question I asked about supporting an expression language and used the Javascript idea sucessfully Putting a simple expression language into java

But the Javascript expressions required have become quite verbose and Im trying to work out how I can use ScriptEngine to create javascript functions that I can refer to in my expressions so that the expressions can be shorter.

So far I've hacked a solution by using reexp on the user entered string which can include a pseudo function called ifempty which I then convert to the javascript before passing to script engine

public final String formatFromMask(String mask,Song exampleSong)
    {
        mask = convertPsuedoFunctions(mask);
        try
        {
            ScriptEngineManager manager = new ScriptEngineManager();
            ScriptEngine engine = manager.getEngineByName("JavaScript");
            for(SongFieldName next:SongFieldName.values())
            {
                engine.put(next.getScriptVar(),exampleSong.getFieldValueOrEmptyString(next.getSongFieldKey()));
            }
            Object result = engine.eval(mask);
            return (String)result;
        }
        catch(ScriptException se)
        {
            se.printStackTrace();
        }
        return "";
    }


    private String convertPsuedoFunctions(String mask)
    {
        //i.e ifnotempty(artist,' - ') -> (artist.length>0 ? artist + ' - ' : '')
        mask=mask.replaceAll("ifnotempty\\(([a-z]*)\\,('.*')\\)",
                             "($1.length>0 ? $1 + $2 : '')");

        return mask;
    }

which could parse an expression such as

ifnotempty(album,'/')
+ ifnotempty(artist,' - ')
+ ifnotempty(album,' - ')
+ ifnotempty(track,' - ')
+ ifnotempty(title,'')

but I was wondering about a proper solution, whereby I actually create a real javascript function.

Was it helpful?

Solution

Why not creating a real Javascript function that you add to the script?

function ifnotempty(value,sep){
    return value != undefined && value.length > 0 ? value + sep : '';
}

So your function becomes:

private String convertPsuedoFunctions(String mask)
{
    return 
         "function ifnotempty(value,sep){return value!=undefined&&value.length>0?value+sep:'';}"
         + mask;
}

Additionally you can create a file with some default functions you support and prepend that to the users script. Just like above. But instead of one hardcoded function, you read the file into a String.

private static final String defaultFunctions = 
     com.google.common.io.Files.toString(new File("functions.js"),Charsets.US_ASCII);

private String convertPsuedoFunctions(String mask)
{
    return defaultFunctions + mask;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top