Such expression evaluation becomes way too complicated and for example
in your case requires "import java.util.Date" to be included into the
expression definition. IMO, in such cases it is better to have two or
more getters created using PojoUtils and call them as necessary
depending on the described logic.
Thank you,
Vlad
On 12/2/15 21:26, Chinmay Kolhatkar wrote:
Hi Vlad,
Sure. Here is the example of than one POJO used:
Consider a input POJO as following:
class InputPOJO {
int id;
Date dob;
}
Consider another POJO object, for the sake of discussion is, comming from a
database:
class InputDB {
int id;
Date dob;
}
Requirement is that I want to find the age of the person under following
circumstances:
1) Input POJO may or may not have it. It might be null.
2) If input POJO has it, it should be picked up over DB one.
In such a case, lets say I have 2 placeholder: “inp” & “db” for Input POJO
and DB object respectively.
The expression would now become:
(${inp.dob} == null) ? (new Date().getYear() - ${db.dob}.getYear()) :
(new Date().getYear() - ${inp.dob}.getYear())
The code using the ExpressionEvaluator.java I pasted before would look like
following:
InputPOJO inp = new InputPOJO();
inp.dob = null;
DBPOJO db = new DBPOJO();
db.dob = new Date(1988-1900, 2, 11);
ExpressionEvaluator ee = new ExpressionEvaluator();
ee.addDefaultImports(new String[]{"java.util.Date"});
ee.setInputObjectPlaceholders(new String[]{"inp", "db"}, new
Class[]{InputPOJO.class, DBPOJO.class});
String expression = "(${inp.dob} == null) ? (new Date().getYear()
- ${db.dob}.getYear()) : (new Date().getYear() -
${inp.dob}.getYear())";
ExpressionEvaluator.DataGetter<Integer> getter =
ee.createGetter(expression, Integer.class);
// null dob
inp.dob = null;
Integer age = getter.get(inp, db);
System.out.println("Age is: " + age);
// same dob
inp.dob = new Date(1988-1900, 2, 11);
age = getter.get(inp, db);
System.out.println("Age is: " + age);
I hope this clarifies the case. As of now I see requirement for only 2 such
objects being input. But in future I might have more than 2 of them as well.
Can above be done using POJOUtils?
Considering such a use case, would you suggest the approach I took is
correct one OR suggest any better approach is there?
Thanks,
Chinmay.
~ Chinmay.
On Thu, Dec 3, 2015 at 12:28 AM, Vlad Rozov <[email protected]> wrote:
In the example there is only one Pojo object. Can you please provide an
example/use case with two Pojo objects?
Thank you,
Vlad
On 12/2/15 10:00, Chinmay Kolhatkar wrote:
Hi Vlad,
I had a look at pojoutils. It can cater for getter method taking a single
pojo object as param.
What I need is atleast 2 pojo objects from which final result will be
derived as per expression.
Hence I wrote getter using janino which can takes 'n' number of pojo
objects as params as work off the expression.
This might possibly be a extension to pojoutils.
Please correct me if I'm wrong.
- Chinmay.
On 2 Dec 2015 22:07, "Vlad Rozov" <[email protected]> wrote:
The use case is already fully covered by PojoUtils that is part of Malhar.
Please take a look and let me know if you have any questions how to use
it.
Thank you,
Vlad
On 12/2/15 02:50, Chinmay Kolhatkar wrote:
Hi All,
We’re evaluating a expression evaluator for our use case.
*Example Use Case:*
The expressions needs to contain Java specific code for evaluating once
and running the same for every tuple.
For e.g. a POJO has following definition:
|public class POJO { String firstname; // Firstname String lastname; //
Lastname Date dob; // Date of birth } |
From this POJO, we need to generate fullname as concatenation of
firstname & lastname and age which will be derived from dob field.
The expressions for those might look like following:
For full name : ${inp.firstname} + “ “ + ${inp.lastname}
For Age : new Date().getYear() - ${inp.dob}.getYear()
Currently, I have a implementation using Janino library for expression
evaluation. Code (ExpressionEvaluator.java) and Test code (Main.java)
attached.
As performance is an important concern, we chose a custom evaluator
using
Janino’s fast script evaluator.
*Design of the custom expression evaluator:*
/ExpressionEvaluator class is used for evaluating expressions
which takes multiple parameter object and the result is returned
for that expression./
/
/
/The way to reference a variable in an object is
${placeholder.varname}./
/The variable will be resolved to its accessible variable or
getter method in order. After this the variable can be used as if
its a Java variable./
/
/
/ExpressionEvaluator also allows you to set extra imports that
needs to be added over default is java.lang.*/
/
/
/ExpressionEvaluator needs to be configured with following
configurations as minimal configuration:/
/1. Mapping of input object place holders to it corresponding
types./
/ This can be done with setInputObjectPlaceholders method./
/2. Return type of of expression eveluation./
/3. Expression to be evaluated. This is a standard java expression
except for referencing the variable inside object JEL syntax needs
to be used i.e. ${objectPlaceHolder.varName}/
*Example Use of custom expression evaluator:*
|ExpressionEveluator ee = new ExpressionEvaluator(); // Let expression
evaluator know what are the object mappings present in expressions and
their class types. ee.setInputObjectPlaceholders(new String[]{"input"},
new
Class[]{Test.class}); // Generate expression for finding age from Date
object. String expression = "${input.firstname} + \" \" +
${input.lastname}"; ExpressionEvaluator.DataGetter<String> getter4 =
ee.createGetter(expression, String.class); inp1.firstname = "ABC";
inp1.lastname = "XYZ"; String fullname = getter4.get(inp1);
System.out.println("Fullname is: " + fullname); |
*Output:*
|Fullname is: ABC XYZ |
Can you please suggest for any improvements in this OR is there a better
option to achieve expression evaluation?
Can this code possibly go into Malhar library?
~ Chinmay.