/************************************************************************************** * 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; } }