package com.uservoice.uservoicesdk.model; import android.annotation.SuppressLint; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.text.Html; import com.uservoice.uservoicesdk.Config; import com.uservoice.uservoicesdk.Session; import com.uservoice.uservoicesdk.rest.RestMethod; import com.uservoice.uservoicesdk.rest.RestTask; import com.uservoice.uservoicesdk.rest.RestTaskCallback; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Map; public class BaseModel { protected int id; public static <T extends BaseModel> T load(SharedPreferences prefs, String prefsKey, String rootKey, Class<T> modelClass) { try { JSONObject container = new JSONObject(prefs.getString(prefsKey, "{}")); return deserializeObject(container, rootKey, modelClass); } catch (JSONException e) { return null; } } protected static Session getSession() { return Session.getInstance(); } protected static Config getConfig() { return getSession().getConfig(); } protected static ClientConfig getClientConfig() { return getSession().getClientConfig(); } protected static String apiPath(String path, Object... args) { return "/api/v1" + String.format(path, args); } protected static RestTask doGet(String path, RestTaskCallback callback) { return doGet(path, null, callback); } protected static RestTask doPost(String path, RestTaskCallback callback) { return doPost(path, null, callback); } protected static RestTask doDelete(String path, RestTaskCallback callback) { return doDelete(path, null, callback); } protected static RestTask doPut(String path, RestTaskCallback callback) { return doPut(path, null, callback); } protected static RestTask doGet(String path, Map<String, String> params, RestTaskCallback callback) { RestTask task = new RestTask(RestMethod.GET, path, params, callback); task.execute(); return task; } protected static RestTask doPost(String path, Map<String, String> params, RestTaskCallback callback) { RestTask task = new RestTask(RestMethod.POST, path, params, callback); task.execute(); return task; } protected static RestTask doDelete(String path, Map<String, String> params, RestTaskCallback callback) { RestTask task = new RestTask(RestMethod.DELETE, path, params, callback); task.execute(); return task; } protected static RestTask doPut(String path, Map<String, String> params, RestTaskCallback callback) { RestTask task = new RestTask(RestMethod.PUT, path, params, callback); task.execute(); return task; } protected static <T extends BaseModel> List<T> deserializeList(JSONObject object, String rootKey, Class<T> modelClass) throws JSONException { if (!object.has(rootKey)) return null; try { JSONArray array = object.getJSONArray(rootKey); List<T> list = new ArrayList<T>(array.length()); for (int i = 0; i < array.length(); i++) { T model = modelClass.newInstance(); model.load(array.getJSONObject(i)); list.add(model); } return list; } catch (IllegalArgumentException e) { throw new JSONException("Reflection failed trying to call load on " + modelClass + " " + e.getMessage()); } catch (IllegalAccessException e) { throw new JSONException("Reflection failed trying to call load on " + modelClass + " " + e.getMessage()); } catch (InstantiationException e) { throw new JSONException("Reflection failed trying to instantiate " + modelClass + " " + e.getMessage()); } } protected static <T extends BaseModel> T deserializeObject(JSONObject object, String rootKey, Class<T> modelClass) throws JSONException { if (!object.has(rootKey)) return null; try { JSONObject singleObject = object.getJSONObject(rootKey); T model = modelClass.newInstance(); model.load(singleObject); return modelClass.cast(model); } catch (JSONException e) { throw new JSONException("JSON deserialization failure for " + modelClass + " " + e.getMessage() + " JSON: " + object.toString()); } catch (IllegalArgumentException e) { throw new JSONException("Reflection failed trying to call load on " + modelClass + " " + e.getMessage()); } catch (IllegalAccessException e) { throw new JSONException("Reflection failed trying to call load on " + modelClass + " " + e.getMessage()); } catch (InstantiationException e) { throw new JSONException("Reflection failed trying to instantiate " + modelClass + " " + e.getMessage()); } } protected static List<BaseModel> deserializeHeterogenousList(JSONObject object, String rootKey) throws JSONException { if (!object.has(rootKey)) return null; JSONArray array = object.getJSONArray(rootKey); List<BaseModel> list = new ArrayList<BaseModel>(array.length()); for (int i = 0; i < array.length(); i++) { JSONObject o = array.getJSONObject(i); String type = o.getString("type"); BaseModel model; if (type.equals("suggestion")) model = new Suggestion(); else if (type.equals("article")) model = new Article(); else continue; model.load(o); list.add(model); } return list; } public void load(JSONObject object) throws JSONException { id = object.getInt("id"); } public int getId() { return id; } public boolean persist(SharedPreferences prefs, String prefsKey, String rootKey) { JSONObject object = new JSONObject(); JSONObject container = new JSONObject(); try { save(object); container.put(rootKey, object); } catch (JSONException e) { return false; } Editor edit = prefs.edit(); edit.putString(prefsKey, container.toString()); return edit.commit(); } public void save(JSONObject object) throws JSONException { object.put("id", id); } protected String getString(JSONObject object, String key) throws JSONException { return object.isNull(key) ? null : Html.fromHtml(object.getString(key)).toString().trim(); } protected String getHtml(JSONObject object, String key) throws JSONException { return object.isNull(key) ? null : object.getString(key); } @SuppressLint("SimpleDateFormat") protected Date getDate(JSONObject object, String key) throws JSONException { String dateString = getString(object, key); SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss Z"); try { return format.parse(dateString); } catch (ParseException e1) { throw new JSONException("Could not parse date: " + dateString); } } }