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 }