Package org.apache.beehive.netui.compiler.xdoclet.tools

Source Code of org.apache.beehive.netui.compiler.xdoclet.tools.AnnotationsToXDoclet

/*
* Copyright 2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* $Header:$
*/
package org.apache.beehive.netui.compiler.xdoclet.tools;

import java.io.StreamTokenizer;
import java.io.Reader;
import java.io.File;
import java.io.IOException;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.util.ArrayList;

public class AnnotationsToXDoclet
{
    private static final String[] QUALIFIED_ANNOTATIONS =
            {
                "@org.apache.beehive.netui.pageflow.annotations.",
                "@org.apache.beehive.controls.api.bean."
            };
   
    private static void usage()
    {
        System.err.println( "usage: " + AnnotationsToXDoclet.class.getName() + " input-file output-file" );
        System.err.println( "                            -or-" );
        System.err.println( "usage: " + AnnotationsToXDoclet.class.getName()
                            + " -input-dir <root of input dir> -output-dir <root of output dir> -extensions <comma-separated list>" );
    }
   
    public static void main( String[] args )
        throws IOException, FileNotFoundException
    {
        // Recurse
        if ( args.length == 6 )
        {
            if ( ! args[0].equals( "-input-dir" ) || ! args[2].equals( "-output-dir" ) || ! args[4].equals( "-extensions" ) )
            {
                usage();
                System.exit( 1 );
            }
           
            File inputDir = new File( args[1] );
            if ( ! inputDir.exists() )
            {
                System.err.println( inputDir + " is not a directory" );
                System.exit( 2 );
            }
           
            File outputDir = new File( args[3] );
            if ( ! outputDir.exists() )
            {
                System.err.println( outputDir + " is not a directory" );
                System.exit( 2 );
            }
           
            String[] extensions = args[5].split( "," );
            new AnnotationsToXDoclet().translateRecursive( inputDir, outputDir, extensions );
            return;
        }
       
        // ...or, do a single file translation.
        if ( args.length != 2 )
        {
            usage();
            System.exit( 1 );
        }
       
        File input = new File( args[0] );
        File output = new File( args[1] );
       
        if ( input.equals( output ) )
        {
            System.err.println( "input file " + input + " must be different from output file" );
            System.exit( 2 );
        }
       
        if ( ! input.canRead() )
        {
            System.err.println( "cannot read " + input );
            System.exit( 2 );
        }
       
        if ( output.exists() && ! output.canWrite() )
        {
            System.err.println( "cannot write to " + output );
            System.exit( 2 );
        }
       
        new AnnotationsToXDoclet().translate( input, output );
    }
   
    public void translateRecursive( File inputDir, File outputDir, String[] extensions )
            throws IOException, FileNotFoundException
    {
        File[] children = inputDir.listFiles();
       
        outputDir.mkdirs();
       
        for ( int i = 0; i < children.length; i++ )
        {
            File child = children[i];
           
            if ( child.isFile() )
            {
                for ( int j = 0; j < extensions.length; j++ )
                {
                    String extension = extensions[j];
                    if ( child.getName().endsWith( extension ) )
                    {
                        translate( child, new File( outputDir, child.getName() ) );
                    }
                }
            }
            else if ( child.isDirectory() )
            {
                File childOutputDir = new File( outputDir, child.getName() );
                translateRecursive( child, childOutputDir, extensions );
            }
        }
    }
   
