001package org.kuali.rice.krad.service.impl;
002
003/**
004 * Created by maheswarang on 12/17/14.
005 */
006
007import org.apache.commons.lang.StringUtils;
008import org.apache.commons.lang.time.StopWatch;
009import org.kuali.ole.alert.bo.AlertBo;
010import org.kuali.ole.alert.bo.AlertEvent;
011import org.kuali.ole.alert.bo.AlertEventField;
012import org.kuali.ole.alert.document.OlePersistableBusinessObjectBase;
013import org.kuali.ole.alert.document.OleTransactionalDocumentBase;
014import org.kuali.ole.alert.service.AlertGlobalConfigurationServiceImpl;
015import org.kuali.ole.alert.service.impl.AlertServiceImpl;
016import org.kuali.ole.deliver.bo.OleDeliverRequestType;
017import org.kuali.rice.core.api.CoreApiServiceLocator;
018import org.kuali.rice.core.api.config.ConfigurationException;
019import org.kuali.rice.core.api.config.property.ConfigurationService;
020import org.kuali.rice.core.api.datetime.DateTimeService;
021import org.kuali.rice.core.api.util.RiceKeyConstants;
022import org.kuali.rice.core.framework.persistence.jta.TransactionalNoValidationExceptionRollback;
023import org.kuali.rice.kew.api.WorkflowDocument;
024import org.kuali.rice.kew.api.exception.WorkflowException;
025import org.kuali.rice.kim.api.identity.Person;
026import org.kuali.rice.kim.api.identity.PersonService;
027import org.kuali.rice.kim.api.services.KimApiServiceLocator;
028import org.kuali.rice.krad.UserSession;
029import org.kuali.rice.krad.UserSessionUtils;
030import org.kuali.rice.krad.bo.*;
031import org.kuali.rice.krad.dao.DocumentDao;
032import org.kuali.rice.krad.datadictionary.exception.UnknownDocumentTypeException;
033import org.kuali.rice.krad.document.Document;
034import org.kuali.rice.krad.document.DocumentAuthorizer;
035import org.kuali.rice.krad.document.DocumentPresentationController;
036import org.kuali.rice.krad.exception.DocumentAuthorizationException;
037import org.kuali.rice.krad.exception.ValidationException;
038import org.kuali.rice.krad.maintenance.MaintenanceDocument;
039import org.kuali.rice.krad.maintenance.MaintenanceDocumentBase;
040import org.kuali.rice.krad.rules.rule.event.*;
041import org.kuali.rice.krad.service.*;
042import org.kuali.rice.krad.util.GlobalVariables;
043import org.kuali.rice.krad.util.KRADConstants;
044import org.kuali.rice.krad.util.NoteType;
045import org.kuali.rice.krad.util.ObjectUtils;
046import org.kuali.rice.krad.workflow.service.WorkflowDocumentService;
047import org.springframework.dao.OptimisticLockingFailureException;
048
049import java.lang.reflect.Constructor;
050import java.lang.reflect.InvocationTargetException;
051import java.text.MessageFormat;
052import java.util.ArrayList;
053import java.util.HashMap;
054import java.util.List;
055import java.util.Map;
056
057
058/**
059 * Service implementation for the Document structure. It contains all of the document level type of
060 * processing and calling back into documents for various centralization of functionality. This is the default,
061 * Kuali delivered implementation which utilizes Workflow.
062 *
063 * @author Kuali Rice Team (rice.collab@kuali.org)
064 */
065@TransactionalNoValidationExceptionRollback
066public class DocumentServiceImpl implements DocumentService {
067    private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(DocumentServiceImpl.class);
068
069    private DocumentDao documentDao;
070
071    private DateTimeService dateTimeService;
072    private NoteService noteService;
073    private WorkflowDocumentService workflowDocumentService;
074    private BusinessObjectService businessObjectService;
075    private DataDictionaryService dataDictionaryService;
076    private DocumentHeaderService documentHeaderService;
077    private DocumentDictionaryService documentDictionaryService;
078    private PersonService personService;
079    private ConfigurationService kualiConfigurationService;
080
081    public AlertServiceImpl getAlertService(){
082        return new AlertServiceImpl();
083    }
084
085    /**
086     * @see org.kuali.rice.krad.service.DocumentService#saveDocument(org.kuali.rice.krad.document.Document)
087     */
088    @Override
089    public Document saveDocument(Document document) throws WorkflowException, ValidationException {
090        return saveDocument(document, SaveDocumentEvent.class);
091    }
092
093    @Override
094    public Document saveDocument(Document document,
095                                 Class<? extends KualiDocumentEvent> kualiDocumentEventClass) throws WorkflowException, ValidationException {
096        checkForNulls(document);
097        if (kualiDocumentEventClass == null) {
098            throw new IllegalArgumentException("invalid (null) kualiDocumentEventClass");
099        }
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}