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.apache.commons.lang.StringUtils;
19 import org.apache.log4j.Logger;
20 import org.kuali.rice.core.api.CoreApiServiceLocator;
21 import org.kuali.rice.core.api.search.SearchOperator;
22 import org.kuali.rice.core.api.util.ClassLoaderUtils;
23 import org.kuali.rice.core.api.util.RiceKeyConstants;
24 import org.kuali.rice.core.web.format.DateFormatter;
25 import org.kuali.rice.krad.datadictionary.exception.AttributeValidationException;
26 import org.kuali.rice.krad.datadictionary.validation.AttributeValueReader;
27 import org.kuali.rice.krad.datadictionary.validation.ValidationUtils;
28 import org.kuali.rice.krad.datadictionary.validation.capability.Constrainable;
29 import org.kuali.rice.krad.datadictionary.validation.capability.Formatable;
30 import org.kuali.rice.krad.datadictionary.validation.constraint.Constraint;
31 import org.kuali.rice.krad.datadictionary.validation.constraint.ValidCharactersConstraint;
32 import org.kuali.rice.krad.datadictionary.validation.result.ConstraintValidationResult;
33 import org.kuali.rice.krad.datadictionary.validation.result.DictionaryValidationResult;
34 import org.kuali.rice.krad.datadictionary.validation.result.ProcessorResult;
35 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
36 import org.kuali.rice.krad.util.KRADConstants;
37
38 import java.lang.reflect.Method;
39 import java.util.List;
40
41
42
43
44
45
46
47
48
49 public class ValidCharactersConstraintProcessor extends MandatoryElementConstraintProcessor<ValidCharactersConstraint> {
50
51 public static final String VALIDATE_METHOD = "validate";
52
53 private static final Logger LOG = Logger.getLogger(ValidCharactersConstraintProcessor.class);
54 private static final String[] DATE_RANGE_ERROR_PREFIXES = {KRADConstants.LOOKUP_RANGE_LOWER_BOUND_PROPERTY_PREFIX,
55 KRADConstants.LOOKUP_RANGE_UPPER_BOUND_PROPERTY_PREFIX};
56
57 private static final String CONSTRAINT_NAME = "valid characters constraint";
58
59
60
61
62
63
64 @Override
65 public ProcessorResult process(DictionaryValidationResult result, Object value,
66 ValidCharactersConstraint constraint,
67 AttributeValueReader attributeValueReader) throws AttributeValidationException {
68
69 return new ProcessorResult(processSingleValidCharacterConstraint(result, value, constraint,
70 attributeValueReader));
71 }
72
73 @Override
74 public String getName() {
75 return CONSTRAINT_NAME;
76 }
77
78
79
80
81 @Override
82 public Class<? extends Constraint> getConstraintType() {
83 return ValidCharactersConstraint.class;
84 }
85
86 protected ConstraintValidationResult processSingleValidCharacterConstraint(DictionaryValidationResult result,
87 Object value, ValidCharactersConstraint constraint,
88 AttributeValueReader attributeValueReader) throws AttributeValidationException {
89
90 if (constraint == null) {
91 return result.addNoConstraint(attributeValueReader, CONSTRAINT_NAME);
92 }
93
94 if (ValidationUtils.isNullOrEmpty(value)) {
95 return result.addSkipped(attributeValueReader, CONSTRAINT_NAME);
96 }
97
98
99
100 Constrainable definition = attributeValueReader.getDefinition(attributeValueReader.getAttributeName());
101 if (definition instanceof Formatable) {
102 return doProcessFormattableValidCharConstraint(result, constraint, (Formatable) definition, value,
103 attributeValueReader);
104 }
105
106 ConstraintValidationResult constraintValidationResult = doProcessValidCharConstraint(constraint, value);
107 if (constraintValidationResult == null) {
108 return result.addSuccess(attributeValueReader, CONSTRAINT_NAME);
109 }
110
111 result.addConstraintValidationResult(attributeValueReader, constraintValidationResult);
112 constraintValidationResult.setConstraintLabelKey(constraint.getMessageKey());
113 constraintValidationResult.setErrorParameters(constraint.getValidationMessageParamsArray());
114 return constraintValidationResult;
115 }
116
117 protected ConstraintValidationResult doProcessFormattableValidCharConstraint(DictionaryValidationResult result,
118 ValidCharactersConstraint validCharsConstraint, Formatable definition, Object value,
119 AttributeValueReader attributeValueReader) throws AttributeValidationException {
120 String entryName = attributeValueReader.getEntryName();
121 String attributeName = attributeValueReader.getAttributeName();
122
123
124 List<String> parsedAttributeValues = attributeValueReader.getCleanSearchableValues(attributeName);
125
126 if (parsedAttributeValues != null) {
127
128 Class<?> formatterClass = null;
129 Boolean doValidateDateRangeOrder = null;
130
131
132 if (parsedAttributeValues.size() != 2) {
133 doValidateDateRangeOrder = Boolean.FALSE;
134 }
135
136
137 for (int i = 0; i < parsedAttributeValues.size(); i++) {
138 String parsedAttributeValue = parsedAttributeValues.get(i);
139
140 ConstraintValidationResult constraintValidationResult = doProcessValidCharConstraint(
141 validCharsConstraint, parsedAttributeValue);
142
143
144 if (constraintValidationResult != null) {
145 constraintValidationResult.setConstraintLabelKey(validCharsConstraint.getMessageKey());
146 constraintValidationResult.setErrorParameters(
147 validCharsConstraint.getValidationMessageParamsArray());
148
149 if (formatterClass == null) {
150 String formatterClassName = definition.getFormatterClass();
151 if (formatterClassName != null) {
152 formatterClass = ClassLoaderUtils.getClass(formatterClassName);
153 }
154 }
155
156 if (formatterClass != null) {
157
158 if (doValidateDateRangeOrder == null) {
159
160 doValidateDateRangeOrder = Boolean.valueOf(DateFormatter.class.isAssignableFrom(
161 formatterClass) && StringUtils.contains(ValidationUtils.getString(value),
162 SearchOperator.BETWEEN.toString()));
163 }
164
165 constraintValidationResult = processFormatterValidation(result, formatterClass, entryName,
166 attributeName, parsedAttributeValue, DATE_RANGE_ERROR_PREFIXES[i]);
167
168 if (constraintValidationResult != null) {
169 result.addConstraintValidationResult(attributeValueReader, constraintValidationResult);
170 return constraintValidationResult;
171 }
172 } else {
173
174 result.addConstraintValidationResult(attributeValueReader, constraintValidationResult);
175 return constraintValidationResult;
176 }
177 }
178 }
179
180 if (doValidateDateRangeOrder != null && doValidateDateRangeOrder.booleanValue()) {
181 ConstraintValidationResult dateOrderValidationResult = validateDateOrder(parsedAttributeValues.get(0),
182 parsedAttributeValues.get(1), entryName, attributeName);
183
184 if (dateOrderValidationResult != null) {
185 result.addConstraintValidationResult(attributeValueReader, dateOrderValidationResult);
186 return dateOrderValidationResult;
187 }
188 }
189
190 return result.addSuccess(attributeValueReader, CONSTRAINT_NAME);
191 }
192 return result.addSkipped(attributeValueReader, CONSTRAINT_NAME);
193 }
194
195 protected ConstraintValidationResult doProcessValidCharConstraint(ValidCharactersConstraint validCharsConstraint,
196 Object value) {
197
198 StringBuilder fieldValue = new StringBuilder();
199 String validChars = validCharsConstraint.getValue();
200
201 if (value instanceof java.sql.Date) {
202 fieldValue.append(getDateTimeService().toDateString((java.sql.Date) value));
203 } else {
204 fieldValue.append(ValidationUtils.getString(value));
205 }
206
207
208
209
210
211
212
213
214
215
216
217 if (!fieldValue.toString().matches(validChars)) {
218 ConstraintValidationResult constraintValidationResult = new ConstraintValidationResult(CONSTRAINT_NAME);
219 constraintValidationResult.setError(RiceKeyConstants.ERROR_INVALID_FORMAT, fieldValue.toString());
220 constraintValidationResult.setConstraintLabelKey(validCharsConstraint.getMessageKey());
221 constraintValidationResult.setErrorParameters(validCharsConstraint.getValidationMessageParamsArray());
222 return constraintValidationResult;
223 }
224
225
226 return null;
227 }
228
229 protected ConstraintValidationResult processFormatterValidation(DictionaryValidationResult result,
230 Class<?> formatterClass, String entryName, String attributeName, String parsedAttributeValue,
231 String errorKeyPrefix) {
232
233 boolean isError = false;
234
235 try {
236 Method validatorMethod = formatterClass.getDeclaredMethod(VALIDATE_METHOD, new Class<?>[]{String.class});
237 Object o = validatorMethod.invoke(formatterClass.newInstance(), parsedAttributeValue);
238 if (o instanceof Boolean) {
239 isError = !((Boolean) o).booleanValue();
240 }
241 } catch (Exception e) {
242 if (LOG.isDebugEnabled()) {
243 LOG.debug(e.getMessage(), e);
244 }
245
246 isError = true;
247 }
248
249 if (isError) {
250 String errorMessageKey = getDataDictionaryService().getAttributeValidatingErrorMessageKey(entryName,
251 attributeName);
252 String[] errorMessageParameters = getDataDictionaryService().getAttributeValidatingErrorMessageParameters(
253 entryName, attributeName);
254
255 ConstraintValidationResult constraintValidationResult = new ConstraintValidationResult(CONSTRAINT_NAME);
256 constraintValidationResult.setEntryName(entryName);
257 constraintValidationResult.setAttributeName(errorKeyPrefix + attributeName);
258 constraintValidationResult.setError(errorMessageKey, errorMessageParameters);
259
260 return constraintValidationResult;
261 }
262
263 return null;
264 }
265
266 protected ConstraintValidationResult validateDateOrder(String firstDateTime, String secondDateTime,
267 String entryName, String attributeName) {
268
269 java.sql.Timestamp lVal = null;
270 java.sql.Timestamp uVal = null;
271 try {
272 lVal = CoreApiServiceLocator.getDateTimeService().convertToSqlTimestamp(firstDateTime);
273 uVal = CoreApiServiceLocator.getDateTimeService().convertToSqlTimestamp(secondDateTime);
274 } catch (Exception ex) {
275
276 String errorMessageKey =
277 KRADServiceLocatorWeb.getDataDictionaryService().getAttributeValidatingErrorMessageKey(entryName,
278 attributeName);
279 String[] errorMessageParameters =
280 KRADServiceLocatorWeb.getDataDictionaryService().getAttributeValidatingErrorMessageParameters(
281 entryName, attributeName);
282 ConstraintValidationResult constraintValidationResult = new ConstraintValidationResult(CONSTRAINT_NAME);
283 constraintValidationResult.setEntryName(entryName);
284 constraintValidationResult.setAttributeName(
285 KRADConstants.LOOKUP_RANGE_LOWER_BOUND_PROPERTY_PREFIX + attributeName);
286 constraintValidationResult.setError(errorMessageKey, errorMessageParameters);
287 return constraintValidationResult;
288 }
289
290 if (lVal != null && lVal.compareTo(uVal) > 0) {
291 String errorMessageKey =
292 KRADServiceLocatorWeb.getDataDictionaryService().getAttributeValidatingErrorMessageKey(entryName,
293 attributeName);
294 String[] errorMessageParameters =
295 KRADServiceLocatorWeb.getDataDictionaryService().getAttributeValidatingErrorMessageParameters(
296 entryName, attributeName);
297 ConstraintValidationResult constraintValidationResult = new ConstraintValidationResult(CONSTRAINT_NAME);
298 constraintValidationResult.setEntryName(entryName);
299 constraintValidationResult.setAttributeName(
300 KRADConstants.LOOKUP_RANGE_LOWER_BOUND_PROPERTY_PREFIX + attributeName);
301 constraintValidationResult.setError(errorMessageKey + ".range", errorMessageParameters);
302 return constraintValidationResult;
303 }
304
305 return null;
306 }
307
308 }