1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.krms.framework.engine.expression;
17
18 import org.apache.commons.lang.ObjectUtils;
19 import org.kuali.rice.core.api.mo.common.Coded;
20 import org.kuali.rice.krms.api.engine.IncompatibleTypeException;
21
22 import java.lang.reflect.InvocationTargetException;
23 import java.math.BigDecimal;
24 import java.math.BigInteger;
25
26 public enum ComparisonOperator implements Coded {
27
28 EQUALS("="),
29 NOT_EQUALS("!="),
30 GREATER_THAN(">"),
31 GREATER_THAN_EQUAL(">="),
32 LESS_THAN("<"),
33 LESS_THAN_EQUAL("<=");
34
35 private final String code;
36
37 private ComparisonOperator(String code) {
38 this.code = code;
39 }
40
41 public String getCode() {
42 return code;
43 }
44
45 public static ComparisonOperator fromCode(String code) {
46 if (code == null) {
47 return null;
48 }
49 for (ComparisonOperator comparisonOperator : values()) {
50 if (comparisonOperator.code.equals(code)) {
51 return comparisonOperator;
52 }
53 }
54 throw new IllegalArgumentException("Failed to locate the ComparisionOperator with the given code: " + code);
55 }
56
57 private Object coerceRhs(Object lhs, Object rhs) {
58 if (lhs != null && rhs != null) {
59 if (!lhs.getClass().equals(rhs.getClass()) && rhs instanceof String) {
60 rhs = coerceRhsHelper(lhs, rhs.toString(), Double.class, Float.class, Long.class, Integer.class);
61
62 if (rhs instanceof String) {
63 if (lhs instanceof BigDecimal) {
64 try {
65 rhs = BigDecimal.valueOf(Double.valueOf(rhs.toString()));
66 } catch (NumberFormatException e) {
67 throw new IncompatibleTypeException("Could not coerce String to BigDecimal" + this, rhs, lhs.getClass());
68 }
69 } else if (lhs instanceof BigInteger) {
70 try {
71 rhs = BigInteger.valueOf(Long.valueOf(rhs.toString()));
72 } catch (NumberFormatException e) {
73 throw new IncompatibleTypeException("Could not coerce String to BigInteger" + this, rhs, lhs.getClass());
74 }
75 } else {
76 throw new IncompatibleTypeException("Could not compare values for operator " + this, lhs, rhs.getClass());
77 }
78 }
79 }
80 }
81 return rhs;
82 }
83
84 private Object coerceRhsHelper(Object lhs, String rhs, Class<?> ... clazzes) {
85 for (Class clazz : clazzes) {
86 if (clazz.isInstance(lhs)) {
87 try {
88 return clazz.getMethod("valueOf", String.class).invoke(null, rhs);
89 } catch (NumberFormatException e) {
90 throw new IncompatibleTypeException("Could not coerce String to " +
91 clazz.getSimpleName() + " " + this, rhs, lhs.getClass());
92 } catch (NoSuchMethodException e) {
93 throw new IncompatibleTypeException("Could not coerce String to " +
94 clazz.getSimpleName() + " " + this, rhs, lhs.getClass());
95 } catch (InvocationTargetException e) {
96 throw new IncompatibleTypeException("Could not coerce String to " +
97 clazz.getSimpleName() + " " + this, rhs, lhs.getClass());
98 } catch (IllegalAccessException e) {
99 throw new IncompatibleTypeException("Could not coerce String to " +
100 clazz.getSimpleName() + " " + this, rhs, lhs.getClass());
101 }
102 }
103 }
104 return rhs;
105 }
106
107 public boolean compare(Object lhs, Object rhs) {
108
109
110
111
112
113 rhs = coerceRhs(lhs, rhs);
114
115 if (this == EQUALS) {
116 return ObjectUtils.equals(lhs, rhs);
117 } else if (this == NOT_EQUALS) {
118 return ObjectUtils.notEqual(lhs, rhs);
119 } else if (lhs == null || rhs == null) {
120
121 return false;
122 }
123 if (lhs instanceof Comparable && rhs instanceof Comparable) {
124
125
126
127
128 int result = ((Comparable)lhs).compareTo(rhs);
129 if (this == GREATER_THAN) {
130 return result > 0;
131 }
132 if (this == GREATER_THAN_EQUAL) {
133 return result >= 0;
134 }
135 if (this == LESS_THAN) {
136 return result < 0;
137 }
138 if (this == LESS_THAN_EQUAL) {
139 return result <= 0;
140 }
141 } else {
142 throw new IncompatibleTypeException("Could not compare values, they are not comparable for operator " + this, lhs, rhs.getClass());
143 }
144 throw new IllegalStateException("Invalid operator detected: " + this);
145 }
146
147 }