You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by pr...@apache.org on 2003/06/22 21:43:01 UTC

cvs commit: jakarta-commons/jexl/src/test/org/apache/commons/jexl JexlTest.java

proyal      2003/06/22 12:43:01

  Modified:    jexl/src/java/org/apache/commons/jexl/parser ASTGENode.java
                        ASTGTNode.java ASTLENode.java ASTLTNode.java
               jexl/src/java/org/apache/commons/jexl/util Coercion.java
               jexl/src/test/org/apache/commons/jexl JexlTest.java
  Log:
  Fix 20728 - Implement JSTL-compliant parameter coercion for LT/GT/LE/GE expressions
  
  Revision  Changes    Path
  1.2       +46 -6     jakarta-commons/jexl/src/java/org/apache/commons/jexl/parser/ASTGENode.java
  
  Index: ASTGENode.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/jexl/src/java/org/apache/commons/jexl/parser/ASTGENode.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- ASTGENode.java	26 Apr 2002 04:23:14 -0000	1.1
  +++ ASTGENode.java	22 Jun 2003 19:43:01 -0000	1.2
  @@ -54,11 +54,15 @@
   package org.apache.commons.jexl.parser;
   
   import org.apache.commons.jexl.JexlContext;
  +import org.apache.commons.jexl.util.Coercion;
   
   /**
    *  GE : a >= b
    *
  + *  Follows A.3.6.1 of the JSTL 1.0 specification
  + *
    *  @author <a href="mailto:geirm@apache.org">Geir Magnusson Jr.</a>
  + *  @author <a href="mailto:proyal@apache.org">Peter Royal</a>
    *  @version $Id$
    */
   public class ASTGENode extends SimpleNode
  @@ -90,16 +94,52 @@
           Object left = ( (SimpleNode) jjtGetChild(0)).value(jc);
           Object right = ( (SimpleNode) jjtGetChild(1)).value(jc);
   
  -        if ((left==null) || (right==null))
  +        if( left == right )
  +        {
  +            return Boolean.TRUE;
  +        }
  +        else if ( ( left == null ) || ( right == null ) )
           {
  -            throw new Exception("Null comparison : GE ");
  +            return Boolean.FALSE;
  +        }
  +        else if( Coercion.isFloatingPoint( left ) || Coercion.isFloatingPoint( right ) )
  +        {
  +            double leftDouble = Coercion.coerceDouble( left ).doubleValue();
  +            double rightDouble = Coercion.coerceDouble( right ).doubleValue();
  +
  +            return leftDouble >= rightDouble
  +                ? Boolean.TRUE
  +                : Boolean.FALSE;
           }
  +        else if( Coercion.isNumberable( left ) || Coercion.isNumberable( right ) )
  +        {
  +            long leftLong = Coercion.coerceLong( left ).longValue();
  +            long rightLong = Coercion.coerceLong( right ).longValue();
   
  -        if (left instanceof Integer && right instanceof Integer)
  +            return leftLong >= rightLong
  +                ? Boolean.TRUE
  +                : Boolean.FALSE;
  +        }
  +        else if( left instanceof String || right instanceof String )
           {
  -            int val = ((Integer) left).compareTo((Integer)right);
  +            String leftString = left.toString();
  +            String rightString = right.toString();
   
  -            return new Boolean(val >= 0);
  +            return leftString.compareTo( rightString ) >= 0
  +                ? Boolean.TRUE
  +                : Boolean.FALSE;
  +        }
  +        else if( left instanceof Comparable )
  +        {
  +            return ( (Comparable)left ).compareTo( right ) >= 0
  +                ? Boolean.TRUE
  +                : Boolean.FALSE;
  +        }
  +        else if( right instanceof Comparable )
  +        {
  +            return ( (Comparable)right ).compareTo( left ) <= 0
  +                ? Boolean.TRUE
  +                : Boolean.FALSE;
           }
   
           throw new Exception("Invalid comparison : GE ");
  
  
  
  1.3       +52 -21    jakarta-commons/jexl/src/java/org/apache/commons/jexl/parser/ASTGTNode.java
  
  Index: ASTGTNode.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/jexl/src/java/org/apache/commons/jexl/parser/ASTGTNode.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- ASTGTNode.java	6 Mar 2003 21:34:32 -0000	1.2
  +++ ASTGTNode.java	22 Jun 2003 19:43:01 -0000	1.3
  @@ -54,58 +54,89 @@
   package org.apache.commons.jexl.parser;
   
   import org.apache.commons.jexl.JexlContext;
  +import org.apache.commons.jexl.util.Coercion;
   
   /**
    *  GT : a > b
    *
  + *  Follows A.3.6.1 of the JSTL 1.0 specification
  + *
    *  @author <a href="mailto:geirm@apache.org">Geir Magnusson Jr.</a>
  + *  @author <a href="mailto:proyal@apache.org">Peter Royal</a>
    *  @version $Id$
    */
   public class ASTGTNode extends SimpleNode
   {
  -    public ASTGTNode(int id)
  +    public ASTGTNode( int id )
       {
  -        super(id);
  +        super( id );
       }
   
  -    public ASTGTNode(Parser p, int id)
  +    public ASTGTNode( Parser p, int id )
       {
  -        super(p, id);
  +        super( p, id );
       }
   
       /** Accept the visitor. **/
  -    public Object jjtAccept(ParserVisitor visitor, Object data)
  +    public Object jjtAccept( ParserVisitor visitor, Object data )
       {
  -        return visitor.visit(this, data);
  +        return visitor.visit( this, data );
       }
   
  -    public Object value(JexlContext jc)
  +    public Object value( JexlContext jc )
           throws Exception
       {
           /*
            * now get the values
            */
   
  -        Object left = ( (SimpleNode) jjtGetChild(0)).value(jc);
  -        Object right = ( (SimpleNode) jjtGetChild(1)).value(jc);
  +        Object left = ( (SimpleNode)jjtGetChild( 0 ) ).value( jc );
  +        Object right = ( (SimpleNode)jjtGetChild( 1 ) ).value( jc );
   
  -        if ((left==null) || (right==null))
  +        if( ( left == right ) || ( left == null ) || ( right == null ) )
           {
  -            throw new Exception("Null comparison : GT ");
  +            return Boolean.FALSE;
           }
  +        else if( Coercion.isFloatingPoint( left ) || Coercion.isFloatingPoint( right ) )
  +        {
  +            double leftDouble = Coercion.coerceDouble( left ).doubleValue();
  +            double rightDouble = Coercion.coerceDouble( right ).doubleValue();
   
  -        if ( (left instanceof Integer || left instanceof Long)
  -             && (right instanceof Integer || right instanceof Long) )
  +            return leftDouble > rightDouble
  +                ? Boolean.TRUE
  +                : Boolean.FALSE;
  +        }
  +        else if( Coercion.isNumberable( left ) || Coercion.isNumberable( right ) )
           {
  -            long leftLong = ((Number)left).longValue();
  -            long rightLong = ((Number)right).longValue();
  +            long leftLong = Coercion.coerceLong( left ).longValue();
  +            long rightLong = Coercion.coerceLong( right ).longValue();
   
  -            return ( ( leftLong > rightLong  )
  -                     ? Boolean.TRUE
  -                     : Boolean.FALSE );
  +            return leftLong > rightLong
  +                ? Boolean.TRUE
  +                : Boolean.FALSE;
           }
  +        else if( left instanceof String || right instanceof String )
  +        {
  +            String leftString = left.toString();
  +            String rightString = right.toString();
   
  -        throw new Exception("Invalid comparison : GT ");
  -    }
  +            return leftString.compareTo( rightString ) > 0
  +                ? Boolean.TRUE
  +                : Boolean.FALSE;
  +        }
  +        else if( left instanceof Comparable )
  +        {
  +            return ( (Comparable)left ).compareTo( right ) > 0
  +                ? Boolean.TRUE
  +                : Boolean.FALSE;
  +        }
  +        else if( right instanceof Comparable )
  +        {
  +            return ( (Comparable)right ).compareTo( left ) < 0
  +                ? Boolean.TRUE
  +                : Boolean.FALSE;
  +        }
   
  +        throw new Exception( "Invalid comparison : GT " );
  +    }
   }
  
  
  
  1.2       +46 -6     jakarta-commons/jexl/src/java/org/apache/commons/jexl/parser/ASTLENode.java
  
  Index: ASTLENode.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/jexl/src/java/org/apache/commons/jexl/parser/ASTLENode.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- ASTLENode.java	26 Apr 2002 04:23:14 -0000	1.1
  +++ ASTLENode.java	22 Jun 2003 19:43:01 -0000	1.2
  @@ -54,11 +54,15 @@
   package org.apache.commons.jexl.parser;
   
   import org.apache.commons.jexl.JexlContext;
  +import org.apache.commons.jexl.util.Coercion;
   
   /**
    *  LE : a <= b
    *
  + *  Follows A.3.6.1 of the JSTL 1.0 specification
  + *
    *  @author <a href="mailto:geirm@apache.org">Geir Magnusson Jr.</a>
  + *  @author <a href="mailto:proyal@apache.org">Peter Royal</a>
    *  @version $Id$
    */
   public class ASTLENode extends SimpleNode
  @@ -89,16 +93,52 @@
           Object left = ( (SimpleNode) jjtGetChild(0)).value(jc);
           Object right = ( (SimpleNode) jjtGetChild(1)).value(jc);
   
  -        if ((left==null) || (right==null))
  +        if( left == right )
  +        {
  +            return Boolean.TRUE;
  +        }
  +        else if ( ( left == null ) || ( right == null ) )
           {
  -            throw new Exception("Null comparison : LE ");
  +            return Boolean.FALSE;
  +        }
  +        else if( Coercion.isFloatingPoint( left ) || Coercion.isFloatingPoint( right ) )
  +        {
  +            double leftDouble = Coercion.coerceDouble( left ).doubleValue();
  +            double rightDouble = Coercion.coerceDouble( right ).doubleValue();
  +
  +            return leftDouble <= rightDouble
  +                ? Boolean.TRUE
  +                : Boolean.FALSE;
           }
  +        else if( Coercion.isNumberable( left ) || Coercion.isNumberable( right ) )
  +        {
  +            long leftLong = Coercion.coerceLong( left ).longValue();
  +            long rightLong = Coercion.coerceLong( right ).longValue();
   
  -        if (left instanceof Integer && right instanceof Integer)
  +            return leftLong <= rightLong
  +                ? Boolean.TRUE
  +                : Boolean.FALSE;
  +        }
  +        else if( left instanceof String || right instanceof String )
           {
  -            int val = ((Integer) left).compareTo((Integer)right);
  +            String leftString = left.toString();
  +            String rightString = right.toString();
   
  -            return new Boolean(val <= 0);
  +            return leftString.compareTo( rightString ) <= 0
  +                ? Boolean.TRUE
  +                : Boolean.FALSE;
  +        }
  +        else if( left instanceof Comparable )
  +        {
  +            return ( (Comparable)left ).compareTo( right ) <= 0
  +                ? Boolean.TRUE
  +                : Boolean.FALSE;
  +        }
  +        else if( right instanceof Comparable )
  +        {
  +            return ( (Comparable)right ).compareTo( left ) >= 0
  +                ? Boolean.TRUE
  +                : Boolean.FALSE;
           }
   
           throw new Exception("Invalid comparison : LE ");
  
  
  
  1.3       +42 -10    jakarta-commons/jexl/src/java/org/apache/commons/jexl/parser/ASTLTNode.java
  
  Index: ASTLTNode.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/jexl/src/java/org/apache/commons/jexl/parser/ASTLTNode.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- ASTLTNode.java	6 Mar 2003 21:34:32 -0000	1.2
  +++ ASTLTNode.java	22 Jun 2003 19:43:01 -0000	1.3
  @@ -55,11 +55,15 @@
   package org.apache.commons.jexl.parser;
   
   import org.apache.commons.jexl.JexlContext;
  +import org.apache.commons.jexl.util.Coercion;
   
   /**
    *  LT : a < b
    *
  + *  Follows A.3.6.1 of the JSTL 1.0 specification
  + *
    *  @author <a href="mailto:geirm@apache.org">Geir Magnusson Jr.</a>
  + *  @author <a href="mailto:proyal@apache.org">Peter Royal</a>
    *  @version $Id$
    */
   public class ASTLTNode extends SimpleNode
  @@ -90,20 +94,48 @@
           Object left = ( (SimpleNode) jjtGetChild(0)).value(jc);
           Object right = ( (SimpleNode) jjtGetChild(1)).value(jc);
   
  -        if ((left==null) || (right==null))
  +        if( ( left == right ) || ( left == null ) || ( right == null ) )
           {
  -            throw new Exception("Null comparison : LT ");
  +            return Boolean.FALSE;
           }
  +        else if( Coercion.isFloatingPoint( left ) || Coercion.isFloatingPoint( right ) )
  +        {
  +            double leftDouble = Coercion.coerceDouble( left ).doubleValue();
  +            double rightDouble = Coercion.coerceDouble( right ).doubleValue();
  +
  +            return leftDouble < rightDouble
  +                ? Boolean.TRUE
  +                : Boolean.FALSE;
  +        }
  +        else if( Coercion.isNumberable( left ) || Coercion.isNumberable( right ) )
  +        {
  +            long leftLong = Coercion.coerceLong( left ).longValue();
  +            long rightLong = Coercion.coerceLong( right ).longValue();
   
  -        if ( (left instanceof Integer || left instanceof Long) 
  -             && ( right instanceof Integer || right instanceof Long) )
  +            return leftLong < rightLong
  +                ? Boolean.TRUE
  +                : Boolean.FALSE;
  +        }
  +        else if( left instanceof String || right instanceof String )
           {
  -            long leftLong = ((Number)left).longValue();
  -            long rightLong = ((Number)right).longValue();
  +            String leftString = left.toString();
  +            String rightString = right.toString();
   
  -            return ( ( leftLong < rightLong )
  -                     ? Boolean.TRUE
  -                     : Boolean.FALSE );
  +            return leftString.compareTo( rightString ) < 0
  +                ? Boolean.TRUE
  +                : Boolean.FALSE;
  +        }
  +        else if( left instanceof Comparable )
  +        {
  +            return ( (Comparable)left ).compareTo( right ) < 0
  +                ? Boolean.TRUE
  +                : Boolean.FALSE;
  +        }
  +        else if( right instanceof Comparable )
  +        {
  +            return ( (Comparable)right ).compareTo( left ) > 0
  +                ? Boolean.TRUE
  +                : Boolean.FALSE;
           }
   
           throw new Exception("Invalid comparison : LT ");
  
  
  
  1.3       +16 -0     jakarta-commons/jexl/src/java/org/apache/commons/jexl/util/Coercion.java
  
  Index: Coercion.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/jexl/src/java/org/apache/commons/jexl/util/Coercion.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- Coercion.java	17 May 2002 12:23:22 -0000	1.2
  +++ Coercion.java	22 Jun 2003 19:43:01 -0000	1.3
  @@ -175,10 +175,26 @@
           }
           else if (val instanceof Number)
           {
  +            //The below construct is used rather than ((Number)val).doubleValue() to ensure
  +            //equality between comparint new Double( 6.4 / 3 ) and the jexl expression of 6.4 / 3
               return new Double(Double.parseDouble(String.valueOf(val)));
           }
   
           throw new Exception("Double coercion exception");
  +    }
  +
  +    public static boolean isFloatingPoint( final Object o )
  +    {
  +        return o instanceof Float || o instanceof Double;
  +    }
  +
  +    public static boolean isNumberable( final Object o )
  +    {
  +        return o instanceof Integer
  +            || o instanceof Long
  +            || o instanceof Byte
  +            || o instanceof Short
  +            || o instanceof Character;
       }
   
   }
  
  
  
  1.29      +13 -1     jakarta-commons/jexl/src/test/org/apache/commons/jexl/JexlTest.java
  
  Index: JexlTest.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/jexl/src/test/org/apache/commons/jexl/JexlTest.java,v
  retrieving revision 1.28
  retrieving revision 1.29
  diff -u -r1.28 -r1.29
  --- JexlTest.java	9 May 2003 12:22:29 -0000	1.28
  +++ JexlTest.java	22 Jun 2003 19:43:01 -0000	1.29
  @@ -946,6 +946,18 @@
           }
       }
   
  +    public void testCoercionWithComparisionOperators()
  +        throws Exception
  +    {
  +        JexlContext jc = JexlHelper.createContext();
  +
  +        assertExpression(jc, "'2' > 1", Boolean.TRUE);
  +        assertExpression(jc, "'2' >= 1", Boolean.TRUE);
  +        assertExpression(jc, "'2' >= 2", Boolean.TRUE);
  +        assertExpression(jc, "'2' < 1", Boolean.FALSE);
  +        assertExpression(jc, "'2' <= 1", Boolean.FALSE);
  +        assertExpression(jc, "'2' <= 2", Boolean.TRUE);
  +    }
   
       public void testResolver()
           throws Exception
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org