package org.geogebra.common.move.ggtapi.models;
import java.util.ArrayList;
import java.util.List;
import org.geogebra.common.move.ggtapi.models.Material.MaterialType;
import org.geogebra.common.move.ggtapi.models.json.JSONArray;
import org.geogebra.common.move.ggtapi.models.json.JSONException;
import org.geogebra.common.move.ggtapi.models.json.JSONObject;
import org.geogebra.common.move.ggtapi.models.json.JSONTokener;
import org.geogebra.common.util.debug.Log;
/**
* JSON parser for MAT reply objects
*
*/
public class JSONParserGGT {
/**
* Parser instance
*/
public static final JSONParserGGT prototype = new JSONParserGGT();
/**
* @param obj
* parsed material
* @return material object
*/
public Material toMaterial(JSONObject obj) {
return toMaterial(obj, false);
}
/**
* @param obj
* parsed data
* @param setLocalValues
* whether to initialiye sznc timestamp and local ID
* @return material
*/
public Material toMaterial(JSONObject obj, boolean setLocalValues) {
Material.MaterialType type = MaterialType.ggb;
if (getString(obj, "type").length() > 0) {
try {
type = MaterialType.valueOf(getString(obj, "type"));
} catch (Throwable t) {
Log.error("Unknown material type:" + getString(obj, "type"));
}
}
int ID = getInt(obj, "id", -1);
Material material = new Material(ID, type);
material.setTitle(getString(obj, "title"));
material.setDescription(getString(obj, "description"));
if (!"".equals(getString(obj, "timestamp"))) {
material.setTimestamp(Long.parseLong(getString(obj, "timestamp")));
}
if (!"".equals(getString(obj, "modified"))) {
material.setModified(Long.parseLong(getString(obj, "modified")));
}
if (!"".equals(getString(obj, "syncstamp"))) {
material.setSyncStamp(Long.parseLong(getString(obj, "syncstamp")));
}
material.setVisibility(getString(obj, "visibility"));
material.setSharingKey(getString(obj, "sharing_key"));
material.setAuthor(getString(obj, "author"));
material.setAuthorId(getInt(obj, "author_id", -1));
material.setURL(getString(obj, "url"));
material.setURLdirect(getString(obj, "url_direct"));
material.setThumbnailUrl(getString(obj, "thumbnail"));
material.setPreviewURL(getString(obj, "previewUrl"));
material.setLanguage(getString(obj, "language"));
material.setFeatured(Boolean.parseBoolean(getString(obj, "featured")));
material.setLikes(getInt(obj, "likes", -1));
material.setHeight(getInt(obj, "height", 600));
material.setWidth(getInt(obj, "width", 800));
material.setInstructionsPost(getString(obj, "instructions_post"));
material.setInstructionsPre(getString(obj, "instructions_pre"));
material.setShowToolbar(getBoolean(obj, "toolbar", false));
material.setShowMenu(getBoolean(obj, "menubar", false));
material.setShowInputbar(getBoolean(obj, "inputbar", false));
material.setFavorite(getBoolean(obj, "favorite", false));
material.setShiftDragZoom(getBoolean(obj, "shiftdragzoom", false));
material.setShowResetIcon(getBoolean(obj, "reseticon", false));
material.setBase64(getString(obj, "ggbBase64"));
material.setDeleted(getBoolean(obj, "deleted", false));
material.setFromAnotherDevice(
getBoolean(obj, "from_another_device", false));
material.setIs3d(getStringBoolean(obj, "is3d", false));
material.setSpreadsheet(getStringBoolean(obj, "spreadsheet", false));
material.setCas(getStringBoolean(obj, "cas", false));
material.setGraphics2(getStringBoolean(obj, "graphics2", false));
material.setConstprot(getStringBoolean(obj, "constprot", false));
material.setPropcalc(getStringBoolean(obj, "propcalc", false));
material.setDataanalysis(getStringBoolean(obj, "dataanalysis", false));
material.setFuncinsp(getStringBoolean(obj, "funcinsp", false));
material.setMacro(getStringBoolean(obj, "macro", false));
material.setElemcntApplet(getInt(obj, "elemcnt_applet", -1));
material.setViewerID(getInt(obj, "viewerID", -1));
if (setLocalValues) {
material.setLocalID(getInt(obj, "localID", -1));
material.setAutosaveTimestamp(getInt(obj, "autoSaveTimestamp", 0));
}
return material;
}
private static boolean getBoolean(JSONObject obj, String string,
boolean def) {
if (!obj.has(string)) {
return def;
}
Object str = null;
try {
str = obj.get(string);
} catch (Exception e) {
// ignore
}
if (str == null || "".equals(str)) {
return def;
}
return Boolean.parseBoolean(str.toString());
}
private static String getString(JSONObject obj, String string) {
if (!obj.has(string)) {
return "";
}
Object str = null;
try {
str = obj.get(string);
} catch (Exception e) {
// ignore
}
if (str == null) {
return "";
}
return str.toString();
}
private static int getInt(JSONObject obj, String string, int def) {
if (!obj.has(string)) {
return def;
}
Object str = null;
try {
str = obj.get(string);
} catch (Exception e) {
// ignore
}
if (str == null || "".equals(str)) {
return def;
}
return Integer.parseInt(str.toString());
}
private static long getLong(JSONObject obj, String string, long def) {
if (!obj.has(string)) {
return def;
}
Object str = null;
try {
str = obj.get(string);
} catch (Exception e) {
// ignore
}
if (str == null || "".equals(str)) {
return def;
}
return Long.parseLong(str.toString());
}
private static boolean getStringBoolean(JSONObject obj, String name,
boolean def) {
if (!obj.has(name)) {
return def;
}
String value = null;
try {
value = obj.getString(name);
if ("".equals(value)) {
return def;
}
} catch (Exception e) {
// ignore
}
return "0".equals(value) ? false : true;
}
private static void addEvent(JSONObject object,
ArrayList<SyncEvent> events) {
SyncEvent se = new SyncEvent(getInt(object, "id", 0),
getLong(object, "ts", 0));
try {
if (object.has("deleted")
&& object.get("deleted") instanceof String) {
se.setDelete(true);
}
} catch (Exception e) {
Log.debug("error parsing deletion");
}
try {
if (object.has("favorite")
&& getBoolean(object, "favorite", false)) {
se.setFavorite(true);
}
} catch (Exception e) {
Log.debug("error parsing favorite");
}
try {
if (object.has("unfavorited")
&& object.get("unfavorited") instanceof String) {
se.setUnfavorite(true);
}
} catch (Exception e) {
Log.debug("error parsing unfavorite");
}
events.add(se);
}
/**
* @param events
* output array of events
* @param items
* parsed sync items
* @throws JSONException
* for malformed JSON
*/
public void addEvents(ArrayList<SyncEvent> events, Object items)
throws JSONException {
if (items instanceof JSONArray) {
for (int i = 0; i < ((JSONArray) items).length(); i++) {
addEvent((JSONObject) ((JSONArray) items).get(i), events);
}
} else if (items instanceof JSONObject) {
addEvent((JSONObject) items, events);
}
}
/**
* @param response
* JSON list of materials
* @param result
* output array
* @return book metadata
*/
public ArrayList<Chapter> parseResponse(String response,
ArrayList<Material> result) {
Object materialsArray = null;
ArrayList<Chapter> meta = null;
if (response != null) {
JSONObject responseObject = new JSONObject();
try {
JSONTokener tokener = new JSONTokener(response);
responseObject = new JSONObject(tokener);
if (responseObject.has("responses")) {
JSONObject materialsObject = (JSONObject) ((JSONObject) responseObject
.get("responses")).get("response");
if (materialsObject.has(("meta"))) {
String content = ((JSONObject) materialsObject
.get("meta")).get("-content").toString();
meta = parseMeta(content);
}
if (materialsObject.has(("item"))) {
materialsArray = materialsObject.get("item");
} else {
// List is empty
}
} else if (responseObject.has("error")) {
// Show error
}
} catch (Throwable t) {
Log.debug(t.getMessage());
Log.debug("'" + response + "'");
}
} else {
// Response String was null
}
// 0 materials
if (materialsArray == null) {
return meta;
}
// >1 materials
if (materialsArray instanceof JSONArray) {
for (int i = 0; i < ((JSONArray) materialsArray).length(); i++) {
Object obj;
try {
obj = ((JSONArray) materialsArray).get(i);
addToArray(result, obj);
} catch (Exception e) {
Log.debug("problem adding material " + i);
}
}
}
// 1 material
else if (materialsArray instanceof JSONObject) {
addToArray(result, materialsArray);
}
return meta;
}
private static ArrayList<Chapter> parseMeta(String s) {
ArrayList<Chapter> ret = new ArrayList<Chapter>();
try {
JSONTokener tokener = new JSONTokener(s);
JSONArray parsed = new JSONArray(tokener);
for (int i = 0; i < parsed.length(); i++) {
String title = ((JSONObject) parsed.get(i)).get("title")
.toString();
JSONArray materials = (JSONArray) ((JSONObject) parsed.get(i))
.get("materials");
int[] mats = new int[materials.length()];
for (int m = 0; m < materials.length(); m++) {
mats[m] = (int) ((Double) materials.get(m)).doubleValue();
}
ret.add(new Chapter(title, mats));
}
} catch (Throwable t) {
// ignore
}
return ret;
}
private void addToArray(List<Material> result, Object obj) {
if (!(obj instanceof JSONObject)) {
return;
}
result.add(toMaterial(((JSONObject) obj)));
}
/**
* @param item
* material JSON string
* @return parsed material
*/
public static Material parseMaterial(String item) {
return parseMaterial(item, false);
}
/**
* @param item
* material JSON string
* @param setLocalValues
* whether to initialize sync timestamp and local ID
* @return parsed material
*/
public static Material parseMaterial(String item, boolean setLocalValues) {
JSONObject mat = null;
try {
JSONTokener tok = new JSONTokener(item);
mat = new JSONObject(tok);
} catch (Throwable t) {
t.printStackTrace();
}
if (mat == null) {
return null;
}
return prototype.toMaterial(mat, setLocalValues);
}
}