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