📄 beanmap.java
字号:
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.commons.beanutils;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.AbstractMap;
import java.util.AbstractSet;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import org.apache.commons.collections.list.UnmodifiableList;
import org.apache.commons.collections.keyvalue.AbstractMapEntry;
import org.apache.commons.collections.set.UnmodifiableSet;
import org.apache.commons.collections.Transformer;
/**
* An implementation of Map for JavaBeans which uses introspection to
* get and put properties in the bean.
* <p>
* If an exception occurs during attempts to get or set a property then the
* property is considered non existent in the Map
*
* @version $Revision: 557796 $ $Date: 2007-07-19 23:28:49 +0100 (Thu, 19 Jul 2007) $
*
* @author James Strachan
* @author Stephen Colebourne
*/
public class BeanMap extends AbstractMap implements Cloneable {
private transient Object bean;
private transient HashMap readMethods = new HashMap();
private transient HashMap writeMethods = new HashMap();
private transient HashMap types = new HashMap();
/**
* An empty array. Used to invoke accessors via reflection.
*/
public static final Object[] NULL_ARGUMENTS = {};
/**
* Maps primitive Class types to transformers. The transformer
* transform strings into the appropriate primitive wrapper.
*
* N.B. private & unmodifiable replacement for the (public & static) defaultTransformers instance.
*/
private static Map typeTransformers = Collections.unmodifiableMap(createTypeTransformers());
/**
* This HashMap has been made unmodifiable to prevent issues when
* loaded in a shared ClassLoader enviroment.
*
* @see http://issues.apache.org/jira/browse/BEANUTILS-112
* @deprecated Use {@link BeanMap#getTypeTransformer(Class)} method
*/
public static HashMap defaultTransformers = new HashMap() {
public void clear() {
throw new UnsupportedOperationException();
}
public boolean containsKey(Object key) {
return typeTransformers.containsKey(key);
}
public boolean containsValue(Object value) {
return typeTransformers.containsValue(value);
}
public Set entrySet() {
return typeTransformers.entrySet();
}
public Object get(Object key) {
return typeTransformers.get(key);
}
public boolean isEmpty() {
return false;
}
public Set keySet() {
return typeTransformers.keySet();
}
public Object put(Object key, Object value) {
throw new UnsupportedOperationException();
}
public void putAll(Map m) {
throw new UnsupportedOperationException();
}
public Object remove(Object key) {
throw new UnsupportedOperationException();
}
public int size() {
return typeTransformers.size();
}
public Collection values() {
return typeTransformers.values();
}
};
private static Map createTypeTransformers() {
Map defaultTransformers = new HashMap();
defaultTransformers.put(
Boolean.TYPE,
new Transformer() {
public Object transform( Object input ) {
return Boolean.valueOf( input.toString() );
}
}
);
defaultTransformers.put(
Character.TYPE,
new Transformer() {
public Object transform( Object input ) {
return new Character( input.toString().charAt( 0 ) );
}
}
);
defaultTransformers.put(
Byte.TYPE,
new Transformer() {
public Object transform( Object input ) {
return Byte.valueOf( input.toString() );
}
}
);
defaultTransformers.put(
Short.TYPE,
new Transformer() {
public Object transform( Object input ) {
return Short.valueOf( input.toString() );
}
}
);
defaultTransformers.put(
Integer.TYPE,
new Transformer() {
public Object transform( Object input ) {
return Integer.valueOf( input.toString() );
}
}
);
defaultTransformers.put(
Long.TYPE,
new Transformer() {
public Object transform( Object input ) {
return Long.valueOf( input.toString() );
}
}
);
defaultTransformers.put(
Float.TYPE,
new Transformer() {
public Object transform( Object input ) {
return Float.valueOf( input.toString() );
}
}
);
defaultTransformers.put(
Double.TYPE,
new Transformer() {
public Object transform( Object input ) {
return Double.valueOf( input.toString() );
}
}
);
return defaultTransformers;
}
// Constructors
//-------------------------------------------------------------------------
/**
* Constructs a new empty <code>BeanMap</code>.
*/
public BeanMap() {
}
/**
* Constructs a new <code>BeanMap</code> that operates on the
* specified bean. If the given bean is <code>null</code>, then
* this map will be empty.
*
* @param bean the bean for this map to operate on
*/
public BeanMap(Object bean) {
this.bean = bean;
initialise();
}
// Map interface
//-------------------------------------------------------------------------
/**
* Renders a string representation of this object.
* @return a <code>String</code> representation of this object
*/
public String toString() {
return "BeanMap<" + String.valueOf(bean) + ">";
}
/**
* Clone this bean map using the following process:
*
* <ul>
* <li>If there is no underlying bean, return a cloned BeanMap without a
* bean.
*
* <li>Since there is an underlying bean, try to instantiate a new bean of
* the same type using Class.newInstance().
*
* <li>If the instantiation fails, throw a CloneNotSupportedException
*
* <li>Clone the bean map and set the newly instantiated bean as the
* underlying bean for the bean map.
*
* <li>Copy each property that is both readable and writable from the
* existing object to a cloned bean map.
*
* <li>If anything fails along the way, throw a
* CloneNotSupportedException.
*
* <ul>
*
* @return a cloned instance of this bean map
* @throws CloneNotSupportedException if the underlying bean
* cannot be cloned
*/
public Object clone() throws CloneNotSupportedException {
BeanMap newMap = (BeanMap)super.clone();
if(bean == null) {
// no bean, just an empty bean map at the moment. return a newly
// cloned and empty bean map.
return newMap;
}
Object newBean = null;
Class beanClass = null;
try {
beanClass = bean.getClass();
newBean = beanClass.newInstance();
} catch (Exception e) {
// unable to instantiate
throw new CloneNotSupportedException
("Unable to instantiate the underlying bean \"" +
beanClass.getName() + "\": " + e);
}
try {
newMap.setBean(newBean);
} catch (Exception exception) {
throw new CloneNotSupportedException
("Unable to set bean in the cloned bean map: " +
exception);
}
try {
// copy only properties that are readable and writable. If its
// not readable, we can't get the value from the old map. If
// its not writable, we can't write a value into the new map.
Iterator readableKeys = readMethods.keySet().iterator();
while(readableKeys.hasNext()) {
Object key = readableKeys.next();
if(getWriteMethod(key) != null) {
newMap.put(key, get(key));
}
}
} catch (Exception exception) {
throw new CloneNotSupportedException
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -