View Javadoc

1   /*
2    * Copyright 2007 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 1.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/ecl1.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.datadictionary.DataDictionaryException;
20  import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
21  import org.kuali.rice.krad.uif.UifParameters;
22  import org.kuali.rice.krad.uif.container.View;
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.HashMap;
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(UifServletRequestDataBinder.class);
44  
45  	private UifBeanPropertyBindingResult bindingResult;
46  	private ConversionService conversionService;
47  	
48  	protected ViewService viewService;
49  
50  
51  	public UifServletRequestDataBinder(Object target) {
52          super(target);
53          setBindingErrorProcessor(new UifBindingErrorProcessor());
54      }
55  	
56  	public UifServletRequestDataBinder(Object target, String name) {
57          super(target, name);
58          setBindingErrorProcessor(new UifBindingErrorProcessor());
59      }
60  	
61      /**
62       * Allows for a custom binding result class.
63       * 
64       * @see org.springframework.validation.DataBinder#initBeanPropertyAccess()
65       */
66      @Override
67  	public void initBeanPropertyAccess() {
68  		Assert.state(this.bindingResult == null,
69  				"DataBinder is already initialized - call initBeanPropertyAccess before other configuration methods");
70  		this.bindingResult = new UifBeanPropertyBindingResult(getTarget(), getObjectName(), isAutoGrowNestedPaths());
71  		if (this.conversionService != null) {
72  			this.bindingResult.initConversion(this.conversionService);
73  		}
74  	}
75  
76      /**
77       * Allows for the setting attributes to use to find the data dictionary data from Kuali
78       * 
79       * @see org.springframework.validation.DataBinder#getInternalBindingResult()
80       */
81      @Override
82  	protected AbstractPropertyBindingResult getInternalBindingResult() {
83  		if (this.bindingResult == null) {
84  			initBeanPropertyAccess();
85  		}
86  		return this.bindingResult;
87  	}
88  
89  	/**
90       * Disallows direct field access for Kuali
91       * 
92       * @see org.springframework.validation.DataBinder#initDirectFieldAccess()
93       */
94      @Override
95  	public void initDirectFieldAccess() {
96      	LOG.error("Direct Field access is not allowed in UifServletRequestDataBinder.");
97  		throw new RuntimeException("Direct Field access is not allowed in Kuali");
98  	}
99  
100 	@Override
101 	@SuppressWarnings("unchecked")
102     public void bind(ServletRequest request) {
103         super.bind(request);
104         UifFormBase form = (UifFormBase) this.getTarget();
105         
106         // check for request param that indicates to skip view initialize
107         Boolean skipViewInit = KRADUtils.getRequestParameterAsBoolean(request, UifParameters.SKIP_VIEW_INIT);
108         if ((skipViewInit != null) && skipViewInit.booleanValue()) {
109             // just invoke post bind on form and return
110             form.postBind((HttpServletRequest) request);
111             return;
112         }
113 
114         // back up previous view instance
115         View previousView = form.getView();
116         form.setPreviousView(previousView);
117 
118         Map<String, String> viewRequestParameters = new HashMap<String, String>();
119         // TODO: this should get from form not previous view, test
120         if (previousView != null) {
121             viewRequestParameters = previousView.getViewRequestParameters();
122         }
123 
124         // initialize new view for request
125         View view = null;
126 
127         // we are going to need this no matter how we get the view, so do it
128         // once
129         Map<String, String> parameterMap = KRADUtils.translateRequestParameterMap(request.getParameterMap());
130 
131         // determine whether full view should be rendered or just page
132         // if not specified on the request and previous is not null, default to
133         // just page
134         // TODO: revisit and see if we can have a general pattern
135         // if ((previousView != null) &&
136         // !parameterMap.containsKey(UifParameters.RENDER_FULL_VIEW)) {
137         // form.setRenderFullView(false);
138         // }
139 
140         // add/override view request parameters
141         parameterMap.putAll(viewRequestParameters);
142 
143         String viewId = request.getParameter(UifParameters.VIEW_ID);
144         if (viewId != null) {
145             view = getViewService().getView(viewId, parameterMap);
146         } else {
147             String viewTypeName = request.getParameter(UifParameters.VIEW_TYPE_NAME);
148             if (viewTypeName == null) {
149                 viewTypeName = form.getViewTypeName();
150             }
151 
152             if (StringUtils.isBlank(viewTypeName)) {
153                 view = getViewFromPreviousModel(form, parameterMap);
154                 if (view == null) {
155                     throw new RuntimeException(
156                             "Could not find enough information to fetch the required view. " +
157                              " Checked the model retrieved from session for both viewTypeName and viewId");
158                 }
159             } else {
160                 try {
161                     view = getViewService().getViewByType(viewTypeName, parameterMap);
162                 } catch (DataDictionaryException ddex) {
163                     view = getViewFromPreviousModel(form, parameterMap);
164                     // if we didn't find one, just re-throw
165                     if (view == null) {
166                         throw ddex;
167                     }
168                     LOG.warn("Obtained viewId from cached form, this may not be safe!");
169                 }
170             }
171         }
172 
173         // apply default values to form if needed
174         if (!form.isDefaultsApplied()) {
175             view.getViewHelperService().applyDefaultValues(view, form);
176         }
177 
178         form.setViewRequestParameters(view.getViewRequestParameters());
179         form.setViewId(view.getId());
180         form.setView(view);
181         form.postBind((HttpServletRequest) request);
182     }
183 
184 	protected View getViewFromPreviousModel(UifFormBase form, Map<String, String> parameterMap) {
185         // maybe we have a view id from the session form
186         if(form.getViewId() != null) {
187             return getViewService().getView(form.getViewId(), parameterMap);
188         }
189         return null;
190 	}
191 
192 	public ViewService getViewService() {
193         if(viewService == null) {
194             viewService = KRADServiceLocatorWeb.getViewService();
195         }
196         return this.viewService;
197     }
198 
199     public void setViewService(ViewService viewService) {
200         this.viewService = viewService;
201     }
202 
203 }