Coverage Report - org.kuali.rice.kns.web.struts.action.KualiDocumentActionBase
 
Classes in this File Line Coverage Branch Coverage Complexity
KualiDocumentActionBase
0%
0/640
0%
0/330
4
 
 1  
 /*
 2  
  * Copyright 2006-2011 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  
 
 17  
 package org.kuali.rice.kns.web.struts.action;
 18  
 
 19  
 import org.apache.commons.lang.ArrayUtils;
 20  
 import org.apache.commons.lang.StringUtils;
 21  
 import org.apache.ojb.broker.OptimisticLockException;
 22  
 import org.apache.struts.action.ActionForm;
 23  
 import org.apache.struts.action.ActionForward;
 24  
 import org.apache.struts.action.ActionMapping;
 25  
 import org.apache.struts.upload.FormFile;
 26  
 import org.kuali.rice.core.api.config.property.ConfigurationService;
 27  
 import org.kuali.rice.core.framework.parameter.ParameterConstants;
 28  
 import org.kuali.rice.core.framework.parameter.ParameterService;
 29  
 import org.kuali.rice.core.framework.services.CoreFrameworkServiceLocator;
 30  
 import org.kuali.rice.core.util.ConcreteKeyValue;
 31  
 import org.kuali.rice.core.util.KeyValue;
 32  
 import org.kuali.rice.core.util.RiceConstants;
 33  
 import org.kuali.rice.core.util.RiceKeyConstants;
 34  
 import org.kuali.rice.kew.api.WorkflowDocument;
 35  
 import org.kuali.rice.kew.exception.WorkflowException;
 36  
 import org.kuali.rice.kew.util.KEWConstants;
 37  
 import org.kuali.rice.kim.api.group.Group;
 38  
 import org.kuali.rice.kim.api.group.GroupService;
 39  
 import org.kuali.rice.kim.api.services.KimApiServiceLocator;
 40  
 import org.kuali.rice.kim.bo.Person;
 41  
 import org.kuali.rice.kim.util.KimConstants;
 42  
 import org.kuali.rice.kns.datadictionary.DocumentEntry;
 43  
 import org.kuali.rice.kns.document.MaintenanceDocument;
 44  
 import org.kuali.rice.kns.rule.PromptBeforeValidation;
 45  
 import org.kuali.rice.kns.rule.event.PromptBeforeValidationEvent;
 46  
 import org.kuali.rice.kns.service.BusinessObjectAuthorizationService;
 47  
 import org.kuali.rice.kns.service.BusinessObjectMetaDataService;
 48  
 import org.kuali.rice.kns.service.DataDictionaryService;
 49  
 import org.kuali.rice.kns.service.KNSServiceLocator;
 50  
 import org.kuali.rice.kns.util.KNSGlobalVariables;
 51  
 import org.kuali.rice.kns.util.WebUtils;
 52  
 import org.kuali.rice.kns.web.struts.form.BlankFormFile;
 53  
 import org.kuali.rice.kns.web.struts.form.KualiDocumentFormBase;
 54  
 import org.kuali.rice.kns.web.struts.form.KualiForm;
 55  
 import org.kuali.rice.kns.web.struts.form.KualiMaintenanceForm;
 56  
 import org.kuali.rice.krad.UserSession;
 57  
 import org.kuali.rice.krad.bo.AdHocRoutePerson;
 58  
 import org.kuali.rice.krad.bo.AdHocRouteRecipient;
 59  
 import org.kuali.rice.krad.bo.AdHocRouteWorkgroup;
 60  
 import org.kuali.rice.krad.bo.Attachment;
 61  
 import org.kuali.rice.krad.bo.DocumentHeader;
 62  
 import org.kuali.rice.krad.bo.Note;
 63  
 import org.kuali.rice.krad.bo.PersistableBusinessObject;
 64  
 import org.kuali.rice.krad.datadictionary.DataDictionary;
 65  
 import org.kuali.rice.krad.document.Document;
 66  
 import org.kuali.rice.krad.document.authorization.DocumentAuthorizer;
 67  
 import org.kuali.rice.krad.document.authorization.DocumentAuthorizerBase;
 68  
 import org.kuali.rice.krad.document.authorization.DocumentPresentationController;
 69  
 import org.kuali.rice.krad.document.authorization.PessimisticLock;
 70  
 import org.kuali.rice.krad.exception.AuthorizationException;
 71  
 import org.kuali.rice.krad.exception.DocumentAuthorizationException;
 72  
 import org.kuali.rice.krad.exception.UnknownDocumentIdException;
 73  
 import org.kuali.rice.krad.question.ConfirmationQuestion;
 74  
 import org.kuali.rice.krad.rule.event.AddAdHocRoutePersonEvent;
 75  
 import org.kuali.rice.krad.rule.event.AddAdHocRouteWorkgroupEvent;
 76  
 import org.kuali.rice.krad.rule.event.AddNoteEvent;
 77  
 import org.kuali.rice.krad.rule.event.SendAdHocRequestsEvent;
 78  
 import org.kuali.rice.krad.service.AttachmentService;
 79  
 import org.kuali.rice.krad.service.BusinessObjectService;
 80  
 import org.kuali.rice.krad.service.DocumentHelperService;
 81  
 import org.kuali.rice.krad.service.DocumentService;
 82  
 import org.kuali.rice.krad.service.KRADServiceLocator;
 83  
 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
 84  
 import org.kuali.rice.krad.service.KualiRuleService;
 85  
 import org.kuali.rice.krad.service.NoteService;
 86  
 import org.kuali.rice.krad.service.PessimisticLockService;
 87  
 import org.kuali.rice.krad.util.GlobalVariables;
 88  
 import org.kuali.rice.krad.util.KRADConstants;
 89  
 import org.kuali.rice.krad.util.KRADPropertyConstants;
 90  
 import org.kuali.rice.krad.util.KRADUtils;
 91  
 import org.kuali.rice.krad.util.NoteType;
 92  
 import org.kuali.rice.krad.util.ObjectUtils;
 93  
 import org.kuali.rice.krad.util.SessionTicket;
 94  
 import org.kuali.rice.krad.util.UrlFactory;
 95  
 import org.springmodules.orm.ojb.OjbOperationException;
 96  
 
 97  
 import javax.persistence.EntityManagerFactory;
 98  
 import javax.servlet.http.HttpServletRequest;
 99  
 import javax.servlet.http.HttpServletResponse;
 100  
 import java.io.ByteArrayOutputStream;
 101  
 import java.io.IOException;
 102  
 import java.util.ArrayList;
 103  
 import java.util.Enumeration;
 104  
 import java.util.HashMap;
 105  
 import java.util.Iterator;
 106  
 import java.util.List;
 107  
 import java.util.Map;
 108  
 import java.util.Properties;
 109  
 import java.util.Set;
 110  
 
 111  
 
 112  
 /**
 113  
  * This class handles all of the document handling related actions in terms of passing them from here at a central point to the
 114  
  * distributed transactions that actually implement document handling.
 115  
  */
 116  0
 public class KualiDocumentActionBase extends KualiAction {
 117  0
     private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(KualiDocumentActionBase.class);
 118  
 
 119  
     // COMMAND constants which cause docHandler to load an existing document instead of creating a new one
 120  0
     protected static final String[] DOCUMENT_LOAD_COMMANDS = {
 121  
             KEWConstants.ACTIONLIST_COMMAND,
 122  
             KEWConstants.DOCSEARCH_COMMAND,
 123  
             KEWConstants.SUPERUSER_COMMAND,
 124  
             KEWConstants.HELPDESK_ACTIONLIST_COMMAND};
 125  
 
 126  
     private DataDictionaryService dataDictionaryService;
 127  
     private DocumentHelperService documentHelperService;
 128  
     private DocumentService documentService;
 129  
     private ConfigurationService kualiConfigurationService;
 130  
     private ParameterService parameterService;
 131  
     private PessimisticLockService pessimisticLockService;
 132  
     private KualiRuleService kualiRuleService;
 133  
     private GroupService groupService;
 134  
     private AttachmentService attachmentService;
 135  
     private NoteService noteService;
 136  
     private BusinessObjectAuthorizationService businessObjectAuthorizationService;
 137  
     private BusinessObjectService businessObjectService;
 138  
     private BusinessObjectMetaDataService businessObjectMetaDataService;
 139  
     private EntityManagerFactory entityManagerFactory;
 140  
 
 141  
     @Override
 142  
     protected void checkAuthorization(ActionForm form, String methodToCall) throws AuthorizationException {
 143  0
         if (!(form instanceof KualiDocumentFormBase)) {
 144  0
             super.checkAuthorization(form, methodToCall);
 145  
         }
 146  0
     }
 147  
 
 148  
     /**
 149  
      * Entry point to all actions.
 150  
      * <p/>
 151  
      * NOTE: No need to hook into execute for handling framwork setup anymore. Just implement the methodToCall for the framework
 152  
      * setup, Constants.METHOD_REQUEST_PARAMETER will contain the full parameter, which can be sub stringed for getting framework
 153  
      * parameters.
 154  
      *
 155  
      * @see org.apache.struts.action.Action#execute(org.apache.struts.action.ActionMapping, org.apache.struts.action.ActionForm,
 156  
      *      javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
 157  
      */
 158  
     @Override
 159  
     public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 160  0
         ActionForward returnForward = mapping.findForward(RiceConstants.MAPPING_BASIC);
 161  
 
 162  
         // if found methodToCall, pass control to that method
 163  
         try {
 164  0
             returnForward = super.execute(mapping, form, request, response);
 165  0
         } catch (OjbOperationException e) {
 166  
             // special handling for OptimisticLockExceptions
 167  0
             OjbOperationException ooe = e;
 168  
 
 169  0
             Throwable cause = ooe.getCause();
 170  0
             if (cause instanceof OptimisticLockException) {
 171  0
                 OptimisticLockException ole = (OptimisticLockException) cause;
 172  0
                 GlobalVariables.getMessageMap().putError(KRADConstants.DOCUMENT_ERRORS, RiceKeyConstants.ERROR_OPTIMISTIC_LOCK);
 173  0
                 logOjbOptimisticLockException(ole);
 174  0
             } else {
 175  
                 // if exceptions are from 'save'
 176  0
                 throw e;
 177  
             }
 178  
         } finally {
 179  0
             if (form instanceof KualiDocumentFormBase) {
 180  0
                 ((KualiDocumentFormBase) form).setMessageMapFromPreviousRequest(GlobalVariables.getMessageMap());
 181  
             }
 182  
         }
 183  
 
 184  0
         if (form instanceof KualiDocumentFormBase
 185  
                 && ((KualiDocumentFormBase) form).isHasWorkflowDocument()) {
 186  0
             KualiDocumentFormBase formBase = (KualiDocumentFormBase) form;
 187  0
             Document document = formBase.getDocument();
 188  
 
 189  
             //KULRICE-2210 fix location of document header population
 190  0
             WorkflowDocument workflowDocument = formBase.getDocument().getDocumentHeader().getWorkflowDocument();
 191  0
             formBase.populateHeaderFields(workflowDocument);
 192  0
             formBase.setDocId(document.getDocumentNumber());
 193  
             //End of KULRICE-2210 fix
 194  
 
 195  
             // check to see if document is a pessimistic lock document
 196  0
             if (isFormRepresentingLockObject(formBase)) {
 197  
                 // form represents a document using the BO class PessimisticLock so we need to skip the authorizations in the next logic check
 198  0
                 if (LOG.isDebugEnabled()) {
 199  0
                     LOG.debug("Form " + formBase + " represents a PessimisticLock BO object");
 200  
                 }
 201  
             } else {
 202  
                 // populates authorization-related fields in KualiDocumentFormBase instances, which are derived from
 203  
                 // information which is contained in the form but which may be unavailable until this point
 204  
                 //DocumentAuthorizer documentAuthorizer = KRADServiceLocatorInternal.getDocumentAuthorizationService().getDocumentAuthorizer(document);
 205  
                 //formBase.populateAuthorizationFields(documentAuthorizer);
 206  0
                 populateAuthorizationFields(formBase);
 207  0
                 populateAdHocActionRequestCodes(formBase);
 208  
 
 209  
                 //set the formBase into userSession if the document is a session document
 210  0
                 UserSession userSession = (UserSession) request.getSession().getAttribute(KRADConstants.USER_SESSION_KEY);
 211  
 
 212  0
                 if (WebUtils.isDocumentSession(document, formBase)) {
 213  0
                     String formKey = formBase.getFormKey();
 214  0
                     if (StringUtils.isBlank(formBase.getFormKey()) || userSession.retrieveObject(formBase.getFormKey()) == null) {
 215  
                         // generate doc form key here if it does not exist
 216  0
                         formKey = GlobalVariables.getUserSession().addObjectWithGeneratedKey(form);
 217  0
                         formBase.setFormKey(formKey);
 218  
                     }
 219  
                 }
 220  
 
 221  
 
 222  
                 // below used by KualiHttpSessionListener to handle lock expiration
 223  0
                 request.getSession().setAttribute(KRADConstants.DOCUMENT_HTTP_SESSION_KEY, document.getDocumentNumber());
 224  
                 // set returnToActionList flag, if needed
 225  0
                 if ("displayActionListView".equals(formBase.getCommand())) {
 226  0
                     formBase.setReturnToActionList(true);
 227  
                 }
 228  
 
 229  0
                 String attachmentEnabled =
 230  
                         getKualiConfigurationService().getPropertyString(
 231  
                                 KRADConstants.NOTE_ATTACHMENT_ENABLED);
 232  
                 // Override the document entry
 233  0
                 if (attachmentEnabled != null) {
 234  
                     // This is a hack for KULRICE-1602 since the document entry is modified by a
 235  
                     // global configuration that overrides the document templates without some sort
 236  
                     // of rules or control
 237  
                     //DataDictionary dataDictionary = getDataDictionaryService().getDataDictionary();
 238  0
                     DataDictionary dataDictionary = getDataDictionaryService().getDataDictionary();
 239  
 
 240  0
                     DocumentEntry entry = (DocumentEntry) dataDictionary.getDocumentEntry(document.getClass().getName());
 241  0
                     entry.setAllowsNoteAttachments(Boolean.parseBoolean(attachmentEnabled));
 242  
                 }
 243  
                 //the request attribute will be used in KualiRequestProcess#processActionPerform
 244  0
                 if (exitingDocument()) {
 245  0
                     request.setAttribute(KRADConstants.EXITING_DOCUMENT, Boolean.TRUE);
 246  
                 }
 247  
 
 248  
                 // pessimistic locking
 249  0
                 String methodCalledViaDispatch = (String) GlobalVariables.getUserSession().retrieveObject(DocumentAuthorizerBase.USER_SESSION_METHOD_TO_CALL_OBJECT_KEY);
 250  0
                 if ((StringUtils.isNotBlank(methodCalledViaDispatch)) && (exitingDocument())) {
 251  0
                     GlobalVariables.getUserSession().removeObject(DocumentAuthorizerBase.USER_SESSION_METHOD_TO_CALL_COMPLETE_OBJECT_KEY);
 252  0
                     attemptLockRelease(document, methodCalledViaDispatch);
 253  
                 }
 254  0
                 setupPessimisticLockMessages(document, request);
 255  0
                 if (!document.getPessimisticLocks().isEmpty()) {
 256  0
                     String warningMinutes = getParameterService().getParameterValueAsString(KRADConstants.KRAD_NAMESPACE, KRADConstants.DetailTypes.DOCUMENT_DETAIL_TYPE, KRADConstants.SESSION_TIMEOUT_WARNING_MESSAGE_TIME_PARM_NM);
 257  0
                     request.setAttribute(KRADConstants.SESSION_TIMEOUT_WARNING_MINUTES, warningMinutes);
 258  0
                     request.setAttribute(KRADConstants.SESSION_TIMEOUT_WARNING_MILLISECONDS, (request.getSession().getMaxInactiveInterval() - (Integer.valueOf(warningMinutes) * 60)) * 1000);
 259  
                 }
 260  
             }
 261  
         }
 262  
 
 263  0
         return returnForward;
 264  
     }
 265  
 
 266  
     protected boolean isFormRepresentingLockObject(KualiDocumentFormBase form) throws Exception {
 267  0
         if (form instanceof KualiMaintenanceForm) {
 268  0
             KualiMaintenanceForm maintForm = (KualiMaintenanceForm) form;
 269  0
             if (ObjectUtils.isNotNull(maintForm.getBusinessObjectClassName())) {
 270  0
                 return PessimisticLock.class.isAssignableFrom(Class.forName(((KualiMaintenanceForm) form).getBusinessObjectClassName()));
 271  
             }
 272  
         }
 273  0
         return false;
 274  
     }
 275  
 
 276  
     protected void attemptLockRelease(Document document, String methodToCall) {
 277  0
         if ((document != null) && (!document.getPessimisticLocks().isEmpty())) {
 278  0
             releaseLocks(document, methodToCall);
 279  
             // refresh pessimistic locks in case custom add/remove changes were made
 280  
             //document.refreshPessimisticLocks();
 281  
         }
 282  0
     }
 283  
 
 284  
     protected void releaseLocks(Document document, String methodToCall) {
 285  
         // first check if the method to call is listed as required lock clearing
 286  0
         if (document.getLockClearningMethodNames().contains(methodToCall)) {
 287  
             // find all locks for the current user and remove them
 288  0
             getPessimisticLockService().releaseAllLocksForUser(document.getPessimisticLocks(), GlobalVariables.getUserSession().getPerson());
 289  
         }
 290  0
     }
 291  
 
 292  
     protected void setupPessimisticLockMessages(Document document, HttpServletRequest request) {
 293  0
         List<String> lockMessages = new ArrayList<String>();
 294  0
         for (PessimisticLock lock : document.getPessimisticLocks()) {
 295  
             // if lock is owned by current user, do not display message for it
 296  0
             if (!lock.isOwnedByUser(GlobalVariables.getUserSession().getPerson())) {
 297  0
                 lockMessages.add(generatePessimisticLockMessage(lock));
 298  
             }
 299  
         }
 300  0
         request.setAttribute(KRADConstants.PESSIMISTIC_LOCK_MESSAGES, lockMessages);
 301  0
     }
 302  
 
 303  
     protected String generatePessimisticLockMessage(PessimisticLock lock) {
 304  0
         String descriptor = (lock.getLockDescriptor() != null) ? lock.getLockDescriptor() : "";
 305  
         // TODO: this should be pulled into a properties file
 306  0
         return "This document currently has a " + descriptor + " lock owned by " + lock.getOwnedByUser().getName() + " as of " + RiceConstants.getDefaultTimeFormat().format(lock.getGeneratedTimestamp()) + " on " + RiceConstants.getDefaultDateFormat().format(lock.getGeneratedTimestamp());
 307  
     }
 308  
 
 309  
 //    private void saveMessages(HttpServletRequest request) {
 310  
 //        if (!GlobalVariables.getMessageList().isEmpty()) {
 311  
 //            request.setAttribute(KRADConstants.GLOBAL_MESSAGES, GlobalVariables.getMessageList());
 312  
 //        }
 313  
 //    }
 314  
 
 315  
     /**
 316  
      * This method may be used to funnel all document handling through, we could do useful things like log and record various
 317  
      * openings and status Additionally it may be nice to have a single dispatcher that can know how to dispatch to a redirect url
 318  
      * for document specific handling but we may not need that as all we should need is the document to be able to load itself based
 319  
      * on document id and then which actionforward or redirect is pertinent for the document type.
 320  
      *
 321  
      * @param mapping
 322  
      * @param form
 323  
      * @param request
 324  
      * @param response
 325  
      * @return ActionForward
 326  
      * @throws Exception
 327  
      */
 328  
     public ActionForward docHandler(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 329  0
         KualiDocumentFormBase kualiDocumentFormBase = (KualiDocumentFormBase) form;
 330  0
         String command = kualiDocumentFormBase.getCommand();
 331  
 
 332  
         // in all of the following cases we want to load the document
 333  0
         if (ArrayUtils.contains(DOCUMENT_LOAD_COMMANDS, command) && kualiDocumentFormBase.getDocId() != null) {
 334  0
             loadDocument(kualiDocumentFormBase);
 335  0
         } else if (KEWConstants.INITIATE_COMMAND.equals(command)) {
 336  0
             createDocument(kualiDocumentFormBase);
 337  
         } else {
 338  0
             LOG.error("docHandler called with invalid parameters");
 339  0
             throw new IllegalStateException("docHandler called with invalid parameters");
 340  
         }
 341  
 
 342  
         // attach any extra JS from the data dictionary
 343  0
         if (LOG.isDebugEnabled()) {
 344  0
             LOG.debug("kualiDocumentFormBase.getAdditionalScriptFiles(): " + kualiDocumentFormBase.getAdditionalScriptFiles());
 345  
         }
 346  0
         if (kualiDocumentFormBase.getAdditionalScriptFiles().isEmpty()) {
 347  0
             DocumentEntry docEntry = (DocumentEntry) getDataDictionaryService().getDataDictionary().getDocumentEntry(kualiDocumentFormBase.getDocument().getDocumentHeader().getWorkflowDocument().getDocumentTypeName());
 348  0
             kualiDocumentFormBase.getAdditionalScriptFiles().addAll(docEntry.getWebScriptFiles());
 349  
         }
 350  0
         if (KEWConstants.SUPERUSER_COMMAND.equalsIgnoreCase(command)) {
 351  0
             kualiDocumentFormBase.setSuppressAllButtons(true);
 352  
         }
 353  0
         return mapping.findForward(RiceConstants.MAPPING_BASIC);
 354  
     }
 355  
 
 356  
     /**
 357  
      * This method loads the document by its provided document header id. This has been abstracted out so that it can be overridden
 358  
      * in children if the need arises.
 359  
      *
 360  
      * @param kualiDocumentFormBase
 361  
      * @throws WorkflowException
 362  
      */
 363  
     protected void loadDocument(KualiDocumentFormBase kualiDocumentFormBase) throws WorkflowException {
 364  0
         String docId = kualiDocumentFormBase.getDocId();
 365  0
         Document doc = null;
 366  0
         doc = getDocumentService().getByDocumentHeaderId(docId);
 367  0
         if (doc == null) {
 368  0
             throw new UnknownDocumentIdException("Document no longer exists.  It may have been cancelled before being saved.");
 369  
         }
 370  0
         WorkflowDocument workflowDocument = doc.getDocumentHeader().getWorkflowDocument();
 371  0
         if (!getDocumentHelperService().getDocumentAuthorizer(doc).canOpen(doc, GlobalVariables.getUserSession().getPerson())) {
 372  0
             throw buildAuthorizationException("open", doc);
 373  
         }
 374  
         // re-retrieve the document using the current user's session - remove the system user from the WorkflowDcument object
 375  0
         if (workflowDocument != doc.getDocumentHeader().getWorkflowDocument()) {
 376  0
             LOG.warn("Workflow document changed via canOpen check");
 377  0
             doc.getDocumentHeader().setWorkflowDocument(workflowDocument);
 378  
         }
 379  0
         kualiDocumentFormBase.setDocument(doc);
 380  0
         WorkflowDocument workflowDoc = doc.getDocumentHeader().getWorkflowDocument();
 381  0
         kualiDocumentFormBase.setDocTypeName(workflowDoc.getDocumentTypeName());
 382  
         // KualiDocumentFormBase.populate() needs this updated in the session
 383  0
         KRADServiceLocatorWeb.getSessionDocumentService().addDocumentToUserSession(GlobalVariables.getUserSession(), workflowDoc);
 384  0
     }
 385  
 
 386  
 
 387  
     /**
 388  
      * This method creates a new document of the type specified by the docTypeName property of the given form. This has been
 389  
      * abstracted out so that it can be overridden in children if the need arises.
 390  
      *
 391  
      * @param kualiDocumentFormBase
 392  
      * @throws WorkflowException
 393  
      */
 394  
     protected void createDocument(KualiDocumentFormBase kualiDocumentFormBase) throws WorkflowException {
 395  0
         Document doc = getDocumentService().getNewDocument(kualiDocumentFormBase.getDocTypeName());
 396  
 
 397  0
         kualiDocumentFormBase.setDocument(doc);
 398  0
         kualiDocumentFormBase.setDocTypeName(doc.getDocumentHeader().getWorkflowDocument().getDocumentTypeName());
 399  0
     }
 400  
 
 401  
     /**
 402  
      * This method will insert the new ad hoc person from the from into the list of ad hoc person recipients, put a new new record
 403  
      * in place and return like normal.
 404  
      *
 405  
      * @param mapping
 406  
      * @param form
 407  
      * @param request
 408  
      * @param response
 409  
      * @return ActionForward
 410  
      * @throws Exception
 411  
      */
 412  
     public ActionForward insertAdHocRoutePerson(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 413  0
         KualiDocumentFormBase kualiDocumentFormBase = (KualiDocumentFormBase) form;
 414  0
         Document document = kualiDocumentFormBase.getDocument();
 415  
 
 416  
 
 417  
         // check authorization for adding ad hoc route person
 418  0
         DocumentAuthorizer documentAuthorizer = getDocumentHelperService().getDocumentAuthorizer(document);
 419  0
         if (!documentAuthorizer.canSendAdHocRequests(document, kualiDocumentFormBase.getNewAdHocRoutePerson().getActionRequested(), GlobalVariables.getUserSession().getPerson())) {
 420  0
             throw buildAuthorizationException("ad-hoc route", document);
 421  
         }
 422  
 
 423  
         // check business rules
 424  0
         boolean rulePassed = getKualiRuleService().applyRules(new AddAdHocRoutePersonEvent(document, kualiDocumentFormBase.getNewAdHocRoutePerson()));
 425  
 
 426  
         // if the rule evaluation passed, let's add the ad hoc route person
 427  0
         if (rulePassed) {
 428  
             // uppercase userid for consistency
 429  
 //            kualiDocumentFormBase.getNewAdHocRoutePerson().setId(StringUtils.upperCase(kualiDocumentFormBase.getNewAdHocRoutePerson().getId()));
 430  0
             kualiDocumentFormBase.getNewAdHocRoutePerson().setId(kualiDocumentFormBase.getNewAdHocRoutePerson().getId());
 431  0
             kualiDocumentFormBase.getAdHocRoutePersons().add(kualiDocumentFormBase.getNewAdHocRoutePerson());
 432  0
             AdHocRoutePerson person = new AdHocRoutePerson();
 433  0
             kualiDocumentFormBase.setNewAdHocRoutePerson(person);
 434  
         }
 435  
 
 436  0
         return mapping.findForward(RiceConstants.MAPPING_BASIC);
 437  
     }
 438  
 
 439  
     /**
 440  
      * This method will delete one of the ad hoc persons from the list of ad hoc persons to route to based on the line number of the
 441  
      * delete button that was clicked. then it will return to the form.
 442  
      *
 443  
      * @param mapping
 444  
      * @param form
 445  
      * @param request
 446  
      * @param response
 447  
      * @return ActionForward
 448  
      * @throws Exception
 449  
      */
 450  
     public ActionForward deleteAdHocRoutePerson(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 451  0
         KualiDocumentFormBase kualiDocumentFormBase = (KualiDocumentFormBase) form;
 452  
 
 453  
 
 454  0
         kualiDocumentFormBase.getAdHocRoutePersons().remove(this.getLineToDelete(request));
 455  0
         return mapping.findForward(RiceConstants.MAPPING_BASIC);
 456  
     }
 457  
 
 458  
     /**
 459  
      * This method will insert the new ad hoc workgroup into the list of ad hoc workgroup recipients put a nuew record in place and
 460  
      * then return like normal.
 461  
      *
 462  
      * @param mapping
 463  
      * @param form
 464  
      * @param request
 465  
      * @param response
 466  
      * @return ActionForward
 467  
      * @throws Exception
 468  
      */
 469  
     public ActionForward insertAdHocRouteWorkgroup(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 470  0
         KualiDocumentFormBase kualiDocumentFormBase = (KualiDocumentFormBase) form;
 471  0
         Document document = kualiDocumentFormBase.getDocument();
 472  
 
 473  
         // check authorization for add ad hoc route workgroup
 474  0
         DocumentAuthorizer documentAuthorizer = getDocumentHelperService().getDocumentAuthorizer(document);
 475  0
         if (!documentAuthorizer.canSendAdHocRequests(document, kualiDocumentFormBase.getNewAdHocRouteWorkgroup().getActionRequested(), GlobalVariables.getUserSession().getPerson())) {
 476  0
             throw buildAuthorizationException("ad-hoc route", document);
 477  
         }
 478  
 
 479  
         // check business rules
 480  0
         boolean rulePassed = getKualiRuleService().applyRules(new AddAdHocRouteWorkgroupEvent(document, kualiDocumentFormBase.getNewAdHocRouteWorkgroup()));
 481  
 
 482  
         // if the rule evaluation passed, let's add the ad hoc route workgroup
 483  0
         if (rulePassed) {
 484  
             //fill id if not already filled
 485  0
             AdHocRouteWorkgroup newWorkgroup = kualiDocumentFormBase.getNewAdHocRouteWorkgroup();
 486  0
             if (newWorkgroup.getId() == null) {
 487  0
                 newWorkgroup.setId(KimApiServiceLocator.getGroupService().getGroupByName(newWorkgroup.getRecipientNamespaceCode(), newWorkgroup.getRecipientName()).getId());
 488  
             }
 489  0
             kualiDocumentFormBase.getAdHocRouteWorkgroups().add(newWorkgroup);
 490  0
             AdHocRouteWorkgroup workgroup = new AdHocRouteWorkgroup();
 491  0
             kualiDocumentFormBase.setNewAdHocRouteWorkgroup(workgroup);
 492  
         }
 493  
 
 494  0
         return mapping.findForward(RiceConstants.MAPPING_BASIC);
 495  
     }
 496  
 
 497  
     /**
 498  
      * This method will delete one of the ad hoc workgroups from the list of ad hoc workgroups to route to based on the line number
 499  
      * of the delete button that was clicked. then it will return
 500  
      *
 501  
      * @param mapping
 502  
      * @param form
 503  
      * @param request
 504  
      * @param response
 505  
      * @return ActionForward
 506  
      * @throws Exception
 507  
      */
 508  
     public ActionForward deleteAdHocRouteWorkgroup(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 509  0
         KualiDocumentFormBase kualiDocumentFormBase = (KualiDocumentFormBase) form;
 510  
 
 511  0
         kualiDocumentFormBase.getAdHocRouteWorkgroups().remove(this.getLineToDelete(request));
 512  0
         return mapping.findForward(RiceConstants.MAPPING_BASIC);
 513  
     }
 514  
 
 515  
     public ActionForward sendAdHocRequests(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 516  0
         KualiDocumentFormBase kualiDocumentFormBase = (KualiDocumentFormBase) form;
 517  0
         Document document = kualiDocumentFormBase.getDocument();
 518  
 
 519  0
         boolean rulePassed = getKualiRuleService().applyRules(new SendAdHocRequestsEvent(document));
 520  
 
 521  0
         if (rulePassed) {
 522  0
             getDocumentService().sendAdHocRequests(document, kualiDocumentFormBase.getAnnotation(), combineAdHocRecipients(kualiDocumentFormBase));
 523  0
             KNSGlobalVariables.getMessageList().add(RiceKeyConstants.MESSAGE_SEND_AD_HOC_REQUESTS_SUCCESSFUL);
 524  
         }
 525  
 
 526  0
         return mapping.findForward(RiceConstants.MAPPING_BASIC);
 527  
     }
 528  
 
 529  
     /**
 530  
      * This method will reload the document.
 531  
      *
 532  
      * @param mapping
 533  
      * @param form
 534  
      * @param request
 535  
      * @param response
 536  
      * @return ActionForward
 537  
      * @throws Exception
 538  
      */
 539  
     public ActionForward reload(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 540  0
         KualiDocumentFormBase kualiDocumentFormBase = (KualiDocumentFormBase) form;
 541  0
         Document document = kualiDocumentFormBase.getDocument();
 542  
 
 543  
         // prepare for the reload action - set doc id and command
 544  0
         kualiDocumentFormBase.setDocId(document.getDocumentNumber());
 545  0
         kualiDocumentFormBase.setCommand(DOCUMENT_LOAD_COMMANDS[1]);
 546  
 
 547  
         // forward off to the doc handler
 548  0
         ActionForward actionForward = docHandler(mapping, form, request, response);
 549  
 
 550  0
         KNSGlobalVariables.getMessageList().add(RiceKeyConstants.MESSAGE_RELOADED);
 551  
         // TODO: remove this when further testing passed
 552  
 //        if (form instanceof KualiDocumentFormBase) {
 553  
 //            UserSession userSession = (UserSession) request.getSession().getAttribute(RiceConstants.USER_SESSION_KEY);
 554  
 //            // force to recreate formkey in execute method
 555  
 //            if (document instanceof SessionDocumentService && userSession.retrieveObject(kualiDocumentFormBase.getFormKey()) != null) {
 556  
 //                userSession.removeObject(kualiDocumentFormBase.getFormKey());;
 557  
 //            }
 558  
 //        }
 559  
 
 560  0
         return actionForward;
 561  
     }
 562  
 
 563  
     /**
 564  
      * This method will save the document, which will then be available via the action list for the person who saved the document.
 565  
      *
 566  
      * @param mapping
 567  
      * @param form
 568  
      * @param request
 569  
      * @param response
 570  
      * @return ActionForward
 571  
      * @throws Exception
 572  
      */
 573  
     public ActionForward save(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 574  0
         KualiDocumentFormBase kualiDocumentFormBase = (KualiDocumentFormBase) form;
 575  0
         doProcessingAfterPost(kualiDocumentFormBase, request);
 576  
         //get any possible changes to to adHocWorkgroups
 577  0
         refreshAdHocRoutingWorkgroupLookups(request, kualiDocumentFormBase);
 578  0
         Document document = kualiDocumentFormBase.getDocument();
 579  
 
 580  0
         ActionForward forward = checkAndWarnAboutSensitiveData(mapping, form, request, response, KRADPropertyConstants.DOCUMENT_EXPLANATION, document.getDocumentHeader().getExplanation(), "save", "");
 581  0
         if (forward != null) {
 582  0
             return forward;
 583  
         }
 584  
 
 585  
         // save in workflow
 586  0
         getDocumentService().saveDocument(document);
 587  
 
 588  0
         KNSGlobalVariables.getMessageList().add(RiceKeyConstants.MESSAGE_SAVED);
 589  0
         kualiDocumentFormBase.setAnnotation("");
 590  
 
 591  
         // TODO: remove this when further testing passed
 592  
 //        if (form instanceof KualiDocumentFormBase) {
 593  
 //            UserSession userSession = (UserSession) request.getSession().getAttribute(RiceConstants.USER_SESSION_KEY);
 594  
 //            // force to recreate formkey in execute method
 595  
 //            if (document instanceof SessionDocumentService && userSession.retrieveObject(kualiDocumentFormBase.getFormKey()) != null) {
 596  
 //                userSession.removeObject(kualiDocumentFormBase.getFormKey());;
 597  
 //            }
 598  
 //        }
 599  
 
 600  0
         return mapping.findForward(RiceConstants.MAPPING_BASIC);
 601  
     }
 602  
 
 603  
     /**
 604  
      * Checks if the given value matches patterns that indicate sensitive data and if configured to give a warning for sensitive data will
 605  
      * prompt the user to continue
 606  
      *
 607  
      * @param mapping
 608  
      * @param form
 609  
      * @param request
 610  
      * @param response
 611  
      * @param fieldName  - name of field with value being checked
 612  
      * @param fieldValue - value to check for sensitive data
 613  
      * @param caller     - method that should be called back from question
 614  
      * @param context    - additional context that needs to be passed back with the question response
 615  
      * @return ActionForward which contains the question forward, or basic forward if user select no to prompt, otherwise will return null
 616  
      *         to indicate processing should continue
 617  
      * @throws Exception
 618  
      */
 619  
     protected ActionForward checkAndWarnAboutSensitiveData(ActionMapping mapping, ActionForm form,
 620  
                                                            HttpServletRequest request, HttpServletResponse response, String fieldName, String fieldValue, String caller, String context)
 621  
             throws Exception {
 622  0
         KualiDocumentFormBase kualiDocumentFormBase = (KualiDocumentFormBase) form;
 623  0
         Document document = kualiDocumentFormBase.getDocument();
 624  
 
 625  0
         boolean containsSensitiveData = KRADUtils.containsSensitiveDataPatternMatch(fieldValue);
 626  
 
 627  
         // check if warning is configured in which case we will prompt, or if not business rules will thrown an error
 628  0
         boolean warnForSensitiveData = CoreFrameworkServiceLocator.getParameterService().getParameterValueAsBoolean(
 629  
                 KRADConstants.KRAD_NAMESPACE, ParameterConstants.ALL_COMPONENT,
 630  
                 KRADConstants.SystemGroupParameterNames.SENSITIVE_DATA_PATTERNS_WARNING_IND);
 631  
 
 632  
         // determine if the question has been asked yet
 633  0
         Map<String, String> ticketContext = new HashMap<String, String>();
 634  0
         ticketContext.put(KRADPropertyConstants.DOCUMENT_NUMBER, document.getDocumentNumber());
 635  0
         ticketContext.put(KRADConstants.CALLING_METHOD, caller);
 636  0
         ticketContext.put(KRADPropertyConstants.NAME, fieldName);
 637  
 
 638  0
         boolean questionAsked = GlobalVariables.getUserSession().hasMatchingSessionTicket(
 639  
                 KRADConstants.SENSITIVE_DATA_QUESTION_SESSION_TICKET, ticketContext);
 640  
 
 641  
         // start in logic for confirming the sensitive data
 642  0
         if (containsSensitiveData && warnForSensitiveData && !questionAsked) {
 643  0
             Object question = request.getParameter(KRADConstants.QUESTION_INST_ATTRIBUTE_NAME);
 644  0
             if (question == null || !KRADConstants.DOCUMENT_SENSITIVE_DATA_QUESTION.equals(question)) {
 645  
 
 646  
                 // question hasn't been asked, prompt to continue
 647  0
                 return this.performQuestionWithoutInput(mapping, form, request, response,
 648  
                         KRADConstants.DOCUMENT_SENSITIVE_DATA_QUESTION, getKualiConfigurationService()
 649  
                         .getPropertyString(RiceKeyConstants.QUESTION_SENSITIVE_DATA_DOCUMENT),
 650  
                         KRADConstants.CONFIRMATION_QUESTION, caller, context);
 651  
             }
 652  
 
 653  0
             Object buttonClicked = request.getParameter(KRADConstants.QUESTION_CLICKED_BUTTON);
 654  0
             if (question != null && KRADConstants.DOCUMENT_SENSITIVE_DATA_QUESTION.equals(question)) {
 655  
                 // if no button clicked just reload the doc
 656  0
                 if (ConfirmationQuestion.NO.equals(buttonClicked)) {
 657  
 
 658  0
                     return mapping.findForward(RiceConstants.MAPPING_BASIC);
 659  
                 }
 660  
 
 661  
                 // answered yes, create session ticket so we not to ask question again if there are further question requests
 662  0
                 SessionTicket ticket = new SessionTicket(KRADConstants.SENSITIVE_DATA_QUESTION_SESSION_TICKET);
 663  0
                 ticket.setTicketContext(ticketContext);
 664  0
                 GlobalVariables.getUserSession().putSessionTicket(ticket);
 665  
             }
 666  
         }
 667  
 
 668  
         // return null to indicate processing should continue (no redirect)
 669  0
         return null;
 670  
     }
 671  
 
 672  
     /**
 673  
      * This method will verify that the form is representing a {@link PessimisticLock} object and delete it if possible
 674  
      *
 675  
      * @param mapping
 676  
      * @param form
 677  
      * @param request
 678  
      * @param response
 679  
      * @return ActionForward
 680  
      * @throws Exception
 681  
      */
 682  
     public ActionForward delete(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 683  0
         KualiDocumentFormBase kualiDocumentFormBase = (KualiDocumentFormBase) form;
 684  0
         if (isFormRepresentingLockObject(kualiDocumentFormBase)) {
 685  0
             String idValue = request.getParameter(KRADPropertyConstants.ID);
 686  0
             getPessimisticLockService().delete(idValue);
 687  0
             return returnToSender(request, mapping, kualiDocumentFormBase);
 688  
         }
 689  0
         throw buildAuthorizationException(KRADConstants.DELETE_METHOD, kualiDocumentFormBase.getDocument());
 690  
     }
 691  
 
 692  
     /**
 693  
      * route the document using the document service
 694  
      *
 695  
      * @param mapping
 696  
      * @param form
 697  
      * @param request
 698  
      * @param response
 699  
      * @return ActionForward
 700  
      * @throws Exception
 701  
      */
 702  
     public ActionForward performRouteReport(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 703  0
         KualiDocumentFormBase kualiDocumentFormBase = (KualiDocumentFormBase) form;
 704  
 
 705  0
         kualiDocumentFormBase.setDerivedValuesOnForm(request);
 706  0
         ActionForward preRulesForward = promptBeforeValidation(mapping, form, request, response);
 707  0
         if (preRulesForward != null) {
 708  0
             return preRulesForward;
 709  
         }
 710  
 
 711  0
         Document document = kualiDocumentFormBase.getDocument();
 712  
         // check authorization for reloading document
 713  
         //DocumentActionFlags flags = getDocumentActionFlags(document);
 714  0
         if (!kualiDocumentFormBase.getDocumentActions().containsKey(KRADConstants.KUALI_ACTION_PERFORM_ROUTE_REPORT)) {
 715  0
             throw buildAuthorizationException("perform route report", document);
 716  
         }
 717  
 
 718  0
         String backUrlBase = getReturnLocation(request, mapping);
 719  0
         String globalVariableFormKey = GlobalVariables.getUserSession().addObjectWithGeneratedKey(form);
 720  
         // setup back form variables
 721  0
         request.setAttribute("backUrlBase", backUrlBase);
 722  0
         List<KeyValue> backFormParameters = new ArrayList<KeyValue>();
 723  0
         backFormParameters.add(new ConcreteKeyValue(KRADConstants.DISPATCH_REQUEST_PARAMETER, KRADConstants.RETURN_METHOD_TO_CALL));
 724  0
         backFormParameters.add(new ConcreteKeyValue(KRADConstants.DOC_FORM_KEY, globalVariableFormKey));
 725  0
         request.setAttribute("backFormHiddenVariables", backFormParameters);
 726  
 
 727  
         // setup route report form variables
 728  0
         request.setAttribute("workflowRouteReportUrl", getKualiConfigurationService().getPropertyString(KRADConstants.WORKFLOW_URL_KEY) + "/" + KEWConstants.DOCUMENT_ROUTING_REPORT_PAGE);
 729  0
         List<KeyValue> generalRouteReportFormParameters = new ArrayList<KeyValue>();
 730  0
         generalRouteReportFormParameters.add(new ConcreteKeyValue(KEWConstants.INITIATOR_ID_ATTRIBUTE_NAME, document.getDocumentHeader().getWorkflowDocument().getDocument().getInitiatorPrincipalId()));
 731  0
         generalRouteReportFormParameters.add(new ConcreteKeyValue(KEWConstants.DOCUMENT_TYPE_NAME_ATTRIBUTE_NAME, document.getDocumentHeader().getWorkflowDocument().getDocumentTypeName()));
 732  
         // prepareForRouteReport() method should populate document header workflow document application content xml
 733  0
         String xml = document.getXmlForRouteReport();
 734  0
         if (LOG.isDebugEnabled()) {
 735  0
             LOG.debug("XML being used for Routing Report is: " + xml);
 736  
         }
 737  0
         generalRouteReportFormParameters.add(new ConcreteKeyValue(KEWConstants.DOCUMENT_CONTENT_ATTRIBUTE_NAME, xml));
 738  
 
 739  
         // set up the variables for the form if java script is working (includes a close button variable and no back url)
 740  0
         List<KeyValue> javaScriptFormParameters = new ArrayList<KeyValue>();
 741  0
         javaScriptFormParameters.addAll(generalRouteReportFormParameters);
 742  0
         javaScriptFormParameters.add(new ConcreteKeyValue(KEWConstants.DISPLAY_CLOSE_BUTTON_ATTRIBUTE_NAME, KEWConstants.DISPLAY_CLOSE_BUTTON_TRUE_VALUE));
 743  0
         request.setAttribute("javaScriptFormVariables", javaScriptFormParameters);
 744  
 
 745  
         // set up the variables for the form if java script is NOT working (includes a back url but no close button)
 746  0
         List<KeyValue> noJavaScriptFormParameters = new ArrayList<KeyValue>();
 747  0
         noJavaScriptFormParameters.addAll(generalRouteReportFormParameters);
 748  0
         Properties parameters = new Properties();
 749  0
         for (KeyValue pair : backFormParameters) {
 750  0
             parameters.put(pair.getKey(), pair.getValue());
 751  
         }
 752  0
         noJavaScriptFormParameters.add(new ConcreteKeyValue(KEWConstants.RETURN_URL_ATTRIBUTE_NAME, UrlFactory.parameterizeUrl(backUrlBase, parameters)));
 753  0
         request.setAttribute("noJavaScriptFormVariables", noJavaScriptFormParameters);
 754  
 
 755  0
         return mapping.findForward(KRADConstants.MAPPING_ROUTE_REPORT);
 756  
     }
 757  
 
 758  
     /**
 759  
      * route the document using the document service
 760  
      *
 761  
      * @param mapping
 762  
      * @param form
 763  
      * @param request
 764  
      * @param response
 765  
      * @return ActionForward
 766  
      * @throws Exception
 767  
      */
 768  
     public ActionForward route(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 769  0
         KualiDocumentFormBase kualiDocumentFormBase = (KualiDocumentFormBase) form;
 770  0
         doProcessingAfterPost(kualiDocumentFormBase, request);
 771  
 
 772  0
         kualiDocumentFormBase.setDerivedValuesOnForm(request);
 773  0
         ActionForward preRulesForward = promptBeforeValidation(mapping, form, request, response);
 774  0
         if (preRulesForward != null) {
 775  0
             return preRulesForward;
 776  
         }
 777  
 
 778  0
         Document document = kualiDocumentFormBase.getDocument();
 779  
 
 780  0
         ActionForward forward = checkAndWarnAboutSensitiveData(mapping, form, request, response, KRADPropertyConstants.DOCUMENT_EXPLANATION, document.getDocumentHeader().getExplanation(), "route", "");
 781  0
         if (forward != null) {
 782  0
             return forward;
 783  
         }
 784  
 
 785  0
         getDocumentService().routeDocument(document, kualiDocumentFormBase.getAnnotation(), combineAdHocRecipients(kualiDocumentFormBase));
 786  0
         KNSGlobalVariables.getMessageList().add(RiceKeyConstants.MESSAGE_ROUTE_SUCCESSFUL);
 787  0
         kualiDocumentFormBase.setAnnotation("");
 788  
 
 789  
 //        GlobalVariables.getUserSession().addObject(DocumentAuthorizerBase.USER_SESSION_METHOD_TO_CALL_COMPLETE_OBJECT_KEY,Boolean.TRUE);
 790  0
         return mapping.findForward(RiceConstants.MAPPING_BASIC);
 791  
     }
 792  
 
 793  
     /**
 794  
      * Calls the document service to blanket approve the document
 795  
      *
 796  
      * @param mapping
 797  
      * @param form
 798  
      * @param request
 799  
      * @param response
 800  
      * @return ActionForward
 801  
      * @throws Exception
 802  
      */
 803  
     public ActionForward blanketApprove(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 804  0
         KualiDocumentFormBase kualiDocumentFormBase = (KualiDocumentFormBase) form;
 805  0
         doProcessingAfterPost(kualiDocumentFormBase, request);
 806  
 
 807  0
         kualiDocumentFormBase.setDerivedValuesOnForm(request);
 808  0
         ActionForward preRulesForward = promptBeforeValidation(mapping, form, request, response);
 809  0
         if (preRulesForward != null) {
 810  0
             return preRulesForward;
 811  
         }
 812  
 
 813  0
         Document document = kualiDocumentFormBase.getDocument();
 814  
 
 815  0
         ActionForward forward = checkAndWarnAboutSensitiveData(mapping, form, request, response, KRADPropertyConstants.DOCUMENT_EXPLANATION, document.getDocumentHeader().getExplanation(), "blanketApprove", "");
 816  0
         if (forward != null) {
 817  0
             return forward;
 818  
         }
 819  
 
 820  0
         getDocumentService().blanketApproveDocument(document, kualiDocumentFormBase.getAnnotation(), combineAdHocRecipients(kualiDocumentFormBase));
 821  0
         KNSGlobalVariables.getMessageList().add(RiceKeyConstants.MESSAGE_ROUTE_APPROVED);
 822  0
         kualiDocumentFormBase.setAnnotation("");
 823  0
         return returnToSender(request, mapping, kualiDocumentFormBase);
 824  
     }
 825  
 
 826  
     /**
 827  
      * Calls the document service to approve the document
 828  
      *
 829  
      * @param mapping
 830  
      * @param form
 831  
      * @param request
 832  
      * @param response
 833  
      * @return ActionForward
 834  
      * @throws Exception
 835  
      */
 836  
     public ActionForward approve(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 837  0
         KualiDocumentFormBase kualiDocumentFormBase = (KualiDocumentFormBase) form;
 838  0
         doProcessingAfterPost(kualiDocumentFormBase, request);
 839  
 
 840  0
         kualiDocumentFormBase.setDerivedValuesOnForm(request);
 841  0
         ActionForward preRulesForward = promptBeforeValidation(mapping, form, request, response);
 842  0
         if (preRulesForward != null) {
 843  0
             return preRulesForward;
 844  
         }
 845  
 
 846  0
         Document document = kualiDocumentFormBase.getDocument();
 847  
 
 848  0
         ActionForward forward = checkAndWarnAboutSensitiveData(mapping, form, request, response, KRADPropertyConstants.DOCUMENT_EXPLANATION, document.getDocumentHeader().getExplanation(), "approve", "");
 849  0
         if (forward != null) {
 850  0
             return forward;
 851  
         }
 852  
 
 853  0
         getDocumentService().approveDocument(document, kualiDocumentFormBase.getAnnotation(), combineAdHocRecipients(kualiDocumentFormBase));
 854  0
         KNSGlobalVariables.getMessageList().add(RiceKeyConstants.MESSAGE_ROUTE_APPROVED);
 855  0
         kualiDocumentFormBase.setAnnotation("");
 856  0
         return returnToSender(request, mapping, kualiDocumentFormBase);
 857  
     }
 858  
 
 859  
     /**
 860  
      * Calls the document service to disapprove the document
 861  
      *
 862  
      * @param mapping
 863  
      * @param form
 864  
      * @param request
 865  
      * @param response
 866  
      * @return ActionForward
 867  
      * @throws Exception
 868  
      */
 869  
     public ActionForward disapprove(ActionMapping mapping, ActionForm form, HttpServletRequest request,
 870  
                                     HttpServletResponse response) throws Exception {
 871  0
         Object question = request.getParameter(KRADConstants.QUESTION_INST_ATTRIBUTE_NAME);
 872  0
         String reason = request.getParameter(KRADConstants.QUESTION_REASON_ATTRIBUTE_NAME);
 873  
 
 874  0
         if (StringUtils.isBlank(reason)) {
 875  0
             String context = request.getParameter(KRADConstants.QUESTION_CONTEXT);
 876  0
             if (context != null && StringUtils.contains(context, KRADConstants.QUESTION_REASON_ATTRIBUTE_NAME + "=")) {
 877  0
                 reason = StringUtils.substringAfter(context, KRADConstants.QUESTION_REASON_ATTRIBUTE_NAME + "=");
 878  
             }
 879  
         }
 880  
 
 881  0
         String disapprovalNoteText = "";
 882  
 
 883  
         // start in logic for confirming the disapproval
 884  0
         if (question == null) {
 885  
             // ask question if not already asked
 886  0
             return this.performQuestionWithInput(mapping, form, request, response,
 887  
                     KRADConstants.DOCUMENT_DISAPPROVE_QUESTION,
 888  
                     getKualiConfigurationService().getPropertyString(RiceKeyConstants.QUESTION_DISAPPROVE_DOCUMENT),
 889  
                     KRADConstants.CONFIRMATION_QUESTION, KRADConstants.MAPPING_DISAPPROVE, "");
 890  
         }
 891  0
         Object buttonClicked = request.getParameter(KRADConstants.QUESTION_CLICKED_BUTTON);
 892  0
         if ((KRADConstants.DOCUMENT_DISAPPROVE_QUESTION.equals(question))
 893  
                 && ConfirmationQuestion.NO.equals(buttonClicked)) {
 894  
             // if no button clicked just reload the doc
 895  0
             return mapping.findForward(RiceConstants.MAPPING_BASIC);
 896  
         }
 897  
 
 898  
         // have to check length on value entered
 899  0
         String introNoteMessage = getKualiConfigurationService().getPropertyString(
 900  
                 RiceKeyConstants.MESSAGE_DISAPPROVAL_NOTE_TEXT_INTRO)
 901  
                 + KRADConstants.BLANK_SPACE;
 902  
 
 903  
         // build out full message
 904  0
         disapprovalNoteText = introNoteMessage + reason;
 905  
 
 906  
         // check for sensitive data in note
 907  0
         boolean warnForSensitiveData = CoreFrameworkServiceLocator.getParameterService().getParameterValueAsBoolean(
 908  
                 KRADConstants.KRAD_NAMESPACE, ParameterConstants.ALL_COMPONENT,
 909  
                 KRADConstants.SystemGroupParameterNames.SENSITIVE_DATA_PATTERNS_WARNING_IND);
 910  0
         if (warnForSensitiveData) {
 911  0
             String context = KRADConstants.QUESTION_REASON_ATTRIBUTE_NAME + "=" + reason;
 912  0
             ActionForward forward = checkAndWarnAboutSensitiveData(mapping, form, request, response,
 913  
                     KRADConstants.QUESTION_REASON_ATTRIBUTE_NAME, disapprovalNoteText, "disapprove", context);
 914  0
             if (forward != null) {
 915  0
                 return forward;
 916  
             }
 917  0
         } else {
 918  0
             if (KRADUtils.containsSensitiveDataPatternMatch(disapprovalNoteText)) {
 919  0
                 return this
 920  
                         .performQuestionWithInputAgainBecauseOfErrors(mapping, form, request, response,
 921  
                                 KRADConstants.DOCUMENT_DISAPPROVE_QUESTION, getKualiConfigurationService()
 922  
                                 .getPropertyString(RiceKeyConstants.QUESTION_DISAPPROVE_DOCUMENT),
 923  
                                 KRADConstants.CONFIRMATION_QUESTION, KRADConstants.MAPPING_DISAPPROVE, "", reason,
 924  
                                 RiceKeyConstants.ERROR_DOCUMENT_FIELD_CONTAINS_POSSIBLE_SENSITIVE_DATA,
 925  
                                 KRADConstants.QUESTION_REASON_ATTRIBUTE_NAME, "reason");
 926  
             }
 927  
         }
 928  
 
 929  0
         int disapprovalNoteTextLength = disapprovalNoteText.length();
 930  
 
 931  
         // get note text max length from DD
 932  0
         int noteTextMaxLength = getDataDictionaryService().getAttributeMaxLength(Note.class,
 933  
                 KRADConstants.NOTE_TEXT_PROPERTY_NAME);
 934  
 
 935  0
         if (StringUtils.isBlank(reason) || (disapprovalNoteTextLength > noteTextMaxLength)) {
 936  
 
 937  0
             if (reason == null) {
 938  
                 // prevent a NPE by setting the reason to a blank string
 939  0
                 reason = "";
 940  
             }
 941  0
             return this.performQuestionWithInputAgainBecauseOfErrors(mapping, form, request, response,
 942  
                     KRADConstants.DOCUMENT_DISAPPROVE_QUESTION,
 943  
                     getKualiConfigurationService().getPropertyString(RiceKeyConstants.QUESTION_DISAPPROVE_DOCUMENT),
 944  
                     KRADConstants.CONFIRMATION_QUESTION, KRADConstants.MAPPING_DISAPPROVE, "", reason,
 945  
                     RiceKeyConstants.ERROR_DOCUMENT_DISAPPROVE_REASON_REQUIRED,
 946  
                     KRADConstants.QUESTION_REASON_ATTRIBUTE_NAME, Integer.toString(noteTextMaxLength));
 947  
         }
 948  
 
 949  0
         KualiDocumentFormBase kualiDocumentFormBase = (KualiDocumentFormBase) form;
 950  0
         doProcessingAfterPost(kualiDocumentFormBase, request);
 951  0
         getDocumentService().disapproveDocument(kualiDocumentFormBase.getDocument(), disapprovalNoteText);
 952  0
         KNSGlobalVariables.getMessageList().add(RiceKeyConstants.MESSAGE_ROUTE_DISAPPROVED);
 953  0
         kualiDocumentFormBase.setAnnotation("");
 954  
 
 955  0
         return returnToSender(request, mapping, kualiDocumentFormBase);
 956  
     }
 957  
 
 958  
     /**
 959  
      * Calls the document service to cancel the document
 960  
      *
 961  
      * @param mapping
 962  
      * @param form
 963  
      * @param request
 964  
      * @param response
 965  
      * @return ActionForward
 966  
      * @throws Exception
 967  
      */
 968  
     public ActionForward cancel(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 969  0
         Object question = request.getParameter(KRADConstants.QUESTION_INST_ATTRIBUTE_NAME);
 970  
         // this should probably be moved into a private instance variable
 971  
         // logic for cancel question
 972  0
         if (question == null) {
 973  
             // ask question if not already asked
 974  0
             return this.performQuestionWithoutInput(mapping, form, request, response, KRADConstants.DOCUMENT_CANCEL_QUESTION, getKualiConfigurationService().getPropertyString("document.question.cancel.text"), KRADConstants.CONFIRMATION_QUESTION, KRADConstants.MAPPING_CANCEL, "");
 975  
         } else {
 976  0
             Object buttonClicked = request.getParameter(KRADConstants.QUESTION_CLICKED_BUTTON);
 977  0
             if ((KRADConstants.DOCUMENT_CANCEL_QUESTION.equals(question)) && ConfirmationQuestion.NO.equals(buttonClicked)) {
 978  
                 // if no button clicked just reload the doc
 979  0
                 return mapping.findForward(RiceConstants.MAPPING_BASIC);
 980  
             }
 981  
             // else go to cancel logic below
 982  
         }
 983  
 
 984  0
         KualiDocumentFormBase kualiDocumentFormBase = (KualiDocumentFormBase) form;
 985  0
         doProcessingAfterPost(kualiDocumentFormBase, request);
 986  
         // KULRICE-4447 Call cancelDocument() only if the document exists
 987  0
         if (getDocumentService().documentExists(kualiDocumentFormBase.getDocId())) {
 988  0
             getDocumentService().cancelDocument(kualiDocumentFormBase.getDocument(), kualiDocumentFormBase.getAnnotation());
 989  
         }
 990  
 
 991  0
         return returnToSender(request, mapping, kualiDocumentFormBase);
 992  
     }
 993  
 
 994  
     /**
 995  
      * Close the document and take the user back to the index; only after asking the user if they want to save the document first.
 996  
      * Only users who have the "canSave()" permission are given this option.
 997  
      *
 998  
      * @param mapping
 999  
      * @param form
 1000  
      * @param request
 1001  
      * @param response
 1002  
      * @return ActionForward
 1003  
      * @throws Exception
 1004  
      */
 1005  
     public ActionForward close(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 1006  0
         KualiDocumentFormBase docForm = (KualiDocumentFormBase) form;
 1007  0
         doProcessingAfterPost(docForm, request);
 1008  0
         Document document = docForm.getDocument();
 1009  
         // only want to prompt them to save if they already can save
 1010  0
         if (canSave(docForm)) {
 1011  0
             Object question = getQuestion(request);
 1012  
             // logic for close question
 1013  0
             if (question == null) {
 1014  
                 // ask question if not already asked
 1015  0
                 return this.performQuestionWithoutInput(mapping, form, request, response, KRADConstants.DOCUMENT_SAVE_BEFORE_CLOSE_QUESTION, getKualiConfigurationService().getPropertyString(RiceKeyConstants.QUESTION_SAVE_BEFORE_CLOSE), KRADConstants.CONFIRMATION_QUESTION, KRADConstants.MAPPING_CLOSE, "");
 1016  
             } else {
 1017  0
                 Object buttonClicked = request.getParameter(KRADConstants.QUESTION_CLICKED_BUTTON);
 1018  0
                 if ((KRADConstants.DOCUMENT_SAVE_BEFORE_CLOSE_QUESTION.equals(question)) && ConfirmationQuestion.YES.equals(buttonClicked)) {
 1019  
                     // if yes button clicked - save the doc
 1020  0
                     ActionForward forward = checkAndWarnAboutSensitiveData(mapping, form, request, response, KRADPropertyConstants.DOCUMENT_EXPLANATION, document.getDocumentHeader().getExplanation(), "save", "");
 1021  0
                     if (forward != null) {
 1022  0
                         return forward;
 1023  
                     }
 1024  
 
 1025  0
                     getDocumentService().saveDocument(docForm.getDocument());
 1026  
                 }
 1027  
                 // else go to close logic below
 1028  
             }
 1029  
         }
 1030  
 
 1031  0
         return returnToSender(request, mapping, docForm);
 1032  
     }
 1033  
 
 1034  
     protected boolean canSave(ActionForm form) {
 1035  0
         KualiDocumentFormBase docForm = (KualiDocumentFormBase) form;
 1036  0
         return docForm.getDocumentActions().containsKey(KRADConstants.KUALI_ACTION_CAN_SAVE);
 1037  
     }
 1038  
 
 1039  
     protected Object getQuestion(HttpServletRequest request) {
 1040  0
         return request.getParameter(KRADConstants.QUESTION_INST_ATTRIBUTE_NAME);
 1041  
     }
 1042  
 
 1043  
     /**
 1044  
      * call the document service to clear the fyis
 1045  
      *
 1046  
      * @param mapping
 1047  
      * @param form
 1048  
      * @param request
 1049  
      * @param response
 1050  
      * @return ActionForward
 1051  
      * @throws Exception
 1052  
      */
 1053  
     public ActionForward fyi(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 1054  0
         KualiDocumentFormBase kualiDocumentFormBase = (KualiDocumentFormBase) form;
 1055  0
         doProcessingAfterPost(kualiDocumentFormBase, request);
 1056  0
         getDocumentService().clearDocumentFyi(kualiDocumentFormBase.getDocument(), combineAdHocRecipients(kualiDocumentFormBase));
 1057  0
         KNSGlobalVariables.getMessageList().add(RiceKeyConstants.MESSAGE_ROUTE_FYIED);
 1058  0
         kualiDocumentFormBase.setAnnotation("");
 1059  0
         return returnToSender(request, mapping, kualiDocumentFormBase);
 1060  
     }
 1061  
 
 1062  
     /**
 1063  
      * call the document service to acknowledge
 1064  
      *
 1065  
      * @param mapping
 1066  
      * @param form
 1067  
      * @param request
 1068  
      * @param response
 1069  
      * @return ActionForward
 1070  
      * @throws Exception
 1071  
      */
 1072  
     public ActionForward acknowledge(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 1073  0
         KualiDocumentFormBase kualiDocumentFormBase = (KualiDocumentFormBase) form;
 1074  0
         doProcessingAfterPost(kualiDocumentFormBase, request);
 1075  0
         getDocumentService().acknowledgeDocument(kualiDocumentFormBase.getDocument(), kualiDocumentFormBase.getAnnotation(), combineAdHocRecipients(kualiDocumentFormBase));
 1076  0
         KNSGlobalVariables.getMessageList().add(RiceKeyConstants.MESSAGE_ROUTE_ACKNOWLEDGED);
 1077  0
         kualiDocumentFormBase.setAnnotation("");
 1078  0
         return returnToSender(request, mapping, kualiDocumentFormBase);
 1079  
     }
 1080  
 
 1081  
     /**
 1082  
      * redirect to the supervisor functions that exist.
 1083  
      *
 1084  
      * @param mapping
 1085  
      * @param form
 1086  
      * @param request
 1087  
      * @param response
 1088  
      * @return ActionForward
 1089  
      * @throws Exception
 1090  
      */
 1091  
     public ActionForward supervisorFunctions(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 1092  0
         KualiDocumentFormBase kualiDocumentFormBase = (KualiDocumentFormBase) form;
 1093  
 
 1094  
 
 1095  0
         String workflowSuperUserUrl = getKualiConfigurationService().getPropertyString(KRADConstants.WORKFLOW_URL_KEY) + "/SuperUser.do?methodToCall=displaySuperUserDocument&documentId=" + kualiDocumentFormBase.getDocument().getDocumentHeader().getDocumentNumber();
 1096  0
         response.sendRedirect(workflowSuperUserUrl);
 1097  
 
 1098  0
         return null;
 1099  
     }
 1100  
 
 1101  
     /**
 1102  
      * Convenience method to combine the two lists of ad hoc recipients into one which should be done before calling any of the
 1103  
      * document service methods that expect a list of ad hoc recipients
 1104  
      *
 1105  
      * @param kualiDocumentFormBase
 1106  
      * @return List
 1107  
      */
 1108  
     protected List<AdHocRouteRecipient> combineAdHocRecipients(KualiDocumentFormBase kualiDocumentFormBase) {
 1109  0
         List<AdHocRouteRecipient> adHocRecipients = new ArrayList<AdHocRouteRecipient>();
 1110  0
         adHocRecipients.addAll(kualiDocumentFormBase.getAdHocRoutePersons());
 1111  0
         adHocRecipients.addAll(kualiDocumentFormBase.getAdHocRouteWorkgroups());
 1112  0
         return adHocRecipients;
 1113  
     }
 1114  
 
 1115  
     /**
 1116  
      * if the action desires to retain error messages generated by the rules framework for save/submit/etc. validation after returning from a lookup.
 1117  
      *
 1118  
      * @see KualiAction#refresh(org.apache.struts.action.ActionMapping,
 1119  
      *      org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
 1120  
      */
 1121  
     @Override
 1122  
     public ActionForward refresh(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 1123  0
         KualiDocumentFormBase kualiForm = (KualiDocumentFormBase) form;
 1124  0
         kualiForm.setDerivedValuesOnForm(request);
 1125  
 
 1126  0
         super.refresh(mapping, form, request, response);
 1127  0
         refreshAdHocRoutingWorkgroupLookups(request, kualiForm);
 1128  
 
 1129  0
         return mapping.findForward(RiceConstants.MAPPING_BASIC);
 1130  
     }
 1131  
 
 1132  
     /**
 1133  
      * special refresh needed to get the workgroups populated correctly when coming back from workgroup lookups
 1134  
      *
 1135  
      * @param request
 1136  
      * @param kualiForm
 1137  
      * @throws WorkflowException
 1138  
      */
 1139  
     @SuppressWarnings("unchecked")
 1140  
     protected void refreshAdHocRoutingWorkgroupLookups(HttpServletRequest request, KualiDocumentFormBase kualiForm) throws WorkflowException {
 1141  0
         for (Enumeration<String> i = request.getParameterNames(); i.hasMoreElements();) {
 1142  0
             String parameterName = i.nextElement();
 1143  0
             if (parameterName.equals("newAdHocRouteWorkgroup.recipientName") && !"".equals(request.getParameter(parameterName))) {
 1144  
                 //check for namespace
 1145  0
                 String namespace = KimConstants.KIM_GROUP_DEFAULT_NAMESPACE_CODE;
 1146  0
                 if (request.getParameter("newAdHocRouteWorkgroup.recipientNamespaceCode") != null && !"".equals(request.getParameter("newAdHocRouteWorkgroup.recipientName").trim())) {
 1147  0
                     namespace = request.getParameter("newAdHocRouteWorkgroup.recipientNamespaceCode").trim();
 1148  
                 }
 1149  0
                 Group group = getGroupService().getGroupByName(namespace, request.getParameter(parameterName));
 1150  0
                 if (group != null) {
 1151  0
                     kualiForm.getNewAdHocRouteWorkgroup().setId(group.getId());
 1152  0
                     kualiForm.getNewAdHocRouteWorkgroup().setRecipientName(group.getName());
 1153  0
                     kualiForm.getNewAdHocRouteWorkgroup().setRecipientNamespaceCode(group.getNamespaceCode());
 1154  
                 } else {
 1155  0
                     throw new RuntimeException("Invalid workgroup id passed as parameter.");
 1156  
                 }
 1157  
             }
 1158  0
             if (parameterName.startsWith("adHocRouteWorkgroup[") && !"".equals(request.getParameter(parameterName))) {
 1159  0
                 if (parameterName.endsWith(".recipientName")) {
 1160  0
                     int lineNumber = Integer.parseInt(StringUtils.substringBetween(parameterName, "[", "]"));
 1161  
                     //check for namespace
 1162  0
                     String namespaceParam = "adHocRouteWorkgroup[" + lineNumber + "].recipientNamespaceCode";
 1163  0
                     String namespace = KimConstants.KIM_GROUP_DEFAULT_NAMESPACE_CODE;
 1164  0
                     if (request.getParameter(namespaceParam) != null && !"".equals(request.getParameter(namespaceParam).trim())) {
 1165  0
                         namespace = request.getParameter(namespaceParam).trim();
 1166  
                     }
 1167  0
                     Group group = getGroupService().getGroupByName(namespace, request.getParameter(parameterName));
 1168  0
                     if (group != null) {
 1169  0
                         kualiForm.getAdHocRouteWorkgroup(lineNumber).setId(group.getId());
 1170  0
                         kualiForm.getAdHocRouteWorkgroup(lineNumber).setRecipientName(group.getName());
 1171  0
                         kualiForm.getAdHocRouteWorkgroup(lineNumber).setRecipientNamespaceCode(group.getNamespaceCode());
 1172  
                     } else {
 1173  0
                         throw new RuntimeException("Invalid workgroup id passed as parameter.");
 1174  
                     }
 1175  
                 }
 1176  
             }
 1177  
             /*
 1178  
             if (parameterName.startsWith("newAdHocRouteWorkgroup[") && !"".equals(request.getParameter(parameterName))) {
 1179  
                 if (parameterName.endsWith(".recipientName")) {
 1180  
                     int lineNumber = Integer.parseInt(StringUtils.substringBetween(parameterName, "[", "]"));
 1181  
                   //check for namespace
 1182  
                     String namespaceParam = "newAdHocRouteWorkgroup[" + lineNumber + "].recipientNamespaceCode";
 1183  
                     String namespace = KimConstants.KIM_GROUP_DEFAULT_NAMESPACE_CODE;
 1184  
                     if (request.getParameter(namespaceParam) != null && !"".equals(request.getParameter(namespaceParam).trim())) {
 1185  
                         namespace = request.getParameter(namespaceParam).trim();
 1186  
                     }
 1187  
                     KimGroup group = getIdentityManagementService().getGroupByName(namespace, request.getParameter(parameterName));
 1188  
                     if (group != null) {
 1189  
                         kualiForm.getAdHocRouteWorkgroup(lineNumber).setId(group.getGroupId());
 1190  
                         kualiForm.getAdHocRouteWorkgroup(lineNumber).setRecipientName(group.getGroupName());
 1191  
                         kualiForm.getAdHocRouteWorkgroup(lineNumber).setRecipientNamespaceCode(group.getNamespaceCode());
 1192  
                     } else {
 1193  
                         throw new RuntimeException("Invalid workgroup id passed as parameter.");
 1194  
                     }
 1195  
                 }
 1196  
             }
 1197  
             */
 1198  0
         }
 1199  0
     }
 1200  
 
 1201  
 
 1202  
     /**
 1203  
      * Cancels the pending attachment, if any.
 1204  
      *
 1205  
      * @param mapping
 1206  
      * @param form
 1207  
      * @param request
 1208  
      * @param response
 1209  
      * @return ActionForward
 1210  
      * @throws Exception
 1211  
      */
 1212  
     public ActionForward cancelBOAttachment(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 1213  0
         KualiDocumentFormBase documentForm = (KualiDocumentFormBase) form;
 1214  
 
 1215  
         // blank current attachmentFile
 1216  0
         documentForm.setAttachmentFile(new BlankFormFile());
 1217  
 
 1218  
         // remove current attachment, if any
 1219  0
         Note note = documentForm.getNewNote();
 1220  0
         note.removeAttachment();
 1221  0
         documentForm.setNewNote(note);
 1222  
 
 1223  0
         return mapping.findForward(RiceConstants.MAPPING_BASIC);
 1224  
     }
 1225  
 
 1226  
     /**
 1227  
      * Handy method to stream the byte array to response object
 1228  
      *
 1229  
      * @param fileContents
 1230  
      * @param fileName
 1231  
      * @param fileContentType
 1232  
      * @param response
 1233  
      * @throws Exception
 1234  
      */
 1235  
     protected void streamToResponse(byte[] fileContents, String fileName, String fileContentType, HttpServletResponse response) throws Exception {
 1236  0
         ByteArrayOutputStream baos = null;
 1237  
         try {
 1238  0
             baos = new ByteArrayOutputStream(fileContents.length);
 1239  0
             baos.write(fileContents);
 1240  0
             WebUtils.saveMimeOutputStreamAsFile(response, fileContentType, baos, fileName);
 1241  
         } finally {
 1242  0
             try {
 1243  0
                 if (baos != null) {
 1244  0
                     baos.close();
 1245  0
                     baos = null;
 1246  
                 }
 1247  0
             } catch (IOException ioEx) {
 1248  0
                 LOG.error("Error while downloading attachment");
 1249  0
                 throw new RuntimeException("IOException occurred while downloading attachment", ioEx);
 1250  0
             }
 1251  
         }
 1252  0
     }
 1253  
 
 1254  
     /**
 1255  
      * Downloads the selected attachment to the user's browser
 1256  
      *
 1257  
      * @param mapping
 1258  
      * @param form
 1259  
      * @param request
 1260  
      * @param response
 1261  
      * @return ActionForward
 1262  
      * @throws Exception
 1263  
      */
 1264  
     public ActionForward downloadBOAttachment(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 1265  0
         KualiDocumentFormBase documentForm = (KualiDocumentFormBase) form;
 1266  
 
 1267  0
         int attachmentIndex = selectedAttachmentIndex(request);
 1268  0
         if (attachmentIndex >= 0) {
 1269  0
             Note note = documentForm.getDocument().getNote(attachmentIndex);
 1270  0
             Attachment attachment = note.getAttachment();
 1271  
             //make sure attachment is setup with backwards reference to note (rather then doing this we could also just call the attachment service (with a new method that took in the note)
 1272  0
             attachment.setNote(note);
 1273  
 
 1274  
             // since we're downloading a file, all of the editable properties from the previous request will continue to be editable.
 1275  0
             documentForm.copyPopulateEditablePropertiesToActionEditableProperties();
 1276  
 
 1277  0
             WebUtils.saveMimeInputStreamAsFile(response, attachment.getAttachmentMimeTypeCode(), attachment.getAttachmentContents(), attachment.getAttachmentFileName(), attachment.getAttachmentFileSize().intValue());
 1278  0
             return null;
 1279  
         }
 1280  
 
 1281  0
         return mapping.findForward(RiceConstants.MAPPING_BASIC);
 1282  
     }
 1283  
 
 1284  
 
 1285  
     /**
 1286  
      * @param request
 1287  
      * @return index of the attachment whose download button was just pressed
 1288  
      */
 1289  
     protected int selectedAttachmentIndex(HttpServletRequest request) {
 1290  0
         int attachmentIndex = -1;
 1291  
 
 1292  0
         String parameterName = (String) request.getAttribute(KRADConstants.METHOD_TO_CALL_ATTRIBUTE);
 1293  0
         if (StringUtils.isNotBlank(parameterName)) {
 1294  0
             String attachmentIndexParam = StringUtils.substringBetween(parameterName, ".attachment[", "].");
 1295  
 
 1296  
             try {
 1297  0
                 attachmentIndex = Integer.parseInt(attachmentIndexParam);
 1298  0
             } catch (NumberFormatException ignored) {
 1299  0
             }
 1300  
         }
 1301  
 
 1302  0
         return attachmentIndex;
 1303  
     }
 1304  
 
 1305  
 
 1306  
     /**
 1307  
      * insert a note into the document
 1308  
      *
 1309  
      * @param mapping
 1310  
      * @param form
 1311  
      * @param request
 1312  
      * @param response
 1313  
      * @return ActionForward
 1314  
      * @throws Exception
 1315  
      */
 1316  
     public ActionForward insertBONote(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 1317  0
         KualiDocumentFormBase kualiDocumentFormBase = (KualiDocumentFormBase) form;
 1318  0
         Document document = kualiDocumentFormBase.getDocument();
 1319  0
         Note newNote = kualiDocumentFormBase.getNewNote();
 1320  0
         newNote.setNotePostedTimestampToCurrent();
 1321  
 
 1322  0
         String attachmentTypeCode = null;
 1323  
 
 1324  0
         FormFile attachmentFile = kualiDocumentFormBase.getAttachmentFile();
 1325  0
         if (attachmentFile == null) {
 1326  0
             GlobalVariables.getMessageMap().putError(
 1327  
                     String.format("%s.%s",
 1328  
                             KRADConstants.NEW_DOCUMENT_NOTE_PROPERTY_NAME,
 1329  
                             KRADConstants.NOTE_ATTACHMENT_FILE_PROPERTY_NAME),
 1330  
                     RiceKeyConstants.ERROR_UPLOADFILE_NULL);
 1331  
             // This line was removed in order to continue to validates other
 1332  
             // return mapping.findForward(RiceConstants.MAPPING_BASIC);
 1333  
         }
 1334  
 
 1335  0
         if (newNote.getAttachment() != null) {
 1336  0
             attachmentTypeCode = newNote.getAttachment().getAttachmentTypeCode();
 1337  
         }
 1338  
 
 1339  
         // check authorization for adding notes
 1340  0
         DocumentAuthorizer documentAuthorizer = getDocumentHelperService().getDocumentAuthorizer(document);
 1341  0
         if (!documentAuthorizer.canAddNoteAttachment(document, attachmentTypeCode, GlobalVariables.getUserSession().getPerson())) {
 1342  0
             throw buildAuthorizationException("annotate", document);
 1343  
         }
 1344  
 
 1345  
         // create the attachment first, so that failure-to-create-attachment can be treated as a validation failure
 1346  
 
 1347  0
         Attachment attachment = null;
 1348  0
         if (attachmentFile != null && !StringUtils.isBlank(attachmentFile.getFileName())) {
 1349  0
             if (attachmentFile.getFileSize() == 0) {
 1350  0
                 GlobalVariables.getMessageMap().putError(
 1351  
                         String.format("%s.%s",
 1352  
                                 KRADConstants.NEW_DOCUMENT_NOTE_PROPERTY_NAME,
 1353  
                                 KRADConstants.NOTE_ATTACHMENT_FILE_PROPERTY_NAME),
 1354  
                         RiceKeyConstants.ERROR_UPLOADFILE_EMPTY,
 1355  
                         attachmentFile.getFileName());
 1356  
                 // This line was removed in order to continue to validates other
 1357  
 //                return mapping.findForward(RiceConstants.MAPPING_BASIC);
 1358  
             } else {
 1359  0
                 String attachmentType = null;
 1360  0
                 Attachment newAttachment = kualiDocumentFormBase.getNewNote().getAttachment();
 1361  0
                 if (newAttachment != null) {
 1362  0
                     attachmentType = newAttachment.getAttachmentTypeCode();
 1363  
                 }
 1364  0
                 attachment = getAttachmentService().createAttachment(document.getNoteTarget(), attachmentFile.getFileName(), attachmentFile.getContentType(), attachmentFile.getFileSize(), attachmentFile.getInputStream(), attachmentType);
 1365  
             }
 1366  
         }
 1367  
 
 1368  0
         DataDictionary dataDictionary = getDataDictionaryService().getDataDictionary();
 1369  0
         org.kuali.rice.krad.datadictionary.DocumentEntry entry = dataDictionary.getDocumentEntry(document.getClass().getName());
 1370  
 
 1371  0
         if (entry.getDisplayTopicFieldInNotes()) {
 1372  0
             String topicText = kualiDocumentFormBase.getNewNote().getNoteTopicText();
 1373  0
             if (StringUtils.isBlank(topicText)) {
 1374  0
                 GlobalVariables.getMessageMap().putError(
 1375  
                         String.format("%s.%s",
 1376  
                                 KRADConstants.NEW_DOCUMENT_NOTE_PROPERTY_NAME,
 1377  
                                 KRADConstants.NOTE_TOPIC_TEXT_PROPERTY_NAME),
 1378  
                         RiceKeyConstants.ERROR_REQUIRED,
 1379  
                         "Note Topic (Note Topic)");
 1380  
             }
 1381  
         }
 1382  
 
 1383  
         // create a new note from the data passed in
 1384  
         // TODO gah! this is awful
 1385  0
         Person kualiUser = GlobalVariables.getUserSession().getPerson();
 1386  0
         if (kualiUser == null) {
 1387  0
             throw new IllegalStateException("Current UserSession has a null Person.");
 1388  
         }
 1389  0
         Note tmpNote = getNoteService().createNote(newNote, document.getNoteTarget(), kualiUser.getPrincipalId());
 1390  
 
 1391  0
         ActionForward forward = checkAndWarnAboutSensitiveData(mapping, form, request, response, KRADPropertyConstants.NOTE, tmpNote.getNoteText(), "insertBONote", "");
 1392  0
         if (forward != null) {
 1393  0
             return forward;
 1394  
         }
 1395  
 
 1396  
         // validate the note
 1397  0
         boolean rulePassed = getKualiRuleService().applyRules(new AddNoteEvent(document, tmpNote));
 1398  
 
 1399  
         // if the rule evaluation passed, let's add the note
 1400  0
         if (rulePassed) {
 1401  0
             tmpNote.refresh();
 1402  
 
 1403  
 
 1404  0
             DocumentHeader documentHeader = document.getDocumentHeader();
 1405  
 
 1406  
             // associate note with object now
 1407  0
             document.addNote(tmpNote);
 1408  
 
 1409  
             // persist the note if the document is already saved the getObjectId check is to get around a bug with certain documents where
 1410  
             // "saved" doesn't really persist, if you notice any problems with missing notes check this line
 1411  
             //maintenance document BO note should only be saved into table when document is in the PROCESSED workflow status
 1412  0
             if (!documentHeader.getWorkflowDocument().isInitiated() && StringUtils.isNotEmpty(document.getNoteTarget().getObjectId())
 1413  
                     && !(document instanceof MaintenanceDocument && NoteType.BUSINESS_OBJECT.getCode().equals(tmpNote.getNoteTypeCode()))
 1414  
                     ) {
 1415  0
                 getNoteService().save(tmpNote);
 1416  
             }
 1417  
             // adding the attachment after refresh gets called, since the attachment record doesn't get persisted
 1418  
             // until the note does (and therefore refresh doesn't have any attachment to autoload based on the id, nor does it
 1419  
             // autopopulate the id since the note hasn't been persisted yet)
 1420  0
             if (attachment != null) {
 1421  0
                 tmpNote.addAttachment(attachment);
 1422  
                 // save again for attachment, note this is because sometimes the attachment is added first to the above then ojb tries to save
 1423  
                 //without the PK on the attachment I think it is safer then trying to get the sequence manually
 1424  0
                 if (!documentHeader.getWorkflowDocument().isInitiated() && StringUtils.isNotEmpty(document.getNoteTarget().getObjectId())
 1425  
                         && !(document instanceof MaintenanceDocument && NoteType.BUSINESS_OBJECT.getCode().equals(tmpNote.getNoteTypeCode()))
 1426  
                         ) {
 1427  0
                     getNoteService().save(tmpNote);
 1428  
                 }
 1429  
             }
 1430  
 
 1431  
 
 1432  
             // reset the new note back to an empty one
 1433  0
             kualiDocumentFormBase.setNewNote(new Note());
 1434  
         }
 1435  
 
 1436  
 
 1437  0
         return mapping.findForward(RiceConstants.MAPPING_BASIC);
 1438  
     }
 1439  
 
 1440  
     /**
 1441  
      * delete a note from the document
 1442  
      *
 1443  
      * @param mapping
 1444  
      * @param form
 1445  
      * @param request
 1446  
      * @param response
 1447  
      * @return ActionForward
 1448  
      * @throws Exception
 1449  
      */
 1450  
     public ActionForward deleteBONote(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 1451  0
         KualiDocumentFormBase kualiDocumentFormBase = (KualiDocumentFormBase) form;
 1452  0
         Document document = kualiDocumentFormBase.getDocument();
 1453  
 
 1454  
 
 1455  
 //        DataDictionary dataDictionary = getDataDictionaryService().getDataDictionary();
 1456  
 //        DocumentEntry entry = dataDictionary.getDocumentEntry(document.getClass().getName());
 1457  
 
 1458  
         // check authorization for adding notes
 1459  
         //DocumentActionFlags flags = getDocumentActionFlags(document);
 1460  
         //if (!kualiDocumentFormBase.getDocumentActions().containsKey(KRADConstants.KUALI_ACTION_CAN_ANNOTATE)) {
 1461  
         //    buildAuthorizationException("annotate", document);
 1462  
         //    return mapping.findForward(RiceConstants.MAPPING_BASIC);
 1463  
         //}
 1464  
 
 1465  
         // ok to delete the note/attachment
 1466  
         // derive the note property from the newNote on the form
 1467  0
         Note newNote = kualiDocumentFormBase.getNewNote();
 1468  0
         Note note = document.getNote(getLineToDelete(request));
 1469  0
         Attachment attachment = note.getAttachment();
 1470  0
         String attachmentTypeCode = null;
 1471  0
         if (attachment != null) {
 1472  0
             attachmentTypeCode = attachment.getAttachmentTypeCode();
 1473  
         }
 1474  0
         String authorUniversalIdentifier = note.getAuthorUniversalIdentifier();
 1475  0
         if (!WebUtils.canDeleteNoteAttachment(document, attachmentTypeCode, authorUniversalIdentifier)) {
 1476  0
             throw buildAuthorizationException("annotate", document);
 1477  
         }
 1478  
 
 1479  0
         if (attachment != null) { // only do this if the note has been persisted
 1480  
             //KFSMI-798 - refresh() changed to refreshNonUpdateableReferences()
 1481  
             //All references for the business object Attachment are auto-update="none",
 1482  
             //so refreshNonUpdateableReferences() should work the same as refresh()
 1483  0
             if (note.getNoteIdentifier() != null) { // KULRICE-2343 don't blow away note reference if the note wasn't persisted
 1484  0
                 attachment.refreshNonUpdateableReferences();
 1485  
             }
 1486  0
             getAttachmentService().deleteAttachmentContents(attachment);
 1487  
         }
 1488  
         // delete the note if the document is already saved
 1489  0
         if (!document.getDocumentHeader().getWorkflowDocument().isInitiated()) {
 1490  0
             getNoteService().deleteNote(note);
 1491  
         }
 1492  0
         document.removeNote(note);
 1493  
 
 1494  0
         return mapping.findForward(RiceConstants.MAPPING_BASIC);
 1495  
     }
 1496  
 
 1497  
     /**
 1498  
      * Override this to customize which routing action to take when sending a note.  This method reads the system parameter
 1499  
      * KR-NS/Document/SEND_NOTE_WORKFLOW_NOTIFICATION_ACTIONS to determine which action to take
 1500  
      *
 1501  
      * @param request
 1502  
      * @param note
 1503  
      * @return a value from {@link KEWConstants}
 1504  
      */
 1505  
     protected String determineNoteWorkflowNotificationAction(HttpServletRequest request, KualiDocumentFormBase kualiDocumentFormBase, Note note) {
 1506  0
         return getParameterService().getParameterValueAsString(KRADConstants.KRAD_NAMESPACE, KRADConstants.DetailTypes.DOCUMENT_DETAIL_TYPE, KRADConstants.SEND_NOTE_WORKFLOW_NOTIFICATION_ACTIONS_PARM_NM);
 1507  
     }
 1508  
 
 1509  
     public ActionForward sendNoteWorkflowNotification(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 1510  0
         KualiDocumentFormBase kualiDocumentFormBase = (KualiDocumentFormBase) form;
 1511  0
         Document document = kualiDocumentFormBase.getDocument();
 1512  
 
 1513  0
         Note note = document.getNote(getSelectedLine(request));
 1514  
 
 1515  
         // verify recipient was specified
 1516  0
         if (StringUtils.isBlank(note.getAdHocRouteRecipient().getId())) {
 1517  0
             GlobalVariables.getMessageMap().putError(KRADPropertyConstants.NEW_DOCUMENT_NOTE, RiceKeyConstants.ERROR_SEND_NOTE_NOTIFICATION_RECIPIENT);
 1518  0
             return mapping.findForward(RiceConstants.MAPPING_BASIC);
 1519  
         }
 1520  
         // check recipient is valid
 1521  
         else {
 1522  0
             note.getAdHocRouteRecipient().setActionRequested(determineNoteWorkflowNotificationAction(request, kualiDocumentFormBase, note));
 1523  
 
 1524  0
             boolean rulePassed = getKualiRuleService().applyRules(new AddAdHocRoutePersonEvent(KRADPropertyConstants.NEW_DOCUMENT_NOTE, document, (AdHocRoutePerson) note.getAdHocRouteRecipient()));
 1525  0
             if (!rulePassed) {
 1526  0
                 return mapping.findForward(RiceConstants.MAPPING_BASIC);
 1527  
             }
 1528  
         }
 1529  
 
 1530  
         // if document is saved, send notification
 1531  0
         if (!document.getDocumentHeader().getWorkflowDocument().isInitiated()) {
 1532  0
             getDocumentService().sendNoteRouteNotification(document, note, GlobalVariables.getUserSession().getPerson());
 1533  
 
 1534  
             // add success message
 1535  0
             KNSGlobalVariables.getMessageList().add(RiceKeyConstants.MESSAGE_SEND_NOTE_NOTIFICATION_SUCCESSFUL);
 1536  
         } else {
 1537  0
             GlobalVariables.getMessageMap().putError(KRADPropertyConstants.NEW_DOCUMENT_NOTE, RiceKeyConstants.ERROR_SEND_NOTE_NOTIFICATION_DOCSTATUS);
 1538  
         }
 1539  
 
 1540  0
         return mapping.findForward(RiceConstants.MAPPING_BASIC);
 1541  
     }
 1542  
 
 1543  
 
 1544  
     /**
 1545  
      * Generates detailed log messages for OptimisticLockExceptions
 1546  
      *
 1547  
      * @param e
 1548  
      */
 1549  
     private final void logOjbOptimisticLockException(OptimisticLockException e) {
 1550  0
         if (LOG.isInfoEnabled()) {
 1551  0
             StringBuffer message = new StringBuffer("caught OptimisticLockException, caused by ");
 1552  0
             Object sourceObject = e.getSourceObject();
 1553  0
             String infix = null;
 1554  
             try {
 1555  
                 // try to add instance details
 1556  0
                 infix = sourceObject.toString();
 1557  0
             } catch (Exception e2) {
 1558  
                 // just use the class name
 1559  0
                 infix = sourceObject.getClass().getName();
 1560  0
             }
 1561  0
             message.append(infix);
 1562  
 
 1563  0
             if (sourceObject instanceof PersistableBusinessObject) {
 1564  0
                 PersistableBusinessObject persistableObject = (PersistableBusinessObject) sourceObject;
 1565  0
                 message.append(" [versionNumber = ").append(persistableObject.getVersionNumber()).append("]");
 1566  
             }
 1567  
 
 1568  0
             LOG.info(message.toString(), e);
 1569  
         }
 1570  0
     }
 1571  
 
 1572  
 
 1573  
     /**
 1574  
      * Makes calls to the PromptBeforeValidation specified for the document. If the class returns an actionforward, that forward
 1575  
      * will be returned (thus controlling how execution occurs), or null.
 1576  
      *
 1577  
      * @param mapping
 1578  
      * @param form
 1579  
      * @param request
 1580  
      * @param response
 1581  
      * @return
 1582  
      * @throws Exception
 1583  
      */
 1584  
     public ActionForward promptBeforeValidation(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 1585  0
         return promptBeforeValidation(mapping, form, request, response, "route");
 1586  
     }
 1587  
 
 1588  
     /**
 1589  
      * Makes calls to the PromptBeforeValidation specified for the document. If the class returns an actionforward, that forward
 1590  
      * will be returned (thus controlling how execution occurs), or null.
 1591  
      *
 1592  
      * @param mapping
 1593  
      * @param form
 1594  
      * @param request
 1595  
      * @param response
 1596  
      * @param methodToCall
 1597  
      * @return
 1598  
      * @throws Exception
 1599  
      */
 1600  
     public ActionForward promptBeforeValidation(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response, String methodToCall) throws Exception {
 1601  0
         KualiDocumentFormBase kualiDocumentFormBase = (KualiDocumentFormBase) form;
 1602  
 
 1603  
         /* callback to any pre rules check class */
 1604  0
         Class<? extends PromptBeforeValidation> promptBeforeValidationClass = getDataDictionaryService().getPromptBeforeValidationClass(kualiDocumentFormBase.getDocTypeName());
 1605  0
         if (LOG.isDebugEnabled()) {
 1606  0
             LOG.debug("PromptBeforeValidationClass: " + promptBeforeValidationClass);
 1607  
         }
 1608  0
         if (promptBeforeValidationClass != null) {
 1609  0
             PromptBeforeValidation promptBeforeValidation = promptBeforeValidationClass.newInstance();
 1610  0
             PromptBeforeValidationEvent event = new PromptBeforeValidationEvent("Pre Maint route Check", "", kualiDocumentFormBase.getDocument());
 1611  0
             boolean continueRoute = promptBeforeValidation.processPrompts(form, request, event);
 1612  0
             if (!continueRoute) {
 1613  0
                 if (event.isPerformQuestion()) {
 1614  0
                     return super.performQuestionWithoutInput(mapping, kualiDocumentFormBase, request, response, event.getQuestionId(), event.getQuestionText(), event.getQuestionType(), methodToCall, event.getQuestionContext());
 1615  
                 } else {
 1616  
                     // This error section is here to avoid a silent and very confusing failure. If the PreRule
 1617  
                     // instance returns a null for the processPreRuleChecks above, but does not set an
 1618  
                     // ActionForwardName on the event, processing will just silently fail here, and the user
 1619  
                     // will be presented with a blank frame.
 1620  
                     //
 1621  
                     // If the processPreRuleCheck() returns a false, an ActionForwardName needs to be set before hand
 1622  
                     // by the PreRule class.
 1623  0
                     ActionForward actionForward = mapping.findForward(event.getActionForwardName());
 1624  0
                     if (actionForward == null) {
 1625  0
                         throw new RuntimeException("No ActionForwardName defined on this Event, no further actions will be processed.");
 1626  
                     }
 1627  0
                     return actionForward;
 1628  
                 }
 1629  
             }
 1630  
         }
 1631  
 
 1632  0
         return null;
 1633  
     }
 1634  
 
 1635  
 
 1636  
     /**
 1637  
      * Convenience method for building authorization exceptions
 1638  
      *
 1639  
      * @param action
 1640  
      * @param document
 1641  
      */
 1642  
     protected DocumentAuthorizationException buildAuthorizationException(String action, Document document) {
 1643  0
         return new DocumentAuthorizationException(GlobalVariables.getUserSession().getPerson().getPrincipalName(), action, document.getDocumentNumber());
 1644  
     }
 1645  
 
 1646  
     protected boolean exitingDocument() {
 1647  0
             String methodCalledViaDispatch = (String) GlobalVariables.getUserSession().retrieveObject(DocumentAuthorizerBase.USER_SESSION_METHOD_TO_CALL_OBJECT_KEY);
 1648  0
         String methodCompleted = (String) GlobalVariables.getUserSession().retrieveObject(DocumentAuthorizerBase.USER_SESSION_METHOD_TO_CALL_COMPLETE_OBJECT_KEY);
 1649  0
         return StringUtils.isNotEmpty(methodCompleted) && StringUtils.isNotEmpty(methodCalledViaDispatch) && methodCompleted.startsWith(methodCalledViaDispatch);
 1650  
     }
 1651  
 
 1652  
     protected void setupDocumentExit() {
 1653  0
             String methodCalledViaDispatch = (String) GlobalVariables.getUserSession().retrieveObject(DocumentAuthorizerBase.USER_SESSION_METHOD_TO_CALL_OBJECT_KEY);
 1654  0
             if(StringUtils.isNotEmpty(methodCalledViaDispatch)) {
 1655  0
                     GlobalVariables.getUserSession().addObject(DocumentAuthorizerBase.USER_SESSION_METHOD_TO_CALL_COMPLETE_OBJECT_KEY, (Object) (methodCalledViaDispatch + DocumentAuthorizerBase.USER_SESSION_METHOD_TO_CALL_COMPLETE_MARKER));
 1656  
             }
 1657  0
     }
 1658  
 
 1659  
     /**
 1660  
      * If the given form has returnToActionList set to true, this method returns an ActionForward that should take the user back to
 1661  
      * their action list; otherwise, it returns them to the portal.
 1662  
      *
 1663  
      * @param form
 1664  
      * @return
 1665  
      */
 1666  
     protected ActionForward returnToSender(HttpServletRequest request, ActionMapping mapping, KualiDocumentFormBase form) {
 1667  
         final ActionForward dest;
 1668  0
         if (form.isReturnToActionList()) {
 1669  0
             String workflowBase = getKualiConfigurationService().getPropertyString(KRADConstants.WORKFLOW_URL_KEY);
 1670  0
             String actionListUrl = workflowBase + "/ActionList.do";
 1671  
 
 1672  0
             dest = new ActionForward(actionListUrl, true);
 1673  0
         } else if (StringUtils.isNotBlank(form.getBackLocation())) {
 1674  0
             dest = new ActionForward(form.getBackLocation(), true);
 1675  
         } else {
 1676  0
             dest = mapping.findForward(KRADConstants.MAPPING_PORTAL);
 1677  
         }
 1678  
 
 1679  0
         setupDocumentExit();
 1680  0
         return dest;
 1681  
     }
 1682  
 
 1683  
     @SuppressWarnings("unchecked")
 1684  
     protected void populateAuthorizationFields(KualiDocumentFormBase formBase) {
 1685  0
         if (formBase.isFormDocumentInitialized()) {
 1686  0
             Document document = formBase.getDocument();
 1687  0
             Person user = GlobalVariables.getUserSession().getPerson();
 1688  0
             DocumentPresentationController documentPresentationController = KRADServiceLocatorWeb
 1689  
                     .getDocumentHelperService().getDocumentPresentationController(document);
 1690  0
             DocumentAuthorizer documentAuthorizer = getDocumentHelperService().getDocumentAuthorizer(document);
 1691  0
             Set<String> documentActions = documentPresentationController.getDocumentActions(document);
 1692  0
             documentActions = documentAuthorizer.getDocumentActions(document, user, documentActions);
 1693  
 
 1694  0
             if (getDataDictionaryService().getDataDictionary().getDocumentEntry(document.getClass().getName()).getUsePessimisticLocking()) {
 1695  0
                 documentActions = getPessimisticLockService().getDocumentActions(document, user, documentActions);
 1696  
             }
 1697  
 
 1698  
             //DocumentActionFlags flags = new DocumentActionFlags();
 1699  0
             formBase.setDocumentActions(convertSetToMap(documentActions));
 1700  
 
 1701  
         }
 1702  0
     }
 1703  
 
 1704  
     protected void populateAdHocActionRequestCodes(KualiDocumentFormBase formBase) {
 1705  0
         Document document = formBase.getDocument();
 1706  0
         DocumentAuthorizer documentAuthorizer = getDocumentHelperService().getDocumentAuthorizer(document);
 1707  0
         Map<String, String> adHocActionRequestCodes = new HashMap<String, String>();
 1708  
 
 1709  0
         if (documentAuthorizer.canSendAdHocRequests(document, KEWConstants.ACTION_REQUEST_FYI_REQ, GlobalVariables.getUserSession().getPerson())) {
 1710  0
             adHocActionRequestCodes.put(KEWConstants.ACTION_REQUEST_FYI_REQ, KEWConstants.ACTION_REQUEST_FYI_REQ_LABEL);
 1711  
         }
 1712  0
         if (!document.getDocumentHeader().getWorkflowDocument().isFinal() && documentAuthorizer.canSendAdHocRequests(document, KEWConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ, GlobalVariables.getUserSession().getPerson())) {
 1713  0
             adHocActionRequestCodes.put(KEWConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ, KEWConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ_LABEL);
 1714  
         }
 1715  0
         if (!(document.getDocumentHeader().getWorkflowDocument().isApproved() || document.getDocumentHeader().getWorkflowDocument().isProcessed() || document.getDocumentHeader().getWorkflowDocument().isFinal()) && documentAuthorizer.canSendAdHocRequests(document, KEWConstants.ACTION_REQUEST_APPROVE_REQ, GlobalVariables.getUserSession().getPerson())) {
 1716  0
             adHocActionRequestCodes.put(KEWConstants.ACTION_REQUEST_APPROVE_REQ, KEWConstants.ACTION_REQUEST_APPROVE_REQ_LABEL);
 1717  
         }
 1718  
 
 1719  0
         formBase.setAdHocActionRequestCodes(adHocActionRequestCodes);
 1720  
 
 1721  0
     }
 1722  
 
 1723  
 
 1724  
     @SuppressWarnings("unchecked")
 1725  
     protected Map convertSetToMap(Set s) {
 1726  0
         Map map = new HashMap();
 1727  0
         Iterator i = s.iterator();
 1728  0
         while (i.hasNext()) {
 1729  0
             Object key = i.next();
 1730  0
             map.put(key, KRADConstants.KUALI_DEFAULT_TRUE_VALUE);
 1731  0
         }
 1732  0
         return map;
 1733  
     }
 1734  
 
 1735  
     /**
 1736  
      * @return the dataDictionaryService
 1737  
      */
 1738  
     protected DataDictionaryService getDataDictionaryService() {
 1739  0
         if (dataDictionaryService == null) {
 1740  0
             dataDictionaryService = KNSServiceLocator.getDataDictionaryService();
 1741  
         }
 1742  0
         return dataDictionaryService;
 1743  
     }
 1744  
 
 1745  
     protected DocumentHelperService getDocumentHelperService() {
 1746  0
         if (documentHelperService == null) {
 1747  0
             documentHelperService = KRADServiceLocatorWeb.getDocumentHelperService();
 1748  
         }
 1749  0
         return this.documentHelperService;
 1750  
     }
 1751  
 
 1752  
     protected DocumentService getDocumentService() {
 1753  0
         if (documentService == null) {
 1754  0
             documentService = KRADServiceLocatorWeb.getDocumentService();
 1755  
         }
 1756  0
         return this.documentService;
 1757  
     }
 1758  
 
 1759  
     protected ConfigurationService getKualiConfigurationService() {
 1760  0
         if (kualiConfigurationService == null) {
 1761  0
             kualiConfigurationService = KRADServiceLocator.getKualiConfigurationService();
 1762  
         }
 1763  0
         return this.kualiConfigurationService;
 1764  
     }
 1765  
 
 1766  
     protected ParameterService getParameterService() {
 1767  0
         if (parameterService == null) {
 1768  0
             parameterService = CoreFrameworkServiceLocator.getParameterService();
 1769  
         }
 1770  0
         return this.parameterService;
 1771  
     }
 1772  
 
 1773  
     protected PessimisticLockService getPessimisticLockService() {
 1774  0
         if (pessimisticLockService == null) {
 1775  0
             pessimisticLockService = KRADServiceLocatorWeb.getPessimisticLockService();
 1776  
         }
 1777  0
         return this.pessimisticLockService;
 1778  
     }
 1779  
 
 1780  
     protected KualiRuleService getKualiRuleService() {
 1781  0
         if (kualiRuleService == null) {
 1782  0
             kualiRuleService = KRADServiceLocatorWeb.getKualiRuleService();
 1783  
         }
 1784  0
         return this.kualiRuleService;
 1785  
     }
 1786  
 
 1787  
     protected GroupService getGroupService() {
 1788  0
         if (groupService == null) {
 1789  0
             groupService = KimApiServiceLocator.getGroupService();
 1790  
         }
 1791  0
         return this.groupService;
 1792  
     }
 1793  
 
 1794  
     protected AttachmentService getAttachmentService() {
 1795  0
         if (attachmentService == null) {
 1796  0
             attachmentService = KRADServiceLocator.getAttachmentService();
 1797  
         }
 1798  0
         return this.attachmentService;
 1799  
     }
 1800  
 
 1801  
     protected NoteService getNoteService() {
 1802  0
         if (noteService == null) {
 1803  0
             noteService = KRADServiceLocator.getNoteService();
 1804  
         }
 1805  0
         return this.noteService;
 1806  
     }
 1807  
 
 1808  
     protected BusinessObjectService getBusinessObjectService() {
 1809  0
         if (businessObjectService == null) {
 1810  0
             businessObjectService = KRADServiceLocator.getBusinessObjectService();
 1811  
         }
 1812  0
         return this.businessObjectService;
 1813  
     }
 1814  
 
 1815  
     @Override
 1816  
     protected BusinessObjectAuthorizationService getBusinessObjectAuthorizationService() {
 1817  0
         if (businessObjectAuthorizationService == null) {
 1818  0
             businessObjectAuthorizationService = KNSServiceLocator.getBusinessObjectAuthorizationService();
 1819  
         }
 1820  0
         return businessObjectAuthorizationService;
 1821  
     }
 1822  
 
 1823  
     public BusinessObjectMetaDataService getBusinessObjectMetaDataService() {
 1824  0
         if (businessObjectMetaDataService == null) {
 1825  0
             businessObjectMetaDataService = KNSServiceLocator.getBusinessObjectMetaDataService();
 1826  
         }
 1827  0
         return this.businessObjectMetaDataService;
 1828  
     }
 1829  
 
 1830  
     public EntityManagerFactory getEntityManagerFactory() {
 1831  0
         if (entityManagerFactory == null) {
 1832  0
             entityManagerFactory = KRADServiceLocator.getApplicationEntityManagerFactory();
 1833  
         }
 1834  0
         return this.entityManagerFactory;
 1835  
     }
 1836  
 
 1837  
     /**
 1838  
      * @see KualiAction#hideAllTabs(org.apache.struts.action.ActionMapping, org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
 1839  
      */
 1840  
     @Override
 1841  
     public ActionForward hideAllTabs(ActionMapping mapping, ActionForm form,
 1842  
                                      HttpServletRequest request, HttpServletResponse response)
 1843  
             throws Exception {
 1844  0
         if (form instanceof KualiDocumentFormBase) {
 1845  0
             WebUtils.reuseErrorMapFromPreviousRequest((KualiDocumentFormBase) form);
 1846  
         }
 1847  0
         return super.hideAllTabs(mapping, form, request, response);
 1848  
     }
 1849  
 
 1850  
     /**
 1851  
      * @see KualiAction#showAllTabs(org.apache.struts.action.ActionMapping, org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
 1852  
      */
 1853  
     @Override
 1854  
     public ActionForward showAllTabs(ActionMapping mapping, ActionForm form,
 1855  
                                      HttpServletRequest request, HttpServletResponse response)
 1856  
             throws Exception {
 1857  0
         if (form instanceof KualiDocumentFormBase) {
 1858  0
             WebUtils.reuseErrorMapFromPreviousRequest((KualiDocumentFormBase) form);
 1859  
         }
 1860  0
         return super.showAllTabs(mapping, form, request, response);
 1861  
     }
 1862  
 
 1863  
     /**
 1864  
      * @see KualiAction#toggleTab(org.apache.struts.action.ActionMapping, org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
 1865  
      */
 1866  
     @Override
 1867  
     public ActionForward toggleTab(ActionMapping mapping, ActionForm form,
 1868  
                                    HttpServletRequest request, HttpServletResponse response)
 1869  
             throws Exception {
 1870  0
         if (form instanceof KualiDocumentFormBase) {
 1871  0
             WebUtils.reuseErrorMapFromPreviousRequest((KualiDocumentFormBase) form);
 1872  
         }
 1873  0
         return super.toggleTab(mapping, form, request, response);
 1874  
     }
 1875  
 
 1876  
     @Override
 1877  
     protected void doProcessingAfterPost(KualiForm form, HttpServletRequest request) {
 1878  0
         super.doProcessingAfterPost(form, request);
 1879  0
         if (form instanceof KualiDocumentFormBase) {
 1880  0
             Document document = ((KualiDocumentFormBase) form).getDocument();
 1881  
 
 1882  0
             getBusinessObjectService().linkUserFields(document);
 1883  
         }
 1884  0
     }
 1885  
 }
 1886