View Javadoc
1   package org.kuali.rice.krad.service.impl;
2   
3   /**
4    * Created by maheswarang on 12/17/14.
5    */
6   
7   import org.apache.commons.lang.StringUtils;
8   import org.apache.commons.lang.time.StopWatch;
9   import org.kuali.ole.alert.bo.AlertBo;
10  import org.kuali.ole.alert.bo.AlertEvent;
11  import org.kuali.ole.alert.bo.AlertEventField;
12  import org.kuali.ole.alert.document.OlePersistableBusinessObjectBase;
13  import org.kuali.ole.alert.document.OleTransactionalDocumentBase;
14  import org.kuali.ole.alert.service.AlertGlobalConfigurationServiceImpl;
15  import org.kuali.ole.alert.service.impl.AlertServiceImpl;
16  import org.kuali.ole.deliver.bo.OleDeliverRequestType;
17  import org.kuali.rice.core.api.CoreApiServiceLocator;
18  import org.kuali.rice.core.api.config.ConfigurationException;
19  import org.kuali.rice.core.api.config.property.ConfigurationService;
20  import org.kuali.rice.core.api.datetime.DateTimeService;
21  import org.kuali.rice.core.api.util.RiceKeyConstants;
22  import org.kuali.rice.core.framework.persistence.jta.TransactionalNoValidationExceptionRollback;
23  import org.kuali.rice.kew.api.WorkflowDocument;
24  import org.kuali.rice.kew.api.exception.WorkflowException;
25  import org.kuali.rice.kim.api.identity.Person;
26  import org.kuali.rice.kim.api.identity.PersonService;
27  import org.kuali.rice.kim.api.services.KimApiServiceLocator;
28  import org.kuali.rice.krad.UserSession;
29  import org.kuali.rice.krad.UserSessionUtils;
30  import org.kuali.rice.krad.bo.*;
31  import org.kuali.rice.krad.dao.DocumentDao;
32  import org.kuali.rice.krad.datadictionary.exception.UnknownDocumentTypeException;
33  import org.kuali.rice.krad.document.Document;
34  import org.kuali.rice.krad.document.DocumentAuthorizer;
35  import org.kuali.rice.krad.document.DocumentPresentationController;
36  import org.kuali.rice.krad.exception.DocumentAuthorizationException;
37  import org.kuali.rice.krad.exception.ValidationException;
38  import org.kuali.rice.krad.maintenance.MaintenanceDocument;
39  import org.kuali.rice.krad.maintenance.MaintenanceDocumentBase;
40  import org.kuali.rice.krad.rules.rule.event.*;
41  import org.kuali.rice.krad.service.*;
42  import org.kuali.rice.krad.util.GlobalVariables;
43  import org.kuali.rice.krad.util.KRADConstants;
44  import org.kuali.rice.krad.util.NoteType;
45  import org.kuali.rice.krad.util.ObjectUtils;
46  import org.kuali.rice.krad.workflow.service.WorkflowDocumentService;
47  import org.springframework.dao.OptimisticLockingFailureException;
48  
49  import java.lang.reflect.Constructor;
50  import java.lang.reflect.InvocationTargetException;
51  import java.text.MessageFormat;
52  import java.util.ArrayList;
53  import java.util.HashMap;
54  import java.util.List;
55  import java.util.Map;
56  
57  
58  /**
59   * Service implementation for the Document structure. It contains all of the document level type of
60   * processing and calling back into documents for various centralization of functionality. This is the default,
61   * Kuali delivered implementation which utilizes Workflow.
62   *
63   * @author Kuali Rice Team (rice.collab@kuali.org)
64   */
65  @TransactionalNoValidationExceptionRollback
66  public class DocumentServiceImpl implements DocumentService {
67      private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(DocumentServiceImpl.class);
68  
69      private DocumentDao documentDao;
70  
71      private DateTimeService dateTimeService;
72      private NoteService noteService;
73      private WorkflowDocumentService workflowDocumentService;
74      private BusinessObjectService businessObjectService;
75      private DataDictionaryService dataDictionaryService;
76      private DocumentHeaderService documentHeaderService;
77      private DocumentDictionaryService documentDictionaryService;
78      private PersonService personService;
79      private ConfigurationService kualiConfigurationService;
80  
81      public AlertServiceImpl getAlertService(){
82          return new AlertServiceImpl();
83      }
84  
85      /**
86       * @see org.kuali.rice.krad.service.DocumentService#saveDocument(org.kuali.rice.krad.document.Document)
87       */
88      @Override
89      public Document saveDocument(Document document) throws WorkflowException, ValidationException {
90          return saveDocument(document, SaveDocumentEvent.class);
91      }
92  
93      @Override
94      public Document saveDocument(Document document,
95                                   Class<? extends KualiDocumentEvent> kualiDocumentEventClass) throws WorkflowException, ValidationException {
96          checkForNulls(document);
97          if (kualiDocumentEventClass == null) {
98              throw new IllegalArgumentException("invalid (null) kualiDocumentEventClass");
99          }
100         // if event is not an instance of a SaveDocumentEvent or a SaveOnlyDocumentEvent
101         if (!SaveEvent.class.isAssignableFrom(kualiDocumentEventClass)) {
102             throw new ConfigurationException("The KualiDocumentEvent class '" + kualiDocumentEventClass.getName() +
103                     "' does not implement the class '" + SaveEvent.class.getName() + "'");
104         }
105 //        if (!getDocumentActionFlags(document).getCanSave()) {
106 //            throw buildAuthorizationException("save", document);
107 //        }
108         document.prepareForSave();
109         Document savedDocument = validateAndPersistDocumentAndSaveAdHocRoutingRecipients(document,
110                 generateKualiDocumentEvent(document, kualiDocumentEventClass));
111         prepareWorkflowDocument(savedDocument);
112         getWorkflowDocumentService().save(savedDocument.getDocumentHeader().getWorkflowDocument(), null);
113 
114         UserSessionUtils.addWorkflowDocument(GlobalVariables.getUserSession(),
115                 savedDocument.getDocumentHeader().getWorkflowDocument());
116         if(document instanceof OleTransactionalDocumentBase){
117             OleTransactionalDocumentBase oleTransactionalDocumentBase = (OleTransactionalDocumentBase)document;
118             if(!oleTransactionalDocumentBase.getAlertBoList().containsAll(oleTransactionalDocumentBase.getTempAlertBoList())) {
119                 oleTransactionalDocumentBase.getAlertBoList().addAll(oleTransactionalDocumentBase.getTempAlertBoList());
120             }
121             getAlertService().deleteAlerts(document.getDocumentNumber());
122             getAlertService().saveAlert(oleTransactionalDocumentBase);
123             List<AlertBo> alertBos = oleTransactionalDocumentBase.getAlertBoList();
124             oleTransactionalDocumentBase = (OleTransactionalDocumentBase)savedDocument;
125             alertBos.removeAll(oleTransactionalDocumentBase.getTempAlertBoList());
126             oleTransactionalDocumentBase.setAlertBoList(alertBos);
127         }
128 
129         if(document instanceof MaintenanceDocumentBase){
130             MaintenanceDocumentBase maintenanceDocumentBase = (MaintenanceDocumentBase) document;
131              if(maintenanceDocumentBase.getDocumentDataObject() instanceof OlePersistableBusinessObjectBase){
132                  OlePersistableBusinessObjectBase olePersistableBusinessObjectBase = (OlePersistableBusinessObjectBase)maintenanceDocumentBase.getDocumentDataObject();
133                  getAlertService().deleteAlerts(maintenanceDocumentBase.getDocumentNumber());
134                  getAlertService().deleteAlerts(document.getDocumentNumber());
135                  getAlertService().saveAlert(maintenanceDocumentBase);
136 
137              }
138         }
139 
140         return savedDocument;
141     }
142 
143     private KualiDocumentEvent generateKualiDocumentEvent(Document document,
144                                                           Class<? extends KualiDocumentEvent> eventClass) throws ConfigurationException {
145         String potentialErrorMessage =
146                 "Found error trying to generate Kuali Document Event using event class '" + eventClass.getName() +
147                         "' for document " + document.getDocumentNumber();
148 
149         try {
150             Constructor<?> usableConstructor = null;
151             List<Object> paramList = new ArrayList<Object>();
152             for (Constructor<?> currentConstructor : eventClass.getConstructors()) {
153                 for (Class<?> parameterClass : currentConstructor.getParameterTypes()) {
154                     if (Document.class.isAssignableFrom(parameterClass)) {
155                         usableConstructor = currentConstructor;
156                         paramList.add(document);
157                     } else {
158                         paramList.add(null);
159                     }
160                 }
161                 if (ObjectUtils.isNotNull(usableConstructor)) {
162                     break;
163                 }
164             }
165             if (usableConstructor == null) {
166                 throw new RuntimeException("Cannot find a constructor for class '" + eventClass.getName() +
167                         "' that takes in a document parameter");
168             }
169             return (KualiDocumentEvent) usableConstructor.newInstance(paramList.toArray());
170         } catch (SecurityException e) {
171             throw new ConfigurationException(potentialErrorMessage, e);
172         } catch (IllegalArgumentException e) {
173             throw new ConfigurationException(potentialErrorMessage, e);
174         } catch (InstantiationException e) {
175             throw new ConfigurationException(potentialErrorMessage, e);
176         } catch (IllegalAccessException e) {
177             throw new ConfigurationException(potentialErrorMessage, e);
178         } catch (InvocationTargetException e) {
179             throw new ConfigurationException(potentialErrorMessage, e);
180         }
181     }
182 
183     /**
184      * @see org.kuali.rice.krad.service.DocumentService#routeDocument(org.kuali.rice.krad.document.Document,
185      *      String, java.util.List)
186      */
187     @Override
188     public Document routeDocument(Document document, String annotation,
189                                   List<AdHocRouteRecipient> adHocRecipients) throws ValidationException, WorkflowException {
190         checkForNulls(document);
191         //if (!getDocumentActionFlags(document).getCanRoute()) {
192         //    throw buildAuthorizationException("route", document);
193         //}
194         document.prepareForSave();
195         Document savedDocument = validateAndPersistDocument(document, new RouteDocumentEvent(document));
196         prepareWorkflowDocument(savedDocument);
197         getWorkflowDocumentService()
198                 .route(savedDocument.getDocumentHeader().getWorkflowDocument(), annotation, adHocRecipients);
199         UserSessionUtils.addWorkflowDocument(GlobalVariables.getUserSession(),
200                 savedDocument.getDocumentHeader().getWorkflowDocument());
201         removeAdHocPersonsAndWorkgroups(savedDocument);
202         if(document instanceof OleTransactionalDocumentBase){
203             OleTransactionalDocumentBase oleTransactionalDocumentBase = (OleTransactionalDocumentBase)document;
204             if(!oleTransactionalDocumentBase.getAlertBoList().containsAll(oleTransactionalDocumentBase.getTempAlertBoList())) {
205                 oleTransactionalDocumentBase.getAlertBoList().addAll(oleTransactionalDocumentBase.getTempAlertBoList());
206             }
207             getAlertService().deleteAlerts(document.getDocumentNumber());
208             getAlertService().saveAlert(oleTransactionalDocumentBase);
209             List<AlertBo> alertBos = oleTransactionalDocumentBase.getAlertBoList();
210             oleTransactionalDocumentBase = (OleTransactionalDocumentBase)savedDocument;
211             alertBos.removeAll(oleTransactionalDocumentBase.getTempAlertBoList());
212             oleTransactionalDocumentBase.setAlertBoList(alertBos);
213             processGlobalAlerts(document);
214         }
215         if(document instanceof MaintenanceDocumentBase){
216             MaintenanceDocumentBase maintenanceDocumentBase = (MaintenanceDocumentBase) document;
217             if(maintenanceDocumentBase.getDocumentDataObject() instanceof OlePersistableBusinessObjectBase){
218                 OlePersistableBusinessObjectBase olePersistableBusinessObjectBase = (OlePersistableBusinessObjectBase)maintenanceDocumentBase.getDocumentDataObject();
219                 getAlertService().deleteAlerts(maintenanceDocumentBase.getDocumentNumber());
220                 getAlertService().deleteAlerts(document.getDocumentNumber());
221                 getAlertService().saveAlert(maintenanceDocumentBase);
222                 processGlobalAlerts(document);
223             }
224         }
225         return savedDocument;
226     }
227 
228     /**
229      * @see org.kuali.rice.krad.service.DocumentService#approveDocument(org.kuali.rice.krad.document.Document,
230      *      String,
231      *      java.util.List)
232      */
233     @Override
234     public Document approveDocument(Document document, String annotation,
235                                     List<AdHocRouteRecipient> adHocRecipients) throws ValidationException, WorkflowException {
236         checkForNulls(document);
237         //if (!getDocumentActionFlags(document).getCanApprove()) {
238         //    throw buildAuthorizationException("approve", document);
239         //}
240         document.prepareForSave();
241         Document savedDocument = validateAndPersistDocument(document, new ApproveDocumentEvent(document));
242         prepareWorkflowDocument(savedDocument);
243         getWorkflowDocumentService()
244                 .approve(savedDocument.getDocumentHeader().getWorkflowDocument(), annotation, adHocRecipients);
245         UserSessionUtils.addWorkflowDocument(GlobalVariables.getUserSession(),
246                 savedDocument.getDocumentHeader().getWorkflowDocument());
247         removeAdHocPersonsAndWorkgroups(savedDocument);
248         return savedDocument;
249     }
250 
251     /**
252      * @see org.kuali.rice.krad.service.DocumentService#superUserApproveDocument(org.kuali.rice.krad.document.Document,
253      *      String)
254      */
255     @Override
256     public Document superUserApproveDocument(Document document, String annotation) throws WorkflowException {
257         getDocumentDao().save(document);
258         prepareWorkflowDocument(document);
259         getWorkflowDocumentService().superUserApprove(document.getDocumentHeader().getWorkflowDocument(), annotation);
260         UserSessionUtils.addWorkflowDocument(GlobalVariables.getUserSession(),
261                 document.getDocumentHeader().getWorkflowDocument());
262         removeAdHocPersonsAndWorkgroups(document);
263         return document;
264     }
265 
266     /**
267      * @see org.kuali.rice.krad.service.DocumentService#superUserCancelDocument(org.kuali.rice.krad.document.Document,
268      *      String)
269      */
270     @Override
271     public Document superUserCancelDocument(Document document, String annotation) throws WorkflowException {
272         getDocumentDao().save(document);
273         prepareWorkflowDocument(document);
274         getWorkflowDocumentService().superUserCancel(document.getDocumentHeader().getWorkflowDocument(), annotation);
275         UserSessionUtils.addWorkflowDocument(GlobalVariables.getUserSession(),
276                 document.getDocumentHeader().getWorkflowDocument());
277         removeAdHocPersonsAndWorkgroups(document);
278         return document;
279     }
280 
281     /**
282      * @see org.kuali.rice.krad.service.DocumentService#superUserCancelDocument(org.kuali.rice.krad.document.Document,
283      *      String)
284      */
285     @Override
286     public Document superUserDisapproveDocument(Document document, String annotation) throws WorkflowException {
287         getDocumentDao().save(document);
288         return superUserDisapproveDocumentWithoutSaving(document, annotation);
289     }
290 
291     /**
292      * @see org.kuali.rice.krad.service.DocumentService#superUserCancelDocument(org.kuali.rice.krad.document.Document,
293      *      String)
294      */
295     @Override
296     public Document superUserDisapproveDocumentWithoutSaving(Document document, String annotation) throws WorkflowException {
297         prepareWorkflowDocument(document);
298         getWorkflowDocumentService()
299                 .superUserDisapprove(document.getDocumentHeader().getWorkflowDocument(), annotation);
300         UserSessionUtils.addWorkflowDocument(GlobalVariables.getUserSession(),
301                 document.getDocumentHeader().getWorkflowDocument());
302         removeAdHocPersonsAndWorkgroups(document);
303         return document;
304     }
305 
306 
307     /**
308      * @see org.kuali.rice.krad.service.DocumentService#disapproveDocument(org.kuali.rice.krad.document.Document,
309      *      String)
310      */
311     @Override
312     public Document disapproveDocument(Document document, String annotation) throws Exception {
313         checkForNulls(document);
314 
315         Note note = createNoteFromDocument(document, annotation);
316         //if note type is BO, override and link disapprove notes to Doc Header
317         if (document.getNoteType().equals(NoteType.BUSINESS_OBJECT)) {
318             note.setNoteTypeCode(NoteType.DOCUMENT_HEADER.getCode());
319             note.setRemoteObjectIdentifier(document.getDocumentHeader().getObjectId());
320         }
321         document.addNote(note);
322 
323         //SAVE THE NOTE
324         //Note: This save logic is replicated here and in KualiDocumentAction, when to save (based on doc state) should be moved
325         //      into a doc service method
326         getNoteService().save(note);
327 
328         prepareWorkflowDocument(document);
329         getWorkflowDocumentService().disapprove(document.getDocumentHeader().getWorkflowDocument(), annotation);
330         UserSessionUtils.addWorkflowDocument(GlobalVariables.getUserSession(),
331                 document.getDocumentHeader().getWorkflowDocument());
332         removeAdHocPersonsAndWorkgroups(document);
333         return document;
334     }
335 
336     /**
337      * @see org.kuali.rice.krad.service.DocumentService#cancelDocument(org.kuali.rice.krad.document.Document,
338      *      String)
339      */
340     @Override
341     public Document cancelDocument(Document document, String annotation) throws WorkflowException {
342         checkForNulls(document);
343         //if (!getDocumentActionFlags(document).getCanCancel()) {
344         //    throw buildAuthorizationException("cancel", document);
345         //}
346         if (document instanceof MaintenanceDocument) {
347             MaintenanceDocument maintDoc = ((MaintenanceDocument) document);
348             if (maintDoc.getOldMaintainableObject() != null &&
349                     (maintDoc.getOldMaintainableObject().getDataObject() instanceof BusinessObject)) {
350                 ((BusinessObject) maintDoc.getOldMaintainableObject().getDataObject()).refresh();
351             }
352 
353             if (maintDoc.getNewMaintainableObject().getDataObject() instanceof BusinessObject) {
354                 ((BusinessObject) maintDoc.getNewMaintainableObject().getDataObject()).refresh();
355             }
356         }
357         prepareWorkflowDocument(document);
358         getWorkflowDocumentService().cancel(document.getDocumentHeader().getWorkflowDocument(), annotation);
359         UserSessionUtils.addWorkflowDocument(GlobalVariables.getUserSession(),
360                 document.getDocumentHeader().getWorkflowDocument());
361         //getBusinessObjectService().delete(document.getAdHocRoutePersons());
362         //getBusinessObjectService().delete(document.getAdHocRouteWorkgroups());
363         removeAdHocPersonsAndWorkgroups(document);
364         return document;
365     }
366 
367     @Override
368     public Document recallDocument(Document document, String annotation, boolean cancel) throws WorkflowException {
369         checkForNulls(document);
370 
371         Note note = createNoteFromDocument(document, annotation);
372         document.addNote(note);
373         getNoteService().save(note);
374 
375         prepareWorkflowDocument(document);
376         getWorkflowDocumentService().recall(document.getDocumentHeader().getWorkflowDocument(), annotation, cancel);
377         UserSessionUtils.addWorkflowDocument(GlobalVariables.getUserSession(),
378                 document.getDocumentHeader().getWorkflowDocument());
379         removeAdHocPersonsAndWorkgroups(document);
380         return document;
381     }
382 
383     /**
384      * @see org.kuali.rice.krad.service.DocumentService#acknowledgeDocument(org.kuali.rice.krad.document.Document,
385      *      String,
386      *      java.util.List)
387      */
388     @Override
389     public Document acknowledgeDocument(Document document, String annotation,
390                                         List<AdHocRouteRecipient> adHocRecipients) throws WorkflowException {
391         checkForNulls(document);
392         //if (!getDocumentActionFlags(document).getCanAcknowledge()) {
393         //    throw buildAuthorizationException("acknowledge", document);
394         //}
395         prepareWorkflowDocument(document);
396         getWorkflowDocumentService()
397                 .acknowledge(document.getDocumentHeader().getWorkflowDocument(), annotation, adHocRecipients);
398         UserSessionUtils.addWorkflowDocument(GlobalVariables.getUserSession(),
399                 document.getDocumentHeader().getWorkflowDocument());
400         removeAdHocPersonsAndWorkgroups(document);
401         return document;
402     }
403 
404     /**
405      * @see org.kuali.rice.krad.service.DocumentService#blanketApproveDocument(org.kuali.rice.krad.document.Document,
406      *      String,
407      *      java.util.List)
408      */
409     @Override
410     public Document blanketApproveDocument(Document document, String annotation,
411                                            List<AdHocRouteRecipient> adHocRecipients) throws ValidationException, WorkflowException {
412         checkForNulls(document);
413         //if (!getDocumentActionFlags(document).getCanBlanketApprove()) {
414         //    throw buildAuthorizationException("blanket approve", document);
415         //}
416         document.prepareForSave();
417         Document savedDocument = validateAndPersistDocument(document, new BlanketApproveDocumentEvent(document));
418         prepareWorkflowDocument(savedDocument);
419         getWorkflowDocumentService()
420                 .blanketApprove(savedDocument.getDocumentHeader().getWorkflowDocument(), annotation, adHocRecipients);
421         UserSessionUtils.addWorkflowDocument(GlobalVariables.getUserSession(),
422                 savedDocument.getDocumentHeader().getWorkflowDocument());
423         removeAdHocPersonsAndWorkgroups(savedDocument);
424         return savedDocument;
425     }
426 
427     /**
428      * @see org.kuali.rice.krad.service.DocumentService#clearDocumentFyi(org.kuali.rice.krad.document.Document,
429      *      java.util.List)
430      */
431     @Override
432     public Document clearDocumentFyi(Document document,
433                                      List<AdHocRouteRecipient> adHocRecipients) throws WorkflowException {
434         checkForNulls(document);
435         // populate document content so searchable attributes will be indexed properly
436         document.populateDocumentForRouting();
437         getWorkflowDocumentService().clearFyi(document.getDocumentHeader().getWorkflowDocument(), adHocRecipients);
438         UserSessionUtils.addWorkflowDocument(GlobalVariables.getUserSession(),
439                 document.getDocumentHeader().getWorkflowDocument());
440         removeAdHocPersonsAndWorkgroups(document);
441         return document;
442     }
443 
444     /**
445      * @see org.kuali.rice.krad.service.DocumentService#completeDocument(org.kuali.rice.krad.document.Document,
446      *      String,
447      *      java.util.List)
448      */
449     @Override
450     public Document completeDocument(Document document, String annotation,
451                                      List adHocRecipients) throws WorkflowException {
452         checkForNulls(document);
453 
454         document.prepareForSave();
455         validateAndPersistDocument(document, new CompleteDocumentEvent(document));
456 
457         prepareWorkflowDocument(document);
458         getWorkflowDocumentService().complete(document.getDocumentHeader().getWorkflowDocument(), annotation,
459                 adHocRecipients);
460 
461         UserSessionUtils.addWorkflowDocument(GlobalVariables.getUserSession(),
462                 document.getDocumentHeader().getWorkflowDocument());
463 
464         removeAdHocPersonsAndWorkgroups(document);
465 
466         return document;
467     }
468 
469     protected void checkForNulls(Document document) {
470         if (document == null) {
471             throw new IllegalArgumentException("invalid (null) document");
472         }
473         if (document.getDocumentNumber() == null) {
474             throw new IllegalStateException("invalid (null) documentHeaderId");
475         }
476     }
477 
478     private Document validateAndPersistDocumentAndSaveAdHocRoutingRecipients(Document document,
479                                                                              KualiDocumentEvent event) {
480         /*
481          * Using this method to wrap validateAndPersistDocument to keep everything in one transaction. This avoids modifying the
482          * signature on validateAndPersistDocument method
483          */
484         List<AdHocRouteRecipient> adHocRoutingRecipients = new ArrayList<AdHocRouteRecipient>();
485         adHocRoutingRecipients.addAll(document.getAdHocRoutePersons());
486         adHocRoutingRecipients.addAll(document.getAdHocRouteWorkgroups());
487 
488         for (AdHocRouteRecipient recipient : adHocRoutingRecipients) {
489             recipient.setdocumentNumber(document.getDocumentNumber());
490         }
491         Map<String, String> criteria = new HashMap<String, String>();
492         criteria.put("documentNumber", document.getDocumentNumber());
493         getBusinessObjectService().deleteMatching(AdHocRouteRecipient.class, criteria);
494 
495         getBusinessObjectService().save(adHocRoutingRecipients);
496         return validateAndPersistDocument(document, event);
497     }
498 
499     /**
500      * @see org.kuali.rice.krad.service.DocumentService#documentExists(String)
501      */
502     @Override
503     public boolean documentExists(String documentHeaderId) {
504         // validate parameters
505         if (StringUtils.isBlank(documentHeaderId)) {
506             throw new IllegalArgumentException("invalid (blank) documentHeaderId");
507         }
508 
509         boolean internalUserSession = false;
510         try {
511             // KFSMI-2543 - allowed method to run without a user session so it can be used
512             // by workflow processes
513             if (GlobalVariables.getUserSession() == null) {
514                 internalUserSession = true;
515                 GlobalVariables.setUserSession(new UserSession(KRADConstants.SYSTEM_USER));
516                 GlobalVariables.clear();
517             }
518 
519             // look for workflowDocumentHeader, since that supposedly won't break the transaction
520             if (getWorkflowDocumentService().workflowDocumentExists(documentHeaderId)) {
521                 // look for docHeaderId, since that fails without breaking the transaction
522                 return getDocumentHeaderService().getDocumentHeaderById(documentHeaderId) != null;
523             }
524 
525             return false;
526         } finally {
527             // if a user session was established for this call, clear it our
528             if (internalUserSession) {
529                 GlobalVariables.clear();
530                 GlobalVariables.setUserSession(null);
531             }
532         }
533     }
534 
535     /**
536      * Creates a new document by class.
537      *
538      * @see org.kuali.rice.krad.service.DocumentService#getNewDocument(Class)
539      */
540     @Override
541     public Document getNewDocument(Class<? extends Document> documentClass) throws WorkflowException {
542         if (documentClass == null) {
543             throw new IllegalArgumentException("invalid (null) documentClass");
544         }
545         if (!Document.class.isAssignableFrom(documentClass)) {
546             throw new IllegalArgumentException("invalid (non-Document) documentClass");
547         }
548 
549         String documentTypeName = getDataDictionaryService().getDocumentTypeNameByClass(documentClass);
550         if (StringUtils.isBlank(documentTypeName)) {
551             throw new UnknownDocumentTypeException(
552                     "unable to get documentTypeName for unknown documentClass '" + documentClass.getName() + "'");
553         }
554         return getNewDocument(documentTypeName);
555     }
556 
557     /**
558      * Creates a new document by document type name. The principal name
559      * passed in will be used as the document initiator.  If the  initiatorPrincipalNm
560      * is null or blank, the current user will be used.
561      *
562      * @see org.kuali.rice.krad.service.DocumentService#getNewDocument(String, String)
563      */
564     @Override
565     public Document getNewDocument(String documentTypeName, String initiatorPrincipalNm) throws WorkflowException {
566 
567         // argument validation
568         String watchName = "DocumentServiceImpl.getNewDocument";
569         StopWatch watch = new StopWatch();
570         watch.start();
571         if (LOG.isDebugEnabled()) {
572             LOG.debug(watchName + ": started");
573         }
574         if (StringUtils.isBlank(documentTypeName)) {
575             throw new IllegalArgumentException("invalid (blank) documentTypeName");
576         }
577         if (GlobalVariables.getUserSession() == null) {
578             throw new IllegalStateException(
579                     "GlobalVariables must be populated with a valid UserSession before a new document can be created");
580         }
581 
582         // get the class for this docTypeName
583         Class<? extends Document> documentClass = getDocumentClassByTypeName(documentTypeName);
584 
585         // get the initiator
586         Person initiator = null;
587         if (StringUtils.isBlank(initiatorPrincipalNm)) {
588             initiator = GlobalVariables.getUserSession().getPerson();
589         } else {
590             initiator = KimApiServiceLocator.getPersonService().getPersonByPrincipalName(initiatorPrincipalNm);
591             if (ObjectUtils.isNull(initiator)) {
592                 initiator = GlobalVariables.getUserSession().getPerson();
593             }
594         }
595 
596         // get the authorization
597         DocumentAuthorizer documentAuthorizer = getDocumentDictionaryService().getDocumentAuthorizer(documentTypeName);
598         DocumentPresentationController documentPresentationController =
599                 getDocumentDictionaryService().getDocumentPresentationController(documentTypeName);
600         // make sure this person is authorized to initiate
601         LOG.debug("calling canInitiate from getNewDocument()");
602         if (!documentPresentationController.canInitiate(documentTypeName) ||
603                 !documentAuthorizer.canInitiate(documentTypeName, initiator)) {
604             throw new DocumentAuthorizationException(initiator.getPrincipalName(), "initiate", documentTypeName);
605         }
606 
607         // initiate new workflow entry, get the workflow doc
608         WorkflowDocument workflowDocument = getWorkflowDocumentService().createWorkflowDocument(documentTypeName, initiator);
609         UserSessionUtils.addWorkflowDocument(GlobalVariables.getUserSession(), workflowDocument);
610 
611         // create a new document header object
612         DocumentHeader documentHeader = null;
613         try {
614             // create a new document header object
615             Class<? extends DocumentHeader> documentHeaderClass =
616                     getDocumentHeaderService().getDocumentHeaderBaseClass();
617             documentHeader = documentHeaderClass.newInstance();
618             documentHeader.setWorkflowDocument(workflowDocument);
619             documentHeader.setDocumentNumber(workflowDocument.getDocumentId());
620             // status and notes are initialized correctly in the constructor
621         } catch (IllegalAccessException e) {
622             throw new RuntimeException("Error instantiating DocumentHeader", e);
623         } catch (InstantiationException e) {
624             throw new RuntimeException("Error instantiating DocumentHeader", e);
625         }
626 
627         // build Document of specified type
628         Document document = null;
629         try {
630             // all maintenance documents have same class
631             if (MaintenanceDocumentBase.class.isAssignableFrom(documentClass)) {
632                 Class<?>[] defaultConstructor = new Class[]{String.class};
633                 Constructor<? extends Document> cons = documentClass.getConstructor(defaultConstructor);
634                 if (ObjectUtils.isNull(cons)) {
635                     throw new ConfigurationException(
636                             "Could not find constructor with document type name parameter needed for Maintenance Document Base class");
637                 }
638                 document = cons.newInstance(documentTypeName);
639             } else {
640                 // non-maintenance document
641                 document = documentClass.newInstance();
642             }
643         } catch (IllegalAccessException e) {
644             throw new RuntimeException("Error instantiating Document", e);
645         } catch (InstantiationException e) {
646             throw new RuntimeException("Error instantiating Document", e);
647         } catch (SecurityException e) {
648             throw new RuntimeException("Error instantiating Maintenance Document", e);
649         } catch (NoSuchMethodException e) {
650             throw new RuntimeException(
651                     "Error instantiating Maintenance Document: No constructor with String parameter found", e);
652         } catch (IllegalArgumentException e) {
653             throw new RuntimeException("Error instantiating Maintenance Document", e);
654         } catch (InvocationTargetException e) {
655             throw new RuntimeException("Error instantiating Maintenance Document", e);
656         }
657 
658         document.setDocumentHeader(documentHeader);
659         document.setDocumentNumber(documentHeader.getDocumentNumber());
660 
661         watch.stop();
662         if (LOG.isDebugEnabled()) {
663             LOG.debug(watchName + ": " + watch.toString());
664         }
665 
666         return document;
667     }
668 
669     /**
670      * Creates a new document by document type name.
671      *
672      * @see org.kuali.rice.krad.service.DocumentService#getNewDocument(String)
673      */
674     @Override
675     public Document getNewDocument(String documentTypeName) throws WorkflowException {
676         return getNewDocument(documentTypeName, null);
677     }
678 
679 
680     /**
681      * This is temporary until workflow 2.0 and reads from a table to get documents whose status has changed to A
682      * (approved - no
683      * outstanding approval actions requested)
684      *
685      * @param documentHeaderId
686      * @return Document
687      * @throws org.kuali.rice.kew.api.exception.WorkflowException
688      */
689     @Override
690     public Document getByDocumentHeaderId(String documentHeaderId) throws WorkflowException {
691         if (documentHeaderId == null) {
692             throw new IllegalArgumentException("invalid (null) documentHeaderId");
693         }
694         boolean internalUserSession = false;
695         try {
696             // KFSMI-2543 - allowed method to run without a user session so it can be used
697             // by workflow processes
698             if (GlobalVariables.getUserSession() == null) {
699                 internalUserSession = true;
700                 GlobalVariables.setUserSession(new UserSession(KRADConstants.SYSTEM_USER));
701                 GlobalVariables.clear();
702             }
703 
704             WorkflowDocument workflowDocument = null;
705 
706             if (LOG.isDebugEnabled()) {
707                 LOG.debug("Retrieving doc id: " + documentHeaderId + " from workflow service.");
708             }
709             workflowDocument = getWorkflowDocumentService()
710                     .loadWorkflowDocument(documentHeaderId, GlobalVariables.getUserSession().getPerson());
711             UserSessionUtils.addWorkflowDocument(GlobalVariables.getUserSession(), workflowDocument);
712 
713             Class<? extends Document> documentClass = getDocumentClassByTypeName(workflowDocument.getDocumentTypeName());
714 
715             // retrieve the Document
716             Document document = getDocumentDao().findByDocumentHeaderId(documentClass, documentHeaderId);
717 
718             return postProcessDocument(documentHeaderId, workflowDocument, document);
719         } finally {
720             // if a user session was established for this call, clear it out
721             if (internalUserSession) {
722                 GlobalVariables.clear();
723                 GlobalVariables.setUserSession(null);
724             }
725         }
726     }
727 
728     /**
729      * @see org.kuali.rice.krad.service.DocumentService#getByDocumentHeaderIdSessionless(String)
730      */
731     @Override
732     public Document getByDocumentHeaderIdSessionless(String documentHeaderId) throws WorkflowException {
733         if (documentHeaderId == null) {
734             throw new IllegalArgumentException("invalid (null) documentHeaderId");
735         }
736 
737         WorkflowDocument workflowDocument = null;
738 
739         if (LOG.isDebugEnabled()) {
740             LOG.debug("Retrieving doc id: " + documentHeaderId + " from workflow service.");
741         }
742 
743         Person person = getPersonService().getPersonByPrincipalName(KRADConstants.SYSTEM_USER);
744         workflowDocument = workflowDocumentService.loadWorkflowDocument(documentHeaderId, person);
745 
746         Class<? extends Document> documentClass = getDocumentClassByTypeName(workflowDocument.getDocumentTypeName());
747 
748         // retrieve the Document
749         Document document = getDocumentDao().findByDocumentHeaderId(documentClass, documentHeaderId);
750 
751         return postProcessDocument(documentHeaderId, workflowDocument, document);
752     }
753 
754     private Class<? extends Document> getDocumentClassByTypeName(String documentTypeName) {
755         if (StringUtils.isBlank(documentTypeName)) {
756             throw new IllegalArgumentException("invalid (blank) documentTypeName");
757         }
758 
759         Class<? extends Document> clazz = getDataDictionaryService().getDocumentClassByTypeName(documentTypeName);
760         if (clazz == null) {
761             throw new UnknownDocumentTypeException(
762                     "unable to get class for unknown documentTypeName '" + documentTypeName + "'");
763         }
764         return clazz;
765     }
766 
767     /**
768      * Loads the Notes for the note target on this Document.
769      *
770      * @param document the document for which to load the notes
771      */
772     protected void loadNotes(Document document) {
773         if (isNoteTargetReady(document)) {
774             List<Note> notes = new ArrayList<Note>();
775             if (StringUtils.isNotBlank(document.getNoteTarget().getObjectId())) {
776                 notes.addAll(getNoteService().getByRemoteObjectId(document.getNoteTarget().getObjectId()));
777             }
778             //notes created on 'disapprove' are linked to Doc Header, so this checks that even if notetype = BO
779             if (document.getNoteType().equals(NoteType.BUSINESS_OBJECT)
780                     && document.getDocumentHeader().getWorkflowDocument().isDisapproved()) {
781                 notes.addAll(getNoteService().getByRemoteObjectId(document.getDocumentHeader().getObjectId()));
782             }
783 
784             // KULRNE-5692 - force a refresh of the attachments
785             // they are not (non-updateable) references and don't seem to update properly upon load
786             for (Note note : notes) {
787                 note.refreshReferenceObject("attachment");
788             }
789             document.setNotes(notes);
790         }
791     }
792 
793     /**
794      * Performs required post-processing for every document from the documentDao
795      *
796      * @param documentHeaderId
797      * @param workflowDocument
798      * @param document
799      */
800     private Document postProcessDocument(String documentHeaderId, WorkflowDocument workflowDocument, Document document) {
801         if (document != null) {
802             document.getDocumentHeader().setWorkflowDocument(workflowDocument);
803             document.processAfterRetrieve();
804             loadNotes(document);
805         }
806         return document;
807     }
808 
809     /**
810      * The default implementation - this retrieves all documents by a list of documentHeader for a given class.
811      *
812      * @see org.kuali.rice.krad.service.DocumentService#getDocumentsByListOfDocumentHeaderIds(Class,
813      *      java.util.List)
814      */
815     @Override
816     public List<Document> getDocumentsByListOfDocumentHeaderIds(Class<? extends Document> documentClass,
817                                                                 List<String> documentHeaderIds) throws WorkflowException {
818         // validate documentHeaderIdList and contents
819         if (documentHeaderIds == null) {
820             throw new IllegalArgumentException("invalid (null) documentHeaderId list");
821         }
822         int index = 0;
823         for (String documentHeaderId : documentHeaderIds) {
824             if (StringUtils.isBlank(documentHeaderId)) {
825                 throw new IllegalArgumentException("invalid (blank) documentHeaderId at list index " + index);
826             }
827             index++;
828         }
829 
830         boolean internalUserSession = false;
831         try {
832             // KFSMI-2543 - allowed method to run without a user session so it can be used
833             // by workflow processes
834             if (GlobalVariables.getUserSession() == null) {
835                 internalUserSession = true;
836                 GlobalVariables.setUserSession(new UserSession(KRADConstants.SYSTEM_USER));
837                 GlobalVariables.clear();
838             }
839 
840             // retrieve all documents that match the document header ids
841             List<? extends Document> rawDocuments =
842                     getDocumentDao().findByDocumentHeaderIds(documentClass, documentHeaderIds);
843 
844             // post-process them
845             List<Document> documents = new ArrayList<Document>();
846             for (Document document : rawDocuments) {
847                 WorkflowDocument workflowDocument = getWorkflowDocumentService().loadWorkflowDocument(document.getDocumentNumber(), GlobalVariables.getUserSession().getPerson());
848 
849                 document = postProcessDocument(document.getDocumentNumber(), workflowDocument, document);
850                 documents.add(document);
851             }
852             return documents;
853         } finally {
854             // if a user session was established for this call, clear it our
855             if (internalUserSession) {
856                 GlobalVariables.clear();
857                 GlobalVariables.setUserSession(null);
858             }
859         }
860     }
861 
862     /* Helper Methods */
863 
864     /**
865      * Validates and persists a document.
866      */
867     @Override
868     public Document validateAndPersistDocument(Document document, KualiDocumentEvent event) throws ValidationException {
869         if (document == null) {
870             LOG.error("document passed to validateAndPersist was null");
871             throw new IllegalArgumentException("invalid (null) document");
872         }
873         if (LOG.isDebugEnabled()) {
874             LOG.debug("validating and preparing to persist document " + document.getDocumentNumber());
875         }
876 
877         document.validateBusinessRules(event);
878         document.prepareForSave(event);
879 
880         // save the document
881         Document savedDocument = null;
882         try {
883             if (LOG.isInfoEnabled()) {
884                 LOG.info("storing document " + document.getDocumentNumber());
885             }
886             savedDocument = getDocumentDao().save(document);
887         } catch (OptimisticLockingFailureException e) {
888             LOG.error("exception encountered on store of document " + e.getMessage());
889             throw e;
890         }
891 
892         boolean notesSaved = saveDocumentNotes(document);
893         if (!notesSaved) {
894             if (LOG.isInfoEnabled()) {
895                 LOG.info(
896                         "Notes not saved during validateAndPersistDocument, likely means that note save needs to be deferred because note target is not ready.");
897             }
898         }
899 
900         savedDocument.postProcessSave(event);
901 
902         return savedDocument;
903     }
904 
905     /**
906      * Sets the title and app document id in the flex document
907      *
908      * @param document
909      * @throws org.kuali.rice.kew.api.exception.WorkflowException
910      */
911     @Override
912     public void prepareWorkflowDocument(Document document) throws WorkflowException {
913         // populate document content so searchable attributes will be indexed properly
914         document.populateDocumentForRouting();
915 
916         // make sure we push the document title into the workflowDocument
917         populateDocumentTitle(document);
918 
919         // make sure we push the application document id into the workflowDocument
920         populateApplicationDocumentId(document);
921     }
922 
923     /**
924      * This method will grab the generated document title from the document and add it to the workflowDocument so that
925      * it gets pushed into
926      * workflow when routed.
927      *
928      * @param document
929      * @throws org.kuali.rice.kew.api.exception.WorkflowException
930      */
931     private void populateDocumentTitle(Document document) throws WorkflowException {
932         String documentTitle = document.getDocumentTitle();
933         if (StringUtils.isNotBlank(documentTitle)) {
934             document.getDocumentHeader().getWorkflowDocument().setTitle(documentTitle);
935         }
936     }
937 
938     /**
939      * This method will grab the organization document number from the document and add it to the workflowDocument so
940      * that it gets pushed
941      * into workflow when routed.
942      *
943      * @param document
944      */
945     private void populateApplicationDocumentId(Document document) {
946         String organizationDocumentNumber = document.getDocumentHeader().getOrganizationDocumentNumber();
947         if (StringUtils.isNotBlank(organizationDocumentNumber)) {
948             document.getDocumentHeader().getWorkflowDocument().setApplicationDocumentId(organizationDocumentNumber);
949         }
950     }
951 
952     /**
953      * This is to allow for updates of document statuses and other related requirements for updates outside of the
954      * initial save and
955      * route
956      */
957     @Override
958     public Document updateDocument(Document document) {
959         checkForNulls(document);
960         return getDocumentDao().save(document);
961     }
962 
963     /**
964      * @see org.kuali.rice.krad.service.DocumentService#createNoteFromDocument(org.kuali.rice.krad.document.Document,
965      *      String)
966      */
967     @Override
968     public Note createNoteFromDocument(Document document, String text) {
969         Note note = new Note();
970 
971         note.setNotePostedTimestamp(getDateTimeService().getCurrentTimestamp());
972         note.setVersionNumber(Long.valueOf(1));
973         note.setNoteText(text);
974         note.setNoteTypeCode(document.getNoteType().getCode());
975 
976         PersistableBusinessObject bo = document.getNoteTarget();
977         // TODO gah! this is awful
978         Person kualiUser = GlobalVariables.getUserSession().getPerson();
979         if (kualiUser == null) {
980             throw new IllegalStateException("Current UserSession has a null Person.");
981         }
982         return bo == null ? null : getNoteService().createNote(note, bo, kualiUser.getPrincipalId());
983     }
984 
985     /**
986      * @see org.kuali.rice.krad.service.DocumentService#saveDocumentNotes(org.kuali.rice.krad.document.Document)
987      */
988     @Override
989     public boolean saveDocumentNotes(Document document) {
990         if (isNoteTargetReady(document)) {
991             List<Note> notes = document.getNotes();
992             for (Note note : document.getNotes()) {
993                 linkNoteRemoteObjectId(note, document.getNoteTarget());
994             }
995             getNoteService().saveNoteList(notes);
996             return true;
997         }
998         return false;
999     }
1000 
1001     /**
1002      * @see org.kuali.rice.krad.service.DocumentService
1003      */
1004     @Override
1005     public void sendNoteRouteNotification(Document document, Note note, Person sender) throws WorkflowException {
1006         AdHocRouteRecipient routeRecipient = note.getAdHocRouteRecipient();
1007 
1008         // build notification request
1009         Person requestedUser = this.getPersonService().getPersonByPrincipalName(routeRecipient.getId());
1010         String senderName = sender.getFirstName() + " " + sender.getLastName();
1011         String requestedName = requestedUser.getFirstName() + " " + requestedUser.getLastName();
1012 
1013         String notificationText =
1014                 kualiConfigurationService.getPropertyValueAsString(
1015                         RiceKeyConstants.MESSAGE_NOTE_NOTIFICATION_ANNOTATION);
1016         if (StringUtils.isBlank(notificationText)) {
1017             throw new RuntimeException(
1018                     "No annotation message found for note notification. Message needs added to application resources with key:" +
1019                             RiceKeyConstants.MESSAGE_NOTE_NOTIFICATION_ANNOTATION);
1020         }
1021         notificationText =
1022                 MessageFormat.format(notificationText, new Object[]{senderName, requestedName, note.getNoteText()});
1023 
1024         List<AdHocRouteRecipient> routeRecipients = new ArrayList<AdHocRouteRecipient>();
1025         routeRecipients.add(routeRecipient);
1026 
1027         workflowDocumentService
1028                 .sendWorkflowNotification(document.getDocumentHeader().getWorkflowDocument(), notificationText,
1029                         routeRecipients, KRADConstants.NOTE_WORKFLOW_NOTIFICATION_REQUEST_LABEL);
1030 
1031         // clear recipient allowing an notification to be sent to another person
1032         note.setAdHocRouteRecipient(new AdHocRoutePerson());
1033     }
1034 
1035     /**
1036      * Determines if the given document's note target is ready for notes to be
1037      * attached and persisted against it.  This method verifies that the document's
1038      * note target is non-null as well as checking that it has a non-empty object id.
1039      *
1040      * @param document the document on which to check for note target readiness
1041      * @return true if the note target is ready, false otherwise
1042      */
1043     protected boolean isNoteTargetReady(Document document) {
1044 
1045         //special case for disappoved documents
1046         if (document.getDocumentHeader().getWorkflowDocument().isDisapproved()) {
1047             return true;
1048         }
1049         PersistableBusinessObject noteTarget = document.getNoteTarget();
1050         if (noteTarget == null || StringUtils.isBlank(noteTarget.getObjectId())) {
1051             return false;
1052         }
1053         return true;
1054     }
1055 
1056     private void linkNoteRemoteObjectId(Note note, PersistableBusinessObject noteTarget) {
1057         String objectId = noteTarget.getObjectId();
1058         if (StringUtils.isBlank(objectId)) {
1059             throw new IllegalStateException(
1060                     "Attempted to link a Note with a PersistableBusinessObject with no object id");
1061         }
1062         note.setRemoteObjectIdentifier(noteTarget.getObjectId());
1063     }
1064 
1065     /**
1066      * @see org.kuali.rice.krad.service.DocumentService#sendAdHocRequests(org.kuali.rice.krad.document.Document, String, java.util.List)
1067      */
1068     @Override
1069     public void sendAdHocRequests(Document document, String annotation,
1070                                   List<AdHocRouteRecipient> adHocRecipients) throws WorkflowException {
1071         prepareWorkflowDocument(document);
1072         getWorkflowDocumentService()
1073                 .sendWorkflowNotification(document.getDocumentHeader().getWorkflowDocument(), annotation,
1074                         adHocRecipients);
1075         UserSessionUtils.addWorkflowDocument(GlobalVariables.getUserSession(),
1076                 document.getDocumentHeader().getWorkflowDocument());
1077         //getBusinessObjectService().delete(document.getAdHocRoutePersons());
1078         //getBusinessObjectService().delete(document.getAdHocRouteWorkgroups());
1079         removeAdHocPersonsAndWorkgroups(document);
1080     }
1081 
1082     private void removeAdHocPersonsAndWorkgroups(Document document) {
1083         List<AdHocRoutePerson> adHocRoutePersons = new ArrayList<AdHocRoutePerson>();
1084         List<AdHocRouteWorkgroup> adHocRouteWorkgroups = new ArrayList<AdHocRouteWorkgroup>();
1085         getBusinessObjectService().delete(document.getAdHocRoutePersons());
1086         getBusinessObjectService().delete(document.getAdHocRouteWorkgroups());
1087         document.setAdHocRoutePersons(adHocRoutePersons);
1088         document.setAdHocRouteWorkgroups(adHocRouteWorkgroups);
1089     }
1090 
1091     public void setDateTimeService(DateTimeService dateTimeService) {
1092         this.dateTimeService = dateTimeService;
1093     }
1094 
1095     protected DateTimeService getDateTimeService() {
1096         if (this.dateTimeService == null) {
1097             this.dateTimeService = CoreApiServiceLocator.getDateTimeService();
1098         }
1099         return this.dateTimeService;
1100     }
1101 
1102     public void setNoteService(NoteService noteService) {
1103         this.noteService = noteService;
1104     }
1105 
1106     protected NoteService getNoteService() {
1107         if (this.noteService == null) {
1108             this.noteService = KRADServiceLocator.getNoteService();
1109         }
1110         return this.noteService;
1111     }
1112 
1113     public void setBusinessObjectService(BusinessObjectService businessObjectService) {
1114         this.businessObjectService = businessObjectService;
1115     }
1116 
1117     protected BusinessObjectService getBusinessObjectService() {
1118         if (this.businessObjectService == null) {
1119             this.businessObjectService = KRADServiceLocator.getBusinessObjectService();
1120         }
1121         return this.businessObjectService;
1122     }
1123 
1124     public void setWorkflowDocumentService(WorkflowDocumentService workflowDocumentService) {
1125         this.workflowDocumentService = workflowDocumentService;
1126     }
1127 
1128     protected WorkflowDocumentService getWorkflowDocumentService() {
1129         if (this.workflowDocumentService == null) {
1130             this.workflowDocumentService = KRADServiceLocatorWeb.getWorkflowDocumentService();
1131         }
1132         return this.workflowDocumentService;
1133     }
1134 
1135     public void setDocumentDao(DocumentDao documentDao) {
1136         this.documentDao = documentDao;
1137     }
1138 
1139     protected DocumentDao getDocumentDao() {
1140         return documentDao;
1141     }
1142 
1143     public void setDataDictionaryService(DataDictionaryService dataDictionaryService) {
1144         this.dataDictionaryService = dataDictionaryService;
1145     }
1146 
1147     protected DataDictionaryService getDataDictionaryService() {
1148         if (this.dataDictionaryService == null) {
1149             this.dataDictionaryService = KRADServiceLocatorWeb.getDataDictionaryService();
1150         }
1151         return this.dataDictionaryService;
1152     }
1153 
1154     public void setDocumentHeaderService(DocumentHeaderService documentHeaderService) {
1155         this.documentHeaderService = documentHeaderService;
1156     }
1157 
1158     protected DocumentHeaderService getDocumentHeaderService() {
1159         if (this.documentHeaderService == null) {
1160             this.documentHeaderService = KRADServiceLocatorWeb.getDocumentHeaderService();
1161         }
1162         return this.documentHeaderService;
1163     }
1164 
1165     protected DocumentDictionaryService getDocumentDictionaryService() {
1166         if (documentDictionaryService == null) {
1167             documentDictionaryService = KRADServiceLocatorWeb.getDocumentDictionaryService();
1168         }
1169         return documentDictionaryService;
1170     }
1171 
1172     public void setDocumentDictionaryService(DocumentDictionaryService documentDictionaryService) {
1173         this.documentDictionaryService = documentDictionaryService;
1174     }
1175 
1176     public PersonService getPersonService() {
1177         if (personService == null) {
1178             personService = KimApiServiceLocator.getPersonService();
1179         }
1180         return personService;
1181     }
1182 
1183     public void setKualiConfigurationService(ConfigurationService kualiConfigurationService) {
1184         this.kualiConfigurationService = kualiConfigurationService;
1185     }
1186 
1187 
1188     public void processGlobalAlerts(Document document){
1189 
1190         AlertGlobalConfigurationServiceImpl alertGlobalConfigurationService = new AlertGlobalConfigurationServiceImpl();
1191         alertGlobalConfigurationService.processAlert(document);
1192        //get the class name
1193        //get the alert document
1194        //get the events
1195         //pass the event and object
1196         //get the value form the object using reflection
1197         //check for the conditions if everything get passed for the enent then send mail or alert based on the role user and group id and send the alert
1198 
1199       /*   AlertEvent alertEvent = new AlertEvent();
1200         alertEvent.setActive(true);
1201         alertEvent.setAlertDocumentClassName("org.kuali.ole.deliver.bo.OleDeliverRequestType");
1202         alertEvent.setAlertDocumentTypeName("DLVR_TYP_t");
1203         AlertEventField alertEventField = new AlertEventField();
1204         alertEventField.setActive(true);
1205         alertEventField.setAlertFieldName("active");
1206         alertEventField.setAlertFieldType("boolean");
1207         alertEventField.setAlertFieldValue("true");
1208         alertEventField.setAlertCriteria("equalTo");
1209        // alertEventField.setAlertCriteria("notEqualTo");
1210         AlertEventField alertEventField1 = new AlertEventField();
1211         alertEventField1.setActive(true);
1212         alertEventField1.setAlertFieldValue("Mahesh");
1213         alertEventField1.setAlertFieldType("String");
1214         alertEventField1.setAlertFieldName("requestTypeCode");
1215      //   alertEventField1.setAlertCriteria("equalTo");
1216         alertEventField1.setAlertCriteria("notEqualTo");
1217 
1218         AlertEventField alertEventField2= new AlertEventField();
1219         alertEventField2.setAlertFieldName("requestInteger");
1220       //  alertEventField2.setAlertCriteria("equalTo");
1221         alertEventField2.setAlertCriteria("greaterThanOrEqualTo");
1222       *//*  alertEventField2.setAlertCriteria("equalTo");
1223         alertEventField2.setAlertCriteria("equalTo");
1224         alertEventField2.setAlertCriteria("equalTo");
1225         alertEventField2.setAlertCriteria("equalTo");
1226         alertEventField2.setAlertCriteria("equalTo");*//*
1227         alertEventField2.setAlertFieldType("Integer");
1228         alertEventField2.setAlertFieldValue("10");
1229         List<AlertEventField> alertEventFieldList = new ArrayList<AlertEventField>();
1230        // alertEventFieldList.add(alertEventField);
1231         //alertEventFieldList.add(alertEventField1);
1232         alertEventFieldList.add(alertEventField2);
1233         alertEvent.setAlertEventFieldList(alertEventFieldList);
1234         OleDeliverRequestType oleDeliverRequestType = new OleDeliverRequestType();
1235         oleDeliverRequestType.setActive(true);
1236         oleDeliverRequestType.setRequestTypeCode("kumar");
1237         oleDeliverRequestType.setRequestInteger(100);
1238         AlertGlobalConfigurationServiceImpl alertGlobalConfigurationService = new AlertGlobalConfigurationServiceImpl();
1239         alertGlobalConfigurationService.processEvent(alertEvent,oleDeliverRequestType);*/
1240     }
1241 
1242 }