Coverage Report - org.kuali.rice.kns.service.impl.DocumentServiceImpl
 
Classes in this File Line Coverage Branch Coverage Complexity
DocumentServiceImpl
0%
0/363
0%
0/116
3.056
 
 1  
 /*
 2  
  * Copyright 2005-2007 The Kuali Foundation
 3  
  *
 4  
  * Licensed under the Educational Community License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  * http://www.opensource.org/licenses/ecl2.php
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  */
 16  
 package org.kuali.rice.kns.service.impl;
 17  
 
 18  
 import java.lang.reflect.Constructor;
 19  
 import java.lang.reflect.InvocationTargetException;
 20  
 import java.util.ArrayList;
 21  
 import java.util.HashMap;
 22  
 import java.util.Iterator;
 23  
 import java.util.List;
 24  
 
 25  
 import org.apache.commons.lang.StringUtils;
 26  
 import org.kuali.rice.core.config.ConfigurationException;
 27  
 import org.kuali.rice.kew.exception.WorkflowException;
 28  
 import org.kuali.rice.kim.bo.Person;
 29  
 import org.kuali.rice.kim.service.KIMServiceLocator;
 30  
 import org.kuali.rice.kim.service.PersonService;
 31  
 import org.kuali.rice.kns.UserSession;
 32  
 import org.kuali.rice.kns.bo.AdHocRoutePerson;
 33  
 import org.kuali.rice.kns.bo.AdHocRouteRecipient;
 34  
 import org.kuali.rice.kns.bo.AdHocRouteWorkgroup;
 35  
 import org.kuali.rice.kns.bo.DocumentHeader;
 36  
 import org.kuali.rice.kns.bo.Note;
 37  
 import org.kuali.rice.kns.bo.PersistableBusinessObject;
 38  
 import org.kuali.rice.kns.dao.DocumentDao;
 39  
 import org.kuali.rice.kns.document.Document;
 40  
 import org.kuali.rice.kns.document.MaintenanceDocument;
 41  
 import org.kuali.rice.kns.document.MaintenanceDocumentBase;
 42  
 import org.kuali.rice.kns.document.authorization.DocumentAuthorizer;
 43  
 import org.kuali.rice.kns.document.authorization.DocumentPresentationController;
 44  
 import org.kuali.rice.kns.exception.DocumentAuthorizationException;
 45  
 import org.kuali.rice.kns.exception.UnknownDocumentTypeException;
 46  
 import org.kuali.rice.kns.exception.ValidationException;
 47  
 import org.kuali.rice.kns.rule.event.ApproveDocumentEvent;
 48  
 import org.kuali.rice.kns.rule.event.BlanketApproveDocumentEvent;
 49  
 import org.kuali.rice.kns.rule.event.KualiDocumentEvent;
 50  
 import org.kuali.rice.kns.rule.event.RouteDocumentEvent;
 51  
 import org.kuali.rice.kns.rule.event.SaveDocumentEvent;
 52  
 import org.kuali.rice.kns.rule.event.SaveEvent;
 53  
 import org.kuali.rice.kns.service.BusinessObjectService;
 54  
 import org.kuali.rice.kns.service.DataDictionaryService;
 55  
 import org.kuali.rice.kns.service.DateTimeService;
 56  
 import org.kuali.rice.kns.service.DictionaryValidationService;
 57  
 import org.kuali.rice.kns.service.DocumentHeaderService;
 58  
 import org.kuali.rice.kns.service.DocumentHelperService;
 59  
 import org.kuali.rice.kns.service.DocumentService;
 60  
 import org.kuali.rice.kns.service.KNSServiceLocator;
 61  
 import org.kuali.rice.kns.service.KualiRuleService;
 62  
 import org.kuali.rice.kns.service.MaintenanceDocumentService;
 63  
 import org.kuali.rice.kns.service.NoteService;
 64  
 import org.kuali.rice.kns.util.GlobalVariables;
 65  
 import org.kuali.rice.kns.util.KNSConstants;
 66  
 import org.kuali.rice.kns.util.ObjectUtils;
 67  
 import org.kuali.rice.kns.util.Timer;
 68  
 import org.kuali.rice.kns.workflow.service.KualiWorkflowDocument;
 69  
 import org.kuali.rice.kns.workflow.service.WorkflowDocumentService;
 70  
 import org.springframework.dao.OptimisticLockingFailureException;
 71  
 import org.springframework.transaction.annotation.Transactional;
 72  
 
 73  
 
 74  
 
 75  
 /**
 76  
  * This class is the service implementation for the Document structure. It contains all of the document level type of processing and
 77  
  * calling back into documents for various centralization of functionality. This is the default, Kuali delivered implementation
 78  
  * which utilizes Workflow.
 79  
  */
 80  
 @Transactional
 81  0
 public class DocumentServiceImpl implements DocumentService {
 82  0
     private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(DocumentServiceImpl.class);
 83  
 
 84  
     private DateTimeService dateTimeService;
 85  
 
 86  
     private NoteService noteService;
 87  
 
 88  
     protected WorkflowDocumentService workflowDocumentService;
 89  
 
 90  
     protected BusinessObjectService businessObjectService;
 91  
 
 92  
     /**
 93  
      * Don't access directly, use synchronized getter and setter to access
 94  
      */
 95  
     private DocumentDao documentDao;
 96  
 
 97  
     private DataDictionaryService dataDictionaryService;
 98  
 
 99  
     private DocumentHeaderService documentHeaderService;
 100  
 
 101  
     private PersonService personService;
 102  
 
 103  
     private DocumentHelperService documentHelperService;
 104  
 
 105  
     /**
 106  
      * @see org.kuali.rice.kns.service.DocumentService#saveDocument(org.kuali.rice.kns.document.Document)
 107  
      */
 108  
     public Document saveDocument(Document document) throws WorkflowException, ValidationException {
 109  0
         return saveDocument(document, SaveDocumentEvent.class);
 110  
     }
 111  
 
 112  
     public Document saveDocument(Document document, Class kualiDocumentEventClass) throws WorkflowException, ValidationException {
 113  0
         checkForNulls(document);
 114  0
         if (kualiDocumentEventClass == null) {
 115  0
             throw new IllegalArgumentException("invalid (null) kualiDocumentEventClass");
 116  
         }
 117  
         // if event is not an instance of a SaveDocumentEvent or a SaveOnlyDocumentEvent
 118  0
         if (!SaveEvent.class.isAssignableFrom(kualiDocumentEventClass)) {
 119  0
             throw new ConfigurationException("The KualiDocumentEvent class '" + kualiDocumentEventClass.getName() + "' does not implement the class '" + SaveEvent.class.getName() + "'");
 120  
         }
 121  
 //        if (!getDocumentActionFlags(document).getCanSave()) {
 122  
 //            throw buildAuthorizationException("save", document);
 123  
 //        }
 124  0
         document.prepareForSave();
 125  0
         validateAndPersistDocumentAndSaveAdHocRoutingRecipients(document, generateKualiDocumentEvent(document, kualiDocumentEventClass));
 126  0
         prepareWorkflowDocument(document);
 127  0
         getWorkflowDocumentService().save(document.getDocumentHeader().getWorkflowDocument(), null);
 128  0
         GlobalVariables.getUserSession().setWorkflowDocument(document.getDocumentHeader().getWorkflowDocument());
 129  
 
 130  0
         return document;
 131  
     }
 132  
 
 133  
     private KualiDocumentEvent generateKualiDocumentEvent(Document document, Class eventClass) throws ConfigurationException {
 134  0
             String potentialErrorMessage = "Found error trying to generate Kuali Document Event using event class '" + 
 135  
             eventClass.getName() + "' for document " + document.getDocumentNumber();
 136  
             
 137  
             try {
 138  0
                     Constructor usableConstructor = null;
 139  0
                     List<Object> paramList = null;
 140  0
                     for (Constructor currentConstructor : eventClass.getConstructors()) {
 141  0
                             paramList = new ArrayList<Object>();
 142  0
                             for (Class parameterClass : currentConstructor.getParameterTypes()) {
 143  0
                                     if (Document.class.isAssignableFrom(parameterClass)) {
 144  0
                                             usableConstructor = currentConstructor;
 145  0
                                             paramList.add(document);
 146  
                                     } else {
 147  0
                                             paramList.add(null);
 148  
                                     }
 149  
                             }
 150  0
                             if (ObjectUtils.isNotNull(usableConstructor)) {
 151  0
                                     break;
 152  
                             }
 153  
                     }
 154  0
                     if (ObjectUtils.isNull(usableConstructor)) {
 155  0
                             throw new RuntimeException("Cannot find a constructor for class '" + eventClass.getName() + "' that takes in a document parameter");
 156  
                     }
 157  
                     else {
 158  0
                             usableConstructor.newInstance(paramList.toArray());
 159  0
                             return (KualiDocumentEvent) usableConstructor.newInstance(paramList.toArray());
 160  
                     }
 161  0
             } catch (SecurityException e) {
 162  0
                     throw new ConfigurationException(potentialErrorMessage, e);
 163  0
             } catch (IllegalArgumentException e) {
 164  0
                     throw new ConfigurationException(potentialErrorMessage, e);
 165  0
             } catch (InstantiationException e) {
 166  0
                     throw new ConfigurationException(potentialErrorMessage, e);
 167  0
             } catch (IllegalAccessException e) {
 168  0
                     throw new ConfigurationException(potentialErrorMessage, e);
 169  0
             } catch (InvocationTargetException e) {
 170  0
                     throw new ConfigurationException(potentialErrorMessage, e);
 171  
             }
 172  
     }
 173  
 
 174  
     /**
 175  
      * @see org.kuali.rice.kns.service.DocumentService#routeDocument(org.kuali.rice.kns.document.Document, java.lang.String, java.util.List)
 176  
      */
 177  
     public Document routeDocument(Document document, String annotation, List adHocRecipients) throws ValidationException, WorkflowException {
 178  0
         checkForNulls(document);
 179  
         //if (!getDocumentActionFlags(document).getCanRoute()) {
 180  
         //    throw buildAuthorizationException("route", document);
 181  
         //}
 182  0
         document.prepareForSave();
 183  0
         validateAndPersistDocument(document, new RouteDocumentEvent(document));
 184  0
         prepareWorkflowDocument(document);
 185  0
         getWorkflowDocumentService().route(document.getDocumentHeader().getWorkflowDocument(), annotation, adHocRecipients);
 186  0
         GlobalVariables.getUserSession().setWorkflowDocument(document.getDocumentHeader().getWorkflowDocument());
 187  
         //getBusinessObjectService().delete(document.getAdHocRoutePersons());
 188  
         //getBusinessObjectService().delete(document.getAdHocRouteWorkgroups());
 189  0
         removeAdHocPersonsAndWorkgroups(document);
 190  0
         return document;
 191  
     }
 192  
 
 193  
     /**
 194  
      * @see org.kuali.rice.kns.service.DocumentService#approveDocument(org.kuali.rice.kns.document.Document, java.lang.String,
 195  
      *      java.util.List)
 196  
      */
 197  
     public Document approveDocument(Document document, String annotation, List adHocRecipients) throws ValidationException, WorkflowException {
 198  0
         checkForNulls(document);
 199  
         //if (!getDocumentActionFlags(document).getCanApprove()) {
 200  
         //    throw buildAuthorizationException("approve", document);
 201  
         //}
 202  0
         document.prepareForSave();
 203  0
         validateAndPersistDocument(document, new ApproveDocumentEvent(document));
 204  0
         prepareWorkflowDocument(document);
 205  0
         getWorkflowDocumentService().approve(document.getDocumentHeader().getWorkflowDocument(), annotation, adHocRecipients);
 206  0
         GlobalVariables.getUserSession().setWorkflowDocument(document.getDocumentHeader().getWorkflowDocument());
 207  0
         return document;
 208  
     }
 209  
 
 210  
 
 211  
     /**
 212  
      * @see org.kuali.rice.kns.service.DocumentService#superUserApproveDocument(org.kuali.rice.kns.document.Document, java.lang.String)
 213  
      */
 214  
     public Document superUserApproveDocument(Document document, String annotation) throws WorkflowException {
 215  0
         getDocumentDao().save(document);
 216  0
         prepareWorkflowDocument(document);
 217  0
         getWorkflowDocumentService().superUserApprove(document.getDocumentHeader().getWorkflowDocument(), annotation);
 218  0
         GlobalVariables.getUserSession().setWorkflowDocument(document.getDocumentHeader().getWorkflowDocument());
 219  0
         return document;
 220  
     }
 221  
 
 222  
     /**
 223  
      * @see org.kuali.rice.kns.service.DocumentService#superUserCancelDocument(org.kuali.rice.kns.document.Document, java.lang.String)
 224  
      */
 225  
     public Document superUserCancelDocument(Document document, String annotation) throws WorkflowException {
 226  0
         getDocumentDao().save(document);
 227  0
         prepareWorkflowDocument(document);
 228  0
         getWorkflowDocumentService().superUserCancel(document.getDocumentHeader().getWorkflowDocument(), annotation);
 229  0
         GlobalVariables.getUserSession().setWorkflowDocument(document.getDocumentHeader().getWorkflowDocument());
 230  0
         return document;
 231  
     }
 232  
 
 233  
     /**
 234  
      * @see org.kuali.rice.kns.service.DocumentService#superUserCancelDocument(org.kuali.rice.kns.document.Document, java.lang.String)
 235  
      */
 236  
     public Document superUserDisapproveDocument(Document document, String annotation) throws WorkflowException {
 237  0
         getDocumentDao().save(document);
 238  0
         prepareWorkflowDocument(document);
 239  0
         getWorkflowDocumentService().superUserDisapprove(document.getDocumentHeader().getWorkflowDocument(), annotation);
 240  0
         GlobalVariables.getUserSession().setWorkflowDocument(document.getDocumentHeader().getWorkflowDocument());
 241  0
         return document;
 242  
     }
 243  
 
 244  
     /**
 245  
      * @see org.kuali.rice.kns.service.DocumentService#disapproveDocument(org.kuali.rice.kns.document.Document, java.lang.String)
 246  
      */
 247  
     public Document disapproveDocument(Document document, String annotation) throws Exception {
 248  0
         checkForNulls(document);
 249  
         //if (!getDocumentActionFlags(document).getCanDisapprove()) {
 250  
         //    throw buildAuthorizationException("disapprove", document);
 251  
         //}
 252  
 
 253  0
         Note note = createNoteFromDocument(document,annotation);
 254  0
         addNoteToDocument(document, note);
 255  
 
 256  
         //SAVE THE NOTE
 257  
         //Note: This save logic is replicated here and in KualiDocumentAction, when to save (based on doc state) should be moved
 258  
         //      into a doc service method
 259  0
         getNoteService().save(note);
 260  
 
 261  0
         prepareWorkflowDocument(document);
 262  0
         getWorkflowDocumentService().disapprove(document.getDocumentHeader().getWorkflowDocument(), annotation);
 263  0
         GlobalVariables.getUserSession().setWorkflowDocument(document.getDocumentHeader().getWorkflowDocument());
 264  0
         return document;
 265  
     }
 266  
 
 267  
     /**
 268  
      * @see org.kuali.rice.kns.service.DocumentService#cancelDocument(org.kuali.rice.kns.document.Document, java.lang.String)
 269  
      */
 270  
     public Document cancelDocument(Document document, String annotation) throws WorkflowException {
 271  0
         checkForNulls(document);
 272  
         //if (!getDocumentActionFlags(document).getCanCancel()) {
 273  
         //    throw buildAuthorizationException("cancel", document);
 274  
         //}
 275  0
         if (document instanceof MaintenanceDocument) {
 276  0
                 MaintenanceDocument maintDoc = ((MaintenanceDocument) document);
 277  0
                 if (maintDoc.getOldMaintainableObject() != null) {
 278  0
                         maintDoc.getOldMaintainableObject().getBusinessObject().refresh();
 279  
                 }
 280  0
                        maintDoc.getNewMaintainableObject().getBusinessObject().refresh();
 281  
         }
 282  0
         prepareWorkflowDocument(document);
 283  0
         getWorkflowDocumentService().cancel(document.getDocumentHeader().getWorkflowDocument(), annotation);
 284  0
         GlobalVariables.getUserSession().setWorkflowDocument(document.getDocumentHeader().getWorkflowDocument());
 285  
         //getBusinessObjectService().delete(document.getAdHocRoutePersons());
 286  
         //getBusinessObjectService().delete(document.getAdHocRouteWorkgroups());
 287  0
         removeAdHocPersonsAndWorkgroups(document);
 288  0
         return document;
 289  
     }
 290  
 
 291  
     /**
 292  
      * @see org.kuali.rice.kns.service.DocumentService#acknowledgeDocument(org.kuali.rice.kns.document.Document, java.lang.String,
 293  
      *      java.util.List)
 294  
      */
 295  
     public Document acknowledgeDocument(Document document, String annotation, List adHocRecipients) throws WorkflowException {
 296  0
         checkForNulls(document);
 297  
         //if (!getDocumentActionFlags(document).getCanAcknowledge()) {
 298  
         //    throw buildAuthorizationException("acknowledge", document);
 299  
         //}
 300  0
         prepareWorkflowDocument(document);
 301  0
         getWorkflowDocumentService().acknowledge(document.getDocumentHeader().getWorkflowDocument(), annotation, adHocRecipients);
 302  0
         GlobalVariables.getUserSession().setWorkflowDocument(document.getDocumentHeader().getWorkflowDocument());
 303  0
         return document;
 304  
     }
 305  
 
 306  
     /**
 307  
      * @see org.kuali.rice.kns.service.DocumentService#blanketApproveDocument(org.kuali.rice.kns.document.Document, java.lang.String,
 308  
      *      java.util.List)
 309  
      */
 310  
     public Document blanketApproveDocument(Document document, String annotation, List adHocRecipients) throws ValidationException, WorkflowException {
 311  0
         checkForNulls(document);
 312  
         //if (!getDocumentActionFlags(document).getCanBlanketApprove()) {
 313  
         //    throw buildAuthorizationException("blanket approve", document);
 314  
         //}
 315  0
         document.prepareForSave();
 316  0
         validateAndPersistDocument(document, new BlanketApproveDocumentEvent(document));
 317  0
         prepareWorkflowDocument(document);
 318  0
         getWorkflowDocumentService().blanketApprove(document.getDocumentHeader().getWorkflowDocument(), annotation, adHocRecipients);
 319  0
         GlobalVariables.getUserSession().setWorkflowDocument(document.getDocumentHeader().getWorkflowDocument());
 320  0
         return document;
 321  
     }
 322  
 
 323  
     /**
 324  
      * @see org.kuali.rice.kns.service.DocumentService#clearDocumentFyi(org.kuali.rice.kns.document.Document, java.util.List)
 325  
      */
 326  
     public Document clearDocumentFyi(Document document, List adHocRecipients) throws WorkflowException {
 327  0
         checkForNulls(document);
 328  
         //if (!getDocumentActionFlags(document).getCanFYI()) {
 329  
          //   throw buildAuthorizationException("clear FYI", document);
 330  
         //}
 331  
         // populate document content so searchable attributes will be indexed properly
 332  0
         document.populateDocumentForRouting();
 333  0
         getWorkflowDocumentService().clearFyi(document.getDocumentHeader().getWorkflowDocument(), adHocRecipients);
 334  0
         GlobalVariables.getUserSession().setWorkflowDocument(document.getDocumentHeader().getWorkflowDocument());
 335  0
         return document;
 336  
     }
 337  
 
 338  
     protected void checkForNulls(Document document) {
 339  0
         if (document == null) {
 340  0
             throw new IllegalArgumentException("invalid (null) document");
 341  
         }
 342  0
         if (document.getDocumentNumber() == null) {
 343  0
             throw new IllegalStateException("invalid (null) documentHeaderId");
 344  
         }
 345  0
     }
 346  
 
 347  
     private void validateAndPersistDocumentAndSaveAdHocRoutingRecipients(Document document, KualiDocumentEvent event) throws WorkflowException {
 348  
         /*
 349  
          * Using this method to wrap validateAndPersistDocument to keep everything in one transaction. This avoids modifying the
 350  
          * signature on validateAndPersistDocument method
 351  
          */
 352  0
         ArrayList<AdHocRouteRecipient> adHocRoutingRecipients = new ArrayList();
 353  0
         adHocRoutingRecipients.addAll(document.getAdHocRoutePersons());
 354  0
         adHocRoutingRecipients.addAll(document.getAdHocRouteWorkgroups());
 355  
 
 356  0
         for (AdHocRouteRecipient recipient : adHocRoutingRecipients)
 357  0
             recipient.setdocumentNumber(document.getDocumentNumber());
 358  0
         HashMap criteria = new HashMap();
 359  0
         criteria.put("documentNumber", document.getDocumentNumber());
 360  0
         getBusinessObjectService().deleteMatching(AdHocRouteRecipient.class, criteria);
 361  
 
 362  0
         getBusinessObjectService().save(adHocRoutingRecipients);
 363  0
         validateAndPersistDocument(document, event);
 364  0
     }
 365  
 
 366  
     /**
 367  
      * @see org.kuali.rice.kns.service.DocumentService#documentExists(java.lang.String)
 368  
      */
 369  
     public boolean documentExists(String documentHeaderId) {
 370  
         // validate parameters
 371  0
         if (StringUtils.isBlank(documentHeaderId)) {
 372  0
             throw new IllegalArgumentException("invalid (blank) documentHeaderId");
 373  
         }
 374  
 
 375  0
             boolean internalUserSession = false;
 376  
             try {
 377  
                     // KFSMI-2543 - allowed method to run without a user session so it can be used
 378  
                     // by workflow processes
 379  0
                 if (GlobalVariables.getUserSession() == null) {
 380  0
                         internalUserSession = true;
 381  0
                         GlobalVariables.setUserSession(new UserSession(KNSConstants.SYSTEM_USER));
 382  0
                         GlobalVariables.clear();
 383  
                 }
 384  
 
 385  
                 // look for workflowDocumentHeader, since that supposedly won't break the transaction
 386  0
                 if (getWorkflowDocumentService().workflowDocumentExists(documentHeaderId)) {
 387  
                     // look for docHeaderId, since that fails without breaking the transaction
 388  0
                     return getDocumentHeaderService().getDocumentHeaderById(documentHeaderId) != null;
 389  
                 }
 390  
 
 391  0
                 return false;
 392  
             } finally {
 393  
                     // if a user session was established for this call, clear it our
 394  0
                     if ( internalUserSession ) {
 395  0
                             GlobalVariables.clear();
 396  0
                             GlobalVariables.setUserSession(null);
 397  
                     }
 398  
             }
 399  
     }
 400  
 
 401  
     /**
 402  
      * Creates a new document by class.
 403  
      *
 404  
      * @see org.kuali.rice.kns.service.DocumentService#getNewDocument(java.lang.Class)
 405  
      */
 406  
     public Document getNewDocument(Class documentClass) throws WorkflowException {
 407  0
         if (documentClass == null) {
 408  0
             throw new IllegalArgumentException("invalid (null) documentClass");
 409  
         }
 410  0
         if (!Document.class.isAssignableFrom(documentClass)) {
 411  0
             throw new IllegalArgumentException("invalid (non-Document) documentClass");
 412  
         }
 413  
 
 414  0
         String documentTypeName = getDataDictionaryService().getDocumentTypeNameByClass(documentClass);
 415  0
         if (StringUtils.isBlank(documentTypeName)) {
 416  0
             throw new UnknownDocumentTypeException("unable to get documentTypeName for unknown documentClass '" + documentClass.getName() + "'");
 417  
         }
 418  0
         return getNewDocument(documentTypeName);
 419  
     }
 420  
 
 421  
 
 422  
     /**
 423  
      * Creates a new document by document type name.
 424  
      *
 425  
      * @see org.kuali.rice.kns.service.DocumentService#getNewDocument(java.lang.String)
 426  
      */
 427  
     public Document getNewDocument(String documentTypeName) throws WorkflowException {
 428  
 
 429  
         // argument validation
 430  0
         Timer t0 = new Timer("DocumentServiceImpl.getNewDocument");
 431  0
         if (StringUtils.isBlank(documentTypeName)) {
 432  0
             throw new IllegalArgumentException("invalid (blank) documentTypeName");
 433  
         }
 434  0
         if (GlobalVariables.getUserSession() == null) {
 435  0
             throw new IllegalStateException("GlobalVariables must be populated with a valid UserSession before a new document can be created");
 436  
         }
 437  
 
 438  
         // get the class for this docTypeName
 439  0
         Class documentClass = getDocumentClassByTypeName(documentTypeName);
 440  
 
 441  
         // get the current user
 442  0
         Person currentUser = GlobalVariables.getUserSession().getPerson();
 443  
 
 444  
         // get the authorization
 445  0
         DocumentAuthorizer documentAuthorizer = getDocumentHelperService().getDocumentAuthorizer(documentTypeName);
 446  0
         DocumentPresentationController documentPresentationController = getDocumentHelperService().getDocumentPresentationController(documentTypeName);
 447  
         // make sure this person is authorized to initiate
 448  0
         LOG.debug("calling canInitiate from getNewDocument()");
 449  0
         if (!documentPresentationController.canInitiate(documentTypeName) || !documentAuthorizer.canInitiate(documentTypeName, currentUser)) {
 450  0
                 throw new DocumentAuthorizationException(currentUser.getPrincipalName(), "initiate", documentTypeName);
 451  
         }
 452  
 
 453  
         // initiate new workflow entry, get the workflow doc
 454  0
         KualiWorkflowDocument workflowDocument = getWorkflowDocumentService().createWorkflowDocument(documentTypeName, GlobalVariables.getUserSession().getPerson());
 455  0
         GlobalVariables.getUserSession().setWorkflowDocument(workflowDocument);
 456  
 
 457  
         // create a new document header object
 458  0
         DocumentHeader documentHeader = null;
 459  
         try {
 460  
             // create a new document header object
 461  0
             Class documentHeaderClass = getDocumentHeaderService().getDocumentHeaderBaseClass();
 462  0
             documentHeader = (DocumentHeader) documentHeaderClass.newInstance();
 463  0
             documentHeader.setWorkflowDocument(workflowDocument);
 464  0
             documentHeader.setDocumentNumber(workflowDocument.getRouteHeaderId().toString());
 465  
             // status and notes are initialized correctly in the constructor
 466  
         }
 467  0
         catch (IllegalAccessException e) {
 468  0
             throw new RuntimeException("Error instantiating DocumentHeader", e);
 469  
         }
 470  0
         catch (InstantiationException e) {
 471  0
             throw new RuntimeException("Error instantiating DocumentHeader", e);
 472  0
         }
 473  
 
 474  
         // build Document of specified type
 475  0
         Document document = null;
 476  
         try {
 477  
             // all maintenance documents have same class
 478  0
             if (MaintenanceDocumentBase.class.isAssignableFrom(documentClass)) {
 479  0
                 Class[] defaultConstructor = new Class[]{String.class};
 480  0
                 Constructor cons = documentClass.getConstructor(defaultConstructor);
 481  0
                 if (ObjectUtils.isNull(cons)) {
 482  0
                     throw new ConfigurationException("Could not find constructor with document type name parameter needed for Maintenance Document Base class");
 483  
                 }
 484  0
                 document = (Document) cons.newInstance(documentTypeName);
 485  0
             } else {
 486  
                 // non-maintenance document
 487  0
                 document = (Document) documentClass.newInstance();
 488  
             }
 489  0
         } catch (IllegalAccessException e) {
 490  0
             throw new RuntimeException("Error instantiating Document", e);
 491  0
         } catch (InstantiationException e) {
 492  0
             throw new RuntimeException("Error instantiating Document", e);
 493  0
         } catch (SecurityException e) {
 494  0
             throw new RuntimeException("Error instantiating Maintenance Document", e);
 495  0
         } catch (NoSuchMethodException e) {
 496  0
             throw new RuntimeException("Error instantiating Maintenance Document: No constructor with String parameter found", e);
 497  0
         } catch (IllegalArgumentException e) {
 498  0
             throw new RuntimeException("Error instantiating Maintenance Document", e);
 499  0
         } catch (InvocationTargetException e) {
 500  0
             throw new RuntimeException("Error instantiating Maintenance Document", e);
 501  0
         }
 502  
 
 503  0
         document.setDocumentHeader(documentHeader);
 504  0
         document.setDocumentNumber(documentHeader.getDocumentNumber());
 505  
 
 506  0
         t0.log();
 507  0
         return document;
 508  
     }
 509  
 
 510  
     /**
 511  
      * This is temporary until workflow 2.0 and reads from a table to get documents whose status has changed to A (approved - no
 512  
      * outstanding approval actions requested)
 513  
      *
 514  
      * @param documentHeaderId
 515  
      * @throws WorkflowException
 516  
      * @return Document
 517  
      */
 518  
     public Document getByDocumentHeaderId(String documentHeaderId) throws WorkflowException {
 519  0
         if (documentHeaderId == null) {
 520  0
             throw new IllegalArgumentException("invalid (null) documentHeaderId");
 521  
         }
 522  0
             boolean internalUserSession = false;
 523  
             try {
 524  
                     // KFSMI-2543 - allowed method to run without a user session so it can be used
 525  
                     // by workflow processes
 526  0
                 if (GlobalVariables.getUserSession() == null) {
 527  0
                         internalUserSession = true;
 528  0
                         GlobalVariables.setUserSession(new UserSession(KNSConstants.SYSTEM_USER));
 529  0
                         GlobalVariables.clear();
 530  
                 }
 531  
 
 532  0
                 KualiWorkflowDocument workflowDocument = null;
 533  
 
 534  0
                 if ( LOG.isDebugEnabled() ) {
 535  0
                         LOG.debug("Retrieving doc id: " + documentHeaderId + " from workflow service.");
 536  
                 }
 537  0
                 workflowDocument = getWorkflowDocumentService().createWorkflowDocument(Long.valueOf(documentHeaderId), GlobalVariables.getUserSession().getPerson());
 538  0
                 GlobalVariables.getUserSession().setWorkflowDocument(workflowDocument);
 539  
 
 540  0
                 Class documentClass = getDocumentClassByTypeName(workflowDocument.getDocumentType());
 541  
 
 542  
                 // retrieve the Document
 543  0
                 Document document = getDocumentDao().findByDocumentHeaderId(documentClass, documentHeaderId);
 544  0
                 return postProcessDocument(documentHeaderId, workflowDocument, document);
 545  
             } finally {
 546  
                     // if a user session was established for this call, clear it out
 547  0
                     if ( internalUserSession ) {
 548  0
                             GlobalVariables.clear();
 549  0
                             GlobalVariables.setUserSession(null);
 550  
                     }
 551  
             }
 552  
     }
 553  
 
 554  
         /**
 555  
          * @see org.kuali.rice.kns.service.DocumentService#getByDocumentHeaderIdSessionless(java.lang.String)
 556  
          */
 557  
         public Document getByDocumentHeaderIdSessionless(String documentHeaderId)
 558  
                         throws WorkflowException {
 559  0
         if (documentHeaderId == null) {
 560  0
             throw new IllegalArgumentException("invalid (null) documentHeaderId");
 561  
         }
 562  
 
 563  0
         KualiWorkflowDocument workflowDocument = null;
 564  
 
 565  0
         if ( LOG.isDebugEnabled() ) {
 566  0
             LOG.debug("Retrieving doc id: " + documentHeaderId + " from workflow service.");
 567  
         }
 568  
 
 569  0
         Person person = getPersonService().getPersonByPrincipalName(KNSConstants.SYSTEM_USER);
 570  0
         workflowDocument = workflowDocumentService.createWorkflowDocument(Long.valueOf(documentHeaderId), person);
 571  
 
 572  0
         Class documentClass = getDocumentClassByTypeName(workflowDocument.getDocumentType());
 573  
 
 574  
         // retrieve the Document
 575  0
         Document document = getDocumentDao().findByDocumentHeaderId(documentClass, documentHeaderId);
 576  0
         return postProcessDocument(documentHeaderId, workflowDocument, document);
 577  
         }
 578  
 
 579  
     private Class getDocumentClassByTypeName(String documentTypeName) {
 580  0
         if (StringUtils.isBlank(documentTypeName)) {
 581  0
             throw new IllegalArgumentException("invalid (blank) documentTypeName");
 582  
         }
 583  
 
 584  0
         Class clazz = getDataDictionaryService().getDocumentClassByTypeName(documentTypeName);
 585  0
         if (clazz == null) {
 586  0
             throw new UnknownDocumentTypeException("unable to get class for unknown documentTypeName '" + documentTypeName + "'");
 587  
         }
 588  0
         return clazz;
 589  
     }
 590  
 
 591  
     /**
 592  
      * Performs required post-processing for every document from the documentDao
 593  
      *
 594  
      * @param documentHeaderId
 595  
      * @param workflowDocument
 596  
      * @param document
 597  
      */
 598  
     private Document postProcessDocument(String documentHeaderId, KualiWorkflowDocument workflowDocument, Document document) {
 599  0
         if (document != null) {
 600  0
             document.getDocumentHeader().setWorkflowDocument(workflowDocument);
 601  0
             document.processAfterRetrieve();
 602  
         }
 603  0
         return document;
 604  
     }
 605  
 
 606  
 
 607  
     /**
 608  
      * The default implementation - this retrieves all documents by a list of documentHeader for a given class.
 609  
      *
 610  
      * @see org.kuali.rice.kns.service.DocumentService#getDocumentsByListOfDocumentHeaderIds(java.lang.Class, java.util.List)
 611  
      */
 612  
     public List getDocumentsByListOfDocumentHeaderIds(Class clazz, List documentHeaderIds) throws WorkflowException {
 613  
         // make sure that the supplied class is of the document type
 614  0
         if (!Document.class.isAssignableFrom(clazz)) {
 615  0
             throw new IllegalArgumentException("invalid (non-document) class of " + clazz.getName());
 616  
         }
 617  
 
 618  
         // validate documentHeaderIdList and contents
 619  0
         if (documentHeaderIds == null) {
 620  0
             throw new IllegalArgumentException("invalid (null) documentHeaderId list");
 621  
         }
 622  0
         int index = 0;
 623  0
         for (Iterator i = documentHeaderIds.iterator(); i.hasNext(); index++) {
 624  0
             String documentHeaderId = (String) i.next();
 625  0
             if (StringUtils.isBlank(documentHeaderId)) {
 626  0
                 throw new IllegalArgumentException("invalid (blank) documentHeaderId at list index " + index);
 627  
             }
 628  
         }
 629  
 
 630  0
             boolean internalUserSession = false;
 631  
             try {
 632  
                     // KFSMI-2543 - allowed method to run without a user session so it can be used
 633  
                     // by workflow processes
 634  0
                 if (GlobalVariables.getUserSession() == null) {
 635  0
                         internalUserSession = true;
 636  0
                         GlobalVariables.setUserSession(new UserSession(KNSConstants.SYSTEM_USER));
 637  0
                         GlobalVariables.clear();
 638  
                 }
 639  
 
 640  
                 // retrieve all documents that match the document header ids
 641  0
                 List rawDocuments = getDocumentDao().findByDocumentHeaderIds(clazz, documentHeaderIds);
 642  
 
 643  
                 // post-process them
 644  0
                 List documents = new ArrayList();
 645  0
                 for (Iterator i = rawDocuments.iterator(); i.hasNext();) {
 646  0
                     Document document = (Document) i.next();
 647  
 
 648  0
                     KualiWorkflowDocument workflowDocument = getWorkflowDocumentService().createWorkflowDocument(Long.valueOf(document.getDocumentNumber()), GlobalVariables.getUserSession().getPerson());
 649  
 
 650  0
                     document = postProcessDocument(document.getDocumentNumber(), workflowDocument, document);
 651  0
                     documents.add(document);
 652  0
                 }
 653  0
                 return documents;
 654  
             } finally {
 655  
                     // if a user session was established for this call, clear it our
 656  0
                     if ( internalUserSession ) {
 657  0
                             GlobalVariables.clear();
 658  0
                             GlobalVariables.setUserSession(null);
 659  
                     }
 660  
             }
 661  
     }
 662  
 
 663  
     /* Helper Methods */
 664  
 
 665  
     /**
 666  
      * Validates and persists a document.
 667  
      *
 668  
      * @see org.kuali.rice.kns.service.DocumentService#validateAndPersistDocument(org.kuali.rice.kns.document.Document, java.lang.String)
 669  
      */
 670  
     public void validateAndPersistDocument(Document document, KualiDocumentEvent event) throws WorkflowException, ValidationException {
 671  0
         if (document == null) {
 672  0
             LOG.error("document passed to validateAndPersist was null");
 673  0
             throw new IllegalArgumentException("invalid (null) document");
 674  
         }
 675  0
         if ( LOG.isDebugEnabled() ) {
 676  0
                 LOG.debug("validating and preparing to persist document " + document.getDocumentNumber());
 677  
         }
 678  
 
 679  0
         document.validateBusinessRules(event);
 680  0
         document.prepareForSave(event);
 681  
 
 682  
         // save the document
 683  
         try {
 684  0
                 if ( LOG.isInfoEnabled() ) {
 685  0
                         LOG.info("storing document " + document.getDocumentNumber());
 686  
                 }
 687  0
             getDocumentDao().save(document);
 688  
         }
 689  0
         catch (OptimisticLockingFailureException e) {
 690  0
             LOG.error("exception encountered on store of document " + e.getMessage());
 691  0
             throw e;
 692  0
         }
 693  
 
 694  0
         document.postProcessSave(event);
 695  
 
 696  
 
 697  0
     }
 698  
 
 699  
 
 700  
     /**
 701  
      * Sets the title and app document id in the flex document
 702  
      *
 703  
      * @param document
 704  
      * @throws WorkflowException
 705  
      */
 706  
     public void prepareWorkflowDocument(Document document) throws WorkflowException {
 707  
         // populate document content so searchable attributes will be indexed properly
 708  0
         document.populateDocumentForRouting();
 709  
 
 710  
         // make sure we push the document title into the workflowDocument
 711  0
         populateDocumentTitle(document);
 712  
 
 713  
         // make sure we push the application document id into the workflowDocument
 714  0
         populateApplicationDocumentId(document);
 715  0
     }
 716  
 
 717  
     /**
 718  
      * This method will grab the generated document title from the document and add it to the workflowDocument so that it gets pushed into
 719  
      * workflow when routed.
 720  
      *
 721  
      * @param document
 722  
      * @throws WorkflowException
 723  
      */
 724  
     private void populateDocumentTitle(Document document) throws WorkflowException {
 725  0
         String documentTitle = document.getDocumentTitle();
 726  0
         if (StringUtils.isNotBlank(documentTitle)) {
 727  0
             document.getDocumentHeader().getWorkflowDocument().setTitle(documentTitle);
 728  
         }
 729  0
     }
 730  
 
 731  
     /**
 732  
      * This method will grab the organization document number from the document and add it to the workflowDocument so that it gets pushed
 733  
      * into workflow when routed.
 734  
      *
 735  
      * @param document
 736  
      */
 737  
     private void populateApplicationDocumentId(Document document) {
 738  0
         String organizationDocumentNumber = document.getDocumentHeader().getOrganizationDocumentNumber();
 739  0
         if (StringUtils.isNotBlank(organizationDocumentNumber)) {
 740  0
             document.getDocumentHeader().getWorkflowDocument().setAppDocId(organizationDocumentNumber);
 741  
         }
 742  0
     }
 743  
 
 744  
     /**
 745  
      * This is to allow for updates of document statuses and other related requirements for updates outside of the initial save and
 746  
      * route
 747  
      */
 748  
     public void updateDocument(Document document) {
 749  0
         checkForNulls(document);
 750  0
         getDocumentDao().save(document);
 751  0
     }
 752  
 
 753  
     /**
 754  
      *
 755  
      * @see org.kuali.rice.kns.service.DocumentService#createNoteFromDocument(org.kuali.rice.kns.document.Document, java.lang.String)
 756  
      */
 757  
     public Note createNoteFromDocument(Document document, String text) throws Exception {
 758  0
         Note note = new Note();
 759  
 
 760  0
         note.setNotePostedTimestamp(getDateTimeService().getCurrentTimestamp());
 761  0
         note.setVersionNumber(Long.valueOf(1));
 762  0
         note.setNoteText(text);
 763  0
         if(document.isBoNotesSupport()) {
 764  0
             note.setNoteTypeCode(KNSConstants.NoteTypeEnum.BUSINESS_OBJECT_NOTE_TYPE.getCode());
 765  
         } else {
 766  0
             note.setNoteTypeCode(KNSConstants.NoteTypeEnum.DOCUMENT_HEADER_NOTE_TYPE.getCode());
 767  
         }
 768  
 
 769  0
         PersistableBusinessObject bo = null;
 770  0
         String propertyName = getNoteService().extractNoteProperty(note);
 771  0
         bo = (PersistableBusinessObject)ObjectUtils.getPropertyValue(document, propertyName);
 772  0
         return (bo==null)?null:getNoteService().createNote(note,bo);
 773  
     }
 774  
 
 775  
 
 776  
     /**
 777  
      * @see org.kuali.rice.kns.service.DocumentService#addNoteToDocument(org.kuali.rice.kns.document.Document, org.kuali.rice.kns.bo.Note)
 778  
      */
 779  
     public boolean addNoteToDocument(Document document, Note note) {
 780  0
         PersistableBusinessObject parent = getNoteParent(document,note);
 781  0
         return parent.addNote(note);
 782  
     }
 783  
 
 784  
     public PersistableBusinessObject getNoteParent(Document document, Note newNote) {
 785  
         //get the property name to set (this assumes this is a document type note)
 786  0
         String propertyName = getNoteService().extractNoteProperty(newNote);
 787  
         //get BO to set
 788  0
         PersistableBusinessObject noteParent = (PersistableBusinessObject)ObjectUtils.getPropertyValue(document, propertyName);
 789  0
         return noteParent;
 790  
     }
 791  
 
 792  
     /**
 793  
          * This overridden method ...
 794  
          *
 795  
          * @see org.kuali.rice.kns.service.DocumentService#sendAdHocRequests(org.kuali.rice.kns.document.Document, java.util.List)
 796  
          */
 797  
         public void sendAdHocRequests(Document document, String annotation, List<AdHocRouteRecipient> adHocRecipients) throws WorkflowException{
 798  0
                 prepareWorkflowDocument(document);
 799  0
                 getWorkflowDocumentService().sendWorkflowNotification(document.getDocumentHeader().getWorkflowDocument(),
 800  
                         annotation, adHocRecipients);
 801  0
                 GlobalVariables.getUserSession().setWorkflowDocument(document.getDocumentHeader().getWorkflowDocument());
 802  
                 //getBusinessObjectService().delete(document.getAdHocRoutePersons());
 803  
                 //getBusinessObjectService().delete(document.getAdHocRouteWorkgroups());
 804  0
                 removeAdHocPersonsAndWorkgroups(document);
 805  0
         }
 806  
 
 807  
         /**
 808  
      * @param documentTypeName
 809  
      * @return DocumentAuthorizer instance for the given documentType name
 810  
      */
 811  
     private DocumentAuthorizer getDocumentAuthorizer(String documentTypeName) {
 812  0
         return getDocumentHelperService().getDocumentAuthorizer(documentTypeName);
 813  
     }
 814  
 
 815  
     /**
 816  
      * spring injected date time service
 817  
      *
 818  
      * @param dateTimeService
 819  
      */
 820  
     public synchronized void setDateTimeService(DateTimeService dateTimeService) {
 821  0
         this.dateTimeService = dateTimeService;
 822  0
     }
 823  
 
 824  
     /**
 825  
      * Gets the DateTimeService, lazily initializing if necessary
 826  
      * @return the DateTimeService
 827  
      */
 828  
     private synchronized DateTimeService getDateTimeService() {
 829  0
         if (this.dateTimeService == null) {
 830  0
             this.dateTimeService = KNSServiceLocator.getDateTimeService();
 831  
         }
 832  0
         return this.dateTimeService;
 833  
     }
 834  
 
 835  
     /**
 836  
      * @param kualiRuleService The kualiRuleService to set.
 837  
      * @deprecated nothing uses this field
 838  
      */
 839  
     public void setKualiRuleService(KualiRuleService kualiRuleService) {
 840  
         // nothing uses this field...
 841  0
     }
 842  
 
 843  
     /**
 844  
      * @param dictionaryValidationService The dictionaryValidationService to set.
 845  
      * @deprecated nothing uses this field
 846  
      */
 847  
     public void setDictionaryValidationService(DictionaryValidationService dictionaryValidationService) {
 848  
         // nothing uses this field...
 849  0
     }
 850  
 
 851  
     /**
 852  
      * Sets the maintenanceDocumentService attribute value.
 853  
      *
 854  
      * @param maintenanceDocumentService The maintenanceDocumentService to set.
 855  
      * @deprecated nothing uses this field
 856  
      */
 857  
     public final void setMaintenanceDocumentService(MaintenanceDocumentService maintenanceDocumentService) {
 858  
         // nothing uses this field...
 859  0
     }
 860  
 
 861  
     /**
 862  
      * Sets the noteService attribute value.
 863  
      * @param noteService The noteService to set.
 864  
      */
 865  
     public synchronized void setNoteService(NoteService noteService) {
 866  0
         this.noteService = noteService;
 867  0
     }
 868  
 
 869  
     /**
 870  
      * Gets the NoteService, lazily initializing if necessary
 871  
      * @return the NoteService
 872  
      */
 873  
     protected synchronized NoteService getNoteService() {
 874  0
         if (this.noteService == null) {
 875  0
             this.noteService = KNSServiceLocator.getNoteService();
 876  
         }
 877  0
         return this.noteService;
 878  
     }
 879  
 
 880  
     /**
 881  
      * Sets the businessObjectService attribute value.
 882  
      *
 883  
      * @param businessObjectService The businessObjectService to set.
 884  
      */
 885  
     public synchronized void setBusinessObjectService(BusinessObjectService businessObjectService) {
 886  0
         this.businessObjectService = businessObjectService;
 887  0
     }
 888  
 
 889  
     /**
 890  
      * Gets the {@link BusinessObjectService}, lazily initializing if necessary
 891  
      * @return the {@link BusinessObjectService}
 892  
      */
 893  
     protected synchronized BusinessObjectService getBusinessObjectService() {
 894  0
         if (this.businessObjectService == null) {
 895  0
             this.businessObjectService = KNSServiceLocator.getBusinessObjectService();
 896  
         }
 897  0
         return this.businessObjectService;
 898  
     }
 899  
 
 900  
     /**
 901  
      * Sets the workflowDocumentService attribute value.
 902  
      *
 903  
      * @param workflowDocumentService The workflowDocumentService to set.
 904  
      */
 905  
     public synchronized void setWorkflowDocumentService(WorkflowDocumentService workflowDocumentService) {
 906  0
         this.workflowDocumentService = workflowDocumentService;
 907  0
     }
 908  
 
 909  
     /**
 910  
      * Gets the {@link WorkflowDocumentService}, lazily initializing if necessary
 911  
      * @return the {@link WorkflowDocumentService}
 912  
      */
 913  
     protected synchronized WorkflowDocumentService getWorkflowDocumentService() {
 914  0
         if (this.workflowDocumentService == null) {
 915  0
             this.workflowDocumentService = KNSServiceLocator.getWorkflowDocumentService();
 916  
         }
 917  0
         return this.workflowDocumentService;
 918  
     }
 919  
 
 920  
     /**
 921  
      * Sets the documentDao attribute value.
 922  
      *
 923  
      * @param documentDao The documentDao to set.
 924  
      */
 925  
     public synchronized void setDocumentDao(DocumentDao documentDao) {
 926  0
         this.documentDao = documentDao;
 927  0
     }
 928  
 
 929  
     /**
 930  
      * Gets the {@link DocumentDao}, lazily initializing if necessary
 931  
      * @return the {@link DocumentDao}
 932  
      */
 933  
     protected synchronized DocumentDao getDocumentDao() {
 934  0
         if (this.documentDao == null) {
 935  0
             this.documentDao = KNSServiceLocator.getDocumentDao();
 936  
         }
 937  0
         return documentDao;
 938  
     }
 939  
 
 940  
     /**
 941  
      * Sets the dataDictionaryService attribute value.
 942  
      *
 943  
      * @param dataDictionaryService
 944  
      */
 945  
     public synchronized void setDataDictionaryService(DataDictionaryService dataDictionaryService) {
 946  0
         this.dataDictionaryService = dataDictionaryService;
 947  0
     }
 948  
 
 949  
     /**
 950  
      * Gets the {@link DataDictionaryService}, lazily initializing if necessary
 951  
      * @return the {@link DataDictionaryService}
 952  
      */
 953  
     protected synchronized DataDictionaryService getDataDictionaryService() {
 954  0
         if (this.dataDictionaryService == null) {
 955  0
             this.dataDictionaryService = KNSServiceLocator.getDataDictionaryService();
 956  
         }
 957  0
         return this.dataDictionaryService;
 958  
     }
 959  
 
 960  
     /**
 961  
      * @param documentHeaderService the documentHeaderService to set
 962  
      */
 963  
     public synchronized void setDocumentHeaderService(DocumentHeaderService documentHeaderService) {
 964  0
         this.documentHeaderService = documentHeaderService;
 965  0
     }
 966  
 
 967  
     /**
 968  
      * Gets the {@link DocumentHeaderService}, lazily initializing if necessary
 969  
      * @return the {@link DocumentHeaderService}
 970  
      */
 971  
     protected synchronized DocumentHeaderService getDocumentHeaderService() {
 972  0
         if (this.documentHeaderService == null) {
 973  0
             this.documentHeaderService = KNSServiceLocator.getDocumentHeaderService();
 974  
         }
 975  0
         return this.documentHeaderService;
 976  
     }
 977  
 
 978  
     /**
 979  
          * @param personService the personService to set
 980  
          */
 981  
         public PersonService getPersonService() {
 982  0
                 if (personService == null) {
 983  0
                         personService = KIMServiceLocator.getPersonService();
 984  
                 }
 985  0
                 return personService;
 986  
         }
 987  
 
 988  
     /**
 989  
      * @return the documentHelperService
 990  
      */
 991  
     public DocumentHelperService getDocumentHelperService() {
 992  0
         if (documentHelperService == null) {
 993  0
             this.documentHelperService = KNSServiceLocator.getDocumentHelperService();
 994  
         }
 995  0
         return this.documentHelperService;
 996  
     }
 997  
 
 998  
     /**
 999  
      * @param documentHelperService the documentHelperService to set
 1000  
      */
 1001  
     public void setDocumentHelperService(DocumentHelperService documentHelperService) {
 1002  0
         this.documentHelperService = documentHelperService;
 1003  0
     }
 1004  
     
 1005  
     private void removeAdHocPersonsAndWorkgroups(Document document){
 1006  0
             List<AdHocRoutePerson> adHocRoutePersons = new ArrayList<AdHocRoutePerson>();
 1007  0
             List<AdHocRouteWorkgroup> adHocRouteWorkgroups = new ArrayList<AdHocRouteWorkgroup>();
 1008  0
             getBusinessObjectService().delete(document.getAdHocRoutePersons());
 1009  0
             getBusinessObjectService().delete(document.getAdHocRouteWorkgroups());
 1010  0
             document.setAdHocRoutePersons(adHocRoutePersons);
 1011  0
             document.setAdHocRouteWorkgroups(adHocRouteWorkgroups);
 1012  0
     }
 1013  
 }