KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > beehive > netui > compiler > xdoclet > tools > AnnotationsToXDoclet


1 /*
2  * Copyright 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  * $Header:$
17  */

18 package org.apache.beehive.netui.compiler.xdoclet.tools;
19
20 import java.io.StreamTokenizer JavaDoc;
21 import java.io.Reader JavaDoc;
22 import java.io.File JavaDoc;
23 import java.io.IOException JavaDoc;
24 import java.io.FileNotFoundException JavaDoc;
25 import java.io.FileReader JavaDoc;
26 import java.io.FileWriter JavaDoc;
27 import java.io.PrintWriter JavaDoc;
28 import java.util.ArrayList JavaDoc;
29
30 public class AnnotationsToXDoclet
31 {
32     private static final String JavaDoc[] QUALIFIED_ANNOTATIONS =
33             {
34                 "@org.apache.beehive.netui.pageflow.annotations.",
35                 "@org.apache.beehive.controls.api.bean."
36             };
37     
38     private static void usage()
39     {
40         System.err.println( "usage: " + AnnotationsToXDoclet.class.getName() + " input-file output-file" );
41         System.err.println( " -or-" );
42         System.err.println( "usage: " + AnnotationsToXDoclet.class.getName()
43                             + " -input-dir <root of input dir> -output-dir <root of output dir> -extensions <comma-separated list>" );
44     }
45     
46     public static void main( String JavaDoc[] args )
47         throws IOException JavaDoc, FileNotFoundException JavaDoc
48     {
49         // Recurse
50
if ( args.length == 6 )
51         {
52             if ( ! args[0].equals( "-input-dir" ) || ! args[2].equals( "-output-dir" ) || ! args[4].equals( "-extensions" ) )
53             {
54                 usage();
55                 System.exit( 1 );
56             }
57             
58             File JavaDoc inputDir = new File JavaDoc( args[1] );
59             if ( ! inputDir.exists() )
60             {
61                 System.err.println( inputDir + " is not a directory" );
62                 System.exit( 2 );
63             }
64             
65             File JavaDoc outputDir = new File JavaDoc( args[3] );
66             if ( ! outputDir.exists() )
67             {
68                 System.err.println( outputDir + " is not a directory" );
69                 System.exit( 2 );
70             }
71             
72             String JavaDoc[] extensions = args[5].split( "," );
73             new AnnotationsToXDoclet().translateRecursive( inputDir, outputDir, extensions );
74             return;
75         }
76         
77         // ...or, do a single file translation.
78
if ( args.length != 2 )
79         {
80             usage();
81             System.exit( 1 );
82         }
83         
84         File JavaDoc input = new File JavaDoc( args[0] );
85         File JavaDoc output = new File JavaDoc( args[1] );
86         
87         if ( input.equals( output ) )
88         {
89             System.err.println( "input file " + input + " must be different from output file" );
90             System.exit( 2 );
91         }
92         
93         if ( ! input.canRead() )
94         {
95             System.err.println( "cannot read " + input );
96             System.exit( 2 );
97         }
98         
99         if ( output.exists() && ! output.canWrite() )
100         {
101             System.err.println( "cannot write to " + output );
102             System.exit( 2 );
103         }
104         
105         new AnnotationsToXDoclet().translate( input, output );
106     }
107     
108     public void translateRecursive( File JavaDoc inputDir, File JavaDoc outputDir, String JavaDoc[] extensions )
109             throws IOException JavaDoc, FileNotFoundException JavaDoc
110     {
111         File JavaDoc[] children = inputDir.listFiles();
112         
113         outputDir.mkdirs();
114         
115         for ( int i = 0; i < children.length; i++ )
116         {
117             File JavaDoc child = children[i];
118             
119             if ( child.isFile() )
120             {
121                 for ( int j = 0; j < extensions.length; j++ )
122                 {
123                     String JavaDoc extension = extensions[j];
124                     if ( child.getName().endsWith( extension ) )
125                     {
126                         translate( child, new File JavaDoc( outputDir, child.getName() ) );
127                     }
128                 }
129             }
130             else if ( child.isDirectory() )
131             {
132                 File JavaDoc childOutputDir = new File JavaDoc( outputDir, child.getName() );
133                 translateRecursive( child, childOutputDir, extensions );
134             }
135         }
136     }
137     
138     public void translate( File JavaDoc input, File JavaDoc output )
139             throws IOException JavaDoc, FileNotFoundException JavaDoc
140     {
141 System.err.println( input + " -> " + output );
142         output.getParentFile().mkdirs();
143         FileReader JavaDoc in = new FileReader JavaDoc( input );
144         PrintWriter JavaDoc out = null;
145         
146         try
147         {
148             out = new PrintWriter JavaDoc( new FileWriter JavaDoc( output ) );
149             StreamTokenizer JavaDoc tok = getJavaTokenizer( in );
150             boolean addedSpace = false;
151             StringBuffer JavaDoc indentBuffer = new StringBuffer JavaDoc();
152             String JavaDoc indent = "";
153             
154             while ( tok.nextToken() != StreamTokenizer.TT_EOF )
155             {
156                 boolean wasSpace = false;
157                 boolean wasChar = false;
158                 
159                 switch ( tok.ttype )
160                 {
161                     case StreamTokenizer.TT_WORD:
162                         if ( indentBuffer != null )
163                         {
164                             indent = indentBuffer.toString();
165                             indentBuffer = null;
166                         }
167                         String JavaDoc str = tok.sval;
168                         if ( str.startsWith( "@Jpf.ViewProperties" ) )
169                         {
170                             ignoreUntil( tok, ")" );
171                         }
172                         else if ( str.startsWith( "@Jpf." ) || str.startsWith( "@Control" )
173                              || str.startsWith( "@org.apache.beehive" ) )
174                         {
175                             out.println( "/**" );
176                             ArrayList JavaDoc tags = new ArrayList JavaDoc();
177                             translateAnnotation( tok, out, str, indent, tags );
178                             for ( int i = 0; i < tags.size(); ++i )
179                             {
180                                 out.print( indent );
181                                 out.print( " * " );
182                                 out.println( ( String JavaDoc ) tags.get( i ) );
183                             }
184                             out.print( indent );
185                             out.print( " */" );
186                         }
187                         else if ( str.equals( "import" ) )
188                         {
189                             filterImport( tok, out );
190                         }
191                         else
192                         {
193                             out.print( str );
194                             if ( str.length() == 1 )
195                             {
196                                 char c = str.charAt( 0 );
197                                 if ( c == '\'' || c == '"' ) wasChar = true;
198                             }
199                         }
200                         break;
201                         
202                     case StreamTokenizer.TT_NUMBER:
203                         assert false : tok.nval; // parseNumbers() was set to false on the tokenizer.
204
break;
205                         
206                     default:
207                         char c = ( char ) tok.ttype;
208                         wasChar = true;
209                         if ( ! addedSpace || c != ' ' ) out.print( c );
210                         wasSpace = Character.isWhitespace( c );
211                         if ( ! wasSpace && indentBuffer != null )
212                         {
213                             indent = indentBuffer.toString();
214                             indentBuffer = null;
215                         }
216                         if ( indentBuffer != null ) indentBuffer.append( c );
217                         if ( c == '\n' ) indentBuffer = new StringBuffer JavaDoc();
218                 }
219                 
220                 if ( ! wasChar )
221                 {
222                     out.print( ' ' );
223                     addedSpace = true;
224                 }
225                 else
226                 {
227                     addedSpace = false;
228                 }
229             }
230         }
231         finally
232         {
233             in.close();
234             if ( out != null ) out.close();
235         }
236     }
237     
238     private void ignoreUntil( StreamTokenizer JavaDoc tok, String JavaDoc str )
239         throws IOException JavaDoc
240     {
241         while ( ! getToken( tok ).equals( str ) )
242         {
243         }
244     }
245     
246     private void filterImport( StreamTokenizer JavaDoc tok, PrintWriter JavaDoc out )
247         throws IOException JavaDoc
248     {
249         String JavaDoc importName = getToken( tok );
250         if ( ! importName.startsWith( "org.apache.beehive.netui.pageflow.annotations" )
251              && ! importName.startsWith( "org.apache.beehive.controls.api.bean.Control" ) )
252         {
253             out.print( "import " );
254             out.print( importName );
255         }
256         else
257         {
258             expectToken( tok, ";" );
259         }
260     }
261     
262     private void translateAnnotation( StreamTokenizer JavaDoc tok, PrintWriter JavaDoc out, String JavaDoc firstToken, String JavaDoc indent,
263                                       ArrayList JavaDoc tags )
264         throws IOException JavaDoc
265     {
266         for ( int i = 0; i < QUALIFIED_ANNOTATIONS.length; i++ )
267         {
268             String JavaDoc qualifiedAnnotation = QUALIFIED_ANNOTATIONS[i];
269             if ( firstToken.startsWith( qualifiedAnnotation ) )
270             {
271                 firstToken = '@' + firstToken.substring( qualifiedAnnotation.length() );
272             }
273         }
274         
275         String JavaDoc nextToken = getToken( tok );
276         
277         if ( ! nextToken.equals( "(" ) )
278         {
279             tok.pushBack();
280             tags.add( firstToken );
281             return;
282         }
283         else
284         {
285             StringBuffer JavaDoc tag = new StringBuffer JavaDoc( firstToken );
286             int thisTagPos = tags.size();
287             tags.add( "" );
288             
289             while ( ! ( nextToken = getToken( tok ) ).equals( ")" ) )
290             {
291                 if ( nextToken.equals( "," ) ) nextToken = getToken( tok );
292                 String JavaDoc attrName = nextToken;
293                 expectToken( tok, "=" );
294                 String JavaDoc value = getToken( tok );
295                 int pos;
296                 
297                 if ( value.charAt( 0 ) == '@' )
298                 {
299                     if ( attrName.equals( "validationErrorForward" ) )
300                     {
301                         // Special case:
302
// validationErrorForward=@Jpf.Forward(...)
303
// goes to
304
// @Jpf.ValidationErrorForward(...)
305
value = "@Jpf.ValidationErrorForward";
306                     }
307                     
308                     translateAnnotation( tok, out, value, indent, tags );
309                     value = null;
310                 }
311                 else if ( value.equals( "{" ) )
312                 {
313                     StringBuffer JavaDoc stringArray = null;
314                     
315                     while ( ! ( nextToken = getToken( tok ) ).equals( "}" ) )
316                     {
317                         if ( nextToken.equals( "," ) ) nextToken = getToken( tok );
318                         
319                         if ( nextToken.charAt( 0 ) == '@' )
320                         {
321                             translateAnnotation( tok, out, nextToken, indent, tags );
322                         }
323                         else
324                         {
325                             // We're expecting a string array element here.
326
assert nextToken.length() > 1 && nextToken.charAt( 0 ) == '"'
327                                    && nextToken.charAt( nextToken.length() - 1 ) == '"' : nextToken;
328                             if ( stringArray == null )
329                             {
330                                 stringArray = new StringBuffer JavaDoc( "\"" );
331                             }
332                             else
333                             {
334                                 stringArray.append( ',' );
335                             }
336                             stringArray.append( nextToken.substring( 1, nextToken.length() - 1 ) );
337                         }
338                     }
339                     
340                     value = stringArray != null ? stringArray.append( '"' ).toString() : null;
341                 }
342                 else if ( value.equals( "true" ) || value.equals( "false" ) )
343                 {
344                     value = '"' + value + '"';
345                 }
346                 else if ( value.endsWith( ".class" ) )
347                 {
348                     value = '"' + value.substring( 0, value.length() - 6 ) + '"';
349                 }
350                 else if ( ( pos = value.indexOf( "Jpf.NavigateTo." ) ) != -1 )
351                 {
352                     value = '"' + value.substring( pos + 15 ) + '"';
353                 }
354                 else if ( ( pos = value.indexOf( "Jpf.ValidatorVersion." ) ) != -1 )
355                 {
356                     value = '"' + value.substring( pos + 21 ) + '"';
357                 }
358                 else if ( isNumber( value ) )
359                 {
360                     value = '"' + value + '"';
361                 }
362                 else
363                 {
364                     assert value.charAt( 0 ) == '"' && value.charAt( value.length() - 1 ) == '"' : value;
365                     if ( value.charAt( 0 ) != '"' ) value = '"' + value;
366                     if ( value.charAt( value.length() - 1 ) != '"' ) value += '"';
367                 }
368                 
369                 if ( value != null )
370                 {
371                     tag.append( ' ' ).append( attrName ).append( '=' ).append( value );
372                 }
373             }
374             
375             tags.set( thisTagPos, tag.toString() );
376         }
377     }
378     
379     private static boolean isNumber( String JavaDoc str )
380     {
381         char firstChar = str.charAt( 0 );
382         if ( firstChar != '-' && ! Character.isDigit( firstChar ) && firstChar != '.' ) return false;
383         
384         for ( int i = 1; i < str.length(); ++i )
385         {
386             char c = str.charAt( i );
387             if ( ! Character.isDigit( c ) && c != '.' ) return false;
388         }
389         
390         return true;
391     }
392     
393     private String JavaDoc expectToken( StreamTokenizer JavaDoc tok, String JavaDoc expected )
394         throws IOException JavaDoc
395     {
396         String JavaDoc token = getToken( tok );
397         assert token.equals( expected ) : "expected \"" + expected + "\", got \"" + token + "\" (line " + tok.lineno() + ')';
398         return token;
399     }
400     
401     private String JavaDoc getToken( StreamTokenizer JavaDoc tok )
402             throws IOException JavaDoc
403     {
404         return getToken( tok, false, "" );
405     }
406     
407     private String JavaDoc getToken( StreamTokenizer JavaDoc tok, boolean includeSpace, String JavaDoc prepend )
408         throws IOException JavaDoc
409     {
410         tok.nextToken();
411         assert tok.ttype != StreamTokenizer.TT_EOF : "unexpected eof";
412         String JavaDoc retVal;
413         
414         switch ( tok.ttype )
415         {
416             case StreamTokenizer.TT_WORD:
417                 retVal = prepend + tok.sval;
418                 break;
419                 
420             case StreamTokenizer.TT_NUMBER:
421                 assert false : tok.nval; // parseNumbers() was set to false on the tokenizer.
422
retVal = new Double JavaDoc( tok.nval ).toString();
423                 break;
424                 
425             default:
426                 char c = ( char ) tok.ttype;
427                 if ( Character.isWhitespace( c ) && ! includeSpace ) return getToken( tok );
428                 retVal = prepend + Character.toString( c );
429         }
430         
431         // If quotes are imbalanced, keep reading tokens until they're balanced.
432
return count( retVal, '"' ) % 2 != 0 ? getToken( tok, true, retVal ) : retVal;
433     }
434     
435     private static int count( String JavaDoc s, char c )
436     {
437         int count = 0;
438         char lastChar = '\0';
439         
440         for ( int i = 0; i < s.length(); ++i )
441         {
442             if ( lastChar != '\\' && s.charAt( i ) == c ) ++count;
443             lastChar = c;
444         }
445         
446         return count;
447     }
448     
449     private static StreamTokenizer JavaDoc getJavaTokenizer( Reader JavaDoc reader )
450     {
451         StreamTokenizer JavaDoc tok = new StreamTokenizer JavaDoc( reader );
452         tok.resetSyntax();
453         tok.eolIsSignificant( true );
454         tok.lowerCaseMode( false );
455         tok.wordChars( 'A', 'Z' );
456         tok.wordChars( 'a', 'z' );
457         tok.wordChars( '_', '_' );
458         tok.wordChars( '@', '@' );
459         tok.wordChars( '[', '[' );
460         tok.wordChars( ']', ']' );
461         tok.wordChars( '.', '.' );
462         tok.wordChars( '"', '"' );
463         tok.wordChars( '\'', '\'' );
464         tok.wordChars( '-', '-' );
465         tok.wordChars( '0', '9' );
466         tok.wordChars( ':', ':' );
467         tok.wordChars( '$', '$' );
468         tok.wordChars( '/', '/' );
469         tok.wordChars( '*', '*' );
470         tok.wordChars( '\\', '\\' );
471         tok.wordChars( '?', '?' );
472         return tok;
473     }
474 }
475
Popular Tags