OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [gnu/] [java/] [beans/] [IntrospectionIncubator.java] - Blame information for rev 769

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 769 jeremybenn
/* gnu.java.beans.IntrospectionIncubator
2
   Copyright (C) 1998, 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA
19
02110-1301 USA.
20
 
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.
25
 
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. */
37
 
38
 
39
package gnu.java.beans;
40
 
41
import gnu.java.lang.ArrayHelper;
42
import gnu.java.lang.ClassHelper;
43
 
44
import java.beans.BeanInfo;
45
import java.beans.EventSetDescriptor;
46
import java.beans.IndexedPropertyDescriptor;
47
import java.beans.IntrospectionException;
48
import java.beans.Introspector;
49
import java.beans.MethodDescriptor;
50
import java.beans.PropertyDescriptor;
51
import java.lang.reflect.Array;
52
import java.lang.reflect.Method;
53
import java.lang.reflect.Modifier;
54
import java.util.Enumeration;
55
import java.util.Hashtable;
56
import java.util.Vector;
57
 
58
/**
59
 ** IntrospectionIncubator takes in a bunch of Methods, and
60
 ** Introspects only those Methods you give it.<br/>
61
 **
62
 ** See {@link addMethod(Method)} for details which rules apply to
63
 ** the methods.
64
 **
65
 ** @author John Keiser
66
 ** @author Robert Schuster
67
 ** @see gnu.java.beans.ExplicitBeanInfo
68
 ** @see java.beans.BeanInfo
69
 **/
70
 
