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