001/* 002 * Copyright 2002-2020 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.beans; 018 019import java.util.Arrays; 020import java.util.LinkedList; 021import java.util.List; 022import java.util.Map; 023 024/** 025 * Abstract implementation of the {@link PropertyAccessor} interface. 026 * Provides base implementations of all convenience methods, with the 027 * implementation of actual property access left to subclasses. 028 * 029 * @author Juergen Hoeller 030 * @author Stephane Nicoll 031 * @since 2.0 032 * @see #getPropertyValue 033 * @see #setPropertyValue 034 */ 035public abstract class AbstractPropertyAccessor extends TypeConverterSupport implements ConfigurablePropertyAccessor { 036 037 private boolean extractOldValueForEditor = false; 038 039 private boolean autoGrowNestedPaths = false; 040 041 boolean suppressNotWritablePropertyException = false; 042 043 044 @Override 045 public void setExtractOldValueForEditor(boolean extractOldValueForEditor) { 046 this.extractOldValueForEditor = extractOldValueForEditor; 047 } 048 049 @Override 050 public boolean isExtractOldValueForEditor() { 051 return this.extractOldValueForEditor; 052 } 053 054 @Override 055 public void setAutoGrowNestedPaths(boolean autoGrowNestedPaths) { 056 this.autoGrowNestedPaths = autoGrowNestedPaths; 057 } 058 059 @Override 060 public boolean isAutoGrowNestedPaths() { 061 return this.autoGrowNestedPaths; 062 } 063 064 065 @Override 066 public void setPropertyValue(PropertyValue pv) throws BeansException { 067 setPropertyValue(pv.getName(), pv.getValue()); 068 } 069 070 @Override 071 public void setPropertyValues(Map<?, ?> map) throws BeansException { 072 setPropertyValues(new MutablePropertyValues(map)); 073 } 074 075 @Override 076 public void setPropertyValues(PropertyValues pvs) throws BeansException { 077 setPropertyValues(pvs, false, false); 078 } 079 080 @Override 081 public void setPropertyValues(PropertyValues pvs, boolean ignoreUnknown) throws BeansException { 082 setPropertyValues(pvs, ignoreUnknown, false); 083 } 084 085 @Override 086 public void setPropertyValues(PropertyValues pvs, boolean ignoreUnknown, boolean ignoreInvalid) 087 throws BeansException { 088 089 List<PropertyAccessException> propertyAccessExceptions = null; 090 List<PropertyValue> propertyValues = (pvs instanceof MutablePropertyValues ? 091 ((MutablePropertyValues) pvs).getPropertyValueList() : Arrays.asList(pvs.getPropertyValues())); 092 093 if (ignoreUnknown) { 094 this.suppressNotWritablePropertyException = true; 095 } 096 try { 097 for (PropertyValue pv : propertyValues) { 098 // setPropertyValue may throw any BeansException, which won't be caught 099 // here, if there is a critical failure such as no matching field. 100 // We can attempt to deal only with less serious exceptions. 101 try { 102 setPropertyValue(pv); 103 } 104 catch (NotWritablePropertyException ex) { 105 if (!ignoreUnknown) { 106 throw ex; 107 } 108 // Otherwise, just ignore it and continue... 109 } 110 catch (NullValueInNestedPathException ex) { 111 if (!ignoreInvalid) { 112 throw ex; 113 } 114 // Otherwise, just ignore it and continue... 115 } 116 catch (PropertyAccessException ex) { 117 if (propertyAccessExceptions == null) { 118 propertyAccessExceptions = new LinkedList<PropertyAccessException>(); 119 } 120 propertyAccessExceptions.add(ex); 121 } 122 } 123 } 124 finally { 125 if (ignoreUnknown) { 126 this.suppressNotWritablePropertyException = false; 127 } 128 } 129 130 // If we encountered individual exceptions, throw the composite exception. 131 if (propertyAccessExceptions != null) { 132 PropertyAccessException[] paeArray = 133 propertyAccessExceptions.toArray(new PropertyAccessException[propertyAccessExceptions.size()]); 134 throw new PropertyBatchUpdateException(paeArray); 135 } 136 } 137 138 139 // Redefined with public visibility. 140 @Override 141 public Class<?> getPropertyType(String propertyPath) { 142 return null; 143 } 144 145 /** 146 * Actually get the value of a property. 147 * @param propertyName name of the property to get the value of 148 * @return the value of the property 149 * @throws InvalidPropertyException if there is no such property or 150 * if the property isn't readable 151 * @throws PropertyAccessException if the property was valid but the 152 * accessor method failed 153 */ 154 @Override 155 public abstract Object getPropertyValue(String propertyName) throws BeansException; 156 157 /** 158 * Actually set a property value. 159 * @param propertyName name of the property to set value of 160 * @param value the new value 161 * @throws InvalidPropertyException if there is no such property or 162 * if the property isn't writable 163 * @throws PropertyAccessException if the property was valid but the 164 * accessor method failed or a type mismatch occurred 165 */ 166 @Override 167 public abstract void setPropertyValue(String propertyName, Object value) throws BeansException; 168 169}