?? typeconverterdelegate.java
字號:
/*
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.beans;
import java.beans.PropertyDescriptor;
import java.beans.PropertyEditor;
import java.beans.PropertyEditorManager;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.Map;
import java.util.WeakHashMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.core.CollectionFactory;
import org.springframework.core.GenericCollectionTypeResolver;
import org.springframework.core.JdkVersion;
import org.springframework.core.MethodParameter;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
/**
* Internal helper class for converting property values to target types.
*
* <p>Works on a given {@link PropertyEditorRegistrySupport} instance.
* Used as a delegate by {@link BeanWrapperImpl} and {@link SimpleTypeConverter}.
*
* @author Juergen Hoeller
* @author Rob Harrop
* @since 2.0
* @see BeanWrapperImpl
* @see SimpleTypeConverter
*/
class TypeConverterDelegate {
private static final Log logger = LogFactory.getLog(TypeConverterDelegate.class);
private static final Map unknownEditorTypes = Collections.synchronizedMap(new WeakHashMap());
private final PropertyEditorRegistrySupport propertyEditorRegistry;
private final Object targetObject;
/**
* Create a new TypeConverterDelegate for the given editor registry.
* @param propertyEditorRegistry the editor registry to use
*/
public TypeConverterDelegate(PropertyEditorRegistrySupport propertyEditorRegistry) {
this(propertyEditorRegistry, null);
}
/**
* Create a new TypeConverterDelegate for the given editor registry and bean instance.
* @param propertyEditorRegistry the editor registry to use
* @param targetObject the target object to work on (as context that can be passed to editors)
*/
public TypeConverterDelegate(PropertyEditorRegistrySupport propertyEditorRegistry, Object targetObject) {
this.propertyEditorRegistry = propertyEditorRegistry;
this.targetObject = targetObject;
}
/**
* Convert the value to the specified required type.
* @param newValue the proposed new value
* @param requiredType the type we must convert to
* (or <code>null</code> if not known, for example in case of a collection element)
* @return the new value, possibly the result of type conversion
* @throws IllegalArgumentException if type conversion failed
*/
public Object convertIfNecessary(Object newValue, Class requiredType) throws IllegalArgumentException {
return convertIfNecessary(null, null, newValue, requiredType, null, null);
}
/**
* Convert the value to the specified required type.
* @param newValue the proposed new value
* @param requiredType the type we must convert to
* (or <code>null</code> if not known, for example in case of a collection element)
* @param methodParam the method parameter that is the target of the conversion
* (may be <code>null</code>)
* @return the new value, possibly the result of type conversion
* @throws IllegalArgumentException if type conversion failed
*/
public Object convertIfNecessary(Object newValue, Class requiredType, MethodParameter methodParam)
throws IllegalArgumentException {
return convertIfNecessary(null, null, newValue, requiredType, null, methodParam);
}
/**
* Convert the value to the required type for the specified property.
* @param propertyName name of the property
* @param oldValue the previous value, if available (may be <code>null</code>)
* @param newValue the proposed new value
* @param requiredType the type we must convert to
* (or <code>null</code> if not known, for example in case of a collection element)
* @return the new value, possibly the result of type conversion
* @throws IllegalArgumentException if type conversion failed
*/
public Object convertIfNecessary(
String propertyName, Object oldValue, Object newValue, Class requiredType)
throws IllegalArgumentException {
return convertIfNecessary(propertyName, oldValue, newValue, requiredType, null, null);
}
/**
* Convert the value to the required type for the specified property.
* @param oldValue the previous value, if available (may be <code>null</code>)
* @param newValue the proposed new value
* @param descriptor the JavaBeans descriptor for the property
* @return the new value, possibly the result of type conversion
* @throws IllegalArgumentException if type conversion failed
*/
public Object convertIfNecessary(Object oldValue, Object newValue, PropertyDescriptor descriptor)
throws IllegalArgumentException {
return convertIfNecessary(
descriptor.getName(), oldValue, newValue, descriptor.getPropertyType(), descriptor,
BeanUtils.getWriteMethodParameter(descriptor));
}
/**
* Convert the value to the required type (if necessary from a String),
* for the specified property.
* @param propertyName name of the property
* @param oldValue the previous value, if available (may be <code>null</code>)
* @param newValue the proposed new value
* @param requiredType the type we must convert to
* (or <code>null</code> if not known, for example in case of a collection element)
* @param descriptor the JavaBeans descriptor for the property
* @param methodParam the method parameter that is the target of the conversion
* (may be <code>null</code>)
* @return the new value, possibly the result of type conversion
* @throws IllegalArgumentException if type conversion failed
*/
protected Object convertIfNecessary(
String propertyName, Object oldValue, Object newValue, Class requiredType,
PropertyDescriptor descriptor, MethodParameter methodParam)
throws IllegalArgumentException {
Object convertedValue = newValue;
// Custom editor for this type?
PropertyEditor editor = this.propertyEditorRegistry.findCustomEditor(requiredType, propertyName);
// Value not of required type?
if (editor != null || (requiredType != null && !ClassUtils.isAssignableValue(requiredType, convertedValue))) {
if (editor == null) {
editor = findDefaultEditor(requiredType, descriptor);
}
convertedValue = doConvertValue(oldValue, convertedValue, requiredType, editor);
}
if (requiredType != null) {
// Try to apply some standard type conversion rules if appropriate.
if (convertedValue != null) {
if (String.class.equals(requiredType) && ClassUtils.isPrimitiveOrWrapper(convertedValue.getClass())) {
// We can stringify any primitive value...
return convertedValue.toString();
}
else if (requiredType.isArray()) {
// Array required -> apply appropriate conversion of elements.
return convertToTypedArray(convertedValue, propertyName, requiredType.getComponentType());
}
else if (convertedValue instanceof Collection && CollectionFactory.isApproximableCollectionType(requiredType)) {
// Convert elements to target type, if determined.
convertedValue = convertToTypedCollection((Collection) convertedValue, propertyName, methodParam);
}
else if (convertedValue instanceof Map && CollectionFactory.isApproximableMapType(requiredType)) {
// Convert keys and values to respective target type, if determined.
convertedValue = convertToTypedMap((Map) convertedValue, propertyName, methodParam);
}
else if (convertedValue instanceof String && !requiredType.isInstance(convertedValue)) {
String strValue = ((String) convertedValue).trim();
if (JdkVersion.isAtLeastJava15() && requiredType.isEnum() && "".equals(strValue)) {
// It's an empty enum identifier: reset the enum value to null.
return null;
}
// Try field lookup as fallback: for JDK 1.5 enum or custom enum
// with values defined as static fields. Resulting value still needs
// to be checked, hence we don't return it right away.
try {
Field enumField = requiredType.getField(strValue);
convertedValue = enumField.get(null);
}
catch (Throwable ex) {
if (logger.isTraceEnabled()) {
logger.trace("Field [" + convertedValue + "] isn't an enum value", ex);
}
}
}
}
if (!ClassUtils.isAssignableValue(requiredType, convertedValue)) {
// Definitely doesn't match: throw IllegalArgumentException.
throw new IllegalArgumentException("Cannot convert value of type [" +
(newValue != null ? ClassUtils.getQualifiedName(newValue.getClass()) : null) +
"] to required type [" + ClassUtils.getQualifiedName(requiredType) + "]" +
(propertyName != null ? " for property '" + propertyName + "'" : "") +
": no matching editors or conversion strategy found");
}
}
return convertedValue;
}
/**
* Find a default editor for the given type.
* @param requiredType the type to find an editor for
* @param descriptor the JavaBeans descriptor for the property
* @return the corresponding editor, or <code>null</code> if none
*/
protected PropertyEditor findDefaultEditor(Class requiredType, PropertyDescriptor descriptor) {
PropertyEditor editor = null;
if (descriptor != null) {
if (JdkVersion.isAtLeastJava15()) {
editor = descriptor.createPropertyEditor(this.targetObject);
}
else {
Class editorClass = descriptor.getPropertyEditorClass();
if (editorClass != null) {
editor = (PropertyEditor) BeanUtils.instantiateClass(editorClass);
}
}
}
if (editor == null && requiredType != null) {
// No custom editor -> check BeanWrapperImpl's default editors.
editor = (PropertyEditor) this.propertyEditorRegistry.getDefaultEditor(requiredType);
if (editor == null && !String.class.equals(requiredType)) {
// No BeanWrapper default editor -> check standard JavaBean editor.
editor = BeanUtils.findEditorByConvention(requiredType);
if (editor == null && !unknownEditorTypes.containsKey(requiredType)) {
// Deprecated global PropertyEditorManager fallback...
editor = PropertyEditorManager.findEditor(requiredType);
if (editor == null) {
// Regular case as of Spring 2.5
unknownEditorTypes.put(requiredType, Boolean.TRUE);
}
else {
logger.warn("PropertyEditor [" + editor.getClass().getName() +
"] found through deprecated global PropertyEditorManager fallback - " +
"consider using a more isolated form of registration, e.g. on the BeanWrapper/BeanFactory!");
}
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -