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.krms.api.engine.IncompatibleTypeException;
20
21 import java.lang.reflect.Constructor;
22 import java.lang.reflect.InvocationTargetException;
23 import java.math.BigDecimal;
24 import java.math.BigInteger;
25
26
27
28
29
30
31
32
33
34 public class DefaultComparisonOperator implements EngineComparatorExtension, StringCoercionExtension {
35
36 @Override
37 public int compare(Object lhs, Object rhs) {
38
39 if (lhs == null && rhs == null) {
40 return 0;
41 } else if (lhs == null) {
42 return -1;
43 } else if (rhs == null) {
44 return 1;
45 }
46
47 if (rhs instanceof String && !(lhs instanceof String)) {
48 rhs = coerceStringOperand(lhs, rhs.toString());
49 } else if (lhs instanceof String && !(rhs instanceof String)) {
50 lhs = coerceStringOperand(rhs, lhs.toString());
51 }
52
53
54 if (ObjectUtils.equals(lhs, rhs)) {
55 return 0;
56 }
57
58 if (lhs instanceof Comparable && rhs instanceof Comparable) {
59 int result = ((Comparable)lhs).compareTo(rhs);
60 return result;
61 }
62 else {
63 throw new IncompatibleTypeException("DefaultComparisonOperator could not compare values", lhs, rhs.getClass());
64 }
65 }
66
67 @Override
68 public boolean canCompare(Object lhs, Object rhs) {
69 try {
70 compare(lhs, rhs);
71 return true;
72 } catch (Exception e) {
73 return false;
74 }
75 }
76
77
78
79
80
81
82
83
84 private Object coerceStringOperand(Object objectArg, String stringArg) {
85 Object result = stringArg;
86 if (objectArg != null && stringArg != null) {
87 if (!(objectArg instanceof String)) {
88 result = coerceHelper(objectArg, stringArg, Double.class, Float.class, Long.class, Integer.class, Boolean.class);
89
90 if (result instanceof String) {
91 if (objectArg instanceof BigDecimal) {
92 try {
93 result = BigDecimal.valueOf(Double.valueOf(stringArg.toString()));
94 } catch (NumberFormatException e) {
95 throw new IncompatibleTypeException("Could not coerce String to BigDecimal" + this, stringArg, objectArg.getClass());
96 }
97 } else if (objectArg instanceof BigInteger) {
98 try {
99 result = BigInteger.valueOf(Long.valueOf(stringArg.toString()));
100 } catch (NumberFormatException e) {
101 throw new IncompatibleTypeException("Could not coerce String to BigInteger" + this, stringArg, objectArg.getClass());
102 }
103 } else {
104 throw new IncompatibleTypeException("Could not compare values for operator " + this, objectArg, stringArg.getClass());
105 }
106 }
107 }
108 }
109 return result;
110 }
111
112
113
114
115
116
117
118
119 private Object coerceHelper(Object objectArg, String stringArg, Class<?> ... clazzes) {
120 for (Class clazz : clazzes) {
121 if (clazz.isInstance(objectArg)) {
122 try {
123 return clazz.getMethod("valueOf", String.class).invoke(null, stringArg);
124 } catch (NumberFormatException e) {
125 throw new IncompatibleTypeException("Could not coerce String to " +
126 clazz.getSimpleName() + " " + this, stringArg, objectArg.getClass());
127 } catch (NoSuchMethodException e) {
128 throw new IncompatibleTypeException("Could not coerce String to " +
129 clazz.getSimpleName() + " " + this, stringArg, objectArg.getClass());
130 } catch (InvocationTargetException e) {
131 throw new IncompatibleTypeException("Could not coerce String to " +
132 clazz.getSimpleName() + " " + this, stringArg, objectArg.getClass());
133 } catch (IllegalAccessException e) {
134 throw new IncompatibleTypeException("Could not coerce String to " +
135 clazz.getSimpleName() + " " + this, stringArg, objectArg.getClass());
136 }
137 }
138 }
139 return stringArg;
140 }
141
142 @Override
143 public Object coerce(String type, String value) {
144 try {
145 Class clazz = Class.forName(type);
146
147 Constructor constructor = clazz.getConstructor(new Class[]{String.class});
148 Object propObject = constructor.newInstance(value);
149 return propObject;
150 } catch (Exception e) {
151 return null;
152 }
153 }
154
155 @Override
156 public boolean canCoerce(String type, String value) {
157 return coerce(type, value) != null;
158 }
159 }