1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.krad.datadictionary.validation.processor;
17
18 import org.kuali.rice.core.api.uif.DataType;
19 import org.kuali.rice.core.api.util.RiceKeyConstants;
20 import org.kuali.rice.krad.datadictionary.exception.AttributeValidationException;
21 import org.kuali.rice.krad.datadictionary.validation.AttributeValueReader;
22 import org.kuali.rice.krad.datadictionary.validation.ValidationUtils;
23 import org.kuali.rice.krad.datadictionary.validation.ValidationUtils.Result;
24 import org.kuali.rice.krad.datadictionary.validation.capability.RangeConstrainable;
25 import org.kuali.rice.krad.datadictionary.validation.constraint.Constraint;
26 import org.kuali.rice.krad.datadictionary.validation.constraint.RangeConstraint;
27 import org.kuali.rice.krad.datadictionary.validation.result.ConstraintValidationResult;
28 import org.kuali.rice.krad.datadictionary.validation.result.DictionaryValidationResult;
29 import org.kuali.rice.krad.datadictionary.validation.result.ProcessorResult;
30
31 import java.math.BigDecimal;
32 import java.util.Date;
33
34
35
36
37
38
39
40
41
42
43
44
45 public class RangeConstraintProcessor extends MandatoryElementConstraintProcessor<RangeConstraint> {
46
47 private static final String CONSTRAINT_NAME = "range constraint";
48 private static final String MIN_EXCLUSIVE_KEY = "validation.minExclusive";
49 private static final String MAX_INCLUSIVE_KEY = "validation.maxInclusive";
50 private static final String RANGE_KEY = "validation.range";
51
52
53
54
55
56
57 @Override
58 public ProcessorResult process(DictionaryValidationResult result, Object value, RangeConstraint constraint,
59 AttributeValueReader attributeValueReader) throws AttributeValidationException {
60
61
62 return new ProcessorResult(processSingleRangeConstraint(result, value, constraint, attributeValueReader));
63 }
64
65 @Override
66 public String getName() {
67 return CONSTRAINT_NAME;
68 }
69
70
71
72
73 @Override
74 public Class<? extends Constraint> getConstraintType() {
75 return RangeConstraint.class;
76 }
77
78
79
80
81
82
83
84
85
86
87 protected ConstraintValidationResult processSingleRangeConstraint(DictionaryValidationResult result, Object value,
88 RangeConstraint constraint, AttributeValueReader attributeValueReader) throws AttributeValidationException {
89
90 if (ValidationUtils.isNullOrEmpty(value) || (constraint.getExclusiveMin() == null
91 && constraint.getInclusiveMax() == null)) {
92 return result.addSkipped(attributeValueReader, CONSTRAINT_NAME);
93 }
94
95
96 DataType dataType = constraint.getDataType();
97 Object typedValue = value;
98
99 if (dataType != null) {
100 typedValue = ValidationUtils.convertToDataType(value, dataType, dateTimeService);
101 } else if (value instanceof String) {
102
103 try {
104 Double d = Double.parseDouble((String) value);
105 typedValue = d;
106 } catch (NumberFormatException n) {
107
108 }
109 }
110
111
112 if (typedValue instanceof Date) {
113 return validateRange(result, (Date) typedValue, constraint, attributeValueReader);
114 } else if (typedValue instanceof Number) {
115 return validateRange(result, (Number) typedValue, constraint, attributeValueReader);
116 }
117
118 return result.addSkipped(attributeValueReader, CONSTRAINT_NAME);
119 }
120
121
122
123
124
125
126
127
128
129
130
131 protected ConstraintValidationResult validateRange(DictionaryValidationResult result, Date value,
132 RangeConstraint constraint, AttributeValueReader attributeValueReader) throws IllegalArgumentException {
133
134 Date date = value != null ? ValidationUtils.getDate(value, dateTimeService) : null;
135
136 String inclusiveMaxText = constraint.getInclusiveMax();
137 String exclusiveMinText = constraint.getExclusiveMin();
138
139 Date inclusiveMax = inclusiveMaxText != null ? ValidationUtils.getDate(inclusiveMaxText, dateTimeService) :
140 null;
141 Date exclusiveMin = exclusiveMinText != null ? ValidationUtils.getDate(exclusiveMinText, dateTimeService) :
142 null;
143
144 return isInRange(result, date, inclusiveMax, inclusiveMaxText, exclusiveMin, exclusiveMinText,
145 attributeValueReader);
146 }
147
148
149
150
151
152
153
154
155
156
157
158 protected ConstraintValidationResult validateRange(DictionaryValidationResult result, Number value,
159 RangeConstraint constraint, AttributeValueReader attributeValueReader) throws IllegalArgumentException {
160
161
162
163 BigDecimal number = value != null ? new BigDecimal(value.toString()) : null;
164
165 String inclusiveMaxText = constraint.getInclusiveMax();
166 String exclusiveMinText = constraint.getExclusiveMin();
167
168 BigDecimal inclusiveMax = inclusiveMaxText != null ? new BigDecimal(inclusiveMaxText) : null;
169 BigDecimal exclusiveMin = exclusiveMinText != null ? new BigDecimal(exclusiveMinText) : null;
170
171 return isInRange(result, number, inclusiveMax, inclusiveMaxText, exclusiveMin, exclusiveMinText,
172 attributeValueReader);
173 }
174
175
176
177
178
179
180
181
182
183
184
185
186
187 private <T> ConstraintValidationResult isInRange(DictionaryValidationResult result, T value,
188 Comparable<T> inclusiveMax, String inclusiveMaxText, Comparable<T> exclusiveMin, String exclusiveMinText,
189 AttributeValueReader attributeValueReader) {
190
191 Result lessThanMax = ValidationUtils.isLessThanOrEqual(value, inclusiveMax);
192
193 Result greaterThanMin = ValidationUtils.isGreaterThan(value, exclusiveMin);
194
195
196 if (lessThanMax != Result.INVALID && greaterThanMin != Result.INVALID) {
197
198 if (lessThanMax == Result.UNDEFINED && greaterThanMin == Result.UNDEFINED) {
199 return result.addNoConstraint(attributeValueReader, CONSTRAINT_NAME);
200 }
201
202
203 return result.addSuccess(attributeValueReader, CONSTRAINT_NAME);
204 }
205
206
207 if (lessThanMax != Result.UNDEFINED && greaterThanMin != Result.UNDEFINED) {
208 return result.addError(RANGE_KEY, attributeValueReader, CONSTRAINT_NAME,
209 RiceKeyConstants.ERROR_OUT_OF_RANGE, exclusiveMinText, inclusiveMaxText);
210 }
211
212 else if (lessThanMax == Result.INVALID) {
213 return result.addError(MAX_INCLUSIVE_KEY, attributeValueReader, CONSTRAINT_NAME,
214 RiceKeyConstants.ERROR_INCLUSIVE_MAX, inclusiveMaxText);
215 }
216
217 else {
218 return result.addError(MIN_EXCLUSIVE_KEY, attributeValueReader, CONSTRAINT_NAME,
219 RiceKeyConstants.ERROR_EXCLUSIVE_MIN, exclusiveMinText);
220 }
221 }
222
223 }