As per the documentation for MVEL in [http://mvel.codehaus.org/Value+Emptiness
empty
should evaluate to true if the below mentioned conditions are true.
a string has a length greater than 0 but is comprised only of whitespace
a boolean value is false
a numeric value is 0
But It does not give desired result.
For String case condition evaluates to false when String length>0 but comprised only of whitespace(Code used is given below).
String stringValue=" ";
Map<String,Object> contextMap=new HashMap<String, Object>();
contextMap.put("stringValue", stringValue);
System.out.println(MVEL.eval("stringValue == empty",contextMap));
For Boolean it evalautes to false irrespective of boolean value(Code used is given below);
Boolean booleanValue=false;
Map<String,Object> contextMap=new HashMap<String, Object>();
contextMap.put("booleanValue", booleanValue);
System.out.println(MVEL.eval("booleanValue == empty",contextMap));
And it shows error on comparing integers. Code:
Integer integerValue=0;
Map<String,Object> contextMap=new HashMap<String, Object>();
contextMap.put("integerValue", integerValue);
System.out.println(MVEL.eval("integerValue == empty",contextMap));
Error:
Exception in thread "main" [Error: failed to subEval expression]
[Near : {... integerValue == empty ....}]
^
[Line: 1, Column: 17]
at org.mvel2.compiler.AbstractParser.reduce(AbstractParser.java:2653)
at org.mvel2.compiler.AbstractParser.arithmeticFunctionReduction(AbstractParser.java:2552)
at org.mvel2.MVELInterpretedRuntime.parseAndExecuteInterpreted(MVELInterpretedRuntime.java:152)
at org.mvel2.MVELInterpretedRuntime.parse(MVELInterpretedRuntime.java:49)
at org.mvel2.MVEL.eval(MVEL.java:165)
at com.Test1.main(Test1.java:15)
Caused by: java.lang.RuntimeException: cannot convert <> to a numeric type: class org.mvel2.compiler.BlankLiteral [200]
at org.mvel2.math.MathProcessor.getNumber(MathProcessor.java:702)
at org.mvel2.math.MathProcessor._doOperations(MathProcessor.java:214)
at org.mvel2.math.MathProcessor.doOperations(MathProcessor.java:79)
at org.mvel2.math.MathProcessor.doOperations(MathProcessor.java:48)
at org.mvel2.util.ExecutionStack.op(ExecutionStack.java:178)
at org.mvel2.compiler.AbstractParser.reduce(AbstractParser.java:2593)
... 5 more
Why it is not working as per documentation?
All three are related to MVEL issues.
For the Q1 and Q2
,
For empty
operator, MVEL has a class BlankLiteral
, and it has a method
public boolean equals(Object obj) {
if (obj == null || "".equals(valueOf(obj))) {
return true;
}
else if (isNumeric(obj)) {
return "0".equals(valueOf(obj));
}
else if (obj instanceof Collection) {
return ((Collection) obj).size() == 0;
}
else if (obj.getClass().isArray()) {
return getLength(obj) == 0;
}
return false;
}
which does not handle the cases as questioned by you in Q1 and Q2
.
Q3, expression integerValue == empty
,
MVEl tries to cast empty
to Number, control comes to this class MathProcessor.class
Method is
private static Double getNumber(Object in, int type) {
if (in == null)
return 0d;
switch (type) {
case BIG_DECIMAL:
return ((Number) in).doubleValue();
case DataTypes.BIG_INTEGER:
return ((Number) in).doubleValue();
case DataTypes.INTEGER:
case DataTypes.W_INTEGER:
return ((Number) in).doubleValue();
case DataTypes.LONG:
case DataTypes.W_LONG:
return ((Number) in).doubleValue();
case DataTypes.STRING:
return Double.parseDouble((String) in);
case DataTypes.FLOAT:
case DataTypes.W_FLOAT:
return ((Number) in).doubleValue();
case DataTypes.DOUBLE:
case DataTypes.W_DOUBLE:
return (Double) in;
case DataTypes.SHORT:
case DataTypes.W_SHORT:
return ((Number) in).doubleValue();
case DataTypes.CHAR:
case DataTypes.W_CHAR:
return Double.parseDouble(String.valueOf((Character) in));
case DataTypes.BOOLEAN:
case DataTypes.W_BOOLEAN:
return ((Boolean) in) ? 1d : 0d;
case DataTypes.W_BYTE:
case DataTypes.BYTE:
return ((Byte) in).doubleValue();
}
throw new RuntimeException("cannot convert <" + in + "> to a numeric type: " + in.getClass() + " [" + type + "]");
}
Observing the values in debug mode,
Object in - BlankLiteral
int type - 200
200 is nothing but DataTypes.EMPTY
which is currently not handled by MVEL. So since no case is matched it throws exception.
So still 'empty' is not fully implemented in MVEL