FSF GCC merge 02/23/03
[official-gcc.git] / libjava / java / beans / IndexedPropertyDescriptor.java
blob965a9942cde1bd5ea1ee66f3fdc6ee1d155db1ee
1 /* java.beans.IndexedPropertyDescriptor
2 Copyright (C) 1998 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA.
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package java.beans;
41 import java.util.*;
42 import java.lang.reflect.*;
44 /**
45 ** IndexedPropertyDescriptor describes information about a JavaBean
46 ** indexed property, by which we mean an array-like property that
47 ** has been exposed via a pair of get and set methods and another
48 ** pair that allows you to get to the property by an index.<P>
50 ** An example property would have four methods like this:<P>
51 ** <CODE>FooBar[] getFoo()</CODE><BR>
52 ** <CODE>void setFoo(FooBar[])</CODE><BR>
53 ** <CODE>FooBar getFoo(int)</CODE><BR>
54 ** <CODE>void setFoo(int,FooBar)</CODE><P>
56 ** The constraints put on get and set methods are:<P>
57 ** <OL>
58 ** <LI>There must be at least a get(int) or a set(int,...) method.
59 ** Nothing else is required. <B>Spec note:</B>One nice restriction
60 ** would be that if there is a get() there must be a get(int), same
61 ** with set, but that is not in the spec and is fairly harmless.)</LI>
62 ** <LI>A get array method must have signature
63 ** <CODE>&lt;propertyType&gt;[] &lt;getMethodName&gt;()</CODE></LI>
64 ** <LI>A set array method must have signature
65 ** <CODE>void &lt;setMethodName&gt;(&lt;propertyType&gt;[])</CODE></LI>
66 ** <LI>A get index method must have signature
67 ** <CODE>&lt;propertyType&gt; &lt;getMethodName&gt;(int)</CODE></LI>
68 ** <LI>A set index method must have signature
69 ** <CODE>void &lt;setMethodName&gt;(int,&lt;propertyType&gt;)</CODE></LI>
70 ** <LI>All these methods may throw any exception.</LI>
71 ** <LI>All these methods must be public.</LI>
72 ** </OL>
74 ** @author John Keiser
75 ** @since JDK1.1
76 ** @version 1.1.0, 26 Jul 1998
77 **/
79 public class IndexedPropertyDescriptor extends PropertyDescriptor {
80 private Class indexedPropertyType;
81 private Method setIndex;
82 private Method getIndex;
84 /** Create a new IndexedPropertyDescriptor by introspection.
85 ** This form of constructor creates the PropertyDescriptor by
86 ** looking for getter methods named <CODE>get&lt;name&gt;()</CODE>
87 ** and setter methods named
88 ** <CODE>set&lt;name&gt;()</CODE> in class
89 ** <CODE>&lt;beanClass&gt;</CODE>, where &lt;name&gt; has its
90 ** first letter capitalized by the constructor.<P>
92 ** <B>Implementation note:</B> If there is a get(int) method,
93 ** then the return type of that method is used to find the
94 ** remaining methods. If there is no get method, then the
95 ** set(int) method is searched for exhaustively and that type
96 ** is used to find the others.<P>
98 ** <B>Spec note:</B>
99 ** If there is no get(int) method and multiple set(int) methods with
100 ** the same name and the correct parameters (different type of course),
101 ** then an IntrospectionException is thrown. While Sun's spec
102 ** does not state this, it can make Bean behavior different on
103 ** different systems (since method order is not guaranteed) and as
104 ** such, can be treated as a bug in the spec. I am not aware of
105 ** whether Sun's implementation catches this.
107 ** @param name the programmatic name of the property, usually
108 ** starting with a lowercase letter (e.g. fooManChu
109 ** instead of FooManChu).
110 ** @param beanClass the class the get and set methods live in.
111 ** @exception IntrospectionException if the methods are not found or invalid.
113 public IndexedPropertyDescriptor(String name, Class beanClass) throws IntrospectionException {
114 super(name);
115 String capitalized;
116 try {
117 capitalized = Character.toUpperCase(name.charAt(0)) + name.substring(1);
118 } catch(StringIndexOutOfBoundsException e) {
119 capitalized = "";
121 findMethods(beanClass, "get" + capitalized, "set" + capitalized, "get" + capitalized, "set" + capitalized);
124 /** Create a new IndexedPropertyDescriptor by introspection.
125 ** This form of constructor allows you to specify the
126 ** names of the get and set methods to search for.<P>
128 ** <B>Implementation note:</B> If there is a get(int) method,
129 ** then the return type of that method is used to find the
130 ** remaining methods. If there is no get method, then the
131 ** set(int) method is searched for exhaustively and that type
132 ** is used to find the others.<P>
134 ** <B>Spec note:</B>
135 ** If there is no get(int) method and multiple set(int) methods with
136 ** the same name and the correct parameters (different type of course),
137 ** then an IntrospectionException is thrown. While Sun's spec
138 ** does not state this, it can make Bean behavior different on
139 ** different systems (since method order is not guaranteed) and as
140 ** such, can be treated as a bug in the spec. I am not aware of
141 ** whether Sun's implementation catches this.
143 ** @param name the programmatic name of the property, usually
144 ** starting with a lowercase letter (e.g. fooManChu
145 ** instead of FooManChu).
146 ** @param beanClass the class the get and set methods live in.
147 ** @param getMethodName the name of the get array method.
148 ** @param setMethodName the name of the set array method.
149 ** @param getIndexName the name of the get index method.
150 ** @param setIndexName the name of the set index method.
151 ** @exception IntrospectionException if the methods are not found or invalid.
153 public IndexedPropertyDescriptor(String name, Class beanClass, String getMethodName, String setMethodName, String getIndexName, String setIndexName) throws IntrospectionException {
154 super(name);
155 findMethods(beanClass, getMethodName, setMethodName, getIndexName, setIndexName);
158 /** Create a new PropertyDescriptor using explicit Methods.
159 ** Note that the methods will be checked for conformance to standard
160 ** Property method rules, as described above at the top of this class.
162 ** @param name the programmatic name of the property, usually
163 ** starting with a lowercase letter (e.g. fooManChu
164 ** instead of FooManChu).
165 ** @param getMethod the get array method.
166 ** @param setMethod the set array method.
167 ** @param getIndex the get index method.
168 ** @param setIndex the set index method.
169 ** @exception IntrospectionException if the methods are not found or invalid.
171 public IndexedPropertyDescriptor(String name, Method getMethod, Method setMethod, Method getIndex, Method setIndex) throws IntrospectionException {
172 super(name);
173 if(getMethod != null && getMethod.getParameterTypes().length > 0) {
174 throw new IntrospectionException("get method has parameters");
176 if(getMethod != null && setMethod.getParameterTypes().length != 1) {
177 throw new IntrospectionException("set method does not have exactly one parameter");
179 if(getMethod != null && setMethod != null) {
180 if(!getMethod.getReturnType().equals(setMethod.getParameterTypes()[0])) {
181 throw new IntrospectionException("set and get methods do not share the same type");
183 if(!getMethod.getDeclaringClass().isAssignableFrom(setMethod.getDeclaringClass())
184 && !setMethod.getDeclaringClass().isAssignableFrom(getMethod.getDeclaringClass())) {
185 throw new IntrospectionException("set and get methods are not in the same class.");
189 if(getIndex != null && (getIndex.getParameterTypes().length != 1
190 || !(getIndex.getParameterTypes()[0]).equals(java.lang.Integer.TYPE))) {
191 throw new IntrospectionException("get index method has wrong parameters");
193 if(setIndex != null && (setIndex.getParameterTypes().length != 2
194 || !(setIndex.getParameterTypes()[0]).equals(java.lang.Integer.TYPE))) {
195 throw new IntrospectionException("set index method has wrong parameters");
197 if(getIndex != null && setIndex != null) {
198 if(!getIndex.getReturnType().equals(setIndex.getParameterTypes()[1])) {
199 throw new IntrospectionException("set index methods do not share the same type");
201 if(!getIndex.getDeclaringClass().isAssignableFrom(setIndex.getDeclaringClass())
202 && !setIndex.getDeclaringClass().isAssignableFrom(getIndex.getDeclaringClass())) {
203 throw new IntrospectionException("get and set index methods are not in the same class.");
207 if(getIndex != null && getMethod != null && !getIndex.getDeclaringClass().isAssignableFrom(getMethod.getDeclaringClass())
208 && !getMethod.getDeclaringClass().isAssignableFrom(getIndex.getDeclaringClass())) {
209 throw new IntrospectionException("methods are not in the same class.");
212 if(getIndex != null && getMethod != null && !Array.newInstance(getIndex.getReturnType(),0).getClass().equals(getMethod.getReturnType())) {
213 throw new IntrospectionException("array methods do not match index methods.");
216 this.getMethod = getMethod;
217 this.setMethod = setMethod;
218 this.getIndex = getIndex;
219 this.setIndex = getIndex;
220 this.indexedPropertyType = getIndex != null ? getIndex.getReturnType() : setIndex.getParameterTypes()[1];
221 this.propertyType = getMethod != null ? getMethod.getReturnType() : (setMethod != null ? setMethod.getParameterTypes()[0] : Array.newInstance(this.indexedPropertyType,0).getClass());
224 public Class getIndexedPropertyType() {
225 return indexedPropertyType;
228 public Method getIndexedReadMethod() {
229 return getIndex;
232 public Method getIndexedWriteMethod() {
233 return setIndex;
236 private void findMethods(Class beanClass, String getMethodName, String setMethodName, String getIndexName, String setIndexName) throws IntrospectionException {
237 try {
238 if(getIndexName != null) {
239 try {
240 Class[] getArgs = new Class[1];
241 getArgs[0] = java.lang.Integer.TYPE;
242 getIndex = beanClass.getMethod(getIndexName,getArgs);
243 indexedPropertyType = getIndex.getReturnType();
244 } catch(NoSuchMethodException E) {
247 if(getIndex != null) {
248 if(setIndexName != null) {
249 try {
250 Class[] setArgs = new Class[2];
251 setArgs[0] = java.lang.Integer.TYPE;
252 setArgs[1] = indexedPropertyType;
253 setIndex = beanClass.getMethod(setIndexName,setArgs);
254 if(!setIndex.getReturnType().equals(java.lang.Void.TYPE)) {
255 throw new IntrospectionException(setIndexName + " has non-void return type");
257 } catch(NoSuchMethodException E) {
260 } else if(setIndexName != null) {
261 Method[] m = beanClass.getMethods();
262 for(int i=0;i<m.length;i++) {
263 Method current = m[i];
264 if(current.getName().equals(setIndexName)
265 && current.getParameterTypes().length == 2
266 && (current.getParameterTypes()[0]).equals(java.lang.Integer.TYPE)
267 && current.getReturnType().equals(java.lang.Void.TYPE)) {
268 if(setIndex != null) {
269 throw new IntrospectionException("Multiple, different set methods found that fit the bill!");
270 } else {
271 setIndex = current;
272 indexedPropertyType = current.getParameterTypes()[1];
276 if(setIndex == null) {
277 throw new IntrospectionException("Cannot find get or set methods.");
279 } else {
280 throw new IntrospectionException("Cannot find get or set methods.");
283 Class arrayType = Array.newInstance(indexedPropertyType,0).getClass();
285 Class[] setArgs = new Class[1];
286 setArgs[0] = arrayType;
287 try {
288 setMethod = beanClass.getMethod(setMethodName,setArgs);
289 if(!setMethod.getReturnType().equals(java.lang.Void.TYPE)) {
290 setMethod = null;
292 } catch(NoSuchMethodException E) {
295 Class[] getArgs = new Class[0];
296 try {
297 getMethod = beanClass.getMethod(getMethodName,getArgs);
298 if(!getMethod.getReturnType().equals(arrayType)) {
299 getMethod = null;
301 } catch(NoSuchMethodException E) {
303 } catch(SecurityException E) {
304 throw new IntrospectionException("SecurityException while trying to find methods.");