package org.mvel2.ast; import org.mvel2.CompileException; import org.mvel2.MVEL; import org.mvel2.ParserContext; import org.mvel2.compiler.ExecutableStatement; import org.mvel2.integration.VariableResolverFactory; import org.mvel2.util.ParseTools; import java.io.Serializable; import java.math.BigDecimal; import java.math.BigInteger; import static org.mvel2.util.ParseTools.boxPrimitive; public class Sign extends ASTNode { private Signer signer; private ExecutableStatement stmt; public Sign(char[] expr, int start, int end, int fields, ParserContext pCtx) { super(pCtx); this.expr = expr; this.start = start + 1; this.offset = end - 1; this.fields = fields; if ((fields & COMPILE_IMMEDIATE) != 0) { stmt = (ExecutableStatement) ParseTools.subCompileExpression(expr, this.start, this.offset, pCtx); egressType = stmt.getKnownEgressType(); if (egressType != null && egressType != Object.class) { initSigner(egressType); } } } public ExecutableStatement getStatement() { return stmt; } @Override public Object getReducedValueAccelerated(Object ctx, Object thisValue, VariableResolverFactory factory) { return sign(stmt.getValue(ctx, thisValue, factory)); } @Override public Object getReducedValue(Object ctx, Object thisValue, VariableResolverFactory factory) { return sign(MVEL.eval(expr, start, offset, thisValue, factory)); } private Object sign(Object o) { if (o == null) return null; if (signer == null) { if (egressType == null || egressType == Object.class) egressType = o.getClass(); initSigner(egressType); } return signer.sign(o); } private void initSigner(Class type) { if (Integer.class.isAssignableFrom(type = boxPrimitive(type))) signer = new IntegerSigner(); else if (Double.class.isAssignableFrom(type)) signer = new DoubleSigner(); else if (Long.class.isAssignableFrom(type)) signer = new LongSigner(); else if (Float.class.isAssignableFrom(type)) signer = new FloatSigner(); else if (Short.class.isAssignableFrom(type)) signer = new ShortSigner(); else if (BigInteger.class.isAssignableFrom(type)) signer = new BigIntSigner(); else if (BigDecimal.class.isAssignableFrom(type)) signer = new BigDecSigner(); else { throw new CompileException("illegal use of '-': cannot be applied to: " + type.getName(), expr, start); } } private interface Signer extends Serializable { public Object sign(Object o); } private class IntegerSigner implements Signer { public Object sign(Object o) { return -((Integer) o); } } private class ShortSigner implements Signer { public Object sign(Object o) { return -((Short) o); } } private class LongSigner implements Signer { public Object sign(Object o) { return -((Long) o); } } private class DoubleSigner implements Signer { public Object sign(Object o) { return -((Double) o); } } private class FloatSigner implements Signer { public Object sign(Object o) { return -((Float) o); } } private class BigIntSigner implements Signer { public Object sign(Object o) { return new BigInteger(String.valueOf(-(((BigInteger) o).longValue()))); } } private class BigDecSigner implements Signer { public Object sign(Object o) { return new BigDecimal(-((BigDecimal) o).doubleValue()); } } @Override public boolean isIdentifier() { return false; } }