Source Code Cross Referenced for GiLoader.java in  » Ajax » dwr » org » directwebremoting » drapgen » loader » gi » 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 » Ajax » dwr » org.directwebremoting.drapgen.loader.gi 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright 2005 Joe Walker
0003:         *
0004:         * Licensed under the Apache License, Version 2.0 (the "License");
0005:         * you may not use this file except in compliance with the License.
0006:         * You may obtain a copy of the License at
0007:         *
0008:         *     http://www.apache.org/licenses/LICENSE-2.0
0009:         *
0010:         * Unless required by applicable law or agreed to in writing, software
0011:         * distributed under the License is distributed on an "AS IS" BASIS,
0012:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013:         * See the License for the specific language governing permissions and
0014:         * limitations under the License.
0015:         */
0016:        package org.directwebremoting.drapgen.loader.gi;
0017:
0018:        import java.io.File;
0019:        import java.util.ArrayList;
0020:        import java.util.HashMap;
0021:        import java.util.HashSet;
0022:        import java.util.LinkedList;
0023:        import java.util.List;
0024:        import java.util.Map;
0025:        import java.util.Set;
0026:        import java.util.SortedSet;
0027:        import java.util.Stack;
0028:        import java.util.TreeSet;
0029:        import java.util.concurrent.ExecutorService;
0030:        import java.util.concurrent.Executors;
0031:        import java.util.concurrent.TimeUnit;
0032:
0033:        import nu.xom.Attribute;
0034:        import nu.xom.Builder;
0035:        import nu.xom.Document;
0036:        import nu.xom.Element;
0037:        import nu.xom.Elements;
0038:        import nu.xom.Node;
0039:        import nu.xom.Nodes;
0040:        import nu.xom.XPathException;
0041:
0042:        import org.directwebremoting.drapgen.ast.Constructor;
0043:        import org.directwebremoting.drapgen.ast.Field;
0044:        import org.directwebremoting.drapgen.ast.Method;
0045:        import org.directwebremoting.drapgen.ast.Parameter;
0046:        import org.directwebremoting.drapgen.ast.Project;
0047:        import org.directwebremoting.drapgen.ast.Type;
0048:        import org.directwebremoting.drapgen.loader.Loader;
0049:        import org.directwebremoting.drapgen.util.XomHelper;
0050:        import org.directwebremoting.drapgen.util.XomHelper.ElementBlock;
0051:        import org.directwebremoting.fsguide.FileSystemGuide;
0052:        import org.directwebremoting.fsguide.Visitor;
0053:        import org.directwebremoting.util.Logger;
0054:
0055:        /**
0056:         * @author Joe Walker [joe at getahead dot ltd dot uk]
0057:         */
0058:        public class GiLoader implements  Loader {
0059:            /**
0060:             * @param source Where we read the API XML source from
0061:             */
0062:            public GiLoader(File source) throws Exception {
0063:                log.info("Loading GI API from: " + source.getCanonicalPath());
0064:                load(source);
0065:            }
0066:
0067:            /**
0068:             * @param source Where we read the API XML source from
0069:             */
0070:            protected void load(File source) throws Exception {
0071:                loadGiClasses(source);
0072:
0073:                applyPreProcessingHacks();
0074:                copyMixinFunctions();
0075:                trimDuplicateMethods();
0076:                applyPostProcessingHacks();
0077:            }
0078:
0079:            /**
0080:             * 
0081:             */
0082:            protected void applyPreProcessingHacks() {
0083:                log
0084:                        .warn("jsx3.gui.Alerts.alert(): Type of parameter 'objParams' should be 'String'");
0085:                changeAttributeValue(
0086:                        "jsx3.gui.Alerts",
0087:                        "/interface/method[@name='alert']/param[@name='objParams']/type",
0088:                        "name", "String");
0089:
0090:                log
0091:                        .warn("jsx3.gui.Alerts.prompt(): Type of parameter 'objParams' should be 'String'");
0092:                changeAttributeValue(
0093:                        "jsx3.gui.Alerts",
0094:                        "/interface/method[@name='prompt']/param[@name='objParams']/type",
0095:                        "name", "String");
0096:
0097:                log
0098:                        .warn("jsx3.gui.Alerts.confirm(): Type of parameter 'objParams' should be 'String'");
0099:                changeAttributeValue(
0100:                        "jsx3.gui.Alerts",
0101:                        "/interface/method[@name='confirm']/param[@name='objParams']/type",
0102:                        "name", "String");
0103:
0104:                log
0105:                        .warn("jsx3.chart.PlotChart.DEFAULT_MAX_POINT_RADIUS: Type of number can't be 'String' assuming 'int'");
0106:                changeAttributeValue("jsx3.chart.PlotChart",
0107:                        "/class/field[@name='DEFAULT_MAX_POINT_RADIUS']/type",
0108:                        "name", "int");
0109:
0110:                log
0111:                        .warn("jsx3.gui.Matrix.MINIMUM_COLUMN_WIDTH: Type of number can't be 'String' assuming 'int'");
0112:                changeAttributeValue("jsx3.gui.Matrix",
0113:                        "/class/field[@name='MINIMUM_COLUMN_WIDTH']/type",
0114:                        "name", "int");
0115:            }
0116:
0117:            /**
0118:             * 
0119:             */
0120:            protected void changeAttributeValue(String typename,
0121:                    String elementXPath, final String attributeName,
0122:                    final String newValue) {
0123:                Document doc = types.get(typename);
0124:                int changes = XomHelper.query(doc, elementXPath,
0125:                        new ElementBlock() {
0126:                            public void use(Element typeElement) {
0127:                                typeElement.addAttribute(new Attribute(
0128:                                        attributeName, newValue));
0129:                            }
0130:                        });
0131:
0132:                if (changes == 0) {
0133:                    log.warn("** Changing " + elementXPath + " from "
0134:                            + typename + " didn't result in any changes");
0135:                }
0136:            }
0137:
0138:            /**
0139:             * 
0140:             */
0141:            protected void applyPostProcessingHacks() {
0142:                log
0143:                        .warn("jsx3.gui.TextBox.OVERFLOWSCROLL: Field is overridden from jsx3.gui.Block (with a different type), is this safe?");
0144:                removeElement("jsx3.gui.TextBox",
0145:                        "/class/field[@name='OVERFLOWSCROLL']");
0146:
0147:                log
0148:                        .warn("jsx3.gui.Block.OVERFLOWSCROLL: Field is overridden in jsx3.gui.TextBox (with a different type), is this safe?");
0149:                removeElement("jsx3.gui.Block",
0150:                        "/class/field[@name='OVERFLOWSCROLL']");
0151:
0152:                log
0153:                        .warn("jsx3.gui.Block.DEFAULTCLASSNAME: Field is overridden in several places, is this safe?");
0154:                removeElement("jsx3.gui.Block",
0155:                        "/class/field[@name='DEFAULTCLASSNAME']");
0156:
0157:                log
0158:                        .warn("jsx3.gui.Block.DEFAULTFONTSIZE: Field is overridden in jsx3.gui.WindowBar, is this safe?");
0159:                removeElement("jsx3.gui.Block",
0160:                        "/class/field[@name='DEFAULTFONTSIZE']");
0161:
0162:                log
0163:                        .warn("jsx3.chart.Chart.DEFAULT_FILLS: Ignoring, value has been trimmed to 1st line");
0164:                removeElement("jsx3.chart.Chart",
0165:                        "/class/field[@name='DEFAULT_FILLS']");
0166:
0167:                log
0168:                        .warn("jsx3.app.Model.META_FIELDS: Ignoring, value has been trimmed to 1st line");
0169:                removeElement("jsx3.app.Model",
0170:                        "/class/field[@name='META_FIELDS']");
0171:
0172:                log
0173:                        .warn("jsx3.gui.Sound.QUICKTIME: Ignoring, value has been trimmed to 1st line");
0174:                removeElement("jsx3.gui.Sound",
0175:                        "/class/field[@name='QUICKTIME']");
0176:
0177:                log
0178:                        .warn("jsx3.gui.Table.DEFAULT_CELL_VALUE_TEMPLATE: Ignoring, value has been trimmed to 1st line");
0179:                removeElement("jsx3.gui.Table",
0180:                        "/class/field[@name='DEFAULT_CELL_VALUE_TEMPLATE']");
0181:
0182:                // We don't warn for these because Drapgen is at fault
0183:                removeElement("jsx3.chart.PointRenderer",
0184:                        "/interface/field[@name='CIRCLE']");
0185:                removeElement("jsx3.chart.PointRenderer",
0186:                        "/interface/field[@name='CROSS']");
0187:                removeElement("jsx3.chart.PointRenderer",
0188:                        "/interface/field[@name='DIAMOND']");
0189:                removeElement("jsx3.chart.PointRenderer",
0190:                        "/interface/field[@name='BOX']");
0191:                removeElement("jsx3.chart.PointRenderer",
0192:                        "/interface/field[@name='TRIANGLE']");
0193:
0194:                log
0195:                        .warn("jsx3.gui.Stack.BORDER: ';' in value triggers end of line trimming");
0196:                removeElement("jsx3.gui.Stack", "/class/field[@name='BORDER']");
0197:
0198:                log
0199:                        .warn("jsx3.gui.WindowBar.DEFAULTBORDER: ';' in value triggers end of line trimming");
0200:                removeElement("jsx3.gui.WindowBar",
0201:                        "/class/field[@name='DEFAULTBORDER']");
0202:
0203:                log
0204:                        .warn("jsx3.gui.WindowBar.DEFAULTBORDERCAPTION: ';' in value triggers end of line trimming");
0205:                removeElement("jsx3.gui.WindowBar",
0206:                        "/class/field[@name='DEFAULTBORDERCAPTION']");
0207:            }
0208:
0209:            /**
0210:             * Utility to remove (an) element(s) by xpath selector from a type
0211:             */
0212:            protected void removeElement(String typename, String xpath) {
0213:                Document doc = types.get(typename);
0214:                int changes = XomHelper.query(doc, xpath, new ElementBlock() {
0215:                    public void use(Element element) {
0216:                        element.getParent().removeChild(element);
0217:                    }
0218:                });
0219:
0220:                if (changes == 0) {
0221:                    log.warn("** Removing " + xpath + " from " + typename
0222:                            + " didn't result in any changes");
0223:                }
0224:            }
0225:
0226:            /**
0227:             * Load the GI XML files into a map of loaded XOM documents
0228:             * @param directory The source of GI XML files
0229:             */
0230:            protected void loadGiClasses(final File directory) {
0231:                types = new HashMap<String, Document>();
0232:
0233:                // Create a list of all the classes we need to generate
0234:                FileSystemGuide guide = new FileSystemGuide(directory);
0235:                guide.visit(new Visitor() {
0236:                    public void visitFile(File file) {
0237:                        try {
0238:                            if (!file.getAbsolutePath().endsWith(".xml")) {
0239:                                log.info("Skipping: " + file.getAbsolutePath());
0240:                                return;
0241:                            }
0242:
0243:                            String className = file.getAbsolutePath()
0244:                                    .substring(
0245:                                            directory.getAbsolutePath()
0246:                                                    .length() + 1)
0247:                                    .replaceFirst("\\.xml$", "").replace("/",
0248:                                            ".");
0249:
0250:                            Document doc = builder.build(file);
0251:
0252:                            types.put(className, doc);
0253:                        } catch (Exception ex) {
0254:                            throw new RuntimeException(ex);
0255:                        }
0256:                    }
0257:
0258:                    public boolean visitDirectory(File dir) {
0259:                        return true;
0260:                    }
0261:                });
0262:            }
0263:
0264:            /**
0265:             * Find the super class names listed in the given document.
0266:             * Perhaps this should be cached somewhere???
0267:             * @param doc The document to search in
0268:             * @return The list of found super classes
0269:             */
0270:            protected List<String> getSuperClasses(Document doc) {
0271:                List<String> super Classes = new ArrayList<String>();
0272:                Nodes super ClassNodes = doc.query("/class/superclass/@name");
0273:                for (int i = 0; i < super ClassNodes.size(); i++) {
0274:                    super Classes.add(super ClassNodes.get(i).getValue());
0275:                }
0276:                return super Classes;
0277:            }
0278:
0279:            /**
0280:             * Copying mixin functions because Java does not do MI
0281:             * @throws InterruptedException If the threading breaks
0282:             */
0283:            protected void copyMixinFunctions() throws InterruptedException {
0284:                ExecutorService exec = Executors.newFixedThreadPool(2);
0285:
0286:                for (final Map.Entry<String, Document> entry : types.entrySet()) {
0287:                    exec.execute(new Runnable() {
0288:                        public void run() {
0289:                            String className = entry.getKey();
0290:                            Document doc = entry.getValue();
0291:
0292:                            // Search the XML for lines like this from Button.xml:
0293:                            //   <implements direct="1" id="implements:0" loaded="1" name="jsx3.gui.Form"/>
0294:
0295:                            // Find all the inherited functions, and trim the ones that are not
0296:                            // from super-classes - leaving the mixins
0297:                            Nodes mixinRefNodes = doc
0298:                                    .query("/class/method[@inherited='1']");
0299:
0300:                            for (int i = 0; i < mixinRefNodes.size(); i++) {
0301:                                Element mixinRefNode = (Element) mixinRefNodes
0302:                                        .get(i);
0303:                                String name = mixinRefNode
0304:                                        .getAttributeValue("name");
0305:                                if (name == null) {
0306:                                    throw new NullPointerException(
0307:                                            "Missing name attribute from element: "
0308:                                                    + mixinRefNode);
0309:                                }
0310:
0311:                                // We might be implemented elsewhere
0312:                                String mixinSource = mixinRefNode
0313:                                        .getAttributeValue("source");
0314:                                if (mixinSource == null) {
0315:                                    mixinSource = className;
0316:                                }
0317:
0318:                                boolean isMixin = true;
0319:                                for (String super Class : getSuperClasses(doc)) {
0320:                                    if (mixinSource.equals(super Class)) {
0321:                                        isMixin = false;
0322:                                    }
0323:                                }
0324:
0325:                                if (isMixin) {
0326:                                    // replace the method element with the corresponding element from Form.
0327:                                    if (!"jsx3.lang.Object".equals(mixinSource)) {
0328:                                        Document mixinSourceDocument = types
0329:                                                .get(mixinSource);
0330:                                        Nodes templateNodes = mixinSourceDocument
0331:                                                .query("/interface/method[@name='"
0332:                                                        + name + "']");
0333:                                        if (templateNodes.size() != 1) {
0334:                                            log
0335:                                                    .warn("** Found "
0336:                                                            + templateNodes
0337:                                                                    .size()
0338:                                                            + " methods called "
0339:                                                            + name
0340:                                                            + " in "
0341:                                                            + mixinSource
0342:                                                            + " as a result of reference from "
0343:                                                            + className);
0344:                                        } else {
0345:                                            Element templateNode = (Element) templateNodes
0346:                                                    .get(0);
0347:                                            Node replacementNode = templateNode
0348:                                                    .copy();
0349:                                            mixinRefNode.getParent()
0350:                                                    .replaceChild(mixinRefNode,
0351:                                                            replacementNode);
0352:                                        }
0353:                                    }
0354:                                }
0355:                            }
0356:                        }
0357:                    });
0358:                }
0359:                exec.shutdown();
0360:                exec.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
0361:            }
0362:
0363:            /**
0364:             * Remove functions implemented by parent
0365:             */
0366:            protected void trimDuplicateMethods() {
0367:                SortedSet<String> keys = new TreeSet<String>(types.keySet());
0368:                for (final String className : keys) {
0369:                    Document doc = types.get(className);
0370:
0371:                    // Get a list of super classes
0372:                    final List<Document> parents = new ArrayList<Document>();
0373:                    for (String super ClassName : getSuperClasses(doc)) {
0374:                        Document parent = types.get(super ClassName);
0375:                        if (parent == null) {
0376:                            throw new IllegalStateException(
0377:                                    "Unknown superclass: " + super ClassName);
0378:                        }
0379:                        parents.add(parent);
0380:                    }
0381:
0382:                    // Find all the inherited functions, and trim the ones that are not
0383:                    // from super-classes - leaving the mixins
0384:                    XomHelper.query(doc, "/class/method[not(@inherited)]",
0385:                            new ElementBlock() {
0386:                                public void use(final Element inherited) {
0387:                                    final String inheritedName = inherited
0388:                                            .getAttributeValue("name");
0389:
0390:                                    // Loop over signatures, checking for methods in super-classes
0391:                                    for (Document parent : parents) {
0392:                                        try {
0393:                                            XomHelper
0394:                                                    .query(
0395:                                                            parent,
0396:                                                            "/class/method[not(@inherited)]",
0397:                                                            new ElementBlock() {
0398:                                                                public void use(
0399:                                                                        Element parentMethod) {
0400:                                                                    if (inherited
0401:                                                                            .getParent() == null) {
0402:                                                                        return;
0403:                                                                    }
0404:
0405:                                                                    String parentMethodName = parentMethod
0406:                                                                            .getAttributeValue("name");
0407:                                                                    if (inheritedName
0408:                                                                            .equals(parentMethodName)) {
0409:                                                                        inherited
0410:                                                                                .getParent()
0411:                                                                                .removeChild(
0412:                                                                                        inherited);
0413:                                                                    }
0414:                                                                }
0415:                                                            });
0416:                                        } catch (XPathException ex) {
0417:                                            log.warn("** Failed XPath for '"
0418:                                                    + className + "': "
0419:                                                    + ex.getXPath());
0420:                                        }
0421:                                    }
0422:                                }
0423:                            });
0424:                }
0425:            }
0426:
0427:            /* (non-Javadoc)
0428:             * @see org.directwebremoting.drapgen.loader.Loader#loadToProject(org.directwebremoting.drapgen.ast.Project)
0429:             */
0430:            public void loadToProject(final Project project) {
0431:                SortedSet<String> keys = new TreeSet<String>(types.keySet());
0432:                for (String className : keys) {
0433:                    String rename = hasLocalVersion(className);
0434:                    if (rename != null) {
0435:                        log
0436:                                .debug(className
0437:                                        + ": Skipping: has a local version - "
0438:                                        + rename);
0439:                        continue;
0440:                    }
0441:
0442:                    if (skipOnInput(className)) {
0443:                        log.debug(className
0444:                                + ": Skipping: marked skip on input");
0445:                        continue;
0446:                    }
0447:
0448:                    // Remove documentation classes like index.java, package-summary.java, etc
0449:                    if (className.endsWith("index")
0450:                            || className.endsWith("inheritance")
0451:                            || className.endsWith("package-summary")) {
0452:                        log.debug(className + ": Skipping: it's documentation");
0453:                        continue;
0454:                    }
0455:
0456:                    Element root = types.get(className).getRootElement();
0457:                    if (root.getAttributeValue("deprecated") != null) {
0458:                        deprecatedTypes.add(className);
0459:                        log.debug(className + ": Skipping: it's deprecated");
0460:                        continue;
0461:                    }
0462:
0463:                    final Type type = getType(project, className);
0464:                    String typeDocs = readDocumentation(root);
0465:                    type.setDocumentation(typeDocs);
0466:
0467:                    String super ClassName = XomHelper.queryValue(root,
0468:                            "superclass[@direct='1']/@name");
0469:                    if (super ClassName == null) {
0470:                        type
0471:                                .setSuperClass(getType(project,
0472:                                        "jsx3.lang.Object"));
0473:                    } else {
0474:                        type.setSuperClass(getType(project, super ClassName));
0475:                    }
0476:
0477:                    XomHelper.getChildElements(root, "implements",
0478:                            new ImplementsElementBlock(project, type));
0479:                    XomHelper.getChildElements(root, "constructor",
0480:                            new ConstructorElementBlock(project, type));
0481:                    XomHelper.getChildElements(root, "method",
0482:                            new MethodElementBlock(project, type));
0483:                    XomHelper.getChildElements(root, "field",
0484:                            new FieldElementBlock(project, type));
0485:                }
0486:
0487:                // We need to remove the classes that we don't want to generate
0488:                Set<Type> toDelete = new HashSet<Type>();
0489:                types: for (Type type : project.getTypes()) {
0490:                    if (!type.getPackageName().startsWith("jsx3")) {
0491:                        toDelete.add(type);
0492:                        continue types;
0493:                    }
0494:                    for (String manualClassName : SKIP_ON_OUTPUT) {
0495:                        if (type.getFullName().equals(manualClassName)) {
0496:                            toDelete.add(type);
0497:                            continue types;
0498:                        }
0499:                    }
0500:                }
0501:                for (Type type : toDelete) {
0502:                    project.remove(type);
0503:                }
0504:            }
0505:
0506:            /**
0507:             * Find all the constants
0508:             */
0509:            protected class FieldElementBlock extends ProjectElementBlock {
0510:                protected FieldElementBlock(Project project, Type type) {
0511:                    super (project, type);
0512:                }
0513:
0514:                public void use(Element fieldElement) {
0515:                    if (fieldElement.getAttribute("deprecated") != null) {
0516:                        return;
0517:                    }
0518:
0519:                    String statc = fieldElement.getAttributeValue("static");
0520:                    if (statc == null || !statc.equals("1")) {
0521:                        return;
0522:                    }
0523:
0524:                    String access = fieldElement.getAttributeValue("access");
0525:                    if (access == null || !access.equals("public")) {
0526:                        return;
0527:                    }
0528:
0529:                    String name = fieldElement.getAttributeValue("name");
0530:
0531:                    Field field = type.createConstant();
0532:                    field.setDocumentation(stripToNull(fieldElement
0533:                            .getAttributeValue("text")));
0534:                    field.setDocumentation(readDocumentation(fieldElement));
0535:                    field.setName(name);
0536:                    field.setValue(fieldElement.getAttributeValue("value"));
0537:
0538:                    Elements typeElements = fieldElement
0539:                            .getChildElements("type");
0540:                    if (typeElements.size() == 0) {
0541:                        log
0542:                                .warn(type.getFullName()
0543:                                        + "."
0544:                                        + name
0545:                                        + "(): Missing type element for constant. Using Object.");
0546:                        field.setType(getType(project, "java.lang.Object"));
0547:                    } else {
0548:                        if (typeElements.size() > 1) {
0549:                            log
0550:                                    .warn(type.getFullName()
0551:                                            + "."
0552:                                            + name
0553:                                            + "(): Multiple type element for a constant!. Using first.");
0554:                        }
0555:
0556:                        Element typeElement = typeElements.get(0);
0557:                        String typeName = typeElement.getAttributeValue("name");
0558:                        field.setType(getType(project, typeName));
0559:                    }
0560:                }
0561:            }
0562:
0563:            /**
0564:             * Find all the methods that we're interested in
0565:             */
0566:            protected class MethodElementBlock extends ProjectElementBlock {
0567:                protected MethodElementBlock(Project project, Type type) {
0568:                    super (project, type);
0569:                }
0570:
0571:                public void use(Element methodElement) {
0572:                    if (methodElement.getAttribute("deprecated") != null) {
0573:                        return;
0574:                    }
0575:
0576:                    if (methodElement.getAttribute("inherited") != null) {
0577:                        return;
0578:                    }
0579:
0580:                    String methodName = methodElement.getAttributeValue("name");
0581:                    String debugName = type.getFullName() + "." + methodName;
0582:
0583:                    String documentation = readDocumentation(methodElement);
0584:                    Parameter returnType = readGiReturnType(methodElement,
0585:                            project, debugName);
0586:
0587:                    // Read a set of param elements attached to a constructor or method
0588:
0589:                    Set<List<Parameter>> parameters = getGiParamList(
0590:                            methodElement, debugName, project);
0591:                    for (List<Parameter> parameter : parameters) {
0592:                        Method method = type.createMethod();
0593:                        method.setDocumentation(documentation);
0594:                        method.setName(methodName);
0595:                        method.setReturnType(returnType);
0596:                        method.setParameters(parameter);
0597:                    }
0598:                }
0599:            }
0600:
0601:            /**
0602:             * Find all the constructors that we're interested in
0603:             */
0604:            protected class ConstructorElementBlock extends ProjectElementBlock {
0605:                protected ConstructorElementBlock(Project project, Type type) {
0606:                    super (project, type);
0607:                }
0608:
0609:                public void use(Element ctorElement) {
0610:                    if (ctorElement.getAttribute("deprecated") != null) {
0611:                        return;
0612:                    }
0613:
0614:                    // Read a set of param elements attached to a constructor or method
0615:
0616:                    String documentation = readDocumentation(ctorElement);
0617:                    Set<List<Parameter>> parameters = getGiParamList(
0618:                            ctorElement, type.getFullName() + ".ctor", project);
0619:                    for (List<Parameter> parameter : parameters) {
0620:                        Constructor constructor = type.createConstructor();
0621:                        constructor.setDocumentation(documentation);
0622:                        constructor.setParameters(parameter);
0623:                    }
0624:                }
0625:            }
0626:
0627:            /**
0628:             * Helper so we can implement ElementBlock easily
0629:             */
0630:            protected abstract class ProjectElementBlock implements 
0631:                    ElementBlock {
0632:                /**
0633:                 * @param project The project that we are writing to
0634:                 * @param type The type we are creating
0635:                 */
0636:                protected ProjectElementBlock(Project project, Type type) {
0637:                    this .project = project;
0638:                    this .type = type;
0639:                }
0640:
0641:                /**
0642:                 * The project that we are writing to
0643:                 */
0644:                protected final Project project;
0645:
0646:                /**
0647:                 * The type we are creating
0648:                 */
0649:                protected final Type type;
0650:            }
0651:
0652:            /**
0653:             * Process an implements element
0654:             */
0655:            protected class ImplementsElementBlock extends ProjectElementBlock {
0656:                protected ImplementsElementBlock(Project project, Type type) {
0657:                    super (project, type);
0658:                }
0659:
0660:                public void use(Element implements Element) {
0661:                    String direct = implements Element
0662:                            .getAttributeValue("direct");
0663:                    if (direct == null || !direct.equals("1")) {
0664:                        return;
0665:                    }
0666:
0667:                    String interfaceName = implements Element
0668:                            .getAttributeValue("name");
0669:                    if (interfaceName == null) {
0670:                        log
0671:                                .warn(type.getFullName()
0672:                                        + ": Skipping direct implements element with no name");
0673:                    }
0674:                    type.addInterface(getType(project, interfaceName));
0675:                }
0676:            }
0677:
0678:            /**
0679:             * We want to alter the names of some classes as we generate them
0680:             * @param project The project that we use to lookup Types
0681:             * @param className The name of the requested class
0682:             * @return A Type representing the name altered type
0683:             */
0684:            protected Type getType(Project project, String className) {
0685:                if (isDeprecated(className)) {
0686:                    log.warn("** Request for deprecated type: " + className);
0687:                    return project.getType("jsx3.lang.Unavailable");
0688:                }
0689:
0690:                String name = checkAlternativeNames(className);
0691:
0692:                return project.getType(name);
0693:            }
0694:
0695:            /**
0696:             * @param className The name to check for deprecation
0697:             * @return true if the type has been deprecated
0698:             */
0699:            protected boolean isDeprecated(String className) {
0700:                for (String deprecatedType : deprecatedTypes) {
0701:                    if (className.equals(deprecatedType)) {
0702:                        return true;
0703:                    }
0704:                }
0705:
0706:                return false;
0707:            }
0708:
0709:            /**
0710:             * We might need to use differing versions of class names
0711:             */
0712:            protected String checkAlternativeNames(String className) {
0713:                for (String[] pairs : JSX3_RENAMES) {
0714:                    if (className.equals(pairs[0])) {
0715:                        return pairs[1];
0716:                    }
0717:                }
0718:                for (String[] pairs : HAS_LOCAL_VERSION) {
0719:                    if (className.equals(pairs[0])) {
0720:                        return pairs[1];
0721:                    }
0722:                }
0723:                return className;
0724:            }
0725:
0726:            /**
0727:             * Does the given string have a local version?
0728:             */
0729:            protected String hasLocalVersion(String className) {
0730:                for (String[] pairs : HAS_LOCAL_VERSION) {
0731:                    if (className.equals(pairs[0])) {
0732:                        return pairs[1];
0733:                    }
0734:                }
0735:                return null;
0736:            }
0737:
0738:            /**
0739:             * Does the given string have a local version?
0740:             */
0741:            protected boolean skipOnInput(String className) {
0742:                for (String skip : SKIP_ON_INPUT) {
0743:                    if (className.equals(skip)) {
0744:                        return true;
0745:                    }
0746:                }
0747:                return false;
0748:            }
0749:
0750:            /**
0751:             * We might want to move jsx3 classes around the hierarchy, mostly this
0752:             * is due to lack of current support for inner classes
0753:             */
0754:            private static final String[][] JSX3_RENAMES = new String[][] {
0755:                    { "jsx3.gui.Matrix.BlockMask", "jsx3.gui.matrix.BlockMask" },
0756:                    { "jsx3.gui.Matrix.Column", "jsx3.gui.matrix.Column" },
0757:                    { "jsx3.gui.Matrix.ColumnFormat",
0758:                            "jsx3.gui.matrix.ColumnFormat" },
0759:                    { "jsx3.gui.Matrix.EditMask", "jsx3.gui.matrix.EditMask" }, };
0760:
0761:            /**
0762:             * JSX classes that we don't have a local version of, but we ignore anyway
0763:             */
0764:            private static final String[] SKIP_ON_INPUT = new String[] {
0765:                    "jsx3.app.Monitor", "jsx3.app.PropsBundle",
0766:                    "jsx3.lang.NativeError", "jsx3.lang.Package",
0767:                    "jsx3.net.URIResolver", "jsx3.util.Logger",
0768:                    "jsx3.util.Logger.AlertHandler",
0769:                    "jsx3.util.Logger.FormatHandler",
0770:                    "jsx3.util.Logger.Handler", "jsx3.util.Logger.Manager",
0771:                    "jsx3.util.Logger.MemoryHandler",
0772:                    "jsx3.util.Logger.Record", "jsx3.xml.XslDocument", };
0773:
0774:            /**
0775:             * Many JSX classes are not converted because there is a better local
0776:             * version.
0777:             */
0778:            private static final String[][] HAS_LOCAL_VERSION = new String[][] {
0779:                    { "", "jsx3.lang.Object" },
0780:                    { "Object", "jsx3.lang.Object" },
0781:                    { "Date", "java.util.Date" },
0782:                    { "Iterator", "java.util.Iterator" },
0783:                    { "Math", "java.lang.Math" },
0784:                    { "RegExp", "java.util.regex.Pattern" },
0785:                    { "Number", "Integer" },
0786:                    { "String", "String" },
0787:                    { "Array", "Object[]" },
0788:                    { "Boolean", "Boolean" },
0789:                    { "Function", "org.directwebremoting.proxy.CodeBlock" },
0790:                    { "HTMLElement", "String" },
0791:                    { "HTMLDocument", "String" },
0792:                    { "VectorStroke", "String" },
0793:                    { "jsx3.Boolean", "Boolean" },
0794:                    { "jsx3.app.Locale", "java.util.Locale" },
0795:                    { "jsx3.app.Properties", "java.util.Properties" },
0796:                    { "jsx3.lang.Class", "Class" },
0797:                    { "jsx3.lang.ClassLoader", "ClassLoader" },
0798:                    { "jsx3.lang.Exception", "Exception" },
0799:                    { "jsx3.lang.IllegalArgumentException",
0800:                            "IllegalArgumentException" },
0801:                    { "jsx3.lang.Method", "java.lang.reflect.Method" },
0802:                    { "jsx3.net.URI", "java.net.URI" },
0803:                    { "jsx3.util.DateFormat", "java.util.DateFormat" },
0804:                    { "jsx3.util.Locale", "java.util.Locale" },
0805:                    { "jsx3.util.List", "java.util.List" },
0806:                    { "jsx3.util.Iterator", "java.util.Iterator" },
0807:                    { "jsx3.util.MessageFormat", "java.util.MessageFormat" },
0808:                    { "jsx3.util.NumberFormat", "java.util.NumberFormat" },
0809:                    { "jsx3.xml.CDF", "jsx3.xml.CdfDocument" },
0810:                    { "jsx3.xml.CDF.Document", "jsx3.xml.CdfDocument" },
0811:                    { "jsx3.xml.Document", "jsx3.xml.CdfDocument" },
0812:                    { "jsx3.xml.Entity", "jsx3.xml.Node" }, };
0813:
0814:            /**
0815:             * Some JSX3 classes have been hand cranked, or should not be generated
0816:             */
0817:            private static final String[] SKIP_ON_OUTPUT = new String[] {
0818:                    "jsx3.lang.Object", "jsx3.lang.Unavailable",
0819:                    "jsx3.net.URIResolver", "jsx3.xml.CdfDocument",
0820:                    "jsx3.xml.Node", };
0821:
0822:            /**
0823:             * Read the text child element and set the drapgen AST element with it's
0824:             * content
0825:             * @param xomElement the XML element to read from
0826:             */
0827:            protected String readDocumentation(Element xomElement) {
0828:                Element textElement = xomElement.getFirstChildElement("text");
0829:                if (textElement != null) {
0830:                    return stripToNull(textElement.getValue());
0831:                } else {
0832:                    return null;
0833:                }
0834:            }
0835:
0836:            /**
0837:             * Read a set of param elements attached to a constructor or method
0838:             * @param element The XOM element to read from
0839:             * @param debugName
0840:             * @param project
0841:             * @return A list of found parameters
0842:             */
0843:            protected Set<List<Parameter>> getGiParamList(Element element,
0844:                    final String debugName, final Project project) {
0845:                // The types used by this method are somewhat funky. We first create a
0846:                // list of parameters with the alternative types for each in a stack.
0847:                // We then need to return a set where all the different combinations of
0848:                // these alternatives are represented. We use Set<List<>> and
0849:                // List<Stack<>> to help make it clearer what we are working on.
0850:
0851:                // So GI has a list of parameters for this subroutine. Each parameter
0852:                // has a set of types that it can be
0853:                final List<Stack<Parameter>> parametersWithOptions = new ArrayList<Stack<Parameter>>();
0854:                XomHelper.getChildElements(element, "param",
0855:                        new ElementBlock() {
0856:                            public void use(Element paramElement) {
0857:                                String documentation = stripToNull(paramElement
0858:                                        .getAttributeValue("text"));
0859:                                String name = paramElement
0860:                                        .getAttributeValue("name");
0861:
0862:                                Set<Type> alternatives = new HashSet<Type>();
0863:
0864:                                Elements typeElements = paramElement
0865:                                        .getChildElements("type");
0866:                                if (typeElements.size() == 0) {
0867:                                    String typeName = "java.lang.Object";
0868:                                    if (name.startsWith("str")) {
0869:                                        typeName = "String";
0870:                                    } else if (name.startsWith("b")) {
0871:                                        typeName = "boolean";
0872:                                    } else if (name.startsWith("int")) {
0873:                                        typeName = "int";
0874:                                    }
0875:                                    log
0876:                                            .warn(debugName
0877:                                                    + "(): Missing type element for parameter '"
0878:                                                    + name + "'. Guessing at '"
0879:                                                    + typeName
0880:                                                    + "' from parameter name.");
0881:                                    alternatives
0882:                                            .add(getType(project, typeName));
0883:                                } else {
0884:                                    for (int i = 0; i < typeElements.size(); i++) {
0885:                                        Element typeElement = typeElements
0886:                                                .get(i);
0887:                                        String typeName = typeElement
0888:                                                .getAttributeValue("name");
0889:                                        if (typeName.equals("function")) {
0890:                                            typeName = "Function";
0891:                                            log
0892:                                                    .warn(debugName
0893:                                                            + "(): Types of parameter '"
0894:                                                            + name
0895:                                                            + "' includes 'function', it probably should be 'Function'");
0896:                                        }
0897:                                        alternatives.add(getType(project,
0898:                                                typeName));
0899:                                    }
0900:                                }
0901:
0902:                                Stack<Parameter> p = new Stack<Parameter>();
0903:                                for (Type alternative : alternatives) {
0904:                                    Parameter parameter = new Parameter(project);
0905:                                    parameter.setDocumentation(documentation);
0906:                                    parameter.setName(name);
0907:                                    parameter.setType(alternative);
0908:                                    p.add(parameter);
0909:                                }
0910:
0911:                                parametersWithOptions.add(p);
0912:                            }
0913:                        });
0914:
0915:                Set<List<Parameter>> parameterCombinations = new HashSet<List<Parameter>>();
0916:
0917:                if (parametersWithOptions.size() > 0) {
0918:                    recurseOverTypesInParameter(parametersWithOptions, 0,
0919:                            new LinkedList<Integer>(), parameterCombinations);
0920:                } else {
0921:                    // There is one combination - that with no parameters
0922:                    parameterCombinations.add(new ArrayList<Parameter>());
0923:                }
0924:
0925:                return parameterCombinations;
0926:            }
0927:
0928:            /**
0929:             * @param parametersWithOptions
0930:             * @param paramNumber
0931:             * @param combinations
0932:             */
0933:            private void recurseOverTypesInParameter(
0934:                    List<Stack<Parameter>> parametersWithOptions,
0935:                    int paramNumber, LinkedList<Integer> typeList,
0936:                    Set<List<Parameter>> combinations) {
0937:                // We do *something* for each of the alternatives in the set of
0938:                // parameters for this type
0939:                Stack<Parameter> alternatives = parametersWithOptions
0940:                        .get(paramNumber);
0941:                for (int i = 0; i < alternatives.size(); i++) {
0942:                    LinkedList<Integer> nextTypeList = new LinkedList<Integer>(
0943:                            typeList);
0944:                    nextTypeList.add(i);
0945:
0946:                    if (paramNumber == parametersWithOptions.size() - 1) {
0947:                        // If this is the last parameter then *something* is creating
0948:                        // an entry in the output set
0949:                        List<Parameter> combination = new ArrayList<Parameter>();
0950:                        for (int paramIndex = 0; paramIndex < nextTypeList
0951:                                .size(); paramIndex++) {
0952:                            Integer selection = nextTypeList.get(paramIndex);
0953:                            Parameter selected = parametersWithOptions.get(
0954:                                    paramIndex).get(selection);
0955:                            combination.add(selected);
0956:                        }
0957:                        combinations.add(combination);
0958:                    } else {
0959:                        // If this is not the last parameter then *something* is to call
0960:                        // ourself to loop over the options for the next parameter
0961:                        recurseOverTypesInParameter(parametersWithOptions,
0962:                                paramNumber + 1, nextTypeList, combinations);
0963:                    }
0964:                }
0965:            }
0966:
0967:            /**
0968:             * Read a return type element attached to a method.
0969:             * For some reason calling method.toString as part of the log.warn messages
0970:             * crashes the VM on mac-os. Why???
0971:             * @param element The XOM element to read from
0972:             */
0973:            protected Parameter readGiReturnType(Element element,
0974:                    Project project, final String name) {
0975:                Parameter returnType = new Parameter(project);
0976:
0977:                //Project project = method.getParent().getProject();
0978:                Elements returnElements = element.getChildElements("return");
0979:                if (returnElements.size() == 0) {
0980:                    returnType.setType(getType(project, "void"));
0981:                    return returnType;
0982:                } else {
0983:                    if (returnElements.size() > 1) {
0984:                        log
0985:                                .warn(name
0986:                                        + "(): More than one return element. Using first.");
0987:                    }
0988:
0989:                    Element returnElement = returnElements.get(0);
0990:
0991:                    String documentation = returnElement
0992:                            .getAttributeValue("text");
0993:                    returnType.setDocumentation(stripToNull(documentation));
0994:
0995:                    Elements typeElements = returnElement
0996:                            .getChildElements("type");
0997:                    if (typeElements.size() == 0) {
0998:                        log.warn(name
0999:                                + "(): Missing return element. Using Object.");
1000:                        Type type = getType(project, "java.lang.Object");
1001:                        returnType.setType(type);
1002:                        return returnType;
1003:                    } else {
1004:                        if (typeElements.size() > 1) {
1005:                            log
1006:                                    .warn(name
1007:                                            + "(): More than one type element in return. Using first. Are the semantics of this clear?");
1008:                        }
1009:
1010:                        Element typeElement = typeElements.get(0);
1011:                        String typeName = typeElement.getAttributeValue("name");
1012:                        Type type = getType(project, typeName);
1013:                        returnType.setType(type);
1014:                        return returnType;
1015:                    }
1016:                }
1017:            }
1018:
1019:            /**
1020:             * Utility for simplifying documentation
1021:             * @param input The string to call {@link String#trim()} on before swapping
1022:             * empty replies for null
1023:             * @return A non blank, trimmed string, possibly null
1024:             */
1025:            public static String stripToNull(String input) {
1026:                if (input == null) {
1027:                    return null;
1028:                }
1029:                String output = input.trim();
1030:                if (output.length() == 0) {
1031:                    return null;
1032:                }
1033:                return output;
1034:            }
1035:
1036:            /**
1037:             * What classes have been deprecated?
1038:             */
1039:            protected Set<String> deprecatedTypes = new HashSet<String>();
1040:
1041:            /**
1042:             * Our cache of loaded GI documents
1043:             */
1044:            protected Map<String, Document> types;
1045:
1046:            /**
1047:             * The XOM document builder
1048:             */
1049:            protected Builder builder = new Builder();
1050:
1051:            /**
1052:             * The log stream
1053:             */
1054:            protected static final Logger log = Logger
1055:                    .getLogger(GiLoader.class);
1056:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.