libGdx平台特定代码

时间:2014-09-09 11:34:03

标签: java eclipse gwt libgdx

我需要创建特定代码以从基于 libGdx 的项目访问 Derby DB FoundationDB SQL解析器,并使用不同的实现在应用程序的桌面 WebGL 版本之间。桌面应用程序可以访问SQL解析器并可以在本地连接到DB,其他WebGL版本使用GWT RPC服务通过客户端 - 服务器机制访问数据。是否有可能以某种方式实现这种类型的功能?我还想讨论玩具代码的实现,如果可能的话:) :( / p>)

这里是当前(不在WebGL项目上工作)QueryManager代码,存储在主项目文件夹中:

/**
 * 
 */
package it.viscioletti.sqlapprentice.sql;

import it.viscioletti.sqlapprentice.data.FieldDescription;
import it.viscioletti.sqlapprentice.data.FieldType;
import it.viscioletti.sqlapprentice.data.Row;
import it.viscioletti.sqlapprentice.data.TableDescription;
import it.viscioletti.sqlapprentice.gui.table.TableGui;
import it.viscioletti.sqlapprentice.utils.Constants;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;
import java.util.Vector;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Application.ApplicationType;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.foundationdb.sql.StandardException;
import com.foundationdb.sql.parser.SQLParser;
import com.foundationdb.sql.parser.StatementNode;

/**
 * @author Federico
 *
 */
public class QueryManager {

    /* Member Variables: */
    private float tablesAreaW, tablesAreaH, textAreaH;
    private Connection conn;
    private ResultSet rs;
    private Statement stmt;
    private String sql;
    private TableGui resultTable;


    /* Constructors: */
    /** @throws SQLException */
    public QueryManager(String sql) {
        // stores the SQL String
        this.sql = sql.trim();

        // sets sizes used by the QueryManager
        float w = Gdx.graphics.getWidth(), h = Gdx.graphics.getHeight();
        tablesAreaW = (w / 10) * 7;
        tablesAreaH = (h / 10) * 6;
        textAreaH = h - (h / 10) - tablesAreaH;
    }

    /* Methods: */
    /** Checks the query sintax using Derby DBMS
     * @throws SQLException */
    public void checkSintax() throws SQLException {
        // connects to the DB
        connect();

        /* tries to execute the query. 
         * If is all fine, this method doesn't return anything,
         * otherwise it will throws a SQLException to the calling class */
        String[] sqlArray = sql.split(" ");
        // checks if is an INSERT INTO query type and then executes
        if(sqlArray[0].toUpperCase().equals("INSERT")) {
            System.out.println("Eseguo la INSERT (QM)"); // TODO remove later
            stmt.executeUpdate(sql); //TODO remove later
        } else
            stmt.executeQuery(sql);
    }

    /** Connects to the DB
     * @throws SQLException */
    private void connect() throws SQLException {
        // gets the connection to Derby DB
        conn = DriverManager.getConnection( Constants.CONNECTION_URL );
        // creates the statement for the connection
        stmt = conn.createStatement();
    }

