001package jmri.beans; 002 003import java.util.Set; 004 005/** 006 * Generic implementation of {@link jmri.beans.BeanInterface} that supports 007 * arbitrary properties defined at runtime. 008 * <p> 009 * <b>NOTE</b> This class does not implement 010 * {@link java.beans.PropertyChangeSupport}. Subclass {@link jmri.beans.Bean} if 011 * you need to support property change listeners. 012 * 013 * @author Randall Wood 014 */ 015public abstract class UnboundArbitraryBean extends UnboundBean { 016 017 protected final ArbitraryPropertySupport arbitraryPropertySupport = new ArbitraryPropertySupport(this); 018 019 /** 020 * Get value of element at <i>index</i> of property array <i>key</i>. 021 * <p> 022 * This implementation calls a read method for the indexed property using 023 * JavaBeans introspection, and assumes, based on JavaBeans coding patterns, 024 * that the read method has the following parameter: <code>index</code>. 025 * 026 * Note that this method returns null instead of throwing 027 * {@link java.lang.ArrayIndexOutOfBoundsException} if the index is invalid 028 * since the Java introspection methods provide no reliable way to get the 029 * size of the indexed property. 030 * 031 * @param key Property array to parse. 032 * @param index Element to retrieve. 033 * @return value of element or null 034 */ 035 @Override 036 public Object getIndexedProperty(String key, int index) { 037 return this.arbitraryPropertySupport.getIndexedProperty(key, index); 038 } 039 040 /** 041 * Get the value of property key. 042 * <p> 043 * If <i>null</i> is a valid (or expected) value for <i>key</i>, you might 044 * want to use {@link Bean#hasProperty(java.lang.String)} to test that the 045 * property exists. 046 * <p> 047 * This implementation searches the internal property collection 048 * and uses introspection to get the property. 049 * 050 * @param key Property to retrieve. 051 * @return value of key or null. 052 * @see BeanInterface#getProperty(java.lang.String) 053 */ 054 @Override 055 public Object getProperty(String key) { 056 return this.arbitraryPropertySupport.getProperty(key); 057 } 058 059 /** 060 * Return a list of property names. 061 * <p> 062 * This implementation combines the keys in 063 * {@link ArbitraryPropertySupport#getPropertyNames()} with the results of 064 * {@link BeanUtil#getIntrospectedPropertyNames(java.lang.Object)}. 065 * 066 * @return a Set of names 067 * @see BeanInterface#getPropertyNames() 068 */ 069 @Override 070 public Set<String> getPropertyNames() { 071 return this.arbitraryPropertySupport.getPropertyNames(); 072 } 073 074 /** 075 * Test if a property exists. 076 * <p> 077 * This implementation searches the internal property collection 078 * and uses introspection to get the property. 079 * 080 * @param key Property to inspect. 081 * @return true if property exists 082 * @see BeanInterface#hasProperty(java.lang.String) 083 */ 084 @Override 085 public boolean hasProperty(String key) { 086 return this.arbitraryPropertySupport.hasProperty(key); 087 } 088 089 @Override 090 public boolean hasIndexedProperty(String key) { 091 return this.arbitraryPropertySupport.hasIndexedProperty(key); 092 } 093 094 /** 095 * Set element at <i>index</i> of property array <i>key</i> to <i>value</i>. 096 * <p> 097 * This implementation calls a write method for the indexed property using 098 * JavaBeans introspection, and assumes, based on JavaBeans coding patterns, 099 * that the write method has the following two parameters in order: 100 * <code>index</code>, <code>value</code>. 101 * 102 * @param key Property array to use. 103 * @param index Element to write. 104 * @param value Value to set. 105 * @see BeanInterface#setIndexedProperty(java.lang.String, int, 106 * java.lang.Object) 107 */ 108 @Override 109 public void setIndexedProperty(String key, int index, Object value) { 110 this.arbitraryPropertySupport.setIndexedProperty(key, index, value); 111 } 112 113 /** 114 * Set property <i>key</i> to <i>value</i>. 115 * <p> 116 * This implementation checks that a write method is not available for the 117 * property using JavaBeans introspection, and stores the property using 118 * {@link ArbitraryPropertySupport#setProperty(String, Object)} only if a 119 * write method does not exist. This implementation also fires a 120 * PropertyChangeEvent for the property. 121 * 122 * @param key Property to use. 123 * @param value Value to store. 124 * @see BeanInterface#setProperty(java.lang.String, java.lang.Object) 125 */ 126 @Override 127 public void setProperty(String key, Object value) { 128 this.arbitraryPropertySupport.setProperty(key, value); 129 } 130}