Source Code Cross Referenced for AptControlInterface.java in  » Library » Apache-beehive-1.0.2-src » org » apache » beehive » controls » runtime » generator » 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 » Library » Apache beehive 1.0.2 src » org.apache.beehive.controls.runtime.generator 
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:         * $Header:$
0018:         */
0019:        package org.apache.beehive.controls.runtime.generator;
0020:
0021:        import java.io.*;
0022:        import java.lang.reflect.*;
0023:        import java.lang.annotation.*;
0024:        import java.net.*;
0025:        import java.util.*;
0026:
0027:        import com.sun.mirror.apt.Filer;
0028:        import com.sun.mirror.declaration.AnnotationMirror;
0029:        import com.sun.mirror.declaration.AnnotationTypeDeclaration;
0030:        import com.sun.mirror.declaration.Declaration;
0031:        import com.sun.mirror.declaration.InterfaceDeclaration;
0032:        import com.sun.mirror.declaration.MethodDeclaration;
0033:        import com.sun.mirror.declaration.TypeDeclaration;
0034:        import com.sun.mirror.type.DeclaredType;
0035:        import com.sun.mirror.type.InterfaceType;
0036:        import com.sun.mirror.type.MirroredTypesException;
0037:
0038:        import org.apache.beehive.controls.api.bean.ControlChecker;
0039:        import org.apache.beehive.controls.api.bean.ControlExtension;
0040:        import org.apache.beehive.controls.api.bean.ControlInterface;
0041:        import org.apache.beehive.controls.api.bean.ExternalPropertySets;
0042:        import org.apache.beehive.controls.api.events.EventSet;
0043:        import org.apache.beehive.controls.api.packaging.FeatureInfo;
0044:        import org.apache.beehive.controls.api.packaging.ManifestAttribute;
0045:        import org.apache.beehive.controls.api.packaging.ManifestAttributes;
0046:        import org.apache.beehive.controls.api.properties.PropertySet;
0047:        import org.apache.beehive.controls.api.versioning.Version;
0048:        import org.apache.beehive.controls.api.versioning.VersionRequired;
0049:        import org.apache.beehive.controls.runtime.generator.apt.TwoPhaseAnnotationProcessor;
0050:        import org.apache.beehive.controls.runtime.generator.apt.CheckerAnnotationProcessorEnvironmentImpl;
0051:
0052:        /**
0053:         * The AptControlInterface provides validation and metadata management for a ControlInterface
0054:         * or ControlExtension class during APT processing.  It is also used to model the interface
0055:         * to contextual services, since they parallel the conventions of control interfaces.
0056:         */
0057:        public class AptControlInterface extends AptType implements  Generator {
0058:            /**
0059:             * Constructs a new AptControlInterface instance where interface information is derived
0060:             * from an APT interface declaration
0061:             * @param decl the annotated Declaration
0062:             * @param ap the top-level annotation processor
0063:             */
0064:            public AptControlInterface(Declaration decl,
0065:                    TwoPhaseAnnotationProcessor ap) {
0066:                _ap = ap;
0067:
0068:                //
0069:                // Verify that the @ControlInterface/@ControlExtension annotations are only used on an
0070:                // interface.
0071:                // Note: AptControlInterface is also used to construct the operation and event model
0072:                // for contextual services (see AptContextField).  Becaue contextual sevices can actually
0073:                // be classes as well as interfaces, the test below has to be specific to the annotated
0074:                // use cases
0075:                //
0076:                if (!(decl instanceof  InterfaceDeclaration)
0077:                        && (decl.getAnnotation(ControlExtension.class) != null || decl
0078:                                .getAnnotation(ControlInterface.class) != null)) {
0079:                    _ap.printError(decl,
0080:                            "control.interface.annotation.badlocation");
0081:                    return;
0082:                }
0083:
0084:                _intfDecl = (InterfaceDeclaration) decl;
0085:                setDeclaration(_intfDecl);
0086:
0087:                _isExtension = initIsExtension();
0088:
0089:                _super Class = initSuperClass();
0090:
0091:                _operations = initOperations();
0092:
0093:                _intfProps = initIntfProperties();
0094:
0095:                _propertySets = initPropertySets();
0096:
0097:                _eventSets = initEventSets();
0098:
0099:                _featureInfo = initFeatureInfo();
0100:
0101:                _version = initVersion();
0102:                _versionRequired = initVersionRequired();
0103:
0104:                //
0105:                // Construct a bean instance for this interface
0106:                //
0107:                _bean = new ControlBean(this );
0108:
0109:                //
0110:                // Enforce VersionRequired semantics
0111:                //
0112:                enforceVersionRequired();
0113:
0114:                //
0115:                // Do work specific to control extensions
0116:                //
0117:
0118:                if (isExtension()) {
0119:                    //
0120:                    // If this is an control extension, run the control-author-specified
0121:                    // checker class to perform additional validation.
0122:                    //
0123:                    check();
0124:                }
0125:            }
0126:
0127:            /**
0128:             * Returns the parent control interface or extension type from which the control
0129:             * interface is derived (or null, if it is at the root of the interface hierarchy)
0130:             */
0131:            public InterfaceType getSuperType() {
0132:                if (_intfDecl.getSuperinterfaces() == null)
0133:                    return null;
0134:
0135:                for (InterfaceType intfType : _intfDecl.getSuperinterfaces()) {
0136:                    InterfaceDeclaration super Decl = intfType.getDeclaration();
0137:                    if (super Decl != null) {
0138:                        if (super Decl.getAnnotation(ControlExtension.class) != null
0139:                                || super Decl
0140:                                        .getAnnotation(ControlInterface.class) != null) {
0141:                            _super Decl = super Decl;
0142:                            return intfType;
0143:                        }
0144:                    }
0145:                }
0146:
0147:                return null;
0148:            }
0149:
0150:            /**
0151:             * Initializes the super interface that this ControlInterface extends (or sets it to null
0152:             * if a base interface)
0153:             */
0154:            private AptControlInterface initSuperClass() {
0155:                //
0156:                // Look for a super interface that is either a control interface or extension.
0157:                // If found, return it.
0158:                //
0159:                InterfaceType super Type = getSuperType();
0160:                if (super Type == null) {
0161:                    // At this point, we're processing the root of the interface heirarchy,
0162:                    // which is not permitted to be a ControlExtension (that would imply a
0163:                    // ControlExtension that wasn't actually extending a ControlInterface).
0164:                    if (isExtension()) {
0165:                        _ap.printError(_intfDecl,
0166:                                "control.extension.badinterface");
0167:                    }
0168:
0169:                    return null;
0170:                }
0171:
0172:                InterfaceDeclaration super Decl = super Type.getDeclaration();
0173:                if (super Decl != null) {
0174:                    if (super Decl.getAnnotation(ControlExtension.class) != null
0175:                            || super Decl.getAnnotation(ControlInterface.class) != null) {
0176:                        _super Decl = super Decl;
0177:                        AptControlInterface super Intf = new AptControlInterface(
0178:                                _super Decl, _ap);
0179:
0180:                        if (!isExtension() && super Intf.isExtension()) {
0181:                            _ap.printError(_intfDecl,
0182:                                    "control.interface.badinterface");
0183:                        }
0184:                        return super Intf;
0185:                    }
0186:                }
0187:
0188:                return null;
0189:            }
0190:
0191:            /**
0192:             * Returns the super interface for this interface
0193:             */
0194:            public AptControlInterface getSuperClass() {
0195:                return _super Class;
0196:            }
0197:
0198:            /**
0199:             * Initializes the list of operations declared by this AptControlInterface
0200:             */
0201:            private AptMethodSet<AptOperation> initOperations() {
0202:                AptMethodSet<AptOperation> operList = new AptMethodSet<AptOperation>();
0203:
0204:                if (_intfDecl == null)
0205:                    return operList;
0206:
0207:                //
0208:                // Add the methods from the current interface and all super interfaces *other*
0209:                // than the one from which control inheritance or extension is defined.  These
0210:                // exceptions are handled on the super ControlInterface (the return value
0211:                // of AptControlInterface.initSuperClass())
0212:                //
0213:                // Do this by:
0214:                //  - initially populate the check vector with the control interface
0215:                //  - iterate through the check vector, examining each interface to:
0216:                //      * ignore the super interface
0217:                //      * add all declared interface methods to the operations list
0218:                //      * add any super interfaces to the Vector (avoiding recursion)
0219:                //  - the iteration continues until all superinterfaces have been processed
0220:                //
0221:                Vector<InterfaceDeclaration> checkIntfs = new Vector<InterfaceDeclaration>();
0222:                checkIntfs.add(_intfDecl);
0223:
0224:                for (int i = 0; i < checkIntfs.size(); i++) {
0225:                    InterfaceDeclaration intfDecl = checkIntfs.elementAt(i);
0226:                    if (intfDecl.equals(_super Decl))
0227:                        continue;
0228:
0229:                    if (intfDecl.getMethods() == null)
0230:                        continue;
0231:
0232:                    // Add all declared methods, but ignore the mystery <clinit> methods
0233:                    for (MethodDeclaration methodDecl : intfDecl.getMethods())
0234:                        if (!methodDecl.toString().equals("<clinit>()"))
0235:                            operList
0236:                                    .add(new AptOperation(this , methodDecl, _ap));
0237:
0238:                    if (intfDecl.getSuperinterfaces() == null)
0239:                        continue;
0240:
0241:                    for (InterfaceType super Type : intfDecl
0242:                            .getSuperinterfaces()) {
0243:                        InterfaceDeclaration super Decl = super Type
0244:                                .getDeclaration();
0245:                        if (super Decl != null
0246:                                && !checkIntfs.contains(super Decl))
0247:                            checkIntfs.add(super Decl);
0248:                    }
0249:                }
0250:
0251:                return operList;
0252:            }
0253:
0254:            /**
0255:             * Returns the list of ControlOperations declared directly by this AptControlInterface
0256:             */
0257:            public Collection<AptOperation> getOperations() {
0258:                return _operations.getMethods();
0259:            }
0260:
0261:            /**
0262:             * Returns the total number of operations for this control interface
0263:             */
0264:            public int getOperationCount() {
0265:                int count = _operations.size();
0266:                if (_super Class != null)
0267:                    count += _super Class.getOperationCount();
0268:
0269:                return count;
0270:            }
0271:
0272:            /**
0273:             * Initializes the list of PropertySets declared or referenced by this AptControlInterface
0274:             */
0275:            private ArrayList<AptPropertySet> initPropertySets() {
0276:                ArrayList<AptPropertySet> propSets = new ArrayList<AptPropertySet>();
0277:
0278:                if (_intfDecl == null)
0279:                    return propSets;
0280:
0281:                // TODO: enforce presence of prefixes when multiple property sets w/ the same
0282:                // property name exist
0283:
0284:                //
0285:                // Add the intrinsic/base property set
0286:                //
0287:
0288:                TypeDeclaration basePropsDecl = _ap
0289:                        .getAnnotationProcessorEnvironment()
0290:                        .getTypeDeclaration(
0291:                                "org.apache.beehive.controls.api.properties.BaseProperties");
0292:                if (basePropsDecl != null) {
0293:                    propSets.add(new AptPropertySet(null, basePropsDecl, _ap));
0294:                }
0295:
0296:                //
0297:                // Add external property sets
0298:                //
0299:                ExternalPropertySets extPropsAnnotation = _intfDecl
0300:                        .getAnnotation(ExternalPropertySets.class);
0301:                if (extPropsAnnotation != null) {
0302:                    if (isExtension()) {
0303:                        _ap.printError(_intfDecl,
0304:                                "extpropertyset.illegal.usage");
0305:                    }
0306:
0307:                    try {
0308:                        Class[] extProps = extPropsAnnotation.value();
0309:                    } catch (MirroredTypesException mte) {
0310:                        Collection<String> extProps = mte.getQualifiedNames();
0311:                        for (String extPropName : extProps) {
0312:                            TypeDeclaration extPropDecl = _ap
0313:                                    .getAnnotationProcessorEnvironment()
0314:                                    .getTypeDeclaration(extPropName);
0315:                            if (extPropDecl != null) {
0316:                                AptPropertySet extPropSet = new AptPropertySet(
0317:                                        null, extPropDecl, _ap);
0318:                                propSets.add(extPropSet);
0319:                            } else {
0320:                                _ap.printError(_intfDecl,
0321:                                        "extpropertyset.type.not.found",
0322:                                        extPropName);
0323:                            }
0324:                        }
0325:                    }
0326:                }
0327:
0328:                //
0329:                // Add nested property sets
0330:                //
0331:
0332:                if (_intfDecl.getNestedTypes() == null)
0333:                    return propSets;
0334:
0335:                for (TypeDeclaration innerDecl : _intfDecl.getNestedTypes()) {
0336:                    boolean fError = false;
0337:                    if (innerDecl.getAnnotation(PropertySet.class) != null) {
0338:                        if (!(innerDecl instanceof  AnnotationTypeDeclaration)) {
0339:                            _ap.printError(innerDecl,
0340:                                    "propertyset.not.annotation.type");
0341:                            fError = true;
0342:                        }
0343:
0344:                        Retention ret = innerDecl
0345:                                .getAnnotation(Retention.class);
0346:                        if (ret == null
0347:                                || ret.value() != RetentionPolicy.RUNTIME) {
0348:                            _ap.printError(innerDecl,
0349:                                    "propertyset.missing.retention");
0350:                            fError = true;
0351:                        }
0352:
0353:                        if (isExtension()) {
0354:                            _ap.printError(innerDecl,
0355:                                    "propertyset.illegal.usage.2");
0356:                            fError = true;
0357:                        }
0358:
0359:                        if (!fError)
0360:                            propSets
0361:                                    .add(new AptPropertySet(
0362:                                            this ,
0363:                                            (AnnotationTypeDeclaration) innerDecl,
0364:                                            _ap));
0365:                    }
0366:                }
0367:
0368:                //
0369:                // Detect the presence of locally declared bound or constrained properties
0370:                // Enforce property name (including prefix) uniqueness across all propertysets on this interface.
0371:                //
0372:
0373:                Set<String> propertyNames = new HashSet<String>();
0374:
0375:                for (AptPropertySet propSet : propSets) {
0376:                    for (AptProperty prop : propSet.getProperties()) {
0377:                        if (prop.isBound())
0378:                            _hasBoundProperties = true;
0379:
0380:                        if (prop.isConstrained())
0381:                            _hasConstrainedProperties = true;
0382:
0383:                        String propName = prop.getAccessorName();
0384:
0385:                        if (propertyNames.contains(propName)) {
0386:                            _ap.printError(_intfDecl,
0387:                                    "propertyset.duplicate.property.names",
0388:                                    propName, propSet.getShortName());
0389:                        } else {
0390:                            propertyNames.add(propName);
0391:                        }
0392:                    }
0393:                }
0394:
0395:                return propSets;
0396:            }
0397:
0398:            /**
0399:             * Returns the list of PropertySets declared directly by this AptControlInterface
0400:             */
0401:            public Collection<AptPropertySet> getPropertySets() {
0402:                return _propertySets;
0403:            }
0404:
0405:            /**
0406:             * Returns the total number of properties for this control interface
0407:             */
0408:            public int getPropertyCount() {
0409:                int count;
0410:                if (_super Class == null)
0411:                    count = 0;
0412:                else
0413:                    count = _super Class.getPropertyCount();
0414:
0415:                for (AptPropertySet propertySet : _propertySets) {
0416:                    // if a property set is set to optional and hasSetters is set to false,
0417:                    // there isn't a getter or setter available for that property
0418:                    if (propertySet.hasSetters() || !propertySet.isOptional()) {
0419:                        count += propertySet.getProperties().size();
0420:                    }
0421:                }
0422:
0423:                count += _intfProps.size();
0424:                return count;
0425:            }
0426:
0427:            /**
0428:             * Returns the list of properties defined by getter and setter methods in this control interface.
0429:             */
0430:            public Collection<AptControlInterfaceProperty> getInterfaceProperties() {
0431:                return _intfProps;
0432:            }
0433:
0434:            /**
0435:             * Returns true if the interface has any bound properties associated with it.
0436:             */
0437:            public boolean hasBoundProperties() {
0438:                if (_super Class != null && _super Class.hasBoundProperties())
0439:                    return true;
0440:
0441:                return _hasBoundProperties;
0442:            }
0443:
0444:            /**
0445:             * Returns true if this interface is the first interface in the inheritance hierarchy
0446:             * to declare support for bound properties.  This is used to declared PropertyChangeListener
0447:             * registration methods for the bean once (and only once).
0448:             */
0449:            public boolean addsBoundPropertySupport() {
0450:                //
0451:                // If a super interface has already added support, then not added here
0452:                //
0453:                if (_super Class != null
0454:                        && _super Class.addsBoundPropertySupport())
0455:                    return false;
0456:
0457:                return hasBoundProperties();
0458:            }
0459:
0460:            /**
0461:             * Returns true if any properties declared directly by this control interface are constrained
0462:             * properties.  This <b>will not</b> reflect the attributes of properties declared on
0463:             * an interface from which this interface derives.
0464:             */
0465:            public boolean hasConstrainedProperties() {
0466:                if (_super Class != null
0467:                        && _super Class.hasConstrainedProperties())
0468:                    return true;
0469:
0470:                return _hasConstrainedProperties;
0471:            }
0472:
0473:            /**
0474:             * Returns true if this interface is the first interface in the inheritance hierarchy
0475:             * to declare support for constrained properties.  This is used to declared 
0476:             * VetoableChangeListener registration methods for the bean once (and only once).
0477:             */
0478:            public boolean addsConstrainedPropertySupport() {
0479:                //
0480:                // If a super interface has already added support, then not added here
0481:                //
0482:                if (_super Class != null
0483:                        && _super Class.addsConstrainedPropertySupport())
0484:                    return false;
0485:
0486:                return hasConstrainedProperties();
0487:            }
0488:
0489:            /**
0490:             * Initializes the list of EventSets declared by this AptControlInterface
0491:             */
0492:            private ArrayList<AptEventSet> initEventSets() {
0493:                ArrayList<AptEventSet> eventSets = new ArrayList<AptEventSet>();
0494:
0495:                if (_intfDecl == null || _intfDecl.getNestedTypes() == null)
0496:                    return eventSets;
0497:
0498:                for (TypeDeclaration innerDecl : _intfDecl.getNestedTypes()) {
0499:                    // HACKHACK: There appear to be mirror API bugs where calling getAnnotation()
0500:                    // on certain entity types will result in an endless loop.  For now, work around
0501:                    // this by a priori filtering... but this mechanism will drop errors that appear
0502:                    // on an inapropriate type (see check below)
0503:                    if (!(innerDecl instanceof  InterfaceDeclaration))
0504:                        continue;
0505:
0506:                    if (innerDecl.getAnnotation(EventSet.class) != null) {
0507:
0508:                        if (!(innerDecl instanceof  InterfaceDeclaration)) {
0509:                            _ap.printError(innerDecl, "eventset.illegal.usage");
0510:                        } else {
0511:                            eventSets.add(new AptEventSet(this ,
0512:                                    (InterfaceDeclaration) innerDecl, _ap));
0513:                        }
0514:                    }
0515:                }
0516:                return eventSets;
0517:            }
0518:
0519:            /**
0520:             * Returns the list of AptEventSet declared directly by this AptControlInterface
0521:             */
0522:            public Collection<AptEventSet> getEventSets() {
0523:                return _eventSets;
0524:            }
0525:
0526:            /**
0527:             * Returns the total number of operations for this control interface
0528:             */
0529:            public int getEventSetCount() {
0530:                int count = _eventSets.size();
0531:                if (_super Class != null)
0532:                    count += _super Class.getEventSetCount();
0533:
0534:                return count;
0535:            }
0536:
0537:            /**
0538:             * Returns the number of event sets declared in this control interface.
0539:             * Does not include eventset's declared in super class(es).
0540:             */
0541:            public int getLocalEventSetCount() {
0542:                return _eventSets.size();
0543:            }
0544:
0545:            /**
0546:             * Returns the AptEventSet with the specified name
0547:             */
0548:            public AptEventSet getEventSet(String name) {
0549:                for (AptEventSet eventSet : getEventSets())
0550:                    if (eventSet.getClassName().equals(name))
0551:                        return eventSet;
0552:
0553:                if (_super Class != null)
0554:                    return _super Class.getEventSet(name);
0555:
0556:                return null;
0557:            }
0558:
0559:            /**
0560:             * Returns the FeatureInfo attributes for this control interface
0561:             */
0562:            public FeatureInfo getFeatureInfo() {
0563:                return _featureInfo;
0564:            }
0565:
0566:            /**
0567:             * Returns the list of fully qualified class names for types that are derived
0568:             * from this Generator
0569:             */
0570:            public String[] getGeneratedTypes() {
0571:                return new String[] { _bean.getClassName() };
0572:            }
0573:
0574:            /**
0575:             * Returns the Version annotation, if any.
0576:             */
0577:            public Version getVersion() {
0578:                return _version;
0579:            }
0580:
0581:            /**
0582:             * Returns the VersionRequired annotation, if any.
0583:             */
0584:            public VersionRequired getVersionRequired() {
0585:                return _versionRequired;
0586:            }
0587:
0588:            /**
0589:             * Returns the information necessary to generate a ControlBean from this AptControlInterface
0590:             */
0591:            public List<GeneratorOutput> getCheckOutput(Filer filer)
0592:                    throws IOException {
0593:                HashMap<String, Object> map = new HashMap<String, Object>();
0594:
0595:                map.put("intf", this ); // the control interface
0596:                map.put("bean", _bean);
0597:
0598:                ArrayList<GeneratorOutput> genList = new ArrayList<GeneratorOutput>();
0599:
0600:                //
0601:                // the ControlBean class
0602:                //
0603:                Writer beanWriter = new IndentingWriter(filer
0604:                        .createSourceFile(_bean.getClassName()));
0605:                GeneratorOutput beanSource = new GeneratorOutput(
0606:                        beanWriter,
0607:                        "org/apache/beehive/controls/runtime/generator/ControlBean.vm",
0608:                        map);
0609:                genList.add(beanSource);
0610:
0611:                //
0612:                // the ControlBean BeanInfo class
0613:                //
0614:                Writer beanInfoWriter = new IndentingWriter(filer
0615:                        .createSourceFile(_bean.getBeanInfoName()));
0616:                GeneratorOutput beanInfoSource = new GeneratorOutput(
0617:                        beanInfoWriter,
0618:                        "org/apache/beehive/controls/runtime/generator/ControlBeanInfo.vm",
0619:                        map);
0620:                genList.add(beanInfoSource);
0621:
0622:                return genList;
0623:            }
0624:
0625:            /**
0626:             * Returns the information necessary to generate a packaging information from this 
0627:             * AptControlInterface.  Since this information is not needed during type validation,
0628:             * it can be delated until the generate phase.
0629:             */
0630:            public List<GeneratorOutput> getGenerateOutput(Filer filer)
0631:                    throws IOException {
0632:                HashMap<String, Object> map = new HashMap<String, Object>();
0633:
0634:                map.put("intf", this ); // the control interface
0635:                map.put("bean", _bean);
0636:
0637:                ArrayList<GeneratorOutput> genList = new ArrayList<GeneratorOutput>();
0638:
0639:                //
0640:                // the ControlBean MANIFEST.MF section
0641:                //
0642:                Writer manifestWriter = filer.createTextFile(
0643:                        Filer.Location.CLASS_TREE, _bean.getPackage(),
0644:                        new File(_bean.getShortName() + ".class.manifest"),
0645:                        null);
0646:                GeneratorOutput beanManifest = new GeneratorOutput(
0647:                        manifestWriter,
0648:                        "org/apache/beehive/controls/runtime/generator/ControlManifest.vm",
0649:                        map);
0650:                genList.add(beanManifest);
0651:
0652:                return genList;
0653:            }
0654:
0655:            /**
0656:             * Returns true if this interface is a ControlExtension (jcx) interface, false
0657:             * otherwise.
0658:             */
0659:            public boolean isExtension() {
0660:                return _isExtension;
0661:            }
0662:
0663:            /**
0664:             * Returns the most-derived interface in the inheritance chain that is annotated
0665:             * with @ControlInterface.  It represents the point in the inheritance chain
0666:             * where @ControlInterface becomes @ControlExtension (i.e., anything interface derived from
0667:             * the 'most-derived interface' is annotated with @ControlExtension).  May return
0668:             * null if the inheritance chain is malformed.
0669:             */
0670:            public AptControlInterface getMostDerivedInterface() {
0671:                //
0672:                // Walk up ControlInterface chain looking for the 1st instance annotated
0673:                // w/ @ControlInterface (as opposed to @ControlExtension)
0674:                //
0675:                // REVIEW: TBD rules for inheritance of @ControlInterface will affect this.
0676:                // Probably need to keep walking and examine each @ControlInterface in the chain.
0677:                // Run all checkers in chain?  Make checkers responsible for invoking their base
0678:                // class-defined checkers?
0679:                //
0680:
0681:                AptControlInterface ancestor = getSuperClass();
0682:                while (ancestor != null) {
0683:                    if (!ancestor.isExtension())
0684:                        break;
0685:
0686:                    ancestor = ancestor.getSuperClass();
0687:                }
0688:
0689:                return ancestor;
0690:            }
0691:
0692:            /**
0693:             * Returns a classloader that can be used to load external classes
0694:             */
0695:            public ClassLoader getExternalClassLoader() {
0696:                Map<String, String> opts = _ap
0697:                        .getAnnotationProcessorEnvironment().getOptions();
0698:                String classpath = opts.get("-classpath");
0699:
0700:                if (classpath != null) {
0701:                    String[] cpEntries = classpath.split(File.pathSeparator);
0702:                    ArrayList a = new ArrayList();
0703:                    for (String e : cpEntries) {
0704:                        try {
0705:                            File f = (new File(e)).getCanonicalFile();
0706:                            URL u = f.toURL();
0707:                            a.add(u);
0708:                        } catch (Exception ex) {
0709:                            System.err
0710:                                    .println("getExternalClassLoader(): bad cp entry="
0711:                                            + e);
0712:                            System.err.println("Exception processing e=" + ex);
0713:                        }
0714:                    }
0715:                    URL[] urls = new URL[a.size()];
0716:                    urls = (URL[]) a.toArray(urls);
0717:
0718:                    return new URLClassLoader(urls, ControlChecker.class
0719:                            .getClassLoader());
0720:                }
0721:
0722:                return null;
0723:            }
0724:
0725:            //
0726:            // These are defined by the JAR spec, Name-value pair section
0727:            //
0728:            static final String alphaNum = "ABCDEFGHIJKLMNOPQRSUVWXYZabcdefghijklmnopqrstuvwyz0123456789";
0729:            static final String headerChar = alphaNum + "_-";
0730:
0731:            /**
0732:             *  Validates a manifest attribute.  If the attribute is invalid, it will generate
0733:             *  appropriate APT messager entries and return false, else return true.
0734:             */
0735:            private boolean isValidManifestAttribute(ManifestAttribute attr) {
0736:                String name = attr.name();
0737:                String value = attr.value();
0738:                boolean isValid = true;
0739:
0740:                /*
0741:                Note, the null-check for "name" is necessary when the annotation processor is hosted inside
0742:                of an IDE where the name attribute of the ManifestAttribute metadata can be null
0743:                temporarily.  In order to "keep going", just report a warning and proceed.
0744:                 */
0745:                if (name == null || name.length() == 0) {
0746:                    _ap.printError(_intfDecl,
0747:                            "manifestattribute.illegal.name.1");
0748:                    isValid = false;
0749:                } else {
0750:                    if (alphaNum.indexOf(name.charAt(0)) < 0) {
0751:                        _ap.printError(_intfDecl,
0752:                                "manifestattribute.illegal.name.2");
0753:                        isValid = false;
0754:                    }
0755:                    for (int i = 1; i < name.length(); i++) {
0756:                        if (headerChar.indexOf(name.charAt(i)) < 0) {
0757:                            _ap.printError(_intfDecl,
0758:                                    "manifestattribute.illegal.name.3", name
0759:                                            .charAt(i));
0760:                            isValid = false;
0761:                            break;
0762:                        }
0763:                    }
0764:                }
0765:
0766:                /*
0767:                Note, the null-check for "value" is necessary when the annotation processor is hosted inside
0768:                of an IDE where the value attribute of the ManifestAttribute metadata can be null
0769:                temporarily.  In order to "keep going", just report a warning and proceed.
0770:                 */
0771:                if (value == null || value.length() == 0) {
0772:                    _ap.printError(_intfDecl,
0773:                            "manifestattribute.illegal.name.4");
0774:                    isValid = false;
0775:                } else {
0776:                    // TODO: validate string contents are valid UTF-8?
0777:                }
0778:
0779:                return isValid;
0780:            }
0781:
0782:            /**
0783:             * Returns the array of ManifestAttributes associated with the AptControlInterface
0784:             */
0785:            public HashMap<String, String> getManifestAttributes() {
0786:                HashMap<String, String> attributes = new HashMap<String, String>();
0787:
0788:                if (_intfDecl == null)
0789:                    return attributes;
0790:
0791:                try {
0792:                    ManifestAttributes annotAttrs = _intfDecl
0793:                            .getAnnotation(ManifestAttributes.class);
0794:                    if (annotAttrs != null) {
0795:                        ManifestAttribute[] attrs = (ManifestAttribute[]) annotAttrs
0796:                                .value();
0797:                        for (int i = 0; i < attrs.length; i++) {
0798:                            if (isValidManifestAttribute(attrs[i]))
0799:                                attributes.put(attrs[i].name(), attrs[i]
0800:                                        .value());
0801:                        }
0802:                    }
0803:                    ManifestAttribute annotAttr = _intfDecl
0804:                            .getAnnotation(ManifestAttribute.class);
0805:                    if (annotAttr != null) {
0806:                        if (isValidManifestAttribute(annotAttr))
0807:                            attributes.put(annotAttr.name(), annotAttr.value());
0808:                    }
0809:                    return attributes;
0810:                } catch (Exception e) {
0811:                    e.printStackTrace();
0812:                    return attributes;
0813:                }
0814:            }
0815:
0816:            /**
0817:             * Computes whether this interface is a ControlInterface or a ControlExtension
0818:             */
0819:            private boolean initIsExtension() {
0820:                if (_intfDecl == null)
0821:                    return false;
0822:
0823:                return _intfDecl.getAnnotation(ControlExtension.class) != null;
0824:            }
0825:
0826:            /**
0827:             * Returns the FeatureInfo annotation for this control interface, or null if there is none.
0828:             */
0829:            private FeatureInfo initFeatureInfo() {
0830:                if (_intfDecl == null)
0831:                    return null;
0832:                return _intfDecl.getAnnotation(FeatureInfo.class);
0833:            }
0834:
0835:            /**
0836:             * Returns the Version annotation for this control interface, or null if there is none.
0837:             */
0838:            private Version initVersion() {
0839:                if (_intfDecl == null)
0840:                    return null;
0841:                return _intfDecl.getAnnotation(Version.class);
0842:            }
0843:
0844:            /**
0845:             * Returns the VersionRequired annotation for this control interface, or null if there is none.
0846:             */
0847:            private VersionRequired initVersionRequired() {
0848:                if (_intfDecl == null)
0849:                    return null;
0850:                return _intfDecl.getAnnotation(VersionRequired.class);
0851:            }
0852:
0853:            /**
0854:             * Enforces the VersionRequired annotation for control extensions.
0855:             */
0856:            private void enforceVersionRequired() {
0857:                if (_versionRequired != null) {
0858:                    if (!isExtension()) {
0859:                        _ap.printError(_intfDecl,
0860:                                "versionrequired.illegal.usage");
0861:                        return;
0862:                    }
0863:
0864:                    int majorRequired = _versionRequired.major();
0865:                    int minorRequired = _versionRequired.minor();
0866:
0867:                    if (majorRequired < 0) // no real version requirement
0868:                        return;
0869:
0870:                    AptControlInterface ci = getMostDerivedInterface();
0871:                    if (ci == null)
0872:                        return;
0873:
0874:                    int majorPresent = -1;
0875:                    int minorPresent = -1;
0876:                    Version ciVersion = ci._version;
0877:                    if (ciVersion != null) {
0878:                        majorPresent = ciVersion.major();
0879:                        minorPresent = ciVersion.minor();
0880:
0881:                        if (majorRequired <= majorPresent
0882:                                && (minorRequired < 0 || minorRequired <= minorPresent)) {
0883:                            // Version requirement is satisfied
0884:                            return;
0885:                        }
0886:                    }
0887:
0888:                    //
0889:                    // Version requirement failed
0890:                    //
0891:                    _ap.printError(_intfDecl, "versionrequired.failed",
0892:                            _intfDecl.getSimpleName(), majorRequired,
0893:                            minorRequired, majorPresent, minorPresent);
0894:                }
0895:            }
0896:
0897:            /**
0898:             * Runs control-specific checker class (if specified)
0899:             */
0900:            public void check() {
0901:                //
0902:                // Find the nearest @ControlInterface, which is where the relevant control checker
0903:                // annotation will be found.
0904:                //
0905:
0906:                AptControlInterface mostDerived = (AptControlInterface) getMostDerivedInterface();
0907:                if (mostDerived == null)
0908:                    return;
0909:
0910:                InterfaceDeclaration intfDecl = mostDerived._intfDecl;
0911:
0912:                if (intfDecl == null)
0913:                    return;
0914:
0915:                AnnotationMirror controlMirror = null;
0916:
0917:                for (AnnotationMirror annot : intfDecl.getAnnotationMirrors()) {
0918:                    if (annot
0919:                            .getAnnotationType()
0920:                            .getDeclaration()
0921:                            .getQualifiedName()
0922:                            .equals(
0923:                                    "org.apache.beehive.controls.api.bean.ControlInterface")) {
0924:                        controlMirror = annot;
0925:                        break;
0926:                    }
0927:                }
0928:
0929:                assert (controlMirror != null) : "Found a control interface that isn't annotated properly: "
0930:                        + intfDecl;
0931:
0932:                AptAnnotationHelper controlAnnot = new AptAnnotationHelper(
0933:                        controlMirror);
0934:
0935:                //
0936:                // Read the name of the checker class from the @ControlInterface annotation,
0937:                // dynamically load and run it.
0938:                //
0939:
0940:                DeclaredType checkerMirror = (DeclaredType) controlAnnot
0941:                        .getObjectValue("checker");
0942:                if (checkerMirror == null) {
0943:                    // try the deprecated 'checkerClass' attribute
0944:                    checkerMirror = (DeclaredType) controlAnnot
0945:                            .getObjectValue("checkerClass");
0946:                }
0947:
0948:                if (checkerMirror != null
0949:                        && checkerMirror.getDeclaration() != null) {
0950:                    // TODO: optimize to not invoke default checker?
0951:                    String checkerName = checkerMirror.toString();
0952:
0953:                    try {
0954:                        ClassLoader loader = getExternalClassLoader();
0955:
0956:                        Class checkerClass = loader.loadClass(checkerName);
0957:                        if (!ControlChecker.class
0958:                                .isAssignableFrom(checkerClass)) {
0959:                            _ap.printError(intfDecl,
0960:                                    "control.interface.illegal.checker",
0961:                                    intfDecl.getSimpleName(), checkerName);
0962:                        } else {
0963:
0964:                            Constructor ctor = checkerClass.getConstructor();
0965:
0966:                            ControlChecker checker = (ControlChecker) ctor
0967:                                    .newInstance();
0968:                            CheckerAnnotationProcessorEnvironmentImpl ape = new CheckerAnnotationProcessorEnvironmentImpl(
0969:                                    _ap);
0970:                            checker.check(_intfDecl, ape);
0971:                        }
0972:                    } catch (Exception e) {
0973:                        _ap.printError(intfDecl,
0974:                                "control.interface.checker.load.failed",
0975:                                intfDecl.getSimpleName(), checkerName);
0976:                    }
0977:                }
0978:            }
0979:
0980:            /**
0981:             * Build a list of properties defined by getter/setter methods on this control interface.
0982:             */
0983:            private ArrayList<AptControlInterfaceProperty> initIntfProperties() {
0984:
0985:                HashMap<String, AptControlInterfaceProperty> intfPropMap = new HashMap<String, AptControlInterfaceProperty>();
0986:
0987:                Collection<AptOperation> ops = getOperations();
0988:                for (AptOperation op : ops) {
0989:                    String opName = op.getName();
0990:                    if (!op.isPublic()) {
0991:                        continue;
0992:                    }
0993:
0994:                    if (isGetter(op)) {
0995:                        String propertyName = getIntfPropertyName(op);
0996:                        if (intfPropMap.containsKey(propertyName)) {
0997:                            intfPropMap.get(propertyName).setGetterName(opName);
0998:                        } else {
0999:                            intfPropMap.put(propertyName,
1000:                                    new AptControlInterfaceProperty(
1001:                                            propertyName, opName, null));
1002:                        }
1003:                    } else if (isSetter(op)) {
1004:                        String propertyName = getIntfPropertyName(op);
1005:                        if (intfPropMap.containsKey(propertyName)) {
1006:                            intfPropMap.get(propertyName).setSetterName(opName);
1007:                        } else {
1008:                            intfPropMap.put(propertyName,
1009:                                    new AptControlInterfaceProperty(
1010:                                            propertyName, null, opName));
1011:                        }
1012:                    } else if (isIsGetter(op)) {
1013:                        String propertyName = getIntfPropertyName(op);
1014:                        if (intfPropMap.containsKey(propertyName)) {
1015:                            intfPropMap.get(propertyName).setGetterName(opName);
1016:                        } else {
1017:                            intfPropMap.put(propertyName,
1018:                                    new AptControlInterfaceProperty(
1019:                                            propertyName, opName, null));
1020:                        }
1021:                    }
1022:                }
1023:                return new ArrayList<AptControlInterfaceProperty>(intfPropMap
1024:                        .values());
1025:            }
1026:
1027:            /**
1028:             * Does the method have a Java Beans getter method signature.
1029:             * @param method AptMethod instance
1030:             * @return true if getter
1031:             */
1032:            private boolean isGetter(AptMethod method) {
1033:                String methodName = method.getName();
1034:
1035:                if (methodName.length() < 4)
1036:                    return false;
1037:
1038:                if (!methodName.startsWith("get"))
1039:                    return false;
1040:
1041:                if (method.getArgList().length() > 0)
1042:                    return false;
1043:
1044:                if ("void".equals(method.getReturnType()))
1045:                    return false;
1046:
1047:                return true;
1048:            }
1049:
1050:            /**
1051:             * Does the method have a Java Beans getter method signature (is varient).
1052:             * @param method AptMethod instance.
1053:             * @return true if 'is' getter.
1054:             */
1055:            private boolean isIsGetter(AptMethod method) {
1056:                String methodName = method.getName();
1057:
1058:                if (methodName.length() < 3)
1059:                    return false;
1060:
1061:                if (!methodName.startsWith("is"))
1062:                    return false;
1063:
1064:                if (method.getArgList().length() > 0)
1065:                    return false;
1066:
1067:                if (!"boolean".equals(method.getReturnType()))
1068:                    return false;
1069:
1070:                return true;
1071:            }
1072:
1073:            /**
1074:             * Does the method have a Java Beans setter method signature (is varient).
1075:             * @param method AptMethod instance.
1076:             * @return true if setter.
1077:             */
1078:            private boolean isSetter(AptMethod method) {
1079:                String methodName = method.getName();
1080:
1081:                if (methodName.length() < 4)
1082:                    return false;
1083:
1084:                if (!methodName.startsWith("set"))
1085:                    return false;
1086:
1087:                String argList = method.getArgList();
1088:                if (argList.length() == 0)
1089:                    return false;
1090:
1091:                if (argList.indexOf(',') > -1)
1092:                    return false;
1093:
1094:                if (!"void".equals(method.getReturnType()))
1095:                    return false;
1096:
1097:                return true;
1098:            }
1099:
1100:            /**
1101:             * Generate a property name from a method name.
1102:             * @param method AptMethod instance.
1103:             * @return property name.
1104:             */
1105:            private String getIntfPropertyName(AptMethod method) {
1106:                String opName = method.getName();
1107:
1108:                int prefixIdx = 3;
1109:                if (opName.startsWith("is"))
1110:                    prefixIdx = 2;
1111:
1112:                if (opName.length() == prefixIdx + 1)
1113:                    return "" + Character.toLowerCase(opName.charAt(prefixIdx));
1114:
1115:                return Character.toLowerCase(opName.charAt(prefixIdx))
1116:                        + opName.substring(prefixIdx + 1);
1117:            }
1118:
1119:            private ArrayList<AptControlInterfaceProperty> _intfProps;
1120:            private AptControlInterface _super Class;
1121:            private AptMethodSet<AptOperation> _operations;
1122:            private ArrayList<AptPropertySet> _propertySets;
1123:            private boolean _isExtension; // true if ControlExtension, else ControlInterface
1124:            private boolean _hasBoundProperties;
1125:            private boolean _hasConstrainedProperties;
1126:            private ArrayList<AptEventSet> _eventSets;
1127:            private ControlBean _bean;
1128:            private FeatureInfo _featureInfo;
1129:            private Version _version;
1130:            private VersionRequired _versionRequired;
1131:            private InterfaceDeclaration _intfDecl;
1132:            private InterfaceDeclaration _super Decl;
1133:            private TwoPhaseAnnotationProcessor _ap;
1134:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.