001/** 002 * Copyright 2005-2016 The Kuali Foundation 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.kuali.rice.krad.web.controller; 017 018import org.apache.commons.lang.StringUtils; 019import org.kuali.rice.core.api.config.property.ConfigContext; 020import org.kuali.rice.core.web.format.BooleanFormatter; 021import org.kuali.rice.kim.api.identity.Person; 022import org.kuali.rice.krad.exception.AuthorizationException; 023import org.kuali.rice.krad.service.KRADServiceLocatorWeb; 024import org.kuali.rice.krad.service.ModuleService; 025import org.kuali.rice.krad.uif.UifConstants; 026import org.kuali.rice.krad.uif.UifParameters; 027import org.kuali.rice.krad.uif.UifPropertyPaths; 028import org.kuali.rice.krad.uif.component.Component; 029import org.kuali.rice.krad.uif.container.CollectionGroup; 030import org.kuali.rice.krad.uif.field.AttributeQueryResult; 031import org.kuali.rice.krad.uif.service.ViewService; 032import org.kuali.rice.krad.uif.util.ComponentFactory; 033import org.kuali.rice.krad.uif.util.LookupInquiryUtils; 034import org.kuali.rice.krad.uif.util.UifFormManager; 035import org.kuali.rice.krad.uif.util.UifWebUtils; 036import org.kuali.rice.krad.uif.view.History; 037import org.kuali.rice.krad.uif.view.HistoryEntry; 038import org.kuali.rice.krad.uif.view.View; 039import org.kuali.rice.krad.util.GlobalVariables; 040import org.kuali.rice.krad.util.KRADConstants; 041import org.kuali.rice.krad.util.KRADUtils; 042import org.kuali.rice.krad.util.UrlFactory; 043import org.kuali.rice.krad.web.form.UifFormBase; 044import org.springframework.validation.BindingResult; 045import org.springframework.web.bind.annotation.ModelAttribute; 046import org.springframework.web.bind.annotation.RequestMapping; 047import org.springframework.web.bind.annotation.RequestMethod; 048import org.springframework.web.bind.annotation.ResponseBody; 049import org.springframework.web.servlet.ModelAndView; 050 051import javax.servlet.http.HttpServletRequest; 052import javax.servlet.http.HttpServletResponse; 053import java.util.HashMap; 054import java.util.List; 055import java.util.Map; 056import java.util.Map.Entry; 057import java.util.Properties; 058 059/** 060 * Base controller class for views within the KRAD User Interface Framework 061 * 062 * Provides common methods such as: 063 * 064 * <ul> 065 * <li>Authorization methods such as method to call check</li> 066 * <li>Preparing the View instance and setup in the returned 067 * <code>ModelAndView</code></li> 068 * </ul> 069 * 070 * All subclass controller methods after processing should call one of the 071 * #getUIFModelAndView methods to setup the <code>View</code> and return the 072 * <code>ModelAndView</code> instance. 073 * 074 * @author Kuali Rice Team (rice.collab@kuali.org) 075 */ 076public abstract class UifControllerBase { 077 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(UifControllerBase.class); 078 079 protected static final String REDIRECT_PREFIX = "redirect:"; 080 081 /** 082 * Create/obtain the model(form) object before it is passed to the Binder/BeanWrapper. This method 083 * is not intended to be overridden by client applications as it handles framework setup and session 084 * maintenance. Clients should override createIntialForm() instead when they need custom form initialization. 085 * 086 * @param request - the http request that was made 087 */ 088 @ModelAttribute(value = "KualiForm") 089 public final UifFormBase initForm(HttpServletRequest request) { 090 UifFormBase form = null; 091 092 // get Uif form manager from session if exists or setup a new one for the session 093 UifFormManager uifFormManager = (UifFormManager) request.getSession().getAttribute( 094 UifParameters.FORM_MANAGER); 095 if (uifFormManager == null) { 096 uifFormManager = new UifFormManager(); 097 request.getSession().setAttribute(UifParameters.FORM_MANAGER, uifFormManager); 098 } 099 100 // add form manager to GlobalVariables for easy reference by other controller methods 101 GlobalVariables.setUifFormManager(uifFormManager); 102 103 String formKeyParam = request.getParameter(UifParameters.FORM_KEY); 104 if (StringUtils.isNotBlank(formKeyParam)) { 105 form = uifFormManager.getForm(formKeyParam); 106 } 107 108 // if form not in manager, create a new form 109 if (form == null) { 110 form = createInitialForm(request); 111 } 112 113 uifFormManager.setCurrentForm(form); 114 115 return form; 116 } 117 118 /** 119 * Called to create a new model(form) object when necessary. This usually occurs on the initial request 120 * in a conversation (when the model is not present in the session). This method must be 121 * overridden when extending a controller and using a different form type than the superclass. 122 * 123 * @param request - the http request that was made 124 */ 125 protected abstract UifFormBase createInitialForm(HttpServletRequest request); 126 127 /** 128 * Initial method called when requesting a new view instance which checks authorization and forwards 129 * the view for rendering 130 */ 131 @RequestMapping(params = "methodToCall=start") 132 public ModelAndView start(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result, 133 HttpServletRequest request, HttpServletResponse response) { 134 135 // check view authorization 136 // TODO: this needs to be invoked for each request 137 if (form.getView() != null) { 138 String methodToCall = request.getParameter(KRADConstants.DISPATCH_REQUEST_PARAMETER); 139 checkViewAuthorization(form, methodToCall); 140 } 141 142 return getUIFModelAndView(form); 143 } 144 145 /** 146 * Invokes the configured {@link org.kuali.rice.krad.uif.view.ViewAuthorizer} to verify the user has access to 147 * open the view. An exception is thrown if access has not been granted 148 * 149 * <p> 150 * Note this method is invoked automatically by the controller interceptor for each request 151 * </p> 152 * 153 * @param form - form instance containing the request data 154 * @param methodToCall - the request parameter 'methodToCall' which is used to determine the controller 155 * method invoked 156 */ 157 public void checkViewAuthorization(UifFormBase form, String methodToCall) throws AuthorizationException { 158 Person user = GlobalVariables.getUserSession().getPerson(); 159 160 boolean canOpenView = form.getView().getAuthorizer().canOpenView(form.getView(), form, user); 161 if (!canOpenView) { 162 throw new AuthorizationException(user.getPrincipalName(), "open", form.getView().getId(), 163 "User '" + user.getPrincipalName() + "' is not authorized to open view ID: " + form.getView() 164 .getId(), null); 165 } 166 } 167 168 /** 169 * Called by the add line action for a new collection line. Method 170 * determines which collection the add action was selected for and invokes 171 * the view helper service to add the line 172 */ 173 @RequestMapping(method = RequestMethod.POST, params = "methodToCall=addLine") 174 public ModelAndView addLine(@ModelAttribute("KualiForm") UifFormBase uifForm, BindingResult result, 175 HttpServletRequest request, HttpServletResponse response) { 176 177 String selectedCollectionPath = uifForm.getActionParamaterValue(UifParameters.SELLECTED_COLLECTION_PATH); 178 if (StringUtils.isBlank(selectedCollectionPath)) { 179 throw new RuntimeException("Selected collection was not set for add line action, cannot add new line"); 180 } 181 182 View view = uifForm.getPostedView(); 183 view.getViewHelperService().processCollectionAddLine(view, uifForm, selectedCollectionPath); 184 185 return updateComponent(uifForm, result, request, response); 186 } 187 188 /** 189 * Called by the delete line action for a model collection. Method 190 * determines which collection the action was selected for and the line 191 * index that should be removed, then invokes the view helper service to 192 * process the action 193 */ 194 @RequestMapping(method = RequestMethod.POST, params = "methodToCall=deleteLine") 195 public ModelAndView deleteLine(@ModelAttribute("KualiForm") UifFormBase uifForm, BindingResult result, 196 HttpServletRequest request, HttpServletResponse response) { 197 198 String selectedCollectionPath = uifForm.getActionParamaterValue(UifParameters.SELLECTED_COLLECTION_PATH); 199 if (StringUtils.isBlank(selectedCollectionPath)) { 200 throw new RuntimeException("Selected collection was not set for delete line action, cannot delete line"); 201 } 202 203 int selectedLineIndex = -1; 204 String selectedLine = uifForm.getActionParamaterValue(UifParameters.SELECTED_LINE_INDEX); 205 if (StringUtils.isNotBlank(selectedLine)) { 206 selectedLineIndex = Integer.parseInt(selectedLine); 207 } 208 209 if (selectedLineIndex == -1) { 210 throw new RuntimeException("Selected line index was not set for delete line action, cannot delete line"); 211 } 212 213 View view = uifForm.getPostedView(); 214 view.getViewHelperService().processCollectionDeleteLine(view, uifForm, selectedCollectionPath, 215 selectedLineIndex); 216 217 return updateComponent(uifForm, result, request, response); 218 } 219 220 /** 221 * Invoked to toggle the show inactive indicator on the selected collection group and then 222 * rerun the component lifecycle and rendering based on the updated indicator and form data 223 * 224 * @param request - request object that should contain the request component id (for the collection group) 225 * and the show inactive indicator value 226 */ 227 @RequestMapping(method = RequestMethod.POST, params = "methodToCall=toggleInactiveRecordDisplay") 228 public ModelAndView toggleInactiveRecordDisplay(@ModelAttribute("KualiForm") UifFormBase uifForm, 229 BindingResult result, HttpServletRequest request, HttpServletResponse response) { 230 String collectionGroupId = request.getParameter(UifParameters.REQUESTED_COMPONENT_ID); 231 if (StringUtils.isBlank(collectionGroupId)) { 232 throw new RuntimeException( 233 "Collection group id to update for inactive record display not found in request"); 234 } 235 236 String showInactiveStr = request.getParameter(UifParameters.SHOW_INACTIVE_RECORDS); 237 Boolean showInactive = false; 238 if (StringUtils.isNotBlank(showInactiveStr)) { 239 // TODO: should use property editors once we have util class 240 showInactive = (Boolean) (new BooleanFormatter()).convertFromPresentationFormat(showInactiveStr); 241 } else { 242 throw new RuntimeException("Show inactive records flag not found in request"); 243 } 244 245 CollectionGroup collectionGroup = (CollectionGroup) ComponentFactory.getNewInstanceForRefresh( 246 uifForm.getPostedView(), collectionGroupId); 247 248 // update inactive flag on group 249 collectionGroup.setShowInactive(showInactive); 250 251 // run lifecycle and update in view 252 uifForm.getPostedView().getViewHelperService().performComponentLifecycle(uifForm.getPostedView(), uifForm, 253 collectionGroup, collectionGroupId); 254 255 return UifWebUtils.getComponentModelAndView(collectionGroup, uifForm); 256 } 257 258 /** 259 * Just returns as if return with no value was selected. 260 */ 261 @RequestMapping(params = "methodToCall=cancel") 262 public ModelAndView cancel(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result, 263 HttpServletRequest request, HttpServletResponse response) { 264 return close(form, result, request, response); 265 } 266 267 /** 268 * Just returns as if return with no value was selected. 269 */ 270 @RequestMapping(params = "methodToCall=close") 271 public ModelAndView close(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result, 272 HttpServletRequest request, HttpServletResponse response) { 273 Properties props = new Properties(); 274 props.put(UifParameters.METHOD_TO_CALL, UifConstants.MethodToCallNames.REFRESH); 275 if (StringUtils.isNotBlank(form.getReturnFormKey())) { 276 props.put(UifParameters.FORM_KEY, form.getReturnFormKey()); 277 } 278 279 // TODO this needs setup for lightbox and possible home location 280 // property 281 String returnUrl = form.getReturnLocation(); 282 if (StringUtils.isBlank(returnUrl)) { 283 returnUrl = ConfigContext.getCurrentContextConfig().getProperty(KRADConstants.APPLICATION_URL_KEY); 284 } 285 286 // clear current form from session 287 GlobalVariables.getUifFormManager().removeForm(form); 288 289 return performRedirect(form, returnUrl, props); 290 } 291 292 /** 293 * Invoked to navigate back one page in history.. 294 * 295 * @param form - form object that should contain the history object 296 */ 297 @RequestMapping(params = "methodToCall=returnToPrevious") 298 public ModelAndView returnToPrevious(@ModelAttribute("KualiForm") UifFormBase form) { 299 300 return returnToHistory(form, false); 301 } 302 303 /** 304 * Invoked to navigate back to the first page in history. 305 * 306 * @param form - form object that should contain the history object 307 */ 308 @RequestMapping(params = "methodToCall=returnToHub") 309 public ModelAndView returnToHub(@ModelAttribute("KualiForm") UifFormBase form) { 310 311 return returnToHistory(form, true); 312 } 313 314 /** 315 * Invoked to navigate back to a history entry. The homeFlag will determine whether navigation 316 * will be back to the first or last history entry. 317 * 318 * @param form - form object that should contain the history object 319 * @param homeFlag - if true will navigate back to first entry else will navigate to last entry 320 * in the history 321 */ 322 public ModelAndView returnToHistory(UifFormBase form, boolean homeFlag) { 323 // Get the history from the form 324 History hist = form.getFormHistory(); 325 List<HistoryEntry> histEntries = hist.getHistoryEntries(); 326 327 // Get the history page url. Default to the application url if there is no history. 328 String histUrl = null; 329 if (histEntries.isEmpty()) { 330 histUrl = ConfigContext.getCurrentContextConfig().getProperty(KRADConstants.APPLICATION_URL_KEY); 331 } else { 332 // For home get the first entry, for previous get the last entry. 333 // Remove history up to where page is opened 334 if (homeFlag) { 335 histUrl = histEntries.get(0).getUrl(); 336 histEntries.clear(); 337 } else { 338 histUrl = histEntries.get(histEntries.size() - 1).getUrl(); 339 histEntries.remove(histEntries.size() - 1); 340 hist.setCurrent(null); 341 } 342 } 343 344 // Add the refresh call 345 Properties props = new Properties(); 346 props.put(UifParameters.METHOD_TO_CALL, UifConstants.MethodToCallNames.REFRESH); 347 348 // clear current form from session 349 GlobalVariables.getUifFormManager().removeForm(form); 350 351 return performRedirect(form, histUrl, props); 352 } 353 354 /** 355 * Handles menu navigation between view pages 356 */ 357 @RequestMapping(method = RequestMethod.POST, params = "methodToCall=navigate") 358 public ModelAndView navigate(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result, 359 HttpServletRequest request, HttpServletResponse response) { 360 String pageId = form.getActionParamaterValue(UifParameters.NAVIGATE_TO_PAGE_ID); 361 362 // only refreshing page 363 form.setRenderFullView(false); 364 365 return getUIFModelAndView(form, pageId); 366 } 367 368 /** 369 * handles an ajax refresh 370 * 371 * <p>The query form plugin activates this request via a form post, where on the JS side, 372 * {@code org.kuali.rice.krad.uif.UifParameters#RENDER_FULL_VIEW} is set to false</p> 373 * 374 * @param form - Holds properties necessary to determine the <code>View</code> instance that will be used to render the UI 375 * @param result - represents binding results 376 * @param request - http servlet request data 377 * @param response - http servlet response object 378 * @return the ModelAndView object 379 * @throws Exception 380 */ 381 @RequestMapping(params = "methodToCall=refresh") 382 public ModelAndView refresh(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result, 383 HttpServletRequest request, HttpServletResponse response) throws Exception { 384 // TODO: this code still needs to handle reference refreshes 385 String refreshCallerType = ""; 386 if (request.getParameterMap().containsKey(KRADConstants.REFRESH_CALLER_TYPE)) { 387 refreshCallerType = request.getParameter(KRADConstants.REFRESH_CALLER_TYPE); 388 } 389 390 // process multi-value lookup returns 391 if (StringUtils.equals(refreshCallerType, UifConstants.RefreshCallerTypes.MULTI_VALUE_LOOKUP)) { 392 String lookupCollectionName = ""; 393 if (request.getParameterMap().containsKey(UifParameters.LOOKUP_COLLECTION_NAME)) { 394 lookupCollectionName = request.getParameter(UifParameters.LOOKUP_COLLECTION_NAME); 395 } 396 397 if (StringUtils.isBlank(lookupCollectionName)) { 398 throw new RuntimeException( 399 "Lookup collection name is required for processing multi-value lookup results"); 400 } 401 402 String selectedLineValues = ""; 403 if (request.getParameterMap().containsKey(UifParameters.SELECTED_LINE_VALUES)) { 404 selectedLineValues = request.getParameter(UifParameters.SELECTED_LINE_VALUES); 405 } 406 407 // invoked view helper to populate the collection from lookup results 408 form.getPostedView().getViewHelperService().processMultipleValueLookupResults(form.getPostedView(), 409 form, lookupCollectionName, selectedLineValues); 410 } 411 412 if (request.getParameterMap().containsKey(UifParameters.RENDER_FULL_VIEW)) { 413 form.setRenderFullView(Boolean.parseBoolean(request.getParameter(UifParameters.RENDER_FULL_VIEW))); 414 } else { 415 form.setRenderFullView(true); 416 } 417 418 return getUIFModelAndView(form); 419 } 420 421 /** 422 * Updates the current component by retrieving a fresh copy from the dictionary, 423 * running its component lifecycle, and returning it 424 * 425 * @param request - the request must contain reqComponentId that specifies the component to retrieve 426 */ 427 @RequestMapping(method = RequestMethod.POST, params = "methodToCall=updateComponent") 428 public ModelAndView updateComponent(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result, 429 HttpServletRequest request, HttpServletResponse response) { 430 String requestedComponentId = request.getParameter(UifParameters.REQUESTED_COMPONENT_ID); 431 if (StringUtils.isBlank(requestedComponentId)) { 432 throw new RuntimeException("Requested component id for update not found in request"); 433 } 434 435 // get a new instance of the component 436 Component comp = ComponentFactory.getNewInstanceForRefresh(form.getPostedView(), requestedComponentId); 437 438 View postedView = form.getPostedView(); 439 440 // run lifecycle and update in view 441 postedView.getViewHelperService().performComponentLifecycle(postedView, form, comp, 442 requestedComponentId); 443 444 //Regenerate server message content for page 445 postedView.getCurrentPage().getErrorsField().setDisplayNestedMessages(true); 446 postedView.getCurrentPage().getErrorsField().generateMessages(false, postedView, form, 447 postedView.getCurrentPage()); 448 449 return UifWebUtils.getComponentModelAndView(comp, form); 450 } 451 452 /** 453 * Builds up a URL to the lookup view based on the given post action 454 * parameters and redirects 455 */ 456 @RequestMapping(method = RequestMethod.POST, params = "methodToCall=performLookup") 457 public ModelAndView performLookup(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result, 458 HttpServletRequest request, HttpServletResponse response) { 459 Properties lookupParameters = form.getActionParametersAsProperties(); 460 461 String lookupObjectClassName = (String) lookupParameters.get(UifParameters.DATA_OBJECT_CLASS_NAME); 462 Class<?> lookupObjectClass = null; 463 try { 464 lookupObjectClass = Class.forName(lookupObjectClassName); 465 } catch (ClassNotFoundException e) { 466 LOG.error("Unable to get class for name: " + lookupObjectClassName); 467 throw new RuntimeException("Unable to get class for name: " + lookupObjectClassName, e); 468 } 469 470 // get form values for the lookup parameter fields 471 String lookupParameterString = (String) lookupParameters.get(UifParameters.LOOKUP_PARAMETERS); 472 if (lookupParameterString != null) { 473 Map<String, String> lookupParameterFields = KRADUtils.getMapFromParameterString(lookupParameterString); 474 for (Entry<String, String> lookupParameter : lookupParameterFields.entrySet()) { 475 String lookupParameterValue = LookupInquiryUtils.retrieveLookupParameterValue(form, request, 476 lookupObjectClass, lookupParameter.getValue(), lookupParameter.getKey()); 477 478 if (StringUtils.isNotBlank(lookupParameterValue)) { 479 lookupParameters.put(UifPropertyPaths.CRITERIA_FIELDS + "['" + lookupParameter.getValue() + "']", 480 lookupParameterValue); 481 } 482 } 483 } 484 485 // TODO: lookup anchors and doc number? 486 487 String baseLookupUrl = (String) lookupParameters.get(UifParameters.BASE_LOOKUP_URL); 488 lookupParameters.remove(UifParameters.BASE_LOOKUP_URL); 489 490 // set lookup method to call 491 lookupParameters.put(UifParameters.METHOD_TO_CALL, UifConstants.MethodToCallNames.START); 492 String autoSearchString = (String) lookupParameters.get(UifParameters.AUTO_SEARCH); 493 if (Boolean.parseBoolean(autoSearchString)) { 494 lookupParameters.put(UifParameters.METHOD_TO_CALL, UifConstants.MethodToCallNames.SEARCH); 495 } 496 497 lookupParameters.put(UifParameters.RETURN_LOCATION, form.getFormPostUrl()); 498 lookupParameters.put(UifParameters.RETURN_FORM_KEY, form.getFormKey()); 499 500 // special check for external object classes 501 if (lookupObjectClass != null) { 502 ModuleService responsibleModuleService = 503 KRADServiceLocatorWeb.getKualiModuleService().getResponsibleModuleService(lookupObjectClass); 504 if (responsibleModuleService != null && responsibleModuleService.isExternalizable(lookupObjectClass)) { 505 String lookupUrl = responsibleModuleService.getExternalizableDataObjectLookupUrl(lookupObjectClass, 506 lookupParameters); 507 508 Properties externalInquiryProperties = new Properties(); 509 if (lookupParameters.containsKey(UifParameters.LIGHTBOX_CALL)) { 510 externalInquiryProperties.put(UifParameters.LIGHTBOX_CALL, lookupParameters.get( 511 UifParameters.LIGHTBOX_CALL)); 512 } 513 514 return performRedirect(form, lookupUrl, externalInquiryProperties); 515 } 516 } 517 518 return performRedirect(form, baseLookupUrl, lookupParameters); 519 } 520 521 /** 522 * Invoked to provide the options for a suggest widget. The valid options are retrieved by the associated 523 * <code>AttributeQuery</code> for the field containing the suggest widget. The controller method picks 524 * out the query parameters from the request and calls <code>AttributeQueryService</code> to perform the 525 * suggest query and prepare the result object that will be exposed with JSON 526 */ 527 @RequestMapping(method = RequestMethod.GET, params = "methodToCall=performFieldSuggest") 528 public 529 @ResponseBody 530 AttributeQueryResult performFieldSuggest(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result, 531 HttpServletRequest request, HttpServletResponse response) { 532 533 // retrieve query fields from request 534 Map<String, String> queryParameters = new HashMap<String, String>(); 535 for (Object parameterName : request.getParameterMap().keySet()) { 536 if (parameterName.toString().startsWith(UifParameters.QUERY_PARAMETER + ".")) { 537 String fieldName = StringUtils.substringAfter(parameterName.toString(), 538 UifParameters.QUERY_PARAMETER + "."); 539 String fieldValue = request.getParameter(parameterName.toString()); 540 queryParameters.put(fieldName, fieldValue); 541 } 542 } 543 544 // retrieve id for field to perform query for 545 String queryFieldId = request.getParameter(UifParameters.QUERY_FIELD_ID); 546 if (StringUtils.isBlank(queryFieldId)) { 547 throw new RuntimeException("Unable to find id for field to perform query on under request parameter name: " 548 + UifParameters.QUERY_FIELD_ID); 549 } 550 551 // get the field term to match 552 String queryTerm = request.getParameter(UifParameters.QUERY_TERM); 553 if (StringUtils.isBlank(queryTerm)) { 554 throw new RuntimeException( 555 "Unable to find id for query term value for attribute query on under request parameter name: " 556 + UifParameters.QUERY_TERM); 557 } 558 559 // invoke attribute query service to perform the query 560 AttributeQueryResult queryResult = KRADServiceLocatorWeb.getAttributeQueryService().performFieldSuggestQuery( 561 form.getPostedView(), queryFieldId, queryTerm, queryParameters); 562 563 return queryResult; 564 } 565 566 /** 567 * Invoked to execute the <code>AttributeQuery</code> associated with a field given the query parameters 568 * found in the request. This controller method picks out the query parameters from the request and calls 569 * <code>AttributeQueryService</code> to perform the field query and prepare the result object 570 * that will be exposed with JSON. The result is then used to update field values in the UI with client 571 * script. 572 */ 573 @RequestMapping(method = RequestMethod.GET, params = "methodToCall=performFieldQuery") 574 public 575 @ResponseBody 576 AttributeQueryResult performFieldQuery(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result, 577 HttpServletRequest request, HttpServletResponse response) { 578 579 // retrieve query fields from request 580 Map<String, String> queryParameters = new HashMap<String, String>(); 581 for (Object parameterName : request.getParameterMap().keySet()) { 582 if (parameterName.toString().startsWith(UifParameters.QUERY_PARAMETER + ".")) { 583 String fieldName = StringUtils.substringAfter(parameterName.toString(), 584 UifParameters.QUERY_PARAMETER + "."); 585 String fieldValue = request.getParameter(parameterName.toString()); 586 queryParameters.put(fieldName, fieldValue); 587 } 588 } 589 590 // retrieve id for field to perform query for 591 String queryFieldId = request.getParameter(UifParameters.QUERY_FIELD_ID); 592 if (StringUtils.isBlank(queryFieldId)) { 593 throw new RuntimeException("Unable to find id for field to perform query on under request parameter name: " 594 + UifParameters.QUERY_FIELD_ID); 595 } 596 597 // invoke attribute query service to perform the query 598 AttributeQueryResult queryResult = KRADServiceLocatorWeb.getAttributeQueryService().performFieldQuery( 599 form.getPostedView(), queryFieldId, queryParameters); 600 601 return queryResult; 602 } 603 604 /** 605 * Builds a <code>ModelAndView</code> instance configured to redirect to the 606 * URL formed by joining the base URL with the given URL parameters 607 * 608 * @param form - current form instance 609 * @param baseUrl - base url to redirect to 610 * @param urlParameters - properties containing key/value pairs for the url parameters, if null or empty, 611 * the baseUrl will be used as the full URL 612 * @return ModelAndView configured to redirect to the given URL 613 */ 614 protected ModelAndView performRedirect(UifFormBase form, String baseUrl, Properties urlParameters) { 615 // since we are redirecting and will not be rendering the view, we need to reset the view from the previous 616 form.setView(form.getPostedView()); 617 618 // On post redirects we need to make sure we are sending the history forward: 619 urlParameters.setProperty(UifConstants.UrlParams.HISTORY, form.getFormHistory().getHistoryParameterString()); 620 621 // If this is an Light Box call only return the redirectURL view with the URL 622 // set this is to avoid automatic redirect when using light boxes 623 if (urlParameters.get(UifParameters.LIGHTBOX_CALL) != null && 624 urlParameters.get(UifParameters.LIGHTBOX_CALL).equals("true")) { 625 urlParameters.remove(UifParameters.LIGHTBOX_CALL); 626 String redirectUrl = UrlFactory.parameterizeUrl(baseUrl, urlParameters); 627 628 ModelAndView modelAndView = new ModelAndView(UifConstants.SPRING_REDIRECT_ID); 629 modelAndView.addObject("redirectUrl", redirectUrl); 630 return modelAndView; 631 } 632 633 String redirectUrl = UrlFactory.parameterizeUrl(baseUrl, urlParameters); 634 ModelAndView modelAndView = new ModelAndView(REDIRECT_PREFIX + redirectUrl); 635 636 return modelAndView; 637 } 638 639 protected ModelAndView getUIFModelAndView(UifFormBase form) { 640 return getUIFModelAndView(form, form.getPageId()); 641 } 642 643 /** 644 * Configures the <code>ModelAndView</code> instance containing the form 645 * data and pointing to the UIF generic spring view 646 * 647 * @param form - Form instance containing the model data 648 * @param pageId - Id of the page within the view that should be rendered, can 649 * be left blank in which the current or default page is rendered 650 * @return ModelAndView object with the contained form 651 */ 652 protected ModelAndView getUIFModelAndView(UifFormBase form, String pageId) { 653 return UifWebUtils.getUIFModelAndView(form, pageId); 654 } 655 656 // TODO: add getUIFModelAndView that takes in a view id and can perform view switching 657 658 protected ViewService getViewService() { 659 return KRADServiceLocatorWeb.getViewService(); 660 } 661 662}