Package org.apache.turbine.torque.engine.database.transform

Source Code of org.apache.turbine.torque.engine.database.transform.SQLToAppData

package org.apache.turbine.torque.engine.database.transform;

/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2001 The Apache Software Foundation.  All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in
*    the documentation and/or other materials provided with the
*    distribution.
*
* 3. The end-user documentation included with the redistribution,
*    if any, must include the following acknowledgment:
*       "This product includes software developed by the
*        Apache Software Foundation (http://www.apache.org/)."
*    Alternately, this acknowledgment may appear in the software itself,
*    if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" and
*    "Apache Turbine" must not be used to endorse or promote products
*    derived from this software without prior written permission. For
*    written permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
*    "Apache Turbine", nor may "Apache" appear in their name, without
*    prior written permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation.  For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintStream;
import java.io.Reader;
import java.util.List;
import java.util.Vector;
import org.apache.turbine.torque.engine.database.model.AppData;
import org.apache.turbine.torque.engine.database.model.Column;
import org.apache.turbine.torque.engine.database.model.Database;
import org.apache.turbine.torque.engine.database.model.ForeignKey;
import org.apache.turbine.torque.engine.database.model.Table;
import org.apache.turbine.torque.engine.sql.ParseException;
import org.apache.turbine.torque.engine.sql.SQLScanner;
import org.apache.turbine.torque.engine.sql.Token;

/**
* A Class that converts an sql input file to an AppData
* structure.  The class makes use of SQL Scanner to get
* sql tokens and the parses these to create the AppData
* class. SQLToAppData is in effect a simplified sql parser.
*
*
* @author <a href="mailto:leon@opticode.co.za">Leon Messerschmidt</a>
* @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a>
* @version $Id: SQLToAppData.java,v 1.3.10.4 2001/05/23 03:08:41 jvanzyl Exp $
*/
public class SQLToAppData
{
    private String sqlFile;
    private Vector tokens;
    private Token token;
    private AppData appData;
    private Database appDataDB;
    private int count;

    /**
     * Create a new class without any input Reader.
     */
    public SQLToAppData()
    {
        this (null);
    }

    /**
     * Create a new class with an input Reader
     */
    public SQLToAppData (String sqlFile)
    {
        this.sqlFile = sqlFile;
    }


    /**
     * Get the current input sql file
     */
    public String getSqlFile()
    {
        return sqlFile;
    }

    /**
     * Set the current input sql file
     */
    public void setSqlFile (String sqlFile)
    {
        this.sqlFile = sqlFile;
    }

    /**
     * Move to the next token.  Throws an exception
     * if there is no more tokens available.
     */
    private void next() throws ParseException
    {
        if (count < tokens.size())
        {
            token = (Token) tokens.elementAt(count++);
        }
        else
        {
            throw new ParseException ("No More Tokens");
        }
    }

    /**
     * Creates an error condition and adds the line and
     * column number of the current token to the error
     * message.
     */
    private void err (String name) throws ParseException
    {
        throw new ParseException (name + " at [ line: " + token.getLine() +
            " col: "+token.getCol()+" ]");
    }

    /**
     * Check if there is more tokens available for parsing.
     */
    private boolean hasTokens()
    {
        return count < tokens.size();
    }

    /**
     * Parses a CREATE TABLE FOO command.
     */
    private void Create() throws ParseException
    {
        next();
        if (token.getStr().toUpperCase().equals("TABLE"))
        {
            Create_Table();
        }
    }

    /**
     * Parses a CREATE TABLE sql command
     */
    private void Create_Table() throws ParseException
    {
        next();
        String tableName = token.getStr(); // name of the table
        next();
        if (!token.getStr().equals("(")) err ("( expected");
        next();

        Table tbl = new Table (tableName);
        //tbl.setIdMethod("none");
        while (!token.getStr().equals(";"))
        {
            Create_Table_Column(tbl);
        }
       
        if (tbl.getPrimaryKey().size() == 1)
        {
            tbl.setIdMethod("idbroker");
        }
        else
        {
            tbl.setIdMethod("none");
        }
         
       
        appDataDB.addTable (tbl);
    }

    /**
     * Parses column information between the braces of a CREATE
     * TABLE () sql statement.
     */
    private void Create_Table_Column(Table tbl) throws ParseException
    {
        // The token should be the first item
        // which is the name of the column or
        // PRIMARY/FOREIGN/UNIQUE
        if (token.getStr().equals(","))
            next();
       
        if (token.getStr().toUpperCase().equals("PRIMARY"))
            Create_Table_Column_Primary (tbl);
        else if (token.getStr().toUpperCase().equals("FOREIGN"))
            Create_Table_Column_Foreign (tbl);
        else if (token.getStr().toUpperCase().equals("UNIQUE"))
            Create_Table_Column_Unique (tbl);
        else
            Create_Table_Column_Data (tbl);
    }

    /**
     * Parses PRIMARY KEY (FOO,BAR) statement
     */
    private void Create_Table_Column_Primary (Table tbl) throws ParseException
    {
        next();
        if (!token.getStr().toUpperCase().equals("KEY"))
            err ("KEY expected");
        next();
        if (!token.getStr().toUpperCase().equals("("))
            err ("( expected");
        next();

        String colName = token.getStr();
        Column c = tbl.getColumn(colName);
        if (c == null) err ("Invalid column name: "+colName);
        c.setPrimaryKey(true);
        next();
        while (token.getStr().equals(","))
        {
            next();
            colName = token.getStr();
            c = tbl.getColumn(colName);
            if (c == null) err ("Invalid column name: "+colName);
            c.setPrimaryKey(true);
            next();
        }

        if (!token.getStr().toUpperCase().equals(")"))
            err (") expected");
        next(); // skip the )
    }

    /**
     * Parses UNIQUE (NAME,FOO,BAR) statement
     */
    private void Create_Table_Column_Unique (Table tbl) throws ParseException
    {
        next();
        if (!token.getStr().toUpperCase().equals("("))
            err ("( expected");
        next();
        while (!token.getStr().equals(")"))
        {
            if (!token.getStr().equals(","))
            {
                String colName = token.getStr();
                Column c = tbl.getColumn(colName);
                if (c == null) err ("Invalid column name: "+colName);
                    c.setUnique(true);
            }
            next();
        }
        if (!token.getStr().toUpperCase().equals(")"))
            err (") expected got: " + token.getStr());

        next(); // skip the )
    }
   
    /**
     * Parses FOREIGN KEY (BAR) REFERENCES TABLE (BAR) statement
     */
    private void Create_Table_Column_Foreign (Table tbl) throws ParseException
    {
        next();
        if (!token.getStr().toUpperCase().equals("KEY"))
            err ("KEY expected");
        next();
        if (!token.getStr().toUpperCase().equals("("))
            err ("( expected");
        next();

        ForeignKey fk = new ForeignKey();
        Vector localColumns = new Vector();
        tbl.addForeignKey(fk);

        String colName = token.getStr();
        localColumns.add(colName);
        next();
        while (token.getStr().equals(","))
        {
            next();
            colName = token.getStr();
            localColumns.add(colName);
            next();
        }
        if (!token.getStr().toUpperCase().equals(")"))
            err (") expected");

        next();

        if (!token.getStr().toUpperCase().equals("REFERENCES"))
            err ("REFERENCES expected");

        next();

        fk.setForeignTableName(token.getStr());

        next();

        if (token.getStr().toUpperCase().equals("("))
        {
            next();
            int i=0;
            fk.addReference((String)localColumns.get(i++),token.getStr());
            next();
            while (token.getStr().equals(","))
            {
                next();
                fk.addReference((String)localColumns.get(i++),token.getStr());
                next();
            }
            if (!token.getStr().toUpperCase().equals(")"))
                err (") expected");
            next();
        }
    }

    /**
     * Parse the data definition of the column statement.
     */
    private void Create_Table_Column_Data (Table tbl) throws ParseException
    {
        String columnSize = null;
        String columnPrecision = null;
        String columnDefault = null;
        boolean inEnum = false;


        String columnName = token.getStr();
        next();
        String columnType = token.getStr();

        if (columnName.equals(")") && columnType.equals(";"))
            return;

        next();

        // special case for MySQL ENUM's which are stupid anyway
        // and not properly handled by Torque.
        if (columnType.toUpperCase().equals("ENUM"))
        {
            inEnum = true;
            next(); // skip (
            while (!token.getStr().equals(")"))
            {
                // skip until )
                next();
            }
            while (!token.getStr().equals(","))
            {
                if (token.getStr().toUpperCase().equals("DEFAULT"))
                {
                    next();
                    if (token.getStr().equals("'"))
                    {
                        next();
                    }
                    columnDefault = token.getStr();
                    next();
                    if (token.getStr().equals("'"))
                    {
                        next();
                    }
                }
                // skip until ,
                next();
            }
            next(); // skip ,
            columnType = "VARCHAR";
        }
        else if (token.getStr().toUpperCase().equals("("))
        {
            next();
            columnSize = token.getStr();
            next();
            if (token.getStr().equals (","))
            {
                next();
                columnPrecision = token.getStr();
                next();
            }

            if (!token.getStr().equals (")"))
            {
                err (") expected");
            }
            next();
        }

        Column col = new Column (columnName);
        if (columnPrecision != null)
            columnSize = columnSize + columnPrecision;
        col.setTypeFromString (columnType,columnSize);
        tbl.addColumn (col);
       
        if ( inEnum )
        {
            col.setNotNull(true);
            if (columnDefault != null)
            {
                col.setDefaultValue(columnDefault);
            }
        }
        else
        {
            while (!token.getStr().equals(",") && !token.getStr().equals(")"))
            {
                if (token.getStr().toUpperCase().equals("NOT"))
                {
                    next();
                    if (!token.getStr().toUpperCase().equals("NULL"))
                        err ("NULL expected after NOT");
                    col.setNotNull(true);
                    next();
                }
                else if (token.getStr().toUpperCase().equals("PRIMARY"))
                {
                    next();
                    if (!token.getStr().toUpperCase().equals("KEY"))
                        err ("KEY expected after PRIMARY");
                    col.setPrimaryKey(true);
                    next();
                }
                else if (token.getStr().toUpperCase().equals("UNIQUE"))
                {
                    col.setUnique(true);
                    next();
                }
                else if (token.getStr().toUpperCase().equals("NULL"))
                {
                    col.setNotNull(false);
                    next();
                }
                else if (token.getStr().toUpperCase().equals("AUTO_INCREMENT"))
                {
                    col.setAutoIncrement(true);
                    next();
                }
                else if (token.getStr().toUpperCase().equals("DEFAULT"))
                {
                    next();
                    if (token.getStr().equals("'"))
                    {
                        next();
                    }
                    col.setDefaultValue(token.getStr());
                    next();
                    if (token.getStr().equals("'"))
                    {
                        next();
                    }
                }
            }
            next(); // eat the ,
        }
    }

    /**
     * Execute the parser.
     */
    public AppData execute() throws IOException, ParseException
    {
        count = 0;
        appData = new AppData();
        appDataDB = new Database();
        appData.addDatabase(appDataDB);

        FileReader fr = new FileReader (sqlFile);
        BufferedReader br = new BufferedReader (fr);
        SQLScanner scanner = new SQLScanner(br);

        tokens = scanner.scan();

        br.close();

        while (hasTokens())
        {
            if (token == null)
                next();

            if (token.getStr().toUpperCase().equals("CREATE"))
            {
                Create();
            }
            if (hasTokens())
                next();
        }

        return appData;
    }


    /**
     * Just 4 testing.
     */
    public static void main (String args[]) throws Exception
    {
        SQLToAppData s2a = new SQLToAppData (args[0]);
        AppData ad = s2a.execute();
        System.out.println (ad);
    }
}
TOP

Related Classes of org.apache.turbine.torque.engine.database.transform.SQLToAppData

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.