/*
* Copyright 2013 Guidewire Software, Inc.
*/
package gw.internal.gosu.parser.expressions;
import gw.internal.gosu.parser.BeanAccess;
import gw.lang.parser.expressions.IRelationalExpression;
import gw.lang.reflect.IType;
import gw.lang.reflect.java.JavaTypes;
/**
* Represents a relational expression in the Gosu grammar:
* <pre>
* <i>relational-expression</i>
* <bitshift-expression>
* <relational-expression> <b><</b> <bitshift-expression>
* <relational-expression> <b>></b> <bitshift-expression>
* <relational-expression> <b><=</b> <bitshift-expression>
* <relational-expression> <b>>=</b> <bitshift-expression>
* </pre>
* <p/>
*
* @see gw.lang.parser.IGosuParser
*/
public final class RelationalExpression extends ConditionalExpression implements IRelationalExpression
{
/**
* An attribute specifying the type of operation e.g., > >= < <=
*/
private String _strOperator;
public String getOperator()
{
return _strOperator;
}
public void setOperator( String strOperator )
{
_strOperator = strOperator;
}
/**
* Perform a relational comparison.
*/
public Object evaluate()
{
if( !isCompileTimeConstant() )
{
return super.evaluate();
}
Object lhsValue = getLHS().evaluate();
Object rhsValue = getRHS().evaluate();
IType lhsType = getLHS().getType();
IType rhsType = getRHS().getType();
if( _strOperator.equals( ">" ) )
{
if( BeanAccess.isNumericType( lhsType ) )
{
return compareNumbers( lhsValue, rhsValue, lhsType, rhsType ) > 0;
}
else
{
if( BeanAccess.isBeanType( lhsType ) )
{
if( BeanAccess.isBeanType( rhsType ) )
{
if( lhsType.isAssignableFrom( rhsType ) )
{
if( JavaTypes.COMPARABLE().isAssignableFrom( lhsType ) )
{
//noinspection unchecked
return ((Comparable)lhsValue).compareTo( rhsValue ) > 0;
}
}
}
}
}
}
else if( _strOperator.equals( "<" ) )
{
if( BeanAccess.isNumericType( lhsType ) )
{
return compareNumbers( lhsValue, rhsValue, lhsType, rhsType ) < 0;
}
else
{
if( BeanAccess.isBeanType( lhsType ) )
{
if( BeanAccess.isBeanType( rhsType ) )
{
if( lhsType.isAssignableFrom( rhsType ) )
{
if( JavaTypes.COMPARABLE().isAssignableFrom( lhsType ) )
{
//noinspection unchecked
return ((Comparable)lhsValue).compareTo( rhsValue ) < 0;
}
}
}
}
}
}
else if( _strOperator.equals( ">=" ) )
{
if( BeanAccess.isNumericType( lhsType ) )
{
return compareNumbers( lhsValue, rhsValue, lhsType, rhsType ) >= 0;
}
else
{
if( BeanAccess.isBeanType( lhsType ) )
{
if( BeanAccess.isBeanType( rhsType ) )
{
if( lhsType.isAssignableFrom( rhsType ) )
{
if( JavaTypes.COMPARABLE().isAssignableFrom( lhsType ) )
{
//noinspection unchecked
return ((Comparable)lhsValue).compareTo( rhsValue ) >= 0;
}
}
}
}
}
}
else // if( _strOperator.equals( "<=" ) )
{
if( BeanAccess.isNumericType( lhsType ) )
{
return compareNumbers( lhsValue, rhsValue, lhsType, rhsType ) <= 0;
}
else
{
if( BeanAccess.isBeanType( lhsType ) )
{
if( BeanAccess.isBeanType( rhsType ) )
{
if( lhsType.isAssignableFrom( rhsType ) )
{
if( JavaTypes.COMPARABLE().isAssignableFrom( lhsType ) )
{
//noinspection unchecked
return ((Comparable)lhsValue).compareTo( rhsValue ) <= 0;
}
}
}
}
}
}
throw new UnsupportedOperationException( "Operands are not compile-time constants.\n" +
"(see http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#5313)" );
}
@Override
public String toString()
{
return getLHS().toString() + _strOperator + getRHS().toString();
}
}