1 /* gnu.java.beans.IntrospectionIncubator
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)
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
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. */
28 package gnu.java.beans;
32 import java.lang.reflect.*;
33 import gnu.java.lang.*;
36 ** IntrospectionIncubator takes in a bunch of Methods, and
37 ** Introspects only those Methods you give it.
39 ** @author John Keiser
40 ** @version 1.1.0, 30 Jul 1998
41 ** @see gnu.java.beans.ExplicitBeanInfo
42 ** @see java.beans.BeanInfo
45 public class IntrospectionIncubator {
46 Hashtable propertyMethods = new Hashtable();
47 Hashtable listenerMethods = new Hashtable();
48 Vector otherMethods = new Vector();
50 Class propertyStopClass;
52 Class methodStopClass;
54 public IntrospectionIncubator() {
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);
76 otherMethods.addElement(method);
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);
84 otherMethods.addElement(method);
88 if(eventStopClass == null || (eventStopClass.isAssignableFrom(methodClass) && !eventStopClass.equals(methodClass))) {
89 if(name.startsWith("add")
92 && java.util.EventListener.class.isAssignableFrom(params[0])) {
93 addToListenerHash(name,method,ADD);
94 } else if(name.startsWith("remove")
97 && java.util.EventListener.class.isAssignableFrom(params[0])) {
98 addToListenerHash(name,method,REMOVE);
101 if(methodStopClass == null || (methodStopClass.isAssignableFrom(methodClass) && !methodStopClass.equals(methodClass))) {
102 otherMethods.addElement(method);
107 public void addMethods(Method[] m) {
108 for(int i=0;i<m.length;i++) {
113 public void setPropertyStopClass(Class c) {
114 propertyStopClass = c;
117 public void setEventStopClass(Class c) {
121 public void setMethodStopClass(Class c) {
126 public BeanInfoEmbryo getBeanInfoEmbryo() throws IntrospectionException {
127 BeanInfoEmbryo b = new BeanInfoEmbryo();
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)));
143 public BeanInfo getBeanInfo() throws IntrospectionException {
144 return getBeanInfoEmbryo().getBeanInfo();
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(),
157 e.setUnicast(ArrayHelper.contains(m[ADD].getExceptionTypes(),java.util.TooManyListenersException.class));
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],
175 p.setConstrained(ArrayHelper.contains(m[SET].getExceptionTypes(),java.beans.PropertyVetoException.class));
177 if(!b.hasProperty(p)) {
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) {
191 if(m[SET_I] != null) {
192 constrained = ArrayHelper.contains(m[SET_I].getExceptionTypes(),java.beans.PropertyVetoException.class);
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;
203 p = new IndexedPropertyDescriptor(Introspector.decapitalize(k.getName()),
207 if(constrained && m2[SET] != null) {
208 constrained = ArrayHelper.contains(m2[SET].getExceptionTypes(),java.beans.PropertyVetoException.class);
210 p = new IndexedPropertyDescriptor(Introspector.decapitalize(k.getName()),
214 p.setConstrained(constrained);
215 if(!b.hasProperty(p)) {
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;
228 static final int ADD=0;
229 static final int REMOVE=1;
231 void addToPropertyHash(String name, Method method, int funcType) {
237 type = java.lang.Boolean.TYPE;
238 newName = name.substring(2);
241 type = method.getReturnType();
242 newName = name.substring(3);
245 type = method.getParameterTypes()[1];
246 newName = name.substring(3);
249 type = method.getReturnType();
250 newName = name.substring(3);
253 type = method.getParameterTypes()[0];
254 newName = name.substring(3);
259 newName = capitalize(newName);
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);
267 methods[funcType] = method;
271 void addToListenerHash(String name, Method method, int funcType) {
277 type = method.getParameterTypes()[0];
278 newName = name.substring(3,name.length()-8);
281 type = method.getParameterTypes()[0];
282 newName = name.substring(6,name.length()-8);
287 newName = capitalize(newName);
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);
295 methods[funcType] = method;
298 static String capitalize(String name) {
300 if(Character.isUpperCase(name.charAt(0))) {
303 char[] c = name.toCharArray();
304 c[0] = Character.toLowerCase(c[0]);
305 return new String(c);
307 } catch(StringIndexOutOfBoundsException E) {
309 } catch(NullPointerException E) {
319 DoubleKey(Class type, String name) {
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);
341 public int hashCode() {
342 return type.hashCode() ^ name.hashCode();