View Javadoc

1   /**
2    * Copyright 2005-2013 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.krad.web.bind;
17  
18  import org.apache.commons.lang.StringUtils;
19  import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
20  import org.kuali.rice.krad.uif.UifParameters;
21  import org.kuali.rice.krad.uif.view.View;
22  import org.kuali.rice.krad.uif.UifConstants.ViewType;
23  import org.kuali.rice.krad.uif.service.ViewService;
24  import org.kuali.rice.krad.util.KRADUtils;
25  import org.kuali.rice.krad.web.form.UifFormBase;
26  import org.springframework.core.convert.ConversionService;
27  import org.springframework.util.Assert;
28  import org.springframework.validation.AbstractPropertyBindingResult;
29  import org.springframework.web.bind.ServletRequestDataBinder;
30  
31  import javax.servlet.ServletRequest;
32  import javax.servlet.http.HttpServletRequest;
33  import java.util.Map;
34  
35  /**
36   * Override of ServletRequestDataBinder in order to hook in the UifBeanPropertyBindingResult
37   * which instantiates a custom BeanWrapperImpl, and to initialize the view
38   *
39   * @author Kuali Rice Team (rice.collab@kuali.org)
40   */
41  public class UifServletRequestDataBinder extends ServletRequestDataBinder {
42      protected static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(
43              UifServletRequestDataBinder.class);
44  
45      private UifBeanPropertyBindingResult bindingResult;
46      private ConversionService conversionService;
47  
48      public UifServletRequestDataBinder(Object target) {
49          super(target);
50  
51          setBindingErrorProcessor(new UifBindingErrorProcessor());
52      }
53  
54      public UifServletRequestDataBinder(Object target, String name) {
55          super(target, name);
56  
57          setBindingErrorProcessor(new UifBindingErrorProcessor());
58      }
59  
60      /**
61       * Allows for a custom binding result class.
62       *
63       * @see org.springframework.validation.DataBinder#initBeanPropertyAccess()
64       */
65      @Override
66      public void initBeanPropertyAccess() {
67          Assert.state(this.bindingResult == null,
68                  "DataBinder is already initialized - call initBeanPropertyAccess before other configuration methods");
69  
70          this.bindingResult = new UifBeanPropertyBindingResult(getTarget(), getObjectName(), isAutoGrowNestedPaths(),
71                  getAutoGrowCollectionLimit());
72  
73          if (this.conversionService != null) {
74              this.bindingResult.initConversion(this.conversionService);
75          }
76      }
77  
78      /**
79       * Allows for the setting attributes to use to find the data dictionary data from Kuali
80       *
81       * @see org.springframework.validation.DataBinder#getInternalBindingResult()
82       */
83      @Override
84      protected AbstractPropertyBindingResult getInternalBindingResult() {
85          if (this.bindingResult == null) {
86              initBeanPropertyAccess();
87          }
88  
89          return this.bindingResult;
90      }
91  
92      /**
93       * Disallows direct field access for Kuali
94       *
95       * @see org.springframework.validation.DataBinder#initDirectFieldAccess()
96       */
97      @Override
98      public void initDirectFieldAccess() {
99          LOG.error("Direct Field access is not allowed in UifServletRequestDataBinder.");
100         throw new RuntimeException("Direct Field access is not allowed in Kuali");
101     }
102 
103     /**
104      * Performs data binding from servlet request parameters to the form, initializes view object, then calls
105      * {@link org.kuali.rice.krad.web.form.UifFormBase#postBind(javax.servlet.http.HttpServletRequest)}
106      *
107      * <p>
108      * The view is initialized by first looking for the {@code viewId} parameter in the request. If found, the view is
109      * retrieved based on this id. If the id is not present, then an attempt is made to find a view by type. In order
110      * to retrieve a view based on type, the view request parameter {@code viewTypeName} must be present. If all else
111      * fails and the viewId is populated on the form (could be populated from a previous request), this is used to
112      * retrieve the view.
113      * </p>
114      *
115      * <p>
116      * Note the view is not initialized for Ajax requests that perform partial page updates or dialog updates or no
117      * updates at all
118      * </p>
119      *
120      * @param request - HTTP Servlet Request instance
121      */
122     @Override
123     public void bind(ServletRequest request) {
124         super.bind(request);
125 
126         UifFormBase form = (UifFormBase) this.getTarget();
127 
128         // if doing a partial page update or ajax request with no updating, do not initialize view
129         if (!form.isUpdateComponentRequest() && !form.isUpdateNoneRequest() && !form.isUpdateDialogRequest()) {
130             View view = null;
131 
132             // attempt to retrieve a view by unique identifier first, either as request attribute or parameter
133             String viewId = (String) request.getAttribute(UifParameters.VIEW_ID);
134             if (StringUtils.isBlank(viewId)) {
135                 viewId = request.getParameter(UifParameters.VIEW_ID);
136             }
137 
138             if (StringUtils.isNotBlank(viewId)) {
139                 view = getViewService().getViewById(viewId);
140             }
141 
142             // attempt to get view instance by type parameters
143             if (view == null) {
144                 view = getViewByType(request, form);
145             }
146 
147             // if view not found attempt to find one based on the cached form
148             if (view == null) {
149                 view = getViewFromPreviousModel(form);
150 
151                 if (view != null) {
152                     LOG.warn("Obtained viewId from cached form, this may not be safe!");
153                 }
154             }
155 
156             if (view != null) {
157                 form.setViewId(view.getId());
158 
159 
160             } else {
161                 form.setViewId(null);
162             }
163 
164             form.setView(view);
165         }
166 
167         // invoke form callback for custom binding
168         form.postBind((HttpServletRequest) request);
169     }
170 
171     /**
172      * Attempts to get a view instance by looking for a view type name in the request or the form and querying
173      * that view type with the request parameters
174      *
175      * @param request request instance to pull parameters from
176      * @param form form instance to pull values from
177      * @return View instance if found or null
178      */
179     protected View getViewByType(ServletRequest request, UifFormBase form) {
180         View view = null;
181 
182         String viewTypeName = request.getParameter(UifParameters.VIEW_TYPE_NAME);
183         ViewType viewType = StringUtils.isBlank(viewTypeName) ? form.getViewTypeName() : ViewType.valueOf(viewTypeName);
184 
185         if (viewType != null) {
186             Map<String, String> parameterMap = KRADUtils.translateRequestParameterMap(request.getParameterMap());
187             view = getViewService().getViewByType(viewType, parameterMap);
188         }
189 
190         return view;
191     }
192 
193     /**
194      * Attempts to get a view instance based on the view id stored on the form (which might not be populated
195      * from the request but remaining from session)
196      *
197      * @param form form instance to pull view id from
198      * @return View instance associated with form's view id or null if id or view not found
199      */
200     protected View getViewFromPreviousModel(UifFormBase form) {
201         // maybe we have a view id from the session form
202         if (form.getViewId() != null) {
203             return getViewService().getViewById(form.getViewId());
204         }
205 
206         return null;
207     }
208 
209     public ViewService getViewService() {
210         return KRADServiceLocatorWeb.getViewService();
211     }
212 
213 }
214 
215