Source Code Cross Referenced for StandardBeanInfo.java in  » Apache-Harmony-Java-SE » java-package » java » beans » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Apache Harmony Java SE » java package » java.beans 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         *  Licensed to the Apache Software Foundation (ASF) under one or more
0003:         *  contributor license agreements.  See the NOTICE file distributed with
0004:         *  this work for additional information regarding copyright ownership.
0005:         *  The ASF licenses this file to You under the Apache License, Version 2.0
0006:         *  (the "License"); you may not use this file except in compliance with
0007:         *  the License.  You may obtain a copy of the License at
0008:         *
0009:         *     http://www.apache.org/licenses/LICENSE-2.0
0010:         *
0011:         *  Unless required by applicable law or agreed to in writing, software
0012:         *  distributed under the License is distributed on an "AS IS" BASIS,
0013:         *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014:         *  See the License for the specific language governing permissions and
0015:         *  limitations under the License.
0016:         */
0017:
0018:        package java.beans;
0019:
0020:        import static java.beans.Introspector.decapitalize;
0021:
0022:        import java.awt.Image;
0023:        import java.lang.reflect.Method;
0024:        import java.lang.reflect.Modifier;
0025:        import java.util.ArrayList;
0026:        import java.util.Arrays;
0027:        import java.util.Comparator;
0028:        import java.util.EventListener;
0029:        import java.util.EventObject;
0030:        import java.util.HashMap;
0031:        import java.util.Iterator;
0032:        import java.util.TooManyListenersException;
0033:
0034:        class StandardBeanInfo extends SimpleBeanInfo {
0035:
0036:            // Prefixes for methods that set or get a Property
0037:            private static final String PREFIX_IS = "is"; //$NON-NLS-1$
0038:
0039:            private static final String PREFIX_GET = "get"; //$NON-NLS-1$
0040:
0041:            private static final String PREFIX_SET = "set"; //$NON-NLS-1$
0042:
0043:            // Prefix and suffix for Event related methods
0044:            private static final String PREFIX_ADD = "add"; //$NON-NLS-1$
0045:
0046:            private static final String PREFIX_REMOVE = "remove"; //$NON-NLS-1$
0047:
0048:            private static final String SUFFIX_LISTEN = "Listener"; //$NON-NLS-1$
0049:
0050:            private boolean explicitMethods = false;
0051:
0052:            private boolean explicitProperties = false;
0053:
0054:            private boolean explicitEvents = false;
0055:
0056:            private BeanInfo explicitBeanInfo = null;
0057:
0058:            private EventSetDescriptor[] events = null;
0059:
0060:            private MethodDescriptor[] methods = null;
0061:
0062:            private PropertyDescriptor[] properties = null;
0063:
0064:            BeanInfo[] additionalBeanInfo = null;
0065:
0066:            private Class<?> beanClass;
0067:
0068:            private int defaultEventIndex = -1;
0069:
0070:            private int defaultPropertyIndex = -1;
0071:
0072:            private static PropertyComparator comparator = new PropertyComparator();
0073:
0074:            private Image[] icon = new Image[4];
0075:
0076:            private boolean canAddPropertyChangeListener;
0077:
0078:            private boolean canRemovePropertyChangeListener;
0079:
0080:            StandardBeanInfo(Class<?> beanClass, BeanInfo explicitBeanInfo,
0081:                    Class<?> stopClass) throws IntrospectionException {
0082:                assert (beanClass != null);
0083:                this .beanClass = beanClass;
0084:                /*--------------------------------------------------------------------------------------
0085:                 * There are 3 aspects of BeanInfo that must be supplied:
0086:                 * a) PropertyDescriptors
0087:                 * b) MethodDescriptors
0088:                 * c) EventSetDescriptors
0089:                 * Each of these may be optionally provided in the explicitBeanInfo object relating to
0090:                 * this bean.  Where the explicitBeanInfo provides one of these aspects, it is used
0091:                 * without question and no introspection of the beanClass is performed for that aspect.
0092:                 * There are also 3 optional items of BeanInfo that may be provided by the 
0093:                 * explicitBeanInfo object:
0094:                 * 1) BeanDescriptor
0095:                 * 2) DefaultEventIndex
0096:                 * 3) DefaultPropertyIndex
0097:                 * These aspects of the beanClass cannot be derived through introspection of the class.
0098:                 * If they are not provided by the explicitBeanInfo, then they must be left null in the 
0099:                 * returned BeanInfo, otherwise they will be copied from the explicitBeanInfo 
0100:                 --------------------------------------------------------------------------------------*/
0101:                if (explicitBeanInfo != null) {
0102:                    this .explicitBeanInfo = explicitBeanInfo;
0103:                    events = explicitBeanInfo.getEventSetDescriptors();
0104:                    methods = explicitBeanInfo.getMethodDescriptors();
0105:                    properties = explicitBeanInfo.getPropertyDescriptors();
0106:                    defaultEventIndex = explicitBeanInfo.getDefaultEventIndex();
0107:                    if (defaultEventIndex < 0
0108:                            || defaultEventIndex >= events.length) {
0109:                        defaultEventIndex = -1;
0110:                    }
0111:                    defaultPropertyIndex = explicitBeanInfo
0112:                            .getDefaultPropertyIndex();
0113:                    if (defaultPropertyIndex < 0
0114:                            || defaultPropertyIndex >= properties.length) {
0115:                        defaultPropertyIndex = -1;
0116:                    }
0117:                    additionalBeanInfo = explicitBeanInfo
0118:                            .getAdditionalBeanInfo();
0119:                    for (int i = 0; i < 4; i++) {
0120:                        icon[i] = explicitBeanInfo.getIcon(i + 1);
0121:                    }
0122:
0123:                    if (events != null)
0124:                        explicitEvents = true;
0125:                    if (methods != null)
0126:                        explicitMethods = true;
0127:                    if (properties != null)
0128:                        explicitProperties = true;
0129:                }
0130:
0131:                if (methods == null) {
0132:                    methods = introspectMethods();
0133:                }
0134:
0135:                if (properties == null) {
0136:                    properties = introspectProperties(stopClass);
0137:                }
0138:
0139:                if (events == null) {
0140:                    events = introspectEvents();
0141:                }
0142:            }
0143:
0144:            @Override
0145:            public BeanInfo[] getAdditionalBeanInfo() {
0146:                return null;
0147:            }
0148:
0149:            @Override
0150:            public EventSetDescriptor[] getEventSetDescriptors() {
0151:                return events;
0152:            }
0153:
0154:            @Override
0155:            public MethodDescriptor[] getMethodDescriptors() {
0156:                return methods;
0157:            }
0158:
0159:            @Override
0160:            public PropertyDescriptor[] getPropertyDescriptors() {
0161:                return properties;
0162:            }
0163:
0164:            @Override
0165:            public BeanDescriptor getBeanDescriptor() {
0166:                if (explicitBeanInfo != null) {
0167:                    BeanDescriptor beanDesc = explicitBeanInfo
0168:                            .getBeanDescriptor();
0169:                    if (beanDesc != null) {
0170:                        return beanDesc;
0171:                    }
0172:                }
0173:                return new BeanDescriptor(beanClass);
0174:            }
0175:
0176:            @Override
0177:            public int getDefaultEventIndex() {
0178:                return this .defaultEventIndex;
0179:            }
0180:
0181:            @Override
0182:            public int getDefaultPropertyIndex() {
0183:                return this .defaultPropertyIndex;
0184:            }
0185:
0186:            @Override
0187:            public Image getIcon(int iconKind) {
0188:                return icon[iconKind - 1];
0189:            }
0190:
0191:            void mergeBeanInfo(BeanInfo beanInfo, boolean force)
0192:                    throws IntrospectionException {
0193:                if (force || !explicitProperties) {
0194:                    PropertyDescriptor[] super Descs = beanInfo
0195:                            .getPropertyDescriptors();
0196:                    if (super Descs != null) {
0197:                        if (getPropertyDescriptors() != null) {
0198:                            properties = mergeProps(super Descs, beanInfo
0199:                                    .getDefaultPropertyIndex());
0200:                        } else {
0201:                            properties = super Descs;
0202:                            defaultPropertyIndex = beanInfo
0203:                                    .getDefaultPropertyIndex();
0204:                        }
0205:                    }
0206:                }
0207:
0208:                if (force || !explicitMethods) {
0209:                    MethodDescriptor[] super Methods = beanInfo
0210:                            .getMethodDescriptors();
0211:                    if (super Methods != null) {
0212:                        if (methods != null) {
0213:                            methods = mergeMethods(super Methods);
0214:                        } else {
0215:                            methods = super Methods;
0216:                        }
0217:                    }
0218:                }
0219:
0220:                if (force || !explicitEvents) {
0221:                    EventSetDescriptor[] super Events = beanInfo
0222:                            .getEventSetDescriptors();
0223:                    if (super Events != null) {
0224:                        if (events != null) {
0225:                            events = mergeEvents(super Events, beanInfo
0226:                                    .getDefaultEventIndex());
0227:                        } else {
0228:                            events = super Events;
0229:                            defaultEventIndex = beanInfo.getDefaultEventIndex();
0230:                        }
0231:                    }
0232:                }
0233:            }
0234:
0235:            /*
0236:             * merge the PropertyDescriptor with superclass
0237:             */
0238:            private PropertyDescriptor[] mergeProps(
0239:                    PropertyDescriptor[] super Descs, int super DefaultIndex)
0240:                    throws IntrospectionException {
0241:                // FIXME:change to OO way as EventSetD and MethodD
0242:                HashMap<String, PropertyDescriptor> subMap = internalAsMap(properties);
0243:                String defaultPropertyName = null;
0244:                if (defaultPropertyIndex >= 0
0245:                        && defaultPropertyIndex < properties.length) {
0246:                    defaultPropertyName = properties[defaultPropertyIndex]
0247:                            .getName();
0248:                } else if (super DefaultIndex >= 0
0249:                        && super DefaultIndex < super Descs.length) {
0250:                    defaultPropertyName = super Descs[super DefaultIndex]
0251:                            .getName();
0252:                }
0253:
0254:                for (int i = 0; i < super Descs.length; i++) {
0255:                    PropertyDescriptor super Desc = super Descs[i];
0256:                    String propertyName = super Desc.getName();
0257:                    if (!subMap.containsKey(propertyName)) {
0258:                        subMap.put(propertyName, super Desc);
0259:                        continue;
0260:                    }
0261:
0262:                    Object value = subMap.get(propertyName);
0263:                    // if sub and super are both PropertyDescriptor
0264:                    Method subGet = ((PropertyDescriptor) value)
0265:                            .getReadMethod();
0266:                    Method subSet = ((PropertyDescriptor) value)
0267:                            .getWriteMethod();
0268:                    Method super Get = super Desc.getReadMethod();
0269:                    Method super Set = super Desc.getWriteMethod();
0270:
0271:                    Class<?> super Type = super Desc.getPropertyType();
0272:                    Class<?> super IndexedType = null;
0273:                    Class<?> subType = ((PropertyDescriptor) value)
0274:                            .getPropertyType();
0275:                    Class<?> subIndexedType = null;
0276:
0277:                    if (value instanceof  IndexedPropertyDescriptor) {
0278:                        subIndexedType = ((IndexedPropertyDescriptor) value)
0279:                                .getIndexedPropertyType();
0280:                    }
0281:                    if (super Desc instanceof  IndexedPropertyDescriptor) {
0282:                        super IndexedType = ((IndexedPropertyDescriptor) super Desc)
0283:                                .getIndexedPropertyType();
0284:                    }
0285:
0286:                    // if superDesc is PropertyDescriptor
0287:                    if (super IndexedType == null) {
0288:                        PropertyDescriptor subDesc = (PropertyDescriptor) value;
0289:                        // Sub is PropertyDescriptor
0290:                        if (subIndexedType == null) {
0291:                            // Same property type
0292:                            if (subType.getName().equals(super Type.getName())) {
0293:                                if ((subGet == null) && (super Get != null)) {
0294:                                    subDesc.setReadMethod(super Get);
0295:                                }
0296:                                if ((subSet == null) && (super Set != null)) {
0297:                                    subDesc.setWriteMethod(super Set);
0298:                                }
0299:                            } else { // Different type: type = getMethod
0300:                                if ((subGet == null) && (super Get != null)) {
0301:                                    subDesc.setWriteMethod(null);
0302:                                    subDesc.setReadMethod(super Get);
0303:                                }
0304:                            }
0305:                        } else { // Sub is IndexedPropertyDescriptor
0306:                            if ((super Type.isArray())
0307:                                    && (super Type.getComponentType().getName()
0308:                                            .equals(subIndexedType.getName()))) {
0309:                                // same type
0310:                                if ((subGet == null) && (super Get != null)) {
0311:                                    subDesc.setReadMethod(super Get);
0312:                                }
0313:                                if ((subSet == null) && (super Set != null)) {
0314:                                    subDesc.setWriteMethod(super Set);
0315:                                }
0316:                            } // different type do nothing
0317:                        }
0318:                        subMap.put(propertyName, subDesc);
0319:                    } else { // Super is IndexedPropertyDescriptor
0320:                        if (subIndexedType == null) { // Sub is PropertyDescriptor
0321:                            if (subType.isArray()
0322:                                    && (subType.getComponentType().getName()
0323:                                            .equals(super IndexedType.getName()))) {
0324:                                // Same type
0325:                                if (subGet != null) {
0326:                                    super Desc.setReadMethod(subGet);
0327:                                }
0328:                                if (subSet != null) {
0329:                                    super Desc.setWriteMethod(subSet);
0330:                                }
0331:                                subMap.put(propertyName, super Desc);
0332:                            } else { // Different type do nothing
0333:                                subMap.put(propertyName,
0334:                                        (PropertyDescriptor) value);
0335:                            }
0336:
0337:                        } else if (subIndexedType.getName().equals(
0338:                                super IndexedType.getName())) {
0339:                            // Sub is IndexedPropertyDescriptor and Same type
0340:                            IndexedPropertyDescriptor subDesc = (IndexedPropertyDescriptor) value;
0341:                            if ((subGet == null) && (super Get != null)) {
0342:                                subDesc.setReadMethod(super Get);
0343:                            }
0344:                            if ((subSet == null) && (super Set != null)) {
0345:                                subDesc.setWriteMethod(super Set);
0346:                            }
0347:                            IndexedPropertyDescriptor super IndexedDesc = (IndexedPropertyDescriptor) super Desc;
0348:
0349:                            if ((subDesc.getIndexedReadMethod() == null)
0350:                                    && (super IndexedDesc.getIndexedReadMethod() != null)) {
0351:                                subDesc.setIndexedReadMethod(super IndexedDesc
0352:                                        .getIndexedReadMethod());
0353:                            }
0354:
0355:                            if ((subDesc.getIndexedWriteMethod() == null)
0356:                                    && (super IndexedDesc
0357:                                            .getIndexedWriteMethod() != null)) {
0358:                                subDesc.setIndexedWriteMethod(super IndexedDesc
0359:                                        .getIndexedWriteMethod());
0360:                            }
0361:
0362:                            subMap.put(propertyName, subDesc);
0363:                        } // Different indexed type, do nothing
0364:                    }
0365:                    mergeAttributes((PropertyDescriptor) value, super Desc);
0366:                }
0367:
0368:                PropertyDescriptor[] theDescs = new PropertyDescriptor[subMap
0369:                        .size()];
0370:                subMap.values().toArray(theDescs);
0371:
0372:                if (defaultPropertyName != null && !explicitProperties) {
0373:                    for (int i = 0; i < theDescs.length; i++) {
0374:                        if (defaultPropertyName.equals(theDescs[i].getName())) {
0375:                            defaultPropertyIndex = i;
0376:                            break;
0377:                        }
0378:                    }
0379:                }
0380:                return theDescs;
0381:            }
0382:
0383:            private static void mergeAttributes(PropertyDescriptor subDesc,
0384:                    PropertyDescriptor super Desc) {
0385:                // FIXME: this is just temp workaround, need more elegant solution to
0386:                // handle this
0387:                subDesc.hidden |= super Desc.hidden;
0388:                subDesc.expert |= super Desc.expert;
0389:                subDesc.preferred |= super Desc.preferred;
0390:                subDesc.bound |= super Desc.bound;
0391:                subDesc.constrained |= super Desc.constrained;
0392:                subDesc.name = super Desc.name;
0393:                if (subDesc.shortDescription == null
0394:                        && super Desc.shortDescription != null) {
0395:                    subDesc.shortDescription = super Desc.shortDescription;
0396:                }
0397:                if (subDesc.displayName == null
0398:                        && super Desc.displayName != null) {
0399:                    subDesc.displayName = super Desc.displayName;
0400:                }
0401:            }
0402:
0403:            /*
0404:             * merge the MethodDescriptor
0405:             */
0406:            private MethodDescriptor[] mergeMethods(
0407:                    MethodDescriptor[] super Descs) {
0408:                HashMap<String, MethodDescriptor> subMap = internalAsMap(methods);
0409:
0410:                for (MethodDescriptor super Method : super Descs) {
0411:                    String methodName = getQualifiedName(super Method
0412:                            .getMethod());
0413:                    MethodDescriptor method = subMap.get(methodName);
0414:                    if (method == null) {
0415:                        subMap.put(methodName, super Method);
0416:                    } else {
0417:                        method.merge(super Method);
0418:                    }
0419:                }
0420:                MethodDescriptor[] theMethods = new MethodDescriptor[subMap
0421:                        .size()];
0422:                subMap.values().toArray(theMethods);
0423:                return theMethods;
0424:            }
0425:
0426:            private EventSetDescriptor[] mergeEvents(
0427:                    EventSetDescriptor[] otherEvents, int otherDefaultIndex) {
0428:                HashMap<String, EventSetDescriptor> subMap = internalAsMap(events);
0429:                String defaultEventName = null;
0430:                if (defaultEventIndex >= 0 && defaultEventIndex < events.length) {
0431:                    defaultEventName = events[defaultEventIndex].getName();
0432:                } else if (otherDefaultIndex >= 0
0433:                        && otherDefaultIndex < otherEvents.length) {
0434:                    defaultEventName = otherEvents[otherDefaultIndex].getName();
0435:                }
0436:
0437:                for (EventSetDescriptor event : otherEvents) {
0438:                    String eventName = event.getName();
0439:                    EventSetDescriptor subEvent = subMap.get(eventName);
0440:                    if (subEvent == null) {
0441:                        subMap.put(eventName, event);
0442:                    } else {
0443:                        subEvent.merge(event);
0444:                    }
0445:                }
0446:
0447:                EventSetDescriptor[] theEvents = new EventSetDescriptor[subMap
0448:                        .size()];
0449:                subMap.values().toArray(theEvents);
0450:
0451:                if (defaultEventName != null && !explicitEvents) {
0452:                    for (int i = 0; i < theEvents.length; i++) {
0453:                        if (defaultEventName.equals(theEvents[i].getName())) {
0454:                            defaultEventIndex = i;
0455:                            break;
0456:                        }
0457:                    }
0458:                }
0459:                return theEvents;
0460:            }
0461:
0462:            private static HashMap<String, PropertyDescriptor> internalAsMap(
0463:                    PropertyDescriptor[] propertyDescs) {
0464:                HashMap<String, PropertyDescriptor> map = new HashMap<String, PropertyDescriptor>();
0465:                for (int i = 0; i < propertyDescs.length; i++) {
0466:                    map.put(propertyDescs[i].getName(), propertyDescs[i]);
0467:                }
0468:                return map;
0469:            }
0470:
0471:            private static HashMap<String, MethodDescriptor> internalAsMap(
0472:                    MethodDescriptor[] theDescs) {
0473:                HashMap<String, MethodDescriptor> map = new HashMap<String, MethodDescriptor>();
0474:                for (int i = 0; i < theDescs.length; i++) {
0475:                    String qualifiedName = getQualifiedName(theDescs[i]
0476:                            .getMethod());
0477:                    map.put(qualifiedName, theDescs[i]);
0478:                }
0479:                return map;
0480:            }
0481:
0482:            private static HashMap<String, EventSetDescriptor> internalAsMap(
0483:                    EventSetDescriptor[] theDescs) {
0484:                HashMap<String, EventSetDescriptor> map = new HashMap<String, EventSetDescriptor>();
0485:                for (int i = 0; i < theDescs.length; i++) {
0486:                    map.put(theDescs[i].getName(), theDescs[i]);
0487:                }
0488:                return map;
0489:            }
0490:
0491:            private static String getQualifiedName(Method method) {
0492:                String qualifiedName = method.getName();
0493:                Class[] paramTypes = method.getParameterTypes();
0494:                if (paramTypes != null) {
0495:                    for (int i = 0; i < paramTypes.length; i++) {
0496:                        qualifiedName += "_" + paramTypes[i].getName(); //$NON-NLS-1$
0497:                    }
0498:                }
0499:                return qualifiedName;
0500:            }
0501:
0502:            /**
0503:             * Introspects the supplied class and returns a list of the public methods
0504:             * of the class
0505:             * 
0506:             * @param beanClass -
0507:             *            the class
0508:             * @return An array of MethodDescriptors with the public methods. null if
0509:             *         there are no public methods
0510:             */
0511:            private MethodDescriptor[] introspectMethods() {
0512:                return introspectMethods(false, beanClass);
0513:            }
0514:
0515:            private MethodDescriptor[] introspectMethods(boolean includeSuper) {
0516:                return introspectMethods(includeSuper, beanClass);
0517:            }
0518:
0519:            private MethodDescriptor[] introspectMethods(boolean includeSuper,
0520:                    Class<?> introspectorClass) {
0521:
0522:                // Get the list of methods belonging to this class
0523:                Method[] basicMethods = includeSuper ? introspectorClass
0524:                        .getMethods() : introspectorClass.getDeclaredMethods();
0525:
0526:                if (basicMethods == null || basicMethods.length == 0)
0527:                    return null;
0528:
0529:                ArrayList<MethodDescriptor> methodList = new ArrayList<MethodDescriptor>(
0530:                        basicMethods.length);
0531:
0532:                // Loop over the methods found, looking for public non-static methods
0533:                for (int i = 0; i < basicMethods.length; i++) {
0534:                    int modifiers = basicMethods[i].getModifiers();
0535:                    if (Modifier.isPublic(modifiers)
0536:                            && !Modifier.isStatic(modifiers)) {
0537:                        // Allocate a MethodDescriptor for this method
0538:                        MethodDescriptor theDescriptor = new MethodDescriptor(
0539:                                basicMethods[i]);
0540:                        methodList.add(theDescriptor);
0541:                    }
0542:                }
0543:
0544:                // Get the list of public methods into the returned array
0545:                int methodCount = methodList.size();
0546:                MethodDescriptor[] theMethods = null;
0547:                if (methodCount > 0) {
0548:                    theMethods = new MethodDescriptor[methodCount];
0549:                    theMethods = methodList.toArray(theMethods);
0550:                }
0551:
0552:                return theMethods;
0553:            }
0554:
0555:            /**
0556:             * Introspects the supplied class and returns a list of the Properties of
0557:             * the class
0558:             * 
0559:             * @param beanClass -
0560:             *            the Class
0561:             * @return The list of Properties as an array of PropertyDescriptors
0562:             * @throws IntrospectionException
0563:             */
0564:            @SuppressWarnings("unchecked")
0565:            private PropertyDescriptor[] introspectProperties(Class<?> stopClass)
0566:                    throws IntrospectionException {
0567:
0568:                // Get descriptors for the public methods
0569:                MethodDescriptor[] theMethods = introspectMethods();
0570:
0571:                if (theMethods == null)
0572:                    return null;
0573:
0574:                HashMap<String, HashMap> propertyTable = new HashMap<String, HashMap>(
0575:                        theMethods.length);
0576:
0577:                // Search for methods that either get or set a Property
0578:                for (int i = 0; i < theMethods.length; i++) {
0579:                    introspectGet(theMethods[i].getMethod(), propertyTable);
0580:                    introspectSet(theMethods[i].getMethod(), propertyTable);
0581:                }
0582:
0583:                // If there are listener methods, should be bound.
0584:                MethodDescriptor[] allMethods = introspectMethods(true);
0585:                if (stopClass != null) {
0586:                    MethodDescriptor[] excludeMethods = introspectMethods(true,
0587:                            stopClass);
0588:                    if (excludeMethods != null) {
0589:                        ArrayList<MethodDescriptor> tempMethods = new ArrayList<MethodDescriptor>();
0590:                        for (MethodDescriptor method : allMethods) {
0591:                            if (!isInSuper(method, excludeMethods)) {
0592:                                tempMethods.add(method);
0593:                            }
0594:                        }
0595:                        allMethods = tempMethods
0596:                                .toArray(new MethodDescriptor[0]);
0597:                    }
0598:                }
0599:                for (int i = 0; i < allMethods.length; i++) {
0600:                    introspectPropertyListener(allMethods[i].getMethod());
0601:                }
0602:                // Put the properties found into the PropertyDescriptor array
0603:                ArrayList<PropertyDescriptor> propertyList = new ArrayList<PropertyDescriptor>();
0604:
0605:                Iterator<String> keys = propertyTable.keySet().iterator();
0606:                while (keys.hasNext()) {
0607:                    String propertyName = keys.next();
0608:                    HashMap table = propertyTable.get(propertyName);
0609:                    if (table == null) {
0610:                        continue;
0611:                    }
0612:                    String normalTag = (String) table.get("normal"); //$NON-NLS-1$
0613:                    String indexedTag = (String) table.get("indexed"); //$NON-NLS-1$
0614:
0615:                    if ((normalTag == null) && (indexedTag == null)) {
0616:                        continue;
0617:                    }
0618:
0619:                    Method get = (Method) table.get("normalget"); //$NON-NLS-1$
0620:                    Method set = (Method) table.get("normalset"); //$NON-NLS-1$
0621:                    Method indexedGet = (Method) table.get("indexedget"); //$NON-NLS-1$
0622:                    Method indexedSet = (Method) table.get("indexedset"); //$NON-NLS-1$
0623:
0624:                    PropertyDescriptor propertyDesc = null;
0625:                    if (indexedTag == null) {
0626:                        propertyDesc = new PropertyDescriptor(propertyName,
0627:                                get, set);
0628:                    } else {
0629:                        try {
0630:                            propertyDesc = new IndexedPropertyDescriptor(
0631:                                    propertyName, get, set, indexedGet,
0632:                                    indexedSet);
0633:                        } catch (IntrospectionException e) {
0634:                            // If the getter and the indexGetter is not compatible, try
0635:                            // getter/setter is null;
0636:                            propertyDesc = new IndexedPropertyDescriptor(
0637:                                    propertyName, null, null, indexedGet,
0638:                                    indexedSet);
0639:                        }
0640:                    }
0641:                    // RI set propretyDescriptor as bound. FIXME
0642:                    // propertyDesc.setBound(true);
0643:                    if (canAddPropertyChangeListener
0644:                            && canRemovePropertyChangeListener) {
0645:                        propertyDesc.setBound(true);
0646:                    } else {
0647:                        propertyDesc.setBound(false);
0648:                    }
0649:                    if (table.get("isConstrained") == Boolean.TRUE) { //$NON-NLS-1$
0650:                        propertyDesc.setConstrained(true);
0651:                    }
0652:                    propertyList.add(propertyDesc);
0653:                }
0654:
0655:                PropertyDescriptor[] theProperties = new PropertyDescriptor[propertyList
0656:                        .size()];
0657:                propertyList.toArray(theProperties);
0658:                return theProperties;
0659:            }
0660:
0661:            private boolean isInSuper(MethodDescriptor method,
0662:                    MethodDescriptor[] excludeMethods) {
0663:                for (MethodDescriptor m : excludeMethods) {
0664:                    if (method.getMethod().equals(m.getMethod())) {
0665:                        return true;
0666:                    }
0667:                }
0668:                return false;
0669:            }
0670:
0671:            @SuppressWarnings("nls")
0672:            private void introspectPropertyListener(Method theMethod) {
0673:                String methodName = theMethod.getName();
0674:                Class[] param = theMethod.getParameterTypes();
0675:                if (param.length != 1) {
0676:                    return;
0677:                }
0678:                if (methodName.equals("addPropertyChangeListener")
0679:                        && param[0].equals(PropertyChangeListener.class))
0680:                    canAddPropertyChangeListener = true;
0681:                if (methodName.equals("removePropertyChangeListener")
0682:                        && param[0].equals(PropertyChangeListener.class))
0683:                    canRemovePropertyChangeListener = true;
0684:            }
0685:
0686:            @SuppressWarnings("unchecked")
0687:            private static void introspectGet(Method theMethod,
0688:                    HashMap<String, HashMap> propertyTable) {
0689:                String methodName = theMethod.getName();
0690:                if (methodName == null) {
0691:                    return;
0692:                }
0693:
0694:                int prefixLength = 0;
0695:                if (methodName.startsWith(PREFIX_GET)) {
0696:                    prefixLength = PREFIX_GET.length();
0697:                }
0698:
0699:                if (methodName.startsWith(PREFIX_IS)) {
0700:                    prefixLength = PREFIX_IS.length();
0701:                }
0702:
0703:                if (prefixLength == 0) {
0704:                    return;
0705:                }
0706:
0707:                String propertyName = decapitalize(methodName
0708:                        .substring(prefixLength));
0709:                // validate property name
0710:                if (!isValidProperty(propertyName)) {
0711:                    return;
0712:                }
0713:
0714:                Class propertyType = theMethod.getReturnType();
0715:
0716:                // check return type getMethod
0717:                if (propertyType.getName().equals(Void.TYPE.getName())) {
0718:                    return;
0719:                }
0720:
0721:                // isXXX return boolean
0722:                if (prefixLength == 2) {
0723:                    if (!propertyType.getName().equals(Boolean.TYPE.getName())) {
0724:                        return;
0725:                    }
0726:                }
0727:
0728:                // indexed get method
0729:                Class[] paramTypes = theMethod.getParameterTypes();
0730:
0731:                if (paramTypes.length > 1) {
0732:                    return;
0733:                }
0734:
0735:                String tag = "normal"; //$NON-NLS-1$
0736:
0737:                if (paramTypes.length == 1) {
0738:                    if (paramTypes[0].getName().equals(Integer.TYPE.getName())) {
0739:                        tag = "indexed"; //$NON-NLS-1$
0740:                    } else {
0741:                        return;
0742:                    }
0743:
0744:                }
0745:
0746:                HashMap table = propertyTable.get(propertyName);
0747:                if (table == null) {
0748:                    table = new HashMap();
0749:                    propertyTable.put(propertyName, table);
0750:                }
0751:
0752:                // the "get" propertyType is conflict with "set" propertyType
0753:                Class oldPropertyType = (Class) table.get(tag + "PropertyType"); //$NON-NLS-1$
0754:                if ((oldPropertyType != null)
0755:                        && (!oldPropertyType.getName().equals(
0756:                                propertyType.getName()))) {
0757:                    table.put(tag, "invalid"); //$NON-NLS-1$
0758:                    table.remove(tag + "set"); //$NON-NLS-1$
0759:                } else {
0760:                    table.put(tag, "valid"); //$NON-NLS-1$
0761:                }
0762:
0763:                table.put(tag + "PropertyType", propertyType); //$NON-NLS-1$
0764:
0765:                // According to the spec "is" method should be used prior to "get"
0766:                if (prefixLength == 3) {
0767:                    if (!table.containsKey(tag + "get")) { //$NON-NLS-1$
0768:                        table.put(tag + "get", theMethod); //$NON-NLS-1$
0769:                    }
0770:                } else {
0771:                    table.put(tag + "get", theMethod); //$NON-NLS-1$
0772:                }
0773:            }
0774:
0775:            @SuppressWarnings("unchecked")
0776:            private static void introspectSet(Method theMethod,
0777:                    HashMap<String, HashMap> propertyTable) {
0778:                String methodName = theMethod.getName();
0779:                if (methodName == null) {
0780:                    return;
0781:                }
0782:
0783:                int prefixLength = 0;
0784:                if (methodName.startsWith(PREFIX_SET)) {
0785:                    prefixLength = PREFIX_GET.length();
0786:                }
0787:
0788:                if (prefixLength == 0) {
0789:                    return;
0790:                }
0791:
0792:                String propertyName = decapitalize(methodName
0793:                        .substring(prefixLength));
0794:
0795:                // validate property name
0796:                if (!isValidProperty(propertyName)) {
0797:                    return;
0798:                }
0799:
0800:                Class returnType = theMethod.getReturnType();
0801:
0802:                if (!returnType.getName().equals(Void.TYPE.getName())) {
0803:                    return;
0804:                }
0805:
0806:                // indexed get method
0807:                Class[] paramTypes = theMethod.getParameterTypes();
0808:
0809:                if ((paramTypes.length == 0) || (paramTypes.length > 2)) {
0810:                    return;
0811:                }
0812:
0813:                String tag = "normal"; //$NON-NLS-1$
0814:
0815:                Class propertyType = paramTypes[0];
0816:
0817:                if (paramTypes.length == 2) {
0818:                    if (paramTypes[0].getName().equals(Integer.TYPE.getName())) {
0819:                        tag = "indexed"; //$NON-NLS-1$
0820:                        propertyType = paramTypes[1];
0821:                    } else {
0822:                        return;
0823:                    }
0824:                }
0825:
0826:                HashMap table = propertyTable.get(propertyName);
0827:                if (table == null) {
0828:                    table = new HashMap();
0829:                }
0830:
0831:                Class oldPropertyType = (Class) table.get(tag + "PropertyType"); //$NON-NLS-1$
0832:                if ((oldPropertyType != null)
0833:                        && (!oldPropertyType.getName().equals(
0834:                                propertyType.getName()))) {
0835:                    table.put(tag, "invalid"); //$NON-NLS-1$
0836:                    return;
0837:                }
0838:
0839:                table.put(tag, "valid"); //$NON-NLS-1$
0840:                table.put(tag + "set", theMethod); //$NON-NLS-1$
0841:                table.put(tag + "PropertyType", propertyType); //$NON-NLS-1$
0842:
0843:                // handle constrained
0844:                Class[] exceptions = theMethod.getExceptionTypes();
0845:                for (Class e : exceptions) {
0846:                    if (e.equals(PropertyVetoException.class)) {
0847:                        table.put("isConstrained", Boolean.TRUE); //$NON-NLS-1$
0848:                    }
0849:                }
0850:                propertyTable.put(propertyName, table);
0851:            }
0852:
0853:            /**
0854:             * Introspects the supplied Bean class and returns a list of the Events of
0855:             * the class
0856:             * 
0857:             * @param beanClass
0858:             * @return the events
0859:             * @throws IntrospectionException
0860:             */
0861:            @SuppressWarnings("unchecked")
0862:            private EventSetDescriptor[] introspectEvents()
0863:                    throws IntrospectionException {
0864:                // Get descriptors for the public methods
0865:                // FIXME: performance
0866:                MethodDescriptor[] theMethods = introspectMethods();
0867:
0868:                if (theMethods == null)
0869:                    return null;
0870:
0871:                HashMap<String, HashMap> eventTable = new HashMap<String, HashMap>(
0872:                        theMethods.length);
0873:
0874:                // Search for methods that add an Event Listener
0875:                for (int i = 0; i < theMethods.length; i++) {
0876:                    introspectListenerMethods(PREFIX_ADD, theMethods[i]
0877:                            .getMethod(), eventTable);
0878:                    introspectListenerMethods(PREFIX_REMOVE, theMethods[i]
0879:                            .getMethod(), eventTable);
0880:                    introspectGetListenerMethods(theMethods[i].getMethod(),
0881:                            eventTable);
0882:
0883:                }
0884:
0885:                ArrayList<EventSetDescriptor> eventList = new ArrayList<EventSetDescriptor>();
0886:                Iterator<String> keys = eventTable.keySet().iterator();
0887:                while (keys.hasNext()) {
0888:                    String key = keys.next();
0889:                    HashMap table = eventTable.get(key);
0890:                    Method add = (Method) table.get(PREFIX_ADD);
0891:                    Method remove = (Method) table.get(PREFIX_REMOVE);
0892:
0893:                    if ((add == null) || (remove == null)) {
0894:                        continue;
0895:                    }
0896:
0897:                    Method get = (Method) table.get(PREFIX_GET);
0898:                    Class<?> listenerType = (Class) table.get("listenerType"); //$NON-NLS-1$
0899:                    Method[] listenerMethods = (Method[]) table
0900:                            .get("listenerMethods"); //$NON-NLS-1$
0901:                    EventSetDescriptor eventSetDescriptor = new EventSetDescriptor(
0902:                            decapitalize(key), listenerType, listenerMethods,
0903:                            add, remove, get);
0904:
0905:                    eventSetDescriptor
0906:                            .setUnicast(table.get("isUnicast") != null); //$NON-NLS-1$
0907:                    eventList.add(eventSetDescriptor);
0908:                }
0909:
0910:                EventSetDescriptor[] theEvents = new EventSetDescriptor[eventList
0911:                        .size()];
0912:                eventList.toArray(theEvents);
0913:
0914:                return theEvents;
0915:            }
0916:
0917:            /*
0918:             * find the add, remove listener method
0919:             */
0920:            @SuppressWarnings("unchecked")
0921:            private static void introspectListenerMethods(String type,
0922:                    Method theMethod, HashMap<String, HashMap> methodsTable) {
0923:                String methodName = theMethod.getName();
0924:                if (methodName == null) {
0925:                    return;
0926:                }
0927:
0928:                if (!((methodName.startsWith(type)) && (methodName
0929:                        .endsWith(SUFFIX_LISTEN)))) {
0930:                    return;
0931:                }
0932:
0933:                String listenerName = methodName.substring(type.length());
0934:                String eventName = listenerName.substring(0, listenerName
0935:                        .lastIndexOf(SUFFIX_LISTEN));
0936:                if ((eventName == null) || (eventName.length() == 0)) {
0937:                    return;
0938:                }
0939:
0940:                Class[] paramTypes = theMethod.getParameterTypes();
0941:                if ((paramTypes == null) || (paramTypes.length != 1)) {
0942:                    return;
0943:                }
0944:
0945:                Class<?> listenerType = paramTypes[0];
0946:
0947:                if (!EventListener.class.isAssignableFrom(listenerType)) {
0948:                    return;
0949:                }
0950:
0951:                if (!listenerType.getName().endsWith(listenerName)) {
0952:                    return;
0953:                }
0954:
0955:                HashMap table = methodsTable.get(eventName);
0956:                if (table == null) {
0957:                    table = new HashMap();
0958:                }
0959:                // put listener type
0960:                if (table.get("listenerType") == null) { //$NON-NLS-1$
0961:                    table.put("listenerType", listenerType); //$NON-NLS-1$
0962:                    table.put("listenerMethods", //$NON-NLS-1$
0963:                            introspectListenerMethods(listenerType));
0964:                }
0965:                // put add / remove
0966:                table.put(type, theMethod);
0967:
0968:                // determine isUnicast()
0969:                if (type.equals(PREFIX_ADD)) {
0970:                    Class[] exceptionTypes = theMethod.getExceptionTypes();
0971:                    if (exceptionTypes != null) {
0972:                        for (int i = 0; i < exceptionTypes.length; i++) {
0973:                            if (exceptionTypes[i].getName().equals(
0974:                                    TooManyListenersException.class.getName())) {
0975:                                table.put("isUnicast", "true"); //$NON-NLS-1$//$NON-NLS-2$
0976:                                break;
0977:                            }
0978:                        }
0979:                    }
0980:                }
0981:
0982:                methodsTable.put(eventName, table);
0983:            }
0984:
0985:            private static Method[] introspectListenerMethods(
0986:                    Class<?> listenerType) {
0987:                Method[] methods = listenerType.getDeclaredMethods();
0988:                ArrayList<Method> list = new ArrayList<Method>();
0989:                for (int i = 0; i < methods.length; i++) {
0990:                    Class[] paramTypes = methods[i].getParameterTypes();
0991:                    if (paramTypes.length != 1) {
0992:                        continue;
0993:                    }
0994:
0995:                    if (EventObject.class.isAssignableFrom(paramTypes[0])) {
0996:                        list.add(methods[i]);
0997:                    }
0998:                }
0999:                Method[] matchedMethods = new Method[list.size()];
1000:                list.toArray(matchedMethods);
1001:                return matchedMethods;
1002:            }
1003:
1004:            @SuppressWarnings("unchecked")
1005:            private static void introspectGetListenerMethods(Method theMethod,
1006:                    HashMap<String, HashMap> methodsTable) {
1007:                String type = PREFIX_GET;
1008:
1009:                String methodName = theMethod.getName();
1010:                if (methodName == null) {
1011:                    return;
1012:                }
1013:
1014:                if (!((methodName.startsWith(type)) && (methodName
1015:                        .endsWith(SUFFIX_LISTEN + "s")))) { //$NON-NLS-1$
1016:                    return;
1017:                }
1018:
1019:                String listenerName = methodName.substring(type.length(),
1020:                        methodName.length() - 1);
1021:                String eventName = listenerName.substring(0, listenerName
1022:                        .lastIndexOf(SUFFIX_LISTEN));
1023:                if ((eventName == null) || (eventName.length() == 0)) {
1024:                    return;
1025:                }
1026:
1027:                Class[] paramTypes = theMethod.getParameterTypes();
1028:                if ((paramTypes == null) || (paramTypes.length != 0)) {
1029:                    return;
1030:                }
1031:
1032:                Class returnType = theMethod.getReturnType();
1033:                if ((returnType.getComponentType() == null)
1034:                        || (!returnType.getComponentType().getName().endsWith(
1035:                                listenerName))) {
1036:                    return;
1037:                }
1038:
1039:                HashMap table = methodsTable.get(eventName);
1040:                if (table == null) {
1041:                    table = new HashMap();
1042:                }
1043:                // put add / remove
1044:                table.put(type, theMethod);
1045:                methodsTable.put(eventName, table);
1046:            }
1047:
1048:            private static boolean isValidProperty(String propertyName) {
1049:                return (propertyName != null) && (propertyName.length() != 0);
1050:            }
1051:
1052:            private static class PropertyComparator implements 
1053:                    Comparator<PropertyDescriptor> {
1054:                public int compare(PropertyDescriptor object1,
1055:                        PropertyDescriptor object2) {
1056:                    return object1.getName().compareTo(object2.getName());
1057:                }
1058:
1059:            }
1060:
1061:            // TODO
1062:            void init() {
1063:                if (this .events == null) {
1064:                    events = new EventSetDescriptor[0];
1065:                }
1066:                if (this .properties == null) {
1067:                    this .properties = new PropertyDescriptor[0];
1068:                }
1069:
1070:                if (properties != null) {
1071:                    String defaultPropertyName = (defaultPropertyIndex != -1 ? properties[defaultPropertyIndex]
1072:                            .getName()
1073:                            : null);
1074:                    Arrays.sort(properties, comparator);
1075:                    if (null != defaultPropertyName) {
1076:                        for (int i = 0; i < properties.length; i++) {
1077:                            if (defaultPropertyName.equals(properties[i]
1078:                                    .getName())) {
1079:                                defaultPropertyIndex = i;
1080:                                break;
1081:                            }
1082:                        }
1083:                    }
1084:                }
1085:            }
1086:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.