Coverage Report - org.kuali.rice.kns.web.spring.controller.UifControllerBase
 
Classes in this File Line Coverage Branch Coverage Complexity
UifControllerBase
0%
0/120
0%
0/44
2.667
 
 1  
 /*
 2  
  * Copyright 2007 The Kuali Foundation
 3  
  *
 4  
  * Licensed under the Educational Community License, Version 1.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/ecl1.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.spring.controller;
 17  
 
 18  
 import java.util.Collections;
 19  
 import java.util.Enumeration;
 20  
 import java.util.HashMap;
 21  
 import java.util.HashSet;
 22  
 import java.util.Map;
 23  
 import java.util.Map.Entry;
 24  
 import java.util.Properties;
 25  
 import java.util.Set;
 26  
 
 27  
 import javax.servlet.http.HttpServletRequest;
 28  
 import javax.servlet.http.HttpServletResponse;
 29  
 
 30  
 import org.apache.commons.lang.StringUtils;
 31  
 import org.kuali.rice.core.api.config.property.ConfigContext;
 32  
 import org.kuali.rice.core.xml.dto.AttributeSet;
 33  
 import org.kuali.rice.kim.service.KIMServiceLocator;
 34  
 import org.kuali.rice.kim.util.KimConstants;
 35  
 import org.kuali.rice.kns.exception.AuthorizationException;
 36  
 import org.kuali.rice.kns.service.KNSServiceLocatorWeb;
 37  
 import org.kuali.rice.kns.service.ModuleService;
 38  
 import org.kuali.rice.kns.uif.UifConstants;
 39  
 import org.kuali.rice.kns.uif.UifParameters;
 40  
 import org.kuali.rice.kns.uif.container.View;
 41  
 import org.kuali.rice.kns.uif.service.ViewService;
 42  
 import org.kuali.rice.kns.uif.util.LookupInquiryUtils;
 43  
 import org.kuali.rice.kns.util.GlobalVariables;
 44  
 import org.kuali.rice.kns.util.KNSConstants;
 45  
 import org.kuali.rice.kns.util.KNSUtils;
 46  
 import org.kuali.rice.kns.util.UrlFactory;
 47  
 import org.kuali.rice.kns.util.WebUtils;
 48  
 import org.kuali.rice.kns.web.spring.form.UifFormBase;
 49  
 import org.springframework.validation.BindingResult;
 50  
 import org.springframework.web.bind.annotation.ModelAttribute;
 51  
 import org.springframework.web.bind.annotation.RequestMapping;
 52  
 import org.springframework.web.bind.annotation.RequestMethod;
 53  
 import org.springframework.web.servlet.ModelAndView;
 54  
 
 55  
 /**
 56  
  * Base controller class for views within the KRAD User Interface Framework
 57  
  * 
 58  
  * <p>
 59  
  * Provides common methods such as:
 60  
  * <ul>
 61  
  * <li>Authorization methods such as method to call check</li>
 62  
  * <li>Preparing the View instance and setup in the returned
 63  
  * <code>ModelAndView</code></li>
 64  
  * </ul>
 65  
  * </p>
 66  
  * 
 67  
  * <p>
 68  
  * All subclass controller methods after processing should call one of the
 69  
  * #getUIFModelAndView methods to setup the <code>View</code> and return the
 70  
  * <code>ModelAndView</code> instance.
 71  
  * </p>
 72  
  * 
 73  
  * @author Kuali Rice Team (rice.collab@kuali.org)
 74  
  */
 75  0
 public abstract class UifControllerBase {
 76  0
         private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(UifControllerBase.class);
 77  
 
 78  
         protected static final String REDIRECT_PREFIX = "redirect:";
 79  
 
 80  
         /**
 81  
          * This method will create/obtain the model(form) object before it is passed
 82  
          * to the Binder/BeanWrapper.
 83  
          * 
 84  
          * This method is not intended to be overridden by client applications as it
 85  
          * handles framework setup and session maintenance. Clients should override
 86  
          * createIntialForm() instead when they need custom form initialization.
 87  
          * 
 88  
          * @param request
 89  
          * @return
 90  
          */
 91  
         @ModelAttribute(value = "KualiForm")
 92  
         public UifFormBase initForm(HttpServletRequest request) {
 93  
                 UifFormBase form;
 94  0
                 String formKeyParam = request.getParameter(UifParameters.FORM_KEY);
 95  
 
 96  0
                 if (StringUtils.isNotBlank(formKeyParam)) {
 97  0
                         form = (UifFormBase) request.getSession().getAttribute(formKeyParam);
 98  
                 }
 99  
                 else {
 100  0
                         form = createInitialForm(request);
 101  
                 }
 102  
 
 103  0
                 return form;
 104  
         }
 105  
 
 106  
         /**
 107  
          * This method will be called to create a new model(form) object when
 108  
          * necessary. This usually occurs on the initial request in a conversation
 109  
          * (when the model is not present in the session).
 110  
          * 
 111  
          * This method must be overridden when extending a controller and using a
 112  
          * different form type than the superclass.
 113  
          * 
 114  
          * @param request
 115  
          * @return
 116  
          */
 117  
         protected abstract UifFormBase createInitialForm(HttpServletRequest request);
 118  
 
 119  0
         private Set<String> methodToCallsToNotCheckAuthorization = new HashSet<String>();
 120  
         {
 121  0
                 methodToCallsToNotCheckAuthorization.add("performLookup");
 122  0
                 methodToCallsToNotCheckAuthorization.add("performQuestion");
 123  0
                 methodToCallsToNotCheckAuthorization.add("performQuestionWithInput");
 124  0
                 methodToCallsToNotCheckAuthorization.add("performQuestionWithInputAgainBecauseOfErrors");
 125  0
                 methodToCallsToNotCheckAuthorization.add("performQuestionWithoutInput");
 126  0
                 methodToCallsToNotCheckAuthorization.add("performWorkgroupLookup");
 127  0
         }
 128  
 
 129  
         /**
 130  
          * Use to add a methodToCall to the a list which will not have authorization
 131  
          * checks. This assumes that the call will be redirected (as in the case of
 132  
          * a lookup) that will perform the authorization.
 133  
          */
 134  
         protected final void addMethodToCallToUncheckedList(String methodToCall) {
 135  0
                 methodToCallsToNotCheckAuthorization.add(methodToCall);
 136  0
         }
 137  
 
 138  
         /**
 139  
          * Returns an immutable Set of methodToCall parameters that should not be
 140  
          * checked for authorization.
 141  
          * 
 142  
          * @return
 143  
          */
 144  
         public Set<String> getMethodToCallsToNotCheckAuthorization() {
 145  0
                 return Collections.unmodifiableSet(methodToCallsToNotCheckAuthorization);
 146  
         }
 147  
 
 148  
         /**
 149  
          * Override this method to provide controller class-level access controls to
 150  
          * the application.
 151  
          * 
 152  
          * @param form
 153  
          * @throws AuthorizationException
 154  
          */
 155  
         public void checkAuthorization(UifFormBase form, String methodToCall) throws AuthorizationException {
 156  0
                 String principalId = GlobalVariables.getUserSession().getPrincipalId();
 157  0
                 AttributeSet roleQualifier = new AttributeSet(getRoleQualification(form, methodToCall));
 158  0
                 AttributeSet permissionDetails = KNSUtils.getNamespaceAndActionClass(this.getClass());
 159  
 
 160  0
                 if (!KIMServiceLocator.getIdentityManagementService().isAuthorizedByTemplateName(principalId,
 161  
                                 KNSConstants.KNS_NAMESPACE, KimConstants.PermissionTemplateNames.USE_SCREEN, permissionDetails,
 162  
                                 roleQualifier)) {
 163  0
                         throw new AuthorizationException(GlobalVariables.getUserSession().getPerson().getPrincipalName(),
 164  
                                         methodToCall, this.getClass().getSimpleName());
 165  
                 }
 166  0
         }
 167  
 
 168  
         /**
 169  
          * override this method to add data from the form for role qualification in
 170  
          * the authorization check
 171  
          * 
 172  
          * @param form
 173  
          * @param methodToCall
 174  
          */
 175  
         protected Map<String, String> getRoleQualification(UifFormBase form, String methodToCall) {
 176  0
                 return new HashMap<String, String>();
 177  
         }
 178  
 
 179  
         /**
 180  
          * Called by the add line action for a new collection line. Method
 181  
          * determines which collection the add action was selected for and invokes
 182  
          * the view helper service to add the line
 183  
          * 
 184  
          * @param uifForm
 185  
          *            - form instance that contains the data (should extend
 186  
          *            UifFormBase)
 187  
          * @param result
 188  
          *            - contains results of the data binding
 189  
          * @param request
 190  
          *            - HTTP request
 191  
          * @param response
 192  
          *            - HTTP response
 193  
          * @return ModelAndView
 194  
          */
 195  
         @RequestMapping(method = RequestMethod.POST, params = "methodToCall=addLine")
 196  
         public ModelAndView addLine(@ModelAttribute("KualiForm") UifFormBase uifForm, BindingResult result,
 197  
                         HttpServletRequest request, HttpServletResponse response) {
 198  
 
 199  0
                 String selectedCollectionPath = uifForm.getActionParamaterValue(UifParameters.SELLECTED_COLLECTION_PATH);
 200  0
                 if (StringUtils.isBlank(selectedCollectionPath)) {
 201  0
                         throw new RuntimeException("Selected collection was not set for add line action, cannot add new line");
 202  
                 }
 203  
 
 204  0
                 View view = uifForm.getPreviousView();
 205  0
                 view.getViewHelperService().processCollectionAddLine(view, uifForm, selectedCollectionPath);
 206  
 
 207  0
                 return getUIFModelAndView(uifForm);
 208  
         }
 209  
 
 210  
         /**
 211  
          * Called by the delete line action for a model collection. Method
 212  
          * determines which collection the action was selected for and the line
 213  
          * index that should be removed, then invokes the view helper service to
 214  
          * process the action
 215  
          * 
 216  
          * @param uifForm
 217  
          *            - form instance that contains the data (should extend
 218  
          *            UifFormBase)
 219  
          * @param result
 220  
          *            - contains results of the data binding
 221  
          * @param request
 222  
          *            - HTTP request
 223  
          * @param response
 224  
          *            - HTTP response
 225  
          * @return ModelAndView
 226  
          */
 227  
         @RequestMapping(method = RequestMethod.POST, params = "methodToCall=deleteLine")
 228  
         public ModelAndView deleteLine(@ModelAttribute("KualiForm") UifFormBase uifForm, BindingResult result,
 229  
                         HttpServletRequest request, HttpServletResponse response) {
 230  
 
 231  0
                 String selectedCollectionPath = uifForm.getActionParamaterValue(UifParameters.SELLECTED_COLLECTION_PATH);
 232  0
                 if (StringUtils.isBlank(selectedCollectionPath)) {
 233  0
                         throw new RuntimeException("Selected collection was not set for delete line action, cannot delete line");
 234  
                 }
 235  
 
 236  0
                 int selectedLineIndex = -1;
 237  0
                 String selectedLine = uifForm.getActionParamaterValue(UifParameters.SELECTED_LINE_INDEX);
 238  0
                 if (StringUtils.isNotBlank(selectedLine)) {
 239  0
                         selectedLineIndex = Integer.parseInt(selectedLine);
 240  
                 }
 241  
 
 242  0
                 if (selectedLineIndex == -1) {
 243  0
                         throw new RuntimeException("Selected line index was not set for delete line action, cannot delete line");
 244  
                 }
 245  
 
 246  0
                 View view = uifForm.getPreviousView();
 247  0
                 view.getViewHelperService().processCollectionDeleteLine(view, uifForm, selectedCollectionPath,
 248  
                                 selectedLineIndex);
 249  
 
 250  0
                 return getUIFModelAndView(uifForm);
 251  
         }
 252  
         
 253  
         /**
 254  
      * Just returns as if return with no value was selected.
 255  
      */
 256  
     @RequestMapping(params = "methodToCall=cancel")
 257  
     public ModelAndView cancel(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result, HttpServletRequest request, HttpServletResponse response) {
 258  0
         return close(form, result, request, response);
 259  
     }
 260  
     
 261  
     /**
 262  
      * Just returns as if return with no value was selected.
 263  
      */
 264  
     @RequestMapping(params = "methodToCall=close")
 265  
     public ModelAndView close(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result, HttpServletRequest request, HttpServletResponse response) {
 266  0
         Properties props = new Properties();
 267  0
         props.put(UifParameters.METHOD_TO_CALL, UifConstants.MethodToCallNames.REFRESH);
 268  0
         if (StringUtils.isNotBlank(form.getReturnFormKey())) {
 269  0
             props.put(UifParameters.FORM_KEY, form.getReturnFormKey());
 270  
         }
 271  
         
 272  
         // TODO this needs setup for lightbox and possible home location property
 273  0
         String returnUrl = form.getReturnLocation();
 274  0
         if(StringUtils.isBlank(returnUrl)) {
 275  0
             returnUrl = ConfigContext.getCurrentContextConfig().getProperty(KNSConstants.APPLICATION_URL_KEY);
 276  
         }
 277  
         
 278  0
         return performRedirect(form, returnUrl, props);
 279  
     }
 280  
 
 281  
         /**
 282  
          * Handles menu navigation between view pages
 283  
          */
 284  
         @RequestMapping(method = RequestMethod.POST, params = "methodToCall=navigate")
 285  
         public ModelAndView navigate(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
 286  
                         HttpServletRequest request, HttpServletResponse response) {
 287  0
                 String pageId = form.getActionParamaterValue(UifParameters.NAVIGATE_TO_PAGE_ID);
 288  
                 
 289  
                 // only refreshing page
 290  0
                 form.setRenderFullView(false);
 291  
 
 292  0
                 return getUIFModelAndView(form, form.getViewId(), pageId);
 293  
         }
 294  
 
 295  
         @RequestMapping(params = "methodToCall=refresh")
 296  
     public ModelAndView refresh(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result, HttpServletRequest request,
 297  
             HttpServletResponse response) throws Exception {
 298  
             // TODO: this code still needs ported with whatever we are supposed
 299  
             // to do on refresh
 300  0
             return getUIFModelAndView(form);
 301  
         }
 302  
 
 303  
         /**
 304  
          * Builds up a URL to the lookup view based on the given post action
 305  
          * parameters and redirects
 306  
          */
 307  
         @RequestMapping(method = RequestMethod.POST, params = "methodToCall=performLookup")
 308  
         public ModelAndView performLookup(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
 309  
                         HttpServletRequest request, HttpServletResponse response) {
 310  0
                 Properties lookupParameters = form.getActionParametersAsProperties();
 311  
 
 312  0
                 String lookupObjectClassName = (String) lookupParameters.get(UifParameters.DATA_OBJECT_CLASS_NAME);
 313  0
                 Class<?> lookupObjectClass = null;
 314  
                 try {
 315  0
                         lookupObjectClass = Class.forName(lookupObjectClassName);
 316  
                 }
 317  0
                 catch (ClassNotFoundException e) {
 318  0
                         LOG.error("Unable to get class for name: " + lookupObjectClassName);
 319  0
                         throw new RuntimeException("Unable to get class for name: " + lookupObjectClassName, e);
 320  0
                 }
 321  
 
 322  
                 // get form values for the lookup parameter fields
 323  0
                 String lookupParameterString = (String) lookupParameters.get(UifParameters.LOOKUP_PARAMETERS);
 324  0
                 if (lookupParameterString != null) {
 325  0
                         Map<String, String> lookupParameterFields = WebUtils.getMapFromParameterString(lookupParameterString);
 326  0
                         for (Entry<String, String> lookupParameter : lookupParameterFields.entrySet()) {
 327  0
                                 String lookupParameterValue = LookupInquiryUtils.retrieveLookupParameterValue(form, request,
 328  
                                                 lookupObjectClass, lookupParameter.getValue(), lookupParameter.getKey());
 329  0
                                 if (StringUtils.isNotBlank(lookupParameterValue)) {
 330  0
                                         lookupParameters.put(lookupParameter.getValue(), lookupParameterValue);
 331  
                                 }
 332  0
                         }
 333  
                 }
 334  
 
 335  
                 // TODO: lookup anchors and doc number?
 336  
 
 337  
                 // TODO: multi-value lookup requests
 338  
 
 339  0
                 String baseLookupUrl = (String) lookupParameters.get(UifParameters.BASE_LOOKUP_URL);
 340  0
                 lookupParameters.remove(UifParameters.BASE_LOOKUP_URL);
 341  
 
 342  
                 // set lookup method to call
 343  0
                 lookupParameters.put(UifParameters.METHOD_TO_CALL, UifConstants.MethodToCallNames.START);
 344  0
                 String autoSearchString = (String) lookupParameters.get(UifParameters.AUTO_SEARCH);
 345  0
                 if (Boolean.parseBoolean(autoSearchString)) {
 346  0
                         lookupParameters.put(UifParameters.METHOD_TO_CALL, UifConstants.MethodToCallNames.SEARCH);
 347  
                 }
 348  
 
 349  0
                 lookupParameters.put(UifParameters.RETURN_LOCATION, form.getFormPostUrl());
 350  0
                 lookupParameters.put(UifParameters.RETURN_FORM_KEY, form.getFormKey());
 351  
 
 352  
                 // special check for external object classes
 353  0
                 if (lookupObjectClass != null) {
 354  0
                         ModuleService responsibleModuleService = KNSServiceLocatorWeb.getKualiModuleService()
 355  
                                         .getResponsibleModuleService(lookupObjectClass);
 356  0
                         if (responsibleModuleService != null && responsibleModuleService.isExternalizable(lookupObjectClass)) {
 357  0
                                 Map<String, String> parameterMap = new HashMap<String, String>();
 358  0
                                 Enumeration<Object> e = lookupParameters.keys();
 359  0
                                 while (e.hasMoreElements()) {
 360  0
                                         String paramName = (String) e.nextElement();
 361  0
                                         parameterMap.put(paramName, lookupParameters.getProperty(paramName));
 362  0
                                 }
 363  
 
 364  0
                                 String lookupUrl = responsibleModuleService.getExternalizableBusinessObjectLookupUrl(lookupObjectClass,
 365  
                                                 parameterMap);
 366  0
                                 return performRedirect(form, lookupUrl, new Properties());
 367  
                         }
 368  
                 }
 369  
 
 370  0
                 return performRedirect(form, baseLookupUrl, lookupParameters);
 371  
         }
 372  
 
 373  
         /**
 374  
          * Builds a <code>ModelAndView</code> instance configured to redirect to the
 375  
          * URL formed by joining the base URL with the given URL parameters
 376  
          * 
 377  
          * @param form
 378  
          *            - current form instance
 379  
          * @param baseUrl
 380  
          *            - base url to redirect to
 381  
          * @param urlParameters
 382  
          *            - properties containing key/value pairs for the url parameters
 383  
          * @return ModelAndView configured to redirect to the given URL
 384  
          */
 385  
         protected ModelAndView performRedirect(UifFormBase form, String baseUrl, Properties urlParameters) {
 386  
                 // If this is an Ajax call only return the redirectURL view with the URL set
 387  
                 // This is to avoid automatic redirect when using light boxes
 388  0
                 if (urlParameters.get("ajaxCall") != null && urlParameters.get("ajaxCall").equals("true")) {
 389  0
                         urlParameters.remove("ajaxCall");
 390  0
                     String redirectUrl = UrlFactory.parameterizeUrl(baseUrl, urlParameters);
 391  0
                         ModelAndView modelAndView = new ModelAndView("redirectURL");            
 392  0
             modelAndView.addObject("redirectUrl",  redirectUrl);
 393  0
             return modelAndView;
 394  
                 }  
 395  
                 
 396  0
                 String redirectUrl = UrlFactory.parameterizeUrl(baseUrl, urlParameters);
 397  0
                 ModelAndView modelAndView = new ModelAndView(REDIRECT_PREFIX + redirectUrl);
 398  
 
 399  0
                 return modelAndView;
 400  
         }
 401  
 
 402  
         protected ModelAndView getUIFModelAndView(UifFormBase form) {
 403  0
                 return getUIFModelAndView(form, form.getViewId(), form.getPageId());
 404  
         }
 405  
 
 406  
         protected ModelAndView getUIFModelAndView(UifFormBase form, String viewId) {
 407  0
                 return getUIFModelAndView(form, viewId, "");
 408  
         }
 409  
 
 410  
         /**
 411  
          * Prepares the <code>View</code> instance for the rendering (including
 412  
          * applying the model) and builds the return <code>ModelAndView</code>
 413  
          * object
 414  
          * 
 415  
          * @param form
 416  
          *            - Form instance containing the model data
 417  
          * @param viewId
 418  
          *            - Id of the View to return
 419  
          * @param pageId
 420  
          *            - Id of the page within the view that should be rendered, can
 421  
          *            be left blank in which the current or default page is rendered
 422  
          * @return ModelAndView object with the contained form
 423  
          */
 424  
         protected ModelAndView getUIFModelAndView(UifFormBase form, String viewId, String pageId) {
 425  
                 // if we don't have the view instance or a different view was requested
 426  
                 // get new instance from the view service
 427  0
                 View view = form.getView();
 428  0
                 if ((view == null) || !StringUtils.equals(viewId, view.getId())) {
 429  0
                         view = getViewService().getView(viewId, form.getViewRequestParameters());
 430  
                         
 431  
                         // view changed so force full render
 432  0
                         form.setRenderFullView(true);
 433  
                 }
 434  
 
 435  
                 // if view status is final we need to rebuild (build fresh)
 436  0
                 if (StringUtils.equals(UifConstants.ViewStatus.FINAL, view.getViewStatus())) {
 437  0
                         view = getViewService().rebuildView(viewId, form, form.getViewRequestParameters());
 438  
                 }
 439  
                 else {
 440  
                         // update the view with the model data
 441  0
                         getViewService().buildView(view, form);
 442  
                 }
 443  
 
 444  0
                 if (StringUtils.isNotBlank(pageId)) {
 445  0
                         view.setCurrentPageId(pageId);
 446  
                 }
 447  
 
 448  0
                 form.setViewId(viewId);
 449  0
                 form.setPageId(pageId);
 450  0
                 form.setView(view);
 451  
 
 452  
                 // create the spring return object pointing to View.jsp
 453  0
                 ModelAndView modelAndView = new ModelAndView();
 454  0
                 modelAndView.addObject(UifConstants.DEFAULT_MODEL_NAME, form);
 455  0
                 modelAndView.setViewName(UifConstants.SPRING_VIEW_ID);
 456  
 
 457  0
                 return modelAndView;
 458  
         }
 459  
 
 460  
         protected ViewService getViewService() {
 461  0
                 return KNSServiceLocatorWeb.getViewService();
 462  
         }
 463  
 
 464  
 }