View Javadoc

1   /**
2    * Copyright 2005-2011 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.UifConstants;
21  import org.kuali.rice.krad.uif.UifParameters;
22  import org.kuali.rice.krad.uif.view.View;
23  import org.kuali.rice.krad.uif.UifConstants.ViewType;
24  import org.kuali.rice.krad.uif.service.ViewService;
25  import org.kuali.rice.krad.util.KRADUtils;
26  import org.kuali.rice.krad.web.form.UifFormBase;
27  import org.springframework.core.convert.ConversionService;
28  import org.springframework.util.Assert;
29  import org.springframework.validation.AbstractPropertyBindingResult;
30  import org.springframework.web.bind.ServletRequestDataBinder;
31  
32  import javax.servlet.ServletRequest;
33  import javax.servlet.http.HttpServletRequest;
34  import java.util.Map;
35  
36  /**
37   * Override of ServletRequestDataBinder in order to hook in the UifBeanPropertyBindingResult
38   * which instantiates a custom BeanWrapperImpl.
39   *
40   * @author Kuali Rice Team (rice.collab@kuali.org)
41   */
42  public class UifServletRequestDataBinder extends ServletRequestDataBinder {
43      protected static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(
44              UifServletRequestDataBinder.class);
45  
46      private UifBeanPropertyBindingResult bindingResult;
47      private ConversionService conversionService;
48  
49      public UifServletRequestDataBinder(Object target) {
50          super(target);
51          setBindingErrorProcessor(new UifBindingErrorProcessor());
52      }
53  
54      public UifServletRequestDataBinder(Object target, String name) {
55          super(target, name);
56          setBindingErrorProcessor(new UifBindingErrorProcessor());
57      }
58  
59      /**
60       * Allows for a custom binding result class.
61       *
62       * @see org.springframework.validation.DataBinder#initBeanPropertyAccess()
63       */
64      @Override
65      public void initBeanPropertyAccess() {
66          Assert.state(this.bindingResult == null,
67                  "DataBinder is already initialized - call initBeanPropertyAccess before other configuration methods");
68          this.bindingResult = new UifBeanPropertyBindingResult(getTarget(), getObjectName(), isAutoGrowNestedPaths(),
69                  getAutoGrowCollectionLimit());
70          if (this.conversionService != null) {
71              this.bindingResult.initConversion(this.conversionService);
72          }
73      }
74  
75      /**
76       * Allows for the setting attributes to use to find the data dictionary data from Kuali
77       *
78       * @see org.springframework.validation.DataBinder#getInternalBindingResult()
79       */
80      @Override
81      protected AbstractPropertyBindingResult getInternalBindingResult() {
82          if (this.bindingResult == null) {
83              initBeanPropertyAccess();
84          }
85          return this.bindingResult;
86      }
87  
88      /**
89       * Disallows direct field access for Kuali
90       *
91       * @see org.springframework.validation.DataBinder#initDirectFieldAccess()
92       */
93      @Override
94      public void initDirectFieldAccess() {
95          LOG.error("Direct Field access is not allowed in UifServletRequestDataBinder.");
96          throw new RuntimeException("Direct Field access is not allowed in Kuali");
97      }
98  
99      @Override
100     @SuppressWarnings("unchecked")
101     public void bind(ServletRequest request) {
102         super.bind(request);
103 
104         UifFormBase form = (UifFormBase) this.getTarget();
105 
106         // back up previous view instance
107         View previousView = form.getView();
108         form.setPreviousView(previousView);
109 
110         // check for request param that indicates to skip view initialize
111         Boolean skipViewInit = KRADUtils.getRequestParameterAsBoolean(request, UifParameters.SKIP_VIEW_INIT);
112         if ((skipViewInit == null) || !skipViewInit.booleanValue()) {
113             // initialize new view for request
114             View view = null;
115 
116             String viewId = request.getParameter(UifParameters.VIEW_ID);
117             if (viewId != null) {
118                 view = getViewService().getViewById(viewId);
119             } else {
120                 // attempt to get view instance by type parameters
121                 ViewType viewType = null;
122 
123                 String viewTypeName = request.getParameter(UifParameters.VIEW_TYPE_NAME);
124                 viewType = StringUtils.isBlank(viewTypeName) ? form.getViewTypeName() : ViewType.valueOf(viewTypeName);
125 
126                 if (viewType == null) {
127                     view = getViewFromPreviousModel(form);
128                     if (view == null) {
129                         throw new RuntimeException("Could not find enough information to fetch the required view. "
130                                 + " Checked the model retrieved from session for both viewTypeName and viewId");
131                     }
132                 } else {
133                     Map<String, String> parameterMap = KRADUtils.translateRequestParameterMap(
134                             request.getParameterMap());
135                     try {
136                         view = getViewService().getViewByType(viewType, parameterMap);
137                     } catch (RuntimeException rtex) {
138                         view = getViewFromPreviousModel(form);
139                         // if we didn't find one, just re-throw
140                         if (view == null) {
141                             throw rtex;
142                         }
143                         LOG.warn("Obtained viewId from cached form, this may not be safe!");
144                     }
145                 }
146             }
147 
148             form.setViewId(view.getId());
149             form.setView(view);
150         }
151 
152         form.postBind((HttpServletRequest) request);
153 
154         // set form key as request attribute so form can be pulled from request
155         request.setAttribute(UifParameters.FORM_KEY, form.getFormKey());
156 
157         // set form in session
158         ((HttpServletRequest) request).getSession().setAttribute(form.getFormKey(), form);
159     }
160 
161     protected View getViewFromPreviousModel(UifFormBase form) {
162         // maybe we have a view id from the session form
163         if (form.getViewId() != null) {
164             return getViewService().getViewById(form.getViewId());
165         }
166 
167         return null;
168     }
169 
170     public ViewService getViewService() {
171         return KRADServiceLocatorWeb.getViewService();
172     }
173 
174 }