OSDN Git Service

Jumbo patch:
[pf3gnuchains/gcc-fork.git] / libjava / gnu / java / beans / IntrospectionIncubator.java
1 /* gnu.java.beans.IntrospectionIncubator
2    Copyright (C) 1998 Free Software Foundation, Inc.
3
4 This file is part of GNU Classpath.
5
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.
10  
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.
15
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.
20
21 As a special exception, if you link this library with other files to
22 produce an executable, this library does not by itself cause the
23 resulting executable to be covered by the GNU General Public License.
24 This exception does not however invalidate any other reasons why the
25 executable file might be covered by the GNU General Public License. */
26
27
28 package gnu.java.beans;
29
30 import java.beans.*;
31 import java.util.*;
32 import java.lang.reflect.*;
33 import gnu.java.lang.*;
34
35 /**
36  ** IntrospectionIncubator takes in a bunch of Methods, and
37  ** Introspects only those Methods you give it.
38  **
39  ** @author John Keiser
40  ** @version 1.1.0, 30 Jul 1998
41  ** @see gnu.java.beans.ExplicitBeanInfo
42  ** @see java.beans.BeanInfo
43  **/
44
45 public class IntrospectionIncubator {
46         Hashtable propertyMethods = new Hashtable();
47         Hashtable listenerMethods = new Hashtable();
48         Vector otherMethods = new Vector();
49
50         Class propertyStopClass;
51         Class eventStopClass;
52         Class methodStopClass;
53
54         public IntrospectionIncubator() {
55         }
56
57         /* Paving the way for automatic Introspection */
58         public void addMethod(Method method) {
59                 if(Modifier.isPublic(method.getModifiers()) && !Modifier.isStatic(method.getModifiers())) {
60                         String name = ClassHelper.getTruncatedName(method.getName());
61                         Class retType = method.getReturnType();
62                         Class[] params = method.getParameterTypes();
63                         boolean isVoid = retType.equals(java.lang.Void.TYPE);
64                         Class methodClass = method.getDeclaringClass();
65                         if(propertyStopClass == null || (propertyStopClass.isAssignableFrom(methodClass) && !propertyStopClass.equals(methodClass))) {
66                                 if(name.startsWith("is")
67                                    && retType.equals(java.lang.Boolean.TYPE)
68                                    && params.length == 0) {
69                                         addToPropertyHash(name,method,IS);
70                                 } else if(name.startsWith("get") && !isVoid) {
71                                         if(params.length == 0) {
72                                                 addToPropertyHash(name,method,GET);
73                                         } else if(params.length == 1 && params[0].equals(java.lang.Integer.TYPE)) {
74                                                 addToPropertyHash(name,method,GET_I);
75                                         } else {
76                                                 otherMethods.addElement(method);
77                                         }
78                                 } else if(name.startsWith("set") && isVoid) {
79                                         if(params.length == 1) {
80                                                 addToPropertyHash(name,method,SET);
81                                         } else if(params.length == 2 && params[0].equals(java.lang.Integer.TYPE)) {
82                                                 addToPropertyHash(name,method,SET_I);
83                                         } else {
84                                                 otherMethods.addElement(method);
85                                         }
86                                 }
87                         }
88                         if(eventStopClass == null || (eventStopClass.isAssignableFrom(methodClass) && !eventStopClass.equals(methodClass))) {
89                                 if(name.startsWith("add")
90                                           && isVoid
91                                           && params.length == 1
92                                           && java.util.EventListener.class.isAssignableFrom(params[0])) {
93                                         addToListenerHash(name,method,ADD);
94                                 } else if(name.startsWith("remove")
95                                           && isVoid
96                                           && params.length == 1
97                                           && java.util.EventListener.class.isAssignableFrom(params[0])) {
98                                         addToListenerHash(name,method,REMOVE);
99                                 }
100                         }
101                         if(methodStopClass == null || (methodStopClass.isAssignableFrom(methodClass) && !methodStopClass.equals(methodClass))) {
102                                 otherMethods.addElement(method);
103                         }
104                 }
105         }
106
107         public void addMethods(Method[] m) {
108                 for(int i=0;i<m.length;i++) {
109                         addMethod(m[i]);
110                 }
111         }
112
113         public void setPropertyStopClass(Class c) {
114                 propertyStopClass = c;
115         }
116
117         public void setEventStopClass(Class c) {
118                 eventStopClass = c;
119         }
120
121         public void setMethodStopClass(Class c) {
122                 methodStopClass = c;
123         }
124
125
126         public BeanInfoEmbryo getBeanInfoEmbryo() throws IntrospectionException {
127                 BeanInfoEmbryo b = new BeanInfoEmbryo();
128                 findXXX(b,IS);
129                 findXXXInt(b,GET_I);
130                 findXXXInt(b,SET_I);
131                 findXXX(b,GET);
132                 findXXX(b,SET);
133                 findAddRemovePairs(b);
134                 for(int i=0;i<otherMethods.size();i++) {
135                         MethodDescriptor newMethod = new MethodDescriptor((Method)otherMethods.elementAt(i));
136                         if(!b.hasMethod(newMethod)) {
137                                 b.addMethod(new MethodDescriptor((Method)otherMethods.elementAt(i)));
138                         }
139                 }
140                 return b;
141         }
142
143         public BeanInfo getBeanInfo() throws IntrospectionException {
144                 return getBeanInfoEmbryo().getBeanInfo();
145         }
146
147
148         void findAddRemovePairs(BeanInfoEmbryo b) throws IntrospectionException {
149                 Enumeration listenerEnum = listenerMethods.keys();
150                 while(listenerEnum.hasMoreElements()) {
151                         DoubleKey k = (DoubleKey)listenerEnum.nextElement();
152                         Method[] m = (Method[])listenerMethods.get(k);
153                         if(m[ADD] != null && m[REMOVE] != null) {
154                                 EventSetDescriptor e = new EventSetDescriptor(Introspector.decapitalize(k.getName()),
155                                                                               k.getType(), k.getType().getMethods(),
156                                                                               m[ADD],m[REMOVE]);
157                                 e.setUnicast(ArrayHelper.contains(m[ADD].getExceptionTypes(),java.util.TooManyListenersException.class));
158                                 if(!b.hasEvent(e)) {
159                                         b.addEvent(e);
160                                 }
161                         }
162                 }
163         }
164
165         void findXXX(BeanInfoEmbryo b, int funcType) throws IntrospectionException {
166                 Enumeration keys = propertyMethods.keys();
167                 while(keys.hasMoreElements()) {
168                         DoubleKey k = (DoubleKey)keys.nextElement();
169                         Method[] m = (Method[])propertyMethods.get(k);
170                         if(m[funcType] != null) {
171                                 PropertyDescriptor p = new PropertyDescriptor(Introspector.decapitalize(k.getName()),
172                                                                      m[IS] != null ? m[IS] : m[GET],
173                                                                      m[SET]);
174                                 if(m[SET] != null) {
175                                         p.setConstrained(ArrayHelper.contains(m[SET].getExceptionTypes(),java.beans.PropertyVetoException.class));
176                                 }
177                                 if(!b.hasProperty(p)) {
178                                         b.addProperty(p);
179                                 }
180                         }
181                 }
182         }
183
184         void findXXXInt(BeanInfoEmbryo b, int funcType) throws IntrospectionException {
185                 Enumeration keys = propertyMethods.keys();
186                 while(keys.hasMoreElements()) {
187                         DoubleKey k = (DoubleKey)keys.nextElement();
188                         Method[] m = (Method[])propertyMethods.get(k);
189                         if(m[funcType] != null) {
190                                 boolean constrained;
191                                 if(m[SET_I] != null) {
192                                         constrained = ArrayHelper.contains(m[SET_I].getExceptionTypes(),java.beans.PropertyVetoException.class);
193                                 } else {
194                                         constrained = false;
195                                 }
196
197                                 /** Find out if there is an array type get or set **/
198                                 Class arrayType = Array.newInstance(k.getType(),0).getClass();
199                                 DoubleKey findSetArray = new DoubleKey(arrayType,k.getName());
200                                 Method[] m2 = (Method[])propertyMethods.get(findSetArray);
201                                 IndexedPropertyDescriptor p;
202                                 if(m2 == null) {
203                                         p = new IndexedPropertyDescriptor(Introspector.decapitalize(k.getName()),
204                                                                           null,null,
205                                                                           m[GET_I],m[SET_I]);
206                                 } else {
207                                         if(constrained && m2[SET] != null) {
208                                                 constrained = ArrayHelper.contains(m2[SET].getExceptionTypes(),java.beans.PropertyVetoException.class);
209                                         }
210                                         p = new IndexedPropertyDescriptor(Introspector.decapitalize(k.getName()),
211                                                                           m2[GET],m2[SET],
212                                                                           m[GET_I],m[SET_I]);
213                                 }
214                                 p.setConstrained(constrained);
215                                 if(!b.hasProperty(p)) {
216                                         b.addProperty(p);
217                                 }
218                         }
219                 }
220         }
221
222         static final int IS=0;
223         static final int GET_I=1;
224         static final int SET_I=2;
225         static final int GET=3;
226         static final int SET=4;
227
228         static final int ADD=0;
229         static final int REMOVE=1;
230
231         void addToPropertyHash(String name, Method method, int funcType) {
232                 String newName;
233                 Class type;
234
235                 switch(funcType) {
236                         case IS:
237                                 type = java.lang.Boolean.TYPE;
238                                 newName = name.substring(2);
239                                 break;
240                         case GET_I:
241                                 type = method.getReturnType();
242                                 newName = name.substring(3);
243                                 break;
244                         case SET_I:
245                                 type = method.getParameterTypes()[1];
246                                 newName = name.substring(3);
247                                 break;
248                         case GET:
249                                 type = method.getReturnType();
250                                 newName = name.substring(3);
251                                 break;
252                         case SET:
253                                 type = method.getParameterTypes()[0];
254                                 newName = name.substring(3);
255                                 break;
256                         default:
257                                 return;
258                 }
259                 newName = capitalize(newName);
260
261                 DoubleKey k = new DoubleKey(type,newName);
262                 Method[] methods = (Method[])propertyMethods.get(k);
263                 if(methods == null) {
264                         methods = new Method[5];
265                         propertyMethods.put(k,methods);
266                 }
267                 methods[funcType] = method;
268         }
269
270
271         void addToListenerHash(String name, Method method, int funcType) {
272                 String newName;
273                 Class type;
274
275                 switch(funcType) {
276                         case ADD:
277                                 type = method.getParameterTypes()[0];
278                                 newName = name.substring(3,name.length()-8);
279                                 break;
280                         case REMOVE:
281                                 type = method.getParameterTypes()[0];
282                                 newName = name.substring(6,name.length()-8);
283                                 break;
284                         default:
285                                 return;
286                 }
287                 newName = capitalize(newName);
288
289                 DoubleKey k = new DoubleKey(type,newName);
290                 Method[] methods = (Method[])listenerMethods.get(k);
291                 if(methods == null) {
292                         methods = new Method[2];
293                         listenerMethods.put(k,methods);
294                 }
295                 methods[funcType] = method;
296         }
297
298         static String capitalize(String name) {
299                 try {
300                         if(Character.isUpperCase(name.charAt(0))) {
301                                 return name;
302                         } else {
303                                 char[] c = name.toCharArray();
304                                 c[0] = Character.toLowerCase(c[0]);
305                                 return new String(c);
306                         }
307                 } catch(StringIndexOutOfBoundsException E) {
308                         return name;
309                 } catch(NullPointerException E) {
310                         return null;
311                 }
312         }
313 }
314
315 class DoubleKey {
316         Class type;
317         String name;
318
319         DoubleKey(Class type, String name) {
320                 this.type = type;
321                 this.name = name;
322         }
323
324         Class getType() {
325                 return type;
326         }
327
328         String getName() {
329                 return name;
330         }
331
332         public boolean equals(Object o) {
333                 if(o instanceof DoubleKey) {
334                         DoubleKey d = (DoubleKey)o;
335                         return d.type.equals(type) && d.name.equals(name);
336                 } else {
337                         return false;
338                 }
339         }
340
341         public int hashCode() {
342                 return type.hashCode() ^ name.hashCode();
343         }
344 }