View Javadoc

1   /*
2    * Copyright 2011 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.uif.util;
12  
13  import org.apache.commons.lang.StringUtils;
14  import org.apache.log4j.Logger;
15  import org.kuali.rice.krad.UserSession;
16  import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
17  import org.kuali.rice.krad.service.SessionDocumentService;
18  import org.kuali.rice.krad.uif.UifConstants;
19  import org.kuali.rice.krad.uif.UifParameters;
20  import org.kuali.rice.krad.uif.container.View;
21  import org.kuali.rice.krad.uif.core.Component;
22  import org.kuali.rice.krad.uif.history.History;
23  import org.kuali.rice.krad.uif.service.ViewService;
24  import org.kuali.rice.krad.util.KRADConstants;
25  import org.kuali.rice.krad.web.controller.UifControllerBase;
26  import org.kuali.rice.krad.web.form.DocumentFormBase;
27  import org.kuali.rice.krad.web.form.UifFormBase;
28  import org.springframework.web.servlet.ModelAndView;
29  
30  import javax.servlet.http.HttpServletRequest;
31  import javax.servlet.http.HttpServletResponse;
32  
33  /**
34   * Provides helper methods that will be used during the request lifecycle
35   *
36   * <p>
37   * Created to avoid duplication of the methods used by the UifHandlerExceptionResolver
38   * </p>
39   *
40   * @author Kuali Rice Team (rice.collab@kuali.org)
41   */
42  public class UifWebUtils {
43  
44      private static final Logger LOG = Logger.getLogger(UifWebUtils.class);
45  
46      /**
47       * Gets the form from the request
48       *
49       * <p>
50       * Looks for the form on the session by using the form key. If the form is not
51       * on the session it will attempt to get it from the database.
52       * </p>
53       *
54       * @param request the http request
55       * @return the form from request
56       */
57      public static UifFormBase getFormFromRequest(HttpServletRequest request) {
58          UifFormBase form = null;
59  
60          String formKeyParam = request.getParameter(UifParameters.FORM_KEY);
61          String docId = request.getParameter(KRADConstants.DOCUMENT_DOCUMENT_NUMBER);
62          if (StringUtils.isNotBlank(formKeyParam)) {
63              form = (UifFormBase) request.getSession().getAttribute(formKeyParam);
64              // retreive from db if form not in session
65              if (form == null) {
66                  UserSession userSession =
67                          (UserSession) request.getSession().getAttribute(KRADConstants.USER_SESSION_KEY);
68                  form = KRADServiceLocatorWeb.getSessionDocumentService()
69                          .getDocumentForm(docId, formKeyParam, userSession, request.getRemoteAddr());
70              }
71          }
72  
73          return form;
74      }
75  
76      /**
77       * Configures the <code>ModelAndView</code> instance containing the form
78       * data and pointing to the UIF generic spring view
79       *
80       * @param form - Form instance containing the model data
81       * @param viewId - Id of the View to return
82       * @param pageId - Id of the page within the view that should be rendered, can
83       * be left blank in which the current or default page is rendered
84       * @return ModelAndView object with the contained form
85       */
86      public static ModelAndView getUIFModelAndView(UifFormBase form, String viewId, String pageId) {
87          // update form with the requested view id and page
88          form.setViewId(viewId);
89          if (StringUtils.isNotBlank(pageId)) {
90              form.setPageId(pageId);
91          }
92  
93          // create the spring return object pointing to View.jsp
94          ModelAndView modelAndView = new ModelAndView();
95          modelAndView.addObject(UifConstants.DEFAULT_MODEL_NAME, form);
96          modelAndView.setViewName(UifConstants.SPRING_VIEW_ID);
97  
98          return modelAndView;
99      }
100 
101     public static ModelAndView getComponentModelAndView(Component component, Object model) {
102         ModelAndView modelAndView = new ModelAndView();
103         modelAndView.addObject(UifConstants.DEFAULT_MODEL_NAME, model);
104         modelAndView.addObject("Component", component);
105         modelAndView.setViewName("ComponentUpdate");
106 
107         return modelAndView;
108     }
109 
110     /**
111      * After the controller logic is executed, the form is placed into session
112      * and the corresponding view is prepared for rendering
113      */
114     public static void postControllerHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
115             ModelAndView modelAndView) throws Exception {
116         if (handler instanceof UifControllerBase && (modelAndView != null)) {
117             UifControllerBase controller = (UifControllerBase) handler;
118             UifFormBase form = null;
119 
120             // check to see if this is a full view request
121             if (modelAndView.getViewName().equals(UifConstants.SPRING_VIEW_ID)) {
122                 Object model = modelAndView.getModelMap().get(UifConstants.DEFAULT_MODEL_NAME);
123                 if (model instanceof UifFormBase) {
124                     form = (UifFormBase) model;
125 
126                     form.setPreviousView(null);
127 
128                     // update history for view
129                     prepareHistory(request, form);
130 
131                     // store form to session and persist document form to db as well
132                     request.getSession().setAttribute(form.getFormKey(), model);
133                     if (form instanceof DocumentFormBase) {
134                         UserSession userSession =
135                                 (UserSession) request.getSession().getAttribute(KRADConstants.USER_SESSION_KEY);
136                         getSessionDocumentService()
137                                 .setDocumentForm((DocumentFormBase) form, userSession, request.getRemoteAddr());
138                     }
139 
140                     // perform authorization of controller method
141                     checkMethodToCallAuthorization(request, controller, form);
142 
143                     // prepare view contained in form
144                     prepareViewForRendering(form);
145                 }
146             }
147         }
148     }
149 
150     /**
151      * Verify the user is authorized to invoke the controller method according
152      * to the module that owns the functionality. This is done post handle to be
153      * able to access the form and whatever processing was done TODO: should
154      * this be throwing some exception?
155      *
156      * @param request - current HTTP request containing method to call parameter
157      * @param controller - controller that was invoked
158      * @param form - form instance containing the data
159      */
160     public static void checkMethodToCallAuthorization(HttpServletRequest request, UifControllerBase controller,
161             UifFormBase form) {
162         // currently methodToCall must be a regularly parseable request
163         // parameter, so just get from request
164         String methodToCall = request.getParameter(KRADConstants.DISPATCH_REQUEST_PARAMETER);
165 
166         if (!controller.getMethodToCallsToNotCheckAuthorization().contains(methodToCall)) {
167             if (LOG.isDebugEnabled()) {
168                 LOG.debug("'" + methodToCall + "' not in set of excempt methods: " +
169                         controller.getMethodToCallsToNotCheckAuthorization());
170             }
171 
172             controller.checkAuthorization(form, methodToCall);
173         } else {
174             if (LOG.isDebugEnabled()) {
175                 LOG.debug("'" + methodToCall + "' is exempt from auth checks.");
176             }
177         }
178     }
179 
180     /**
181      * Updates the history object (or constructs a new History) for the view we are getting ready
182      * to render
183      *
184      * @param request - Http request object containing the request parameters
185      * @param form - object containing the view data
186      */
187     public static void prepareHistory(HttpServletRequest request, UifFormBase form) {
188         View view = form.getView();
189 
190         // main history/breadcrumb tracking support
191         History history = form.getFormHistory();
192         if (history == null || request.getMethod().equals("GET")) {
193             history = new History();
194             history.setHomewardPath(view.getBreadcrumbs().getHomewardPathList());
195             history.setAppendHomewardPath(view.getBreadcrumbs().isDisplayHomewardPath());
196             history.setAppendPassedHistory(view.getBreadcrumbs().isDisplayPassedHistory());
197 
198             // passed settings ALWAYS override the defaults
199             if (StringUtils.isNotBlank(request.getParameter(UifConstants.UrlParams.SHOW_HOME))) {
200                 history.setAppendHomewardPath(
201                         Boolean.parseBoolean(request.getParameter(UifConstants.UrlParams.SHOW_HOME)));
202             }
203 
204             if (StringUtils.isNotBlank(request.getParameter(UifConstants.UrlParams.SHOW_HISTORY))) {
205                 history.setAppendPassedHistory(
206                         Boolean.parseBoolean(request.getParameter(UifConstants.UrlParams.SHOW_HISTORY)));
207             }
208 
209             history.setCurrent(form, request);
210             history.buildHistoryFromParameterString(request.getParameter(UifConstants.UrlParams.HISTORY));
211             form.setFormHistory(history);
212         }
213     }
214 
215     /**
216      * Prepares the <code>View</code> instance contained on the form for
217      * rendering
218      *
219      * <p>
220      * First a check is made to verify the view instance contained on the form
221      * has the same id as the view id on the form (id that was requested), if
222      * not a new view instance is retrieved for that view id. Then a check on
223      * the view status is made to determine if we need to run the full view
224      * life-cycle (in the case of a finalized view), or just the build steps
225      * (apply model and finalize). Finally the page is set on the view to
226      * reflect the page that was requested
227      * </p>
228      *
229      * @param form - form instance containing the data and view instance
230      */
231     public static void prepareViewForRendering(UifFormBase form) {
232         // if we don't have the view instance or a different view was
233         // requested get new instance from the view service
234         View view = form.getView();
235         String viewId = form.getViewId();
236         if ((view == null) || !StringUtils.equals(viewId, view.getId())) {
237             if (LOG.isDebugEnabled()) {
238                 LOG.debug("Getting new view instance for view id: " + viewId);
239             }
240 
241             view = getViewService().getView(viewId, form.getViewRequestParameters());
242 
243             // view changed so force full render
244             form.setRenderFullView(true);
245         }
246 
247         // if view status is final we need to rebuild (build fresh)
248         if (StringUtils.equals(UifConstants.ViewStatus.FINAL, view.getViewStatus())) {
249             if (LOG.isDebugEnabled()) {
250                 LOG.debug("Rebuilding view due to final status, view id: " + viewId);
251             }
252 
253             view = getViewService().rebuildView(viewId, form, form.getViewRequestParameters());
254         } else {
255             // update the view with the model data
256             getViewService().buildView(view, form);
257         }
258 
259         // set dirty flag
260         form.setValidateDirty(view.isValidateDirty());
261 
262         // set view page to page requested on form
263         if (StringUtils.isNotBlank(form.getPageId())) {
264             view.setCurrentPageId(form.getPageId());
265         }
266     }
267 
268     protected static SessionDocumentService getSessionDocumentService() {
269         return KRADServiceLocatorWeb.getSessionDocumentService();
270     }
271 
272     protected static ViewService getViewService() {
273         return KRADServiceLocatorWeb.getViewService();
274     }
275 }