From 404fc869b025a37c778555d45bd3f5e4d409a231 Mon Sep 17 00:00:00 2001 From: Alinson Xavier Date: Tue, 18 Jul 2017 21:28:48 -0400 Subject: [PATCH] Repair inconsistent data instead of throwing exception --- .../org/isoron/uhabits/espresso/MainTest.java | 4 +- .../sqlite/SQLiteCheckmarkListTest.java | 35 ++++++++++++++ .../models/sqlite/SQLiteCheckmarkList.java | 31 ++++++++---- .../sqlite/records/CheckmarkRecord.java | 48 +++++++++++++++++++ 4 files changed, 108 insertions(+), 10 deletions(-) diff --git a/app/src/androidTest/java/org/isoron/uhabits/espresso/MainTest.java b/app/src/androidTest/java/org/isoron/uhabits/espresso/MainTest.java index f9284b58e..ea31c54c7 100644 --- a/app/src/androidTest/java/org/isoron/uhabits/espresso/MainTest.java +++ b/app/src/androidTest/java/org/isoron/uhabits/espresso/MainTest.java @@ -171,13 +171,13 @@ public class MainTest clickMenuItem(R.string.archive); assertHabitsDontExist(names); - clickMenuItem(R.string.show_archived); + clickMenuItem(R.string.hide_archived); assertHabitsExist(names); selectHabits(names); clickMenuItem(R.string.unarchive); - clickMenuItem(R.string.show_archived); + clickMenuItem(R.string.hide_archived); assertHabitsExist(names); deleteHabits(names); diff --git a/app/src/androidTest/java/org/isoron/uhabits/models/sqlite/SQLiteCheckmarkListTest.java b/app/src/androidTest/java/org/isoron/uhabits/models/sqlite/SQLiteCheckmarkListTest.java index 32e6df853..45efec5e7 100644 --- a/app/src/androidTest/java/org/isoron/uhabits/models/sqlite/SQLiteCheckmarkListTest.java +++ b/app/src/androidTest/java/org/isoron/uhabits/models/sqlite/SQLiteCheckmarkListTest.java @@ -115,6 +115,41 @@ public class SQLiteCheckmarkListTest extends BaseAndroidTest assertThat(records.get(0).timestamp, equalTo(today - 21 * day)); } + @Test + public void testFixRecords() throws Exception + { + long day = DateUtils.millisecondsInOneDay; + long from = DateUtils.getStartOfToday(); + long to = from + 5 * day; + + List original, actual, expected; + HabitRecord habit = new HabitRecord(); + + original = new ArrayList<>(); + original.add(new CheckmarkRecord(habit, from + 8*day, 2)); + original.add(new CheckmarkRecord(habit, from + 5*day, 0)); + original.add(new CheckmarkRecord(habit, from + 4*day, 0)); + original.add(new CheckmarkRecord(habit, from + 4*day, 2)); + original.add(new CheckmarkRecord(habit, from + 3*day, 2)); + original.add(new CheckmarkRecord(habit, from + 2*day, 1)); + original.add(new CheckmarkRecord(habit, from + 2*day + 100, 1)); + original.add(new CheckmarkRecord(habit, from, 0)); + original.add(new CheckmarkRecord(habit, from, 2)); + original.add(new CheckmarkRecord(habit, from - day, 2)); + + actual = SQLiteCheckmarkList.fixRecords(original, habit, from, to); + + expected = new ArrayList<>(); + expected.add(new CheckmarkRecord(habit, from + 5*day, 0)); + expected.add(new CheckmarkRecord(habit, from + 4*day, 2)); + expected.add(new CheckmarkRecord(habit, from + 3*day, 2)); + expected.add(new CheckmarkRecord(habit, from + 2*day, 1)); + expected.add(new CheckmarkRecord(habit, from + day, 0)); + expected.add(new CheckmarkRecord(habit, from, 2)); + + assertThat(actual, equalTo(expected)); + } + private List getAllRecords() { return new Select() diff --git a/app/src/main/java/org/isoron/uhabits/models/sqlite/SQLiteCheckmarkList.java b/app/src/main/java/org/isoron/uhabits/models/sqlite/SQLiteCheckmarkList.java index a9c9ae871..025a52d93 100644 --- a/app/src/main/java/org/isoron/uhabits/models/sqlite/SQLiteCheckmarkList.java +++ b/app/src/main/java/org/isoron/uhabits/models/sqlite/SQLiteCheckmarkList.java @@ -115,14 +115,7 @@ public class SQLiteCheckmarkList extends CheckmarkList List records = sqlite.query(query, params); for (CheckmarkRecord record : records) record.habit = habitRecord; - int nDays = DateUtils.getDaysBetween(fromTimestamp, toTimestamp) + 1; - if (records.size() != nDays) - { - throw new InconsistentDatabaseException( - String.format("habit=%s, %d expected, %d found", - habit.getName(), nDays, records.size())); - } - + records = fixRecords(records, habitRecord, fromTimestamp, toTimestamp); return toCheckmarks(records); } @@ -198,6 +191,28 @@ public class SQLiteCheckmarkList extends CheckmarkList return checkmarks; } + public static List fixRecords(List original, + HabitRecord habit, + long fromTimestamp, + long toTimestamp) + { + long day = DateUtils.millisecondsInOneDay; + ArrayList records = new ArrayList<>(); + + for (long t = toTimestamp; t >= fromTimestamp; t -= day) + records.add(new CheckmarkRecord(habit, t, Checkmark.UNCHECKED)); + + for (CheckmarkRecord record : original) + { + if ((toTimestamp - record.timestamp) % day != 0) continue; + int offset = (int) ((toTimestamp - record.timestamp) / day); + if (offset < 0 || offset >= records.size()) continue; + records.set(offset, record); + } + + return records; + } + private static class CachedData { int todayValue; diff --git a/app/src/main/java/org/isoron/uhabits/models/sqlite/records/CheckmarkRecord.java b/app/src/main/java/org/isoron/uhabits/models/sqlite/records/CheckmarkRecord.java index 6938b505d..31dd8f35d 100644 --- a/app/src/main/java/org/isoron/uhabits/models/sqlite/records/CheckmarkRecord.java +++ b/app/src/main/java/org/isoron/uhabits/models/sqlite/records/CheckmarkRecord.java @@ -24,6 +24,7 @@ import android.database.*; import com.activeandroid.*; import com.activeandroid.annotation.*; +import org.apache.commons.lang3.builder.*; import org.isoron.uhabits.models.*; /** @@ -53,6 +54,17 @@ public class CheckmarkRecord extends Model implements SQLiteRecord @Column(name = "value") public Integer value; + public CheckmarkRecord() + { + } + + public CheckmarkRecord(HabitRecord habit, Long timestamp, Integer value) + { + this.habit = habit; + this.timestamp = timestamp; + this.value = value; + } + @Override public void copyFrom(Cursor c) { @@ -64,4 +76,40 @@ public class CheckmarkRecord extends Model implements SQLiteRecord { return new Checkmark(timestamp, value); } + + @Override + public boolean equals(Object o) + { + if (this == o) return true; + + if (o == null || getClass() != o.getClass()) return false; + + CheckmarkRecord that = (CheckmarkRecord) o; + + return new EqualsBuilder() + .append(habit, that.habit) + .append(timestamp, that.timestamp) + .append(value, that.value) + .isEquals(); + } + + @Override + public int hashCode() + { + return new HashCodeBuilder(17, 37) + .append(habit) + .append(timestamp) + .append(value) + .toHashCode(); + } + + @Override + public String toString() + { + return new ToStringBuilder(this) + .append("habit", habit) + .append("timestamp", timestamp) + .append("value", value) + .toString(); + } }