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