71
public class IntrospectionIncubator {
72
        Hashtable propertyMethods = new Hashtable();
73
        Hashtable listenerMethods = new Hashtable();
74
        Vector otherMethods = new Vector();
75
 
76
        Class propertyStopClass;
77
        Class eventStopClass;
78
        Class methodStopClass;
79
 
80
        public IntrospectionIncubator() {
81
        }
82
 
83
        /** Examines the given method and files it in a suitable collection.
84
         * It files the method as a property method if it finds:
85
         * <ul>
86
         * <li>boolean "is" getter</li>
87
         * <li>"get" style getter</li>
88
         * <li>single argument setter</li>
89
         * <li>indiced setter and getter</li>
90
         * </ul>
91
         * It files the method as a listener method if all of these rules apply:
92
         * <ul>
93
         * <li>the method name starts with "add" or "remove"</li>
94
         * <li>there is only a single argument</li>
95
         * <li>the argument type is a subclass of <code>java.util.EventListener</code></li>
96
         * </ul>
97
         * All public methods are filed as such.
98
         *
99
         * @param method The method instance to examine.
100
         */
101
        public void addMethod(Method method) {
102
                if(Modifier.isPublic(method.getModifiers())) {
103
                        String name = ClassHelper.getTruncatedName(method.getName());
104
                        Class retType = method.getReturnType();
105
                        Class[] params = method.getParameterTypes();
106
                        boolean isVoid = retType.equals(java.lang.Void.TYPE);
107
                        Class methodClass = method.getDeclaringClass();
108
 
109
                        /* Accepts the method for examination if no stop class is given or the method is declared in a subclass of the stop class.
110
                         * The rules for this are described in {@link java.beans.Introspector.getBeanInfo(Class, Class)}.
111
                         * This block finds out whether the method is a suitable getter or setter method (or read/write method).
112
                         */
113
                        if(isReachable(propertyStopClass, methodClass)) {
114
                                /* At this point a method may regarded as a property's read or write method if its name
115
                                 * starts with "is", "get" or "set". However, if a method is static it cannot be part
116
                                 * of a property.
117
                                 */
118
                                if(Modifier.isStatic(method.getModifiers())) {
119
                                        // files method as other because it is static
120
                                        otherMethods.addElement(method);
121
                                } else if(name.startsWith("is")
122
                                   && retType.equals(java.lang.Boolean.TYPE)
123
                                   && params.length == 0) {
124
                                        // files method as boolean "is" style getter
125
                                        addToPropertyHash(name,method,IS);
126
                                } else if(name.startsWith("get") && !isVoid) {
127
                                        if(params.length == 0) {
128
                                                // files as legal non-argument getter
129
                                                addToPropertyHash(name,method,GET);
130
                                        } else if(params.length == 1 && params[0].equals(java.lang.Integer.TYPE)) {
131
                                                // files as legal indiced getter
132
                                                addToPropertyHash(name,method,GET_I);
133
                                        } else {
134
                                                // files as other because the method's signature is not Bean-like
135
                                                otherMethods.addElement(method);
136
                                        }
137
                                } else if(name.startsWith("set") && isVoid) {
138
                                        if(params.length == 1) {
139
                                                // files as legal single-argument setter method
140
                                                addToPropertyHash(name,method,SET);
141
                                        } else if(params.length == 2 && params[0].equals(java.lang.Integer.TYPE)) {
142
                                                // files as legal indiced setter method
143
                                                addToPropertyHash(name,method,SET_I);
144
                                        } else {
145
                                                // files as other because the method's signature is not Bean-like
146
                                                otherMethods.addElement(method);
147
                                        }
148
                                }
149
                        }
150
 
151
                        if(isReachable(eventStopClass, methodClass)) {
152
                                if(name.startsWith("add")
153
                                          && isVoid
154
                                          && params.length == 1
155
                                          && java.util.EventListener.class.isAssignableFrom(params[0])) {
156
                                        addToListenerHash(name,method,ADD);
157
                                } else if(name.startsWith("remove")
158
                                          && isVoid
159
                                          && params.length == 1
160
                                          && java.util.EventListener.class.isAssignableFrom(params[0])) {
161
                                        addToListenerHash(name,method,REMOVE);
162
                                }
163
                        }
164
 
165
                        if(isReachable(methodStopClass, methodClass)) {
166
                                // files as reachable public method
167
                                otherMethods.addElement(method);
168
                        }
169
 
170
                }
171
        }
172
 
173
        public void addMethods(Method[] m) {
174
                for(int i=0;i<m.length;i++) {
175
                        addMethod(m[i]);
176
                }
177
        }
178
 
179
        public void setPropertyStopClass(Class c) {
180
                propertyStopClass = c;
181
        }
182
 
183
        public void setEventStopClass(Class c) {
184
                eventStopClass = c;
185
        }
186
 
187
        public void setMethodStopClass(Class c) {
188
                methodStopClass = c;
189
        }
190
 
191
 
192
        public BeanInfoEmbryo getBeanInfoEmbryo() throws IntrospectionException {
193
                BeanInfoEmbryo b = new BeanInfoEmbryo();
194
                findXXX(b,IS);
195
                findXXXInt(b,GET_I);
196
                findXXXInt(b,SET_I);
197
                findXXX(b,GET);
198
                findXXX(b,SET);
199
                findAddRemovePairs(b);
200
                for(int i=0;i<otherMethods.size();i++) {
201
                        MethodDescriptor newMethod = new MethodDescriptor((Method)otherMethods.elementAt(i));
202
                        if(!b.hasMethod(newMethod)) {
203
                                b.addMethod(new MethodDescriptor((Method)otherMethods.elementAt(i)));
204
                        }
205
                }
206
                return b;
207
        }
208
 
209
        public BeanInfo getBeanInfo() throws IntrospectionException {
210
                return getBeanInfoEmbryo().getBeanInfo();
211
        }
212
 
213
 
214
        void findAddRemovePairs(BeanInfoEmbryo b) throws IntrospectionException {
215
                Enumeration listenerEnum = listenerMethods.keys();
216
                while(listenerEnum.hasMoreElements()) {
217
                        DoubleKey k = (DoubleKey)listenerEnum.nextElement();
218
                        Method[] m = (Method[])listenerMethods.get(k);
219
                        if(m[ADD] != null && m[REMOVE] != null) {
220
                                EventSetDescriptor e = new EventSetDescriptor(Introspector.decapitalize(k.getName()),
221
                                                                              k.getType(), k.getType().getMethods(),
222
                                                                              m[ADD],m[REMOVE]);
223
                                e.setUnicast(ArrayHelper.contains(m[ADD].getExceptionTypes(),java.util.TooManyListenersException.class));
224
                                if(!b.hasEvent(e)) {
225
                                        b.addEvent(e);
226
                                }
227
                        }
228
                }
229
        }
230
 
231
        void findXXX(BeanInfoEmbryo b, int funcType) throws IntrospectionException {
232
                Enumeration keys = propertyMethods.keys();
233
                while(keys.hasMoreElements()) {
234
                        DoubleKey k = (DoubleKey)keys.nextElement();
235
                        Method[] m = (Method[])propertyMethods.get(k);
236
                        if(m[funcType] != null) {
237
                                PropertyDescriptor p = new PropertyDescriptor(Introspector.decapitalize(k.getName()),
238
                                                                     m[IS] != null ? m[IS] : m[GET],
239
                                                                     m[SET]);
240
                                if(m[SET] != null) {
241
                                        p.setConstrained(ArrayHelper.contains(m[SET].getExceptionTypes(),java.beans.PropertyVetoException.class));
242
                                }
243
                                if(!b.hasProperty(p)) {
244
                                        b.addProperty(p);
245
                                }
246
                        }
247
                }
248
        }
249
 
250
        void findXXXInt(BeanInfoEmbryo b, int funcType) throws IntrospectionException {
251
                Enumeration keys = propertyMethods.keys();
252
                while(keys.hasMoreElements()) {
253
                        DoubleKey k = (DoubleKey)keys.nextElement();
254
                        Method[] m = (Method[])propertyMethods.get(k);
255
                        if(m[funcType] != null) {
256
                                boolean constrained;
257
                                if(m[SET_I] != null) {
258
                                        constrained = ArrayHelper.contains(m[SET_I].getExceptionTypes(),java.beans.PropertyVetoException.class);
259
                                } else {
260
                                        constrained = false;
261
                                }
262
 
263
                                /** Find out if there is an array type get or set **/
264
                                Class arrayType = Array.newInstance(k.getType(),0).getClass();
265
                                DoubleKey findSetArray = new DoubleKey(arrayType,k.getName());
266
                                Method[] m2 = (Method[])propertyMethods.get(findSetArray);
267
                                IndexedPropertyDescriptor p;
268
                                if(m2 == null) {
269
                                        p = new IndexedPropertyDescriptor(Introspector.decapitalize(k.getName()),
270
                                                                          null,null,
271
                                                                          m[GET_I],m[SET_I]);
272
                                } else {
273
                                        if(constrained && m2[SET] != null) {
274
                                                constrained = ArrayHelper.contains(m2[SET].getExceptionTypes(),java.beans.PropertyVetoException.class);
275
                                        }
276
                                        p = new IndexedPropertyDescriptor(Introspector.decapitalize(k.getName()),
277
                                                                          m2[GET],m2[SET],
278
                                                                          m[GET_I],m[SET_I]);
279
                                }
280
                                p.setConstrained(constrained);
281
                                if(!b.hasProperty(p)) {
282
                                        b.addProperty(p);
283
                                }
284
                        }
285
                }
286
        }
287
 
288
        static final int IS=0;
289
        static final int GET_I=1;
290
        static final int SET_I=2;
291
        static final int GET=3;
292
        static final int SET=4;
293
 
294
        static final int ADD=0;
295
        static final int REMOVE=1;
296
 
297
        void addToPropertyHash(String name, Method method, int funcType) {
298
                String newName;
299
                Class type;
300
 
301
                switch(funcType) {
302
                        case IS:
303
                                type = java.lang.Boolean.TYPE;
304
                                newName = name.substring(2);
305
                                break;
306
                        case GET_I:
307
                                type = method.getReturnType();
308
                                newName = name.substring(3);
309
                                break;
310
                        case SET_I:
311
                                type = method.getParameterTypes()[1];
312
                                newName = name.substring(3);
313
                                break;
314
                        case GET:
315
                                type = method.getReturnType();
316
                                newName = name.substring(3);
317
                                break;
318
                        case SET:
319
                                type = method.getParameterTypes()[0];
320
                                newName = name.substring(3);
321
                                break;
322
                        default:
323
                                return;
324
                }
325
                newName = capitalize(newName);
326
                if (newName.length() == 0)
327
                        return;
328
 
329
                DoubleKey k = new DoubleKey(type,newName);
330
                Method[] methods = (Method[])propertyMethods.get(k);
331
                if(methods == null) {
332
                        methods = new Method[5];
333
                        propertyMethods.put(k,methods);
334
                }
335
                methods[funcType] = method;
336
        }
337
 
338
        void addToListenerHash(String name, Method method, int funcType) {
339
                String newName;
340
                Class type;
341
 
342
                switch(funcType) {
343
                        case ADD:
344
                                type = method.getParameterTypes()[0];
345
                                newName = name.substring(3,name.length()-8);
346
                                break;
347
                        case REMOVE:
348
                                type = method.getParameterTypes()[0];
349
                                newName = name.substring(6,name.length()-8);
350
                                break;
351
                        default:
352
                                return;
353
                }
354
                newName = capitalize(newName);
355
                if (newName.length() == 0)
356
                        return;
357
 
358
                DoubleKey k = new DoubleKey(type,newName);
359
                Method[] methods = (Method[])listenerMethods.get(k);
360
                if(methods == null) {
361
                        methods = new Method[2];
362
                        listenerMethods.put(k,methods);
363
                }
364
                methods[funcType] = method;
365
        }
366
 
367
        /* Determines whether <code>stopClass</code> is <code>null</code>
368
         * or <code>declaringClass<code> is a true subclass of <code>stopClass</code>.
369
         * This expression is useful to detect whether a method should be introspected or not.
370
         * The rules for this are described in {@link java.beans.Introspector.getBeanInfo(Class, Class)}.
371
         */
372
        static boolean isReachable(Class stopClass, Class declaringClass) {
373
                return stopClass == null || (stopClass.isAssignableFrom(declaringClass) && !stopClass.equals(declaringClass));
374
        }
375
 
376
        /** Transforms a property name into a part of a method name.
377
         * E.g. "value" becomes "Value" which can then concatenated with
378
         * "set", "get" or "is" to form a valid method name.
379
         *
380
         * Implementation notes:
381
         * If "" is the argument, it is returned without changes.
382
         * If <code>null</code> is the argument, <code>null</code> is returned.
383
         *
384
         * @param name Name of a property.
385
         * @return Part of a method name of a property.
386
         */
387
        static String capitalize(String name) {
388
                try {
389
                        if(Character.isUpperCase(name.charAt(0))) {
390
                                return name;
391
                        } else {
392
                                char[] c = name.toCharArray();
393
                                c[0] = Character.toLowerCase(c[0]);
394
                                return new String(c);
395
                        }
396
                } catch(StringIndexOutOfBoundsException E) {
397
                        return name;
398
                } catch(NullPointerException E) {
399
                        return null;
400
                }
401
        }
402
}
403
 
404
/** This class is a hashmap key that consists of a <code>Class</code> and a
405
 * <code>String</code> element.
406
 *
407
 * It is used for XXX: find out what this is used for
408
 *
409
 * @author John Keiser
410
 * @author Robert Schuster
411
 */
412
class DoubleKey {
413
        Class type;
414
        String name;
415
 
416
        DoubleKey(Class type, String name) {
417
                this.type = type;
418
                this.name = name;
419
        }
420
 
421
        Class getType() {
422
                return type;
423
        }
424
 
425
        String getName() {
426
                return name;
427
        }
428
 
429
        public boolean equals(Object o) {
430
                if(o instanceof DoubleKey) {
431
                        DoubleKey d = (DoubleKey)o;
432
                        return d.type.equals(type) && d.name.equals(name);
433
                } else {
434
                        return false;
435
                }
436
        }
437
 
438
        public int hashCode() {
439
                return type.hashCode() ^ name.hashCode();
440
        }
441
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.