    /** Executes the query and returns a TableGui object
     * @return The TableGui object result of the query
     * @throws SQLException */
    public TableGui getResultTable() throws SQLException {
        // connects to the DB
        connect();

        // gets the result set object of the executed query
        rs = stmt.executeQuery(sql);
        ResultSetMetaData rsmd = rs.getMetaData();

        Vector<FieldDescription> fieldDescriptions = new Vector<FieldDescription>();
        // stores each column name of the table
        String[] fieldNames = new String[rsmd.getColumnCount()];
        FieldType[] fieldTypes = new FieldType[rsmd.getColumnCount()];

        int idPos = -1;

        // the column numeration into the ResultsSetMetaData goes from 1 to column number
        for (int i = 1; i <= rsmd.getColumnCount(); i++) {

            // stores the position of SQLAPPRENTICEID, only if exists
            if(rsmd.getColumnName(i).trim().equals(Constants.TABLE_ID)) 
                idPos = i - 1;

            // gets the field name and adds it to the field names array
            fieldNames[i-1] = rsmd.getColumnName(i).trim();

            FieldType ft;

            // gets the column type and adds it to the field types array
            switch(rsmd.getColumnType(i)) {
                case Types.CHAR:
                case Types.VARCHAR:
                    ft = FieldType.CHAR;
                    break;
                case Types.INTEGER:
                    ft = FieldType.INTEGER;
                    break;
                default:
                    ft = null;
                    assert false;
            } 

            // adds the field type to the array
            fieldTypes[i - 1] = ft;

            // if its not a SQLAPPRENTICETABLEID
            if(!rsmd.getColumnName(i).trim().equals(Constants.TABLE_ID)) {
                // creates a new FieldDescription with appropriates column names and field types
                FieldDescription fd = new FieldDescription(fieldNames[i-1], ft);
                // adds it to the vector
                fieldDescriptions.add(fd);
            }
        }       

        // creates the TableDescription for the given table
        TableDescription td = new TableDescription(rsmd.getTableName(1), fieldDescriptions);

        TextureAtlas atlas = new TextureAtlas("ui/atlas.pack");
        Skin skin = new Skin(Gdx.files.internal("ui/applicationScreenSkin.json"), atlas);

        resultTable = new TableGui(skin, td);

        // sets bounds of the new table created
        resultTable.setBounds(tablesAreaW / 2, tablesAreaH, tablesAreaW, tablesAreaH);
        // draws debug lines
        resultTable.debug(); //TODO remove later

        resultTable.addTableHeader();

        // size of values array
        int valSize = (idPos == -1) ? fieldNames.length : fieldNames.length - 1;

        // stores the values of each table row
        Object[] values = new Object[valSize];

        // retrieves automatically the result set content
        while (rs.next()) {
            // uses a second index for values array because if the 
            // resultset has the id field in it, it's bigger than values
            int j = 0, 
            // initialize id variable on every iteration
                id = 0;

            for (int i = 0; i < fieldNames.length; i++) {

                if(idPos != i) {
                    switch(fieldTypes[i]) {
                        case CHAR:
                            // trims the string returned because of the white spaces
                            values[j] = rs.getString(i + 1).trim();
                            break;
                        case INTEGER:
                            values[j] = rs.getInt(i + 1);
                            break;
                        default: assert false;
                    }
                    j++;
                } else 
                    id = rs.getInt(i + 1);
            }
            resultTable.addRow(new Row(id, td, values));
        }
        resultTable.setBounds((tablesAreaW / 2) - (resultTable.getTableWidth() / 2), 
                textAreaH + (tablesAreaH / 2) - (resultTable.getTableHeight() / 2), 
                resultTable.getTableWidth(), resultTable.getTableHeight());

        return resultTable;
    }

    /** Checks if the device ha 
     * Parses the query and returns its description
     * @return the QueryDescription */
    public QueryDescription dispatchParse() {
        if(Gdx.app.getType() == ApplicationType.Desktop) {
            System.out.println();
            try {
                return localParse();
            } catch (StandardException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        } else if(Gdx.app.getType() == ApplicationType.WebGL) {
            System.out.println();
        }
        return null;
    }

    /** Parses locally the query and returns its description
     * @return the QueryDescription
     * @throws StandardException */
    public QueryDescription localParse() throws StandardException {

        // creates a new SQL parser to parse the query
        SQLParser parser = new SQLParser();

        // parses the query
        StatementNode stmt = parser.parseStatement(sql);

        // using the visitor design pattern to explore the query tree
        QueryVisitor qv = new QueryVisitor();

        stmt.accept(qv);

        // creates the query description
        return qv.createDescription();
    }

    /** Parses the query server-side and returns its description
     * @return the QueryDescription */
    public QueryDescription serverParse() {
        return null;
    }
}

1 个答案:

答案 0 :(得分:0)

也许我找到了问题的解决方案。在我的例子中,最好的选择是在根项目中创建一个puppet类,然后覆盖在同一个包中创建相同的类,进入特定于平台的项目,实现内部的不同行为。仅作为一个例子:

/* The puppet class into the root project: */
public class DBManager implements DBManagerInterface {
    public DBManager() {
    }

    @Override
    public void executeQuery(String sql) {
    }
}


/* the desktop project: */
public class DBManager implements DBManagerInterface {
    public DBManager() {
    }

    @Override
    public void executeQuery(String sql) {
        /* insert here the code to execute a query 
           locally on the desktop application */
    }
}

/* the WebGL project: */
public class DBManager implements DBManagerInterface {
    public DBManager() {
    }

    @Override
    public void executeQuery(String sql) {
        /* insert here the code to execute a query 
           using a client-server interaction via GWT RPC */
    }
}