Coverage Report - org.kuali.rice.kns.web.struts.action.KualiAction
 
Classes in this File Line Coverage Branch Coverage Complexity
KualiAction
0%
0/411
0%
0/224
4.316
 
 1  
 /**
 2  
  * Copyright 2005-2011 The Kuali Foundation
 3  
  *
 4  
  * Licensed under the Educational Community License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  * http://www.opensource.org/licenses/ecl2.php
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  */
 16  
 package org.kuali.rice.kns.web.struts.action;
 17  
 
 18  
 import java.util.Arrays;
 19  
 import java.util.Enumeration;
 20  
 import java.util.HashMap;
 21  
 import java.util.HashSet;
 22  
 import java.util.Map;
 23  
 import java.util.Properties;
 24  
 import java.util.Set;
 25  
 
 26  
 import javax.servlet.http.HttpServletRequest;
 27  
 import javax.servlet.http.HttpServletResponse;
 28  
 
 29  
 import org.apache.commons.lang.ObjectUtils;
 30  
 import org.apache.commons.lang.StringUtils;
 31  
 import org.apache.struts.action.ActionForm;
 32  
 import org.apache.struts.action.ActionForward;
 33  
 import org.apache.struts.action.ActionMapping;
 34  
 import org.apache.struts.actions.DispatchAction;
 35  
 import org.kuali.rice.core.api.CoreApiServiceLocator;
 36  
 import org.kuali.rice.core.api.encryption.EncryptionService;
 37  
 import org.kuali.rice.core.api.util.RiceConstants;
 38  
 import org.kuali.rice.core.framework.parameter.ParameterService;
 39  
 import org.kuali.rice.core.framework.services.CoreFrameworkServiceLocator;
 40  
 import org.kuali.rice.kim.api.KimConstants;
 41  
 import org.kuali.rice.kim.api.services.KimApiServiceLocator;
 42  
 import org.kuali.rice.kns.lookup.LookupUtils;
 43  
 import org.kuali.rice.kns.service.BusinessObjectAuthorizationService;
 44  
 import org.kuali.rice.kns.service.KNSServiceLocator;
 45  
 import org.kuali.rice.kns.util.KNSGlobalVariables;
 46  
 import org.kuali.rice.kns.util.WebUtils;
 47  
 import org.kuali.rice.kns.web.struts.form.KualiDocumentFormBase;
 48  
 import org.kuali.rice.kns.web.struts.form.KualiForm;
 49  
 import org.kuali.rice.kns.web.struts.form.LookupForm;
 50  
 import org.kuali.rice.kns.web.struts.form.pojo.PojoForm;
 51  
 import org.kuali.rice.kns.web.struts.form.pojo.PojoFormBase;
 52  
 import org.kuali.rice.krad.bo.BusinessObject;
 53  
 import org.kuali.rice.krad.document.authorization.DocumentAuthorizerBase;
 54  
 import org.kuali.rice.krad.exception.AuthorizationException;
 55  
 import org.kuali.rice.krad.service.KRADServiceLocator;
 56  
 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
 57  
 import org.kuali.rice.krad.service.KualiModuleService;
 58  
 import org.kuali.rice.krad.service.ModuleService;
 59  
 import org.kuali.rice.krad.util.GlobalVariables;
 60  
 import org.kuali.rice.krad.util.KRADConstants;
 61  
 import org.kuali.rice.krad.util.KRADUtils;
 62  
 import org.kuali.rice.krad.util.UrlFactory;
 63  
 
 64  
 /**
 65  
  * <p>The base {@link org.apache.struts.action.Action} class for all KNS-based Actions. Extends from the standard 
 66  
  * {@link org.apache.struts.actions.DispatchAction} which allows for a <i>methodToCall</i> request parameter to
 67  
  * be used to indicate which method to invoke.</p>
 68  
  * 
 69  
  * <p>This Action overrides #execute to set methodToCall for image submits.  Also performs other setup
 70  
  * required for KNS framework calls.</p>
 71  
  *
 72  
  * @author Kuali Rice Team (rice.collab@kuali.org)
 73  
  */
 74  0
 public abstract class KualiAction extends DispatchAction {
 75  0
     private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(KualiAction.class);
 76  
 
 77  0
     private static KualiModuleService kualiModuleService = null;
 78  0
     private static BusinessObjectAuthorizationService businessObjectAuthorizationService = null;
 79  0
     private static EncryptionService encryptionService = null;
 80  0
     private static Boolean OUTPUT_ENCRYPTION_WARNING = null;
 81  0
     private static String applicationBaseUrl = null;
 82  
     
 83  0
     private Set<String> methodToCallsToNotCheckAuthorization = new HashSet<String>();
 84  
     
 85  
     {
 86  0
             methodToCallsToNotCheckAuthorization.add( "performLookup" );
 87  0
             methodToCallsToNotCheckAuthorization.add( "performQuestion" );
 88  0
             methodToCallsToNotCheckAuthorization.add( "performQuestionWithInput" );
 89  0
             methodToCallsToNotCheckAuthorization.add( "performQuestionWithInputAgainBecauseOfErrors" );
 90  0
             methodToCallsToNotCheckAuthorization.add( "performQuestionWithoutInput" );
 91  0
             methodToCallsToNotCheckAuthorization.add( "performWorkgroupLookup" );
 92  0
     }
 93  
     
 94  
     /**
 95  
      * Entry point to all actions.
 96  
      *
 97  
      * NOTE: No need to hook into execute for handling framework setup anymore. Just implement the methodToCall for the framework
 98  
      * setup, Constants.METHOD_REQUEST_PARAMETER will contain the full parameter, which can be sub stringed for getting framework
 99  
      * parameters.
 100  
      *
 101  
      * @see org.apache.struts.action.Action#execute(org.apache.struts.action.ActionMapping, org.apache.struts.action.ActionForm,
 102  
      *      javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
 103  
      */
 104  
     public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 105  0
         ActionForward returnForward = null;
 106  
 
 107  0
         String methodToCall = findMethodToCall(form, request);
 108  
         
 109  0
         if(isModuleLocked(form, methodToCall, request)) {
 110  0
                 return mapping.findForward(RiceConstants.MODULE_LOCKED_MAPPING);
 111  
         }
 112  
         
 113  0
         if (form instanceof KualiForm && StringUtils.isNotEmpty(((KualiForm) form).getMethodToCall())) {
 114  0
             if (StringUtils.isNotBlank(getImageContext(request, KRADConstants.ANCHOR))) {
 115  0
                 ((KualiForm) form).setAnchor(getImageContext(request, KRADConstants.ANCHOR));
 116  
             }
 117  0
             else if (StringUtils.isNotBlank(request.getParameter(KRADConstants.ANCHOR))) {
 118  0
                 ((KualiForm) form).setAnchor(request.getParameter(KRADConstants.ANCHOR));
 119  
             }
 120  
             else {
 121  0
                 ((KualiForm) form).setAnchor(KRADConstants.ANCHOR_TOP_OF_FORM);
 122  
             }
 123  
         }
 124  
         // if found methodToCall, pass control to that method, else return the basic forward
 125  0
         if (StringUtils.isNotBlank(methodToCall)) {
 126  0
                 if ( LOG.isDebugEnabled() ) {
 127  0
                         LOG.debug("methodToCall: '" + methodToCall+"'");
 128  
                 }
 129  0
             returnForward = dispatchMethod(mapping, form, request, response, methodToCall);
 130  
         }
 131  
         else {
 132  0
             returnForward = defaultDispatch(mapping, form, request, response);
 133  
         }
 134  
 
 135  
         // make sure the user can do what they're trying to according to the module that owns the functionality
 136  0
         if ( !methodToCallsToNotCheckAuthorization.contains(methodToCall) ) {
 137  0
                 if ( LOG.isDebugEnabled() ) {
 138  0
                         LOG.debug( "'" + methodToCall + "' not in set of excempt methods: " + methodToCallsToNotCheckAuthorization);
 139  
                 }
 140  0
                 checkAuthorization(form, methodToCall);
 141  
         } else {
 142  0
                 if ( LOG.isDebugEnabled() ) {
 143  0
                         LOG.debug("'" + methodToCall + "' is exempt from auth checks." );
 144  
                 }
 145  
         }
 146  
 
 147  
         // Add the ActionForm to GlobalVariables
 148  
         // This will allow developers to retrieve both the Document and any request parameters that are not
 149  
         // part of the Form and make them available in ValueFinder classes and other places where they are needed.
 150  0
         if(KNSGlobalVariables.getKualiForm() == null) {
 151  0
                 KNSGlobalVariables.setKualiForm((KualiForm)form);
 152  
         }
 153  
 
 154  0
         return returnForward;
 155  
     }
 156  
     
 157  
     /**
 158  
      * When no methodToCall is specified, the defaultDispatch method is invoked.  Default implementation
 159  
      * returns the "basic" ActionForward.
 160  
      */
 161  
     protected ActionForward defaultDispatch(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 162  0
             return mapping.findForward(RiceConstants.MAPPING_BASIC);
 163  
     }
 164  
 
 165  
     @Override
 166  
     protected ActionForward dispatchMethod(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response, String methodToCall) throws Exception {
 167  0
         GlobalVariables.getUserSession().addObject(DocumentAuthorizerBase.USER_SESSION_METHOD_TO_CALL_OBJECT_KEY, methodToCall);
 168  0
         return super.dispatchMethod(mapping, form, request, response, methodToCall);
 169  
     }
 170  
     
 171  
     protected String findMethodToCall(ActionForm form, HttpServletRequest request) throws Exception {
 172  
         String methodToCall;
 173  0
         if (form instanceof KualiForm && StringUtils.isNotEmpty(((KualiForm) form).getMethodToCall())) {
 174  0
             methodToCall = ((KualiForm) form).getMethodToCall();
 175  
         }
 176  
         else {
 177  
             // call utility method to parse the methodToCall from the request.
 178  0
             methodToCall = WebUtils.parseMethodToCall(form, request);
 179  
         }
 180  0
         return methodToCall;
 181  
     }
 182  
 
 183  
     /**
 184  
      * Toggles the tab state in the ui
 185  
      *
 186  
      * @param mapping
 187  
      * @param form
 188  
      * @param request
 189  
      * @param response
 190  
      * @return
 191  
      * @throws Exception
 192  
      */
 193  
     public ActionForward toggleTab(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 194  0
         KualiForm kualiForm = (KualiForm) form;
 195  0
         String tabToToggle = getTabToToggle(request);
 196  0
         if (StringUtils.isNotBlank(tabToToggle)) {
 197  0
             if (kualiForm.getTabState(tabToToggle).equals("OPEN")) {
 198  0
                     kualiForm.getTabStates().remove(tabToToggle);
 199  0
                     kualiForm.getTabStates().put(tabToToggle, "CLOSE");
 200  
             }
 201  
             else {
 202  0
                     kualiForm.getTabStates().remove(tabToToggle);
 203  0
                     kualiForm.getTabStates().put(tabToToggle, "OPEN");
 204  
             }
 205  
         }
 206  
 
 207  0
         doProcessingAfterPost( kualiForm, request );
 208  0
         return mapping.findForward(RiceConstants.MAPPING_BASIC);
 209  
     }
 210  
 
 211  
     /**
 212  
      * Toggles all tabs to open
 213  
      *
 214  
      * @param mapping
 215  
      * @param form
 216  
      * @param request
 217  
      * @param response
 218  
      * @return
 219  
      * @throws Exception
 220  
      */
 221  
     public ActionForward showAllTabs(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 222  0
             return this.doTabOpenOrClose(mapping, form, request, response, true);
 223  
     }
 224  
 
 225  
     /**
 226  
      * Toggles all tabs to closed
 227  
      *
 228  
      * @param mapping
 229  
      * @param form
 230  
      * @param request
 231  
      * @param response
 232  
      * @return
 233  
      * @throws Exception
 234  
      */
 235  
     public ActionForward hideAllTabs(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 236  0
         return this.doTabOpenOrClose(mapping, form, request, response, false);
 237  
     }
 238  
     
 239  
     /**
 240  
      * 
 241  
      * Toggles all tabs to open of closed depending on the boolean flag.
 242  
      * 
 243  
      * @param mapping the mapping
 244  
      * @param form the form
 245  
      * @param request the request
 246  
      * @param response the response
 247  
      * @param open whether to open of close the tabs
 248  
      * @return the action forward
 249  
      */
 250  
     private ActionForward doTabOpenOrClose(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response, boolean open) {
 251  0
         KualiForm kualiForm = (KualiForm) form;
 252  
 
 253  0
         Map<String, String> tabStates = kualiForm.getTabStates();
 254  0
         Map<String, String> newTabStates = new HashMap<String, String>();
 255  0
         for (String tabKey: tabStates.keySet()) {
 256  0
                 newTabStates.put(tabKey, open ? "OPEN" : "CLOSE");
 257  
         }
 258  0
         kualiForm.setTabStates(newTabStates);
 259  0
         doProcessingAfterPost( kualiForm, request );
 260  0
         return mapping.findForward(RiceConstants.MAPPING_BASIC);
 261  
     }
 262  
 
 263  
     /**
 264  
      * Default refresh method. Called from returning frameworks.
 265  
      *
 266  
      * @param mapping
 267  
      * @param form
 268  
      * @param request
 269  
      * @param response
 270  
      * @return
 271  
      * @throws Exception
 272  
      */
 273  
     public ActionForward refresh(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 274  0
         return mapping.findForward(RiceConstants.MAPPING_BASIC);
 275  
     }
 276  
 
 277  
 
 278  
     /**
 279  
      * Parses the method to call attribute to pick off the line number which should be deleted.
 280  
      *
 281  
      * @param request
 282  
      * @return
 283  
      */
 284  
     protected int getLineToDelete(HttpServletRequest request) {
 285  0
         return getSelectedLine(request);
 286  
     }
 287  
 
 288  
     /**
 289  
      * Parses the method to call attribute to pick off the line number which should have an action performed on it.
 290  
      *
 291  
      * @param request
 292  
      * @return
 293  
      */
 294  
     protected int getSelectedLine(HttpServletRequest request) {
 295  0
         int selectedLine = -1;
 296  0
         String parameterName = (String) request.getAttribute(KRADConstants.METHOD_TO_CALL_ATTRIBUTE);
 297  0
         if (StringUtils.isNotBlank(parameterName)) {
 298  0
             String lineNumber = StringUtils.substringBetween(parameterName, ".line", ".");
 299  0
             selectedLine = Integer.parseInt(lineNumber);
 300  
         }
 301  
 
 302  0
         return selectedLine;
 303  
     }
 304  
 
 305  
     /**
 306  
      * Determines which tab was requested to be toggled
 307  
      *
 308  
      * @param request
 309  
      * @return
 310  
      */
 311  
     protected String getTabToToggle(HttpServletRequest request) {
 312  0
         String tabToToggle = "";
 313  0
         String parameterName = (String) request.getAttribute(KRADConstants.METHOD_TO_CALL_ATTRIBUTE);
 314  0
         if (StringUtils.isNotBlank(parameterName)) {
 315  0
             tabToToggle = StringUtils.substringBetween(parameterName, ".tab", ".");
 316  
         }
 317  
 
 318  0
         return tabToToggle;
 319  
     }
 320  
 
 321  
     /**
 322  
      * Retrieves the header tab to navigate to.
 323  
      *
 324  
      * @param request
 325  
      * @return
 326  
      */
 327  
     protected String getHeaderTabNavigateTo(HttpServletRequest request) {
 328  0
         String headerTabNavigateTo = RiceConstants.MAPPING_BASIC;
 329  0
         String imageContext = getImageContext(request, KRADConstants.NAVIGATE_TO);
 330  0
         if (StringUtils.isNotBlank(imageContext)) {
 331  0
             headerTabNavigateTo = imageContext;
 332  
         }
 333  0
         return headerTabNavigateTo;
 334  
     }
 335  
 
 336  
     /**
 337  
      * Retrieves the header tab dispatch.
 338  
      *
 339  
      * @param request
 340  
      * @return
 341  
      */
 342  
     protected String getHeaderTabDispatch(HttpServletRequest request) {
 343  0
         String headerTabDispatch = null;
 344  0
         String imageContext = getImageContext(request, KRADConstants.HEADER_DISPATCH);
 345  0
         if (StringUtils.isNotBlank(imageContext)) {
 346  0
             headerTabDispatch = imageContext;
 347  
         }
 348  
         else {
 349  
             // In some cases it might be in request params instead
 350  0
             headerTabDispatch = request.getParameter(KRADConstants.METHOD_TO_CALL_ATTRIBUTE);
 351  
         }
 352  0
         return headerTabDispatch;
 353  
     }
 354  
 
 355  
     /**
 356  
      * Retrieves the image context
 357  
      *
 358  
      * @param request
 359  
      * @param contextKey
 360  
      * @return
 361  
      */
 362  
     protected String getImageContext(HttpServletRequest request, String contextKey) {
 363  0
         String imageContext = "";
 364  0
         String parameterName = (String) request.getAttribute(KRADConstants.METHOD_TO_CALL_ATTRIBUTE);
 365  0
         if (StringUtils.isBlank(parameterName)) {
 366  0
             parameterName = request.getParameter("methodToCallPath");
 367  
         }
 368  0
         if (StringUtils.isNotBlank(parameterName)) {
 369  0
             imageContext = StringUtils.substringBetween(parameterName, contextKey, ".");
 370  
         }
 371  0
         return imageContext;
 372  
     }
 373  
 
 374  
     protected String getReturnLocation(HttpServletRequest request, ActionMapping mapping) {
 375  0
             String mappingPath = mapping.getPath();
 376  0
             String basePath = getApplicationBaseUrl();
 377  0
         return basePath + ("/lookup".equals(mappingPath) || "/maintenance".equals(mappingPath) || "/multipleValueLookup".equals(mappingPath) ? "/kr" : "") + mappingPath + ".do";
 378  
     }
 379  
 
 380  
     /**
 381  
      * Retrieves the value of a parameter to be passed into the lookup or inquiry frameworks.  The default implementation of this method will attempt to look
 382  
      * in the request to determine wheter the appropriate value exists as a request parameter.  If not, it will attempt to look through the form object to find
 383  
      * the property.
 384  
      * 
 385  
      * @param boClass a class implementing boClass, representing the BO that will be looked up
 386  
      * @param parameterName the name of the parameter
 387  
      * @param parameterValuePropertyName the property (relative to the form object) where the value to be passed into the lookup/inquiry may be found
 388  
      * @param form
 389  
      * @param request
 390  
      * @return
 391  
      */
 392  
     protected String retrieveLookupParameterValue(Class<? extends BusinessObject> boClass, String parameterName, String parameterValuePropertyName, ActionForm form, HttpServletRequest request) throws Exception {
 393  
             String value;
 394  0
             if (StringUtils.contains(parameterValuePropertyName, "'")) {
 395  0
                     value = StringUtils.replace(parameterValuePropertyName, "'", "");
 396  
             }
 397  0
             else if (request.getParameterMap().containsKey(parameterValuePropertyName)) {
 398  0
                     value = request.getParameter(parameterValuePropertyName);
 399  
             }
 400  
             else {
 401  0
                     if (form instanceof KualiForm) {
 402  0
                             value = ((KualiForm) form).retrieveFormValueForLookupInquiryParameters(parameterName, parameterValuePropertyName);
 403  
                     } else {
 404  0
                             if (LOG.isDebugEnabled()) {
 405  0
                                     LOG.debug("Unable to retrieve lookup/inquiry parameter value for parameter name " + parameterName + " parameter value property " + parameterValuePropertyName);
 406  
                             }
 407  0
                             value = null;
 408  
                     }
 409  
             }
 410  
             
 411  0
             if (value != null && boClass != null && getBusinessObjectAuthorizationService().attributeValueNeedsToBeEncryptedOnFormsAndLinks(boClass, parameterName)) {
 412  0
                     value = getEncryptionService().encrypt(value) + EncryptionService.ENCRYPTION_POST_PREFIX;
 413  
             }
 414  0
             return value;
 415  
     }
 416  
     
 417  
     /**
 418  
      * Takes care of storing the action form in the User session and forwarding to the lookup action.
 419  
      *
 420  
      * @param mapping
 421  
      * @param form
 422  
      * @param request
 423  
      * @param response
 424  
      * @return
 425  
      * @throws Exception
 426  
      */
 427  
     @SuppressWarnings("unchecked")
 428  
         public ActionForward performLookup(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 429  
         // parse out the important strings from our methodToCall parameter
 430  0
         String fullParameter = (String) request.getAttribute(KRADConstants.METHOD_TO_CALL_ATTRIBUTE);
 431  0
         validateLookupInquiryFullParameter(request, form, fullParameter);
 432  
         
 433  0
         KualiForm kualiForm = (KualiForm) form;
 434  
         
 435  
         // when we return from the lookup, our next request's method to call is going to be refresh
 436  0
         kualiForm.registerEditableProperty(KRADConstants.DISPATCH_REQUEST_PARAMETER);
 437  
         
 438  
         // parse out the baseLookupUrl if there is one
 439  0
         String baseLookupUrl = StringUtils.substringBetween(fullParameter, KRADConstants.METHOD_TO_CALL_PARM14_LEFT_DEL, KRADConstants.METHOD_TO_CALL_PARM14_RIGHT_DEL);
 440  
         
 441  
         // parse out business object class name for lookup
 442  0
         String boClassName = StringUtils.substringBetween(fullParameter, KRADConstants.METHOD_TO_CALL_BOPARM_LEFT_DEL, KRADConstants.METHOD_TO_CALL_BOPARM_RIGHT_DEL);
 443  0
         if (StringUtils.isBlank(boClassName)) {
 444  0
             throw new RuntimeException("Illegal call to perform lookup, no business object class name specified.");
 445  
         }
 446  0
         Class boClass = null;
 447  
                 try{
 448  0
                         boClass = Class.forName(boClassName);
 449  0
                 } catch(ClassNotFoundException cnfex){
 450  0
             throw new IllegalArgumentException("The classname (" + boClassName + ") does not represent a valid class which this application understands.");
 451  0
                 }
 452  
                 
 453  
         // build the parameters for the lookup url
 454  0
         Properties parameters = new Properties();
 455  0
         String conversionFields = StringUtils.substringBetween(fullParameter, KRADConstants.METHOD_TO_CALL_PARM1_LEFT_DEL, KRADConstants.METHOD_TO_CALL_PARM1_RIGHT_DEL);
 456  0
         if (StringUtils.isNotBlank(conversionFields)) {
 457  0
             parameters.put(KRADConstants.CONVERSION_FIELDS_PARAMETER, conversionFields);
 458  
             
 459  
             // register each of the destination parameters of the field conversion string as editable
 460  0
             String[] fieldConversions = conversionFields.split(KRADConstants.FIELD_CONVERSIONS_SEPARATOR);
 461  0
             for (String fieldConversion : fieldConversions) {
 462  0
                     String destination = fieldConversion.split(KRADConstants.FIELD_CONVERSION_PAIR_SEPARATOR)[1];
 463  0
                     kualiForm.registerEditableProperty(destination);
 464  
             }
 465  
         }
 466  
 
 467  
         // pass values from form that should be pre-populated on lookup search
 468  0
         String parameterFields = StringUtils.substringBetween(fullParameter, KRADConstants.METHOD_TO_CALL_PARM2_LEFT_DEL, KRADConstants.METHOD_TO_CALL_PARM2_RIGHT_DEL);
 469  0
         if ( LOG.isDebugEnabled() ) {
 470  0
             LOG.debug( "fullParameter: " + fullParameter );
 471  0
             LOG.debug( "parameterFields: " + parameterFields );
 472  
         }
 473  0
         if (StringUtils.isNotBlank(parameterFields)) {
 474  0
             String[] lookupParams = parameterFields.split(KRADConstants.FIELD_CONVERSIONS_SEPARATOR);
 475  0
             if ( LOG.isDebugEnabled() ) {
 476  0
                      LOG.debug( "lookupParams: " + Arrays.toString(lookupParams) ); 
 477  
             }
 478  0
             for (String lookupParam : lookupParams) {
 479  0
                     String[] keyValue = lookupParam.split(KRADConstants.FIELD_CONVERSION_PAIR_SEPARATOR);
 480  0
                 if (keyValue.length != 2) {
 481  0
                                         throw new RuntimeException("malformed field conversion pair: " + Arrays.toString(keyValue));
 482  
                                 } 
 483  
 
 484  0
                 String lookupParameterValue = retrieveLookupParameterValue(boClass, keyValue[1], keyValue[0], form, request);
 485  0
                 if (StringUtils.isNotBlank(lookupParameterValue)) {
 486  0
                         parameters.put(keyValue[1], lookupParameterValue);
 487  
                 }
 488  
 
 489  0
                 if ( LOG.isDebugEnabled() ) {
 490  0
                     LOG.debug( "keyValue[0]: " + keyValue[0] );
 491  0
                     LOG.debug( "keyValue[1]: " + keyValue[1] );
 492  
                 }
 493  
             }
 494  
         }
 495  
 
 496  
         // pass values from form that should be read-Only on lookup search
 497  0
         String readOnlyFields = StringUtils.substringBetween(fullParameter, KRADConstants.METHOD_TO_CALL_PARM8_LEFT_DEL, KRADConstants.METHOD_TO_CALL_PARM8_RIGHT_DEL);
 498  0
         if (StringUtils.isNotBlank(readOnlyFields)) {
 499  0
             parameters.put(KRADConstants.LOOKUP_READ_ONLY_FIELDS, readOnlyFields);
 500  
         }
 501  
 
 502  0
         if ( LOG.isDebugEnabled() ) {
 503  0
             LOG.debug( "fullParameter: " + fullParameter );
 504  0
             LOG.debug( "readOnlyFields: " + readOnlyFields );
 505  
         }
 506  
 
 507  
         // grab whether or not the "return value" link should be hidden or not
 508  0
         String hideReturnLink = StringUtils.substringBetween(fullParameter, KRADConstants.METHOD_TO_CALL_PARM3_LEFT_DEL, KRADConstants.METHOD_TO_CALL_PARM3_RIGHT_DEL);
 509  0
         if (StringUtils.isNotBlank(hideReturnLink)) {
 510  0
             parameters.put(KRADConstants.HIDE_LOOKUP_RETURN_LINK, hideReturnLink);
 511  
         }
 512  
 
 513  
         // add the optional extra button source and parameters string
 514  0
         String extraButtonSource = StringUtils.substringBetween(fullParameter, KRADConstants.METHOD_TO_CALL_PARM4_LEFT_DEL, KRADConstants.METHOD_TO_CALL_PARM4_RIGHT_DEL);
 515  0
         if (StringUtils.isNotBlank(extraButtonSource)) {
 516  0
             parameters.put(KRADConstants.EXTRA_BUTTON_SOURCE, extraButtonSource);
 517  
         }
 518  0
         String extraButtonParams = StringUtils.substringBetween(fullParameter, KRADConstants.METHOD_TO_CALL_PARM5_LEFT_DEL, KRADConstants.METHOD_TO_CALL_PARM5_RIGHT_DEL);
 519  0
         if (StringUtils.isNotBlank(extraButtonParams)) {
 520  0
             parameters.put(KRADConstants.EXTRA_BUTTON_PARAMS, extraButtonParams);
 521  
         }
 522  
 
 523  0
         String lookupAction = KRADConstants.LOOKUP_ACTION;
 524  
 
 525  
         // is this a multi-value return?
 526  0
         boolean isMultipleValue = false;
 527  0
         String multipleValues = StringUtils.substringBetween(fullParameter, KRADConstants.METHOD_TO_CALL_PARM6_LEFT_DEL, KRADConstants.METHOD_TO_CALL_PARM6_RIGHT_DEL);
 528  0
         if ((new Boolean(multipleValues).booleanValue())) {
 529  0
             parameters.put(KRADConstants.MULTIPLE_VALUE, multipleValues);
 530  0
             lookupAction = KRADConstants.MULTIPLE_VALUE_LOOKUP_ACTION;
 531  0
             isMultipleValue = true;
 532  
         }
 533  
 
 534  
         // the name of the collection being looked up (primarily for multivalue lookups
 535  0
         String lookedUpCollectionName = StringUtils.substringBetween(fullParameter, KRADConstants.METHOD_TO_CALL_PARM11_LEFT_DEL, KRADConstants.METHOD_TO_CALL_PARM11_RIGHT_DEL);
 536  0
         if (StringUtils.isNotBlank(lookedUpCollectionName)) {
 537  0
             parameters.put(KRADConstants.LOOKED_UP_COLLECTION_NAME, lookedUpCollectionName);
 538  
         }
 539  
 
 540  
         // grab whether or not the "supress actions" column should be hidden or not
 541  0
         String supressActions = StringUtils.substringBetween(fullParameter, KRADConstants.METHOD_TO_CALL_PARM7_LEFT_DEL, KRADConstants.METHOD_TO_CALL_PARM7_RIGHT_DEL);
 542  0
         if (StringUtils.isNotBlank(supressActions)) {
 543  0
             parameters.put(KRADConstants.SUPPRESS_ACTIONS, supressActions);
 544  
         }
 545  
 
 546  
         // grab the references that should be refreshed upon returning from the lookup
 547  0
         String referencesToRefresh = StringUtils.substringBetween(fullParameter, KRADConstants.METHOD_TO_CALL_PARM10_LEFT_DEL, KRADConstants.METHOD_TO_CALL_PARM10_RIGHT_DEL);
 548  0
         if (StringUtils.isNotBlank(referencesToRefresh)) {
 549  0
             parameters.put(KRADConstants.REFERENCES_TO_REFRESH, referencesToRefresh);
 550  
         }
 551  
 
 552  
         // anchor, if it exists
 553  0
         if (form instanceof KualiForm && StringUtils.isNotEmpty(((KualiForm) form).getAnchor())) {
 554  0
             parameters.put(KRADConstants.LOOKUP_ANCHOR, ((KualiForm) form).getAnchor());
 555  
         }
 556  
 
 557  
         // now add required parameters
 558  0
         parameters.put(KRADConstants.DISPATCH_REQUEST_PARAMETER, "start");
 559  
 
 560  
         // pass value from form that shows if autoSearch is desired for lookup search
 561  0
         String autoSearch = StringUtils.substringBetween(fullParameter, KRADConstants.METHOD_TO_CALL_PARM9_LEFT_DEL, KRADConstants.METHOD_TO_CALL_PARM9_RIGHT_DEL);
 562  
 
 563  0
         if (StringUtils.isNotBlank(autoSearch)) {
 564  0
             parameters.put(KRADConstants.LOOKUP_AUTO_SEARCH, autoSearch);
 565  0
             if ("YES".equalsIgnoreCase(autoSearch)){
 566  0
                 parameters.put(KRADConstants.DISPATCH_REQUEST_PARAMETER, "search");
 567  
             }
 568  
         }
 569  
 
 570  0
         parameters.put(KRADConstants.DOC_FORM_KEY, GlobalVariables.getUserSession().addObjectWithGeneratedKey(form));
 571  0
         parameters.put(KRADConstants.BUSINESS_OBJECT_CLASS_ATTRIBUTE, boClassName);
 572  
 
 573  0
         parameters.put(KRADConstants.RETURN_LOCATION_PARAMETER, getReturnLocation(request, mapping));
 574  
         
 575  0
             if (form instanceof KualiDocumentFormBase) {
 576  0
                     String docNum = ((KualiDocumentFormBase) form).getDocument().getDocumentNumber();
 577  0
                         if(docNum != null){
 578  0
                                 parameters.put(KRADConstants.DOC_NUM, docNum);
 579  
                         }
 580  0
                 }else if(form instanceof LookupForm){
 581  0
                         String docNum = ((LookupForm) form).getDocNum();
 582  0
                         if(docNum != null){
 583  0
                                 parameters.put(KRADConstants.DOC_NUM, ((LookupForm) form).getDocNum());
 584  
                         }
 585  
             }
 586  
 
 587  0
             if (boClass != null) {
 588  0
                     ModuleService responsibleModuleService = getKualiModuleService().getResponsibleModuleService(boClass);
 589  0
                     if(responsibleModuleService!=null && responsibleModuleService.isExternalizable(boClass)){
 590  0
                             Map<String, String> parameterMap = new HashMap<String, String>();
 591  0
                             Enumeration<Object> e = parameters.keys();
 592  0
                             while (e.hasMoreElements()) {
 593  0
                                     String paramName = (String) e.nextElement();
 594  0
                                     parameterMap.put(paramName, parameters.getProperty(paramName));
 595  0
                             }
 596  0
                             return new ActionForward(responsibleModuleService.getExternalizableBusinessObjectLookupUrl(boClass, parameterMap), true);
 597  
                     }
 598  
             }
 599  
                 
 600  0
             if (StringUtils.isBlank(baseLookupUrl)) {
 601  0
                     baseLookupUrl = getApplicationBaseUrl() + "/kr/" + lookupAction;
 602  
             } else {
 603  0
                     if (isMultipleValue) {
 604  0
                             LookupUtils.transformLookupUrlToMultiple(baseLookupUrl);
 605  
                     }
 606  
             }
 607  0
             String lookupUrl = UrlFactory.parameterizeUrl(baseLookupUrl, parameters);
 608  0
         return new ActionForward(lookupUrl, true);
 609  
     }
 610  
 
 611  
     protected void validateLookupInquiryFullParameter(HttpServletRequest request, ActionForm form, String fullParameter){
 612  0
             PojoFormBase pojoFormBase = (PojoFormBase) form;
 613  0
         if(WebUtils.isFormSessionDocument((PojoFormBase) form)){
 614  0
                 if(!pojoFormBase.isPropertyEditable(fullParameter)) {
 615  0
                         throw new RuntimeException("The methodToCallAttribute is not registered as an editable property.");
 616  
                 }
 617  
         }
 618  0
     }
 619  
     
 620  
     @SuppressWarnings("unchecked")
 621  
         public ActionForward performInquiry(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 622  
         // parse out the important strings from our methodToCall parameter
 623  0
         String fullParameter = (String) request.getAttribute(KRADConstants.METHOD_TO_CALL_ATTRIBUTE);
 624  0
         validateLookupInquiryFullParameter(request, form, fullParameter);
 625  
         
 626  
         // when javascript is disabled, the inquiry will appear in the same window as the document.  when we close the inquiry, 
 627  
         // our next request's method to call is going to be refresh
 628  0
         KualiForm kualiForm = (KualiForm) form;
 629  0
         kualiForm.registerEditableProperty(KRADConstants.DISPATCH_REQUEST_PARAMETER);
 630  
         
 631  
         // parse out business object class name for lookup
 632  0
         String boClassName = StringUtils.substringBetween(fullParameter, KRADConstants.METHOD_TO_CALL_BOPARM_LEFT_DEL, KRADConstants.METHOD_TO_CALL_BOPARM_RIGHT_DEL);
 633  0
         if (StringUtils.isBlank(boClassName)) {
 634  0
             throw new RuntimeException("Illegal call to perform inquiry, no business object class name specified.");
 635  
         }
 636  
 
 637  
         // build the parameters for the inquiry url
 638  0
         Properties parameters = new Properties();
 639  0
         parameters.put(KRADConstants.BUSINESS_OBJECT_CLASS_ATTRIBUTE, boClassName);
 640  
 
 641  0
         parameters.put(KRADConstants.RETURN_LOCATION_PARAMETER, getReturnLocation(request, mapping));
 642  
 
 643  
         // pass values from form that should be pre-populated on inquiry
 644  0
         String parameterFields = StringUtils.substringBetween(fullParameter, KRADConstants.METHOD_TO_CALL_PARM2_LEFT_DEL, KRADConstants.METHOD_TO_CALL_PARM2_RIGHT_DEL);
 645  0
         if ( LOG.isDebugEnabled() ) {
 646  0
             LOG.debug( "fullParameter: " + fullParameter );
 647  0
             LOG.debug( "parameterFields: " + parameterFields );
 648  
         }
 649  0
         if (StringUtils.isNotBlank(parameterFields)) {
 650  
             // TODO : create a method for this to be used by both lookup & inquiry ?
 651  0
             String[] inquiryParams = parameterFields.split(KRADConstants.FIELD_CONVERSIONS_SEPARATOR);
 652  0
             if ( LOG.isDebugEnabled() ) {
 653  0
                 LOG.debug( "inquiryParams: " + inquiryParams );
 654  
             }
 655  0
             Class<? extends BusinessObject> boClass = (Class<? extends BusinessObject>) Class.forName(boClassName);
 656  0
             for (String inquiryParam : inquiryParams) {
 657  0
                 String[] keyValue = inquiryParam.split(KRADConstants.FIELD_CONVERSION_PAIR_SEPARATOR);
 658  
 
 659  0
                 String inquiryParameterValue = retrieveLookupParameterValue(boClass, keyValue[1], keyValue[0], form, request);
 660  0
                 if (inquiryParameterValue == null) {
 661  0
                         parameters.put(keyValue[1], "directInquiryKeyNotSpecified");
 662  
                 }
 663  
                 else {
 664  0
                         parameters.put(keyValue[1], inquiryParameterValue);
 665  
                 }
 666  
 
 667  0
                 if ( LOG.isDebugEnabled() ) {
 668  0
                     LOG.debug( "keyValue[0]: " + keyValue[0] );
 669  0
                     LOG.debug( "keyValue[1]: " + keyValue[1] );
 670  
                 }
 671  
             }
 672  
         }
 673  0
         parameters.put(KRADConstants.DISPATCH_REQUEST_PARAMETER, "start");
 674  0
         parameters.put(KRADConstants.DOC_FORM_KEY, GlobalVariables.getUserSession().addObjectWithGeneratedKey(form));
 675  0
         String inquiryUrl = null;
 676  
         try {
 677  0
                 Class.forName(boClassName);
 678  0
                 inquiryUrl = getApplicationBaseUrl() + "/kr/" + KRADConstants.DIRECT_INQUIRY_ACTION;
 679  0
         } catch ( ClassNotFoundException ex ) {
 680  
             // allow inquiry url to be null (and therefore no inquiry link will be displayed) but at least log a warning
 681  0
                 LOG.warn("Class name does not represent a valid class which this application understands: " + boClassName);
 682  0
         }
 683  0
         inquiryUrl = UrlFactory.parameterizeUrl(inquiryUrl, parameters);
 684  0
         return new ActionForward(inquiryUrl, true);
 685  
 
 686  
     }
 687  
 
 688  
     /**
 689  
      * This method handles rendering the question component, but without any of the extra error fields
 690  
      *
 691  
      * @param mapping
 692  
      * @param form
 693  
      * @param request
 694  
      * @param response
 695  
      * @param questionId
 696  
      * @param questionText
 697  
      * @param questionType
 698  
      * @param caller
 699  
      * @param context
 700  
      * @return ActionForward
 701  
      * @throws Exception
 702  
      */
 703  
     protected ActionForward performQuestionWithoutInput(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response, String questionId, String questionText, String questionType, String caller, String context) throws Exception {
 704  0
         return performQuestion(mapping, form, request, response, questionId, questionText, questionType, caller, context, false, "", "", "", "");
 705  
     }
 706  
 
 707  
     /**
 708  
      * Handles rendering a question prompt - without a specified context.
 709  
      *
 710  
      * @param mapping
 711  
      * @param form
 712  
      * @param request
 713  
      * @param response
 714  
      * @param questionId
 715  
      * @param questionText
 716  
      * @param questionType
 717  
      * @param caller
 718  
      * @param context
 719  
      * @return ActionForward
 720  
      * @throws Exception
 721  
      */
 722  
     protected ActionForward performQuestionWithInput(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response, String questionId, String questionText, String questionType, String caller, String context) throws Exception {
 723  0
         return performQuestion(mapping, form, request, response, questionId, questionText, questionType, caller, context, true, "", "", "", "");
 724  
     }
 725  
 
 726  
     /**
 727  
      * Handles re-rendering a question prompt because of an error on what was submitted.
 728  
      *
 729  
      * @param mapping
 730  
      * @param form
 731  
      * @param request
 732  
      * @param response
 733  
      * @param questionId
 734  
      * @param questionText
 735  
      * @param questionType
 736  
      * @param caller
 737  
      * @param context
 738  
      * @param reason
 739  
      * @param errorKey
 740  
      * @param errorPropertyName
 741  
      * @param errorParameter
 742  
      * @return ActionForward
 743  
      * @throws Exception
 744  
      */
 745  
     protected ActionForward performQuestionWithInputAgainBecauseOfErrors(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response, String questionId, String questionText, String questionType, String caller, String context, String reason, String errorKey, String errorPropertyName, String errorParameter) throws Exception {
 746  0
         return performQuestion(mapping, form, request, response, questionId, questionText, questionType, caller, context, true, reason, errorKey, errorPropertyName, errorParameter);
 747  
     }
 748  
 
 749  
     /**
 750  
      * Handles rendering a question prompt - with a specified context.
 751  
      *
 752  
      * @param mapping
 753  
      * @param form
 754  
      * @param request
 755  
      * @param response
 756  
      * @param questionId
 757  
      * @param questionText
 758  
      * @param questionType
 759  
      * @param caller
 760  
      * @param context
 761  
      * @param showReasonField
 762  
      * @param reason
 763  
      * @param errorKey
 764  
      * @param errorPropertyName
 765  
      * @param errorParameter
 766  
      * @return ActionForward
 767  
      * @throws Exception
 768  
      */
 769  
     private ActionForward performQuestion(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response, String questionId, String questionText, String questionType, String caller, String context, boolean showReasonField, String reason, String errorKey, String errorPropertyName, String errorParameter) throws Exception {
 770  0
         Properties parameters = new Properties();
 771  
 
 772  0
         parameters.put(KRADConstants.DISPATCH_REQUEST_PARAMETER, "start");
 773  0
         parameters.put(KRADConstants.DOC_FORM_KEY, GlobalVariables.getUserSession().addObjectWithGeneratedKey(form));
 774  0
         parameters.put(KRADConstants.CALLING_METHOD, caller);
 775  0
         parameters.put(KRADConstants.QUESTION_INST_ATTRIBUTE_NAME, questionId);
 776  0
         parameters.put(KRADConstants.QUESTION_IMPL_ATTRIBUTE_NAME, questionType);
 777  0
         parameters.put(KRADConstants.QUESTION_TEXT_ATTRIBUTE_NAME, questionText);
 778  0
         parameters.put(KRADConstants.RETURN_LOCATION_PARAMETER, getReturnLocation(request, mapping));
 779  0
         parameters.put(KRADConstants.QUESTION_CONTEXT, context);
 780  0
         parameters.put(KRADConstants.QUESTION_SHOW_REASON_FIELD, Boolean.toString(showReasonField));
 781  0
         parameters.put(KRADConstants.QUESTION_REASON_ATTRIBUTE_NAME, reason);
 782  0
         parameters.put(KRADConstants.QUESTION_ERROR_KEY, errorKey);
 783  0
         parameters.put(KRADConstants.QUESTION_ERROR_PROPERTY_NAME, errorPropertyName);
 784  0
         parameters.put(KRADConstants.QUESTION_ERROR_PARAMETER, errorParameter);
 785  0
         parameters.put(KRADConstants.QUESTION_ANCHOR, form instanceof KualiForm ? ObjectUtils.toString(((KualiForm) form).getAnchor()) : "");
 786  0
         Object methodToCallAttribute = request.getAttribute(KRADConstants.METHOD_TO_CALL_ATTRIBUTE);
 787  0
         if (methodToCallAttribute != null) {
 788  0
             parameters.put(KRADConstants.METHOD_TO_CALL_PATH, methodToCallAttribute);
 789  0
             ((PojoForm) form).registerEditableProperty(String.valueOf(methodToCallAttribute));
 790  
         }
 791  
         
 792  0
             if (form instanceof KualiDocumentFormBase) {
 793  0
                     String docNum = ((KualiDocumentFormBase) form).getDocument().getDocumentNumber();
 794  0
                     if(docNum != null){
 795  0
                             parameters.put(KRADConstants.DOC_NUM, ((KualiDocumentFormBase) form)
 796  
                                         .getDocument().getDocumentNumber());
 797  
                     }
 798  
                 }
 799  
 
 800  0
         String questionUrl = UrlFactory.parameterizeUrl(getApplicationBaseUrl() + "/kr/" + KRADConstants.QUESTION_ACTION, parameters);
 801  0
         return new ActionForward(questionUrl, true);
 802  
     }
 803  
 
 804  
 
 805  
     /**
 806  
      * Takes care of storing the action form in the User session and forwarding to the workflow workgroup lookup action.
 807  
      *
 808  
      * @param mapping
 809  
      * @param form
 810  
      * @param request
 811  
      * @param response
 812  
      * @return
 813  
      * @throws Exception
 814  
      */
 815  
     public ActionForward performWorkgroupLookup(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 816  0
             String returnUrl = null;
 817  0
             if ("/kr".equals(mapping.getModuleConfig().getPrefix())) {
 818  0
                     returnUrl = getApplicationBaseUrl() + mapping.getModuleConfig().getPrefix() + mapping.getPath() + ".do";
 819  
             } else {
 820  0
                     returnUrl = getApplicationBaseUrl() + mapping.getPath() + ".do";
 821  
             }
 822  
 
 823  
 
 824  0
         String fullParameter = (String) request.getAttribute(KRADConstants.METHOD_TO_CALL_ATTRIBUTE);
 825  0
         String conversionFields = StringUtils.substringBetween(fullParameter, KRADConstants.METHOD_TO_CALL_PARM1_LEFT_DEL, KRADConstants.METHOD_TO_CALL_PARM1_RIGHT_DEL);
 826  
 
 827  0
         String deploymentBaseUrl = KRADServiceLocator.getKualiConfigurationService().getPropertyValueAsString(
 828  
                 KRADConstants.WORKFLOW_URL_KEY);
 829  0
         String workgroupLookupUrl = deploymentBaseUrl + "/Lookup.do?lookupableImplServiceName=WorkGroupLookupableImplService&methodToCall=start&docFormKey=" + GlobalVariables.getUserSession().addObjectWithGeneratedKey(form);
 830  
 
 831  0
         if (conversionFields != null) {
 832  0
             workgroupLookupUrl += "&conversionFields=" + conversionFields;
 833  
         }
 834  0
             if (form instanceof KualiDocumentFormBase) {
 835  0
                         workgroupLookupUrl +="&docNum="+ ((KualiDocumentFormBase) form).getDocument().getDocumentNumber();
 836  
                 }
 837  
             
 838  0
         workgroupLookupUrl += "&returnLocation=" + returnUrl;
 839  
 
 840  0
         return new ActionForward(workgroupLookupUrl, true);
 841  
     }
 842  
 
 843  
     /**
 844  
      * Handles requests that originate via Header Tabs.
 845  
      *
 846  
      * @param mapping
 847  
      * @param form
 848  
      * @param request
 849  
      * @param response
 850  
      * @return
 851  
      * @throws Exception
 852  
      */
 853  
     public ActionForward headerTab(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 854  
         // header tab actions can do two things - 1, call into an action and perform what needs to happen in there and 2, forward to
 855  
         // a new location.
 856  0
         String headerTabDispatch = getHeaderTabDispatch(request);
 857  0
         if (StringUtils.isNotEmpty(headerTabDispatch)) {
 858  0
             ActionForward forward = dispatchMethod(mapping, form, request, response, headerTabDispatch);
 859  0
             if (GlobalVariables.getMessageMap().getNumberOfPropertiesWithErrors() > 0) {
 860  0
                 return mapping.findForward(RiceConstants.MAPPING_BASIC);
 861  
             }
 862  0
             this.doTabOpenOrClose(mapping, form, request, response, false);
 863  0
             if (forward.getRedirect()) {
 864  0
                 return forward;
 865  
             }
 866  
         }
 867  0
         return dispatchMethod(mapping, form, request, response, getHeaderTabNavigateTo(request));
 868  
     }
 869  
 
 870  
     /**
 871  
      * Override this method to provide action-level access controls to the application.
 872  
      *
 873  
      * @param form
 874  
      * @throws AuthorizationException
 875  
      */
 876  
     protected void checkAuthorization( ActionForm form, String methodToCall) throws AuthorizationException 
 877  
     {
 878  0
             String principalId = GlobalVariables.getUserSession().getPrincipalId();
 879  0
             Map<String, String> roleQualifier = new HashMap<String, String>(getRoleQualification(form, methodToCall));
 880  0
             Map<String, String> permissionDetails = KRADUtils.getNamespaceAndActionClass(this.getClass());
 881  
             
 882  0
         if (!KimApiServiceLocator.getPermissionService().isAuthorizedByTemplateName(principalId, KRADConstants.KRAD_NAMESPACE,
 883  
                         KimConstants.PermissionTemplateNames.USE_SCREEN, permissionDetails, roleQualifier ))
 884  
         {
 885  0
             throw new AuthorizationException(GlobalVariables.getUserSession().getPerson().getPrincipalName(), 
 886  
                             methodToCall,
 887  
                             this.getClass().getSimpleName());
 888  
         }
 889  0
     }
 890  
     
 891  
     /** 
 892  
      * override this method to add data from the form for role qualification in the authorization check
 893  
      */
 894  
     protected Map<String,String> getRoleQualification(ActionForm form, String methodToCall) {
 895  0
             return new HashMap<String,String>();
 896  
     }
 897  
 
 898  
     protected static KualiModuleService getKualiModuleService() {
 899  0
         if ( kualiModuleService == null ) {
 900  0
             kualiModuleService = KRADServiceLocatorWeb.getKualiModuleService();
 901  
         }
 902  0
         return kualiModuleService;
 903  
     }
 904  
 
 905  
     /**
 906  
      * Constant defined to match with TextArea.jsp and updateTextArea function in core.js
 907  
      * <p>Value is textAreaFieldName
 908  
      */
 909  
     public static final String TEXT_AREA_FIELD_NAME="textAreaFieldName";
 910  
     /**
 911  
      * Constant defined to match with TextArea.jsp and updateTextArea function in core.js
 912  
      * <p>Value is textAreaFieldLabel
 913  
     */
 914  
     public static final String TEXT_AREA_FIELD_LABEL="textAreaFieldLabel";
 915  
     /**
 916  
      * Constant defined to match with TextArea.jsp and updateTextArea function in core.js
 917  
      * <p>Value is textAreaReadOnly
 918  
     */
 919  
     public static final String TEXT_AREA_READ_ONLY="textAreaReadOnly";
 920  
     /**
 921  
      * Constant defined to match with TextArea.jsp and updateTextArea function in core.js
 922  
      * <p>Value is textAreaFieldAnchor
 923  
     */
 924  
     public static final String TEXT_AREA_FIELD_ANCHOR="textAreaFieldAnchor";
 925  
     /**
 926  
      * Constant defined to match with TextArea.jsp and updateTextArea function in core.js
 927  
      * <p>Value is textAreaFieldAnchor
 928  
     */
 929  
     public static final String TEXT_AREA_MAX_LENGTH="textAreaMaxLength";
 930  
     /**
 931  
      * Constant defined to match with TextArea.jsp and updateTextArea function in core.js
 932  
      * <p>Value is htmlFormAction
 933  
     */
 934  
     public static final String FORM_ACTION="htmlFormAction";
 935  
     /**
 936  
      * Constant defined to match input parameter from URL and from TextArea.jsp.
 937  
      * <p>Value is methodToCall
 938  
     */
 939  
     public static final String METHOD_TO_CALL="methodToCall";
 940  
     /**
 941  
      * Constant defined to match with global forwarding in struts-config.xml
 942  
      * for Text Area Update.
 943  
      * <p>Value is updateTextArea
 944  
     */
 945  
     public static final String FORWARD_TEXT_AREA_UPDATE="updateTextArea";
 946  
     /**
 947  
      * Constant defined to match with method to call in TextArea.jsp.
 948  
      * <p>Value is postTextAreaToParent
 949  
     */
 950  
     public static final String POST_TEXT_AREA_TO_PARENT="postTextAreaToParent";
 951  
     /**
 952  
      * Constant defined to match with local forwarding in struts-config.xml
 953  
      * for the parent of the Updated Text Area.
 954  
      * <p>Value is forwardNext
 955  
     */
 956  
     public static final String FORWARD_NEXT="forwardNext";
 957  
     
 958  
     /**
 959  
      * Constant defined to match with method call in module-locked.jsp which is
 960  
      * set to a message that is displayed when the module is locked.
 961  
      */
 962  
     public static final String MODULE_LOCKED_MESSAGE = "moduleLockedMessage";
 963  
 
 964  
     /**
 965  
      * This method is invoked when Java Script is turned off from the web browser. It
 966  
      * setup the information that the update text area requires for copying current text
 967  
      * in the calling page text area and returning to the calling page. The information
 968  
      * is passed to the JSP through Http Request attributes. All other parameters are
 969  
      * forwarded 
 970  
      *  
 971  
      * @param mapping
 972  
      * @param form
 973  
      * @param request
 974  
      * @param response
 975  
      * @return
 976  
      */
 977  
     public ActionForward updateTextArea(ActionMapping mapping,
 978  
             ActionForm form,
 979  
             HttpServletRequest request,
 980  
             HttpServletResponse response)  {
 981  0
         if (LOG.isTraceEnabled()) {
 982  0
             String lm=String.format("ENTRY %s%n%s", form.getClass().getSimpleName(),
 983  
                     request.getRequestURI());
 984  0
             LOG.trace(lm);
 985  
         }
 986  
                                 
 987  0
         final String[] keyValue = getTextAreaParams(request);
 988  
         
 989  0
         request.setAttribute(TEXT_AREA_FIELD_NAME, keyValue[0]);
 990  0
         request.setAttribute(FORM_ACTION,keyValue[1]);
 991  0
         request.setAttribute(TEXT_AREA_FIELD_LABEL,keyValue[2]);
 992  0
         request.setAttribute(TEXT_AREA_READ_ONLY,keyValue[3]);
 993  0
         request.setAttribute(TEXT_AREA_MAX_LENGTH,keyValue[4]);
 994  0
         if (form instanceof KualiForm && StringUtils.isNotEmpty(((KualiForm) form).getAnchor())) {
 995  0
             request.setAttribute(TEXT_AREA_FIELD_ANCHOR,((KualiForm) form).getAnchor());
 996  
         }
 997  
         
 998  
         // Set document related parameter
 999  0
         String docWebScope=(String)request.getAttribute(KRADConstants.DOCUMENT_WEB_SCOPE);
 1000  0
         if (docWebScope != null && docWebScope.trim().length() >= 0) {
 1001  0
             request.setAttribute(KRADConstants.DOCUMENT_WEB_SCOPE, docWebScope);
 1002  
         }
 1003  
 
 1004  0
         request.setAttribute(KRADConstants.DOC_FORM_KEY, GlobalVariables.getUserSession().addObjectWithGeneratedKey(form));
 1005  
         
 1006  0
         ActionForward forward=mapping.findForward(FORWARD_TEXT_AREA_UPDATE);
 1007  
 
 1008  0
         if (LOG.isTraceEnabled()) {
 1009  0
             String lm=String.format("EXIT %s", (forward==null)?"null":forward.getPath());
 1010  0
             LOG.trace(lm);
 1011  
         }
 1012  
                         
 1013  0
         return forward;
 1014  
     }
 1015  
     
 1016  
     /**
 1017  
      * This method takes the {@link org.kuali.rice.krad.util.KRADConstants.METHOD_TO_CALL_ATTRIBUTE} out of the request
 1018  
      * and parses it returning the required fields needed for a text area. The fields returned
 1019  
      * are the following in this order.
 1020  
      * <ol>
 1021  
      * <li>{@link #TEXT_AREA_FIELD_NAME}</li>
 1022  
      * <li>{@link #FORM_ACTION}</li>
 1023  
      * <li>{@link #TEXT_AREA_FIELD_LABEL}</li>
 1024  
      * <li>{@link #TEXT_AREA_READ_ONLY}</li>
 1025  
      * <li>{@link #TEXT_AREA_MAX_LENGTH}</li>
 1026  
      * </ol>
 1027  
      * 
 1028  
      * @param request the request to retrieve the textarea parameters
 1029  
      * @return a string array holding the parsed fields
 1030  
      */
 1031  
     private String[] getTextAreaParams(HttpServletRequest request) {
 1032  
         // parse out the important strings from our methodToCall parameter
 1033  0
         String fullParameter = (String) request.getAttribute(
 1034  
                 KRADConstants.METHOD_TO_CALL_ATTRIBUTE);
 1035  
 
 1036  
         // parse textfieldname:htmlformaction
 1037  0
         String parameterFields = StringUtils.substringBetween(fullParameter,
 1038  
                 KRADConstants.METHOD_TO_CALL_PARM2_LEFT_DEL,
 1039  
                 KRADConstants.METHOD_TO_CALL_PARM2_RIGHT_DEL);
 1040  0
         if ( LOG.isDebugEnabled() ) {
 1041  0
             LOG.debug( "fullParameter: " + fullParameter );
 1042  0
             LOG.debug( "parameterFields: " + parameterFields );
 1043  
         }
 1044  0
         String[] keyValue = null;
 1045  0
         if (StringUtils.isNotBlank(parameterFields)) {
 1046  0
             String[] textAreaParams = parameterFields.split(
 1047  
                     KRADConstants.FIELD_CONVERSIONS_SEPARATOR);
 1048  0
             if ( LOG.isDebugEnabled() ) {
 1049  0
                 LOG.debug( "lookupParams: " + textAreaParams );
 1050  
             }
 1051  0
             for (final String textAreaParam : textAreaParams) {
 1052  0
                 keyValue = textAreaParam.split(KRADConstants.FIELD_CONVERSION_PAIR_SEPARATOR);
 1053  
 
 1054  0
                 if ( LOG.isDebugEnabled() ) {
 1055  0
                     LOG.debug( "keyValue[0]: " + keyValue[0] );
 1056  0
                     LOG.debug( "keyValue[1]: " + keyValue[1] );
 1057  0
                     LOG.debug( "keyValue[2]: " + keyValue[2] );
 1058  0
                     LOG.debug( "keyValue[3]: " + keyValue[3] );
 1059  0
                     LOG.debug( "keyValue[4]: " + keyValue[4] );
 1060  
                 }
 1061  
             }
 1062  
         }
 1063  
         
 1064  0
         return keyValue;
 1065  
     }
 1066  
     
 1067  
     /**
 1068  
      * This method is invoked from the TextArea.jsp for posting its value to the parent
 1069  
      * page that called the extended text area page. The invocation is done through
 1070  
      * Struts action. The default forwarding id is RiceContants.MAPPING_BASIC. This
 1071  
      * can be overridden using the parameter key FORWARD_NEXT.
 1072  
      * 
 1073  
      * @param mapping
 1074  
      * @param form
 1075  
      * @param request
 1076  
      * @param response
 1077  
      * @return
 1078  
      */
 1079  
     public ActionForward postTextAreaToParent(ActionMapping mapping,
 1080  
             ActionForm form,
 1081  
             HttpServletRequest request,
 1082  
             HttpServletResponse response) {
 1083  
         
 1084  0
         if (LOG.isTraceEnabled()) {
 1085  0
             String lm=String.format("ENTRY %s%n%s", form.getClass().getSimpleName(),
 1086  
                     request.getRequestURI());
 1087  0
             LOG.trace(lm);
 1088  
         }
 1089  
                         
 1090  0
         String forwardingId=request.getParameter(FORWARD_NEXT);
 1091  0
         if (forwardingId == null) {
 1092  0
             forwardingId=RiceConstants.MAPPING_BASIC;
 1093  
         }
 1094  0
         ActionForward forward=mapping.findForward(forwardingId);
 1095  
              
 1096  0
         if (LOG.isTraceEnabled()) {
 1097  0
             String lm=String.format("EXIT %s", (forward==null)?"null":forward.getPath());
 1098  0
             LOG.trace(lm);
 1099  
         }
 1100  
                         
 1101  0
         return forward;
 1102  
     }
 1103  
     
 1104  
     /**
 1105  
      * Use to add a methodToCall to the a list which will not have authorization checks.
 1106  
      * This assumes that the call will be redirected (as in the case of a lookup) that will perform
 1107  
      * the authorization.
 1108  
      */
 1109  
     protected final void addMethodToCallToUncheckedList( String methodToCall ) {
 1110  0
             methodToCallsToNotCheckAuthorization.add(methodToCall);
 1111  0
     }
 1112  
     
 1113  
     /**
 1114  
      * This method does all special processing on a document that should happen on each HTTP post (ie, save, route, approve, etc).
 1115  
      */
 1116  
     protected void doProcessingAfterPost( KualiForm form, HttpServletRequest request ) {
 1117  
             
 1118  0
     }
 1119  
     
 1120  
     protected BusinessObjectAuthorizationService getBusinessObjectAuthorizationService() {
 1121  0
             if (businessObjectAuthorizationService == null) {
 1122  0
                     businessObjectAuthorizationService = KNSServiceLocator.getBusinessObjectAuthorizationService();
 1123  
             }
 1124  0
             return businessObjectAuthorizationService;
 1125  
     }
 1126  
     
 1127  
     protected EncryptionService getEncryptionService() {
 1128  0
             if (encryptionService == null) {
 1129  0
                     encryptionService = CoreApiServiceLocator.getEncryptionService();
 1130  
             }
 1131  0
             return encryptionService;
 1132  
     }
 1133  
 
 1134  
         public static String getApplicationBaseUrl() {
 1135  0
                 if ( applicationBaseUrl == null ) {
 1136  0
                         applicationBaseUrl = KRADServiceLocator.getKualiConfigurationService().getPropertyValueAsString(
 1137  
                     KRADConstants.APPLICATION_URL_KEY);
 1138  
                 }
 1139  0
                 return applicationBaseUrl;
 1140  
         }
 1141  
         
 1142  
         protected boolean isModuleLocked(ActionForm form, String methodToCall, HttpServletRequest request) {
 1143  0
                 String boClass = request.getParameter(KRADConstants.BUSINESS_OBJECT_CLASS_ATTRIBUTE);
 1144  0
                 ModuleService moduleService = null;
 1145  0
                 if(StringUtils.isNotBlank(boClass)) {
 1146  
                         try {
 1147  0
                                 moduleService = getKualiModuleService().getResponsibleModuleService(Class.forName(boClass));
 1148  0
                         } catch (ClassNotFoundException classNotFoundException) {
 1149  0
                                 LOG.warn("BO class not found: " + boClass, classNotFoundException);
 1150  0
                         }
 1151  
                 } else {
 1152  0
                         moduleService = getKualiModuleService().getResponsibleModuleService(this.getClass());
 1153  
                 }
 1154  0
                 if(moduleService != null && moduleService.isLocked()) {
 1155  0
                         String principalId = GlobalVariables.getUserSession().getPrincipalId();
 1156  0
                         String namespaceCode = KRADConstants.KUALI_RICE_SYSTEM_NAMESPACE;
 1157  0
                         String permissionName = KimConstants.PermissionNames.ACCESS_LOCKED_MODULE;
 1158  0
                         Map<String, String> permissionDetails = new HashMap<String, String>();
 1159  0
                         Map<String, String> qualification = getRoleQualification(form, methodToCall);
 1160  0
                         if(!KimApiServiceLocator.getPermissionService().isAuthorized(principalId, namespaceCode, permissionName, permissionDetails, qualification)) {
 1161  0
                                 ParameterService parameterSerivce = CoreFrameworkServiceLocator.getParameterService();
 1162  0
                                 String messageParamNamespaceCode = moduleService.getModuleConfiguration().getNamespaceCode();
 1163  0
                                 String messageParamComponentCode = KRADConstants.DetailTypes.OLTP_LOCKOUT_DETAIL_TYPE;
 1164  0
                                 String messageParamName = KRADConstants.SystemGroupParameterNames.OLTP_LOCKOUT_MESSAGE_PARM;
 1165  0
                                 String lockoutMessage = parameterSerivce.getParameterValueAsString(messageParamNamespaceCode, messageParamComponentCode, messageParamName);
 1166  
                                 
 1167  0
                                 if(StringUtils.isBlank(lockoutMessage)) {
 1168  0
                                         String defaultMessageParamName = KRADConstants.SystemGroupParameterNames.OLTP_LOCKOUT_DEFAULT_MESSAGE;
 1169  0
                                         lockoutMessage = parameterSerivce.getParameterValueAsString(KRADConstants.KRAD_NAMESPACE, messageParamComponentCode, defaultMessageParamName);
 1170  
                                 }
 1171  0
                                 request.setAttribute(MODULE_LOCKED_MESSAGE, lockoutMessage);
 1172  0
                                 return true;
 1173  
                         }
 1174  
                 }
 1175  0
                 if(moduleService != null) {
 1176  0
                         System.out.println("BENNETT: module = " + moduleService.getModuleConfiguration().getNamespaceCode());
 1177  
                 }
 1178  0
                 return false;
 1179  
         }
 1180  
 }