1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springmodules.validation.valang.predicates;
18
19 import java.math.BigDecimal;
20 import java.util.ArrayList;
21 import java.util.Collection;
22 import java.util.Date;
23 import java.util.Iterator;
24 import java.util.Set;
25
26 import org.apache.commons.collections.Predicate;
27 import org.apache.commons.collections.functors.AndPredicate;
28 import org.apache.commons.collections.functors.AnyPredicate;
29 import org.apache.commons.collections.functors.FalsePredicate;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32 import org.springframework.util.StringUtils;
33 import org.springmodules.validation.valang.ValangException;
34 import org.springmodules.validation.valang.functions.EnumLiteralFunction;
35 import org.springmodules.validation.valang.functions.Function;
36 import org.springmodules.validation.valang.functions.LiteralFunction;
37
38 /**
39 * <p>GenericTestPredicate can test if a property value is null or not null.
40 *
41 * @author Steven Devijver
42 * @since 23-04-2005
43 */
44 public class GenericTestPredicate extends AbstractPropertyPredicate {
45
46 final Logger logger = LoggerFactory.getLogger(GenericTestPredicate.class);
47
48 /**
49 * <p>Constructor taking two functions and an operator.
50 *
51 * @param leftFunction the left function
52 * @param operator the operator.
53 */
54 public GenericTestPredicate(Function leftFunction, Operator operator, Function rightFunction, int line, int column) {
55 super(leftFunction, operator, rightFunction, line, column);
56 }
57
58
59 /**
60 * <p>The evaluate method takes the result of both functions and tests with the operator.
61 *
62 * @param target The target bean.
63 * @return boolean Whether or not the test passed.
64 */
65 public boolean evaluate(Object target) {
66 Object leftValue = getLeftFunction().getResult(target);
67 Object rightValue = null;
68 boolean dates = false;
69 boolean numbers = false;
70
71 if (getRightFunction() != null) {
72 rightValue = getRightFunction().getResult(target);
73 }
74
75 if (leftValue instanceof Number) {
76 leftValue = new BigDecimal(leftValue.toString());
77 }
78 if (rightValue instanceof Number) {
79 rightValue = new BigDecimal(rightValue.toString());
80 }
81
82 dates = leftValue instanceof Date && rightValue instanceof Date;
83 numbers = leftValue instanceof BigDecimal && rightValue instanceof BigDecimal;
84
85 if (getOperator() instanceof Operator.NullOperator) {
86 return leftValue == null;
87 } else if (getOperator() instanceof Operator.NotNullOperator) {
88 return leftValue != null;
89 } else if (getOperator() instanceof Operator.EqualsOperator) {
90 if (leftValue instanceof BigDecimal && rightValue instanceof BigDecimal) {
91 return ((BigDecimal) leftValue).compareTo((BigDecimal) rightValue) == 0;
92 } else if (dates) {
93 return ((Date) leftValue).getTime() == ((Date) rightValue).getTime();
94
95 } else if (getLeftFunction() instanceof EnumLiteralFunction || getRightFunction() instanceof EnumLiteralFunction) {
96 Enum<?> enumValue = null;
97 Enum<?> convertedEnumValue = null;
98 String value = null;
99
100 try {
101 if (getRightFunction() instanceof EnumLiteralFunction) {
102 enumValue = (Enum<?>) leftValue;
103 value = rightValue.toString().trim();
104 } else if (getLeftFunction() instanceof EnumLiteralFunction) {
105 enumValue = (Enum<?>) rightValue;
106 value = leftValue.toString().trim();
107 }
108
109
110 Class<?> enumClass = enumValue.getClass();
111 convertedEnumValue = (Enum<?>) enumClass.getField(value).get(null);
112
113 return enumValue.equals(convertedEnumValue);
114 } catch (Throwable e) {
115 throw new ValangException("Field [" + value + "] isn't an enum value on " + enumValue.getClass().getName() + ".",
116 getLine(), getColumn());
117 }
118 } else {
119 return leftValue.equals(rightValue);
120 }
121 } else if (getOperator() instanceof Operator.NotEqualsOperator) {
122 if (leftValue instanceof BigDecimal && rightValue instanceof BigDecimal) {
123 return ((BigDecimal) leftValue).compareTo((BigDecimal) rightValue) != 0;
124 } else if (dates) {
125 return ((Date) leftValue).getTime() != ((Date) rightValue).getTime();
126 } else {
127 return !leftValue.equals(rightValue);
128 }
129 } else if (getOperator() instanceof Operator.LessThanOperator) {
130 if (dates) {
131 return ((Date) leftValue).getTime() < ((Date) rightValue).getTime();
132 } else if (numbers) {
133 return ((BigDecimal) leftValue).compareTo((BigDecimal) rightValue) < 0;
134 } else {
135 throw new ValangException("< operator only supports two date or two number values!", getLine(), getColumn());
136 }
137 } else if (getOperator() instanceof Operator.LessThanOrEqualOperator) {
138 if (dates) {
139 return ((Date) leftValue).getTime() <= ((Date) rightValue).getTime();
140 } else if (numbers) {
141 return ((BigDecimal) leftValue).compareTo((BigDecimal) rightValue) <= 0;
142 } else {
143 throw new ValangException("<= operator only supports two date or two number values!", getLine(), getColumn());
144 }
145 } else if (getOperator() instanceof Operator.MoreThanOperator) {
146 if (dates) {
147 return ((Date) leftValue).getTime() > ((Date) rightValue).getTime();
148 } else if (numbers) {
149 return ((BigDecimal) leftValue).compareTo((BigDecimal) rightValue) > 0;
150 } else {
151 throw new ValangException("> operator only supports two date or two number values!", getLine(), getColumn());
152 }
153 } else if (getOperator() instanceof Operator.MoreThanOrEqualOperator) {
154 if (dates) {
155 return ((Date) leftValue).getTime() >= ((Date) rightValue).getTime();
156 } else if (numbers) {
157 return ((BigDecimal) leftValue).compareTo((BigDecimal) rightValue) >= 0;
158 } else {
159 throw new IllegalArgumentException(">= operator only supports two date or two number values!");
160 }
161 } else if (getOperator() instanceof Operator.InOperator) {
162 Collection<Predicate> predicates = new ArrayList<Predicate>();
163
164
165 if (rightValue instanceof Set) {
166 Set<?> lComparisonValues = (Set<?>) rightValue;
167
168 return lComparisonValues.contains(leftValue);
169 } else {
170 for (Iterator iter = getIterator(rightValue); iter.hasNext();) {
171 Object o = iter.next();
172 if (o instanceof Function) {
173 predicates.add(getPredicate(new LiteralFunction(leftValue), OperatorConstants.EQUALS_OPERATOR, (Function) o, getLine(), getColumn()));
174 } else {
175 predicates.add(getPredicate(new LiteralFunction(leftValue), OperatorConstants.EQUALS_OPERATOR, new LiteralFunction(o), getLine(), getColumn()));
176 }
177 }
178
179 if (predicates.isEmpty()) {
180 throw new IllegalStateException("IN expression contains no elements!");
181 } else if (predicates.size() == 1) {
182 predicates.add(FalsePredicate.getInstance());
183 }
184
185 return AnyPredicate.getInstance(predicates).evaluate(target);
186 }
187 } else if (getOperator() instanceof Operator.NotInOperator) {
188 Collection<Predicate> predicates = new ArrayList<Predicate>();
189
190 for (Iterator iter = getIterator(rightValue); iter.hasNext();) {
191 Object o = iter.next();
192 if (o instanceof Function) {
193 predicates.add(getPredicate(new LiteralFunction(leftValue), OperatorConstants.EQUALS_OPERATOR, (Function) o, getLine(), getColumn()));
194 } else {
195 predicates.add(getPredicate(new LiteralFunction(leftValue), OperatorConstants.EQUALS_OPERATOR, new LiteralFunction(o), getLine(), getColumn()));
196 }
197 }
198 if (predicates.isEmpty()) {
199 throw new IllegalStateException("NOT IN expression contains no elements!");
200 } else if (predicates.size() == 1) {
201 predicates.add(FalsePredicate.getInstance());
202 }
203 return !AnyPredicate.getInstance(predicates).evaluate(target);
204 } else if (getOperator() instanceof Operator.BetweenOperator) {
205 Object[] array = getArray(rightValue);
206 Predicate predicate1 = getPredicate(new LiteralFunction(leftValue), OperatorConstants.MORE_THAN_OR_EQUAL_OPERATOR, (Function) array[0], getLine(), getColumn());
207 Predicate predicate2 = getPredicate(new LiteralFunction(leftValue), OperatorConstants.LESS_THAN_OR_EQUAL_OPERATOR, (Function) array[1], getLine(), getColumn());
208 return AndPredicate.getInstance(predicate1, predicate2).evaluate(target);
209 } else if (getOperator() instanceof Operator.NotBetweenOperator) {
210 Object[] array = getArray(rightValue);
211 Predicate predicate1 = getPredicate(new LiteralFunction(leftValue), OperatorConstants.MORE_THAN_OR_EQUAL_OPERATOR, (Function) array[0], getLine(), getColumn());
212 Predicate predicate2 = getPredicate(new LiteralFunction(leftValue), OperatorConstants.LESS_THAN_OR_EQUAL_OPERATOR, (Function) array[1], getLine(), getColumn());
213 return !AndPredicate.getInstance(predicate1, predicate2).evaluate(target);
214 } else if (getOperator() instanceof Operator.HasLengthOperator) {
215 return StringUtils.hasLength(leftValue != null ? leftValue.toString() : null);
216 } else if (getOperator() instanceof Operator.HasNoLengthOperator) {
217 return !StringUtils.hasLength(leftValue != null ? leftValue.toString() : null);
218 } else if (getOperator() instanceof Operator.HasTextOperator) {
219 return StringUtils.hasText(leftValue != null ? leftValue.toString() : null);
220 } else if (getOperator() instanceof Operator.HasNoTextOperator) {
221 return !StringUtils.hasText(leftValue != null ? leftValue.toString() : null);
222 } else if (getOperator() instanceof Operator.IsBlankOperator) {
223 return isBlank(leftValue != null ? leftValue.toString() : null);
224 } else if (getOperator() instanceof Operator.IsNotBlankOperator) {
225 return !isBlank(leftValue != null ? leftValue.toString() : null);
226 } else if (getOperator() instanceof Operator.IsWordOperator) {
227 return isWord(leftValue != null ? leftValue.toString() : null);
228 } else if (getOperator() instanceof Operator.IsNotWordOperator) {
229 return !isWord(leftValue != null ? leftValue.toString() : null);
230 } else if (getOperator() instanceof Operator.IsLowerCaseOperator) {
231 return isLowerCase(leftValue != null ? leftValue.toString() : null);
232 } else if (getOperator() instanceof Operator.IsNotLowerCaseOperator) {
233 return !isLowerCase(leftValue != null ? leftValue.toString() : null);
234 } else if (getOperator() instanceof Operator.IsUpperCaseOperator) {
235 return isUpperCase(leftValue != null ? leftValue.toString() : null);
236 } else if (getOperator() instanceof Operator.IsNotUpperCaseOperator) {
237 return !isUpperCase(leftValue != null ? leftValue.toString() : null);
238 }
239
240 throw new IllegalStateException("Operator class [" + getOperator().getClass().getName() + "] not supported!");
241 }
242
243 protected Predicate getPredicate(Function leftFunction, Operator operator, Function rightFunction, int line, int column) {
244 return new GenericTestPredicate(leftFunction, operator, rightFunction, line, column);
245 }
246
247 private boolean isWord(String s) {
248 return s != null && s.length() > 0 &&
249 deleteWhitespace(s).equals(s);
250 }
251
252 private boolean isLowerCase(String s) {
253 return s.length() > 0 &&
254 s.toLowerCase().equals(s);
255 }
256
257 private boolean isUpperCase(String s) {
258 return s.length() > 0 &&
259 s.toUpperCase().equals(s);
260 }
261
262 private boolean isBlank(String s) {
263 return s == null || s.length() == 0;
264 }
265
266 private String deleteWhitespace(String s) {
267 return StringUtils.deleteAny(s, " \t\r\n\b");
268 }
269 }