1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.krad.rules;
17
18 import org.apache.commons.lang.StringUtils;
19 import org.kuali.rice.core.api.config.property.ConfigurationService;
20 import org.kuali.rice.core.api.util.RiceKeyConstants;
21 import org.kuali.rice.core.framework.parameter.ParameterConstants;
22 import org.kuali.rice.core.framework.services.CoreFrameworkServiceLocator;
23 import org.kuali.rice.kim.api.KimConstants;
24 import org.kuali.rice.kim.api.group.Group;
25 import org.kuali.rice.kim.api.group.GroupService;
26 import org.kuali.rice.kim.api.identity.Person;
27 import org.kuali.rice.kim.api.identity.PersonService;
28 import org.kuali.rice.kim.api.permission.PermissionService;
29 import org.kuali.rice.kim.api.services.KimApiServiceLocator;
30 import org.kuali.rice.krad.bo.AdHocRoutePerson;
31 import org.kuali.rice.krad.bo.AdHocRouteWorkgroup;
32 import org.kuali.rice.krad.bo.DocumentHeader;
33 import org.kuali.rice.krad.bo.Note;
34 import org.kuali.rice.krad.document.Document;
35 import org.kuali.rice.krad.document.MaintenanceDocument;
36 import org.kuali.rice.krad.document.TransactionalDocument;
37 import org.kuali.rice.krad.rule.AddAdHocRoutePersonRule;
38 import org.kuali.rice.krad.rule.AddAdHocRouteWorkgroupRule;
39 import org.kuali.rice.krad.rule.AddNoteRule;
40 import org.kuali.rice.krad.rule.ApproveDocumentRule;
41 import org.kuali.rice.krad.rule.RouteDocumentRule;
42 import org.kuali.rice.krad.rule.SaveDocumentRule;
43 import org.kuali.rice.krad.rule.SendAdHocRequestsRule;
44 import org.kuali.rice.krad.rule.event.ApproveDocumentEvent;
45 import org.kuali.rice.krad.service.DataDictionaryService;
46 import org.kuali.rice.krad.service.DictionaryValidationService;
47 import org.kuali.rice.krad.service.DocumentHelperService;
48 import org.kuali.rice.krad.service.KRADServiceLocator;
49 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
50 import org.kuali.rice.krad.util.GlobalVariables;
51 import org.kuali.rice.krad.util.KRADConstants;
52 import org.kuali.rice.krad.util.KRADPropertyConstants;
53 import org.kuali.rice.krad.util.KRADUtils;
54 import org.kuali.rice.krad.util.MessageMap;
55
56
57
58
59
60 public abstract class DocumentRuleBase implements SaveDocumentRule, RouteDocumentRule, ApproveDocumentRule, AddNoteRule, AddAdHocRoutePersonRule, AddAdHocRouteWorkgroupRule, SendAdHocRequestsRule {
61 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(DocumentRuleBase.class);
62
63 private static PersonService personService;
64 private static DictionaryValidationService dictionaryValidationService;
65 private static ConfigurationService kualiConfigurationService;
66 private static DocumentHelperService documentHelperService;
67 private static GroupService groupService;
68 private static PermissionService permissionService;
69 private static DataDictionaryService dataDictionaryService;
70
71
72
73
74 private int maxDictionaryValidationDepth = 100;
75
76 protected PersonService getPersonService() {
77 if ( personService == null ) {
78 personService = KimApiServiceLocator.getPersonService();
79 }
80 return personService;
81 }
82
83 public static GroupService getGroupService() {
84 if ( groupService == null ) {
85 groupService = KimApiServiceLocator.getGroupService();
86 }
87 return groupService;
88 }
89
90 public static PermissionService getPermissionService() {
91 if ( permissionService == null ) {
92 permissionService = KimApiServiceLocator.getPermissionService();
93 }
94 return permissionService;
95 }
96
97 protected DocumentHelperService getDocumentHelperService() {
98 if ( documentHelperService == null ) {
99 documentHelperService = KRADServiceLocatorWeb.getDocumentHelperService();
100 }
101 return documentHelperService;
102 }
103
104 protected DictionaryValidationService getDictionaryValidationService() {
105 if ( dictionaryValidationService == null ) {
106 dictionaryValidationService = KRADServiceLocatorWeb.getDictionaryValidationService();
107 }
108 return dictionaryValidationService;
109 }
110
111 protected ConfigurationService getKualiConfigurationService() {
112 if ( kualiConfigurationService == null ) {
113 kualiConfigurationService = KRADServiceLocator.getKualiConfigurationService();
114 }
115 return kualiConfigurationService;
116 }
117
118
119
120
121
122
123
124 public boolean isDocumentOverviewValid(Document document) {
125
126 GlobalVariables.getMessageMap().addToErrorPath(KRADConstants.DOCUMENT_PROPERTY_NAME);
127 GlobalVariables.getMessageMap().addToErrorPath(KRADConstants.DOCUMENT_HEADER_PROPERTY_NAME);
128
129
130 getDictionaryValidationService().validateBusinessObject(document.getDocumentHeader());
131 validateSensitiveDataValue(KRADPropertyConstants.EXPLANATION, document.getDocumentHeader().getExplanation(),
132 getDataDictionaryService().getAttributeLabel(DocumentHeader.class, KRADPropertyConstants.EXPLANATION));
133
134
135 GlobalVariables.getMessageMap().removeFromErrorPath(KRADConstants.DOCUMENT_HEADER_PROPERTY_NAME);
136 GlobalVariables.getMessageMap().removeFromErrorPath(KRADConstants.DOCUMENT_PROPERTY_NAME);
137
138 return GlobalVariables.getMessageMap().hasNoErrors();
139 }
140
141
142
143
144
145
146
147
148
149 public boolean isDocumentAttributesValid(Document document, boolean validateRequired) {
150
151 GlobalVariables.getMessageMap().addToErrorPath(KRADConstants.DOCUMENT_PROPERTY_NAME);
152
153
154 getDictionaryValidationService().validateDocumentAndUpdatableReferencesRecursively(document, getMaxDictionaryValidationDepth(), validateRequired);
155
156
157 GlobalVariables.getMessageMap().removeFromErrorPath(KRADConstants.DOCUMENT_PROPERTY_NAME);
158
159 return GlobalVariables.getMessageMap().hasNoErrors();
160 }
161
162
163
164
165
166
167
168
169
170 public boolean processSaveDocument(Document document) {
171 boolean isValid = true;
172 isValid = isDocumentOverviewValid(document);
173 GlobalVariables.getMessageMap().addToErrorPath(KRADConstants.DOCUMENT_PROPERTY_NAME);
174 getDictionaryValidationService().validateDocumentAndUpdatableReferencesRecursively(document, getMaxDictionaryValidationDepth(), false);
175 getDictionaryValidationService().validateDefaultExistenceChecksForTransDoc((TransactionalDocument) document);
176 GlobalVariables.getMessageMap().removeFromErrorPath(KRADConstants.DOCUMENT_PROPERTY_NAME);
177 isValid &= GlobalVariables.getMessageMap().hasNoErrors();
178 isValid &= processCustomSaveDocumentBusinessRules(document);
179
180 return isValid;
181 }
182
183
184
185
186
187
188
189
190 protected boolean processCustomSaveDocumentBusinessRules(Document document) {
191 return true;
192 }
193
194
195
196
197
198
199
200
201 public boolean processRouteDocument(Document document) {
202 boolean isValid = true;
203
204 isValid = isDocumentAttributesValid(document, true);
205
206
207 if (isValid) {
208 isValid &= processCustomRouteDocumentBusinessRules(document);
209 }
210 return isValid;
211 }
212
213
214
215
216
217
218
219
220 protected boolean processCustomRouteDocumentBusinessRules(Document document) {
221 return true;
222 }
223
224
225
226
227
228
229
230
231 public boolean processApproveDocument(ApproveDocumentEvent approveEvent) {
232 boolean isValid = true;
233
234 isValid = processCustomApproveDocumentBusinessRules(approveEvent);
235
236 return isValid;
237 }
238
239
240
241
242
243
244
245
246 protected boolean processCustomApproveDocumentBusinessRules(ApproveDocumentEvent approveEvent) {
247 return true;
248 }
249
250
251
252
253
254
255
256 public boolean processAddNote(Document document, Note note) {
257 boolean isValid = true;
258
259 isValid &= isNoteValid(note);
260 isValid &= processCustomAddNoteBusinessRules(document, note);
261
262 return isValid;
263 }
264
265
266
267
268
269
270
271 public boolean isNoteValid(Note note) {
272
273 GlobalVariables.getMessageMap().addToErrorPath(KRADConstants.NEW_DOCUMENT_NOTE_PROPERTY_NAME);
274
275
276 getDictionaryValidationService().validateBusinessObject(note);
277
278 validateSensitiveDataValue(KRADConstants.NOTE_TEXT_PROPERTY_NAME, note.getNoteText(),
279 getDataDictionaryService().getAttributeLabel(Note.class, KRADConstants.NOTE_TEXT_PROPERTY_NAME));
280
281
282 GlobalVariables.getMessageMap().removeFromErrorPath(KRADConstants.NEW_DOCUMENT_NOTE_PROPERTY_NAME);
283
284 return GlobalVariables.getMessageMap().hasNoErrors();
285 }
286
287
288
289
290
291
292
293
294
295 protected boolean processCustomAddNoteBusinessRules(Document document, Note note) {
296 return true;
297 }
298
299
300
301
302
303 public boolean processAddAdHocRoutePerson(Document document, AdHocRoutePerson adHocRoutePerson) {
304 boolean isValid = true;
305
306 isValid &= isAddHocRoutePersonValid(document, adHocRoutePerson);
307
308 isValid &= processCustomAddAdHocRoutePersonBusinessRules(document, adHocRoutePerson);
309 return isValid;
310 }
311
312
313
314
315
316 public boolean processSendAdHocRequests(Document document) {
317 boolean isValid = true;
318
319 isValid &= isAdHocRouteRecipientsValid(document);
320 isValid &= processCustomSendAdHocRequests(document);
321
322 return isValid;
323 }
324
325 protected boolean processCustomSendAdHocRequests(Document document) {
326 return true;
327 }
328
329
330
331
332
333
334
335
336 protected boolean isAdHocRouteRecipientsValid(Document document) {
337 boolean isValid = true;
338 MessageMap errorMap = GlobalVariables.getMessageMap();
339
340 if (errorMap.getErrorPath().size() == 0) {
341
342 errorMap.addToErrorPath(KRADConstants.NEW_AD_HOC_ROUTE_PERSON_PROPERTY_NAME);
343 }
344
345 if ((document.getAdHocRoutePersons() == null || document
346 .getAdHocRoutePersons().isEmpty())
347 && (document.getAdHocRouteWorkgroups() == null || document
348 .getAdHocRouteWorkgroups().isEmpty())) {
349
350 GlobalVariables.getMessageMap().putError(KRADPropertyConstants.ID, "error.adhoc.missing.recipients");
351 isValid = false;
352 }
353
354
355 errorMap.removeFromErrorPath(KRADConstants.NEW_AD_HOC_ROUTE_PERSON_PROPERTY_NAME);
356
357 return isValid;
358 }
359
360
361
362
363
364
365 public boolean isAddHocRoutePersonValid(Document document, AdHocRoutePerson person) {
366 MessageMap errorMap = GlobalVariables.getMessageMap();
367
368
369 if (errorMap.getErrorPath().size() == 0) {
370
371 errorMap.addToErrorPath(KRADConstants.NEW_AD_HOC_ROUTE_PERSON_PROPERTY_NAME);
372 }
373
374 if (StringUtils.isNotBlank(person.getId())) {
375 Person user = getPersonService().getPersonByPrincipalName(person.getId());
376
377 if (user == null) {
378 GlobalVariables.getMessageMap().putError(KRADPropertyConstants.ID, RiceKeyConstants.ERROR_INVALID_ADHOC_PERSON_ID);
379 }
380 else if ( !getPermissionService().hasPermission(user.getPrincipalId(), KimConstants.KIM_TYPE_DEFAULT_NAMESPACE,
381 KimConstants.PermissionNames.LOG_IN, null) ) {
382 GlobalVariables.getMessageMap().putError(KRADPropertyConstants.ID, RiceKeyConstants.ERROR_INACTIVE_ADHOC_PERSON_ID);
383 }
384 else {
385 Class docOrBoClass = null;
386 if (document instanceof MaintenanceDocument) {
387 docOrBoClass = ((MaintenanceDocument) document).getNewMaintainableObject().getDataObjectClass();
388 }
389 else {
390 docOrBoClass = document.getClass();
391 }
392 if (!getDocumentHelperService().getDocumentAuthorizer(document).canReceiveAdHoc(document, user, person.getActionRequested())) {
393 GlobalVariables.getMessageMap().putError(KRADPropertyConstants.ID, RiceKeyConstants.ERROR_UNAUTHORIZED_ADHOC_PERSON_ID);
394 }
395 }
396 }
397 else {
398 GlobalVariables.getMessageMap().putError(KRADPropertyConstants.ID, RiceKeyConstants.ERROR_MISSING_ADHOC_PERSON_ID);
399 }
400
401
402 errorMap.removeFromErrorPath(KRADConstants.NEW_AD_HOC_ROUTE_PERSON_PROPERTY_NAME);
403
404 return GlobalVariables.getMessageMap().hasNoErrors();
405 }
406
407
408
409
410
411
412
413
414
415 protected boolean processCustomAddAdHocRoutePersonBusinessRules(Document document, AdHocRoutePerson person) {
416 return true;
417 }
418
419
420
421
422
423 public boolean processAddAdHocRouteWorkgroup(Document document, AdHocRouteWorkgroup adHocRouteWorkgroup) {
424 boolean isValid = true;
425
426 isValid &= isAddHocRouteWorkgroupValid(adHocRouteWorkgroup);
427
428 isValid &= processCustomAddAdHocRouteWorkgroupBusinessRules(document, adHocRouteWorkgroup);
429 return isValid;
430 }
431
432
433
434
435
436
437
438 public boolean isAddHocRouteWorkgroupValid(AdHocRouteWorkgroup workgroup) {
439 MessageMap errorMap = GlobalVariables.getMessageMap();
440
441
442 if (errorMap.getErrorPath().size() == 0) {
443
444 GlobalVariables.getMessageMap().addToErrorPath(KRADConstants.NEW_AD_HOC_ROUTE_WORKGROUP_PROPERTY_NAME);
445 }
446
447 if (workgroup.getRecipientName() != null && workgroup.getRecipientNamespaceCode() != null) {
448
449 try {
450 Group group = getGroupService().getGroupByNameAndNamespaceCode(workgroup.getRecipientNamespaceCode(),
451 workgroup.getRecipientName());
452 if (group == null || !group.isActive()) {
453 GlobalVariables.getMessageMap().putError(KRADPropertyConstants.ID, RiceKeyConstants.ERROR_INVALID_ADHOC_WORKGROUP_ID);
454 }
455 }
456 catch (Exception e) {
457 LOG.error("isAddHocRouteWorkgroupValid(AdHocRouteWorkgroup)", e);
458
459 GlobalVariables.getMessageMap().putError(KRADPropertyConstants.ID, RiceKeyConstants.ERROR_INVALID_ADHOC_WORKGROUP_ID);
460 }
461 }
462 else {
463 GlobalVariables.getMessageMap().putError(KRADPropertyConstants.ID, RiceKeyConstants.ERROR_MISSING_ADHOC_WORKGROUP_ID);
464 }
465
466
467 GlobalVariables.getMessageMap().removeFromErrorPath(KRADConstants.NEW_AD_HOC_ROUTE_WORKGROUP_PROPERTY_NAME);
468
469 return GlobalVariables.getMessageMap().hasNoErrors();
470 }
471
472
473
474
475
476
477
478
479
480 protected boolean processCustomAddAdHocRouteWorkgroupBusinessRules(Document document, AdHocRouteWorkgroup workgroup) {
481 return true;
482 }
483
484
485
486
487 public int getMaxDictionaryValidationDepth() {
488 return this.maxDictionaryValidationDepth;
489 }
490
491
492
493
494 public void setMaxDictionaryValidationDepth(int maxDictionaryValidationDepth) {
495 if (maxDictionaryValidationDepth < 0) {
496 LOG.error("Dictionary validation depth should be greater than or equal to 0. Value received was: " + maxDictionaryValidationDepth);
497 throw new RuntimeException("Dictionary validation depth should be greater than or equal to 0. Value received was: " + maxDictionaryValidationDepth);
498 }
499 this.maxDictionaryValidationDepth = maxDictionaryValidationDepth;
500 }
501
502 protected boolean validateSensitiveDataValue(String fieldName, String fieldValue, String fieldLabel) {
503 boolean dataValid = true;
504
505 if (fieldValue == null) {
506 return dataValid;
507 }
508
509 boolean patternFound = KRADUtils.containsSensitiveDataPatternMatch(fieldValue);
510 boolean warnForSensitiveData = CoreFrameworkServiceLocator.getParameterService().getParameterValueAsBoolean(
511 KRADConstants.KRAD_NAMESPACE, ParameterConstants.ALL_COMPONENT,
512 KRADConstants.SystemGroupParameterNames.SENSITIVE_DATA_PATTERNS_WARNING_IND);
513 if (patternFound && !warnForSensitiveData) {
514 dataValid = false;
515 GlobalVariables.getMessageMap().putError(fieldName,
516 RiceKeyConstants.ERROR_DOCUMENT_FIELD_CONTAINS_POSSIBLE_SENSITIVE_DATA, fieldLabel);
517 }
518
519 return dataValid;
520 }
521
522 protected DataDictionaryService getDataDictionaryService() {
523 if (dataDictionaryService == null) {
524 dataDictionaryService = KRADServiceLocatorWeb.getDataDictionaryService();
525 }
526 return dataDictionaryService;
527 }
528 }