001: /*
002: * Copyright 2005 Joe Walker
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.directwebremoting.drapgen.generate.gi;
017:
018: import java.io.File;
019: import java.util.Iterator;
020: import java.util.List;
021: import java.util.concurrent.ExecutorService;
022: import java.util.concurrent.Executors;
023: import java.util.concurrent.TimeUnit;
024:
025: import org.directwebremoting.drapgen.generate.xslt.ExtensionFunctions;
026: import org.directwebremoting.drapgen.loader.gi.GiLoader;
027: import org.directwebremoting.fsguide.FileSystemGuide;
028: import org.directwebremoting.fsguide.Visitor;
029: import org.directwebremoting.util.Logger;
030:
031: /**
032: * @author Joe Walker [joe at getahead dot ltd dot uk]
033: */
034: public class Generate {
035: private static final String XML_BASE = "/Applications/TIBCO/tibco-gi-3.5-pro-src/dist/gi/api/xml/";
036: private static final String GENERATED_BASE = "generated/gi/java/org/directwebremoting/proxy/";
037: private static final String DOM_BASE = "generated/gi/dom/";
038: private static final String TEMPLATES_BASE = "etc/drapgen/templates/";
039: private static final String DEFAULT_TEMPLATE = "default.xslt";
040: private static final String PREPROCESSOR = "etc/drapgen/preprocess/default.xslt";
041:
042: public static void main(String[] args) throws Exception {
043: new Generate().generate();
044: }
045:
046: public void generate() throws Exception {
047: final GiProject registry = new GiProject();
048:
049: // Create a list of all the classes we need to generate
050: log.info("Searching for XML files.");
051: FileSystemGuide guide = new FileSystemGuide(new File(XML_BASE));
052: guide.visit(new Visitor() {
053: public void visitFile(File file) {
054: if (file.getAbsolutePath().endsWith(".xml")) {
055: GiType code = new GiType(Generate.XML_BASE, file);
056: registry.add(code);
057: } else {
058: log.info("Skipping: " + file.getAbsolutePath());
059: }
060: }
061:
062: public boolean visitDirectory(File directory) {
063: return true;
064: }
065: });
066: ExtensionFunctions.setJsClassloader(registry);
067:
068: // Clone the functions with multiple input parameter types for overloading
069: log.info("Cloning for overloading.");
070: for (GiType code : registry.getClasses()) {
071: code.cloneForOverloading(PREPROCESSOR);
072: }
073:
074: // Work out which classes are super-classes and mixins
075: log.info("Calculating super classes.");
076: for (GiType code : registry.getClasses()) {
077: List<String> parents = code.getSuperClasses();
078: for (String parent : parents) {
079: registry.getClassByName(parent).setSuperClass(true);
080: }
081: }
082:
083: // Copying mixin functions because Java does not do MI
084: log.info("Copying mixin functions.");
085: ExecutorService exec = Executors.newFixedThreadPool(2);
086: for (final GiType code : registry.getClasses()) {
087: exec.execute(new Runnable() {
088: public void run() {
089: // Search the XML for lines like this from Button.xml:
090: // <implements direct="1" id="implements:0" loaded="1" name="jsx3.gui.Form"/>
091: List<GiMethod> functions = code.getMixinFunctions();
092: for (GiMethod function : functions) {
093: // replace the method element with the corresponding element from Form.
094: if (!"jsx3.lang.Object".equals(function
095: .getDeclarationClassName())) {
096: GiType implementingClass = registry
097: .getClassByName(function
098: .getDeclarationClassName());
099: GiMethod node = implementingClass
100: .getImplementationDeclaration(function
101: .getName());
102: if (node == null) {
103: log
104: .warn("- No implementation of: "
105: + function
106: .getDeclarationClassName()
107: + "."
108: + function.getName()
109: + "() refered to by "
110: + code.getClassName());
111: } else {
112: // log.info("- Promoting: " + mixinFunction.left + "." + mixinFunction.right + "() into " + code.getClassName());
113: code.replaceImplementation(node,
114: function);
115: }
116: }
117: }
118: }
119: });
120: }
121: exec.shutdown();
122: exec.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
123:
124: // Remove functions implemented by parent
125: log
126: .info("Trimming methods with identical implementation in parent.");
127: exec = Executors.newFixedThreadPool(2);
128: for (final GiType code : registry.getClasses()) {
129: exec.execute(new Runnable() {
130: public void run() {
131: code.trimDuplicateMethods(registry);
132: }
133: });
134: }
135: exec.shutdown();
136: exec.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
137:
138: // Remove documentation classes
139: log.info("Pruning documentation classes.");
140: for (Iterator<GiType> it = registry.getClasses().iterator(); it
141: .hasNext();) {
142: GiType code = it.next();
143: if (code.getClassName().equals("index")
144: || code.getClassName().equals("inheritance")
145: || code.getClassName().equals("package-summary")) {
146: it.remove();
147: }
148: }
149:
150: // Write the DOM out to disk
151: log.info("Serializing " + registry.getClasses().size()
152: + " classes.");
153: registry.save(DOM_BASE);
154: System.exit(0);
155:
156: // Transform them all
157: log.info("Transforming " + registry.getClasses().size()
158: + " classes.");
159: for (GiType code : registry.getClasses()) {
160: code.transform(TEMPLATES_BASE, DEFAULT_TEMPLATE);
161: }
162:
163: // Merge Inner Classes
164: log.info("Merging Inner Classes");
165: for (Iterator<GiType> it = registry.getClasses().iterator(); it
166: .hasNext();) {
167: GiType code = it.next();
168: String parentName = "";
169:
170: int lastDot = code.getClassName().lastIndexOf('.');
171: if (lastDot > 0) {
172: parentName = code.getClassName().substring(0, lastDot);
173: }
174:
175: GiType parent = registry.getClassByName(parentName);
176: if (parent != null) {
177: it.remove();
178: parent.absorbClass(code);
179: }
180: }
181:
182: // Write them to disk
183: log.info("Writing " + registry.getClasses().size()
184: + " classes.");
185: for (GiType code : registry.getClasses()) {
186: code.writeCode(GENERATED_BASE);
187: }
188: }
189:
190: /**
191: * The log stream
192: */
193: protected static final Logger log = Logger
194: .getLogger(GiLoader.class);
195: }
|