From 922b234307faa837b2e59e01c7b951609d00858e Mon Sep 17 00:00:00 2001 From: Alinson Xavier Date: Wed, 29 Jun 2016 19:49:19 -0400 Subject: [PATCH] Initial implementation of filters --- .../org/isoron/uhabits/HabitFixtures.java | 2 +- .../uhabits/io/HabitsCSVExporterTest.java | 43 +++-- .../org/isoron/uhabits/io/ImportTest.java | 25 ++- .../models/sqlite/SQLiteHabitListTest.java | 35 ++-- .../uhabits/tasks/ExportCSVTaskTest.java | 5 +- .../uhabits/tasks/ImportDataTaskTest.java | 2 +- .../uhabits/HabitBroadcastReceiver.java | 12 +- .../commands/ArchiveHabitsCommand.java | 38 ++-- .../commands/ChangeHabitColorCommand.java | 35 ++-- .../uhabits/commands/CreateHabitCommand.java | 13 +- .../uhabits/commands/DeleteHabitsCommand.java | 15 +- .../uhabits/commands/EditHabitCommand.java | 8 +- .../commands/UnarchiveHabitsCommand.java | 17 +- .../isoron/uhabits/io/AbstractImporter.java | 20 +-- .../isoron/uhabits/io/GenericImporter.java | 13 +- .../uhabits/io/HabitBullCSVImporter.java | 13 +- .../isoron/uhabits/io/HabitsCSVExporter.java | 168 +++++++++--------- .../org/isoron/uhabits/io/LoopDBImporter.java | 6 + .../isoron/uhabits/io/RewireDBImporter.java | 9 +- .../isoron/uhabits/io/TickmateDBImporter.java | 7 +- .../org/isoron/uhabits/models/HabitList.java | 96 ++++------ .../isoron/uhabits/models/HabitMatcher.java | 71 ++++++++ .../uhabits/models/HabitMatcherBuilder.java | 53 ++++++ .../models/memory/MemoryHabitList.java | 52 +++--- .../models/sqlite/SQLiteHabitList.java | 165 +++++++++++------ .../models/sqlite/records/HabitRecord.java | 3 +- .../isoron/uhabits/tasks/ExportCSVTask.java | 70 ++++---- .../isoron/uhabits/tasks/ImportDataTask.java | 66 ++++--- .../edit/CreateHabitDialogFragment.java | 3 +- .../habits/edit/EditHabitDialogFragment.java | 12 +- .../ui/habits/list/ListHabitsActivity.java | 16 +- .../ui/habits/list/ListHabitsController.java | 17 +- .../ui/habits/list/ListHabitsScreen.java | 5 + .../habits/list/ListHabitsSelectionMenu.java | 22 ++- .../list/model/HabitCardListAdapter.java | 10 +- .../habits/list/model/HabitCardListCache.java | 106 ++++++----- .../ui/habits/show/ShowHabitActivity.java | 4 +- .../uhabits/ui/widgets/HabitPickerDialog.java | 3 +- .../isoron/uhabits/utils/ReminderUtils.java | 9 +- .../uhabits/widgets/BaseWidgetProvider.java | 4 +- .../commands/ArchiveHabitsCommandTest.java | 3 +- .../commands/ChangeHabitColorCommandTest.java | 2 +- .../commands/CreateHabitCommandTest.java | 18 +- .../commands/DeleteHabitsCommandTest.java | 8 +- .../commands/EditHabitCommandTest.java | 4 +- .../commands/UnarchiveHabitsCommandTest.java | 4 +- .../isoron/uhabits/models/HabitFixtures.java | 3 +- .../isoron/uhabits/models/HabitListTest.java | 87 +++++---- 48 files changed, 803 insertions(+), 599 deletions(-) create mode 100644 app/src/main/java/org/isoron/uhabits/models/HabitMatcher.java create mode 100644 app/src/main/java/org/isoron/uhabits/models/HabitMatcherBuilder.java diff --git a/app/src/androidTest/java/org/isoron/uhabits/HabitFixtures.java b/app/src/androidTest/java/org/isoron/uhabits/HabitFixtures.java index 6cf077513..e4ab4193e 100644 --- a/app/src/androidTest/java/org/isoron/uhabits/HabitFixtures.java +++ b/app/src/androidTest/java/org/isoron/uhabits/HabitFixtures.java @@ -84,7 +84,7 @@ public class HabitFixtures public void purgeHabits(HabitList habitList) { - for (Habit h : habitList.getAll(true)) + for (Habit h : habitList) habitList.remove(h); } } diff --git a/app/src/androidTest/java/org/isoron/uhabits/io/HabitsCSVExporterTest.java b/app/src/androidTest/java/org/isoron/uhabits/io/HabitsCSVExporterTest.java index 5cda1ed99..a97b800a7 100644 --- a/app/src/androidTest/java/org/isoron/uhabits/io/HabitsCSVExporterTest.java +++ b/app/src/androidTest/java/org/isoron/uhabits/io/HabitsCSVExporterTest.java @@ -19,27 +19,22 @@ package org.isoron.uhabits.io; -import android.content.Context; -import android.support.test.InstrumentationRegistry; -import android.support.test.runner.AndroidJUnit4; -import android.test.suitebuilder.annotation.SmallTest; - -import org.isoron.uhabits.BaseAndroidTest; -import org.isoron.uhabits.models.Habit; -import org.isoron.uhabits.utils.FileUtils; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.util.Enumeration; -import java.util.List; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; - -import static junit.framework.Assert.assertTrue; +import android.content.*; +import android.support.test.*; +import android.support.test.runner.*; +import android.test.suitebuilder.annotation.*; + +import org.isoron.uhabits.*; +import org.isoron.uhabits.models.*; +import org.isoron.uhabits.utils.*; +import org.junit.*; +import org.junit.runner.*; + +import java.io.*; +import java.util.*; +import java.util.zip.*; + +import static junit.framework.Assert.*; @RunWith(AndroidJUnit4.class) @SmallTest @@ -63,9 +58,11 @@ public class HabitsCSVExporterTest extends BaseAndroidTest @Test public void testExportCSV() throws IOException { - List habits = habitList.getAll(true); + List selected = new LinkedList<>(); + for (Habit h : habitList) selected.add(h); - HabitsCSVExporter exporter = new HabitsCSVExporter(habits, baseDir); + HabitsCSVExporter exporter = + new HabitsCSVExporter(habitList, selected, baseDir); String filename = exporter.writeArchive(); assertAbsolutePathExists(filename); diff --git a/app/src/androidTest/java/org/isoron/uhabits/io/ImportTest.java b/app/src/androidTest/java/org/isoron/uhabits/io/ImportTest.java index e19b035ff..4f86366c5 100644 --- a/app/src/androidTest/java/org/isoron/uhabits/io/ImportTest.java +++ b/app/src/androidTest/java/org/isoron/uhabits/io/ImportTest.java @@ -44,6 +44,7 @@ public class ImportTest extends BaseAndroidTest private Context context; + @Override @Before public void setUp() { @@ -61,10 +62,9 @@ public class ImportTest extends BaseAndroidTest { importFromFile("habitbull.csv"); - List habits = habitList.getAll(true); - assertThat(habits.size(), equalTo(4)); + assertThat(habitList.size(), equalTo(4)); - Habit habit = habits.get(0); + Habit habit = habitList.getByPosition(0); assertThat(habit.getName(), equalTo("Breed dragons")); assertThat(habit.getDescription(), equalTo("with love and fire")); assertThat(habit.getFrequency(), equalTo(Frequency.DAILY)); @@ -78,10 +78,9 @@ public class ImportTest extends BaseAndroidTest { importFromFile("loop.db"); - List habits = habitList.getAll(true); - assertThat(habits.size(), equalTo(9)); + assertThat(habitList.size(), equalTo(9)); - Habit habit = habits.get(0); + Habit habit = habitList.getByPosition(0); assertThat(habit.getName(), equalTo("Wake up early")); assertThat(habit.getFrequency(), equalTo(Frequency.THREE_TIMES_PER_WEEK)); assertTrue(containsRepetition(habit, 2016, 3, 14)); @@ -94,10 +93,9 @@ public class ImportTest extends BaseAndroidTest { importFromFile("rewire.db"); - List habits = habitList.getAll(true); - assertThat(habits.size(), equalTo(3)); + assertThat(habitList.size(), equalTo(3)); - Habit habit = habits.get(0); + Habit habit = habitList.getByPosition(0); assertThat(habit.getName(), equalTo("Wake up early")); assertThat(habit.getFrequency(), equalTo(Frequency.THREE_TIMES_PER_WEEK)); @@ -107,7 +105,7 @@ public class ImportTest extends BaseAndroidTest assertTrue(containsRepetition(habit, 2016, 1, 28)); assertFalse(containsRepetition(habit, 2016, 3, 10)); - habit = habits.get(1); + habit = habitList.getByPosition(1); assertThat(habit.getName(), equalTo("brush teeth")); assertThat(habit.getFrequency(), equalTo(Frequency.THREE_TIMES_PER_WEEK)); @@ -126,10 +124,9 @@ public class ImportTest extends BaseAndroidTest { importFromFile("tickmate.db"); - List habits = habitList.getAll(true); - assertThat(habits.size(), equalTo(3)); + assertThat(habitList.size(), equalTo(3)); - Habit h = habits.get(0); + Habit h = habitList.getByPosition(0); assertThat(h.getName(), equalTo("Vegan")); assertTrue(containsRepetition(h, 2016, 1, 24)); assertTrue(containsRepetition(h, 2016, 2, 5)); @@ -158,7 +155,7 @@ public class ImportTest extends BaseAndroidTest assertTrue(file.exists()); assertTrue(file.canRead()); - GenericImporter importer = new GenericImporter(); + GenericImporter importer = new GenericImporter(habitList); assertThat(importer.canHandle(file), is(true)); importer.importHabitsFromFile(file); diff --git a/app/src/androidTest/java/org/isoron/uhabits/models/sqlite/SQLiteHabitListTest.java b/app/src/androidTest/java/org/isoron/uhabits/models/sqlite/SQLiteHabitListTest.java index cf8693a60..381015feb 100644 --- a/app/src/androidTest/java/org/isoron/uhabits/models/sqlite/SQLiteHabitListTest.java +++ b/app/src/androidTest/java/org/isoron/uhabits/models/sqlite/SQLiteHabitListTest.java @@ -45,10 +45,13 @@ public class SQLiteHabitListTest extends BaseAndroidTest @Rule public ExpectedException exception = ExpectedException.none(); + private SQLiteHabitList habitList; + @Override public void setUp() { super.setUp(); + this.habitList = (SQLiteHabitList) super.habitList; fixtures.purgeHabits(habitList); for (int i = 0; i < 10; i++) @@ -105,35 +108,29 @@ public class SQLiteHabitListTest extends BaseAndroidTest } @Test - public void testCountActive() - { - assertThat(habitList.countActive(), equalTo(5)); - } - - @Test - public void testCountWithArchived() + public void testSize() { - assertThat(habitList.countWithArchived(), equalTo(10)); + assertThat(habitList.size(), equalTo(10)); } @Test public void testGetAll_withArchived() { - List habits = habitList.getAll(true); + List habits = habitList.toList(); assertThat(habits.size(), equalTo(10)); assertThat(habits.get(3).getName(), equalTo("habit 3")); } - @Test - public void testGetAll_withoutArchived() - { - List habits = habitList.getAll(false); - assertThat(habits.size(), equalTo(5)); - assertThat(habits.get(3).getName(), equalTo("habit 7")); - - List another = habitList.getAll(false); - assertThat(habits, equalTo(another)); - } +// @Test +// public void testGetAll_withoutArchived() +// { +// List habits = habitList.toList(); +// assertThat(habits.size(), equalTo(5)); +// assertThat(habits.get(3).getName(), equalTo("habit 7")); +// +// List another = habitList.toList(); +// assertThat(habits, equalTo(another)); +// } @Test public void testGetById() diff --git a/app/src/androidTest/java/org/isoron/uhabits/tasks/ExportCSVTaskTest.java b/app/src/androidTest/java/org/isoron/uhabits/tasks/ExportCSVTaskTest.java index 68b1caa46..6a9e76b9a 100644 --- a/app/src/androidTest/java/org/isoron/uhabits/tasks/ExportCSVTaskTest.java +++ b/app/src/androidTest/java/org/isoron/uhabits/tasks/ExportCSVTaskTest.java @@ -49,9 +49,10 @@ public class ExportCSVTaskTest extends BaseAndroidTest public void testExportCSV() throws Throwable { fixtures.createShortHabit(); - List habits = habitList.getAll(true); + List selected = new LinkedList<>(); + for(Habit h : habitList) selected.add(h); - ExportCSVTask task = new ExportCSVTask(habits, null); + ExportCSVTask task = new ExportCSVTask(habitList, selected, null); task.setListener(archiveFilename -> { assertThat(archiveFilename, is(not(nullValue()))); diff --git a/app/src/androidTest/java/org/isoron/uhabits/tasks/ImportDataTaskTest.java b/app/src/androidTest/java/org/isoron/uhabits/tasks/ImportDataTaskTest.java index 094692083..008669cbe 100644 --- a/app/src/androidTest/java/org/isoron/uhabits/tasks/ImportDataTaskTest.java +++ b/app/src/androidTest/java/org/isoron/uhabits/tasks/ImportDataTaskTest.java @@ -80,7 +80,7 @@ public class ImportDataTaskTest extends BaseAndroidTest { File file = new File(String.format("%s/%s", baseDir.getPath(), assetFilename)); copyAssetToFile(assetFilename, file); - return new ImportDataTask(file, null); + return new ImportDataTask(habitList, file, null); } @Test diff --git a/app/src/main/java/org/isoron/uhabits/HabitBroadcastReceiver.java b/app/src/main/java/org/isoron/uhabits/HabitBroadcastReceiver.java index 90f06191a..c76c3b44a 100644 --- a/app/src/main/java/org/isoron/uhabits/HabitBroadcastReceiver.java +++ b/app/src/main/java/org/isoron/uhabits/HabitBroadcastReceiver.java @@ -55,7 +55,7 @@ public class HabitBroadcastReceiver extends BroadcastReceiver "org.isoron.uhabits.ACTION_SNOOZE"; @Inject - HabitList habitList; + HabitList habits; @Inject CommandRunner commandRunner; @@ -99,7 +99,7 @@ public class HabitBroadcastReceiver extends BroadcastReceiver break; case Intent.ACTION_BOOT_COMPLETED: - ReminderUtils.createReminderAlarms(context, habitList); + ReminderUtils.createReminderAlarms(context, habits); break; } } @@ -111,7 +111,7 @@ public class HabitBroadcastReceiver extends BroadcastReceiver Long timestamp = intent.getLongExtra("timestamp", today); long habitId = ContentUris.parseId(data); - Habit habit = habitList.getById(habitId); + Habit habit = habits.getById(habitId); if (habit != null) { ToggleRepetitionCommand command = @@ -140,7 +140,7 @@ public class HabitBroadcastReceiver extends BroadcastReceiver private void createNotification(final Context context, final Intent intent) { final Uri data = intent.getData(); - final Habit habit = habitList.getById(ContentUris.parseId(data)); + final Habit habit = habits.getById(ContentUris.parseId(data)); final Long timestamp = intent.getLongExtra("timestamp", DateUtils.getStartOfToday()); final Long reminderTime = @@ -223,7 +223,7 @@ public class HabitBroadcastReceiver extends BroadcastReceiver private void createReminderAlarmsDelayed(final Context context) { new Handler().postDelayed( - () -> ReminderUtils.createReminderAlarms(context, habitList), 5000); + () -> ReminderUtils.createReminderAlarms(context, habits), 5000); } private void dismissAllHabits() @@ -250,7 +250,7 @@ public class HabitBroadcastReceiver extends BroadcastReceiver Long.parseLong(prefs.getString("pref_snooze_interval", "15")); long habitId = ContentUris.parseId(data); - Habit habit = habitList.getById(habitId); + Habit habit = habits.getById(habitId); if (habit != null) ReminderUtils.createReminderAlarm(context, habit, new Date().getTime() + delayMinutes * 60 * 1000); dismissNotification(context, habitId); diff --git a/app/src/main/java/org/isoron/uhabits/commands/ArchiveHabitsCommand.java b/app/src/main/java/org/isoron/uhabits/commands/ArchiveHabitsCommand.java index fa2ca827f..a387cdd22 100644 --- a/app/src/main/java/org/isoron/uhabits/commands/ArchiveHabitsCommand.java +++ b/app/src/main/java/org/isoron/uhabits/commands/ArchiveHabitsCommand.java @@ -19,43 +19,32 @@ package org.isoron.uhabits.commands; -import org.isoron.uhabits.HabitsApplication; -import org.isoron.uhabits.R; -import org.isoron.uhabits.models.Habit; -import org.isoron.uhabits.models.HabitList; +import org.isoron.uhabits.*; +import org.isoron.uhabits.models.*; -import java.util.List; - -import javax.inject.Inject; +import java.util.*; /** * Command to archive a list of habits. */ public class ArchiveHabitsCommand extends Command { - @Inject - HabitList habitList; + private List selectedHabits; - private List habits; + private final HabitList habitList; - public ArchiveHabitsCommand(List habits) + public ArchiveHabitsCommand(HabitList habitList, List selectedHabits) { + this.habitList = habitList; HabitsApplication.getComponent().inject(this); - this.habits = habits; + this.selectedHabits = selectedHabits; } @Override public void execute() { - for(Habit h : habits) h.setArchived(true); - habitList.update(habits); - } - - @Override - public void undo() - { - for(Habit h : habits) h.setArchived(false); - habitList.update(habits); + for (Habit h : selectedHabits) h.setArchived(true); + habitList.update(selectedHabits); } @Override @@ -69,4 +58,11 @@ public class ArchiveHabitsCommand extends Command { return R.string.toast_habit_unarchived; } + + @Override + public void undo() + { + for (Habit h : selectedHabits) h.setArchived(false); + habitList.update(selectedHabits); + } } \ No newline at end of file diff --git a/app/src/main/java/org/isoron/uhabits/commands/ChangeHabitColorCommand.java b/app/src/main/java/org/isoron/uhabits/commands/ChangeHabitColorCommand.java index e09ec470b..503acc40f 100644 --- a/app/src/main/java/org/isoron/uhabits/commands/ChangeHabitColorCommand.java +++ b/app/src/main/java/org/isoron/uhabits/commands/ChangeHabitColorCommand.java @@ -19,46 +19,41 @@ package org.isoron.uhabits.commands; -import org.isoron.uhabits.HabitsApplication; -import org.isoron.uhabits.R; -import org.isoron.uhabits.models.Habit; -import org.isoron.uhabits.models.HabitList; +import org.isoron.uhabits.*; +import org.isoron.uhabits.models.*; -import java.util.ArrayList; -import java.util.List; - -import javax.inject.Inject; +import java.util.*; /** * Command to change the color of a list of habits. */ public class ChangeHabitColorCommand extends Command { - @Inject HabitList habitList; - List habits; + List selected; List originalColors; Integer newColor; - public ChangeHabitColorCommand(List habits, Integer newColor) + public ChangeHabitColorCommand(HabitList habitList, + List selected, + Integer newColor) { - HabitsApplication.getComponent().inject(this); - - this.habits = habits; + this.habitList = habitList; + this.selected = selected; this.newColor = newColor; - this.originalColors = new ArrayList<>(habits.size()); + this.originalColors = new ArrayList<>(selected.size()); - for (Habit h : habits) originalColors.add(h.getColor()); + for (Habit h : selected) originalColors.add(h.getColor()); } @Override public void execute() { - for(Habit h : habits) h.setColor(newColor); - habitList.update(habits); + for (Habit h : selected) h.setColor(newColor); + habitList.update(selected); } @Override @@ -77,7 +72,7 @@ public class ChangeHabitColorCommand extends Command public void undo() { int k = 0; - for (Habit h : habits) h.setColor(originalColors.get(k++)); - habitList.update(habits); + for (Habit h : selected) h.setColor(originalColors.get(k++)); + habitList.update(selected); } } diff --git a/app/src/main/java/org/isoron/uhabits/commands/CreateHabitCommand.java b/app/src/main/java/org/isoron/uhabits/commands/CreateHabitCommand.java index 7668e5d2f..f8f550254 100644 --- a/app/src/main/java/org/isoron/uhabits/commands/CreateHabitCommand.java +++ b/app/src/main/java/org/isoron/uhabits/commands/CreateHabitCommand.java @@ -19,28 +19,23 @@ package org.isoron.uhabits.commands; -import org.isoron.uhabits.HabitsApplication; -import org.isoron.uhabits.R; -import org.isoron.uhabits.models.Habit; -import org.isoron.uhabits.models.HabitList; - -import javax.inject.Inject; +import org.isoron.uhabits.*; +import org.isoron.uhabits.models.*; /** * Command to create a habit. */ public class CreateHabitCommand extends Command { - @Inject HabitList habitList; private Habit model; private Long savedId; - public CreateHabitCommand(Habit model) + public CreateHabitCommand(HabitList habitList, Habit model) { + this.habitList = habitList; this.model = model; - HabitsApplication.getComponent().inject(this); } @Override diff --git a/app/src/main/java/org/isoron/uhabits/commands/DeleteHabitsCommand.java b/app/src/main/java/org/isoron/uhabits/commands/DeleteHabitsCommand.java index 0d800cd17..b4da2c671 100644 --- a/app/src/main/java/org/isoron/uhabits/commands/DeleteHabitsCommand.java +++ b/app/src/main/java/org/isoron/uhabits/commands/DeleteHabitsCommand.java @@ -19,29 +19,24 @@ package org.isoron.uhabits.commands; -import org.isoron.uhabits.HabitsApplication; -import org.isoron.uhabits.R; -import org.isoron.uhabits.models.Habit; -import org.isoron.uhabits.models.HabitList; +import org.isoron.uhabits.*; +import org.isoron.uhabits.models.*; -import java.util.List; - -import javax.inject.Inject; +import java.util.*; /** * Command to delete a list of habits. */ public class DeleteHabitsCommand extends Command { - @Inject HabitList habitList; private List habits; - public DeleteHabitsCommand(List habits) + public DeleteHabitsCommand(HabitList habitList, List habits) { this.habits = habits; - HabitsApplication.getComponent().inject(this); + this.habitList = habitList; } @Override diff --git a/app/src/main/java/org/isoron/uhabits/commands/EditHabitCommand.java b/app/src/main/java/org/isoron/uhabits/commands/EditHabitCommand.java index 784d909bf..e75a4cef6 100644 --- a/app/src/main/java/org/isoron/uhabits/commands/EditHabitCommand.java +++ b/app/src/main/java/org/isoron/uhabits/commands/EditHabitCommand.java @@ -22,14 +22,11 @@ package org.isoron.uhabits.commands; import org.isoron.uhabits.*; import org.isoron.uhabits.models.*; -import javax.inject.*; - /** * Command to modify a habit. */ public class EditHabitCommand extends Command { - @Inject HabitList habitList; private Habit original; @@ -40,10 +37,9 @@ public class EditHabitCommand extends Command private boolean hasFrequencyChanged; - public EditHabitCommand(Habit original, Habit modified) + public EditHabitCommand(HabitList habitList, Habit original, Habit modified) { - HabitsApplication.getComponent().inject(this); - + this.habitList = habitList; this.savedId = original.getId(); this.modified = new Habit(); this.original = new Habit(); diff --git a/app/src/main/java/org/isoron/uhabits/commands/UnarchiveHabitsCommand.java b/app/src/main/java/org/isoron/uhabits/commands/UnarchiveHabitsCommand.java index 5d442717c..6e45cda7b 100644 --- a/app/src/main/java/org/isoron/uhabits/commands/UnarchiveHabitsCommand.java +++ b/app/src/main/java/org/isoron/uhabits/commands/UnarchiveHabitsCommand.java @@ -19,29 +19,24 @@ package org.isoron.uhabits.commands; -import org.isoron.uhabits.HabitsApplication; -import org.isoron.uhabits.R; -import org.isoron.uhabits.models.Habit; -import org.isoron.uhabits.models.HabitList; +import org.isoron.uhabits.*; +import org.isoron.uhabits.models.*; -import java.util.List; - -import javax.inject.Inject; +import java.util.*; /** * Command to unarchive a list of habits. */ public class UnarchiveHabitsCommand extends Command { - @Inject HabitList habitList; private List habits; - public UnarchiveHabitsCommand(List habits) + public UnarchiveHabitsCommand(HabitList habitList, List selected) { - this.habits = habits; - HabitsApplication.getComponent().inject(this); + this.habits = selected; + this.habitList = habitList; } @Override diff --git a/app/src/main/java/org/isoron/uhabits/io/AbstractImporter.java b/app/src/main/java/org/isoron/uhabits/io/AbstractImporter.java index 3f6da5f8b..92bc60c95 100644 --- a/app/src/main/java/org/isoron/uhabits/io/AbstractImporter.java +++ b/app/src/main/java/org/isoron/uhabits/io/AbstractImporter.java @@ -19,17 +19,13 @@ package org.isoron.uhabits.io; -import android.support.annotation.NonNull; +import android.support.annotation.*; -import org.isoron.uhabits.HabitsApplication; -import org.isoron.uhabits.models.HabitList; +import org.isoron.uhabits.*; +import org.isoron.uhabits.models.*; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.util.Arrays; - -import javax.inject.Inject; +import java.io.*; +import java.util.*; /** * AbstractImporter is the base class for all classes that import data from @@ -37,12 +33,12 @@ import javax.inject.Inject; */ public abstract class AbstractImporter { - @Inject - HabitList habitList; + protected final HabitList habits; - public AbstractImporter() + public AbstractImporter(HabitList habits) { HabitsApplication.getComponent().inject(this); + this.habits = habits; } public abstract boolean canHandle(@NonNull File file) throws IOException; diff --git a/app/src/main/java/org/isoron/uhabits/io/GenericImporter.java b/app/src/main/java/org/isoron/uhabits/io/GenericImporter.java index 6f8e2ef70..047143c2c 100644 --- a/app/src/main/java/org/isoron/uhabits/io/GenericImporter.java +++ b/app/src/main/java/org/isoron/uhabits/io/GenericImporter.java @@ -21,6 +21,8 @@ package org.isoron.uhabits.io; import android.support.annotation.NonNull; +import org.isoron.uhabits.models.*; + import java.io.File; import java.io.IOException; import java.util.LinkedList; @@ -34,13 +36,14 @@ public class GenericImporter extends AbstractImporter { List importers; - public GenericImporter() + public GenericImporter(HabitList habits) { + super(habits); importers = new LinkedList<>(); - importers.add(new LoopDBImporter()); - importers.add(new RewireDBImporter()); - importers.add(new TickmateDBImporter()); - importers.add(new HabitBullCSVImporter()); + importers.add(new LoopDBImporter(habits)); + importers.add(new RewireDBImporter(habits)); + importers.add(new TickmateDBImporter(habits)); + importers.add(new HabitBullCSVImporter(habits)); } @Override diff --git a/app/src/main/java/org/isoron/uhabits/io/HabitBullCSVImporter.java b/app/src/main/java/org/isoron/uhabits/io/HabitBullCSVImporter.java index 9ce0aa005..7a51670c8 100644 --- a/app/src/main/java/org/isoron/uhabits/io/HabitBullCSVImporter.java +++ b/app/src/main/java/org/isoron/uhabits/io/HabitBullCSVImporter.java @@ -39,6 +39,11 @@ import java.util.HashMap; */ public class HabitBullCSVImporter extends AbstractImporter { + public HabitBullCSVImporter(HabitList habits) + { + super(habits); + } + @Override public boolean canHandle(@NonNull File file) throws IOException { @@ -66,7 +71,7 @@ public class HabitBullCSVImporter extends AbstractImporter private void parseFile(@NonNull File file) throws IOException { CSVReader reader = new CSVReader(new FileReader(file)); - HashMap habits = new HashMap<>(); + HashMap map = new HashMap<>(); for(String line[] : reader) { @@ -87,7 +92,7 @@ public class HabitBullCSVImporter extends AbstractImporter int value = Integer.parseInt(line[4]); if(value != 1) continue; - Habit h = habits.get(name); + Habit h = map.get(name); if(h == null) { @@ -95,8 +100,8 @@ public class HabitBullCSVImporter extends AbstractImporter h.setName(name); h.setDescription(description); h.setFrequency(Frequency.DAILY); - habitList.add(h); - habits.put(name, h); + habits.add(h); + map.put(name, h); } if(!h.getRepetitions().containsTimestamp(timestamp)) diff --git a/app/src/main/java/org/isoron/uhabits/io/HabitsCSVExporter.java b/app/src/main/java/org/isoron/uhabits/io/HabitsCSVExporter.java index e53102f0a..c308c0bb0 100644 --- a/app/src/main/java/org/isoron/uhabits/io/HabitsCSVExporter.java +++ b/app/src/main/java/org/isoron/uhabits/io/HabitsCSVExporter.java @@ -19,67 +19,116 @@ package org.isoron.uhabits.io; -import android.support.annotation.NonNull; - -import org.isoron.uhabits.HabitsApplication; -import org.isoron.uhabits.models.CheckmarkList; -import org.isoron.uhabits.models.Habit; -import org.isoron.uhabits.models.HabitList; -import org.isoron.uhabits.models.ScoreList; -import org.isoron.uhabits.utils.DateUtils; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.FileWriter; -import java.io.IOException; -import java.text.SimpleDateFormat; -import java.util.LinkedList; -import java.util.List; -import java.util.zip.ZipEntry; -import java.util.zip.ZipOutputStream; - -import javax.inject.Inject; +import android.support.annotation.*; + +import org.isoron.uhabits.*; +import org.isoron.uhabits.models.*; +import org.isoron.uhabits.utils.*; + +import java.io.*; +import java.text.*; +import java.util.*; +import java.util.zip.*; /** * Class that exports the application data to CSV files. */ public class HabitsCSVExporter { - private List habits; + private List selectedHabits; private List generateDirs; + private List generateFilenames; private String exportDirName; - @Inject - HabitList habitList; + @NonNull + private final HabitList allHabits; - public HabitsCSVExporter(List habits, File dir) + public HabitsCSVExporter(@NonNull HabitList allHabits, + @NonNull List selectedHabits, + @NonNull File dir) { HabitsApplication.getComponent().inject(this); - this.habits = habits; + this.allHabits = allHabits; + this.selectedHabits = selectedHabits; this.exportDirName = dir.getAbsolutePath() + "/"; generateDirs = new LinkedList<>(); generateFilenames = new LinkedList<>(); } + public String writeArchive() throws IOException + { + String zipFilename; + + writeHabits(); + zipFilename = writeZipFile(); + cleanup(); + + return zipFilename; + } + + private void addFileToZip(ZipOutputStream zos, String filename) + throws IOException + { + FileInputStream fis = + new FileInputStream(new File(exportDirName + filename)); + ZipEntry ze = new ZipEntry(filename); + zos.putNextEntry(ze); + + int length; + byte bytes[] = new byte[1024]; + while ((length = fis.read(bytes)) >= 0) zos.write(bytes, 0, length); + + zos.closeEntry(); + fis.close(); + } + + private void cleanup() + { + for (String filename : generateFilenames) + new File(exportDirName + filename).delete(); + + for (String filename : generateDirs) + new File(exportDirName + filename).delete(); + + new File(exportDirName).delete(); + } + + @NonNull + private String sanitizeFilename(String name) + { + String s = name.replaceAll("[^ a-zA-Z0-9\\._-]+", ""); + return s.substring(0, Math.min(s.length(), 100)); + } + + private void writeCheckmarks(String habitDirName, CheckmarkList checkmarks) + throws IOException + { + String filename = habitDirName + "Checkmarks.csv"; + FileWriter out = new FileWriter(exportDirName + filename); + generateFilenames.add(filename); + checkmarks.writeCSV(out); + out.close(); + } + private void writeHabits() throws IOException { String filename = "Habits.csv"; new File(exportDirName).mkdirs(); FileWriter out = new FileWriter(exportDirName + filename); generateFilenames.add(filename); - habitList.writeCSV(out); + allHabits.writeCSV(out); out.close(); - for(Habit h : habits) + for (Habit h : selectedHabits) { String sane = sanitizeFilename(h.getName()); - String habitDirName = String.format("%03d %s", habitList.indexOf(h) + 1, sane); + String habitDirName = + String.format("%03d %s", allHabits.indexOf(h) + 1, sane); habitDirName = habitDirName.trim() + "/"; new File(exportDirName + habitDirName).mkdirs(); @@ -90,14 +139,8 @@ public class HabitsCSVExporter } } - @NonNull - private String sanitizeFilename(String name) - { - String s = name.replaceAll("[^ a-zA-Z0-9\\._-]+", ""); - return s.substring(0, Math.min(s.length(), 100)); - } - - private void writeScores(String habitDirName, ScoreList scores) throws IOException + private void writeScores(String habitDirName, ScoreList scores) + throws IOException { String path = habitDirName + "Scores.csv"; FileWriter out = new FileWriter(exportDirName + path); @@ -106,25 +149,17 @@ public class HabitsCSVExporter out.close(); } - private void writeCheckmarks(String habitDirName, CheckmarkList checkmarks) throws IOException - { - String filename = habitDirName + "Checkmarks.csv"; - FileWriter out = new FileWriter(exportDirName + filename); - generateFilenames.add(filename); - checkmarks.writeCSV(out); - out.close(); - } - private String writeZipFile() throws IOException { SimpleDateFormat dateFormat = DateUtils.getCSVDateFormat(); String date = dateFormat.format(DateUtils.getStartOfToday()); - String zipFilename = String.format("%s/Loop Habits CSV %s.zip", exportDirName, date); + String zipFilename = + String.format("%s/Loop Habits CSV %s.zip", exportDirName, date); FileOutputStream fos = new FileOutputStream(zipFilename); ZipOutputStream zos = new ZipOutputStream(fos); - for(String filename : generateFilenames) + for (String filename : generateFilenames) addFileToZip(zos, filename); zos.close(); @@ -132,41 +167,4 @@ public class HabitsCSVExporter return zipFilename; } - - private void addFileToZip(ZipOutputStream zos, String filename) throws IOException - { - FileInputStream fis = new FileInputStream(new File(exportDirName + filename)); - ZipEntry ze = new ZipEntry(filename); - zos.putNextEntry(ze); - - int length; - byte bytes[] = new byte[1024]; - while((length = fis.read(bytes)) >= 0) - zos.write(bytes, 0, length); - - zos.closeEntry(); - fis.close(); - } - - public String writeArchive() throws IOException - { - String zipFilename; - - writeHabits(); - zipFilename = writeZipFile(); - cleanup(); - - return zipFilename; - } - - private void cleanup() - { - for(String filename : generateFilenames) - new File(exportDirName + filename).delete(); - - for(String filename : generateDirs) - new File(exportDirName + filename).delete(); - - new File(exportDirName).delete(); - } } diff --git a/app/src/main/java/org/isoron/uhabits/io/LoopDBImporter.java b/app/src/main/java/org/isoron/uhabits/io/LoopDBImporter.java index d0037f9e3..23021b5a9 100644 --- a/app/src/main/java/org/isoron/uhabits/io/LoopDBImporter.java +++ b/app/src/main/java/org/isoron/uhabits/io/LoopDBImporter.java @@ -25,6 +25,7 @@ import android.support.annotation.NonNull; import com.activeandroid.ActiveAndroid; +import org.isoron.uhabits.models.*; import org.isoron.uhabits.utils.DatabaseUtils; import org.isoron.uhabits.utils.FileUtils; @@ -36,6 +37,11 @@ import java.io.IOException; */ public class LoopDBImporter extends AbstractImporter { + public LoopDBImporter(HabitList habits) + { + super(habits); + } + @Override public boolean canHandle(@NonNull File file) throws IOException { diff --git a/app/src/main/java/org/isoron/uhabits/io/RewireDBImporter.java b/app/src/main/java/org/isoron/uhabits/io/RewireDBImporter.java index e9d1d4c83..2717f4eb0 100644 --- a/app/src/main/java/org/isoron/uhabits/io/RewireDBImporter.java +++ b/app/src/main/java/org/isoron/uhabits/io/RewireDBImporter.java @@ -35,6 +35,11 @@ import java.util.*; */ public class RewireDBImporter extends AbstractImporter { + public RewireDBImporter(HabitList habits) + { + super(habits); + } + @Override public boolean canHandle(@NonNull File file) throws IOException { @@ -157,7 +162,7 @@ public class RewireDBImporter extends AbstractImporter } habit.setFrequency(new Frequency(numerator, denominator)); - habitList.add(habit); + habits.add(habit); createReminder(db, habit, id); createCheckmarks(db, habit, id); @@ -202,7 +207,7 @@ public class RewireDBImporter extends AbstractImporter Reminder reminder = new Reminder(hour, minute, days); habit.setReminder(reminder); - habitList.update(habit); + habits.update(habit); } finally { diff --git a/app/src/main/java/org/isoron/uhabits/io/TickmateDBImporter.java b/app/src/main/java/org/isoron/uhabits/io/TickmateDBImporter.java index 3494468ea..47bdd09ad 100644 --- a/app/src/main/java/org/isoron/uhabits/io/TickmateDBImporter.java +++ b/app/src/main/java/org/isoron/uhabits/io/TickmateDBImporter.java @@ -36,6 +36,11 @@ import java.util.GregorianCalendar; */ public class TickmateDBImporter extends AbstractImporter { + public TickmateDBImporter(HabitList habits) + { + super(habits); + } + @Override public boolean canHandle(@NonNull File file) throws IOException { @@ -118,7 +123,7 @@ public class TickmateDBImporter extends AbstractImporter habit.setName(name); habit.setDescription(description); habit.setFrequency(Frequency.DAILY); - habitList.add(habit); + habits.add(habit); createCheckmarks(db, habit, id); diff --git a/app/src/main/java/org/isoron/uhabits/models/HabitList.java b/app/src/main/java/org/isoron/uhabits/models/HabitList.java index 4bd211e7e..6340ca6cc 100644 --- a/app/src/main/java/org/isoron/uhabits/models/HabitList.java +++ b/app/src/main/java/org/isoron/uhabits/models/HabitList.java @@ -31,10 +31,13 @@ import java.util.*; /** * An ordered collection of {@link Habit}s. */ -public abstract class HabitList +public abstract class HabitList implements Iterable { private ModelObservable observable; + @NonNull + protected final HabitMatcher filter; + /** * Creates a new HabitList. *

@@ -45,6 +48,15 @@ public abstract class HabitList public HabitList() { observable = new ModelObservable(); + filter = new HabitMatcherBuilder() + .setArchivedAllowed(true) + .build(); + } + + protected HabitList(@NonNull HabitMatcher filter) + { + observable = new ModelObservable(); + this.filter = filter; } /** @@ -61,30 +73,6 @@ public abstract class HabitList public abstract void add(@NonNull Habit habit) throws IllegalArgumentException; - /** - * Returns the total number of active habits. - * - * @return number of active habits - */ - public abstract int countActive(); - - /** - * Returns the total number of habits, including archived habits. - * - * @return number of habits, including archived - */ - public abstract int countWithArchived(); - - /** - * Returns a list of all habits, optionally including archived habits. - * - * @param includeArchive whether archived habits should be included the - * list - * @return list of all habits - */ - @NonNull - public abstract List getAll(boolean includeArchive); - /** * Returns the habit with specified id. * @@ -110,30 +98,13 @@ public abstract class HabitList * @return the list of matching habits */ @NonNull - public List getFiltered(HabitMatcher matcher) - { - LinkedList habits = new LinkedList<>(); - for (Habit h : getAll(true)) if (matcher.matches(h)) habits.add(h); - return habits; - } + public abstract HabitList getFiltered(HabitMatcher matcher); public ModelObservable getObservable() { return observable; } - /** - * Returns a list the habits that have a reminder. Does not include archived - * habits. - * - * @return list of habits with reminder - */ - @NonNull - public List getWithReminder() - { - return getFiltered(habit -> habit.hasReminder()); - } - /** * Returns the index of the given habit in the list, or -1 if the list does * not contain the habit. @@ -143,6 +114,11 @@ public abstract class HabitList */ public abstract int indexOf(@NonNull Habit h); + public boolean isEmpty() + { + return size() == 0; + } + /** * Removes the given habit from the list. *

@@ -152,6 +128,16 @@ public abstract class HabitList */ public abstract void remove(@NonNull Habit h); + /** + * Removes all the habits from the list. + */ + public void removeAll() + { + List copy = new LinkedList<>(); + for (Habit h : this) copy.add(h); + for (Habit h : copy) remove(h); + } + /** * Changes the position of a habit in the list. * @@ -160,6 +146,13 @@ public abstract class HabitList */ public abstract void reorder(Habit from, Habit to); + /** + * Returns the number of habits in this list. + * + * @return number of habits + */ + public abstract int size(); + /** * Notifies the list that a certain list of habits has been modified. *

@@ -206,7 +199,7 @@ public abstract class HabitList CSVWriter csv = new CSVWriter(out); csv.writeNext(header, false); - for (Habit habit : getAll(true)) + for (Habit habit : this) { Frequency freq = habit.getFrequency(); @@ -224,19 +217,4 @@ public abstract class HabitList csv.close(); } - - /** - * A HabitMatcher decides whether habits match or not a certain condition. - * They can be used to produce filtered lists of habits. - */ - public interface HabitMatcher - { - /** - * Returns true if the given habit matches. - * - * @param habit the habit to be checked. - * @return true if matches, false otherwise. - */ - boolean matches(Habit habit); - } } diff --git a/app/src/main/java/org/isoron/uhabits/models/HabitMatcher.java b/app/src/main/java/org/isoron/uhabits/models/HabitMatcher.java new file mode 100644 index 000000000..f33591a52 --- /dev/null +++ b/app/src/main/java/org/isoron/uhabits/models/HabitMatcher.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2016 Álinson Santos Xavier + * + * This file is part of Loop Habit Tracker. + * + * Loop Habit Tracker is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * Loop Habit Tracker is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +package org.isoron.uhabits.models; + +import static org.isoron.uhabits.models.Checkmark.*; + +public class HabitMatcher +{ + public static final HabitMatcher WITH_ALARM = new HabitMatcherBuilder() + .setArchivedAllowed(true) + .setReminderRequired(true) + .build(); + + private final boolean archivedAllowed; + + private final boolean reminderRequired; + + private final boolean completedAllowed; + + public HabitMatcher(boolean allowArchived, + boolean reminderRequired, + boolean completedAllowed) + { + this.archivedAllowed = allowArchived; + this.reminderRequired = reminderRequired; + this.completedAllowed = completedAllowed; + } + + public boolean isArchivedAllowed() + { + return archivedAllowed; + } + + public boolean isCompletedAllowed() + { + return completedAllowed; + } + + public boolean isReminderRequired() + { + return reminderRequired; + } + + public boolean matches(Habit habit) + { + if (!isArchivedAllowed() && habit.isArchived()) return false; + if (isReminderRequired() && !habit.hasReminder()) return false; + + int todayCheckmark = habit.getCheckmarks().getTodayValue(); + if (todayCheckmark != UNCHECKED && !isCompletedAllowed()) return false; + + return true; + } +} diff --git a/app/src/main/java/org/isoron/uhabits/models/HabitMatcherBuilder.java b/app/src/main/java/org/isoron/uhabits/models/HabitMatcherBuilder.java new file mode 100644 index 000000000..9fd99061e --- /dev/null +++ b/app/src/main/java/org/isoron/uhabits/models/HabitMatcherBuilder.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2016 Álinson Santos Xavier + * + * This file is part of Loop Habit Tracker. + * + * Loop Habit Tracker is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * Loop Habit Tracker is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +package org.isoron.uhabits.models; + +public class HabitMatcherBuilder +{ + private boolean archivedAllowed = false; + + private boolean reminderRequired = false; + + private boolean completedAllowed = true; + + public HabitMatcher build() + { + return new HabitMatcher(archivedAllowed, reminderRequired, + completedAllowed); + } + + public HabitMatcherBuilder setArchivedAllowed(boolean archivedAllowed) + { + this.archivedAllowed = archivedAllowed; + return this; + } + + public HabitMatcherBuilder setCompletedAllowed(boolean completedAllowed) + { + this.completedAllowed = completedAllowed; + return this; + } + + public HabitMatcherBuilder setReminderRequired(boolean reminderRequired) + { + this.reminderRequired = reminderRequired; + return this; + } +} \ No newline at end of file diff --git a/app/src/main/java/org/isoron/uhabits/models/memory/MemoryHabitList.java b/app/src/main/java/org/isoron/uhabits/models/memory/MemoryHabitList.java index d0f76dbce..faa835b68 100644 --- a/app/src/main/java/org/isoron/uhabits/models/memory/MemoryHabitList.java +++ b/app/src/main/java/org/isoron/uhabits/models/memory/MemoryHabitList.java @@ -35,6 +35,13 @@ public class MemoryHabitList extends HabitList public MemoryHabitList() { + super(); + list = new LinkedList<>(); + } + + protected MemoryHabitList(@NonNull HabitMatcher matcher) + { + super(matcher); list = new LinkedList<>(); } @@ -53,45 +60,42 @@ public class MemoryHabitList extends HabitList } @Override - public int countActive() + public Habit getById(long id) { - int count = 0; - for (Habit h : list) if (!h.isArchived()) count++; - return count; + for (Habit h : list) + { + if (h.getId() == null) continue; + if (h.getId() == id) return h; + } + return null; } + @Nullable @Override - public int countWithArchived() + public Habit getByPosition(int position) { - return list.size(); + return list.get(position); } @NonNull @Override - public List getAll(boolean includeArchive) - { - if (includeArchive) return new LinkedList<>(list); - return getFiltered(habit -> !habit.isArchived()); - } - - @Override - public Habit getById(long id) + public HabitList getFiltered(HabitMatcher matcher) { - for (Habit h : list) if (h.getId() == id) return h; - return null; + MemoryHabitList habits = new MemoryHabitList(matcher); + for(Habit h : this) if (matcher.matches(h)) habits.add(h); + return habits; } - @Nullable @Override - public Habit getByPosition(int position) + public int indexOf(@NonNull Habit h) { - return list.get(position); + return list.indexOf(h); } @Override - public int indexOf(@NonNull Habit h) + public Iterator iterator() { - return list.indexOf(h); + return Collections.unmodifiableCollection(list).iterator(); } @Override @@ -108,6 +112,12 @@ public class MemoryHabitList extends HabitList list.add(toPos, from); } + @Override + public int size() + { + return list.size(); + } + @Override public void update(List habits) { diff --git a/app/src/main/java/org/isoron/uhabits/models/sqlite/SQLiteHabitList.java b/app/src/main/java/org/isoron/uhabits/models/sqlite/SQLiteHabitList.java index 4a366dac4..7ced8ae6a 100644 --- a/app/src/main/java/org/isoron/uhabits/models/sqlite/SQLiteHabitList.java +++ b/app/src/main/java/org/isoron/uhabits/models/sqlite/SQLiteHabitList.java @@ -19,12 +19,11 @@ package org.isoron.uhabits.models.sqlite; -import android.database.sqlite.*; import android.support.annotation.*; -import com.activeandroid.*; import com.activeandroid.query.*; +import org.apache.commons.lang3.*; import org.isoron.uhabits.models.*; import org.isoron.uhabits.models.sqlite.records.*; @@ -41,9 +40,17 @@ public class SQLiteHabitList extends HabitList private final SQLiteUtils sqlite; + protected SQLiteHabitList() + { + super(); + cache = new HashMap<>(); + sqlite = new SQLiteUtils<>(HabitRecord.class); + } - private SQLiteHabitList() + protected SQLiteHabitList( + @NonNull org.isoron.uhabits.models.HabitMatcher filter) { + super(filter); cache = new HashMap<>(); sqlite = new SQLiteUtils<>(HabitRecord.class); } @@ -70,7 +77,7 @@ public class SQLiteHabitList extends HabitList HabitRecord record = new HabitRecord(); record.copyFrom(habit); - record.position = countWithArchived(); + record.position = size(); Long id = habit.getId(); if (id == null) id = record.save(); @@ -80,52 +87,6 @@ public class SQLiteHabitList extends HabitList cache.put(id, habit); } - @Override - public int countActive() - { - SQLiteDatabase db = Cache.openDatabase(); - SQLiteStatement st = db.compileStatement( - "select count(*) from habits where archived = 0"); - return (int) st.simpleQueryForLong(); - } - - @Override - public int countWithArchived() - { - SQLiteDatabase db = Cache.openDatabase(); - SQLiteStatement st = db.compileStatement("select count(*) from habits"); - return (int) st.simpleQueryForLong(); - } - - @Override - @NonNull - public List getAll(boolean includeArchive) - { - List recordList; - if (includeArchive) - { - String query = HabitRecord.SELECT + "order by position"; - recordList = sqlite.query(query, null); - } - else - { - String query = HabitRecord.SELECT + "where archived = 0 " + - "order by position"; - recordList = sqlite.query(query, null); - } - - List habits = new LinkedList<>(); - for (HabitRecord record : recordList) - { - Habit habit = getById(record.getId()); - if (habit == null) - throw new RuntimeException("habit not in database"); - habits.add(habit); - } - - return habits; - } - @Override @Nullable public Habit getById(long id) @@ -147,26 +108,36 @@ public class SQLiteHabitList extends HabitList @Nullable public Habit getByPosition(int position) { - String query = HabitRecord.SELECT + "where position = ? limit 1"; + String query = buildSelectQuery() + "limit 1 offset ?"; String params[] = { Integer.toString(position) }; HabitRecord record = sqlite.querySingle(query, params); if (record != null) return getById(record.getId()); return null; } + @NonNull + @Override + public HabitList getFiltered(org.isoron.uhabits.models.HabitMatcher filter) + { + return new SQLiteHabitList(filter); + } + @Override public int indexOf(@NonNull Habit h) { - if (h.getId() == null) return -1; - HabitRecord record = HabitRecord.get(h.getId()); - if (record == null) return -1; - return record.position; + return toList().indexOf(h); + } + + @Override + public Iterator iterator() + { + return Collections.unmodifiableCollection(toList()).iterator(); } @Deprecated public void rebuildOrder() { - List habits = getAll(true); + List habits = toList(); int i = 0; for (Habit h : habits) @@ -195,6 +166,16 @@ public class SQLiteHabitList extends HabitList rebuildOrder(); } + @Override + public void removeAll() + { + sqlite.query("delete from checkmarks", null); + sqlite.query("delete from score", null); + sqlite.query("delete from streak", null); + sqlite.query("delete from repetitions", null); + sqlite.query("delete from habits", null); + } + @Override public void reorder(Habit from, Habit to) { @@ -228,6 +209,16 @@ public class SQLiteHabitList extends HabitList getObservable().notifyListeners(); } + @Override + public int size() + { +// SQLiteDatabase db = Cache.openDatabase(); +// SQLiteStatement st = db.compileStatement(buildCountQuery()); +// return (int) st.simpleQueryForLong(); + + return toList().size(); + } + @Override public void update(List habits) { @@ -241,4 +232,66 @@ public class SQLiteHabitList extends HabitList } } + protected List toList() + { + String query = buildSelectQuery(); + List recordList = sqlite.query(query, null); + + List habits = new LinkedList<>(); + for (HabitRecord record : recordList) + { + Habit habit = getById(record.getId()); + if (habit == null) + throw new RuntimeException("habit not in database"); + + if(!filter.matches(habit)) continue; + habits.add(habit); + } + + return habits; + } + + private void appendCount(StringBuilder query) + { + query.append("select count (*) from habits "); + } + + private void appendOrderBy(StringBuilder query) + { + query.append("order by position "); + } + + private void appendSelect(StringBuilder query) + { + query.append(HabitRecord.SELECT); + } + + private void appendWhere(StringBuilder query) + { + ArrayList where = new ArrayList<>(); + if (filter.isReminderRequired()) where.add("reminder_hour is not null"); + if (!filter.isArchivedAllowed()) where.add("archived = 0"); + + if(where.isEmpty()) return; + query.append("where "); + query.append(StringUtils.join(where, " and ")); + query.append(" "); + } + + private String buildCountQuery() + { + StringBuilder query = new StringBuilder(); + appendCount(query); + appendWhere(query); + return query.toString(); + } + + private String buildSelectQuery() + { + StringBuilder query = new StringBuilder(); + appendSelect(query); + appendWhere(query); + appendOrderBy(query); + return query.toString(); + } } diff --git a/app/src/main/java/org/isoron/uhabits/models/sqlite/records/HabitRecord.java b/app/src/main/java/org/isoron/uhabits/models/sqlite/records/HabitRecord.java index 154312264..25d124927 100644 --- a/app/src/main/java/org/isoron/uhabits/models/sqlite/records/HabitRecord.java +++ b/app/src/main/java/org/isoron/uhabits/models/sqlite/records/HabitRecord.java @@ -82,7 +82,6 @@ public class HabitRecord extends Model implements SQLiteRecord public HabitRecord() { - } @Nullable @@ -149,7 +148,7 @@ public class HabitRecord extends Model implements SQLiteRecord this.freqNum = freq.getNumerator(); this.freqDen = freq.getDenominator(); - if(model.hasReminder()) + if (model.hasReminder()) { Reminder reminder = model.getReminder(); this.reminderHour = reminder.getHour(); diff --git a/app/src/main/java/org/isoron/uhabits/tasks/ExportCSVTask.java b/app/src/main/java/org/isoron/uhabits/tasks/ExportCSVTask.java index 1eb23a12a..e0dd067ce 100644 --- a/app/src/main/java/org/isoron/uhabits/tasks/ExportCSVTask.java +++ b/app/src/main/java/org/isoron/uhabits/tasks/ExportCSVTask.java @@ -19,30 +19,33 @@ package org.isoron.uhabits.tasks; -import android.support.annotation.Nullable; +import android.support.annotation.*; -import org.isoron.uhabits.io.HabitsCSVExporter; -import org.isoron.uhabits.models.Habit; -import org.isoron.uhabits.utils.FileUtils; +import org.isoron.uhabits.io.*; +import org.isoron.uhabits.models.*; +import org.isoron.uhabits.utils.*; -import java.io.File; -import java.io.IOException; -import java.util.List; +import java.io.*; +import java.util.*; public class ExportCSVTask extends BaseTask { - public interface Listener - { - void onExportCSVFinished(@Nullable String archiveFilename); - } - private ProgressBar progressBar; + private final List selectedHabits; + private String archiveFilename; + private ExportCSVTask.Listener listener; - public ExportCSVTask(List selectedHabits, ProgressBar progressBar) + @NonNull + private final HabitList habitList; + + public ExportCSVTask(HabitList habitList, + List selectedHabits, + ProgressBar progressBar) { + this.habitList = habitList; this.selectedHabits = selectedHabits; this.progressBar = progressBar; } @@ -53,36 +56,41 @@ public class ExportCSVTask extends BaseTask } @Override - protected void onPreExecute() + protected void doInBackground() { - super.onPreExecute(); - if(progressBar != null) progressBar.show(); + try + { + File dir = FileUtils.getFilesDir("CSV"); + if (dir == null) return; + + HabitsCSVExporter exporter = + new HabitsCSVExporter(habitList, selectedHabits, dir); + archiveFilename = exporter.writeArchive(); + } + catch (IOException e) + { + e.printStackTrace(); + } } @Override protected void onPostExecute(Void aVoid) { - if(listener != null) - listener.onExportCSVFinished(archiveFilename); + if (listener != null) listener.onExportCSVFinished(archiveFilename); - if(progressBar != null) progressBar.hide(); + if (progressBar != null) progressBar.hide(); super.onPostExecute(null); } @Override - protected void doInBackground() + protected void onPreExecute() { - try - { - File dir = FileUtils.getFilesDir("CSV"); - if(dir == null) return; + super.onPreExecute(); + if (progressBar != null) progressBar.show(); + } - HabitsCSVExporter exporter = new HabitsCSVExporter(selectedHabits, dir); - archiveFilename = exporter.writeArchive(); - } - catch (IOException e) - { - e.printStackTrace(); - } + public interface Listener + { + void onExportCSVFinished(@Nullable String archiveFilename); } } diff --git a/app/src/main/java/org/isoron/uhabits/tasks/ImportDataTask.java b/app/src/main/java/org/isoron/uhabits/tasks/ImportDataTask.java index cdc6c538a..0d6ef6705 100644 --- a/app/src/main/java/org/isoron/uhabits/tasks/ImportDataTask.java +++ b/app/src/main/java/org/isoron/uhabits/tasks/ImportDataTask.java @@ -19,23 +19,20 @@ package org.isoron.uhabits.tasks; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; +import android.support.annotation.*; -import org.isoron.uhabits.io.GenericImporter; +import org.isoron.uhabits.io.*; +import org.isoron.uhabits.models.*; -import java.io.File; +import java.io.*; public class ImportDataTask extends BaseTask { - public static final int SUCCESS = 1; - public static final int NOT_RECOGNIZED = 2; public static final int FAILED = 3; - public interface Listener - { - void onImportDataFinished(int result); - } + public static final int NOT_RECOGNIZED = 2; + + public static final int SUCCESS = 1; @Nullable private final ProgressBar progressBar; @@ -48,8 +45,14 @@ public class ImportDataTask extends BaseTask int result; - public ImportDataTask(@NonNull File file, @Nullable ProgressBar progressBar) + @NonNull + private HabitList habits; + + public ImportDataTask(@NonNull HabitList habits, + @NonNull File file, + @Nullable ProgressBar progressBar) { + this.habits = habits; this.file = file; this.progressBar = progressBar; } @@ -59,29 +62,13 @@ public class ImportDataTask extends BaseTask this.listener = listener; } - @Override - protected void onPreExecute() - { - super.onPreExecute(); - - if(progressBar != null) progressBar.show(); - } - - @Override - protected void onPostExecute(Void aVoid) - { - if(progressBar != null) progressBar.hide(); - if(listener != null) listener.onImportDataFinished(result); - super.onPostExecute(null); - } - @Override protected void doInBackground() { try { - GenericImporter importer = new GenericImporter(); - if(importer.canHandle(file)) + GenericImporter importer = new GenericImporter(habits); + if (importer.canHandle(file)) { importer.importHabitsFromFile(file); result = SUCCESS; @@ -97,4 +84,25 @@ public class ImportDataTask extends BaseTask e.printStackTrace(); } } + + @Override + protected void onPostExecute(Void aVoid) + { + if (progressBar != null) progressBar.hide(); + if (listener != null) listener.onImportDataFinished(result); + super.onPostExecute(null); + } + + @Override + protected void onPreExecute() + { + super.onPreExecute(); + + if (progressBar != null) progressBar.show(); + } + + public interface Listener + { + void onImportDataFinished(int result); + } } \ No newline at end of file diff --git a/app/src/main/java/org/isoron/uhabits/ui/habits/edit/CreateHabitDialogFragment.java b/app/src/main/java/org/isoron/uhabits/ui/habits/edit/CreateHabitDialogFragment.java index 28188964d..6479dd000 100644 --- a/app/src/main/java/org/isoron/uhabits/ui/habits/edit/CreateHabitDialogFragment.java +++ b/app/src/main/java/org/isoron/uhabits/ui/habits/edit/CreateHabitDialogFragment.java @@ -40,9 +40,10 @@ public class CreateHabitDialogFragment extends BaseDialogFragment prefs.getDefaultHabitColor(modifiedHabit.getColor())); } + @Override protected void saveHabit() { - Command command = new CreateHabitCommand(modifiedHabit); + Command command = new CreateHabitCommand(habitList, modifiedHabit); commandRunner.execute(command, null); } } diff --git a/app/src/main/java/org/isoron/uhabits/ui/habits/edit/EditHabitDialogFragment.java b/app/src/main/java/org/isoron/uhabits/ui/habits/edit/EditHabitDialogFragment.java index d4e9beb76..478d7d092 100644 --- a/app/src/main/java/org/isoron/uhabits/ui/habits/edit/EditHabitDialogFragment.java +++ b/app/src/main/java/org/isoron/uhabits/ui/habits/edit/EditHabitDialogFragment.java @@ -19,12 +19,11 @@ package org.isoron.uhabits.ui.habits.edit; -import android.os.Bundle; +import android.os.*; -import org.isoron.uhabits.R; -import org.isoron.uhabits.commands.Command; -import org.isoron.uhabits.commands.EditHabitCommand; -import org.isoron.uhabits.models.Habit; +import org.isoron.uhabits.*; +import org.isoron.uhabits.commands.*; +import org.isoron.uhabits.models.*; public class EditHabitDialogFragment extends BaseDialogFragment { @@ -58,7 +57,8 @@ public class EditHabitDialogFragment extends BaseDialogFragment @Override protected void saveHabit() { - Command command = new EditHabitCommand(originalHabit, modifiedHabit); + Command command = + new EditHabitCommand(habitList, originalHabit, modifiedHabit); commandRunner.execute(command, originalHabit.getId()); } } diff --git a/app/src/main/java/org/isoron/uhabits/ui/habits/list/ListHabitsActivity.java b/app/src/main/java/org/isoron/uhabits/ui/habits/list/ListHabitsActivity.java index 2a93436bb..7109fab8f 100644 --- a/app/src/main/java/org/isoron/uhabits/ui/habits/list/ListHabitsActivity.java +++ b/app/src/main/java/org/isoron/uhabits/ui/habits/list/ListHabitsActivity.java @@ -34,7 +34,7 @@ import javax.inject.*; public class ListHabitsActivity extends BaseActivity { @Inject - HabitList habitList; + HabitList habits; private HabitCardListAdapter adapter; @@ -59,14 +59,22 @@ public class ListHabitsActivity extends BaseActivity int checkmarkCount = ListHabitsRootView.MAX_CHECKMARK_COUNT; system = new BaseSystem(this); - adapter = new HabitCardListAdapter(checkmarkCount); + adapter = new HabitCardListAdapter(habits, checkmarkCount); + +// HabitMatcher matcher = new HabitMatcherBuilder() +// .setCompletedAllowed(false) +// .setArchivedAllowed(false) +// .build(); +// adapter.setFilter(matcher); + rootView = new ListHabitsRootView(this, adapter); screen = new ListHabitsScreen(this, rootView); menu = new ListHabitsMenu(this, screen, adapter); - selectionMenu = new ListHabitsSelectionMenu(screen, adapter); - controller = new ListHabitsController(screen, system, habitList); + selectionMenu = new ListHabitsSelectionMenu(habits, screen, adapter); + controller = new ListHabitsController(habits, screen, system); screen.setMenu(menu); + screen.setController(controller); screen.setSelectionMenu(selectionMenu); rootView.setController(controller, selectionMenu); diff --git a/app/src/main/java/org/isoron/uhabits/ui/habits/list/ListHabitsController.java b/app/src/main/java/org/isoron/uhabits/ui/habits/list/ListHabitsController.java index 8e2c69352..4383c7122 100644 --- a/app/src/main/java/org/isoron/uhabits/ui/habits/list/ListHabitsController.java +++ b/app/src/main/java/org/isoron/uhabits/ui/habits/list/ListHabitsController.java @@ -31,6 +31,7 @@ import org.isoron.uhabits.ui.habits.list.controllers.*; import org.isoron.uhabits.utils.*; import java.io.*; +import java.util.*; import javax.inject.*; @@ -52,9 +53,9 @@ public class ListHabitsController @Inject CommandRunner commandRunner; - public ListHabitsController(@NonNull ListHabitsScreen screen, - @NonNull BaseSystem system, - @NonNull HabitList habitList) + public ListHabitsController(@NonNull HabitList habitList, + @NonNull ListHabitsScreen screen, + @NonNull BaseSystem system) { this.screen = screen; this.system = system; @@ -64,8 +65,13 @@ public class ListHabitsController public void onExportCSV() { + List selected = new LinkedList<>(); + for (Habit h : habitList) selected.add(h); + + ProgressBar progressBar = screen.getProgressBar(); ExportCSVTask task = - new ExportCSVTask(habitList.getAll(true), screen.getProgressBar()); + new ExportCSVTask(habitList, selected, progressBar); + task.setListener(filename -> { if (filename != null) screen.showSendFileScreen(filename); else screen.showMessage(R.string.could_not_export); @@ -97,7 +103,8 @@ public class ListHabitsController public void onImportData(@NonNull File file) { - ImportDataTask task = new ImportDataTask(file, screen.getProgressBar()); + ProgressBar bar = screen.getProgressBar(); + ImportDataTask task = new ImportDataTask(habitList, file, bar); task.setListener(this); task.execute(); } diff --git a/app/src/main/java/org/isoron/uhabits/ui/habits/list/ListHabitsScreen.java b/app/src/main/java/org/isoron/uhabits/ui/habits/list/ListHabitsScreen.java index 8d22d5eb0..2440126c9 100644 --- a/app/src/main/java/org/isoron/uhabits/ui/habits/list/ListHabitsScreen.java +++ b/app/src/main/java/org/isoron/uhabits/ui/habits/list/ListHabitsScreen.java @@ -76,6 +76,11 @@ public class ListHabitsScreen extends BaseScreen } } + public void setController(@Nullable ListHabitsController controller) + { + this.controller = controller; + } + public void showAboutScreen() { Intent intent = new Intent(activity, AboutActivity.class); diff --git a/app/src/main/java/org/isoron/uhabits/ui/habits/list/ListHabitsSelectionMenu.java b/app/src/main/java/org/isoron/uhabits/ui/habits/list/ListHabitsSelectionMenu.java index 07980edca..a9eb8d747 100644 --- a/app/src/main/java/org/isoron/uhabits/ui/habits/list/ListHabitsSelectionMenu.java +++ b/app/src/main/java/org/isoron/uhabits/ui/habits/list/ListHabitsSelectionMenu.java @@ -48,9 +48,14 @@ public class ListHabitsSelectionMenu extends BaseSelectionMenu @Nullable private HabitCardListController listController; - public ListHabitsSelectionMenu(@NonNull ListHabitsScreen screen, - HabitCardListAdapter listAdapter) + @NonNull + private final HabitList habitList; + + public ListHabitsSelectionMenu(@NonNull HabitList habitList, + @NonNull ListHabitsScreen screen, + @NonNull HabitCardListAdapter listAdapter) { + this.habitList = habitList; this.screen = screen; HabitsApplication.getComponent().inject(this); this.listAdapter = listAdapter; @@ -161,13 +166,15 @@ public class ListHabitsSelectionMenu extends BaseSelectionMenu private void archive(@NonNull List selected) { - commandRunner.execute(new ArchiveHabitsCommand(selected), null); + commandRunner.execute(new ArchiveHabitsCommand(habitList, selected), + null); } private void delete(@NonNull List selected) { screen.showDeleteConfirmationScreen(() -> { - commandRunner.execute(new DeleteHabitsCommand(selected), null); + commandRunner.execute(new DeleteHabitsCommand(habitList, selected), + null); finish(); }); } @@ -181,14 +188,15 @@ public class ListHabitsSelectionMenu extends BaseSelectionMenu @NonNull Habit firstHabit) { screen.showColorPicker(firstHabit, color -> { - commandRunner.execute(new ChangeHabitColorCommand(selected, color), - null); + commandRunner.execute( + new ChangeHabitColorCommand(habitList, selected, color), null); finish(); }); } private void unarchive(@NonNull List selected) { - commandRunner.execute(new UnarchiveHabitsCommand(selected), null); + commandRunner.execute(new UnarchiveHabitsCommand(habitList, selected), + null); } } diff --git a/app/src/main/java/org/isoron/uhabits/ui/habits/list/model/HabitCardListAdapter.java b/app/src/main/java/org/isoron/uhabits/ui/habits/list/model/HabitCardListAdapter.java index 0f9dab743..18496edec 100644 --- a/app/src/main/java/org/isoron/uhabits/ui/habits/list/model/HabitCardListAdapter.java +++ b/app/src/main/java/org/isoron/uhabits/ui/habits/list/model/HabitCardListAdapter.java @@ -50,14 +50,15 @@ public class HabitCardListAdapter extends BaseAdapter @NonNull private final HabitCardListCache cache; - public HabitCardListAdapter(int checkmarkCount) + public HabitCardListAdapter(@NonNull HabitList allHabits, + int checkmarkCount) { this.selected = new LinkedList<>(); this.observable = new ModelObservable(); HabitsApplication.getComponent().inject(this); - cache = new HabitCardListCache(); + cache = new HabitCardListCache(allHabits); cache.setListener(this); cache.setCheckmarkCount(checkmarkCount); } @@ -185,6 +186,11 @@ public class HabitCardListAdapter extends BaseAdapter cache.reorder(from, to); } + public void setFilter(HabitMatcher matcher) + { + cache.setFilter(matcher); + } + /** * Sets the HabitCardListView that this adapter will provide data for. *

diff --git a/app/src/main/java/org/isoron/uhabits/ui/habits/list/model/HabitCardListCache.java b/app/src/main/java/org/isoron/uhabits/ui/habits/list/model/HabitCardListCache.java index 65a3fb9ed..6edb3be10 100644 --- a/app/src/main/java/org/isoron/uhabits/ui/habits/list/model/HabitCardListCache.java +++ b/app/src/main/java/org/isoron/uhabits/ui/habits/list/model/HabitCardListCache.java @@ -60,19 +60,23 @@ public class HabitCardListCache implements CommandRunner.Listener @Inject CommandRunner commandRunner; - @Inject - HabitList allHabits; + @NonNull + private HabitList allHabits; + + @NonNull + private HabitList filteredHabits; - public HabitCardListCache() + public HabitCardListCache(@NonNull HabitList allHabits) { + this.allHabits = allHabits; + this.filteredHabits = allHabits; data = new CacheData(); HabitsApplication.getComponent().inject(this); } public void cancelTasks() { - if(currentFetchTask != null) - currentFetchTask.cancel(true); + if (currentFetchTask != null) currentFetchTask.cancel(true); } public int[] getCheckmarks(long habitId) @@ -90,7 +94,7 @@ public class HabitCardListCache implements CommandRunner.Listener @NonNull public Habit getHabitByPosition(int position) { - return data.habitsList.get(position); + return data.habits.get(position); } public int getHabitCount() @@ -98,6 +102,16 @@ public class HabitCardListCache implements CommandRunner.Listener return data.habits.size(); } + public boolean getIncludeArchived() + { + return includeArchived; + } + + public void setIncludeArchived(boolean includeArchived) + { + this.includeArchived = includeArchived; + } + @Nullable public Long getLastLoadTimestamp() { @@ -109,11 +123,6 @@ public class HabitCardListCache implements CommandRunner.Listener return data.scores.get(habitId); } - public boolean getIncludeArchived() - { - return includeArchived; - } - public void onAttached() { refreshAllHabits(true); @@ -149,10 +158,10 @@ public class HabitCardListCache implements CommandRunner.Listener public void reorder(int from, int to) { - Habit fromHabit = data.habitsList.get(from); - data.habitsList.remove(from); - data.habitsList.add(to, fromHabit); - if(listener != null) listener.onCacheRefresh(); + Habit fromHabit = data.habits.get(from); + data.habits.remove(from); + data.habits.add(to, fromHabit); + if (listener != null) listener.onCacheRefresh(); } public void setCheckmarkCount(int checkmarkCount) @@ -160,9 +169,9 @@ public class HabitCardListCache implements CommandRunner.Listener this.checkmarkCount = checkmarkCount; } - public void setIncludeArchived(boolean includeArchived) + public void setFilter(HabitMatcher matcher) { - this.includeArchived = includeArchived; + filteredHabits = allHabits.getFiltered(matcher); } public void setListener(@Nullable Listener listener) @@ -185,10 +194,10 @@ public class HabitCardListCache implements CommandRunner.Listener private class CacheData { @NonNull - public HashMap habits; + public HashMap map; @NonNull - public List habitsList; + public List habits; @NonNull public HashMap checkmarks; @@ -201,8 +210,8 @@ public class HabitCardListCache implements CommandRunner.Listener */ public CacheData() { - habits = new HashMap<>(); - habitsList = new LinkedList<>(); + map = new HashMap<>(); + habits = new LinkedList<>(); checkmarks = new HashMap<>(); scores = new HashMap<>(); } @@ -211,7 +220,7 @@ public class HabitCardListCache implements CommandRunner.Listener { int[] empty = new int[checkmarkCount]; - for (Long id : habits.keySet()) + for (Long id : map.keySet()) { if (oldData.checkmarks.containsKey(id)) checkmarks.put(id, oldData.checkmarks.get(id)); @@ -221,7 +230,7 @@ public class HabitCardListCache implements CommandRunner.Listener public void copyScoresFrom(@NonNull CacheData oldData) { - for (Long id : habits.keySet()) + for (Long id : map.keySet()) { if (oldData.scores.containsKey(id)) scores.put(id, oldData.scores.get(id)); @@ -231,9 +240,11 @@ public class HabitCardListCache implements CommandRunner.Listener public void fetchHabits() { - habitsList = allHabits.getAll(includeArchived); - for (Habit h : habitsList) - habits.put(h.getId(), h); + for (Habit h : filteredHabits) + { + habits.add(h); + map.put(h.getId(), h); + } } } @@ -250,11 +261,6 @@ public class HabitCardListCache implements CommandRunner.Listener newData = new CacheData(); } - private void commit() - { - data = newData; - } - @Override protected void doInBackground() { @@ -272,7 +278,7 @@ public class HabitCardListCache implements CommandRunner.Listener dateTo - (checkmarkCount - 1) * DateUtils.millisecondsInOneDay; int current = 0; - for (Habit h : newData.habitsList) + for (Habit h : newData.habits) { if (isCancelled()) return; @@ -282,19 +288,7 @@ public class HabitCardListCache implements CommandRunner.Listener h.getCheckmarks().getValues(dateFrom, dateTo)); // sleep(1000); - publishProgress(current++, newData.habits.size()); - } - } - - private void sleep(int time) - { - try - { - Thread.sleep(time); - } - catch (InterruptedException e) - { - e.printStackTrace(); + publishProgress(current++, newData.map.size()); } } @@ -316,6 +310,23 @@ public class HabitCardListCache implements CommandRunner.Listener if (listener != null) listener.onCacheRefresh(); } + private void commit() + { + data = newData; + } + + private void sleep(int time) + { + try + { + Thread.sleep(time); + } + catch (InterruptedException e) + { + e.printStackTrace(); + } + } + } private class RefreshHabitTask extends BaseTask @@ -337,9 +348,10 @@ public class HabitCardListCache implements CommandRunner.Listener Habit h = allHabits.getById(id); if (h == null) return; - data.habits.put(id, h); + data.map.put(id, h); data.scores.put(id, h.getScores().getTodayValue()); - data.checkmarks.put(id, h.getCheckmarks().getValues(dateFrom, dateTo)); + data.checkmarks.put(id, + h.getCheckmarks().getValues(dateFrom, dateTo)); } @Override diff --git a/app/src/main/java/org/isoron/uhabits/ui/habits/show/ShowHabitActivity.java b/app/src/main/java/org/isoron/uhabits/ui/habits/show/ShowHabitActivity.java index 55e95d4e8..8ee28d5ef 100644 --- a/app/src/main/java/org/isoron/uhabits/ui/habits/show/ShowHabitActivity.java +++ b/app/src/main/java/org/isoron/uhabits/ui/habits/show/ShowHabitActivity.java @@ -38,7 +38,7 @@ import javax.inject.*; public class ShowHabitActivity extends BaseActivity { @Inject - HabitList habitList; + HabitList habits; private ShowHabitController controller; @@ -70,7 +70,7 @@ public class ShowHabitActivity extends BaseActivity private Habit getHabitFromIntent() { Uri data = getIntent().getData(); - Habit habit = habitList.getById(ContentUris.parseId(data)); + Habit habit = habits.getById(ContentUris.parseId(data)); if (habit == null) throw new RuntimeException("habit not found"); return habit; } diff --git a/app/src/main/java/org/isoron/uhabits/ui/widgets/HabitPickerDialog.java b/app/src/main/java/org/isoron/uhabits/ui/widgets/HabitPickerDialog.java index fe4b57de2..fe8bab08e 100644 --- a/app/src/main/java/org/isoron/uhabits/ui/widgets/HabitPickerDialog.java +++ b/app/src/main/java/org/isoron/uhabits/ui/widgets/HabitPickerDialog.java @@ -82,8 +82,7 @@ public class HabitPickerDialog extends Activity habitIds = new ArrayList<>(); ArrayList habitNames = new ArrayList<>(); - List habits = habitList.getAll(false); - for (Habit h : habits) + for (Habit h : habitList) { habitIds.add(h.getId()); habitNames.add(h.getName()); diff --git a/app/src/main/java/org/isoron/uhabits/utils/ReminderUtils.java b/app/src/main/java/org/isoron/uhabits/utils/ReminderUtils.java index 52ab9ed29..4ecb3fe4d 100644 --- a/app/src/main/java/org/isoron/uhabits/utils/ReminderUtils.java +++ b/app/src/main/java/org/isoron/uhabits/utils/ReminderUtils.java @@ -85,16 +85,17 @@ public abstract class ReminderUtils pendingIntent); else manager.set(AlarmManager.RTC_WAKEUP, reminderTime, pendingIntent); - String name = habit.getName().substring(0, Math.min(3, habit.getName().length())); + String name = + habit.getName().substring(0, Math.min(3, habit.getName().length())); Log.d("ReminderHelper", String.format("Setting alarm (%s): %s", DateFormat.getDateTimeInstance().format(new Date(reminderTime)), name)); } - public static void createReminderAlarms(Context context, - HabitList habitList) + public static void createReminderAlarms(Context context, HabitList habits) { - for (Habit habit : habitList.getWithReminder()) + HabitList reminderHabits = habits.getFiltered(HabitMatcher.WITH_ALARM); + for (Habit habit : reminderHabits) createReminderAlarm(context, habit, null); } diff --git a/app/src/main/java/org/isoron/uhabits/widgets/BaseWidgetProvider.java b/app/src/main/java/org/isoron/uhabits/widgets/BaseWidgetProvider.java index 89d91e2f4..93249ed2a 100644 --- a/app/src/main/java/org/isoron/uhabits/widgets/BaseWidgetProvider.java +++ b/app/src/main/java/org/isoron/uhabits/widgets/BaseWidgetProvider.java @@ -39,7 +39,7 @@ import static org.isoron.uhabits.utils.WidgetUtils.*; public abstract class BaseWidgetProvider extends AppWidgetProvider { @Inject - HabitList habitList; + HabitList habits; @Inject WidgetPreferences widgetPrefs; @@ -105,7 +105,7 @@ public abstract class BaseWidgetProvider extends AppWidgetProvider protected Habit getHabitFromWidgetId(int widgetId) { long habitId = widgetPrefs.getHabitIdFromWidgetId(widgetId); - Habit habit = habitList.getById(habitId); + Habit habit = habits.getById(habitId); if (habit == null) throw new RuntimeException("habit not found"); return habit; } diff --git a/app/src/test/java/org/isoron/uhabits/commands/ArchiveHabitsCommandTest.java b/app/src/test/java/org/isoron/uhabits/commands/ArchiveHabitsCommandTest.java index 3ef68aaed..fe2a61d3e 100644 --- a/app/src/test/java/org/isoron/uhabits/commands/ArchiveHabitsCommandTest.java +++ b/app/src/test/java/org/isoron/uhabits/commands/ArchiveHabitsCommandTest.java @@ -40,7 +40,8 @@ public class ArchiveHabitsCommandTest extends BaseUnitTest super.setUp(); habit = fixtures.createShortHabit(); - command = new ArchiveHabitsCommand(Collections.singletonList(habit)); + command = new ArchiveHabitsCommand(habitList, Collections + .singletonList(habit)); } @Test diff --git a/app/src/test/java/org/isoron/uhabits/commands/ChangeHabitColorCommandTest.java b/app/src/test/java/org/isoron/uhabits/commands/ChangeHabitColorCommandTest.java index 70d60bad5..7e2a40b0a 100644 --- a/app/src/test/java/org/isoron/uhabits/commands/ChangeHabitColorCommandTest.java +++ b/app/src/test/java/org/isoron/uhabits/commands/ChangeHabitColorCommandTest.java @@ -49,7 +49,7 @@ public class ChangeHabitColorCommandTest extends BaseUnitTest habits.add(habit); } - command = new ChangeHabitColorCommand(habits, 0); + command = new ChangeHabitColorCommand(habitList, habits, 0); } @Test diff --git a/app/src/test/java/org/isoron/uhabits/commands/CreateHabitCommandTest.java b/app/src/test/java/org/isoron/uhabits/commands/CreateHabitCommandTest.java index f5adaf27d..6a79f78f4 100644 --- a/app/src/test/java/org/isoron/uhabits/commands/CreateHabitCommandTest.java +++ b/app/src/test/java/org/isoron/uhabits/commands/CreateHabitCommandTest.java @@ -23,8 +23,6 @@ import org.isoron.uhabits.*; import org.isoron.uhabits.models.*; import org.junit.*; -import java.util.*; - import static junit.framework.Assert.*; import static org.hamcrest.CoreMatchers.*; import static org.hamcrest.MatcherAssert.*; @@ -44,32 +42,30 @@ public class CreateHabitCommandTest extends BaseUnitTest model = new Habit(); model.setName("New habit"); - command = new CreateHabitCommand(model); + command = new CreateHabitCommand(habitList, model); fixtures.purgeHabits(); } @Test public void testExecuteUndoRedo() { - assertTrue(habitList.getAll(true).isEmpty()); + assertTrue(habitList.isEmpty()); command.execute(); - List allHabits = habitList.getAll(true); - assertThat(allHabits.size(), equalTo(1)); + assertThat(habitList.size(), equalTo(1)); - Habit habit = allHabits.get(0); + Habit habit = habitList.getByPosition(0); Long id = habit.getId(); assertThat(habit.getName(), equalTo(model.getName())); command.undo(); - assertTrue(habitList.getAll(true).isEmpty()); + assertTrue(habitList.isEmpty()); command.execute(); - allHabits = habitList.getAll(true); - assertThat(allHabits.size(), equalTo(1)); + assertThat(habitList.size(), equalTo(1)); - habit = allHabits.get(0); + habit = habitList.getByPosition(0); Long newId = habit.getId(); assertThat(id, equalTo(newId)); assertThat(habit.getName(), equalTo(model.getName())); diff --git a/app/src/test/java/org/isoron/uhabits/commands/DeleteHabitsCommandTest.java b/app/src/test/java/org/isoron/uhabits/commands/DeleteHabitsCommandTest.java index 28055da8b..03cc0d6e5 100644 --- a/app/src/test/java/org/isoron/uhabits/commands/DeleteHabitsCommandTest.java +++ b/app/src/test/java/org/isoron/uhabits/commands/DeleteHabitsCommandTest.java @@ -58,17 +58,17 @@ public class DeleteHabitsCommandTest extends BaseUnitTest Habit extraHabit = fixtures.createShortHabit(); extraHabit.setName("extra"); - command = new DeleteHabitsCommand(habits); + command = new DeleteHabitsCommand(habitList, habits); } @Test public void testExecuteUndoRedo() { - assertThat(habitList.getAll(true).size(), equalTo(4)); + assertThat(habitList.size(), equalTo(4)); command.execute(); - assertThat(habitList.getAll(true).size(), equalTo(1)); - assertThat(habitList.getAll(true).get(0).getName(), equalTo("extra")); + assertThat(habitList.size(), equalTo(1)); + assertThat(habitList.getByPosition(0).getName(), equalTo("extra")); thrown.expect(UnsupportedOperationException.class); command.undo(); diff --git a/app/src/test/java/org/isoron/uhabits/commands/EditHabitCommandTest.java b/app/src/test/java/org/isoron/uhabits/commands/EditHabitCommandTest.java index b4f09036a..3ddae815d 100644 --- a/app/src/test/java/org/isoron/uhabits/commands/EditHabitCommandTest.java +++ b/app/src/test/java/org/isoron/uhabits/commands/EditHabitCommandTest.java @@ -53,7 +53,7 @@ public class EditHabitCommandTest extends BaseUnitTest @Test public void testExecuteUndoRedo() { - command = new EditHabitCommand(habit, modified); + command = new EditHabitCommand(habitList, habit, modified); int originalScore = habit.getScores().getTodayValue(); assertThat(habit.getName(), equalTo("original")); @@ -75,7 +75,7 @@ public class EditHabitCommandTest extends BaseUnitTest public void testExecuteUndoRedo_withModifiedInterval() { modified.setFrequency(Frequency.TWO_TIMES_PER_WEEK); - command = new EditHabitCommand(habit, modified); + command = new EditHabitCommand(habitList, habit, modified); int originalScore = habit.getScores().getTodayValue(); assertThat(habit.getName(), equalTo("original")); diff --git a/app/src/test/java/org/isoron/uhabits/commands/UnarchiveHabitsCommandTest.java b/app/src/test/java/org/isoron/uhabits/commands/UnarchiveHabitsCommandTest.java index 1d5eddd73..ee251e0e2 100644 --- a/app/src/test/java/org/isoron/uhabits/commands/UnarchiveHabitsCommandTest.java +++ b/app/src/test/java/org/isoron/uhabits/commands/UnarchiveHabitsCommandTest.java @@ -42,7 +42,9 @@ public class UnarchiveHabitsCommandTest extends BaseUnitTest habit.setArchived(true); habitList.update(habit); - command = new UnarchiveHabitsCommand(Collections.singletonList(habit)); + command = new UnarchiveHabitsCommand(habitList, Collections + .singletonList + (habit)); } @Test diff --git a/app/src/test/java/org/isoron/uhabits/models/HabitFixtures.java b/app/src/test/java/org/isoron/uhabits/models/HabitFixtures.java index 0ff459c30..8b4923f7d 100644 --- a/app/src/test/java/org/isoron/uhabits/models/HabitFixtures.java +++ b/app/src/test/java/org/isoron/uhabits/models/HabitFixtures.java @@ -83,7 +83,6 @@ public class HabitFixtures public void purgeHabits() { - for (Habit h : habitList.getAll(true)) - habitList.remove(h); + habitList.removeAll(); } } diff --git a/app/src/test/java/org/isoron/uhabits/models/HabitListTest.java b/app/src/test/java/org/isoron/uhabits/models/HabitListTest.java index 8d0e4590c..eaef8c0ad 100644 --- a/app/src/test/java/org/isoron/uhabits/models/HabitListTest.java +++ b/app/src/test/java/org/isoron/uhabits/models/HabitListTest.java @@ -32,93 +32,90 @@ import static org.hamcrest.CoreMatchers.*; import static org.hamcrest.MatcherAssert.*; import static org.hamcrest.core.IsEqual.equalTo; +@SuppressWarnings("JavaDoc") public class HabitListTest extends BaseUnitTest { - private HabitList list; + private HabitList allHabits; - private ArrayList habits; + private ArrayList habitsArray; + + private HabitList activeHabits; + + private HabitList reminderHabits; @Override public void setUp() { super.setUp(); - list = modelFactory.buildHabitList(); - habits = new ArrayList<>(); + allHabits = modelFactory.buildHabitList(); + habitsArray = new ArrayList<>(); for (int i = 0; i < 10; i++) { Habit habit = new Habit(); habit.setId((long) i); - habits.add(habit); - list.add(habit); + habitsArray.add(habit); + allHabits.add(habit); if (i % 3 == 0) habit.setReminder(new Reminder(8, 30, DateUtils.ALL_WEEK_DAYS)); } - habits.get(0).setArchived(true); - habits.get(1).setArchived(true); - habits.get(4).setArchived(true); - habits.get(7).setArchived(true); - } - - @Test - public void test_count() - { - assertThat(list.countActive(), equalTo(6)); + habitsArray.get(0).setArchived(true); + habitsArray.get(1).setArchived(true); + habitsArray.get(4).setArchived(true); + habitsArray.get(7).setArchived(true); + + activeHabits = allHabits.getFiltered( + new HabitMatcherBuilder().build()); + reminderHabits = allHabits.getFiltered(new HabitMatcherBuilder() + .setArchivedAllowed(true) + .setReminderRequired(true) + .build()); } @Test - public void test_countWithArchived() + public void testSize() { - assertThat(list.countWithArchived(), equalTo(10)); + assertThat(allHabits.size(), equalTo(10)); } @Test - public void test_getAll() + public void test_countActive() { - List filteredList = list.getAll(false); - - assertThat(filteredList.size(), equalTo(6)); - assertThat(filteredList.contains(habits.get(2)), is(true)); - assertThat(filteredList.contains(habits.get(4)), is(false)); - - filteredList = list.getAll(true); - - assertThat(filteredList.size(), equalTo(10)); - assertThat(filteredList.contains(habits.get(2)), is(true)); - assertThat(filteredList.contains(habits.get(4)), is(true)); + assertThat(activeHabits.size(), equalTo(6)); } @Test public void test_getByPosition() { - assertThat(list.getByPosition(0), equalTo(habits.get(0))); - assertThat(list.getByPosition(3), equalTo(habits.get(3))); - assertThat(list.getByPosition(9), equalTo(habits.get(9))); + assertThat(allHabits.getByPosition(0), equalTo(habitsArray.get(0))); + assertThat(allHabits.getByPosition(3), equalTo(habitsArray.get(3))); + assertThat(allHabits.getByPosition(9), equalTo(habitsArray.get(9))); + + assertThat(activeHabits.getByPosition(0), equalTo(habitsArray.get(2))); } @Test public void test_getHabitsWithReminder() { - List filtered = list.getWithReminder(); - assertThat(filtered.size(), equalTo(4)); - assertThat(filtered.contains(habits.get(0)), equalTo(true)); - assertThat(filtered.contains(habits.get(1)), equalTo(false)); + assertThat(reminderHabits.size(), equalTo(4)); + assertThat(reminderHabits.getByPosition(1), + equalTo(habitsArray.get(3))); } @Test public void test_get_withInvalidId() { - assertThat(list.getById(100L), is(nullValue())); + assertThat(allHabits.getById(100L), is(nullValue())); } @Test public void test_get_withValidId() { - Habit habit1 = habits.get(0); - Habit habit2 = list.getById(habit1.getId()); + Habit habit1 = habitsArray.get(0); + Habit habit2 = allHabits.getById(habit1.getId()); assertThat(habit1, equalTo(habit2)); } @@ -141,17 +138,17 @@ public class HabitListTest extends BaseUnitTest int from = operations[i][0]; int to = operations[i][1]; - Habit fromHabit = list.getByPosition(from); - Habit toHabit = list.getByPosition(to); - list.reorder(fromHabit, toHabit); + Habit fromHabit = allHabits.getByPosition(from); + Habit toHabit = allHabits.getByPosition(to); + allHabits.reorder(fromHabit, toHabit); int actualPositions[] = new int[10]; for (int j = 0; j < 10; j++) { - Habit h = list.getById(j); + Habit h = allHabits.getById(j); if (h == null) fail(); - actualPositions[j] = list.indexOf(h); + actualPositions[j] = allHabits.indexOf(h); } assertThat(actualPositions, equalTo(expectedPosition[i]));