| package org.wordpress.android.ui.stats.models; |
| |
| import org.json.JSONArray; |
| import org.json.JSONException; |
| import org.json.JSONObject; |
| import org.wordpress.android.util.AppLog; |
| |
| import java.io.Serializable; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collections; |
| import java.util.Comparator; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.LinkedList; |
| import java.util.List; |
| |
| public class PostViewsModel implements Serializable { |
| private String mOriginalResponse; |
| |
| private int mHighestMonth, mHighestDayAverage, mHighestWeekAverage; |
| private String mDate; |
| private VisitModel[] mDayViews; //Used to build the graph |
| private List<Year> mYears; |
| private List<Year> mAverages; |
| private List<Week> mWeeks; |
| |
| public String getDate() { |
| return mDate; |
| } |
| |
| public String getOriginalResponse() { |
| return mOriginalResponse; |
| } |
| |
| public VisitModel[] getDayViews() { |
| return mDayViews; |
| } |
| |
| public int getHighestMonth() { |
| return mHighestMonth; |
| } |
| |
| public int getHighestDayAverage() { |
| return mHighestDayAverage; |
| } |
| |
| public int getHighestWeekAverage() { |
| return mHighestWeekAverage; |
| } |
| |
| public List<Year> getYears() { |
| return mYears; |
| } |
| |
| public List<Year> getAverages() { |
| return mAverages; |
| } |
| |
| public List<Week> getWeeks() { |
| return mWeeks; |
| } |
| |
| |
| public PostViewsModel(String response) throws JSONException { |
| this.mOriginalResponse = response; |
| JSONObject responseObj = new JSONObject(response); |
| parseResponseObject(responseObj); |
| } |
| |
| public PostViewsModel(JSONObject response) throws JSONException { |
| if (response == null) { |
| return; |
| } |
| this.mOriginalResponse = response.toString(); |
| parseResponseObject(response); |
| } |
| |
| private void parseResponseObject(JSONObject response) throws JSONException { |
| |
| mDate = response.getString("date"); |
| mHighestDayAverage = response.getInt("highest_day_average"); |
| mHighestWeekAverage = response.getInt("highest_week_average"); |
| mHighestMonth = response.getInt("highest_month"); |
| mYears = new LinkedList<>(); |
| mAverages = new LinkedList<>(); |
| mWeeks = new LinkedList<>(); |
| |
| JSONArray dataJSON = response.getJSONArray("data"); |
| if (dataJSON != null) { |
| // Read the position/index of each field in the response |
| JSONArray fieldsJSON = response.getJSONArray("fields"); |
| HashMap<String, Integer> fieldColumnsMapping; |
| try { |
| fieldColumnsMapping = new HashMap<>(2); |
| for (int i = 0; i < fieldsJSON.length(); i++) { |
| final String field = fieldsJSON.getString(i); |
| fieldColumnsMapping.put(field, i); |
| } |
| } catch (JSONException e) { |
| AppLog.e(AppLog.T.STATS, "Cannot read the fields indexes from the JSON response", e); |
| throw e; |
| } |
| |
| VisitModel[] visitModels = new VisitModel[dataJSON.length()]; |
| int viewsColumnIndex = fieldColumnsMapping.get("views"); |
| int periodColumnIndex = fieldColumnsMapping.get("period"); |
| |
| for (int i = 0; i < dataJSON.length(); i++) { |
| try { |
| JSONArray currentDayData = dataJSON.getJSONArray(i); |
| VisitModel currentVisitModel = new VisitModel(); |
| currentVisitModel.setPeriod(currentDayData.getString(periodColumnIndex)); |
| currentVisitModel.setViews(currentDayData.getInt(viewsColumnIndex)); |
| visitModels[i] = currentVisitModel; |
| } catch (JSONException e) { |
| AppLog.e(AppLog.T.STATS, "Cannot create the Visit at index " + i, e); |
| } |
| } |
| mDayViews = visitModels; |
| } else { |
| mDayViews = null; |
| } |
| |
| parseYears(response); |
| parseAverages(response); |
| parseWeeks(response); |
| } |
| |
| private String[] orderKeys(Iterator keys, int numberOfKeys) { |
| // Keys could not be ordered fine. Reordering them. |
| String[] orderedKeys = new String[numberOfKeys]; |
| int i = 0; |
| while (keys.hasNext()) { |
| orderedKeys[i] = (String)keys.next(); |
| i++; |
| } |
| Arrays.sort(orderedKeys); |
| return orderedKeys; |
| } |
| |
| private void parseYears(JSONObject response) { |
| // Parse the Years section |
| try { |
| JSONObject yearsJSON = response.getJSONObject("years"); |
| // Keys could not be ordered fine. Reordering them. |
| String[] orderedKeys = orderKeys(yearsJSON.keys(), yearsJSON.length()); |
| |
| for (String currentYearKey : orderedKeys) { |
| Year currentYear = new Year(); |
| currentYear.setLabel(currentYearKey); |
| |
| JSONObject currentYearObj = yearsJSON.getJSONObject(currentYearKey); |
| int total = currentYearObj.getInt("total"); |
| currentYear.setTotal(total); |
| |
| JSONObject monthsJSON = currentYearObj.getJSONObject("months"); |
| Iterator<String> monthsKeys = monthsJSON.keys(); |
| List<Month> monthsList = new ArrayList<>(monthsJSON.length()); |
| while (monthsKeys.hasNext()) { |
| String currentMonthKey = monthsKeys.next(); |
| int currentMonthVisits = monthsJSON.getInt(currentMonthKey); |
| monthsList.add(new Month(currentMonthKey, currentMonthVisits)); |
| } |
| |
| Collections.sort(monthsList, new Comparator<Month>() { |
| public int compare(Month o1, Month o2) { |
| int v1 = Integer.parseInt(o1.getMonth()); |
| int v2 = Integer.parseInt(o2.getMonth()); |
| // ascending order |
| return v1 - v2; |
| } |
| }); |
| |
| currentYear.setMonths(monthsList); |
| mYears.add(currentYear); |
| } |
| } catch (JSONException e) { |
| AppLog.e(AppLog.T.STATS, "Cannot parse the Years section", e); |
| } |
| } |
| |
| private void parseAverages(JSONObject response) { |
| // Parse the Averages section |
| try { |
| JSONObject averagesJSON = response.getJSONObject("averages"); |
| // Keys could not be ordered fine. Reordering them. |
| String[] orderedKeys = orderKeys(averagesJSON.keys(), averagesJSON.length()); |
| |
| for (String currentJSONKey : orderedKeys) { |
| Year currentAverage = new Year(); |
| currentAverage.setLabel(currentJSONKey); |
| |
| JSONObject currentAverageJSONObj = averagesJSON.getJSONObject(currentJSONKey); |
| currentAverage.setTotal(currentAverageJSONObj.getInt("overall")); |
| |
| JSONObject monthsJSON = currentAverageJSONObj.getJSONObject("months"); |
| Iterator<String> monthsKeys = monthsJSON.keys(); |
| List<Month> monthsList = new ArrayList<>(monthsJSON.length()); |
| while (monthsKeys.hasNext()) { |
| String currentMonthKey = monthsKeys.next(); |
| int currentMonthVisits = monthsJSON.getInt(currentMonthKey); |
| monthsList.add(new Month(currentMonthKey, currentMonthVisits)); |
| } |
| Collections.sort(monthsList, new java.util.Comparator<Month>() { |
| public int compare(Month o1, Month o2) { |
| int v1 = Integer.parseInt(o1.getMonth()); |
| int v2 = Integer.parseInt(o2.getMonth()); |
| // ascending order |
| return v1 - v2; |
| } |
| }); |
| |
| currentAverage.setMonths(monthsList); |
| mAverages.add(currentAverage); |
| } |
| } catch (JSONException e) { |
| AppLog.e(AppLog.T.STATS, "Cannot parse the Averages section", e); |
| } |
| } |
| |
| private void parseWeeks(JSONObject response) { |
| // Parse the Weeks section |
| try { |
| JSONArray weeksJSON = response.getJSONArray("weeks"); |
| for (int i = 0; i < weeksJSON.length(); i++) { |
| Week currentWeek = new Week(); |
| JSONObject currentWeekJSON = weeksJSON.getJSONObject(i); |
| |
| currentWeek.setTotal(currentWeekJSON.getInt("total")); |
| currentWeek.setAverage(currentWeekJSON.getInt("average")); |
| try { |
| if (i == 0 ) { |
| currentWeek.setChange(0); |
| } else { |
| currentWeek.setChange(currentWeekJSON.getInt("change")); |
| } |
| } catch (JSONException e){ |
| AppLog.w(AppLog.T.STATS, "Cannot parse the change value in weeks section. Trying to understand the meaning: 42!!"); |
| // if i == 0 is the first week. if not it could mean infinity |
| String aProblematicValue = currentWeekJSON.get("change").toString(); |
| if (aProblematicValue.contains("infinity")) { |
| currentWeek.setChange(Integer.MAX_VALUE); |
| } else { |
| currentWeek.setChange(0); |
| } |
| } |
| |
| JSONArray daysJSON = currentWeekJSON.getJSONArray("days"); |
| for (int j = 0; j < daysJSON.length(); j++) { |
| Day currentDay = new Day(); |
| JSONObject dayJSON = daysJSON.getJSONObject(j); |
| currentDay.setCount(dayJSON.getInt("count")); |
| currentDay.setDay(dayJSON.getString("day")); |
| currentWeek.getDays().add(currentDay); |
| } |
| mWeeks.add(currentWeek); |
| } |
| } catch (JSONException e) { |
| AppLog.e(AppLog.T.STATS, "Cannot parse the Weeks section", e); |
| } |
| } |
| |
| public class Day implements Serializable { |
| private int mCount; |
| private String mDay; |
| |
| public String getDay() { |
| return mDay; |
| } |
| |
| public void setDay(String day) { |
| this.mDay = day; |
| } |
| |
| public int getCount() { |
| return mCount; |
| } |
| |
| public void setCount(int count) { |
| this.mCount = count; |
| } |
| } |
| |
| public class Week implements Serializable { |
| int mChange; |
| int mTotal; |
| int mAverage; |
| List<Day> mDays = new LinkedList<>(); |
| |
| public int getTotal() { |
| return mTotal; |
| } |
| |
| public void setTotal(int total) { |
| this.mTotal = total; |
| } |
| |
| public int getAverage() { |
| return mAverage; |
| } |
| |
| public void setAverage(int average) { |
| this.mAverage = average; |
| } |
| |
| public int getChange() { |
| return mChange; |
| } |
| |
| public void setChange(int change) { |
| this.mChange = change; |
| } |
| |
| public List<Day> getDays() { |
| return mDays; |
| } |
| |
| public void setDays(List<Day> days) { |
| this.mDays = days; |
| } |
| } |
| |
| public class Year implements Serializable { |
| private String mLabel; |
| private int mTotal; |
| private List<Month> mMonths; |
| |
| public List<Month> getMonths() { |
| return mMonths; |
| } |
| |
| public void setMonths(List<Month> months) { |
| mMonths = months; |
| } |
| |
| public String getLabel() { |
| return mLabel; |
| } |
| |
| public void setLabel(String label) { |
| this.mLabel = label; |
| } |
| |
| public int getTotal() { |
| return mTotal; |
| } |
| |
| public void setTotal(int total) { |
| this.mTotal = total; |
| } |
| } |
| |
| public class Month implements Serializable { |
| private final int mCount; |
| private final String mMonth; |
| |
| Month(String label, int count) { |
| this.mMonth = label; |
| this.mCount = count; |
| } |
| |
| public String getMonth() { |
| return mMonth; |
| } |
| public int getCount() { |
| return mCount; |
| } |
| } |
| } |