1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.kns.service.impl;
17
18 import org.apache.commons.beanutils.PropertyUtils;
19 import org.apache.commons.lang.StringUtils;
20 import org.kuali.rice.core.api.CoreApiServiceLocator;
21 import org.kuali.rice.core.api.util.RiceKeyConstants;
22 import org.kuali.rice.core.api.util.type.TypeUtils;
23 import org.kuali.rice.core.framework.persistence.jdbc.sql.SQLUtils;
24 import org.kuali.rice.core.web.format.DateFormatter;
25 import org.kuali.rice.kns.datadictionary.MaintainableFieldDefinition;
26 import org.kuali.rice.kns.datadictionary.MaintainableItemDefinition;
27 import org.kuali.rice.kns.datadictionary.MaintainableSectionDefinition;
28 import org.kuali.rice.kns.datadictionary.MaintenanceDocumentEntry;
29 import org.kuali.rice.kns.service.DictionaryValidationService;
30 import org.kuali.rice.kns.service.KNSServiceLocator;
31 import org.kuali.rice.kns.service.WorkflowAttributePropertyResolutionService;
32 import org.kuali.rice.krad.bo.BusinessObject;
33 import org.kuali.rice.krad.datadictionary.control.ControlDefinition;
34 import org.kuali.rice.krad.document.Document;
35 import org.kuali.rice.krad.util.GlobalVariables;
36 import org.kuali.rice.krad.util.KRADConstants;
37 import org.kuali.rice.krad.util.ObjectUtils;
38
39 import java.beans.PropertyDescriptor;
40 import java.lang.reflect.Method;
41 import java.math.BigDecimal;
42 import java.util.List;
43 import java.util.regex.Pattern;
44
45
46
47
48 @Deprecated
49 public class DictionaryValidationServiceImpl extends org.kuali.rice.krad.service.impl.DictionaryValidationServiceImpl implements DictionaryValidationService {
50 private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(
51 DictionaryValidationServiceImpl.class);
52
53 protected WorkflowAttributePropertyResolutionService workflowAttributePropertyResolutionService;
54
55
56
57
58
59 @Override
60 @Deprecated
61 public void validateDocumentAndUpdatableReferencesRecursively(Document document, int maxDepth,
62 boolean validateRequired, boolean chompLastLetterSFromCollectionName) {
63
64 validateBusinessObject(document, validateRequired);
65
66 if (maxDepth > 0) {
67 validateUpdatabableReferencesRecursively(document, maxDepth - 1, validateRequired,
68 chompLastLetterSFromCollectionName, newIdentitySet());
69 }
70 }
71
72
73
74
75
76 @Deprecated
77 @Override
78 public void validateDocumentRecursively(Document document, int depth) {
79
80 validateDocument(document);
81
82
83 validateBusinessObjectsFromDescriptors(document, PropertyUtils.getPropertyDescriptors(document.getClass()),
84 depth);
85 }
86
87
88
89
90
91
92 @Deprecated
93 @Override
94 public void validateDocument(Document document) {
95 String documentEntryName = document.getDocumentHeader().getWorkflowDocument().getDocumentTypeName();
96
97 validatePrimitivesFromDescriptors(documentEntryName, document, PropertyUtils.getPropertyDescriptors(document.getClass()), "", true);
98 }
99
100 @Override
101 @Deprecated
102 public void validateBusinessObject(BusinessObject businessObject) {
103 validateBusinessObject(businessObject, true);
104 }
105
106 @Override
107 @Deprecated
108 public void validateBusinessObject(BusinessObject businessObject, boolean validateRequired) {
109 if (ObjectUtils.isNull(businessObject)) {
110 return;
111 }
112 try {
113
114 validatePrimitivesFromDescriptors(businessObject.getClass().getName(), businessObject,
115 PropertyUtils.getPropertyDescriptors(businessObject.getClass()), "", validateRequired);
116 } catch (RuntimeException e) {
117 LOG.error(String.format("Exception while validating %s", businessObject.getClass().getName()), e);
118 throw e;
119 }
120 }
121
122
123
124
125 @Deprecated
126 @Override
127 public void validateBusinessObjectOnMaintenanceDocument(BusinessObject businessObject, String docTypeName) {
128 MaintenanceDocumentEntry entry =
129 KNSServiceLocator.getMaintenanceDocumentDictionaryService().getMaintenanceDocumentEntry(docTypeName);
130 for (MaintainableSectionDefinition sectionDefinition : entry.getMaintainableSections()) {
131 validateBusinessObjectOnMaintenanceDocumentHelper(businessObject, sectionDefinition.getMaintainableItems(),
132 "");
133 }
134 }
135
136 protected void validateBusinessObjectOnMaintenanceDocumentHelper(BusinessObject businessObject,
137 List<? extends MaintainableItemDefinition> itemDefinitions, String errorPrefix) {
138 for (MaintainableItemDefinition itemDefinition : itemDefinitions) {
139 if (itemDefinition instanceof MaintainableFieldDefinition) {
140 if (getDataDictionaryService().isAttributeDefined(businessObject.getClass(),
141 itemDefinition.getName())) {
142 Object value = ObjectUtils.getPropertyValue(businessObject, itemDefinition.getName());
143 if (value != null && StringUtils.isNotBlank(value.toString())) {
144 Class propertyType = ObjectUtils.getPropertyType(businessObject, itemDefinition.getName(),
145 persistenceStructureService);
146 if (TypeUtils.isStringClass(propertyType) ||
147 TypeUtils.isIntegralClass(propertyType) ||
148 TypeUtils.isDecimalClass(propertyType) ||
149 TypeUtils.isTemporalClass(propertyType)) {
150
151 if (!TypeUtils.isTemporalClass(propertyType)) {
152 validateAttributeFormat(businessObject.getClass().getName(), itemDefinition.getName(),
153 value.toString(), errorPrefix + itemDefinition.getName());
154 }
155 }
156 }
157 }
158 }
159 }
160 }
161
162
163
164
165
166
167
168
169
170 @Deprecated
171 protected void validatePrimitivesFromDescriptors(String entryName, Object object,
172 PropertyDescriptor[] propertyDescriptors, String errorPrefix, boolean validateRequired) {
173 for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
174 validatePrimitiveFromDescriptor(entryName, object, propertyDescriptor, errorPrefix, validateRequired);
175 }
176 }
177
178
179
180
181
182
183
184
185
186 @Override
187 @Deprecated
188 public void validatePrimitiveFromDescriptor(String entryName, Object object, PropertyDescriptor propertyDescriptor,
189 String errorPrefix, boolean validateRequired) {
190
191 if (null != propertyDescriptor && getDataDictionaryService().isAttributeDefined(entryName,
192 propertyDescriptor.getName())) {
193 Object value = ObjectUtils.getPropertyValue(object, propertyDescriptor.getName());
194 Class propertyType = propertyDescriptor.getPropertyType();
195
196 if (TypeUtils.isStringClass(propertyType) ||
197 TypeUtils.isIntegralClass(propertyType) ||
198 TypeUtils.isDecimalClass(propertyType) ||
199 TypeUtils.isTemporalClass(propertyType)) {
200
201
202 if (value != null && StringUtils.isNotBlank(value.toString())) {
203 if (!TypeUtils.isTemporalClass(propertyType)) {
204 validateAttributeFormat(entryName, propertyDescriptor.getName(), value.toString(),
205 errorPrefix + propertyDescriptor.getName());
206 }
207 } else if (validateRequired) {
208 validateAttributeRequired(entryName, propertyDescriptor.getName(), value, Boolean.FALSE,
209 errorPrefix + propertyDescriptor.getName());
210 }
211 }
212 }
213 }
214
215
216
217
218
219
220 @Override
221 @Deprecated
222 public void validateAttributeFormat(String objectClassName, String attributeName, String attributeInValue,
223 String errorKey) {
224
225 String attributeDataType = null;
226 try {
227 attributeDataType = getWorkflowAttributePropertyResolutionService().determineFieldDataType(
228 (Class<? extends BusinessObject>) Class.forName(
229 getDataDictionaryService().getDataDictionary().getDictionaryObjectEntry(objectClassName)
230 .getFullClassName()), attributeName);
231 } catch (ClassNotFoundException e) {
232 attributeDataType = KRADConstants.DATA_TYPE_STRING;
233 } catch (NullPointerException e) {
234 attributeDataType = KRADConstants.DATA_TYPE_STRING;
235 }
236
237 validateAttributeFormat(objectClassName, attributeName, attributeInValue, attributeDataType, errorKey);
238 }
239
240
241
242
243
244
245
246
247 @Override
248 @Deprecated
249 public void validateAttributeFormat(String objectClassName, String attributeName, String attributeInValue,
250 String attributeDataType, String errorKey) {
251 boolean checkDateBounds = false;
252 Class<?> formatterClass = null;
253
254 if (LOG.isDebugEnabled()) {
255 LOG.debug("(bo, attributeName, attributeValue) = (" + objectClassName + "," + attributeName + "," +
256 attributeInValue + ")");
257 }
258
259
260
261
262
263
264 final List<String> attributeValues = SQLUtils.getCleanedSearchableValues(attributeInValue, attributeDataType);
265
266 if (attributeValues == null || attributeValues.isEmpty()) {
267 return;
268 }
269
270 for (String attributeValue : attributeValues) {
271
272
273
274
275
276
277 if (StringUtils.isNotBlank(attributeValue)) {
278 Integer minLength = getDataDictionaryService().getAttributeMinLength(objectClassName, attributeName);
279 if ((minLength != null) && (minLength.intValue() > attributeValue.length())) {
280 String errorLabel = getDataDictionaryService().getAttributeErrorLabel(objectClassName,
281 attributeName);
282 GlobalVariables.getMessageMap().putError(errorKey, RiceKeyConstants.ERROR_MIN_LENGTH,
283 new String[]{errorLabel, minLength.toString()});
284 return;
285 }
286 Integer maxLength = getDataDictionaryService().getAttributeMaxLength(objectClassName, attributeName);
287 if ((maxLength != null) && (maxLength.intValue() < attributeValue.length())) {
288 String errorLabel = getDataDictionaryService().getAttributeErrorLabel(objectClassName,
289 attributeName);
290 GlobalVariables.getMessageMap().putError(errorKey, RiceKeyConstants.ERROR_MAX_LENGTH,
291 new String[]{errorLabel, maxLength.toString()});
292 return;
293 }
294 Pattern validationExpression = getDataDictionaryService().getAttributeValidatingExpression(
295 objectClassName, attributeName);
296 if (validationExpression != null && !validationExpression.pattern().equals(".*")) {
297 if (LOG.isDebugEnabled()) {
298 LOG.debug("(bo, attributeName, validationExpression) = (" + objectClassName + "," +
299 attributeName + "," + validationExpression + ")");
300 }
301
302 if (!validationExpression.matcher(attributeValue).matches()) {
303
304 if (formatterClass == null) {
305
306 formatterClass = getDataDictionaryService().getAttributeFormatter(objectClassName,
307 attributeName);
308 }
309
310 if (formatterClass != null) {
311 boolean valuesAreValid = true;
312 boolean isError = true;
313 String errorKeyPrefix = "";
314 try {
315
316
317 if (DateFormatter.class.isAssignableFrom(formatterClass)) {
318 String[] values = attributeInValue.split("\\.\\.");
319 if (values.length == 2 &&
320 attributeValues.size() == 2) {
321 checkDateBounds = true;
322 if (attributeValues.indexOf(attributeValue) ==
323 0) {
324 errorKeyPrefix = KRADConstants.LOOKUP_RANGE_LOWER_BOUND_PROPERTY_PREFIX;
325 }
326 }
327 }
328
329 Method validatorMethod = formatterClass.getDeclaredMethod(VALIDATE_METHOD,
330 new Class<?>[]{String.class});
331 Object o = validatorMethod.invoke(formatterClass.newInstance(), attributeValue);
332 if (o instanceof Boolean) {
333 isError = !((Boolean) o).booleanValue();
334 }
335 valuesAreValid &= !isError;
336 } catch (Exception e) {
337 if (LOG.isDebugEnabled()) {
338 LOG.debug(e.getMessage(), e);
339 }
340 isError = true;
341 valuesAreValid = false;
342 }
343 if (isError) {
344 checkDateBounds = false;
345 String errorMessageKey =
346 getDataDictionaryService().getAttributeValidatingErrorMessageKey(
347 objectClassName, attributeName);
348 String[] errorMessageParameters =
349 getDataDictionaryService().getAttributeValidatingErrorMessageParameters(
350 objectClassName, attributeName);
351 GlobalVariables.getMessageMap().putError(errorKeyPrefix + errorKey, errorMessageKey,
352 errorMessageParameters);
353 }
354 } else {
355
356 String errorMessageKey = getDataDictionaryService().getAttributeValidatingErrorMessageKey(
357 objectClassName, attributeName);
358 String[] errorMessageParameters =
359 getDataDictionaryService().getAttributeValidatingErrorMessageParameters(
360 objectClassName, attributeName);
361 GlobalVariables.getMessageMap().putError(errorKey, errorMessageKey, errorMessageParameters);
362 }
363 }
364 }
365
366 String exclusiveMin = getDataDictionaryService().getAttributeExclusiveMin(objectClassName,
367 attributeName);
368 if (exclusiveMin != null) {
369 try {
370 BigDecimal exclusiveMinBigDecimal = new BigDecimal(exclusiveMin);
371 if (exclusiveMinBigDecimal.compareTo(new BigDecimal(attributeValue)) >= 0) {
372 String errorLabel = getDataDictionaryService().getAttributeErrorLabel(objectClassName,
373 attributeName);
374 GlobalVariables.getMessageMap().putError(errorKey, RiceKeyConstants.ERROR_EXCLUSIVE_MIN,
375
376 new String[]{errorLabel, exclusiveMin.toString()});
377 return;
378 }
379 } catch (NumberFormatException e) {
380
381 }
382 }
383
384 String inclusiveMax = getDataDictionaryService().getAttributeInclusiveMax(objectClassName,
385 attributeName);
386 if (inclusiveMax != null) {
387 try {
388 BigDecimal inclusiveMaxBigDecimal = new BigDecimal(inclusiveMax);
389 if (inclusiveMaxBigDecimal.compareTo(new BigDecimal(attributeValue)) < 0) {
390 String errorLabel = getDataDictionaryService().getAttributeErrorLabel(objectClassName,
391 attributeName);
392 GlobalVariables.getMessageMap().putError(errorKey, RiceKeyConstants.ERROR_INCLUSIVE_MAX,
393
394 new String[]{errorLabel, inclusiveMax.toString()});
395 return;
396 }
397 } catch (NumberFormatException e) {
398
399 }
400 }
401 }
402 }
403
404 if (checkDateBounds) {
405
406 java.sql.Timestamp lVal = null;
407 java.sql.Timestamp uVal = null;
408 try {
409 lVal = CoreApiServiceLocator.getDateTimeService().convertToSqlTimestamp(attributeValues.get(0));
410 uVal = CoreApiServiceLocator.getDateTimeService().convertToSqlTimestamp(attributeValues.get(1));
411 } catch (Exception ex) {
412
413 String errorMessageKey = getDataDictionaryService().getAttributeValidatingErrorMessageKey(
414 objectClassName, attributeName);
415 String[] errorMessageParameters =
416 getDataDictionaryService().getAttributeValidatingErrorMessageParameters(objectClassName,
417 attributeName);
418 GlobalVariables.getMessageMap().putError(
419 KRADConstants.LOOKUP_RANGE_LOWER_BOUND_PROPERTY_PREFIX + errorKey, errorMessageKey,
420 errorMessageParameters);
421 }
422
423 if (lVal != null && lVal.compareTo(uVal) > 0) {
424 String errorMessageKey = getDataDictionaryService().getAttributeValidatingErrorMessageKey(
425 objectClassName, attributeName);
426 String[] errorMessageParameters =
427 getDataDictionaryService().getAttributeValidatingErrorMessageParameters(objectClassName,
428 attributeName);
429 GlobalVariables.getMessageMap().putError(
430 KRADConstants.LOOKUP_RANGE_LOWER_BOUND_PROPERTY_PREFIX + errorKey, errorMessageKey + ".range",
431 errorMessageParameters);
432 }
433 }
434 }
435
436
437
438 @Override
439 @Deprecated
440 public void validateAttributeRequired(String objectClassName, String attributeName, Object attributeValue,
441 Boolean forMaintenance, String errorKey) {
442
443 if (attributeValue == null || (attributeValue instanceof String && StringUtils.isBlank(
444 (String) attributeValue))) {
445 Boolean required = getDataDictionaryService().isAttributeRequired(objectClassName, attributeName);
446 ControlDefinition controlDef = getDataDictionaryService().getAttributeControlDefinition(objectClassName,
447 attributeName);
448
449 if (required != null && required.booleanValue() && !(controlDef != null && controlDef.isHidden())) {
450
451
452 String errorLabel = getDataDictionaryService().getAttributeErrorLabel(objectClassName, attributeName);
453 GlobalVariables.getMessageMap().putError(errorKey, RiceKeyConstants.ERROR_REQUIRED, errorLabel);
454 }
455 }
456 }
457
458
459
460
461
462
463
464
465
466 protected WorkflowAttributePropertyResolutionService getWorkflowAttributePropertyResolutionService() {
467 if (workflowAttributePropertyResolutionService == null) {
468 workflowAttributePropertyResolutionService =
469 KNSServiceLocator.getWorkflowAttributePropertyResolutionService();
470 }
471 return workflowAttributePropertyResolutionService;
472 }
473 }