libGdx platform specific code

北城以北 提交于 2019-12-13 01:31:44

问题


I need to create specific code to access a Derby DB and the FoundationDB SQL parser from a libGdx based project, with a different implementation between the Desktop and the WebGL version of the application. The Desktop application can access the SQL parser and can connect to the DB locally, otherwhise the WebGL version uses the GWT RPC service to access data via a client-server mechanism. Is it possible to implement in a certain way this type of functionality? I would like also to discuss over a toy code implementation, if it's possible :)

Here's the current (not working on the WebGL project) QueryManager code, stored in the main project folder:

/**
 * 
 */
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:


Maybe I've found a solution to the problem. In my case the best option is to create a puppet class in the root project, and then overwrite creating the same class, in the same package, into the platform-specific projects, implementing the different behavior inside. Just as an example:

/* 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 */
    }
}


来源:https://stackoverflow.com/questions/25743610/libgdx-platform-specific-code

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!