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