package com.rapidftr.model; import android.os.Parcel; import android.os.Parcelable; import com.google.common.collect.Lists; import com.rapidftr.RapidFtrApplication; import com.rapidftr.database.Database; import com.rapidftr.utils.RapidFtrDateTime; import org.json.JSONException; import org.json.JSONObject; import java.util.ArrayList; import java.util.List; public class History extends JSONObject implements Parcelable { public static final String HISTORIES = "histories"; public static final String USER_NAME = "user_name"; public static final String USER_ORGANISATION = "user_organisation"; public static final String DATETIME = "datetime"; public static final String CHANGES = "changes"; public static final String FROM = "from"; public static final String TO = "to"; public static final String CREATED = "created"; public History(String jsonSource) throws JSONException { super(jsonSource); } public History() {} @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel parcel, int flags) { parcel.writeString(this.toString()); } public static History buildHistoryBetween(RapidFtrApplication rapidFtrApplication, BaseModel originalModel, BaseModel updatedModel) throws JSONException { History history = new History(); addChangesForOldValues(originalModel, updatedModel, history); addChangesForNewValues(originalModel, updatedModel, history); User currentUser = rapidFtrApplication.getCurrentUser(); String organisation = currentUser.getOrganisation(); String userName = currentUser.getUserName(); history.put(History.USER_NAME, userName); history.put(History.USER_ORGANISATION, organisation); history.put(History.DATETIME, RapidFtrDateTime.now().defaultFormat()); return history; } private static void addChangesForOldValues(BaseModel originalModel, BaseModel updatedModel, History history) throws JSONException { List<String> updatedKeys = Lists.newArrayList(updatedModel.keys()); for (String key : (List<String>) Lists.newArrayList(originalModel.keys())) { boolean valueChanged = updatedKeys.contains(key) && !originalModel.get(key).equals(updatedModel.get(key)); if(shouldRecordHistoryForKey(key) && valueChanged) { history.addChangeForValues(key, originalModel.get(key), updatedModel.get(key)); } boolean valueDeleted = !updatedKeys.contains(key) && !originalModel.get(key).equals(""); if(shouldRecordHistoryForKey(key) && valueDeleted) { history.addChangeForValues(key, originalModel.get(key), ""); } } } private static void addChangesForNewValues(BaseModel originalModel, BaseModel updatedModel, History history) throws JSONException { List<String> originalKeys = Lists.newArrayList(originalModel.keys()); for (String key : (List<String>) Lists.newArrayList(updatedModel.keys())) { boolean newValue = !originalKeys.contains(key) && !updatedModel.get(key).equals(""); if(shouldRecordHistoryForKey(key) && newValue) { history.addChangeForValues(key, "", updatedModel.get(key)); } } } private static boolean shouldRecordHistoryForKey(String key) { List<String> keysToIgnore = new ArrayList<String>(); keysToIgnore.add(Database.ChildTableColumn.synced.getColumnName()); keysToIgnore.add(Database.ChildTableColumn.last_synced_at.getColumnName()); keysToIgnore.add(Database.ChildTableColumn.last_updated_at.getColumnName()); keysToIgnore.add(History.HISTORIES); return !keysToIgnore.contains(key); } private void addChangeForValues(String key, Object oldValue, Object newValue) throws JSONException { JSONObject jsonObject = new JSONObject(); jsonObject.put(FROM, oldValue); jsonObject.put(TO, newValue); addChange(key, jsonObject); } public void addChange(String key, JSONObject changes) throws JSONException { JSONObject jsonChanges = new JSONObject(); if(this.has(CHANGES)) { jsonChanges = (JSONObject) this.get(CHANGES); } jsonChanges.put(key, changes); this.put(CHANGES, jsonChanges); } public static History buildCreationHistory(BaseModel model, User user) throws JSONException { History creationHistory = new History(); creationHistory.put(USER_NAME, user.getUserName()); creationHistory.put(USER_ORGANISATION, user.getOrganisation()); creationHistory.put(DATETIME, RapidFtrDateTime.now()); JSONObject createdChange = new JSONObject().put(CREATED, RapidFtrDateTime.now().toString()); JSONObject changes = new JSONObject(); changes.put(model.getClass().getSimpleName().toLowerCase(), createdChange); creationHistory.put(CHANGES, changes); return creationHistory; } }