Announcement Announcement Module
Collapse
No announcement yet.
SPEL - OperatorOverloader to BigDecimal Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • SPEL - OperatorOverloader to BigDecimal

    Hi folks,

    I need to use a Expression Language API in a system. But in this system all operands is BigDecimal. I've tried implementing a OperatorOverloader in oder to translate expression like '1 + 2' to new BigDecimal('1').add(new BigDecimal('2')).
    I've set up my OperatorOverloader in StandardEvaluationContext object, like this:

    Code:
    StandardEvaluationContext context = new StandardEvaluationContext();
    context.setOperatorOverloader(new OperatorOverloaderBigDecimal());
    context.setTypeConverter(new TypeConverterBigDecimal());
    			
    InternalSpelExpressionParser parser = new InternalSpelExpressionParser();
    Expression exp = parser.parseExpression("1 + 2", context);
    Assert.assertEquals(new BigDecimal("3"), exp.getValue(context));
    I don't know why the parser doesn't call my OperatorOverloader.
    Would someone help me? This is a bug?

    Thank you very much!
    Last edited by leandroorilio; Oct 20th, 2009, 12:40 PM.

  • #2
    Hi folks,

    After analyzing I found my answer.
    The SPEL try to parse the operands to Number if it gets it, the SPEL doesn't call my OperatorOverloaderBigDecimal. Than I had to do something pretty weird, translating my expression like this:
    Code:
    "1 + 1" -> new com.MyOperand('1') + com.MyOperand('1')
    
    MyOperand class is: 
    public class MyOperand
    
            private String operand;
    
    	public EprevOperand(String operand) {
    		this.operand = operand;
    	}
    
    	public String getOperand() {
    		return operand;
    	}
    
    	public String toString() {
    		return operand;
    	}
    
    	public boolean equals(Object other) {
    		if ((this == other))
    			return true;
    		if ((other == null))
    			return false;
    		if (!(other instanceof EprevOperand))
    			return false;
    		EprevOperand castOther = (EprevOperand) other;
    
    		return new EqualsBuilder().append(this.operand, castOther.operand).isEquals();
    	}
    
    	public int hashCode() {
    		return new HashCodeBuilder().append(this.operand).toHashCode();
    	}
    
    and my OperandOverloader is:
    
    public class OperatorOverloaderBigDecimal implements OperatorOverloader {
    
    	@Override
    	public Object operate(Operation operator, Object leftOperand, Object rightOperand) throws EvaluationException {
    		EprevOperand result = null;
    		BigDecimal left = new BigDecimal(((EprevOperand) leftOperand).getOperand());
    		BigDecimal right = new BigDecimal(((EprevOperand) rightOperand).getOperand());
    		switch (operator) {
    		case ADD:
    			result = new EprevOperand(left.add(right).toPlainString());
    			break;
    		case MULTIPLY:
    			result = new EprevOperand(left.multiply(right).toPlainString());
    			break;
    		case DIVIDE:
    			result = new EprevOperand(left.divide(right).toPlainString());
    			break;
    		case POWER:
    			result = new EprevOperand(left.pow(right.intValue()).toPlainString());
    		case SUBTRACT:
    			result = new EprevOperand(left.subtract(right).toPlainString());
    		default:
    			break;
    		}
    		return result;
    	}
    
    	@Override
    	public boolean overridesOperation(Operation operator, Object arg1, Object arg2) throws EvaluationException {
    		return true;
    	}
    I believe that this implementation would be better like, if I set up one OperatorOverload, the SPEL should've been always called my OperatorOverload.

    I hope this solution one day help someone.

    Cheers!
    Leandro Orilio

    Comment

    Working...
    X