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