18 April 2010

Executing an OGNL expression on an array of Strings

Valid since: op4j 1.0

Description
Execute an OGNL (Object-Graph Navigation Language) expression on each of the elements of an array, obtaining another array with the results of these executions.

Scenario
Our String[] riverNames variable contains the names of several rivers in a remote part of the world:
// riverNames == ARRAY [ "Eume", "Ulla", "Tambre" ]
But we want to display these rivers in our interface with the "River" prefix, so we need to create another array containing Strings like:
// rivers == ARRAY [ "River Eume", "River Ulla", "River Tambre" ]

Recipe
We can execute an OGNL expression on each array element in order to create the Strings we really want. This can be easily done by mapping a function from the op4j-ognl extension:

String[] rivers = 
    Op.on(riverNames).map(FnOgnl.evalForString("'River ' + #target")).get();

When executing an OGNL expression, FnOgnl sets the target object as the root of the expression, but it also makes it available at the predefined #target variable (as you can see above). If the expression needed any parameters, the #param array variable would have contained them. Finally, an #index variable contains the iteration index in case you need it.

Comments
But let's go further... what if we wanted to convert this expression we have just created into a function called riverize so that we can apply it to any array of river names we might get?

Easy. Let's first create the river function by using a function expression (as opposite to the usual operation expressions):
Function<String[],String[]> riverize = 
    Fn.onArrayOf(Types.STRING).
        map(FnOgnl.evalForString("'River ' + #target")).get();
Our riverize function is of type Function<String[],String[]>, which means that it receives a String[] input (first type parameter) and returns another String[] object as a result (second type parameter). Let's execute it:
// moreRiverNames == ARRAY [ "Eo", "Sil" ]
String[] moreRivers = riverize.execute(moreRiverNames);
// moreRivers == ARRAY [ "River Eo", "River Sil" ]
Perfect!

No comments:

Post a Comment