View Javadoc

1   /*
2    * Copyright 2007 The Kuali Foundation Licensed under the Educational Community
3    * License, Version 1.0 (the "License"); you may not use this file except in
4    * compliance with the License. You may obtain a copy of the License at
5    * http://www.opensource.org/licenses/ecl1.php Unless required by applicable law
6    * or agreed to in writing, software distributed under the License is
7    * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
8    * KIND, either express or implied. See the License for the specific language
9    * governing permissions and limitations under the License.
10   */
11  package org.kuali.rice.krad.web.controller;
12  
13  import org.apache.commons.lang.StringUtils;
14  import org.kuali.rice.core.api.config.property.ConfigContext;
15  import org.kuali.rice.core.web.format.BooleanFormatter;
16  import org.kuali.rice.kim.api.services.KimApiServiceLocator;
17  import org.kuali.rice.kim.util.KimConstants;
18  import org.kuali.rice.krad.UserSession;
19  import org.kuali.rice.krad.exception.AuthorizationException;
20  import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
21  import org.kuali.rice.krad.service.ModuleService;
22  import org.kuali.rice.krad.service.SessionDocumentService;
23  import org.kuali.rice.krad.uif.UifConstants;
24  import org.kuali.rice.krad.uif.UifParameters;
25  import org.kuali.rice.krad.uif.UifPropertyPaths;
26  import org.kuali.rice.krad.uif.container.CollectionGroup;
27  import org.kuali.rice.krad.uif.container.View;
28  import org.kuali.rice.krad.uif.core.Component;
29  import org.kuali.rice.krad.uif.field.AttributeQueryResult;
30  import org.kuali.rice.krad.uif.service.ViewService;
31  import org.kuali.rice.krad.uif.util.ComponentFactory;
32  import org.kuali.rice.krad.uif.util.LookupInquiryUtils;
33  import org.kuali.rice.krad.uif.util.UifWebUtils;
34  import org.kuali.rice.krad.util.GlobalVariables;
35  import org.kuali.rice.krad.util.KRADConstants;
36  import org.kuali.rice.krad.util.KRADUtils;
37  import org.kuali.rice.krad.util.UrlFactory;
38  import org.kuali.rice.krad.web.form.UifFormBase;
39  import org.springframework.validation.BindingResult;
40  import org.springframework.web.bind.annotation.ModelAttribute;
41  import org.springframework.web.bind.annotation.RequestMapping;
42  import org.springframework.web.bind.annotation.RequestMethod;
43  import org.springframework.web.bind.annotation.ResponseBody;
44  import org.springframework.web.servlet.ModelAndView;
45  
46  import javax.servlet.http.HttpServletRequest;
47  import javax.servlet.http.HttpServletResponse;
48  import java.util.Collections;
49  import java.util.Enumeration;
50  import java.util.HashMap;
51  import java.util.HashSet;
52  import java.util.Map;
53  import java.util.Map.Entry;
54  import java.util.Properties;
55  import java.util.Set;
56  
57  /**
58   * Base controller class for views within the KRAD User Interface Framework
59   *
60   * Provides common methods such as:
61   *
62   * <ul>
63   * <li>Authorization methods such as method to call check</li>
64   * <li>Preparing the View instance and setup in the returned
65   * <code>ModelAndView</code></li>
66   * </ul>
67   *
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   *
72   * @author Kuali Rice Team (rice.collab@kuali.org)
73   */
74  public abstract class UifControllerBase {
75      private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(UifControllerBase.class);
76  
77      protected static final String REDIRECT_PREFIX = "redirect:";
78      private SessionDocumentService sessionDocumentService;
79  
80      /**
81       * Create/obtain the model(form) object before it is passed
82       * to the Binder/BeanWrapper. This method is not intended to be overridden
83       * by client applications as it handles framework setup and session
84       * maintenance. Clients should override createIntialForm() instead when they
85       * need custom form initialization.
86       */
87      @ModelAttribute(value = "KualiForm")
88      public UifFormBase initForm(HttpServletRequest request) {
89          UifFormBase form = null;
90          String formKeyParam = request.getParameter(UifParameters.FORM_KEY);
91          String documentNumber = request.getParameter(KRADConstants.DOCUMENT_DOCUMENT_NUMBER);
92  
93          if (StringUtils.isNotBlank(formKeyParam)) {
94              form = (UifFormBase) request.getSession().getAttribute(formKeyParam);
95  
96              // retreive from db if form not in session
97              if (form == null) {
98                  UserSession userSession = (UserSession) request.getSession()
99                          .getAttribute(KRADConstants.USER_SESSION_KEY);
100                 form = getSessionDocumentService().getDocumentForm(documentNumber, formKeyParam, userSession,
101                         request.getRemoteAddr());
102             }
103         } else {
104             form = createInitialForm(request);
105         }
106 
107         return form;
108     }
109 
110     /**
111      * Called to create a new model(form) object when
112      * necessary. This usually occurs on the initial request in a conversation
113      * (when the model is not present in the session). This method must be
114      * overridden when extending a controller and using a different form type
115      * than the superclass.
116      */
117     protected abstract UifFormBase createInitialForm(HttpServletRequest request);
118 
119     private Set<String> methodToCallsToNotCheckAuthorization = new HashSet<String>();
120     {
121         methodToCallsToNotCheckAuthorization.add("performLookup");
122         methodToCallsToNotCheckAuthorization.add("performQuestion");
123         methodToCallsToNotCheckAuthorization.add("performQuestionWithInput");
124         methodToCallsToNotCheckAuthorization.add("performQuestionWithInputAgainBecauseOfErrors");
125         methodToCallsToNotCheckAuthorization.add("performQuestionWithoutInput");
126         methodToCallsToNotCheckAuthorization.add("performWorkgroupLookup");
127     }
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         methodToCallsToNotCheckAuthorization.add(methodToCall);
136     }
137 
138     /**
139      * Returns an immutable Set of methodToCall parameters that should not be
140      * checked for authorization.
141      */
142     public Set<String> getMethodToCallsToNotCheckAuthorization() {
143         return Collections.unmodifiableSet(methodToCallsToNotCheckAuthorization);
144     }
145 
146     /**
147      * Override this method to provide controller class-level access controls to
148      * the application.
149      */
150     public void checkAuthorization(UifFormBase form, String methodToCall) throws AuthorizationException {
151         String principalId = GlobalVariables.getUserSession().getPrincipalId();
152         Map<String, String> roleQualifier = new HashMap<String, String>(getRoleQualification(form, methodToCall));
153         Map<String, String> permissionDetails = KRADUtils.getNamespaceAndActionClass(this.getClass());
154 
155         if (!KimApiServiceLocator.getPermissionService()
156                 .isAuthorizedByTemplateName(principalId, KRADConstants.KRAD_NAMESPACE,
157                         KimConstants.PermissionTemplateNames.USE_SCREEN, permissionDetails,
158                         roleQualifier)) {
159             throw new AuthorizationException(GlobalVariables.getUserSession().getPerson().getPrincipalName(),
160                     methodToCall, this.getClass().getSimpleName());
161         }
162     }
163 
164     /**
165      * Override this method to add data from the form for role qualification in
166      * the authorization check
167      */
168     protected Map<String, String> getRoleQualification(UifFormBase form, String methodToCall) {
169         return new HashMap<String, String>();
170     }
171 
172     /**
173      * Initial method called when requesting a new view instance which forwards
174      * the view for rendering
175      */
176     @RequestMapping(method = RequestMethod.GET, params = "methodToCall=start")
177     public ModelAndView start(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
178             HttpServletRequest request, HttpServletResponse response) {
179 
180         return getUIFModelAndView(form);
181     }
182 
183     /**
184      * Called by the add line action for a new collection line. Method
185      * determines which collection the add action was selected for and invokes
186      * the view helper service to add the line
187      */
188     @RequestMapping(method = RequestMethod.POST, params = "methodToCall=addLine")
189     public ModelAndView addLine(@ModelAttribute("KualiForm") UifFormBase uifForm, BindingResult result,
190             HttpServletRequest request, HttpServletResponse response) {
191 
192         String selectedCollectionPath = uifForm.getActionParamaterValue(UifParameters.SELLECTED_COLLECTION_PATH);
193         if (StringUtils.isBlank(selectedCollectionPath)) {
194             throw new RuntimeException("Selected collection was not set for add line action, cannot add new line");
195         }
196 
197         View view = uifForm.getPreviousView();
198         view.getViewHelperService().processCollectionAddLine(view, uifForm, selectedCollectionPath);
199 
200         return getUIFModelAndView(uifForm);
201     }
202 
203     /**
204      * Called by the delete line action for a model collection. Method
205      * determines which collection the action was selected for and the line
206      * index that should be removed, then invokes the view helper service to
207      * process the action
208      */
209     @RequestMapping(method = RequestMethod.POST, params = "methodToCall=deleteLine")
210     public ModelAndView deleteLine(@ModelAttribute("KualiForm") UifFormBase uifForm, BindingResult result,
211             HttpServletRequest request, HttpServletResponse response) {
212 
213         String selectedCollectionPath = uifForm.getActionParamaterValue(UifParameters.SELLECTED_COLLECTION_PATH);
214         if (StringUtils.isBlank(selectedCollectionPath)) {
215             throw new RuntimeException("Selected collection was not set for delete line action, cannot delete line");
216         }
217 
218         int selectedLineIndex = -1;
219         String selectedLine = uifForm.getActionParamaterValue(UifParameters.SELECTED_LINE_INDEX);
220         if (StringUtils.isNotBlank(selectedLine)) {
221             selectedLineIndex = Integer.parseInt(selectedLine);
222         }
223 
224         if (selectedLineIndex == -1) {
225             throw new RuntimeException("Selected line index was not set for delete line action, cannot delete line");
226         }
227 
228         View view = uifForm.getPreviousView();
229         view.getViewHelperService().processCollectionDeleteLine(view, uifForm, selectedCollectionPath,
230                 selectedLineIndex);
231 
232         return getUIFModelAndView(uifForm);
233     }
234 
235     /**
236      * Invoked to toggle the show inactive indicator on the selected collection group and then
237      * rerun the component lifecycle and rendering based on the updated indicator and form data
238      *
239      * @param request - request object that should contain the request component id (for the collection group)
240      * and the show inactive indicator value
241      */
242     @RequestMapping(method = RequestMethod.POST, params = "methodToCall=toggleInactiveRecordDisplay")
243     public ModelAndView toggleInactiveRecordDisplay(@ModelAttribute("KualiForm") UifFormBase uifForm,
244             BindingResult result, HttpServletRequest request, HttpServletResponse response) {
245         String collectionGroupId = request.getParameter(UifParameters.REQUESTED_COMPONENT_ID);
246         if (StringUtils.isBlank(collectionGroupId)) {
247             throw new RuntimeException(
248                     "Collection group id to update for inactive record display not found in request");
249         }
250 
251         String showInactiveStr = request.getParameter(UifParameters.SHOW_INACTIVE_RECORDS);
252         Boolean showInactive = false;
253         if (StringUtils.isNotBlank(showInactiveStr)) {
254             // TODO: should use property editors once we have util class
255             showInactive = (Boolean) (new BooleanFormatter()).convertFromPresentationFormat(showInactiveStr);
256         } else {
257             throw new RuntimeException("Show inactive records flag not found in request");
258         }
259 
260         CollectionGroup collectionGroup = (CollectionGroup) ComponentFactory.getComponentById(uifForm, collectionGroupId);
261 
262         // update inactive flag on group
263         collectionGroup.setShowInactive(showInactive);
264 
265         // run lifecycle and update in view
266         uifForm.getView().getViewHelperService().performComponentLifecycle(uifForm, collectionGroup, collectionGroupId);
267         uifForm.getView().getViewIndex().indexComponent(collectionGroup);
268 
269         return UifWebUtils.getComponentModelAndView(collectionGroup, uifForm);
270     }
271 
272     /**
273      * Just returns as if return with no value was selected.
274      */
275     @RequestMapping(params = "methodToCall=cancel")
276     public ModelAndView cancel(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
277             HttpServletRequest request, HttpServletResponse response) {
278         return close(form, result, request, response);
279     }
280 
281     /**
282      * Just returns as if return with no value was selected.
283      */
284     @RequestMapping(params = "methodToCall=close")
285     public ModelAndView close(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
286             HttpServletRequest request, HttpServletResponse response) {
287         Properties props = new Properties();
288         props.put(UifParameters.METHOD_TO_CALL, UifConstants.MethodToCallNames.REFRESH);
289         if (StringUtils.isNotBlank(form.getReturnFormKey())) {
290             props.put(UifParameters.FORM_KEY, form.getReturnFormKey());
291         }
292 
293         // TODO this needs setup for lightbox and possible home location
294         // property
295         String returnUrl = form.getReturnLocation();
296         if (StringUtils.isBlank(returnUrl)) {
297             returnUrl = ConfigContext.getCurrentContextConfig().getProperty(KRADConstants.APPLICATION_URL_KEY);
298         }
299 
300         return performRedirect(form, returnUrl, props);
301     }
302 
303     /**
304      * Handles menu navigation between view pages
305      */
306     @RequestMapping(method = RequestMethod.POST, params = "methodToCall=navigate")
307     public ModelAndView navigate(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
308             HttpServletRequest request, HttpServletResponse response) {
309         String pageId = form.getActionParamaterValue(UifParameters.NAVIGATE_TO_PAGE_ID);
310 
311         // only refreshing page
312         form.setRenderFullView(false);
313 
314         return getUIFModelAndView(form, form.getViewId(), pageId);
315     }
316 
317     @RequestMapping(params = "methodToCall=refresh")
318     public ModelAndView refresh(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
319             HttpServletRequest request, HttpServletResponse response) throws Exception {
320         // TODO: this code still needs ported with whatever we are supposed
321         // to do on refresh
322         return getUIFModelAndView(form);
323     }
324 
325     /**
326      * Updates the current component by retrieving a fresh copy from the dictionary,
327      * running its component lifecycle, and returning it
328      *
329      * @param request - the request must contain reqComponentId that specifies the component to retrieve
330      */
331     @RequestMapping(method = RequestMethod.POST, params = "methodToCall=updateComponent")
332     public ModelAndView updateComponent(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
333             HttpServletRequest request, HttpServletResponse response) {
334         String requestedComponentId = request.getParameter(UifParameters.REQUESTED_COMPONENT_ID);
335         if (StringUtils.isBlank(requestedComponentId)) {
336             throw new RuntimeException("Requested component id for update not found in request");
337         }
338 
339         Component comp = ComponentFactory.getComponentByIdWithLifecycle(form, requestedComponentId);
340 
341         return UifWebUtils.getComponentModelAndView(comp, form);
342     }
343 
344     /**
345      * Builds up a URL to the lookup view based on the given post action
346      * parameters and redirects
347      */
348     @RequestMapping(method = RequestMethod.POST, params = "methodToCall=performLookup")
349     public ModelAndView performLookup(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
350             HttpServletRequest request, HttpServletResponse response) {
351         Properties lookupParameters = form.getActionParametersAsProperties();
352 
353         String lookupObjectClassName = (String) lookupParameters.get(UifParameters.DATA_OBJECT_CLASS_NAME);
354         Class<?> lookupObjectClass = null;
355         try {
356             lookupObjectClass = Class.forName(lookupObjectClassName);
357         } catch (ClassNotFoundException e) {
358             LOG.error("Unable to get class for name: " + lookupObjectClassName);
359             throw new RuntimeException("Unable to get class for name: " + lookupObjectClassName, e);
360         }
361 
362         // get form values for the lookup parameter fields
363         String lookupParameterString = (String) lookupParameters.get(UifParameters.LOOKUP_PARAMETERS);
364         if (lookupParameterString != null) {
365             Map<String, String> lookupParameterFields = KRADUtils.getMapFromParameterString(lookupParameterString);
366             for (Entry<String, String> lookupParameter : lookupParameterFields.entrySet()) {
367                 String lookupParameterValue = LookupInquiryUtils.retrieveLookupParameterValue(form, request,
368                         lookupObjectClass, lookupParameter.getValue(), lookupParameter.getKey());
369 
370                 if (StringUtils.isNotBlank(lookupParameterValue)) {
371                     lookupParameters.put(UifPropertyPaths.CRITERIA_FIELDS + "['" + lookupParameter.getValue() + "']",
372                             lookupParameterValue);
373                 }
374             }
375         }
376 
377         // TODO: lookup anchors and doc number?
378 
379         // TODO: multi-value lookup requests
380 
381         String baseLookupUrl = (String) lookupParameters.get(UifParameters.BASE_LOOKUP_URL);
382         lookupParameters.remove(UifParameters.BASE_LOOKUP_URL);
383 
384         // set lookup method to call
385         lookupParameters.put(UifParameters.METHOD_TO_CALL, UifConstants.MethodToCallNames.START);
386         String autoSearchString = (String) lookupParameters.get(UifParameters.AUTO_SEARCH);
387         if (Boolean.parseBoolean(autoSearchString)) {
388             lookupParameters.put(UifParameters.METHOD_TO_CALL, UifConstants.MethodToCallNames.SEARCH);
389         }
390 
391         lookupParameters.put(UifParameters.RETURN_LOCATION, form.getFormPostUrl());
392         lookupParameters.put(UifParameters.RETURN_FORM_KEY, form.getFormKey());
393 
394         // special check for external object classes
395         if (lookupObjectClass != null) {
396             ModuleService responsibleModuleService = KRADServiceLocatorWeb.getKualiModuleService()
397                     .getResponsibleModuleService(lookupObjectClass);
398             if (responsibleModuleService != null && responsibleModuleService.isExternalizable(lookupObjectClass)) {
399                 Map<String, String> parameterMap = new HashMap<String, String>();
400                 Enumeration<Object> e = lookupParameters.keys();
401                 while (e.hasMoreElements()) {
402                     String paramName = (String) e.nextElement();
403                     parameterMap.put(paramName, lookupParameters.getProperty(paramName));
404                 }
405 
406                 String lookupUrl = responsibleModuleService.getExternalizableBusinessObjectLookupUrl(lookupObjectClass,
407                         parameterMap);
408                 return performRedirect(form, lookupUrl, new Properties());
409             }
410         }
411 
412         return performRedirect(form, baseLookupUrl, lookupParameters);
413     }
414 
415     /**
416      * Invoked to provide the options for a suggest widget. The valid options are retrieved by the associated
417      * <code>AttributeQuery</code> for the field containing the suggest widget. The controller method picks
418      * out the query parameters from the request and calls <code>AttributeQueryService</code> to perform the
419      * suggest query and prepare the result object that will be exposed with JSON
420      */
421     @RequestMapping(method = RequestMethod.GET, params = "methodToCall=performFieldSuggest")
422     public @ResponseBody AttributeQueryResult performFieldSuggest(@ModelAttribute("KualiForm") UifFormBase form,
423             BindingResult result, HttpServletRequest request, HttpServletResponse response) {
424 
425         // retrieve query fields from request
426         Map<String, String> queryParameters = new HashMap<String, String>();
427         for (Object parameterName : request.getParameterMap().keySet()) {
428             if (parameterName.toString().startsWith(UifParameters.QUERY_PARAMETER + ".")) {
429                 String fieldName =
430                         StringUtils.substringAfter(parameterName.toString(), UifParameters.QUERY_PARAMETER + ".");
431                 String fieldValue = request.getParameter(parameterName.toString());
432                 queryParameters.put(fieldName, fieldValue);
433             }
434         }
435 
436         // retrieve id for field to perform query for
437         String queryFieldId = request.getParameter(UifParameters.QUERY_FIELD_ID);
438         if (StringUtils.isBlank(queryFieldId)) {
439             throw new RuntimeException(
440                     "Unable to find id for field to perform query on under request parameter name: " +
441                             UifParameters.QUERY_FIELD_ID);
442         }
443 
444         // get the field term to match
445         String queryTerm = request.getParameter(UifParameters.QUERY_TERM);
446         if (StringUtils.isBlank(queryTerm)) {
447             throw new RuntimeException(
448                     "Unable to find id for query term value for attribute query on under request parameter name: " +
449                             UifParameters.QUERY_TERM);
450         }
451 
452         // invoke attribute query service to perform the query
453         AttributeQueryResult queryResult = KRADServiceLocatorWeb.getAttributeQueryService()
454                 .performFieldSuggestQuery(form.getView(), queryFieldId, queryTerm, queryParameters);
455 
456         return queryResult;
457     }
458 
459     /**
460      * Invoked to execute the <code>AttributeQuery</code> associated with a field given the query parameters
461      * found in the request. This controller method picks out the query parameters from the request and calls
462      * <code>AttributeQueryService</code> to perform the field query and prepare the result object
463      * that will be exposed with JSON. The result is then used to update field values in the UI with client
464      * script.
465      */
466     @RequestMapping(method = RequestMethod.GET, params = "methodToCall=performFieldQuery")
467     public @ResponseBody AttributeQueryResult performFieldQuery(@ModelAttribute("KualiForm") UifFormBase form,
468             BindingResult result, HttpServletRequest request, HttpServletResponse response) {
469 
470         // retrieve query fields from request
471         Map<String, String> queryParameters = new HashMap<String, String>();
472         for (Object parameterName : request.getParameterMap().keySet()) {
473             if (parameterName.toString().startsWith(UifParameters.QUERY_PARAMETER + ".")) {
474                 String fieldName =
475                         StringUtils.substringAfter(parameterName.toString(), UifParameters.QUERY_PARAMETER + ".");
476                 String fieldValue = request.getParameter(parameterName.toString());
477                 queryParameters.put(fieldName, fieldValue);
478             }
479         }
480 
481         // retrieve id for field to perform query for
482         String queryFieldId = request.getParameter(UifParameters.QUERY_FIELD_ID);
483         if (StringUtils.isBlank(queryFieldId)) {
484             throw new RuntimeException(
485                     "Unable to find id for field to perform query on under request parameter name: " +
486                             UifParameters.QUERY_FIELD_ID);
487         }
488 
489         // invoke attribute query service to perform the query
490         AttributeQueryResult queryResult = KRADServiceLocatorWeb.getAttributeQueryService()
491                 .performFieldQuery(form.getView(), queryFieldId, queryParameters);
492 
493         return queryResult;
494     }
495 
496     /**
497      * Builds a <code>ModelAndView</code> instance configured to redirect to the
498      * URL formed by joining the base URL with the given URL parameters
499      *
500      * @param form
501      *            - current form instance
502      * @param baseUrl
503      *            - base url to redirect to
504      * @param urlParameters
505      *            - properties containing key/value pairs for the url parameters
506      * @return ModelAndView configured to redirect to the given URL
507      */
508     protected ModelAndView performRedirect(UifFormBase form, String baseUrl, Properties urlParameters) {
509         // On post redirects we need to make sure we are sending the history
510         // forward:
511         urlParameters.setProperty(UifConstants.UrlParams.HISTORY, form.getFormHistory().getHistoryParameterString());
512 
513         // If this is an Ajax call only return the redirectURL view with the URL
514         // set this is to avoid automatic redirect when using light boxes
515         if (urlParameters.get("ajaxCall") != null && urlParameters.get("ajaxCall").equals("true")) {
516             urlParameters.remove("ajaxCall");
517             String redirectUrl = UrlFactory.parameterizeUrl(baseUrl, urlParameters);
518 
519             ModelAndView modelAndView = new ModelAndView("redirectURL");
520             modelAndView.addObject("redirectUrl", redirectUrl);
521             return modelAndView;
522         }
523 
524         String redirectUrl = UrlFactory.parameterizeUrl(baseUrl, urlParameters);
525         ModelAndView modelAndView = new ModelAndView(REDIRECT_PREFIX + redirectUrl);
526 
527         return modelAndView;
528     }
529 
530     protected ModelAndView getUIFModelAndView(UifFormBase form) {
531         return getUIFModelAndView(form, form.getViewId(), form.getPageId());
532     }
533 
534     protected ModelAndView getUIFModelAndView(UifFormBase form, String viewId) {
535         return getUIFModelAndView(form, viewId, "");
536     }
537 
538     /**
539      * Configures the <code>ModelAndView</code> instance containing the form
540      * data and pointing to the UIF generic spring view
541      *
542      * @param form
543      *            - Form instance containing the model data
544      * @param viewId
545      *            - Id of the View to return
546      * @param pageId
547      *            - Id of the page within the view that should be rendered, can
548      *            be left blank in which the current or default page is rendered
549      * @return ModelAndView object with the contained form
550      */
551     protected ModelAndView getUIFModelAndView(UifFormBase form, String viewId, String pageId) {
552         return UifWebUtils.getUIFModelAndView(form, viewId, pageId);
553     }
554 
555     protected ViewService getViewService() {
556         return KRADServiceLocatorWeb.getViewService();
557     }
558 
559     public SessionDocumentService getSessionDocumentService() {
560         return KRADServiceLocatorWeb.getSessionDocumentService();
561     }
562 
563 }