0

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.

  1. 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));
    
  2. 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));
    
  3. 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?

sud_shan
  • 195
  • 1
  • 11
  • A certain species known as "bug" has been sighted off and on software and other pastures. File a bug report on the MVEL bug reporting site. – laune Dec 20 '14 at 20:56
  • @laune unable to find any link to report a bug(for public). If there is link please share. – sud_shan Dec 22 '14 at 05:10
  • I've started inquiries. Pls stand by. – laune Dec 22 '14 at 05:38
  • @laune shared my analysis, hope you provide a way to log a bug – Ankur Singhal Dec 22 '14 at 07:21
  • @sud_shan it's a bug, find an alternative. :) – Ankur Singhal Dec 22 '14 at 07:22
  • @ankur-singhal Great! - sud_shan: Meanwhile, I've asked my contact about MVEL. M. Brock, its author, isn't expected to continue maintenance of MVEL. There's another group who does, but they'll eventually drop it, too. Can either of you provide the MVEL version which fails in these ways? If it is 2.2.0, the latest, I can create a JIRA on the MVEL site with the data you have provided here. Don't expect anything happening soon, if this bug isn't considered to be high priority.-- Searching for an alternative to MVEL may be a good idea. – laune Dec 22 '14 at 18:28
  • @laune `2.2.0.Final` – Ankur Singhal Dec 23 '14 at 03:19
  • @laune can you log [this bug](http://stackoverflow.com/questions/26839705/mvel-iterate-a-list) too – Ankur Singhal Dec 23 '14 at 03:20
  • @ankur-singhal & sud_shan: I've reported the bug and Mario Fusco of the Drools team has told me that it will be fixed although `empty` isn't used with Drools. I think this is good news, even when it may not happen until the end of this year ;-) – laune Dec 29 '14 at 11:31
  • @laune pls log the above bug as well , i have put the link in my above comment – Ankur Singhal Dec 29 '14 at 11:47
  • @ankur-singhal I've reported both. – laune Dec 29 '14 at 11:48
  • @sud_shan Mario Fusco fixed the problem with the empty literal with this commit: https://github.com/mvel/mvel/commit/b44824e9ccbc565b6619714c92582014271e4bbb Of course the fix will be available with next mvel release. – laune Jan 02 '15 at 14:44
  • @ankur-singhal see previous comment – laune Jan 02 '15 at 14:45
  • @laune thanks for your real active participation. – Ankur Singhal Jan 02 '15 at 17:09

2 Answers2

2

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

Ankur Singhal
  • 26,012
  • 16
  • 82
  • 116
1

I added the missing implementation part of the empty literal with this commit: https://github.com/mvel/mvel/commit/b44824e9ccbc565b6619714c92582014271e4bbb

The fix will be available with next mvel release (2.2.3.Final). Thanks for having reported this.

Mario Fusco
  • 13,548
  • 3
  • 28
  • 37