package se.ginkou.interfaceio;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.List;
import java.util.TreeMap;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import se.ginkou.Debug;
import se.ginkou.Transaction;
import se.ginkou.database.Database;
import se.ginkou.database.SQLiteDB;
public class DataTablesInterface {
TreeMap<String, String> commands;
Database db;
public DataTablesInterface(final String inString) {
String decodedString = "";
try {
decodedString = URLDecoder.decode(inString, "utf-8");
} catch (UnsupportedEncodingException e) {throw new IllegalStateException("The URLDecoder could not handle utf-8");}
String[] rawCommands = decodedString.split("&");
commands = new TreeMap<String,String>();
for (String aCommand : rawCommands) {
String[] commandParts = aCommand.split("=");
assert(commandParts.length == 2);
commands.put(commandParts[0], (commandParts.length > 1 ? commandParts[1] : null));
}
db = SQLiteDB.getDB();
Debug.out(commands.toString());
}
public String getResponse() {
final String[] columns = {"id", "accountID", "date", "notice", "amount"};
final String sqlTable = "transactions";
/*
* Paging
*/
String sqlLimit = "";
if ( commands.containsKey("iDisplayStart") && !commands.get("iDisplayLength").equals("-1") )
{
sqlLimit = " LIMIT " + commands.get("iDisplayLength") + " OFFSET " + commands.get("iDisplayStart");
}
/*
* Ordering
*/
String sqlOrder = "";
if ( commands.containsKey("iSortCol_0") ) {
sqlOrder = " ORDER BY ";
for ( int i = 0 ; i < Integer.parseInt(commands.get("iSortingCols")) ; i++ )
{
if ( commands.get( "bSortable_" + Integer.parseInt(commands.get("iSortCol_" + i)) ).equals("true") ) {
sqlOrder += "`" + columns[ Integer.parseInt( commands.get( "iSortCol_" + i) ) ] + "` " + commands.get("sSortDir_" + i) + ", ";
}
}
sqlOrder = sqlOrder.substring(0, sqlOrder.length() - 2);
if ( sqlOrder.equals(" ORDER BY ") ) {
sqlOrder = "";
}
}
/*
* Filtering
* NOTE this does not match the built-in DataTables filtering which does it
* word by word on any field. It's possible to do here, but concerned about efficiency
* on very large tables, and MySQL's regex functionality is very limited
*/
String sqlWhere = "";
if ( commands.containsKey("sSearch") && commands.get("sSearch") != null )
{
sqlWhere = "WHERE (";
for ( int i = 0 ; i < columns.length ; i++ ) {
sqlWhere += "`" + columns[i] + "` LIKE '%" + commands.get("sSearch") + "%' OR ";
}
sqlWhere = sqlWhere.substring(0, sqlWhere.length() - 4);
sqlWhere += ")";
}
/* Individual column filtering */
for ( int i = 0 ; i < columns.length ; i++ ){
if ( commands.containsKey("bSearchable_" + i) && commands.get("bSearchable_" + i).equals("true") && commands.get("sSearch_" + i) != null ) {
if ( sqlWhere == "" ) {
sqlWhere = "WHERE ";
} else {
sqlWhere += " AND ";
}
sqlWhere += "`" + columns[i] + "` LIKE '%" + commands.get("sSearch_" + i) + "%' ";
}
}
/*
* SQL queries
* Get data to display
*/
StringBuilder sqlColumns = new StringBuilder(9 * columns.length);
for (String aColumn : columns) {
sqlColumns.append(aColumn).append(", ");
}
sqlColumns.setLength(sqlColumns.length() - 2);
String baseQuery = "SELECT " + sqlColumns.toString() +
" FROM " + sqlTable + " " + sqlWhere + sqlOrder;
String pagedQuery = baseQuery + sqlLimit;
List<Transaction> transactions = db.getTransactions(pagedQuery);
/* Data set length after filtering */
int iFilteredTotal = db.sizeOfResult(baseQuery);
JsonParser jParser = new JsonParser();
JsonArray jsonTransactions = new JsonArray();
for (Transaction t : transactions) {
jsonTransactions.add(jParser.parse(t.toJSON()));
}
JsonObject output = new JsonObject();
output.addProperty("sEcho", commands.get("sEcho"));
output.addProperty("iTotalRecords", db.sizeTransactions());
output.addProperty("iTotalDisplayRecords", iFilteredTotal);
output.add("aaData", jsonTransactions);
return output.toString();
}
public static void main(String[] args) {
DataTablesInterface DT = new DataTablesInterface("sEcho=1&iColumns=4&sColumns=&iDisplayStart=0&iDisplayLength=10&mDataProp_0=account&mDataProp_1=date&mDataProp_2=notice&mDataProp_3=sum&sSearch=&bRegex=false&sSearch_0=&bRegex_0=false&bSearchable_0=true&sSearch_1=&bRegex_1=false&bSearchable_1=true&sSearch_2=&bRegex_2=false&bSearchable_2=true&sSearch_3=&bRegex_3=false&bSearchable_3=true&iSortCol_0=0&sSortDir_0=asc&iSortingCols=1&bSortable_0=true&bSortable_1=true&bSortable_2=true&bSortable_3=true");
System.out.println(DT.getResponse());
}
}