📄 beanmap.java
字号:
* property names, although it is possible to set their value and to get * their type. * * @return BeanMap keys. The Set returned by this method is not * modifiable. */ public Set keySet() { return UnmodifiableSet.decorate(readMethods.keySet()); } /** * Gets a Set of MapEntry objects that are the mappings for this BeanMap. * <p> * Each MapEntry can be set but not removed. * * @return the unmodifiable set of mappings */ public Set entrySet() { return UnmodifiableSet.decorate(new AbstractSet() { public Iterator iterator() { return entryIterator(); } public int size() { return BeanMap.this.readMethods.size(); } }); } /** * Returns the values for the BeanMap. * * @return values for the BeanMap. The returned collection is not * modifiable. */ public Collection values() { ArrayList answer = new ArrayList( readMethods.size() ); for ( Iterator iter = valueIterator(); iter.hasNext(); ) { answer.add( iter.next() ); } return UnmodifiableList.decorate(answer); } // Helper methods //------------------------------------------------------------------------- /** * Returns the type of the property with the given name. * * @param name the name of the property * @return the type of the property, or <code>null</code> if no such * property exists */ public Class getType(String name) { return (Class) types.get( name ); } /** * Convenience method for getting an iterator over the keys. * <p> * Write-only properties will not be returned in the iterator. * * @return an iterator over the keys */ public Iterator keyIterator() { return readMethods.keySet().iterator(); } /** * Convenience method for getting an iterator over the values. * * @return an iterator over the values */ public Iterator valueIterator() { final Iterator iter = keyIterator(); return new Iterator() { public boolean hasNext() { return iter.hasNext(); } public Object next() { Object key = iter.next(); return get(key); } public void remove() { throw new UnsupportedOperationException( "remove() not supported for BeanMap" ); } }; } /** * Convenience method for getting an iterator over the entries. * * @return an iterator over the entries */ public Iterator entryIterator() { final Iterator iter = keyIterator(); return new Iterator() { public boolean hasNext() { return iter.hasNext(); } public Object next() { Object key = iter.next(); Object value = get(key); return new Entry( BeanMap.this, key, value ); } public void remove() { throw new UnsupportedOperationException( "remove() not supported for BeanMap" ); } }; } // Properties //------------------------------------------------------------------------- /** * Returns the bean currently being operated on. The return value may * be null if this map is empty. * * @return the bean being operated on by this map */ public Object getBean() { return bean; } /** * Sets the bean to be operated on by this map. The given value may * be null, in which case this map will be empty. * * @param newBean the new bean to operate on */ public void setBean( Object newBean ) { bean = newBean; reinitialise(); } /** * Returns the accessor for the property with the given name. * * @param name the name of the property * @return the accessor method for the property, or null */ public Method getReadMethod(String name) { return (Method) readMethods.get(name); } /** * Returns the mutator for the property with the given name. * * @param name the name of the property * @return the mutator method for the property, or null */ public Method getWriteMethod(String name) { return (Method) writeMethods.get(name); } // Implementation methods //------------------------------------------------------------------------- /** * Returns the accessor for the property with the given name. * * @param name the name of the property * @return null if the name is null; null if the name is not a * {@link String}; null if no such property exists; or the accessor * method for that property */ protected Method getReadMethod( Object name ) { return (Method) readMethods.get( name ); } /** * Returns the mutator for the property with the given name. * * @param name the name of the * @return null if the name is null; null if the name is not a * {@link String}; null if no such property exists; null if the * property is read-only; or the mutator method for that property */ protected Method getWriteMethod( Object name ) { return (Method) writeMethods.get( name ); } /** * Reinitializes this bean. Called during {@link #setBean(Object)}. * Does introspection to find properties. */ protected void reinitialise() { readMethods.clear(); writeMethods.clear(); types.clear(); initialise(); } private void initialise() { if(getBean() == null) return; Class beanClass = getBean().getClass(); try { //BeanInfo beanInfo = Introspector.getBeanInfo( bean, null ); BeanInfo beanInfo = Introspector.getBeanInfo( beanClass ); PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors(); if ( propertyDescriptors != null ) { for ( int i = 0; i < propertyDescriptors.length; i++ ) { PropertyDescriptor propertyDescriptor = propertyDescriptors[i]; if ( propertyDescriptor != null ) { String name = propertyDescriptor.getName(); Method readMethod = propertyDescriptor.getReadMethod(); Method writeMethod = propertyDescriptor.getWriteMethod(); Class aType = propertyDescriptor.getPropertyType(); if ( readMethod != null ) { readMethods.put( name, readMethod ); } if ( writeMethods != null ) { writeMethods.put( name, writeMethod ); } types.put( name, aType ); } } } } catch ( IntrospectionException e ) { logWarn( e ); } } /** * Called during a successful {@link #put(Object,Object)} operation. * Default implementation does nothing. Override to be notified of * property changes in the bean caused by this map. * * @param key the name of the property that changed * @param oldValue the old value for that property * @param newValue the new value for that property */ protected void firePropertyChange( Object key, Object oldValue, Object newValue ) { } // Implementation classes //------------------------------------------------------------------------- /** * Map entry used by {@link BeanMap}. */ protected static class Entry extends AbstractMapEntry { private BeanMap owner; /** * Constructs a new <code>Entry</code>. * * @param owner the BeanMap this entry belongs to * @param key the key for this entry * @param value the value for this entry */ protected Entry( BeanMap owner, Object key, Object value ) { super( key, value ); this.owner = owner; } /** * Sets the value. * * @param value the new value for the entry * @return the old value for the entry */ public Object setValue(Object value) { Object key = getKey(); Object oldValue = owner.get( key ); owner.put( key, value ); Object newValue = owner.get( key ); super.setValue( newValue ); return oldValue; } } /** * Creates an array of parameters to pass to the given mutator method. * If the given object is not the right type to pass to the method * directly, it will be converted using {@link #convertType(Class,Object)}. * * @param method the mutator method * @param value the value to pass to the mutator method * @return an array containing one object that is either the given value * or a transformed value * @throws IllegalAccessException if {@link #convertType(Class,Object)} * raises it * @throws IllegalArgumentException if any other exception is raised * by {@link #convertType(Class,Object)} */ protected Object[] createWriteMethodArguments( Method method, Object value ) throws IllegalAccessException, ClassCastException { try { if ( value != null ) { Class[] types = method.getParameterTypes(); if ( types != null && types.length > 0 ) { Class paramType = types[0]; if ( ! paramType.isAssignableFrom( value.getClass() ) ) { value = convertType( paramType, value ); } } } Object[] answer = { value }; return answer; } catch ( InvocationTargetException e ) { logInfo( e ); throw new IllegalArgumentException( e.getMessage() ); } catch ( InstantiationException e ) { logInfo( e ); throw new IllegalArgumentException( e.getMessage() ); } } /** * Converts the given value to the given type. First, reflection is * is used to find a public constructor declared by the given class * that takes one argument, which must be the precise type of the * given value. If such a constructor is found, a new object is * created by passing the given value to that constructor, and the * newly constructed object is returned.<P> * * If no such constructor exists, and the given type is a primitive * type, then the given value is converted to a string using its * {@link Object#toString() toString()} method, and that string is * parsed into the correct primitive type using, for instance, * {@link Integer#valueOf(String)} to convert the string into an * <code>int</code>.<P> * * If no special constructor exists and the given type is not a * primitive type, this method returns the original value. * * @param newType the type to convert the value to * @param value the value to convert * @return the converted value * @throws NumberFormatException if newType is a primitive type, and * the string representation of the given value cannot be converted * to that type * @throws InstantiationException if the constructor found with * reflection raises it * @throws InvocationTargetException if the constructor found with * reflection raises it * @throws IllegalAccessException never * @throws IllegalArgumentException never */ protected Object convertType( Class newType, Object value ) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { // try call constructor Class[] types = { value.getClass() }; try { Constructor constructor = newType.getConstructor( types ); Object[] arguments = { value }; return constructor.newInstance( arguments ); } catch ( NoSuchMethodException e ) { // try using the transformers Transformer transformer = getTypeTransformer( newType ); if ( transformer != null ) { return transformer.transform( value ); } return value; } } /** * Returns a transformer for the given primitive type. * * @param aType the primitive type whose transformer to return * @return a transformer that will convert strings into that type, * or null if the given type is not a primitive type */ protected Transformer getTypeTransformer( Class aType ) { return (Transformer) defaultTransformers.get( aType ); } /** * Logs the given exception to <code>System.out</code>. Used to display * warnings while accessing/mutating the bean. * * @param ex the exception to log */ protected void logInfo(Exception ex) { // Deliberately do not use LOG4J or Commons Logging to avoid dependencies System.out.println( "INFO: Exception: " + ex ); } /** * Logs the given exception to <code>System.err</code>. Used to display * errors while accessing/mutating the bean. * * @param ex the exception to log */ protected void logWarn(Exception ex) { // Deliberately do not use LOG4J or Commons Logging to avoid dependencies System.out.println( "WARN: Exception: " + ex ); ex.printStackTrace(); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -