/**************************************************************************************
* Copyright (C) 2008 EsperTech, Inc. All rights reserved. *
* http://esper.codehaus.org *
* http://www.espertech.com *
* ---------------------------------------------------------------------------------- *
* The software in this package is published under the terms of the GPL license *
* a copy of which has been included with this distribution in the license.txt file. *
**************************************************************************************/
package com.espertech.esper.type;
import com.espertech.esper.collection.MultiKey;
import com.espertech.esper.collection.MultiKeyUntyped;
import com.espertech.esper.util.SimpleNumberBigIntegerCoercer;
import com.espertech.esper.util.SimpleNumberBigDecimalCoercer;
import com.espertech.esper.util.SimpleNumberCoercerFactory;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.Map;
/**
* Enum representing relational types of operation.
*/
public enum RelationalOpEnum
{
/**
* Greater then.
*/
GT (">"),
/**
* Greater equals.
*/
GE (">="),
/**
* Lesser then.
*/
LT ("<"),
/**
* Lesser equals.
*/
LE ("<=");
private static Map<MultiKeyUntyped, RelationalOpEnum.Computer> computers;
private String expressionText;
private RelationalOpEnum(String expressionText)
{
this.expressionText = expressionText;
}
public RelationalOpEnum reversed() {
if (GT == this) {
return LT;
}
else if (GE == this) {
return LE;
}
else if (LE == this) {
return GE;
}
return GT;
}
/**
* Parses the operator and returns an enum for the operator.
* @param op to parse
* @return enum representing relational operation
*/
public static RelationalOpEnum parse(String op)
{
if (op.equals("<"))
{
return LT;
}
else if (op.equals(">"))
{
return GT;
}
else if ((op.equals(">=")) || op.equals("=>"))
{
return GE;
}
else if ((op.equals("<=")) || op.equals("=<"))
{
return LE;
}
else throw new IllegalArgumentException("Invalid relational operator '" + op + "'");
}
static
{
computers = new HashMap<MultiKeyUntyped, RelationalOpEnum.Computer>();
computers.put(new MultiKeyUntyped(new Object[] {String.class, GT}), new GTStringComputer());
computers.put(new MultiKeyUntyped(new Object[] {String.class, GE}), new GEStringComputer());
computers.put(new MultiKeyUntyped(new Object[] {String.class, LT}), new LTStringComputer());
computers.put(new MultiKeyUntyped(new Object[] {String.class, LE}), new LEStringComputer());
computers.put(new MultiKeyUntyped(new Object[] {Integer.class, GT}), new GTIntegerComputer());
computers.put(new MultiKeyUntyped(new Object[] {Integer.class, GE}), new GEIntegerComputer());
computers.put(new MultiKeyUntyped(new Object[] {Integer.class, LT}), new LTIntegerComputer());
computers.put(new MultiKeyUntyped(new Object[] {Integer.class, LE}), new LEIntegerComputer());
computers.put(new MultiKeyUntyped(new Object[] {Long.class, GT}), new GTLongComputer());
computers.put(new MultiKeyUntyped(new Object[] {Long.class, GE}), new GELongComputer());
computers.put(new MultiKeyUntyped(new Object[] {Long.class, LT}), new LTLongComputer());
computers.put(new MultiKeyUntyped(new Object[] {Long.class, LE}), new LELongComputer());
computers.put(new MultiKeyUntyped(new Object[] {Double.class, GT}), new GTDoubleComputer());
computers.put(new MultiKeyUntyped(new Object[] {Double.class, GE}), new GEDoubleComputer());
computers.put(new MultiKeyUntyped(new Object[] {Double.class, LT}), new LTDoubleComputer());
computers.put(new MultiKeyUntyped(new Object[] {Double.class, LE}), new LEDoubleComputer());
computers.put(new MultiKeyUntyped(new Object[] {Float.class, GT}), new GTFloatComputer());
computers.put(new MultiKeyUntyped(new Object[] {Float.class, GE}), new GEFloatComputer());
computers.put(new MultiKeyUntyped(new Object[] {Float.class, LT}), new LTFloatComputer());
computers.put(new MultiKeyUntyped(new Object[] {Float.class, LE}), new LEFloatComputer());
computers.put(new MultiKeyUntyped(new Object[] {BigDecimal.class, GT}), new GTBigDecComputer());
computers.put(new MultiKeyUntyped(new Object[] {BigDecimal.class, GE}), new GEBigDecComputer());
computers.put(new MultiKeyUntyped(new Object[] {BigDecimal.class, LT}), new LTBigDecComputer());
computers.put(new MultiKeyUntyped(new Object[] {BigDecimal.class, LE}), new LEBigDecComputer());
computers.put(new MultiKeyUntyped(new Object[] {BigInteger.class, GT}), new GTBigIntComputer());
computers.put(new MultiKeyUntyped(new Object[] {BigInteger.class, GE}), new GEBigIntComputer());
computers.put(new MultiKeyUntyped(new Object[] {BigInteger.class, LT}), new LTBigIntComputer());
computers.put(new MultiKeyUntyped(new Object[] {BigInteger.class, LE}), new LEBigIntComputer());
}
/**
* Returns the computer to use for the relational operation based on the coercion type.
* @param coercedType is the object type
* @param typeOne the compare-to type on the LHS
* @param typeTwo the compare-to type on the RHS
* @return computer for performing the relational op
*/
public RelationalOpEnum.Computer getComputer(Class coercedType, Class typeOne, Class typeTwo)
{
if ( (coercedType != Double.class) &&
(coercedType != Float.class) &&
(coercedType != Integer.class) &&
(coercedType != Long.class) &&
(coercedType != String.class) &&
(coercedType != BigDecimal.class) &&
(coercedType != BigInteger.class))
{
throw new IllegalArgumentException("Unsupported type for relational op compare, type " + coercedType);
}
if (coercedType == BigDecimal.class)
{
return makeBigDecimalComputer(typeOne, typeTwo);
}
if (coercedType == BigInteger.class)
{
return makeBigIntegerComputer(typeOne, typeTwo);
}
MultiKeyUntyped key = new MultiKeyUntyped(new Object[] {coercedType, this});
return computers.get(key);
}
private Computer makeBigDecimalComputer(Class typeOne, Class typeTwo)
{
if ((typeOne == BigDecimal.class) && (typeTwo == BigDecimal.class))
{
return computers.get(new MultiKeyUntyped(new Object[] {BigDecimal.class, this}));
}
SimpleNumberBigDecimalCoercer convertorOne = SimpleNumberCoercerFactory.getCoercerBigDecimal(typeOne);
SimpleNumberBigDecimalCoercer convertorTwo = SimpleNumberCoercerFactory.getCoercerBigDecimal(typeTwo);
if (this == GT)
{
return new GTBigDecConvComputer(convertorOne, convertorTwo);
}
if (this == LT)
{
return new LTBigDecConvComputer(convertorOne, convertorTwo);
}
if (this == GE)
{
return new GEBigDecConvComputer(convertorOne, convertorTwo);
}
return new LEBigDecConvComputer(convertorOne, convertorTwo);
}
private Computer makeBigIntegerComputer(Class typeOne, Class typeTwo)
{
if ((typeOne == BigInteger.class) && (typeTwo == BigInteger.class))
{
return computers.get(new MultiKeyUntyped(new Object[] {BigInteger.class, this}));
}
SimpleNumberBigIntegerCoercer convertorOne = SimpleNumberCoercerFactory.getCoercerBigInteger(typeOne);
SimpleNumberBigIntegerCoercer convertorTwo = SimpleNumberCoercerFactory.getCoercerBigInteger(typeTwo);
if (this == GT)
{
return new GTBigIntConvComputer(convertorOne, convertorTwo);
}
if (this == LT)
{
return new LTBigIntConvComputer(convertorOne, convertorTwo);
}
if (this == GE)
{
return new GEBigIntConvComputer(convertorOne, convertorTwo);
}
return new LEBigIntConvComputer(convertorOne, convertorTwo);
}
/**
* Computer for relational op.
*/
public interface Computer
{
/**
* Compares objects and returns boolean indicating larger (true) or smaller (false).
* @param objOne object to compare
* @param objTwo object to compare
* @return true if larger, false if smaller
*/
public boolean compare(Object objOne, Object objTwo);
}
/**
* Computer for relational op compare.
*/
public static class GTStringComputer implements Computer
{
public boolean compare(Object objOne, Object objTwo)
{
String s1 = (String) objOne;
String s2 = (String) objTwo;
int result = s1.compareTo(s2);
return result > 0;
}
}
/**
* Computer for relational op compare.
*/
public static class GEStringComputer implements Computer
{
public boolean compare(Object objOne, Object objTwo)
{
String s1 = (String) objOne;
String s2 = (String) objTwo;
return s1.compareTo(s2) >= 0;
}
}
/**
* Computer for relational op compare.
*/
public static class LEStringComputer implements Computer
{
public boolean compare(Object objOne, Object objTwo)
{
String s1 = (String) objOne;
String s2 = (String) objTwo;
return s1.compareTo(s2) <= 0;
}
}
/**
* Computer for relational op compare.
*/
public static class LTStringComputer implements Computer
{
public boolean compare(Object objOne, Object objTwo)
{
String s1 = (String) objOne;
String s2 = (String) objTwo;
return s1.compareTo(s2) < 0;
}
}
/**
* Computer for relational op compare.
*/
public static class GTLongComputer implements Computer
{
public boolean compare(Object objOne, Object objTwo)
{
Number s1 = (Number) objOne;
Number s2 = (Number) objTwo;
return s1.longValue() > s2.longValue();
}
}
/**
* Computer for relational op compare.
*/
public static class GELongComputer implements Computer
{
public boolean compare(Object objOne, Object objTwo)
{
Number s1 = (Number) objOne;
Number s2 = (Number) objTwo;
return s1.longValue() >= s2.longValue();
}
}
/**
* Computer for relational op compare.
*/
public static class LTLongComputer implements Computer
{
public boolean compare(Object objOne, Object objTwo)
{
Number s1 = (Number) objOne;
Number s2 = (Number) objTwo;
return s1.longValue() < s2.longValue();
}
}
/**
* Computer for relational op compare.
*/
public static class LELongComputer implements Computer
{
public boolean compare(Object objOne, Object objTwo)
{
Number s1 = (Number) objOne;
Number s2 = (Number) objTwo;
return s1.longValue() <= s2.longValue();
}
}
/**
* Computer for relational op compare.
*/
public static class GTIntegerComputer implements Computer
{
public boolean compare(Object objOne, Object objTwo)
{
Number s1 = (Number) objOne;
Number s2 = (Number) objTwo;
return s1.intValue() > s2.intValue();
}
}
/**
* Computer for relational op compare.
*/
public static class GEIntegerComputer implements Computer
{
public boolean compare(Object objOne, Object objTwo)
{
Number s1 = (Number) objOne;
Number s2 = (Number) objTwo;
return s1.intValue() >= s2.intValue();
}
}
/**
* Computer for relational op compare.
*/
public static class LTIntegerComputer implements Computer
{
public boolean compare(Object objOne, Object objTwo)
{
Number s1 = (Number) objOne;
Number s2 = (Number) objTwo;
return s1.intValue() < s2.intValue();
}
}
/**
* Computer for relational op compare.
*/
public static class LEIntegerComputer implements Computer
{
public boolean compare(Object objOne, Object objTwo)
{
Number s1 = (Number) objOne;
Number s2 = (Number) objTwo;
return s1.intValue() <= s2.intValue();
}
}
/**
* Computer for relational op compare.
*/
public static class GTDoubleComputer implements Computer
{
public boolean compare(Object objOne, Object objTwo)
{
Number s1 = (Number) objOne;
Number s2 = (Number) objTwo;
return s1.doubleValue() > s2.doubleValue();
}
}
/**
* Computer for relational op compare.
*/
public static class GEDoubleComputer implements Computer
{
public boolean compare(Object objOne, Object objTwo)
{
Number s1 = (Number) objOne;
Number s2 = (Number) objTwo;
return s1.doubleValue() >= s2.doubleValue();
}
}
/**
* Computer for relational op compare.
*/
public static class LTDoubleComputer implements Computer
{
public boolean compare(Object objOne, Object objTwo)
{
Number s1 = (Number) objOne;
Number s2 = (Number) objTwo;
return s1.doubleValue() < s2.doubleValue();
}
}
/**
* Computer for relational op compare.
*/
public static class LEDoubleComputer implements Computer
{
public boolean compare(Object objOne, Object objTwo)
{
Number s1 = (Number) objOne;
Number s2 = (Number) objTwo;
return s1.doubleValue() <= s2.doubleValue();
}
}
/**
* Computer for relational op compare.
*/
public static class GTFloatComputer implements Computer
{
public boolean compare(Object objOne, Object objTwo)
{
Number s1 = (Number) objOne;
Number s2 = (Number) objTwo;
return s1.floatValue() > s2.floatValue();
}
}
/**
* Computer for relational op compare.
*/
public static class GEFloatComputer implements Computer
{
public boolean compare(Object objOne, Object objTwo)
{
Number s1 = (Number) objOne;
Number s2 = (Number) objTwo;
return s1.floatValue() >= s2.floatValue();
}
}
/**
* Computer for relational op compare.
*/
public static class LTFloatComputer implements Computer
{
public boolean compare(Object objOne, Object objTwo)
{
Number s1 = (Number) objOne;
Number s2 = (Number) objTwo;
return s1.floatValue() < s2.floatValue();
}
}
/**
* Computer for relational op compare.
*/
public static class LEFloatComputer implements Computer
{
public boolean compare(Object objOne, Object objTwo)
{
Number s1 = (Number) objOne;
Number s2 = (Number) objTwo;
return s1.floatValue() <= s2.floatValue();
}
}
/**
* Computer for relational op compare.
*/
public static class GTBigDecComputer implements Computer
{
public boolean compare(Object objOne, Object objTwo)
{
BigDecimal s1 = (BigDecimal) objOne;
BigDecimal s2 = (BigDecimal) objTwo;
int result = s1.compareTo(s2);
return result > 0;
}
}
/**
* Computer for relational op compare.
*/
public static class GEBigDecComputer implements Computer
{
public boolean compare(Object objOne, Object objTwo)
{
BigDecimal s1 = (BigDecimal) objOne;
BigDecimal s2 = (BigDecimal) objTwo;
return s1.compareTo(s2) >= 0;
}
}
/**
* Computer for relational op compare.
*/
public static class LEBigDecComputer implements Computer
{
public boolean compare(Object objOne, Object objTwo)
{
BigDecimal s1 = (BigDecimal) objOne;
BigDecimal s2 = (BigDecimal) objTwo;
return s1.compareTo(s2) <= 0;
}
}
/**
* Computer for relational op compare.
*/
public static class LTBigDecComputer implements Computer
{
public boolean compare(Object objOne, Object objTwo)
{
BigDecimal s1 = (BigDecimal) objOne;
BigDecimal s2 = (BigDecimal) objTwo;
return s1.compareTo(s2) < 0;
}
}
/**
* Computer for relational op compare.
*/
public static class GTBigIntComputer implements Computer
{
public boolean compare(Object objOne, Object objTwo)
{
BigInteger s1 = (BigInteger) objOne;
BigInteger s2 = (BigInteger) objTwo;
int result = s1.compareTo(s2);
return result > 0;
}
}
/**
* Computer for relational op compare.
*/
public static class GEBigIntComputer implements Computer
{
public boolean compare(Object objOne, Object objTwo)
{
BigInteger s1 = (BigInteger) objOne;
BigInteger s2 = (BigInteger) objTwo;
return s1.compareTo(s2) >= 0;
}
}
/**
* Computer for relational op compare.
*/
public static class LEBigIntComputer implements Computer
{
public boolean compare(Object objOne, Object objTwo)
{
BigInteger s1 = (BigInteger) objOne;
BigInteger s2 = (BigInteger) objTwo;
return s1.compareTo(s2) <= 0;
}
}
/**
* Computer for relational op compare.
*/
public static class LTBigIntComputer implements Computer
{
public boolean compare(Object objOne, Object objTwo)
{
BigInteger s1 = (BigInteger) objOne;
BigInteger s2 = (BigInteger) objTwo;
return s1.compareTo(s2) < 0;
}
}
/**
* Computer for relational op compare.
*/
public static class GTBigIntConvComputer implements Computer
{
private final SimpleNumberBigIntegerCoercer convOne;
private final SimpleNumberBigIntegerCoercer convTwo;
/**
* Ctor.
* @param convOne convertor for LHS
* @param convTwo convertor for RHS
*/
public GTBigIntConvComputer(SimpleNumberBigIntegerCoercer convOne, SimpleNumberBigIntegerCoercer convTwo)
{
this.convOne = convOne;
this.convTwo = convTwo;
}
public boolean compare(Object objOne, Object objTwo)
{
BigInteger s1 = convOne.coerceBoxedBigInt((Number)objOne);
BigInteger s2 = convTwo.coerceBoxedBigInt((Number)objTwo);
int result = s1.compareTo(s2);
return result > 0;
}
}
/**
* Computer for relational op compare.
*/
public static class GEBigIntConvComputer implements Computer
{
private final SimpleNumberBigIntegerCoercer convOne;
private final SimpleNumberBigIntegerCoercer convTwo;
/**
* Ctor.
* @param convOne convertor for LHS
* @param convTwo convertor for RHS
*/
public GEBigIntConvComputer(SimpleNumberBigIntegerCoercer convOne, SimpleNumberBigIntegerCoercer convTwo)
{
this.convOne = convOne;
this.convTwo = convTwo;
}
public boolean compare(Object objOne, Object objTwo)
{
BigInteger s1 = convOne.coerceBoxedBigInt((Number)objOne);
BigInteger s2 = convTwo.coerceBoxedBigInt((Number)objTwo);
return s1.compareTo(s2) >= 0;
}
}
/**
* Computer for relational op compare.
*/
public static class LEBigIntConvComputer implements Computer
{
private final SimpleNumberBigIntegerCoercer convOne;
private final SimpleNumberBigIntegerCoercer convTwo;
/**
* Ctor.
* @param convOne convertor for LHS
* @param convTwo convertor for RHS
*/
public LEBigIntConvComputer(SimpleNumberBigIntegerCoercer convOne, SimpleNumberBigIntegerCoercer convTwo)
{
this.convOne = convOne;
this.convTwo = convTwo;
}
public boolean compare(Object objOne, Object objTwo)
{
BigInteger s1 = convOne.coerceBoxedBigInt((Number)objOne);
BigInteger s2 = convTwo.coerceBoxedBigInt((Number)objTwo);
return s1.compareTo(s2) <= 0;
}
}
/**
* Computer for relational op compare.
*/
public static class LTBigIntConvComputer implements Computer
{
private final SimpleNumberBigIntegerCoercer convOne;
private final SimpleNumberBigIntegerCoercer convTwo;
/**
* Ctor.
* @param convOne convertor for LHS
* @param convTwo convertor for RHS
*/
public LTBigIntConvComputer(SimpleNumberBigIntegerCoercer convOne, SimpleNumberBigIntegerCoercer convTwo)
{
this.convOne = convOne;
this.convTwo = convTwo;
}
public boolean compare(Object objOne, Object objTwo)
{
BigInteger s1 = convOne.coerceBoxedBigInt((Number)objOne);
BigInteger s2 = convTwo.coerceBoxedBigInt((Number)objTwo);
return s1.compareTo(s2) < 0;
}
}
/**
* Computer for relational op compare.
*/
public static class GTBigDecConvComputer implements Computer
{
private final SimpleNumberBigDecimalCoercer convOne;
private final SimpleNumberBigDecimalCoercer convTwo;
/**
* Ctor.
* @param convOne convertor for LHS
* @param convTwo convertor for RHS
*/
public GTBigDecConvComputer(SimpleNumberBigDecimalCoercer convOne, SimpleNumberBigDecimalCoercer convTwo)
{
this.convOne = convOne;
this.convTwo = convTwo;
}
public boolean compare(Object objOne, Object objTwo)
{
BigDecimal s1 = convOne.coerceBoxedBigDec((Number)objOne);
BigDecimal s2 = convTwo.coerceBoxedBigDec((Number)objTwo);
int result = s1.compareTo(s2);
return result > 0;
}
}
/**
* Computer for relational op compare.
*/
public static class GEBigDecConvComputer implements Computer
{
private final SimpleNumberBigDecimalCoercer convOne;
private final SimpleNumberBigDecimalCoercer convTwo;
/**
* Ctor.
* @param convOne convertor for LHS
* @param convTwo convertor for RHS
*/
public GEBigDecConvComputer(SimpleNumberBigDecimalCoercer convOne, SimpleNumberBigDecimalCoercer convTwo)
{
this.convOne = convOne;
this.convTwo = convTwo;
}
public boolean compare(Object objOne, Object objTwo)
{
BigDecimal s1 = convOne.coerceBoxedBigDec((Number)objOne);
BigDecimal s2 = convTwo.coerceBoxedBigDec((Number)objTwo);
return s1.compareTo(s2) >= 0;
}
}
/**
* Computer for relational op compare.
*/
public static class LEBigDecConvComputer implements Computer
{
private final SimpleNumberBigDecimalCoercer convOne;
private final SimpleNumberBigDecimalCoercer convTwo;
/**
* Ctor.
* @param convOne convertor for LHS
* @param convTwo convertor for RHS
*/
public LEBigDecConvComputer(SimpleNumberBigDecimalCoercer convOne, SimpleNumberBigDecimalCoercer convTwo)
{
this.convOne = convOne;
this.convTwo = convTwo;
}
public boolean compare(Object objOne, Object objTwo)
{
BigDecimal s1 = convOne.coerceBoxedBigDec((Number)objOne);
BigDecimal s2 = convTwo.coerceBoxedBigDec((Number)objTwo);
return s1.compareTo(s2) <= 0;
}
}
/**
* Computer for relational op compare.
*/
public static class LTBigDecConvComputer implements Computer
{
private final SimpleNumberBigDecimalCoercer convOne;
private final SimpleNumberBigDecimalCoercer convTwo;
/**
* Ctor.
* @param convOne convertor for LHS
* @param convTwo convertor for RHS
*/
public LTBigDecConvComputer(SimpleNumberBigDecimalCoercer convOne, SimpleNumberBigDecimalCoercer convTwo)
{
this.convOne = convOne;
this.convTwo = convTwo;
}
public boolean compare(Object objOne, Object objTwo)
{
BigDecimal s1 = convOne.coerceBoxedBigDec((Number)objOne);
BigDecimal s2 = convTwo.coerceBoxedBigDec((Number)objTwo);
return s1.compareTo(s2) < 0;
}
}
/**
* Returns string rendering of enum.
* @return relational op string
*/
public String getExpressionText()
{
return expressionText;
}
}