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