001/**
002 * Copyright 2005-2016 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.kuali.rice.krad.web.bind;
017
018import org.apache.commons.lang.StringUtils;
019import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
020import org.kuali.rice.krad.uif.UifParameters;
021import org.kuali.rice.krad.uif.view.View;
022import org.kuali.rice.krad.uif.UifConstants.ViewType;
023import org.kuali.rice.krad.uif.service.ViewService;
024import org.kuali.rice.krad.util.GlobalVariables;
025import org.kuali.rice.krad.util.KRADUtils;
026import org.kuali.rice.krad.web.form.UifFormBase;
027import org.springframework.core.convert.ConversionService;
028import org.springframework.util.Assert;
029import org.springframework.validation.AbstractPropertyBindingResult;
030import org.springframework.web.bind.ServletRequestDataBinder;
031
032import javax.servlet.ServletRequest;
033import javax.servlet.http.HttpServletRequest;
034import java.util.Map;
035
036/**
037 * Override of ServletRequestDataBinder in order to hook in the UifBeanPropertyBindingResult
038 * which instantiates a custom BeanWrapperImpl.
039 *
040 * @author Kuali Rice Team (rice.collab@kuali.org)
041 */
042public class UifServletRequestDataBinder extends ServletRequestDataBinder {
043    protected static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(
044            UifServletRequestDataBinder.class);
045
046    private UifBeanPropertyBindingResult bindingResult;
047    private ConversionService conversionService;
048
049    public UifServletRequestDataBinder(Object target) {
050        super(target);
051        setBindingErrorProcessor(new UifBindingErrorProcessor());
052    }
053
054    public UifServletRequestDataBinder(Object target, String name) {
055        super(target, name);
056        setBindingErrorProcessor(new UifBindingErrorProcessor());
057    }
058
059    /**
060     * Allows for a custom binding result class.
061     *
062     * @see org.springframework.validation.DataBinder#initBeanPropertyAccess()
063     */
064    @Override
065    public void initBeanPropertyAccess() {
066        Assert.state(this.bindingResult == null,
067                "DataBinder is already initialized - call initBeanPropertyAccess before other configuration methods");
068        this.bindingResult = new UifBeanPropertyBindingResult(getTarget(), getObjectName(), isAutoGrowNestedPaths(),
069                getAutoGrowCollectionLimit());
070        if (this.conversionService != null) {
071            this.bindingResult.initConversion(this.conversionService);
072        }
073    }
074
075    /**
076     * Allows for the setting attributes to use to find the data dictionary data from Kuali
077     *
078     * @see org.springframework.validation.DataBinder#getInternalBindingResult()
079     */
080    @Override
081    protected AbstractPropertyBindingResult getInternalBindingResult() {
082        if (this.bindingResult == null) {
083            initBeanPropertyAccess();
084        }
085        return this.bindingResult;
086    }
087
088    /**
089     * Disallows direct field access for Kuali
090     *
091     * @see org.springframework.validation.DataBinder#initDirectFieldAccess()
092     */
093    @Override
094    public void initDirectFieldAccess() {
095        LOG.error("Direct Field access is not allowed in UifServletRequestDataBinder.");
096        throw new RuntimeException("Direct Field access is not allowed in Kuali");
097    }
098
099    @Override
100    @SuppressWarnings("unchecked")
101    public void bind(ServletRequest request) {
102        super.bind(request);
103
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            // initialize new view for request
110            View view = null;
111
112            String viewId = request.getParameter(UifParameters.VIEW_ID);
113            if (viewId != null) {
114                view = getViewService().getViewById(viewId);
115            } else {
116                // attempt to get view instance by type parameters
117                ViewType viewType = null;
118
119                String viewTypeName = request.getParameter(UifParameters.VIEW_TYPE_NAME);
120                viewType = StringUtils.isBlank(viewTypeName) ? form.getViewTypeName() : ViewType.valueOf(viewTypeName);
121
122                if (viewType != null) {
123                    Map<String, String> parameterMap = KRADUtils.translateRequestParameterMap(
124                            request.getParameterMap());
125                    view = getViewService().getViewByType(viewType, parameterMap);
126                }
127
128                // if view not found attempt to find one based on the cached form
129                if (view == null) {
130                    view = getViewFromPreviousModel(form);
131
132                    if (view != null) {
133                        LOG.warn("Obtained viewId from cached form, this may not be safe!");
134                    }
135                }
136            }
137
138            if (view != null) {
139                form.setViewId(view.getId());
140                form.setView(view);
141            } else {
142                form.setViewId(null);
143                form.setView(null);
144            }
145        }
146
147        form.postBind((HttpServletRequest) request);
148
149        // add form to manager
150        GlobalVariables.getUifFormManager().addForm(form);
151    }
152
153    protected View getViewFromPreviousModel(UifFormBase form) {
154        // maybe we have a view id from the session form
155        if (form.getViewId() != null) {
156            return getViewService().getViewById(form.getViewId());
157        }
158
159        return null;
160    }
161
162    public ViewService getViewService() {
163        return KRADServiceLocatorWeb.getViewService();
164    }
165
166}