    public void translate( File input, File output )
            throws IOException, FileNotFoundException
    {
System.err.println( input + " -> " + output );
        output.getParentFile().mkdirs();
        FileReader in = new FileReader( input );
        PrintWriter out = null;
       
        try
        {
            out = new PrintWriter( new FileWriter( output ) );
            StreamTokenizer tok = getJavaTokenizer( in );
            boolean addedSpace = false;
            StringBuffer indentBuffer = new StringBuffer();
            String indent = "";
           
            while ( tok.nextToken() != StreamTokenizer.TT_EOF )
            {
                boolean wasSpace = false;
                boolean wasChar = false;
               
                switch ( tok.ttype )
                {
                    case StreamTokenizer.TT_WORD:
                        if ( indentBuffer != null )
                        {
                            indent = indentBuffer.toString();
                            indentBuffer = null;
                        }
                        String str = tok.sval;
                        if ( str.startsWith( "@Jpf.ViewProperties" ) )
                        {
                            ignoreUntil( tok, ")" );
                        }
                        else if ( str.startsWith( "@Jpf." ) || str.startsWith( "@Control" )
                             || str.startsWith( "@org.apache.beehive" ) )
                        {
                            out.println( "/**" );
                            ArrayList tags = new ArrayList();
                            translateAnnotation( tok, out, str, indent, tags );
                            for ( int i = 0; i < tags.size(); ++i )
                            {
                                out.print( indent );
                                out.print( " * " );
                                out.println( ( String ) tags.get( i ) );
                            }
                            out.print( indent );
                            out.print( " */" );
                        }
                        else if ( str.equals( "import" ) )
                        {
                            filterImport( tok, out );
                        }
                        else
                        {
                            out.print( str );
                            if ( str.length() == 1 )
                            {
                                char c = str.charAt( 0 );
                                if ( c == '\'' || c == '"' ) wasChar = true;
                            }
                        }
                        break;
                       
                    case StreamTokenizer.TT_NUMBER:
                        assert false : tok.nval;   // parseNumbers() was set to false on the tokenizer.
                        break;
                       
                    default:
                        char c = ( char ) tok.ttype;
                        wasChar = true;
                        if ( ! addedSpace || c != ' ' ) out.print( c );
                        wasSpace = Character.isWhitespace( c );
                        if ( ! wasSpace && indentBuffer != null )
                        {
                            indent = indentBuffer.toString();
                            indentBuffer = null;
                        }
                        if ( indentBuffer != null ) indentBuffer.append( c );
                        if ( c == '\n' ) indentBuffer = new StringBuffer();
                }
               
                if ( ! wasChar )
                {
                    out.print( ' ' );
                    addedSpace = true;
                }
                else
                {
                    addedSpace = false;
                }
            }
        }
        finally
        {
            in.close();
            if ( out != null ) out.close();
        }
    }
   
    private void ignoreUntil( StreamTokenizer tok, String str )
        throws IOException
    {
        while ( ! getToken( tok ).equals( str ) )
        {
        }
    }
   
    private void filterImport( StreamTokenizer tok, PrintWriter out )
        throws IOException
    {
        String importName = getToken( tok );
        if ( ! importName.startsWith( "org.apache.beehive.netui.pageflow.annotations" )
             && ! importName.startsWith( "org.apache.beehive.controls.api.bean.Control" ) )
        {
            out.print( "import " );
            out.print( importName );
        }
        else
        {
            expectToken( tok, ";" );
        }
    }
   
    private void translateAnnotation( StreamTokenizer tok, PrintWriter out, String firstToken, String indent,
                                      ArrayList tags )
        throws IOException
    {
        for ( int i = 0; i < QUALIFIED_ANNOTATIONS.length; i++ )
        {
            String qualifiedAnnotation = QUALIFIED_ANNOTATIONS[i];
            if ( firstToken.startsWith( qualifiedAnnotation ) )
            {
                firstToken = '@' + firstToken.substring( qualifiedAnnotation.length() );
            }
        }
       
        String nextToken = getToken( tok );
       
        if ( ! nextToken.equals( "(" ) )
        {
            tok.pushBack();
            tags.add( firstToken );
            return;
        }
        else
        {
            StringBuffer tag = new StringBuffer( firstToken );
            int thisTagPos = tags.size();
            tags.add( "" );
           
            while ( ! ( nextToken = getToken( tok ) ).equals( ")" ) )
            {
                if ( nextToken.equals( "," ) ) nextToken = getToken( tok );
                String attrName = nextToken;
                expectToken( tok, "=" );
                String value = getToken( tok );
                int pos;
               
                if ( value.charAt( 0 ) == '@' )
                {
                    if ( attrName.equals( "validationErrorForward" ) )
                    {
                        // Special case:
                        //     validationErrorForward=@Jpf.Forward(...)
                        // goes to
                        //     @Jpf.ValidationErrorForward(...)
                        value = "@Jpf.ValidationErrorForward";
                    }
                   
                    translateAnnotation( tok, out, value, indent, tags );
                    value = null;
                }
                else if ( value.equals( "{" ) )
                {
                    StringBuffer stringArray = null;
                   
                    while ( ! ( nextToken = getToken( tok ) ).equals( "}" ) )
                    {
                        if ( nextToken.equals( "," ) ) nextToken = getToken( tok );
                       
                        if ( nextToken.charAt( 0 ) == '@' )
                        {
                            translateAnnotation( tok, out, nextToken, indent, tags );
                        }
                        else
                        {
                            // We're expecting a string array element here.
                            assert nextToken.length() > 1 && nextToken.charAt( 0 ) == '"'
                                   && nextToken.charAt( nextToken.length() - 1 ) == '"' : nextToken;
                            if ( stringArray == null )
                            {
                                stringArray = new StringBuffer( "\"" );
                            }
                            else
                            {
                                stringArray.append( ',' );
                            }
                            stringArray.append( nextToken.substring( 1, nextToken.length() - 1 ) );
                        }
                    }
                   
                    value = stringArray != null ? stringArray.append( '"' ).toString() : null;
                }
                else if ( value.equals( "true" ) || value.equals( "false" ) )
                {
                    value = '"' + value + '"';
                }
                else if ( value.endsWith( ".class" ) )
                {
                    value = '"' + value.substring( 0, value.length() - 6 ) + '"';
                }
                else if ( ( pos = value.indexOf( "Jpf.NavigateTo." ) ) != -1 )
                {
                    value = '"' + value.substring( pos + 15 ) + '"';
                }
                else if ( ( pos = value.indexOf( "Jpf.ValidatorVersion." ) ) != -1 )
                {
                    value = '"' + value.substring( pos + 21 ) + '"';
                }
                else if ( isNumber( value ) )
                {
                    value = '"' + value + '"';
                }
                else
                {
                    assert value.charAt( 0 ) == '"' && value.charAt( value.length() - 1 ) == '"' : value;
                    if ( value.charAt( 0 ) != '"' ) value = '"' + value;
                    if ( value.charAt( value.length() - 1 ) != '"' ) value += '"';
                }
               
                if ( value != null )
                {
                    tag.append( ' ' ).append( attrName ).append( '=' ).append( value );
                }
            }
           
            tags.set( thisTagPos, tag.toString() );
        }
    }
   
