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.kns.web.spring.controller;
12  
13  import java.util.Collections;
14  import java.util.Enumeration;
15  import java.util.HashMap;
16  import java.util.HashSet;
17  import java.util.Map;
18  import java.util.Map.Entry;
19  import java.util.Properties;
20  import java.util.Set;
21  
22  import javax.servlet.http.HttpServletRequest;
23  import javax.servlet.http.HttpServletResponse;
24  
25  import org.apache.commons.lang.StringUtils;
26  import org.kuali.rice.core.api.config.property.ConfigContext;
27  import org.kuali.rice.core.util.AttributeSet;
28  import org.kuali.rice.kim.api.services.KimApiServiceLocator;
29  import org.kuali.rice.kim.util.KimConstants;
30  import org.kuali.rice.kns.UserSession;
31  import org.kuali.rice.kns.exception.AuthorizationException;
32  import org.kuali.rice.kns.service.KNSServiceLocatorWeb;
33  import org.kuali.rice.kns.service.ModuleService;
34  import org.kuali.rice.kns.service.SessionDocumentService;
35  import org.kuali.rice.kns.uif.UifConstants;
36  import org.kuali.rice.kns.uif.UifParameters;
37  import org.kuali.rice.kns.uif.container.View;
38  import org.kuali.rice.kns.uif.core.Component;
39  import org.kuali.rice.kns.uif.service.ViewService;
40  import org.kuali.rice.kns.uif.field.AttributeQueryResult;
41  import org.kuali.rice.kns.uif.util.ComponentFactory;
42  import org.kuali.rice.kns.uif.util.LookupInquiryUtils;
43  import org.kuali.rice.kns.uif.util.UifWebUtils;
44  import org.kuali.rice.kns.util.GlobalVariables;
45  import org.kuali.rice.kns.util.KNSConstants;
46  import org.kuali.rice.kns.util.KNSUtils;
47  import org.kuali.rice.kns.util.UrlFactory;
48  import org.kuali.rice.kns.util.WebUtils;
49  import org.kuali.rice.kns.web.spring.form.UifFormBase;
50  import org.springframework.validation.BindingResult;
51  import org.springframework.web.bind.annotation.ModelAttribute;
52  import org.springframework.web.bind.annotation.RequestMapping;
53  import org.springframework.web.bind.annotation.RequestMethod;
54  import org.springframework.web.bind.annotation.ResponseBody;
55  import org.springframework.web.servlet.ModelAndView;
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(KNSConstants.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(KNSConstants.USER_SESSION_KEY);
100                 form = getSessionDocumentService().getUifDocumentForm(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         AttributeSet roleQualifier = new AttributeSet(getRoleQualification(form, methodToCall));
153         AttributeSet permissionDetails = KNSUtils.getNamespaceAndActionClass(this.getClass());
154 
155         if (!KimApiServiceLocator.getIdentityManagementService().isAuthorizedByTemplateName(principalId,
156                 KNSConstants.KNS_NAMESPACE, KimConstants.PermissionTemplateNames.USE_SCREEN, permissionDetails,
157                 roleQualifier)) {
158             throw new AuthorizationException(GlobalVariables.getUserSession().getPerson().getPrincipalName(),
159                     methodToCall, this.getClass().getSimpleName());
160         }
161     }
162 
163     /**
164      * Override this method to add data from the form for role qualification in
165      * the authorization check
166      */
167     protected Map<String, String> getRoleQualification(UifFormBase form, String methodToCall) {
168         return new HashMap<String, String>();
169     }
170 
171     /**
172      * Initial method called when requesting a new view instance which forwards
173      * the view for rendering
174      */
175     @RequestMapping(method = RequestMethod.GET, params = "methodToCall=start")
176     public ModelAndView start(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
177             HttpServletRequest request, HttpServletResponse response) {
178 
179         return getUIFModelAndView(form);
180     }
181 
182     /**
183      * Called by the add line action for a new collection line. Method
184      * determines which collection the add action was selected for and invokes
185      * the view helper service to add the line
186      */
187     @RequestMapping(method = RequestMethod.POST, params = "methodToCall=addLine")
188     public ModelAndView addLine(@ModelAttribute("KualiForm") UifFormBase uifForm, BindingResult result,
189             HttpServletRequest request, HttpServletResponse response) {
190 
191         String selectedCollectionPath = uifForm.getActionParamaterValue(UifParameters.SELLECTED_COLLECTION_PATH);
192         if (StringUtils.isBlank(selectedCollectionPath)) {
193             throw new RuntimeException("Selected collection was not set for add line action, cannot add new line");
194         }
195 		
196         View view = uifForm.getPreviousView();
197         view.getViewHelperService().processCollectionAddLine(view, uifForm, selectedCollectionPath);
198 
199         return getUIFModelAndView(uifForm);
200     }
201 
202     /**
203      * Called by the delete line action for a model collection. Method
204      * determines which collection the action was selected for and the line
205      * index that should be removed, then invokes the view helper service to
206      * process the action
207      */
208     @RequestMapping(method = RequestMethod.POST, params = "methodToCall=deleteLine")
209     public ModelAndView deleteLine(@ModelAttribute("KualiForm") UifFormBase uifForm, BindingResult result,
210             HttpServletRequest request, HttpServletResponse response) {
211 
212         String selectedCollectionPath = uifForm.getActionParamaterValue(UifParameters.SELLECTED_COLLECTION_PATH);
213         if (StringUtils.isBlank(selectedCollectionPath)) {
214             throw new RuntimeException("Selected collection was not set for delete line action, cannot delete line");
215         }
216 
217         int selectedLineIndex = -1;
218         String selectedLine = uifForm.getActionParamaterValue(UifParameters.SELECTED_LINE_INDEX);
219         if (StringUtils.isNotBlank(selectedLine)) {
220             selectedLineIndex = Integer.parseInt(selectedLine);
221         }
222 
223         if (selectedLineIndex == -1) {
224             throw new RuntimeException("Selected line index was not set for delete line action, cannot delete line");
225         }
226 
227         View view = uifForm.getPreviousView();
228         view.getViewHelperService().processCollectionDeleteLine(view, uifForm, selectedCollectionPath,
229                 selectedLineIndex);
230 
231         return getUIFModelAndView(uifForm);
232     }
233 
234     @RequestMapping(method = RequestMethod.POST, params = "methodToCall=showInactiveRecords")
235     public ModelAndView showInactiveRecords(@ModelAttribute("KualiForm") UifFormBase uifForm, BindingResult result,
236                                             HttpServletRequest request, HttpServletResponse response) {
237 
238         String selectedCollectionPath = uifForm.getActionParamaterValue(UifParameters.SELLECTED_COLLECTION_PATH);
239         if (StringUtils.isBlank(selectedCollectionPath)) {
240             throw new RuntimeException("Selected collection was not set for show inactive records");
241         }
242 
243         return getUIFModelAndView(uifForm);
244     }
245 
246     @RequestMapping(method = RequestMethod.POST, params = "methodToCall=hideInactiveRecords")
247     public ModelAndView hideInactiveRecords(@ModelAttribute("KualiForm") UifFormBase uifForm, BindingResult result,
248                                             HttpServletRequest request, HttpServletResponse response) {
249 
250         String selectedCollectionPath = uifForm.getActionParamaterValue(UifParameters.SELLECTED_COLLECTION_PATH);
251         if (StringUtils.isBlank(selectedCollectionPath)) {
252             throw new RuntimeException("Selected collection was not set for hide inactive records");
253         }
254 
255         return getUIFModelAndView(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(KNSConstants.APPLICATION_URL_KEY);
284         }
285 
286         return performRedirect(form, returnUrl, props);
287     }
288 
289     /**
290      * Handles menu navigation between view pages
291      */
292     @RequestMapping(method = RequestMethod.POST, params = "methodToCall=navigate")
293     public ModelAndView navigate(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
294             HttpServletRequest request, HttpServletResponse response) {
295         String pageId = form.getActionParamaterValue(UifParameters.NAVIGATE_TO_PAGE_ID);
296 
297         // only refreshing page
298         form.setRenderFullView(false);
299 
300         return getUIFModelAndView(form, form.getViewId(), pageId);
301     }
302 
303     @RequestMapping(params = "methodToCall=refresh")
304     public ModelAndView refresh(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
305             HttpServletRequest request, HttpServletResponse response) throws Exception {
306         // TODO: this code still needs ported with whatever we are supposed
307         // to do on refresh
308         return getUIFModelAndView(form);
309     }
310     
311     /**
312      * This method updates the current component by retrieving a fresh copy from the dictionary,
313      * running its component lifecycle, and returning it.
314      * 
315      * @param form
316      * @param result
317      * @param request - the request must contain reqComponentId that specifies the component to retrieve.
318      * @param response
319      * @return
320      */
321     @RequestMapping(method = RequestMethod.POST, params = "methodToCall=updateComponent")
322     public ModelAndView updateComponent(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
323             HttpServletRequest request, HttpServletResponse response) {
324         
325         Component comp = ComponentFactory.getComponentById(form, request.getParameter("reqComponentId"));
326         
327         return UifWebUtils.getComponentModelAndView(comp, form);
328     }
329 
330     /**
331      * Builds up a URL to the lookup view based on the given post action
332      * parameters and redirects
333      */
334     @RequestMapping(method = RequestMethod.POST, params = "methodToCall=performLookup")
335     public ModelAndView performLookup(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
336             HttpServletRequest request, HttpServletResponse response) {
337         Properties lookupParameters = form.getActionParametersAsProperties();
338 
339         String lookupObjectClassName = (String) lookupParameters.get(UifParameters.DATA_OBJECT_CLASS_NAME);
340         Class<?> lookupObjectClass = null;
341         try {
342             lookupObjectClass = Class.forName(lookupObjectClassName);
343         } catch (ClassNotFoundException e) {
344             LOG.error("Unable to get class for name: " + lookupObjectClassName);
345             throw new RuntimeException("Unable to get class for name: " + lookupObjectClassName, e);
346         }
347 
348         // get form values for the lookup parameter fields
349         String lookupParameterString = (String) lookupParameters.get(UifParameters.LOOKUP_PARAMETERS);
350         if (lookupParameterString != null) {
351             Map<String, String> lookupParameterFields = WebUtils.getMapFromParameterString(lookupParameterString);
352             for (Entry<String, String> lookupParameter : lookupParameterFields.entrySet()) {
353                 String lookupParameterValue = LookupInquiryUtils.retrieveLookupParameterValue(form, request,
354                         lookupObjectClass, lookupParameter.getValue(), lookupParameter.getKey());
355                 if (StringUtils.isNotBlank(lookupParameterValue)) {
356                     lookupParameters.put(lookupParameter.getValue(), lookupParameterValue);
357                 }
358             }
359         }
360 
361         // TODO: lookup anchors and doc number?
362 
363         // TODO: multi-value lookup requests
364 
365         String baseLookupUrl = (String) lookupParameters.get(UifParameters.BASE_LOOKUP_URL);
366         lookupParameters.remove(UifParameters.BASE_LOOKUP_URL);
367 
368         // set lookup method to call
369         lookupParameters.put(UifParameters.METHOD_TO_CALL, UifConstants.MethodToCallNames.START);
370         String autoSearchString = (String) lookupParameters.get(UifParameters.AUTO_SEARCH);
371         if (Boolean.parseBoolean(autoSearchString)) {
372             lookupParameters.put(UifParameters.METHOD_TO_CALL, UifConstants.MethodToCallNames.SEARCH);
373         }
374 
375         lookupParameters.put(UifParameters.RETURN_LOCATION, form.getFormPostUrl());
376         lookupParameters.put(UifParameters.RETURN_FORM_KEY, form.getFormKey());
377 
378         // special check for external object classes
379         if (lookupObjectClass != null) {
380             ModuleService responsibleModuleService = KNSServiceLocatorWeb.getKualiModuleService()
381                     .getResponsibleModuleService(lookupObjectClass);
382             if (responsibleModuleService != null && responsibleModuleService.isExternalizable(lookupObjectClass)) {
383                 Map<String, String> parameterMap = new HashMap<String, String>();
384                 Enumeration<Object> e = lookupParameters.keys();
385                 while (e.hasMoreElements()) {
386                     String paramName = (String) e.nextElement();
387                     parameterMap.put(paramName, lookupParameters.getProperty(paramName));
388                 }
389 
390                 String lookupUrl = responsibleModuleService.getExternalizableBusinessObjectLookupUrl(lookupObjectClass,
391                         parameterMap);
392                 return performRedirect(form, lookupUrl, new Properties());
393             }
394         }
395 
396         return performRedirect(form, baseLookupUrl, lookupParameters);
397     }
398 
399     /**
400      * Invoked to provide the options for a suggest widget. The valid options are retrieved by the associated
401      * <code>AttributeQuery</code> for the field containing the suggest widget. The controller method picks
402      * out the query parameters from the request and calls <code>AttributeQueryService</code> to perform the
403      * suggest query and prepare the result object that will be exposed with JSON
404      */
405     @RequestMapping(method = RequestMethod.GET, params = "methodToCall=performFieldSuggest")
406     public @ResponseBody AttributeQueryResult performFieldSuggest(@ModelAttribute("KualiForm") UifFormBase form,
407             BindingResult result, HttpServletRequest request, HttpServletResponse response) {
408 
409         // retrieve query fields from request
410         Map<String, String> queryParameters = new HashMap<String, String>();
411         for (Object parameterName : request.getParameterMap().keySet()) {
412             if (parameterName.toString().startsWith(UifParameters.QUERY_PARAMETER + ".")) {
413                 String fieldName =
414                         StringUtils.substringAfter(parameterName.toString(), UifParameters.QUERY_PARAMETER + ".");
415                 String fieldValue = request.getParameter(parameterName.toString());
416                 queryParameters.put(fieldName, fieldValue);
417             }
418         }
419 
420         // retrieve id for field to perform query for
421         String queryFieldId = request.getParameter(UifParameters.QUERY_FIELD_ID);
422         if (StringUtils.isBlank(queryFieldId)) {
423             throw new RuntimeException(
424                     "Unable to find id for field to perform query on under request parameter name: " +
425                             UifParameters.QUERY_FIELD_ID);
426         }
427 
428         // get the field term to match
429         String queryTerm = request.getParameter(UifParameters.QUERY_TERM);
430         if (StringUtils.isBlank(queryTerm)) {
431             throw new RuntimeException(
432                     "Unable to find id for query term value for attribute query on under request parameter name: " +
433                             UifParameters.QUERY_TERM);
434         }
435 
436         // invoke attribute query service to perform the query
437         AttributeQueryResult queryResult = KNSServiceLocatorWeb.getAttributeQueryService()
438                 .performFieldSuggestQuery(form.getView(), queryFieldId, queryTerm, queryParameters);
439 
440         return queryResult;
441     }
442 
443     /**
444      * Invoked to execute the <code>AttributeQuery</code> associated with a field given the query parameters
445      * found in the request. This controller method picks out the query parameters from the request and calls
446      * <code>AttributeQueryService</code> to perform the field query and prepare the result object
447      * that will be exposed with JSON. The result is then used to update field values in the UI with client
448      * script.
449      */
450     @RequestMapping(method = RequestMethod.GET, params = "methodToCall=performFieldQuery")
451     public @ResponseBody AttributeQueryResult performFieldQuery(@ModelAttribute("KualiForm") UifFormBase form,
452             BindingResult result, HttpServletRequest request, HttpServletResponse response) {
453 
454         // retrieve query fields from request
455         Map<String, String> queryParameters = new HashMap<String, String>();
456         for (Object parameterName : request.getParameterMap().keySet()) {
457             if (parameterName.toString().startsWith(UifParameters.QUERY_PARAMETER + ".")) {
458                 String fieldName =
459                         StringUtils.substringAfter(parameterName.toString(), UifParameters.QUERY_PARAMETER + ".");
460                 String fieldValue = request.getParameter(parameterName.toString());
461                 queryParameters.put(fieldName, fieldValue);
462             }
463         }
464 
465         // retrieve id for field to perform query for
466         String queryFieldId = request.getParameter(UifParameters.QUERY_FIELD_ID);
467         if (StringUtils.isBlank(queryFieldId)) {
468             throw new RuntimeException(
469                     "Unable to find id for field to perform query on under request parameter name: " +
470                             UifParameters.QUERY_FIELD_ID);
471         }
472 
473         // invoke attribute query service to perform the query
474         AttributeQueryResult queryResult = KNSServiceLocatorWeb.getAttributeQueryService()
475                 .performFieldQuery(form.getView(), queryFieldId, queryParameters);
476 
477         return queryResult;
478     }
479 
480     /**
481      * Builds a <code>ModelAndView</code> instance configured to redirect to the
482      * URL formed by joining the base URL with the given URL parameters
483      * 
484      * @param form
485      *            - current form instance
486      * @param baseUrl
487      *            - base url to redirect to
488      * @param urlParameters
489      *            - properties containing key/value pairs for the url parameters
490      * @return ModelAndView configured to redirect to the given URL
491      */
492     protected ModelAndView performRedirect(UifFormBase form, String baseUrl, Properties urlParameters) {
493         // On post redirects we need to make sure we are sending the history
494         // forward:
495         urlParameters.setProperty(UifConstants.UrlParams.HISTORY, form.getFormHistory().getHistoryParameterString());
496 
497         // If this is an Ajax call only return the redirectURL view with the URL
498         // set this is to avoid automatic redirect when using light boxes
499         if (urlParameters.get("ajaxCall") != null && urlParameters.get("ajaxCall").equals("true")) {
500             urlParameters.remove("ajaxCall");
501             String redirectUrl = UrlFactory.parameterizeUrl(baseUrl, urlParameters);
502 
503             ModelAndView modelAndView = new ModelAndView("redirectURL");
504             modelAndView.addObject("redirectUrl", redirectUrl);
505             return modelAndView;
506         }
507 
508         String redirectUrl = UrlFactory.parameterizeUrl(baseUrl, urlParameters);
509         ModelAndView modelAndView = new ModelAndView(REDIRECT_PREFIX + redirectUrl);
510 
511         return modelAndView;
512     }
513 
514     protected ModelAndView getUIFModelAndView(UifFormBase form) {
515         return getUIFModelAndView(form, form.getViewId(), form.getPageId());
516     }
517 
518     protected ModelAndView getUIFModelAndView(UifFormBase form, String viewId) {
519         return getUIFModelAndView(form, viewId, "");
520     }
521 
522     /**
523      * Configures the <code>ModelAndView</code> instance containing the form
524      * data and pointing to the UIF generic spring view
525      * 
526      * @param form
527      *            - Form instance containing the model data
528      * @param viewId
529      *            - Id of the View to return
530      * @param pageId
531      *            - Id of the page within the view that should be rendered, can
532      *            be left blank in which the current or default page is rendered
533      * @return ModelAndView object with the contained form
534      */
535     protected ModelAndView getUIFModelAndView(UifFormBase form, String viewId, String pageId) {
536         return UifWebUtils.getUIFModelAndView(form, viewId, pageId);
537     }
538 
539     protected ViewService getViewService() {
540         return KNSServiceLocatorWeb.getViewService();
541     }
542 
543     public SessionDocumentService getSessionDocumentService() {
544         return KNSServiceLocatorWeb.getSessionDocumentService();
545     }
546 
547 }