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        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}