KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > attributes > compiler > AttributeCompiler


1 /*
2  * Copyright 2003-2004 The Apache Software Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.commons.attributes.compiler;
17
18 import java.io.BufferedReader JavaDoc;
19 import java.io.File JavaDoc;
20 import java.io.FileReader JavaDoc;
21 import java.io.FileWriter JavaDoc;
22 import java.io.PrintWriter JavaDoc;
23 import java.util.ArrayList JavaDoc;
24 import java.util.Collection JavaDoc;
25 import java.util.HashSet JavaDoc;
26 import java.util.Iterator JavaDoc;
27 import java.util.StringTokenizer JavaDoc;
28
29 import org.apache.tools.ant.BuildException;
30 import org.apache.tools.ant.Project;
31 import org.apache.tools.ant.Task;
32 import org.apache.tools.ant.types.FileSet;
33 import org.apache.tools.ant.types.Path;
34
35 import xjavadoc.SourceClass;
36 import xjavadoc.XClass;
37 import xjavadoc.XConstructor;
38 import xjavadoc.XJavaDoc;
39 import xjavadoc.XField;
40 import xjavadoc.XMethod;
41 import xjavadoc.XParameter;
42 import xjavadoc.XProgramElement;
43 import xjavadoc.XTag;
44 import xjavadoc.ant.XJavadocTask;
45 import xjavadoc.filesystem.AbstractFile;
46
47 /**
48  * Ant task to compile attributes. Usage:
49  *
50  * <pre><code>
51  * &lt;taskdef resource="org/apache/commons/attributes/anttasks.properties"/&gt;
52  *
53  * &lt;attribute-compiler destDir="temp/"&gt; attributepackages="my.attributes;my.otherattributes"
54  * &lt;fileset dir="src/" includes="*.java"/&gt;
55  * &lt;/attribute-compiler&gt;
56  * </code></pre>
57  *
58  * <ul>
59  * <li>destDir<dd>Destination directory for generated source files
60  * <li>attributepackages<dd>A set of package names that will be automatically searched for attributes.
61  * </ul>
62  *
63  * The task should be run before compiling the Java sources, and will produce some
64  * additional Java source files in the destination directory that should be compiled
65  * along with the input source files. (See the overview for a diagram.)
66  */

