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 java.math.BigDecimal;
19 import java.util.Date;
20
21 import org.kuali.rice.core.api.data.DataType;
22 import org.kuali.rice.core.api.util.RiceKeyConstants;
23 import org.kuali.rice.krad.datadictionary.exception.AttributeValidationException;
24 import org.kuali.rice.krad.datadictionary.validation.AttributeValueReader;
25 import org.kuali.rice.krad.datadictionary.validation.ValidationUtils;
26 import org.kuali.rice.krad.datadictionary.validation.ValidationUtils.Result;
27 import org.kuali.rice.krad.datadictionary.validation.capability.RangeConstrainable;
28 import org.kuali.rice.krad.datadictionary.validation.constraint.Constraint;
29 import org.kuali.rice.krad.datadictionary.validation.constraint.RangeConstraint;
30 import org.kuali.rice.krad.datadictionary.validation.result.ConstraintValidationResult;
31 import org.kuali.rice.krad.datadictionary.validation.result.DictionaryValidationResult;
32 import org.kuali.rice.krad.datadictionary.validation.result.ProcessorResult;
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
88 protected ConstraintValidationResult processSingleRangeConstraint(DictionaryValidationResult result, Object value,
89 RangeConstraint constraint, AttributeValueReader attributeValueReader) throws AttributeValidationException {
90
91 if (ValidationUtils.isNullOrEmpty(value) || (constraint.getExclusiveMin() == null
92 && constraint.getInclusiveMax() == null)) {
93 return result.addSkipped(attributeValueReader, CONSTRAINT_NAME);
94 }
95
96
97 DataType dataType = constraint.getDataType();
98 Object typedValue = value;
99
100 if (dataType != null) {
101 typedValue = ValidationUtils.convertToDataType(value, dataType, dateTimeService);
102 } else if (value instanceof String) {
103
104 try {
105 Double d = Double.parseDouble((String) value);
106 typedValue = d;
107 } catch (NumberFormatException n) {
108
109 }
110 }
111
112
113 if (typedValue instanceof Date) {
114 return validateRange(result, (Date) typedValue, constraint, attributeValueReader);
115 } else if (typedValue instanceof Number) {
116 return validateRange(result, (Number) typedValue, constraint, attributeValueReader);
117 }
118
119 return result.addSkipped(attributeValueReader, CONSTRAINT_NAME);
120 }
121
122
123
124
125
126
127
128
129
130
131
132 protected ConstraintValidationResult validateRange(DictionaryValidationResult result, Date value,
133 RangeConstraint constraint, AttributeValueReader attributeValueReader) throws IllegalArgumentException {
134
135 Date date = value != null ? ValidationUtils.getDate(value, dateTimeService) : null;
136
137 String inclusiveMaxText = constraint.getInclusiveMax();
138 String exclusiveMinText = constraint.getExclusiveMin();
139
140 Date inclusiveMax = inclusiveMaxText != null ? ValidationUtils.getDate(inclusiveMaxText, dateTimeService) :
141 null;
142 Date exclusiveMin = exclusiveMinText != null ? ValidationUtils.getDate(exclusiveMinText, dateTimeService) :
143 null;
144
145 return isInRange(result, date, inclusiveMax, inclusiveMaxText, exclusiveMin, exclusiveMinText,
146 attributeValueReader);
147 }
148
149
150
151
152
153
154
155
156
157
158
159 protected ConstraintValidationResult validateRange(DictionaryValidationResult result, Number value,
160 RangeConstraint constraint, AttributeValueReader attributeValueReader) throws IllegalArgumentException {
161
162
163
164 BigDecimal number = value != null ? new BigDecimal(value.toString()) : null;
165
166 String inclusiveMaxText = constraint.getInclusiveMax();
167 String exclusiveMinText = constraint.getExclusiveMin();
168
169 BigDecimal inclusiveMax = inclusiveMaxText != null ? new BigDecimal(inclusiveMaxText) : null;
170 BigDecimal exclusiveMin = exclusiveMinText != null ? new BigDecimal(exclusiveMinText) : null;
171
172 return isInRange(result, number, inclusiveMax, inclusiveMaxText, exclusiveMin, exclusiveMinText,
173 attributeValueReader);
174 }
175
176
177
178
179
180
181
182
183
184
185
186
187
188 private <T> ConstraintValidationResult isInRange(DictionaryValidationResult result, T value,
189 Comparable<T> inclusiveMax, String inclusiveMaxText, Comparable<T> exclusiveMin, String exclusiveMinText,
190 AttributeValueReader attributeValueReader) {
191
192 Result lessThanMax = ValidationUtils.isLessThanOrEqual(value, inclusiveMax);
193
194 Result greaterThanMin = ValidationUtils.isGreaterThan(value, exclusiveMin);
195
196
197 if (lessThanMax != Result.INVALID && greaterThanMin != Result.INVALID) {
198
199 if (lessThanMax == Result.UNDEFINED && greaterThanMin == Result.UNDEFINED) {
200 return result.addNoConstraint(attributeValueReader, CONSTRAINT_NAME);
201 }
202
203
204 return result.addSuccess(attributeValueReader, CONSTRAINT_NAME);
205 }
206
207
208 if (lessThanMax != Result.UNDEFINED && greaterThanMin != Result.UNDEFINED) {
209 return result.addError(RANGE_KEY, attributeValueReader, CONSTRAINT_NAME,
210 RiceKeyConstants.ERROR_OUT_OF_RANGE, exclusiveMinText, inclusiveMaxText);
211 }
212
213 else if (lessThanMax == Result.INVALID) {
214 return result.addError(MAX_INCLUSIVE_KEY, attributeValueReader, CONSTRAINT_NAME,
215 RiceKeyConstants.ERROR_INCLUSIVE_MAX, inclusiveMaxText);
216 }
217
218 else {
219 return result.addError(MIN_EXCLUSIVE_KEY, attributeValueReader, CONSTRAINT_NAME,
220 RiceKeyConstants.ERROR_EXCLUSIVE_MIN, exclusiveMinText);
221 }
222 }
223
224 }