package co.mwater.clientapp.dbsync; import java.util.ArrayList; import java.util.Arrays; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import co.mwater.clientapp.dbsync.ChangeSet.Table; import android.annotation.TargetApi; import android.database.Cursor; import android.database.MatrixCursor; import android.database.MatrixCursor.RowBuilder; import android.database.sqlite.SQLiteCursor; import android.os.Build; /** * Serializes change sets to and from JSON. * @author Clayton * */ public class ChangeSetJsonSerializer { public JSONObject serialize(ChangeSet changeSet) throws JSONException { JSONObject jroot = new JSONObject(); jroot.put("until", changeSet.getUntil()); // Create tables array JSONArray jtables = new JSONArray(); for (ChangeSet.Table table : changeSet.getTables()) { JSONObject jtable = new JSONObject(); jtable.put("name", table.tableName); jtable.put("upserts", serialize(table.upserts)); jtable.put("deletes", serialize(table.deletes)); jtables.put(jtable); } jroot.put("tables", jtables); return jroot; } public ChangeSet deserialize(JSONObject jroot) throws JSONException { long until = jroot.getLong("until"); ArrayList<Table> tables = new ArrayList<Table>(); JSONArray jtables = jroot.getJSONArray("tables"); for (int t = 0; t < jtables.length(); t++) { JSONObject jtable = jtables.getJSONObject(t); Table table = new Table(); table.tableName = jtable.getString("name"); table.upserts = deserializeCursor(jtable.getJSONObject("upserts")); table.deletes = deserializeCursor(jtable.getJSONObject("deletes")); tables.add(table); } return new ChangeSet(until, tables.toArray(new Table[tables.size()])); } Cursor deserializeCursor(JSONObject jcursor) throws JSONException { JSONArray jcols = jcursor.getJSONArray("cols"); String[] cols = new String[jcols.length()]; for (int i = 0; i < jcols.length(); i++) cols[i] = jcols.getString(i); // Create cursor MatrixCursor cursor = new MatrixCursor(cols); // Add rows JSONArray jrows = jcursor.getJSONArray("rows"); for (int i = 0; i < jrows.length(); i++) { JSONArray jrow = jrows.getJSONArray(i); RowBuilder rowBuilder = cursor.newRow(); for (int col = 0; col < jrow.length(); col++) { Object val = jrow.get(col); if (val.equals(JSONObject.NULL)) rowBuilder.add(null); else rowBuilder.add(jrow.get(col)); } } return cursor; } JSONObject serialize(Cursor cursor) throws JSONException { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) return serializeNew(cursor); return serializeOld((SQLiteCursor)cursor); } @SuppressWarnings("deprecation") JSONObject serializeOld(SQLiteCursor cursor) throws JSONException { JSONArray jcols = new JSONArray(Arrays.asList(cursor.getColumnNames())); JSONArray jrows = new JSONArray(); if (cursor.moveToFirst()) { do { JSONArray jrow = new JSONArray(); for (int i = 0; i < cursor.getColumnCount(); i++) { if (cursor.isNull(i)) jrow.put(null); else if (cursor.isLong(i)) jrow.put(cursor.getLong(i)); else if (cursor.isFloat(i)) jrow.put(cursor.getDouble(i)); else if (cursor.isString(i)) jrow.put(cursor.getString(i)); else throw new IllegalArgumentException("BLOB columns not supported"); } jrows.put(jrow); } while (cursor.moveToNext()); } JSONObject jcursor = new JSONObject(); jcursor.put("cols", jcols); jcursor.put("rows", jrows); return jcursor; } @TargetApi(11) JSONObject serializeNew(Cursor cursor) throws JSONException { JSONArray jcols = new JSONArray(Arrays.asList(cursor.getColumnNames())); JSONArray jrows = new JSONArray(); if (cursor.moveToFirst()) { do { JSONArray jrow = new JSONArray(); for (int i = 0; i < cursor.getColumnCount(); i++) { switch (cursor.getType(i)) { case Cursor.FIELD_TYPE_NULL: jrow.put(null); break; case Cursor.FIELD_TYPE_INTEGER: jrow.put(cursor.getLong(i)); break; case Cursor.FIELD_TYPE_FLOAT: jrow.put(cursor.getDouble(i)); break; case Cursor.FIELD_TYPE_STRING: jrow.put(cursor.getString(i)); break; case Cursor.FIELD_TYPE_BLOB: throw new IllegalArgumentException("BLOB columns not supported"); } } jrows.put(jrow); } while (cursor.moveToNext()); } JSONObject jcursor = new JSONObject(); jcursor.put("cols", jcols); jcursor.put("rows", jrows); return jcursor; } }