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.
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          setBindingErrorProcessor(new UifBindingErrorProcessor());
51      }
52  
53      public UifServletRequestDataBinder(Object target, String name) {
54          super(target, name);
55          setBindingErrorProcessor(new UifBindingErrorProcessor());
56      }
57  
58      /**
59       * Allows for a custom binding result class.
60       *
61       * @see org.springframework.validation.DataBinder#initBeanPropertyAccess()
62       */
63      @Override
64      public void initBeanPropertyAccess() {
65          Assert.state(this.bindingResult == null,
66                  "DataBinder is already initialized - call initBeanPropertyAccess before other configuration methods");
67          this.bindingResult = new UifBeanPropertyBindingResult(getTarget(), getObjectName(), isAutoGrowNestedPaths(),
68                  getAutoGrowCollectionLimit());
69          if (this.conversionService != null) {
70              this.bindingResult.initConversion(this.conversionService);
71          }
72      }
73  
74      /**
75       * Allows for the setting attributes to use to find the data dictionary data from Kuali
76       *
77       * @see org.springframework.validation.DataBinder#getInternalBindingResult()
78       */
79      @Override
80      protected AbstractPropertyBindingResult getInternalBindingResult() {
81          if (this.bindingResult == null) {
82              initBeanPropertyAccess();
83          }
84          return this.bindingResult;
85      }
86  
87      /**
88       * Disallows direct field access for Kuali
89       *
90       * @see org.springframework.validation.DataBinder#initDirectFieldAccess()
91       */
92      @Override
93      public void initDirectFieldAccess() {
94          LOG.error("Direct Field access is not allowed in UifServletRequestDataBinder.");
95          throw new RuntimeException("Direct Field access is not allowed in Kuali");
96      }
97  
98      /**
99       * Performs data binding from servlet request parameters to the form, initializes view object, then calls
100      * {@link org.kuali.rice.krad.web.form.UifFormBase#postBind(javax.servlet.http.HttpServletRequest)}
101      *
102      * <p>
103      * The view is initialized by first looking for the {@code viewId} parameter in the request. If found, the view is
104      * retrieved based on this id. If the id is not present, then an attempt is made to find a view by type. In order
105      * to retrieve a view based on type, the view request parameter {@code viewTypeName} must be present. If all else
106      * fails and the viewId is populated on the form (could be populated from a previous request), this is used to
107      * retrieve the view.
108      * </p>
109      *
110      * <p>
111      * Note the view is not initialized for Ajax requests that perform partial page updates or dialog updates or no
112      * updates at all
113      * </p>
114      *
115      * @param request - HTTP Servlet Request instance
116      */
117     @Override
118     public void bind(ServletRequest request) {
119         super.bind(request);
120 
121         UifFormBase form = (UifFormBase) this.getTarget();
122 
123         // if doing a partial page update or ajax request with no updating, do not initialize view
124         if (!form.isUpdateComponentRequest() && !form.isUpdateNoneRequest() && !form.isUpdateDialogRequest()) {
125             View view = null;
126 
127             // attempt to retrieve a view by unique identifier first
128             String viewId = request.getParameter(UifParameters.VIEW_ID);
129             if (viewId != null) {
130                 view = getViewService().getViewById(viewId);
131             } else {
132                 // attempt to get view instance by type parameters
133                 String viewTypeName = request.getParameter(UifParameters.VIEW_TYPE_NAME);
134                 ViewType viewType = StringUtils.isBlank(viewTypeName) ? form.getViewTypeName() : ViewType.valueOf(
135                         viewTypeName);
136 
137                 if (viewType != null) {
138                     Map<String, String> parameterMap = KRADUtils.translateRequestParameterMap(
139                             request.getParameterMap());
140                     view = getViewService().getViewByType(viewType, parameterMap);
141                 }
142 
143                 // if view not found attempt to find one based on the cached form
144                 if (view == null) {
145                     view = getViewFromPreviousModel(form);
146 
147                     if (view != null) {
148                         LOG.warn("Obtained viewId from cached form, this may not be safe!");
149                     }
150                 }
151             }
152 
153             if (view != null) {
154                 form.setViewId(view.getId());
155                 form.setView(view);
156             } else {
157                 form.setViewId(null);
158                 form.setView(null);
159             }
160         }
161 
162         form.postBind((HttpServletRequest) request);
163     }
164 
165     protected View getViewFromPreviousModel(UifFormBase form) {
166         // maybe we have a view id from the session form
167         if (form.getViewId() != null) {
168             return getViewService().getViewById(form.getViewId());
169         }
170 
171         return null;
172     }
173 
174     public ViewService getViewService() {
175         return KRADServiceLocatorWeb.getViewService();
176     }
177 
178 }
179 
180