67 public class AttributeCompiler extends XJavadocTask {
68     
69     private final ArrayList JavaDoc fileSets = new ArrayList JavaDoc ();
70     private Path src;
71     private File JavaDoc destDir;
72     private int numGenerated;
73     private int numIgnored;
74     private String JavaDoc attributePackages = "";
75     
76     public AttributeCompiler () {
77     }
78     
79     public void setAttributePackages (String JavaDoc attributePackages) {
80         this.attributePackages = attributePackages;
81     }
82     
83     public void addFileset (FileSet set) {
84         super.addFileset (set);
85         fileSets.add (set);
86     }
87     
88     public void setDestdir (File JavaDoc destDir) {
89         this.destDir = destDir;
90     }
91     
92     public void setSourcepathref (String JavaDoc pathref) {
93         String JavaDoc sourcePaths = project.getReference (pathref).toString ();
94         StringTokenizer JavaDoc tok = new StringTokenizer JavaDoc (sourcePaths, File.pathSeparator);
95         while (tok.hasMoreTokens ()) {
96             FileSet fs = new FileSet ();
97             fs.setDir (new File JavaDoc (tok.nextToken ()));
98             fs.setIncludes ("**/*.java");
99             fs.setProject (project);
100             addFileset (fs);
101         }
102     }
103     
104     protected void copyImports (File JavaDoc source, PrintWriter JavaDoc dest) throws Exception JavaDoc {
105         BufferedReader JavaDoc br = new BufferedReader JavaDoc (new FileReader JavaDoc (source));
106         try {
107             String JavaDoc line = null;
108             while ((line = br.readLine ()) != null) {
109                 if (line.startsWith ("import ")) {
110                     dest.println (line);
111                 }
112             }
113         } finally {
114             br.close ();
115         }
116     }
117     
118     protected void addExpressions (Collection JavaDoc tags, PrintWriter JavaDoc pw, String JavaDoc collectionName, File JavaDoc sourceFile) {
119         addExpressions (tags, null, pw, collectionName, sourceFile);
120     }
121     
122     protected void addExpressions (Collection JavaDoc tags, String JavaDoc selector, PrintWriter JavaDoc pw, String JavaDoc collectionName, File JavaDoc sourceFile) {
123         String JavaDoc fileName = sourceFile != null ? sourceFile.getPath ().replace ('\\', '/') : "<unknown>";
124         Iterator JavaDoc iter = tags.iterator ();
125         while (iter.hasNext ()) {
126             XTag tag = (XTag) iter.next ();
127             
128             if (isAttribute (tag)) {
129                 String JavaDoc expression = tag.getName () + " " + tag.getValue ();
130                 expression = expression.trim ();
131                 
132                 // Remove the second @-sign.
133
expression = expression.substring (1);
134                 
135                 if (selector != null) {
136                     if (expression.startsWith (".")) {
137                         // We have selector, tag does...
138
String JavaDoc tagSelector = expression.substring (1, expression.indexOf (" "));
139                         expression = expression.substring (expression.indexOf (" ")).trim ();
140                         if (!selector.equals (tagSelector)) {
141                             // ...but they didn't match.
142
continue;
143                         }
144                     } else {
145                         // We have selector, but tag doesn't
146
continue;
147                     }
148                 } else {
149                     // No selector, but tag has selector.
150
if (expression.startsWith (".")) {
151                         continue;
152                     }
153                 }
154                 
155                 pw.println (" {");
156                 outputAttributeExpression (pw, expression, fileName, tag.getLineNumber (), "_attr");
157                 pw.println (" Object _oattr = _attr; // Need to erase type information");
158                 pw.println (" if (_oattr instanceof org.apache.commons.attributes.Sealable) {");
159                 pw.println (" ((org.apache.commons.attributes.Sealable) _oattr).seal ();");
160                 pw.println (" }");
161                 pw.println (" " + collectionName + ".add ( _attr );");
162                 pw.println (" }");
163             }
164         }
165     }
166     
167     protected void outputAttributeExpression (PrintWriter JavaDoc pw, String JavaDoc expression, String JavaDoc filename, int line, String JavaDoc tempVariableName) {
168         AttributeExpressionParser.ParseResult result = AttributeExpressionParser.parse (expression, filename, line);
169         pw.print (" " + result.className + " " + tempVariableName + " = new " + result.className + "(");
170         
171         boolean first = true;
172         Iterator JavaDoc iter = result.arguments.iterator ();
173         while (iter.hasNext ()) {
174             AttributeExpressionParser.Argument arg = (AttributeExpressionParser.Argument) iter.next ();
175             if (arg.field == null) {
176                 if (!first) {
177                     pw.print (", ");
178                 }
179                 first = false;
180                 pw.print (arg.text);
181             }
182         }
183         pw.println (" // " + filename + ":" + line);
184         pw.println (");");
185         
186         iter = result.arguments.iterator ();
187         while (iter.hasNext ()) {
188             AttributeExpressionParser.Argument arg = (AttributeExpressionParser.Argument) iter.next ();
189             if (arg.field != null) {
190                 String JavaDoc methodName = "set" + arg.field.substring (0, 1).toUpperCase () + arg.field.substring (1);
191                 pw.println (" " + tempVariableName + "." + methodName + "(\n" +
192                     arg.text + " // " + filename + ":" + line + "\n" +
193                     ");");
194             }
195         }
196     }
197     
198     protected boolean elementHasAttributes (Collection JavaDoc xElements) {
199         Iterator JavaDoc iter = xElements.iterator ();
200         while (iter.hasNext ()) {
201             XProgramElement element = (XProgramElement) iter.next ();
202             if (tagHasAttributes (element.getDoc ().getTags ())) {
203                 return true;
204             }
205         }
206         return false;
207     }
208     
209     /**
210      * Encodes a class name to the internal Java name.
211      * For example, an inner class Outer.Inner will be
212      * encoed as Outer$Inner.
213      */

214     private void getTransformedQualifiedName (XClass type, StringBuffer JavaDoc sb) {
215         
216         if (type.isInner ()) {
217             String JavaDoc packageName = type.getContainingPackage ().getName ();
218             sb.append (packageName);
219             if (packageName.length () > 0) {
220                 sb.append (".");
221             }
222             sb.append (type.getName ().replace ('.','$'));
223         } else {
224             sb.append (type.getQualifiedName ());
225         }
226     }
227     
228     protected String JavaDoc getParameterTypes (Collection JavaDoc parameters) {
229         StringBuffer JavaDoc sb = new StringBuffer JavaDoc ();
230         for (Iterator JavaDoc params = parameters.iterator (); params.hasNext ();) {
231             XParameter parameter = (XParameter) params.next ();
232             getTransformedQualifiedName (parameter.getType (), sb);
233             sb.append (parameter.getDimensionAsString ());
234             
235             if (params.hasNext ()) {
236                 sb.append (",");
237             }
238         }
239         return sb.toString ();
240     }
241     
242     protected void generateClass (XClass xClass) throws Exception JavaDoc {
243         String JavaDoc name = null;
244         File JavaDoc sourceFile = null;
245         File JavaDoc destFile = null;
246         String JavaDoc packageName = null;
247         String JavaDoc className = null;
248         
249         packageName = xClass.getContainingPackage().getName ();
250         
251         if (xClass.isInner ()) {
252             name = xClass.getQualifiedName ().substring (packageName.length ());
253             
254             sourceFile = getSourceFile (xClass);
255             
256             className = xClass.getName ().replace ('.', '$');
257             name = packageName + (packageName.length () > 0 ? "." : "") + className;
258         } else {
259             name = xClass.getQualifiedName ();
260             sourceFile = getSourceFile (xClass);
261             className = xClass.getName ();
262         }
263         
264         if (sourceFile == null) {
265             log ("Unable to find source file for: " + name);
266         }
267         
268         destFile = new File JavaDoc (destDir, name.replace ('.', '/') + "$__attributeRepository.java");
269         
270         if (xClass.isAnonymous ()) {
271             log (xClass.getName () + " is anonymous - ignoring.", Project.MSG_VERBOSE);
272             numIgnored++;
273             return;
274         }
275         
276         if (!hasAttributes (xClass)) {
277             if (destFile.exists ()) {
278                 destFile.delete ();
279             }
280             return;
281         }
282         
283         if (destFile.exists () && sourceFile != null && destFile.lastModified () >= sourceFile.lastModified ()) {
284             return;
285         }
286         
287         numGenerated++;
288         
289         
290         destFile.getParentFile ().mkdirs ();
291         PrintWriter JavaDoc pw = new PrintWriter JavaDoc (new FileWriter JavaDoc (destFile));
292         try {
293             if (packageName != null && !packageName.equals ("")) {
294                 pw.println ("package " + packageName + ";");
295             }
296             
297             if (sourceFile != null) {
298                 copyImports (sourceFile, pw);
299             }
300             
301             StringTokenizer JavaDoc tok = new StringTokenizer JavaDoc (attributePackages, ";");
302             while (tok.hasMoreTokens ()) {
303                 pw.println ("import " + tok.nextToken () + ".*;");
304             }
305             
306             pw.println ("public class " + className + "$__attributeRepository implements org.apache.commons.attributes.AttributeRepositoryClass {");
307             {
308                 pw.println (" private final java.util.Set classAttributes = new java.util.HashSet ();");
309                 pw.println (" private final java.util.Map fieldAttributes = new java.util.HashMap ();");
310                 pw.println (" private final java.util.Map methodAttributes = new java.util.HashMap ();");
311                 pw.println (" private final java.util.Map constructorAttributes = new java.util.HashMap ();");
312                 pw.println ();
313                 
314                 pw.println (" public " + className + "$__attributeRepository " + "() {");
315                 pw.println (" initClassAttributes ();");
316                 pw.println (" initMethodAttributes ();");
317                 pw.println (" initFieldAttributes ();");
318                 pw.println (" initConstructorAttributes ();");
319                 pw.println (" }");
320                 pw.println ();
321                 
322                 pw.println (" public java.util.Set getClassAttributes () { return classAttributes; }");
323                 pw.println (" public java.util.Map getFieldAttributes () { return fieldAttributes; }");
324                 pw.println (" public java.util.Map getConstructorAttributes () { return constructorAttributes; }");
325                 pw.println (" public java.util.Map getMethodAttributes () { return methodAttributes; }");
326                 pw.println ();
327                 
328                 pw.println (" private void initClassAttributes () {");
329                 addExpressions (xClass.getDoc ().getTags (), pw, "classAttributes", sourceFile);
330                 pw.println (" }");
331                 pw.println ();
332                 
333                 // ---- Field Attributes
334

335                 pw.println (" private void initFieldAttributes () {");
336                 pw.println (" java.util.Set attrs = null;");
337                 for (Iterator JavaDoc iter = xClass.getFields ().iterator (); iter.hasNext ();) {
338                     XField member = (XField) iter.next ();
339                     if (member.getDoc ().getTags ().size () > 0) {
340                         String JavaDoc key = member.getName ();
341                         
342                         pw.println (" attrs = new java.util.HashSet ();");
343                         addExpressions (member.getDoc ().getTags (), pw, "attrs", sourceFile);
344                         pw.println (" fieldAttributes.put (\"" + key + "\", attrs);");
345                         pw.println (" attrs = null;");
346                         pw.println ();
347                     }
348                 }
349                 pw.println (" }");
350                 
351                 // ---- Method Attributes
352

353                 pw.println (" private void initMethodAttributes () {");
354                 pw.println (" java.util.Set attrs = null;");
355                 pw.println (" java.util.List bundle = null;");
356                 for (Iterator JavaDoc iter = xClass.getMethods ().iterator (); iter.hasNext ();) {
357                     XMethod member = (XMethod) iter.next ();
358                     if (member.getDoc ().getTags ().size () > 0) {
359                         StringBuffer JavaDoc sb = new StringBuffer JavaDoc ();
360                         sb.append (member.getName ()).append ("(");
361                         sb.append (getParameterTypes (member.getParameters ()));
362                         sb.append (")");
363                         String JavaDoc key = sb.toString ();
364                         
365                         pw.println (" bundle = new java.util.ArrayList ();");
366                         pw.println (" attrs = new java.util.HashSet ();");
367                         addExpressions (member.getDoc ().getTags (), null, pw, "attrs", sourceFile);
368                         pw.println (" bundle.add (attrs);");
369                         pw.println (" attrs = null;");
370                         
371                         pw.println (" attrs = new java.util.HashSet ();");
372                         addExpressions (member.getDoc ().getTags (), "return", pw, "attrs", sourceFile);
373                         pw.println (" bundle.add (attrs);");
374                         pw.println (" attrs = null;");
375                         
376                         for (Iterator JavaDoc parameters = member.getParameters ().iterator (); parameters.hasNext ();) {
377                             XParameter parameter = (XParameter) parameters.next ();
378                             pw.println (" attrs = new java.util.HashSet ();");
379                             addExpressions (member.getDoc ().getTags (), parameter.getName (), pw, "attrs", sourceFile);
380                             pw.println (" bundle.add (attrs);");
381                             pw.println (" attrs = null;");
382                         }
383                         
384                         pw.println (" methodAttributes.put (\"" + key + "\", bundle);");
385                         pw.println (" bundle = null;");
386                         pw.println ();
387                     }
388                 }
389                 pw.println (" }");
390                 
391                 
392                 // ---- Constructor Attributes
393

394                 pw.println (" private void initConstructorAttributes () {");
395                 pw.println (" java.util.Set attrs = null;");
396                 pw.println (" java.util.List bundle = null;");
397                 for (Iterator JavaDoc iter = xClass.getConstructors ().iterator (); iter.hasNext ();) {
398                     XConstructor member = (XConstructor) iter.next ();
399                     if (member.getDoc ().getTags ().size () > 0) {
400                         StringBuffer JavaDoc sb = new StringBuffer JavaDoc ();
401                         sb.append ("(");
402                         sb.append (getParameterTypes (member.getParameters ()));
403                         sb.append (")");
404                         String JavaDoc key = sb.toString ();
405                         
406                         pw.println (" bundle = new java.util.ArrayList ();");
407                         pw.println (" attrs = new java.util.HashSet ();");
408                         addExpressions (member.getDoc ().getTags (), null, pw, "attrs", sourceFile);
409                         pw.println (" bundle.add (attrs);");
410                         pw.println (" attrs = null;");
411                         
412                         for (Iterator JavaDoc parameters = member.getParameters ().iterator (); parameters.hasNext ();) {
413                             XParameter parameter = (XParameter) parameters.next ();
414                             pw.println (" attrs = new java.util.HashSet ();");
415                             addExpressions (member.getDoc ().getTags (), parameter.getName (), pw, "attrs", sourceFile);
416                             pw.println (" bundle.add (attrs);");
417                             pw.println (" attrs = null;");
418                         }
419                         
420                         pw.println (" constructorAttributes.put (\"" + key + "\", bundle);");
421                         pw.println (" bundle = null;");
422                         pw.println ();
423                     }
424                 }
425                 pw.println (" }");
426             }
427             pw.println ("}");
428             
429             pw.close ();
430         } catch (Exception JavaDoc e) {
431             pw.close ();
432             destFile.delete ();
433             throw e;
434         }
435     }
436     
437     /**
438      * Finds the source file of a class.
439      *
440      * @param qualifiedName the fully qualified class name
441      * @return the file the class is defined in.
442      * @throws BuildException if the file could not be found.
443      */

444     protected File JavaDoc getSourceFile (XClass xClass) throws BuildException {
445         while (xClass != null && xClass.isInner ()) {
446             xClass = xClass.getContainingClass ();
447         }
448         
449         if (xClass != null && xClass instanceof SourceClass) {
450             AbstractFile af = ((SourceClass) xClass).getFile ();
451             return new File JavaDoc (af.getPath ());
452         }
453         return null;
454     }
455     
456     protected boolean hasAttributes (XClass xClass) {
457         if (tagHasAttributes (xClass.getDoc ().getTags ()) ||
458             elementHasAttributes (xClass.getFields ()) ||
459             elementHasAttributes (xClass.getMethods ()) ||
460             elementHasAttributes (xClass.getConstructors ()) ) {
461             return true;
462         }
463         return false;
464     }
465     
466     /**
467      * Tests if a tag is an attribute. Currently the test is
468      * only "check if it is defined with two @-signs".
469      */

470     protected boolean isAttribute (XTag tag) {
471         return tag.getName ().length () > 0 && tag.getName ().charAt (0) == '@';
472     }
473     
474     protected void start() throws BuildException {
475         destDir.mkdirs ();
476         numGenerated = 0;
477         
478         XJavaDoc doc = getXJavaDoc ();
479         Iterator JavaDoc iter = doc.getSourceClasses ().iterator ();
480         try {
481             while (iter.hasNext ()) {
482                 XClass xClass = (XClass) iter.next ();
483                 generateClass (xClass);
484             }
485         } catch (Exception JavaDoc e) {
486             throw new BuildException (e.toString (), e);
487         }
488         log ("Generated attribute information for " + numGenerated + " classes. Ignored " + numIgnored + " classes.");
489     }
490     
491     /**
492      * Checks if a collection of XTags contain any tags specifying attributes.
493      */

494     protected boolean tagHasAttributes (Collection JavaDoc tags) {
495         Iterator JavaDoc iter = tags.iterator ();
496         while (iter.hasNext ()) {
497             XTag tag = (XTag) iter.next ();
498             if (isAttribute (tag)) {
499                 return true;
500             }
501         }
502         return false;
503     }
504 }
Popular Tags