1. /*
  2. * @(#)IndexedPropertyDescriptor.java 1.32 00/02/02
  3. *
  4. * Copyright 1996-2000 Sun Microsystems, Inc. All Rights Reserved.
  5. *
  6. * This software is the proprietary information of Sun Microsystems, Inc.
  7. * Use is subject to license terms.
  8. *
  9. */
  10. package java.beans;
  11. import java.lang.reflect.*;
  12. /**
  13. * An IndexedPropertyDescriptor describes a property that acts like an
  14. * array and has an indexed read and/or indexed write method to access
  15. * specific elements of the array.
  16. * <p>
  17. * An indexed property may also provide simple non-indexed read and write
  18. * methods. If these are present, they read and write arrays of the type
  19. * returned by the indexed read method.
  20. */
  21. public class IndexedPropertyDescriptor extends PropertyDescriptor {
  22. /**
  23. * This constructor constructs an IndexedPropertyDescriptor for a property
  24. * that follows the standard Java conventions by having getFoo and setFoo
  25. * accessor methods, for both indexed access and array access.
  26. * <p>
  27. * Thus if the argument name is "fred", it will assume that there
  28. * is an indexed reader method "getFred", a non-indexed (array) reader
  29. * method also called "getFred", an indexed writer method "setFred",
  30. * and finally a non-indexed writer method "setFred".
  31. *
  32. * @param propertyName The programmatic name of the property.
  33. * @param beanClass The Class object for the target bean.
  34. * @exception IntrospectionException if an exception occurs during
  35. * introspection.
  36. */
  37. public IndexedPropertyDescriptor(String propertyName, Class beanClass)
  38. throws IntrospectionException {
  39. this(propertyName, beanClass,
  40. "get" + capitalize(propertyName),
  41. "set" + capitalize(propertyName),
  42. "get" + capitalize(propertyName),
  43. "set" + capitalize(propertyName));
  44. }
  45. /**
  46. * This constructor takes the name of a simple property, and method
  47. * names for reading and writing the property, both indexed
  48. * and non-indexed.
  49. *
  50. * @param propertyName The programmatic name of the property.
  51. * @param beanClass The Class object for the target bean.
  52. * @param getterName The name of the method used for reading the property
  53. * values as an array. May be null if the property is write-only
  54. * or must be indexed.
  55. * @param setterName The name of the method used for writing the property
  56. * values as an array. May be null if the property is read-only
  57. * or must be indexed.
  58. * @param indexedGetterName The name of the method used for reading
  59. * an indexed property value.
  60. * May be null if the property is write-only.
  61. * @param indexedSetterName The name of the method used for writing
  62. * an indexed property value.
  63. * May be null if the property is read-only.
  64. * @exception IntrospectionException if an exception occurs during
  65. * introspection.
  66. */
  67. public IndexedPropertyDescriptor(String propertyName, Class beanClass,
  68. String getterName, String setterName,
  69. String indexedGetterName, String indexedSetterName)
  70. throws IntrospectionException {
  71. super(propertyName, beanClass, getterName, setterName);
  72. indexedReadMethod = Introspector.findMethod(beanClass, indexedGetterName, 1);
  73. indexedWriteMethod = Introspector.findMethod(beanClass, indexedSetterName, 2);
  74. findIndexedPropertyType();
  75. }
  76. /**
  77. * This constructor takes the name of a simple property, and Method
  78. * objects for reading and writing the property.
  79. *
  80. * @param propertyName The programmatic name of the property.
  81. * @param getter The method used for reading the property values as an array.
  82. * May be null if the property is write-only or must be indexed.
  83. * @param setter The method used for writing the property values as an array.
  84. * May be null if the property is read-only or must be indexed.
  85. * @param indexedGetter The method used for reading an indexed property value.
  86. * May be null if the property is write-only.
  87. * @param indexedSetter The method used for writing an indexed property value.
  88. * May be null if the property is read-only.
  89. * @exception IntrospectionException if an exception occurs during
  90. * introspection.
  91. */
  92. public IndexedPropertyDescriptor(String propertyName, Method getter, Method setter,
  93. Method indexedGetter, Method indexedSetter)
  94. throws IntrospectionException {
  95. super(propertyName, getter, setter);
  96. indexedReadMethod = indexedGetter;
  97. indexedWriteMethod = indexedSetter;
  98. findIndexedPropertyType();
  99. }
  100. /**
  101. * Gets the method that should be used to read an indexed
  102. * property value.
  103. *
  104. * @return The method that should be used to read an indexed
  105. * property value.
  106. * May return null if the property isn't indexed or is write-only.
  107. */
  108. public Method getIndexedReadMethod() {
  109. return indexedReadMethod;
  110. }
  111. /**
  112. * Sets the method that should be used to read an indexed property value.
  113. *
  114. * @param getter The new indexed getter method.
  115. */
  116. public void setIndexedReadMethod(Method getter) throws IntrospectionException {
  117. indexedReadMethod = getter;
  118. findIndexedPropertyType();
  119. }
  120. /**
  121. * Gets the method that should be used to write an indexed property value.
  122. *
  123. * @return The method that should be used to write an indexed
  124. * property value.
  125. * May return null if the property isn't indexed or is read-only.
  126. */
  127. public Method getIndexedWriteMethod() {
  128. return indexedWriteMethod;
  129. }
  130. /**
  131. * Sets the method that should be used to write an indexed property value.
  132. *
  133. * @param getter The new indexed setter method.
  134. */
  135. public void setIndexedWriteMethod(Method setter) throws IntrospectionException {
  136. indexedWriteMethod = setter;
  137. findIndexedPropertyType();
  138. }
  139. /**
  140. * Gets the Class object of the indexed properties' type.
  141. * This is the type that will be returned by the indexedReadMethod.
  142. *
  143. * @return The Java Class for the indexed properties type. Note that
  144. * the Class may describe a primitive Java type such as "int".
  145. */
  146. public Class getIndexedPropertyType() {
  147. return indexedPropertyType;
  148. }
  149. private void findIndexedPropertyType() throws IntrospectionException {
  150. try {
  151. indexedPropertyType = null;
  152. if (indexedReadMethod != null) {
  153. Class params[] = indexedReadMethod.getParameterTypes();
  154. if (params.length != 1) {
  155. throw new IntrospectionException("bad indexed read method arg count");
  156. }
  157. if (params[0] != Integer.TYPE) {
  158. throw new IntrospectionException("non int index to indexed read method");
  159. }
  160. indexedPropertyType = indexedReadMethod.getReturnType();
  161. if (indexedPropertyType == Void.TYPE) {
  162. throw new IntrospectionException("indexed read method returns void");
  163. }
  164. }
  165. if (indexedWriteMethod != null) {
  166. Class params[] = indexedWriteMethod.getParameterTypes();
  167. if (params.length != 2) {
  168. throw new IntrospectionException("bad indexed write method arg count");
  169. }
  170. if (params[0] != Integer.TYPE) {
  171. throw new IntrospectionException("non int index to indexed write method");
  172. }
  173. if (indexedPropertyType != null && indexedPropertyType != params[1]) {
  174. throw new IntrospectionException(
  175. "type mismatch between indexed read and indexed write methods");
  176. }
  177. indexedPropertyType = params[1];
  178. }
  179. Class propertyType = getPropertyType();
  180. if (propertyType != null && (!propertyType.isArray() ||
  181. propertyType.getComponentType() != indexedPropertyType)) {
  182. throw new IntrospectionException(
  183. "type mismatch between indexed and non-indexed methods");
  184. }
  185. } catch (IntrospectionException ex) {
  186. throw ex;
  187. }
  188. }
  189. /*
  190. * Package-private constructor.
  191. * Merge two property descriptors. Where they conflict, give the
  192. * second argument (y) priority over the first argumnnt (x).
  193. *
  194. * @param x The first (lower priority) PropertyDescriptor
  195. * @param y The second (higher priority) PropertyDescriptor
  196. */
  197. IndexedPropertyDescriptor(PropertyDescriptor x, PropertyDescriptor y) {
  198. super(x,y);
  199. if (x instanceof IndexedPropertyDescriptor) {
  200. IndexedPropertyDescriptor ix = (IndexedPropertyDescriptor)x;
  201. indexedReadMethod = ix.indexedReadMethod;
  202. indexedWriteMethod = ix.indexedWriteMethod;
  203. indexedPropertyType = ix.indexedPropertyType;
  204. }
  205. if (y instanceof IndexedPropertyDescriptor) {
  206. IndexedPropertyDescriptor iy = (IndexedPropertyDescriptor)y;
  207. if (iy.indexedReadMethod != null) {
  208. indexedReadMethod = iy.indexedReadMethod;
  209. }
  210. if (iy.indexedWriteMethod != null) {
  211. indexedWriteMethod = iy.indexedWriteMethod;
  212. }
  213. indexedPropertyType = iy.indexedPropertyType;
  214. }
  215. }
  216. /*
  217. * Package-private dup constructor
  218. * This must isolate the new object from any changes to the old object.
  219. */
  220. IndexedPropertyDescriptor(IndexedPropertyDescriptor old) {
  221. super(old);
  222. indexedReadMethod = old.indexedReadMethod;
  223. indexedWriteMethod = old.indexedWriteMethod;
  224. indexedPropertyType = old.indexedPropertyType;
  225. }
  226. private Class indexedPropertyType;
  227. private Method indexedReadMethod;
  228. private Method indexedWriteMethod;
  229. }