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