    private static boolean isNumber( String str )
    {
        char firstChar = str.charAt( 0 );
        if ( firstChar != '-' && ! Character.isDigit( firstChar ) && firstChar != '.' ) return false;
       
        for ( int i = 1; i < str.length(); ++i )
        {
            char c = str.charAt( i );
            if ( ! Character.isDigit( c ) && c != '.' ) return false;
        }
       
        return true;
    }
   
    private String expectToken( StreamTokenizer tok, String expected )
        throws IOException
    {
        String token = getToken( tok );
        assert token.equals( expected ) : "expected \"" + expected + "\", got \"" + token + "\" (line " + tok.lineno() + ')';
        return token;
    }
   
    private String getToken( StreamTokenizer tok )
            throws IOException
    {
        return getToken( tok, false, "" );
    }
   
    private String getToken( StreamTokenizer tok, boolean includeSpace, String prepend )
        throws IOException
    {
        tok.nextToken();
        assert tok.ttype != StreamTokenizer.TT_EOF : "unexpected eof";
        String retVal;
       
        switch ( tok.ttype )
        {
            case StreamTokenizer.TT_WORD:
                retVal = prepend + tok.sval;
                break;
               
            case StreamTokenizer.TT_NUMBER:
                assert false : tok.nval;   // parseNumbers() was set to false on the tokenizer.
                retVal = new Double( tok.nval ).toString();
                break;
               
            default:
                char c = ( char ) tok.ttype;
                if ( Character.isWhitespace( c ) && ! includeSpace ) return getToken( tok );
                retVal = prepend + Character.toString( c );
        }
       
        // If quotes are imbalanced, keep reading tokens until they're balanced.
        return count( retVal, '"' ) % 2 != 0 ? getToken( tok, true, retVal ) : retVal;
    }
   
    private static int count( String s, char c )
    {
        int count = 0;
        char lastChar = '\0';
       
        for ( int i = 0; i < s.length(); ++i )
        {
            if ( lastChar != '\\' && s.charAt( i ) == c ) ++count;
            lastChar = c;
        }
       
        return count;
    }
   
    private static StreamTokenizer getJavaTokenizer( Reader reader )
    {
        StreamTokenizer tok = new StreamTokenizer( reader );
        tok.resetSyntax();
        tok.eolIsSignificant( true );
        tok.lowerCaseMode( false );
        tok.wordChars( 'A', 'Z' );
        tok.wordChars( 'a', 'z' );
        tok.wordChars( '_', '_' );
        tok.wordChars( '@', '@' );
        tok.wordChars( '[', '[' );
        tok.wordChars( ']', ']' );
        tok.wordChars( '.', '.' );
        tok.wordChars( '"', '"' );
        tok.wordChars( '\'', '\'' );
        tok.wordChars( '-', '-' );
        tok.wordChars( '0', '9' );
        tok.wordChars( ':', ':' );
        tok.wordChars( '$', '$' );
        tok.wordChars( '/', '/' );
        tok.wordChars( '*', '*' );
        tok.wordChars( '\\', '\\' );
        tok.wordChars( '?', '?' );
        return tok;
    }
}
TOP

Related Classes of org.apache.beehive.netui.compiler.xdoclet.tools.AnnotationsToXDoclet

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.