001/* 002 * Copyright 2002-2018 the original author or authors. 003 * 004 * Licensed under the Apache 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 * https://www.apache.org/licenses/LICENSE-2.0 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 */ 016 017package org.springframework.validation; 018 019import java.io.Serializable; 020 021import org.springframework.beans.BeanWrapper; 022import org.springframework.beans.ConfigurablePropertyAccessor; 023import org.springframework.beans.PropertyAccessorFactory; 024 025/** 026 * Default implementation of the {@link Errors} and {@link BindingResult} 027 * interfaces, for the registration and evaluation of binding errors on 028 * JavaBean objects. 029 * 030 * <p>Performs standard JavaBean property access, also supporting nested 031 * properties. Normally, application code will work with the 032 * {@code Errors} interface or the {@code BindingResult} interface. 033 * A {@link DataBinder} returns its {@code BindingResult} via 034 * {@link DataBinder#getBindingResult()}. 035 * 036 * @author Juergen Hoeller 037 * @since 2.0 038 * @see DataBinder#getBindingResult() 039 * @see DataBinder#initBeanPropertyAccess() 040 * @see DirectFieldBindingResult 041 */ 042@SuppressWarnings("serial") 043public class BeanPropertyBindingResult extends AbstractPropertyBindingResult implements Serializable { 044 045 private final Object target; 046 047 private final boolean autoGrowNestedPaths; 048 049 private final int autoGrowCollectionLimit; 050 051 private transient BeanWrapper beanWrapper; 052 053 054 /** 055 * Creates a new instance of the {@link BeanPropertyBindingResult} class. 056 * @param target the target bean to bind onto 057 * @param objectName the name of the target object 058 */ 059 public BeanPropertyBindingResult(Object target, String objectName) { 060 this(target, objectName, true, Integer.MAX_VALUE); 061 } 062 063 /** 064 * Creates a new instance of the {@link BeanPropertyBindingResult} class. 065 * @param target the target bean to bind onto 066 * @param objectName the name of the target object 067 * @param autoGrowNestedPaths whether to "auto-grow" a nested path that contains a null value 068 * @param autoGrowCollectionLimit the limit for array and collection auto-growing 069 */ 070 public BeanPropertyBindingResult(Object target, String objectName, boolean autoGrowNestedPaths, int autoGrowCollectionLimit) { 071 super(objectName); 072 this.target = target; 073 this.autoGrowNestedPaths = autoGrowNestedPaths; 074 this.autoGrowCollectionLimit = autoGrowCollectionLimit; 075 } 076 077 078 @Override 079 public final Object getTarget() { 080 return this.target; 081 } 082 083 /** 084 * Returns the {@link BeanWrapper} that this instance uses. 085 * Creates a new one if none existed before. 086 * @see #createBeanWrapper() 087 */ 088 @Override 089 public final ConfigurablePropertyAccessor getPropertyAccessor() { 090 if (this.beanWrapper == null) { 091 this.beanWrapper = createBeanWrapper(); 092 this.beanWrapper.setExtractOldValueForEditor(true); 093 this.beanWrapper.setAutoGrowNestedPaths(this.autoGrowNestedPaths); 094 this.beanWrapper.setAutoGrowCollectionLimit(this.autoGrowCollectionLimit); 095 } 096 return this.beanWrapper; 097 } 098 099 /** 100 * Create a new {@link BeanWrapper} for the underlying target object. 101 * @see #getTarget() 102 */ 103 protected BeanWrapper createBeanWrapper() { 104 if (this.target == null) { 105 throw new IllegalStateException("Cannot access properties on null bean instance '" + getObjectName() + "'"); 106 } 107 return PropertyAccessorFactory.forBeanPropertyAccess(this.target); 108 } 109 110}