Replace toJSON methods by Gson

This commit is contained in:
2017-04-14 20:32:00 -04:00
parent 13b4128777
commit 08e3c9cc40
24 changed files with 888 additions and 602 deletions

View File

@@ -77,6 +77,7 @@ dependencies {
compile 'com.opencsv:opencsv:3.7' compile 'com.opencsv:opencsv:3.7'
compile 'org.apmem.tools:layouts:1.10@aar' compile 'org.apmem.tools:layouts:1.10@aar'
compile 'org.jetbrains:annotations-java5:15.0' compile 'org.jetbrains:annotations-java5:15.0'
compile 'com.google.code.gson:gson:2.8.0'
provided 'javax.annotation:jsr250-api:1.0' provided 'javax.annotation:jsr250-api:1.0'
@@ -89,6 +90,7 @@ dependencies {
testCompile 'junit:junit:4.12' testCompile 'junit:junit:4.12'
testCompile 'org.hamcrest:hamcrest-library:1.3' testCompile 'org.hamcrest:hamcrest-library:1.3'
testCompile 'org.mockito:mockito-core:1.10.19' testCompile 'org.mockito:mockito-core:1.10.19'
testCompile 'org.json:json:20160810'
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.1') { androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.1') {
exclude group: 'com.android.support' exclude group: 'com.android.support'

View File

@@ -23,56 +23,31 @@ import android.support.annotation.*;
import org.isoron.uhabits.*; import org.isoron.uhabits.*;
import org.isoron.uhabits.models.*; import org.isoron.uhabits.models.*;
import org.json.*;
import java.util.*; import java.util.*;
import static org.isoron.uhabits.commands.CommandParser.*;
/** /**
* Command to archive a list of habits. * Command to archive a list of habits.
*/ */
public class ArchiveHabitsCommand extends Command public class ArchiveHabitsCommand extends Command
{ {
private List<Habit> selectedHabits; final List<Habit> selected;
private final HabitList habitList; final HabitList habitList;
public ArchiveHabitsCommand(@NonNull HabitList habitList, public ArchiveHabitsCommand(@NonNull HabitList habitList,
@NonNull List<Habit> selectedHabits) @NonNull List<Habit> selected)
{ {
super(); super();
this.habitList = habitList; this.habitList = habitList;
this.selectedHabits = selectedHabits; this.selected = new LinkedList<>(selected);
}
public ArchiveHabitsCommand(@NonNull String id,
@NonNull HabitList habitList,
@NonNull List<Habit> selectedHabits)
{
super(id);
this.habitList = habitList;
this.selectedHabits = selectedHabits;
}
public static Command fromJSON(@NonNull JSONObject json,
@NonNull HabitList habitList)
throws JSONException
{
String id = json.getString("id");
JSONObject data = (JSONObject) json.get("data");
JSONArray habitIds = data.getJSONArray("ids");
LinkedList<Habit> selectedHabits =
habitListFromJSON(habitList, habitIds);
return new ArchiveHabitsCommand(id, habitList, selectedHabits);
} }
@Override @Override
public void execute() public void execute()
{ {
for (Habit h : selectedHabits) h.setArchived(true); for (Habit h : selected) h.setArchived(true);
habitList.update(selectedHabits); habitList.update(selected);
} }
@Override @Override
@@ -87,28 +62,51 @@ public class ArchiveHabitsCommand extends Command
return R.string.toast_habit_unarchived; return R.string.toast_habit_unarchived;
} }
@Nullable
@Override
public JSONObject toJSON()
{
try
{
JSONObject root = super.toJSON();
JSONObject data = root.getJSONObject("data");
root.put("event", "ArchiveHabits");
data.put("ids", habitListToJSON(selectedHabits));
return root;
}
catch (JSONException e)
{
throw new RuntimeException(e.getMessage());
}
}
@Override @Override
public void undo() public void undo()
{ {
for (Habit h : selectedHabits) h.setArchived(false); for (Habit h : selected) h.setArchived(false);
habitList.update(selectedHabits); habitList.update(selected);
}
@NonNull
@Override
public Record toRecord()
{
return new Record(this);
}
public static class Record
{
@NonNull
public final String id;
@NonNull
public final String event = "Archive";
@NonNull
public final List<Long> habits;
public Record(@NonNull ArchiveHabitsCommand command)
{
id = command.getId();
habits = new LinkedList<>();
for (Habit h : command.selected)
{
habits.add(h.getId());
}
}
@NonNull
public ArchiveHabitsCommand toCommand(@NonNull HabitList habitList)
{
List<Habit> selected = new LinkedList<>();
for (Long id : this.habits) selected.add(habitList.getById(id));
ArchiveHabitsCommand command;
command = new ArchiveHabitsCommand(habitList, selected);
command.setId(id);
return command;
}
} }
} }

View File

@@ -23,54 +23,35 @@ import android.support.annotation.*;
import org.isoron.uhabits.*; import org.isoron.uhabits.*;
import org.isoron.uhabits.models.*; import org.isoron.uhabits.models.*;
import org.json.*;
import java.util.*; import java.util.*;
import static org.isoron.uhabits.commands.CommandParser.*;
/** /**
* Command to change the color of a list of habits. * Command to change the color of a list of habits.
*/ */
public class ChangeHabitColorCommand extends Command public class ChangeHabitColorCommand extends Command
{ {
HabitList habitList; @NonNull
final HabitList habitList;
List<Habit> selected; @NonNull
final List<Habit> selected;
List<Integer> originalColors; @NonNull
final List<Integer> originalColors;
Integer newColor; @NonNull
final Integer newColor;
public ChangeHabitColorCommand(@NonNull HabitList habitList, public ChangeHabitColorCommand(@NonNull HabitList habitList,
@NonNull List<Habit> selected, @NonNull List<Habit> selected,
@NonNull Integer newColor) @NonNull Integer newColor)
{ {
super(); this.habitList = habitList;
init(habitList, selected, newColor); this.selected = selected;
} this.newColor = newColor;
this.originalColors = new ArrayList<>(selected.size());
public ChangeHabitColorCommand(@NonNull String id, for (Habit h : selected) originalColors.add(h.getColor());
@NonNull HabitList habitList,
@NonNull List<Habit> selected,
@NonNull Integer newColor)
{
super(id);
init(habitList, selected, newColor);
}
@NonNull
public static Command fromJSON(@NonNull JSONObject json,
@NonNull HabitList habitList)
throws JSONException
{
String id = json.getString("id");
JSONObject data = (JSONObject) json.get("data");
JSONArray habitIds = data.getJSONArray("ids");
int newColor = data.getInt("color");
LinkedList<Habit> selected = habitListFromJSON(habitList, habitIds);
return new ChangeHabitColorCommand(id, habitList, selected, newColor);
} }
@Override @Override
@@ -92,23 +73,11 @@ public class ChangeHabitColorCommand extends Command
return R.string.toast_habit_changed; return R.string.toast_habit_changed;
} }
@Override
@NonNull @NonNull
public JSONObject toJSON() @Override
public Record toRecord()
{ {
try return new Record(this);
{
JSONObject root = super.toJSON();
JSONObject data = root.getJSONObject("data");
root.put("event", "ChangeHabitColor");
data.put("ids", habitListToJSON(selected));
data.put("color", newColor);
return root;
}
catch (JSONException e)
{
throw new RuntimeException(e.getMessage());
}
} }
@Override @Override
@@ -119,15 +88,41 @@ public class ChangeHabitColorCommand extends Command
habitList.update(selected); habitList.update(selected);
} }
private void init(@NonNull HabitList habitList, public static class Record
@NonNull List<Habit> selected,
@NonNull Integer newColor)
{ {
this.habitList = habitList; @NonNull
this.selected = selected; public String id;
this.newColor = newColor;
this.originalColors = new ArrayList<>(selected.size());
for (Habit h : selected) originalColors.add(h.getColor()); @NonNull
public String event = "ChangeColor";
@NonNull
public List<Long> habits;
@NonNull
public Integer color;
public Record(ChangeHabitColorCommand command)
{
id = command.getId();
color = command.newColor;
habits = new LinkedList<>();
for (Habit h : command.selected)
{
if (!h.hasId()) throw new RuntimeException("Habit not saved");
habits.add(h.getId());
}
}
public ChangeHabitColorCommand toCommand(@NonNull HabitList habitList)
{
List<Habit> selected = new LinkedList<>();
for (Long id : this.habits) selected.add(habitList.getById(id));
ChangeHabitColorCommand command;
command = new ChangeHabitColorCommand(habitList, selected, color);
command.setId(id);
return command;
}
} }
} }

View File

@@ -19,6 +19,10 @@
package org.isoron.uhabits.commands; package org.isoron.uhabits.commands;
import android.support.annotation.*;
import com.google.gson.*;
import org.isoron.uhabits.utils.*; import org.isoron.uhabits.utils.*;
import org.json.*; import org.json.*;
@@ -33,7 +37,7 @@ import org.json.*;
*/ */
public abstract class Command public abstract class Command
{ {
private final String id; private String id;
public Command() public Command()
{ {
@@ -52,31 +56,37 @@ public abstract class Command
return null; return null;
} }
public String getId()
{
return id;
}
public void setId(String id)
{
this.id = id;
}
public Integer getUndoStringId() public Integer getUndoStringId()
{ {
return null; return null;
} }
public abstract void undo(); @NonNull
public JSONObject toJson()
public JSONObject toJSON()
{ {
try try
{ {
JSONObject root = new JSONObject(); String json = new GsonBuilder().create().toJson(toRecord());
JSONObject data = new JSONObject(); return new JSONObject(json);
root.put("id", getId());
root.put("data", data);
return root;
} }
catch (JSONException e) catch (JSONException e)
{ {
throw new RuntimeException(e.getMessage()); throw new RuntimeException(e);
} }
} }
public String getId() @NonNull
{ public abstract Object toRecord();
return id;
} public abstract void undo();
} }

View File

@@ -21,14 +21,13 @@ package org.isoron.uhabits.commands;
import android.support.annotation.*; import android.support.annotation.*;
import com.google.gson.*;
import org.isoron.uhabits.models.*; import org.isoron.uhabits.models.*;
import org.json.*; import org.json.*;
import java.util.*;
public class CommandParser public class CommandParser
{ {
private HabitList habitList; private HabitList habitList;
private ModelFactory modelFactory; private ModelFactory modelFactory;
@@ -41,65 +40,43 @@ public class CommandParser
} }
@NonNull @NonNull
public static LinkedList<Habit> habitListFromJSON( public Command parse(@NonNull JSONObject json) throws JSONException
@NonNull HabitList habitList, @NonNull JSONArray habitIds)
throws JSONException
{ {
LinkedList<Habit> habits = new LinkedList<>(); String event = json.getString("event");
Gson gson = new GsonBuilder().create();
for (int i = 0; i < habitIds.length(); i++) if (event.equals("Archive")) return gson
{ .fromJson(json.toString(), ArchiveHabitsCommand.Record.class)
Long hId = habitIds.getLong(i); .toCommand(habitList);
Habit h = habitList.getById(hId);
if (h == null) continue;
habits.add(h); if (event.equals("ChangeColor")) return gson
} .fromJson(json.toString(), ChangeHabitColorCommand.Record.class)
.toCommand(habitList);
return habits; if (event.equals("CreateHabit")) return gson
} .fromJson(json.toString(), CreateHabitCommand.Record.class)
.toCommand(modelFactory, habitList);
@NonNull if (event.equals("CreateRep")) return gson
protected static JSONArray habitListToJSON(List<Habit> habits) .fromJson(json.toString(), CreateRepetitionCommand.Record.class)
{ .toCommand(habitList);
JSONArray habitIds = new JSONArray();
for (Habit h : habits) habitIds.put(h.getId());
return habitIds;
}
@NonNull if (event.equals("DeleteHabit")) return gson
public Command fromJSON(@NonNull JSONObject json) throws JSONException .fromJson(json.toString(), DeleteHabitsCommand.Record.class)
{ .toCommand(habitList);
switch (json.getString("event"))
{
case "ToggleRepetition":
return ToggleRepetitionCommand.fromJSON(json, habitList);
case "ArchiveHabits": if (event.equals("EditHabit")) return gson
return ArchiveHabitsCommand.fromJSON(json, habitList); .fromJson(json.toString(), EditHabitCommand.Record.class)
.toCommand(modelFactory, habitList);
case "UnarchiveHabits": if (event.equals("Toggle")) return gson
return UnarchiveHabitsCommand.fromJSON(json, habitList); .fromJson(json.toString(), ToggleRepetitionCommand.Record.class)
.toCommand(habitList);
case "ChangeHabitColor": if (event.equals("Unarchive")) return gson
return ChangeHabitColorCommand.fromJSON(json, habitList); .fromJson(json.toString(), UnarchiveHabitsCommand.Record.class)
.toCommand(habitList);
case "CreateHabit": throw new IllegalStateException("Unknown command");
return CreateHabitCommand.fromJSON(json, habitList,
modelFactory);
case "DeleteHabits":
return DeleteHabitsCommand.fromJSON(json, habitList);
case "EditHabit":
return EditHabitCommand.fromJSON(json, habitList, modelFactory);
// TODO: Implement this
// case "ReorderHabit":
// return ReorderHabitCommand.fromJSON(json);
}
return null;
} }
} }

View File

@@ -25,7 +25,6 @@ import com.google.auto.factory.*;
import org.isoron.uhabits.*; import org.isoron.uhabits.*;
import org.isoron.uhabits.models.*; import org.isoron.uhabits.models.*;
import org.json.*;
/** /**
* Command to create a habit. * Command to create a habit.
@@ -33,54 +32,25 @@ import org.json.*;
@AutoFactory @AutoFactory
public class CreateHabitCommand extends Command public class CreateHabitCommand extends Command
{ {
private ModelFactory modelFactory; ModelFactory modelFactory;
HabitList habitList; HabitList habitList;
@NonNull @NonNull
private Habit model; Habit model;
@Nullable @Nullable
private Long savedId; Long savedId;
public CreateHabitCommand(@Provided @NonNull ModelFactory modelFactory, public CreateHabitCommand(@Provided @NonNull ModelFactory modelFactory,
@NonNull HabitList habitList, @NonNull HabitList habitList,
@NonNull Habit model) @NonNull Habit model)
{ {
super();
this.modelFactory = modelFactory; this.modelFactory = modelFactory;
this.habitList = habitList; this.habitList = habitList;
this.model = model; this.model = model;
} }
public CreateHabitCommand(@Provided @NonNull ModelFactory modelFactory,
@NonNull String commandId,
@NonNull HabitList habitList,
@NonNull Habit model,
@Nullable Long savedId)
{
super(commandId);
this.modelFactory = modelFactory;
this.habitList = habitList;
this.model = model;
this.savedId = savedId;
}
@NonNull
public static Command fromJSON(@NonNull JSONObject root,
@NonNull HabitList habitList,
@NonNull ModelFactory modelFactory)
throws JSONException
{
String commandId = root.getString("id");
JSONObject data = (JSONObject) root.get("data");
Habit model = Habit.fromJSON(data.getJSONObject("habit"), modelFactory);
Long savedId = data.getLong("id");
return new CreateHabitCommand(modelFactory, commandId, habitList, model,
savedId);
}
@Override @Override
public void execute() public void execute()
{ {
@@ -104,30 +74,55 @@ public class CreateHabitCommand extends Command
return R.string.toast_habit_deleted; return R.string.toast_habit_deleted;
} }
@NonNull
@Override @Override
public JSONObject toJSON() public Record toRecord()
{ {
try return new Record(this);
{
JSONObject root = super.toJSON();
JSONObject data = root.getJSONObject("data");
root.put("event", "CreateHabit");
data.put("habit", model.toJSON());
data.put("id", savedId);
return root;
}
catch (JSONException e)
{
throw new RuntimeException(e.getMessage());
}
} }
@Override @Override
public void undo() public void undo()
{ {
if (savedId == null) throw new IllegalStateException();
Habit habit = habitList.getById(savedId); Habit habit = habitList.getById(savedId);
if (habit == null) throw new RuntimeException("Habit not found"); if (habit == null) throw new HabitNotFoundException();
habitList.remove(habit); habitList.remove(habit);
} }
public static class Record
{
@NonNull
public String id;
@NonNull
public String event = "CreateHabit";
@NonNull
public Habit.HabitData habit;
@Nullable
public Long savedId;
public Record(CreateHabitCommand command)
{
id = command.getId();
habit = command.model.getData();
savedId = command.savedId;
}
public CreateHabitCommand toCommand(@NonNull ModelFactory modelFactory,
@NonNull HabitList habitList)
{
Habit h = modelFactory.buildHabit(habit);
CreateHabitCommand command;
command = new CreateHabitCommand(modelFactory, habitList, h);
command.savedId = savedId;
command.setId(id);
return command;
}
}
} }

View File

@@ -29,15 +29,17 @@ import org.isoron.uhabits.models.*;
public class CreateRepetitionCommand extends Command public class CreateRepetitionCommand extends Command
{ {
@NonNull @NonNull
private final Habit habit; final Habit habit;
private final long timestamp; final long timestamp;
private final int value; final int value;
private Repetition previousRep; @Nullable
Repetition previousRep;
private Repetition newRep; @Nullable
Repetition newRep;
public CreateRepetitionCommand(@NonNull Habit habit, public CreateRepetitionCommand(@NonNull Habit habit,
long timestamp, long timestamp,
@@ -68,11 +70,57 @@ public class CreateRepetitionCommand extends Command
return habit; return habit;
} }
@Override
@NonNull
public Record toRecord()
{
return new Record(this);
}
@Override @Override
public void undo() public void undo()
{ {
if(newRep == null) throw new IllegalStateException();
habit.getRepetitions().remove(newRep); habit.getRepetitions().remove(newRep);
if (previousRep != null) habit.getRepetitions().add(previousRep); if (previousRep != null) habit.getRepetitions().add(previousRep);
habit.invalidateNewerThan(timestamp); habit.invalidateNewerThan(timestamp);
} }
public static class Record
{
@NonNull
public String id;
@NonNull
public String event = "CreateRep";
public long habitId;
public long timestamp;
public int value;
public Record(CreateRepetitionCommand command)
{
id = command.getId();
Long habitId = command.habit.getId();
if(habitId == null) throw new RuntimeException("Habit not saved");
this.habitId = habitId;
this.timestamp = command.timestamp;
this.value = command.value;
}
public CreateRepetitionCommand toCommand(@NonNull HabitList habitList)
{
Habit h = habitList.getById(habitId);
if(h == null) throw new HabitNotFoundException();
CreateRepetitionCommand command;
command = new CreateRepetitionCommand(h, timestamp, value);
command.setId(id);
return command;
}
}
} }

View File

@@ -23,56 +23,32 @@ import android.support.annotation.*;
import org.isoron.uhabits.*; import org.isoron.uhabits.*;
import org.isoron.uhabits.models.*; import org.isoron.uhabits.models.*;
import org.json.*;
import java.util.*; import java.util.*;
import static org.isoron.uhabits.commands.CommandParser.habitListFromJSON;
import static org.isoron.uhabits.commands.CommandParser.habitListToJSON;
/** /**
* Command to delete a list of habits. * Command to delete a list of habits.
*/ */
public class DeleteHabitsCommand extends Command public class DeleteHabitsCommand extends Command
{ {
HabitList habitList; @NonNull
final HabitList habitList;
private List<Habit> habits;
public DeleteHabitsCommand(@NonNull HabitList habitList,
@NonNull List<Habit> habits)
{
super();
this.habits = habits;
this.habitList = habitList;
}
public DeleteHabitsCommand(@NonNull String id,
@NonNull HabitList habitList,
@NonNull List<Habit> habits)
{
super(id);
this.habits = habits;
this.habitList = habitList;
}
@NonNull @NonNull
public static Command fromJSON(@NonNull JSONObject json, final List<Habit> selected;
@NonNull HabitList habitList)
throws JSONException
{
String id = json.getString("id");
JSONObject data = (JSONObject) json.get("data");
JSONArray habitIds = data.getJSONArray("ids");
LinkedList<Habit> habits = habitListFromJSON(habitList, habitIds); public DeleteHabitsCommand(@NonNull HabitList habitList,
return new DeleteHabitsCommand(id, habitList, habits); @NonNull List<Habit> selected)
{
this.selected = new LinkedList<>(selected);
this.habitList = habitList;
} }
@Override @Override
public void execute() public void execute()
{ {
for (Habit h : habits) for (Habit h : selected)
habitList.remove(h); habitList.remove(h);
} }
@@ -82,9 +58,9 @@ public class DeleteHabitsCommand extends Command
return R.string.toast_habit_deleted; return R.string.toast_habit_deleted;
} }
public List<Habit> getHabits() public List<Habit> getSelected()
{ {
return new LinkedList<>(habits); return Collections.unmodifiableList(selected);
} }
@Override @Override
@@ -95,20 +71,9 @@ public class DeleteHabitsCommand extends Command
@Override @Override
@NonNull @NonNull
public JSONObject toJSON() public Record toRecord()
{ {
try return new Record(this);
{
JSONObject root = super.toJSON();
JSONObject data = root.getJSONObject("data");
root.put("event", "DeleteHabits");
data.put("ids", habitListToJSON(habits));
return root;
}
catch (JSONException e)
{
throw new RuntimeException(e.getMessage());
}
} }
@Override @Override
@@ -116,4 +81,38 @@ public class DeleteHabitsCommand extends Command
{ {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
public static class Record
{
@NonNull
public String id;
@NonNull
public String event = "DeleteHabit";
@NonNull
public List<Long> habits;
public Record(DeleteHabitsCommand command)
{
id = command.getId();
habits = new LinkedList<>();
for (Habit h : command.selected)
{
if (!h.hasId()) throw new RuntimeException("Habit not saved");
habits.add(h.getId());
}
}
public DeleteHabitsCommand toCommand(@NonNull HabitList habitList)
{
List<Habit> selected = new LinkedList<>();
for (Long id : this.habits) selected.add(habitList.getById(id));
DeleteHabitsCommand command;
command = new DeleteHabitsCommand(habitList, selected);
command.setId(id);
return command;
}
}
} }

View File

@@ -25,7 +25,6 @@ import com.google.auto.factory.*;
import org.isoron.uhabits.*; import org.isoron.uhabits.*;
import org.isoron.uhabits.models.*; import org.isoron.uhabits.models.*;
import org.json.*;
/** /**
* Command to modify a habit. * Command to modify a habit.
@@ -33,52 +32,43 @@ import org.json.*;
@AutoFactory @AutoFactory
public class EditHabitCommand extends Command public class EditHabitCommand extends Command
{ {
HabitList habitList; @NonNull
final HabitList habitList;
private Habit original;
private Habit modified;
private long savedId;
private boolean hasFrequencyChanged;
private boolean hasTargetChanged;
public EditHabitCommand(@Provided @NonNull ModelFactory modelFactory,
@NonNull HabitList habitList,
@NonNull Habit original,
@NonNull Habit modified)
{
super();
init(modelFactory, habitList, original, modified);
}
public EditHabitCommand(@Provided @NonNull ModelFactory modelFactory,
@NonNull String id,
@NonNull HabitList habitList,
@NonNull Habit original,
@NonNull Habit modified)
{
super(id);
init(modelFactory, habitList, original, modified);
}
@NonNull @NonNull
public static Command fromJSON(@NonNull JSONObject root, final Habit original;
@NonNull HabitList habitList,
@NonNull ModelFactory modelFactory)
throws JSONException
{
String commandId = root.getString("id");
JSONObject data = (JSONObject) root.get("data");
Habit original = habitList.getById(data.getLong("id"));
if (original == null) throw new HabitNotFoundException();
Habit modified = @NonNull
Habit.fromJSON(data.getJSONObject("params"), modelFactory); final Habit modified;
return new EditHabitCommand(modelFactory, commandId, habitList,
original, modified); final long savedId;
final boolean hasFrequencyChanged;
final boolean hasTargetChanged;
public EditHabitCommand(@Provided @NonNull ModelFactory modelFactory,
@NonNull HabitList habitList,
@NonNull Habit original,
@NonNull Habit modified)
{
Long habitId = original.getId();
if (habitId == null) throw new RuntimeException("Habit not saved");
this.savedId = habitId;
this.habitList = habitList;
this.modified = modelFactory.buildHabit();
this.original = modelFactory.buildHabit();
this.modified.copyFrom(modified);
this.original.copyFrom(original);
Frequency originalFreq = this.original.getFrequency();
Frequency modifiedFreq = this.modified.getFrequency();
hasFrequencyChanged = (!originalFreq.equals(modifiedFreq));
hasTargetChanged =
(original.getTargetType() != modified.getTargetType() ||
original.getTargetValue() != modified.getTargetValue());
} }
@Override @Override
@@ -99,22 +89,11 @@ public class EditHabitCommand extends Command
return R.string.toast_habit_changed_back; return R.string.toast_habit_changed_back;
} }
@NonNull
@Override @Override
public JSONObject toJSON() public Record toRecord()
{ {
try return new Record(this);
{
JSONObject root = super.toJSON();
JSONObject data = root.getJSONObject("data");
root.put("event", "EditHabit");
data.put("id", savedId);
data.put("params", modified.toJSON());
return root;
}
catch (JSONException e)
{
throw new RuntimeException(e.getMessage());
}
} }
@Override @Override
@@ -131,33 +110,44 @@ public class EditHabitCommand extends Command
habit.copyFrom(model); habit.copyFrom(model);
habitList.update(habit); habitList.update(habit);
invalidateIfNeeded(habit);
}
private void init(@NonNull ModelFactory modelFactory,
@NonNull HabitList habitList,
@NonNull Habit original,
@NonNull Habit modified)
{
this.habitList = habitList;
this.savedId = original.getId();
this.modified = modelFactory.buildHabit();
this.original = modelFactory.buildHabit();
this.modified.copyFrom(modified);
this.original.copyFrom(original);
Frequency originalFreq = this.original.getFrequency();
Frequency modifiedFreq = this.modified.getFrequency();
hasFrequencyChanged = (!originalFreq.equals(modifiedFreq));
hasTargetChanged =
(original.getTargetType() != modified.getTargetType() ||
original.getTargetValue() != modified.getTargetValue());
}
private void invalidateIfNeeded(Habit habit)
{
if (hasFrequencyChanged || hasTargetChanged) if (hasFrequencyChanged || hasTargetChanged)
habit.invalidateNewerThan(0); habit.invalidateNewerThan(0);
} }
public static class Record
{
@NonNull
public String id;
@NonNull
public String event = "EditHabit";
@NonNull
public Habit.HabitData habit;
public long habitId;
public Record(EditHabitCommand command)
{
id = command.getId();
this.habitId = command.savedId;
this.habit = command.modified.getData();
}
@NonNull
public EditHabitCommand toCommand(@NonNull ModelFactory modelFactory,
@NonNull HabitList habitList)
{
Habit original = habitList.getById(habitId);
if(original == null) throw new HabitNotFoundException();
Habit modified = modelFactory.buildHabit(habit);
EditHabitCommand command;
command = new EditHabitCommand(modelFactory, habitList, original,
modified);
command.setId(id);
return command;
}
}
} }

View File

@@ -22,16 +22,16 @@ package org.isoron.uhabits.commands;
import android.support.annotation.*; import android.support.annotation.*;
import org.isoron.uhabits.models.*; import org.isoron.uhabits.models.*;
import org.json.*;
/** /**
* Command to toggle a repetition. * Command to toggle a repetition.
*/ */
public class ToggleRepetitionCommand extends Command public class ToggleRepetitionCommand extends Command
{ {
private Long timestamp; final long timestamp;
private Habit habit; @NonNull
final Habit habit;
public ToggleRepetitionCommand(@NonNull Habit habit, long timestamp) public ToggleRepetitionCommand(@NonNull Habit habit, long timestamp)
{ {
@@ -40,37 +40,13 @@ public class ToggleRepetitionCommand extends Command
this.habit = habit; this.habit = habit;
} }
public ToggleRepetitionCommand(@NonNull String id,
@NonNull Habit habit,
long timestamp)
{
super(id);
this.timestamp = timestamp;
this.habit = habit;
}
@NonNull
public static Command fromJSON(@NonNull JSONObject json,
@NonNull HabitList habitList)
throws JSONException
{
String id = json.getString("id");
JSONObject data = (JSONObject) json.get("data");
Long habitId = data.getLong("habit");
Long timestamp = data.getLong("timestamp");
Habit habit = habitList.getById(habitId);
if (habit == null) throw new HabitNotFoundException();
return new ToggleRepetitionCommand(id, habit, timestamp);
}
@Override @Override
public void execute() public void execute()
{ {
habit.getRepetitions().toggleTimestamp(timestamp); habit.getRepetitions().toggleTimestamp(timestamp);
} }
@NonNull
public Habit getHabit() public Habit getHabit()
{ {
return habit; return habit;
@@ -78,21 +54,9 @@ public class ToggleRepetitionCommand extends Command
@Override @Override
@NonNull @NonNull
public JSONObject toJSON() public Record toRecord()
{ {
try return new Record(this);
{
JSONObject root = super.toJSON();
JSONObject data = root.getJSONObject("data");
root.put("event", "ToggleRepetition");
data.put("habit", habit.getId());
data.put("timestamp", timestamp);
return root;
}
catch (JSONException e)
{
throw new RuntimeException(e.getMessage());
}
} }
@Override @Override
@@ -100,4 +64,38 @@ public class ToggleRepetitionCommand extends Command
{ {
execute(); execute();
} }
public static class Record
{
@NonNull
public String id;
@NonNull
public String event = "Toggle";
public long habitId;
public long timestamp;
public Record(@NonNull ToggleRepetitionCommand command)
{
id = command.getId();
Long habitId = command.habit.getId();
if(habitId == null) throw new RuntimeException("Habit not saved");
this.timestamp = command.timestamp;
this.habitId = habitId;
}
public ToggleRepetitionCommand toCommand(@NonNull HabitList habitList)
{
Habit h = habitList.getById(habitId);
if(h == null) throw new HabitNotFoundException();
ToggleRepetitionCommand command;
command = new ToggleRepetitionCommand(h, timestamp);
command.setId(id);
return command;
}
}
} }

View File

@@ -23,56 +23,32 @@ import android.support.annotation.*;
import org.isoron.uhabits.*; import org.isoron.uhabits.*;
import org.isoron.uhabits.models.*; import org.isoron.uhabits.models.*;
import org.json.*;
import java.util.*; import java.util.*;
import static org.isoron.uhabits.commands.CommandParser.*;
/** /**
* Command to unarchive a list of habits. * Command to unarchive a list of habits.
*/ */
public class UnarchiveHabitsCommand extends Command public class UnarchiveHabitsCommand extends Command
{ {
HabitList habitList; @NonNull
final HabitList habitList;
private List<Habit> habits; @NonNull
final List<Habit> selected;
public UnarchiveHabitsCommand(@NonNull HabitList habitList, public UnarchiveHabitsCommand(@NonNull HabitList habitList,
@NonNull List<Habit> selected) @NonNull List<Habit> selected)
{ {
super(); this.selected = new LinkedList<>(selected);
this.habits = selected;
this.habitList = habitList; this.habitList = habitList;
} }
public UnarchiveHabitsCommand(@NonNull String id,
@NonNull HabitList habitList,
@NonNull List<Habit> selected)
{
super(id);
this.habits = selected;
this.habitList = habitList;
}
@NonNull
public static Command fromJSON(@NonNull JSONObject json,
@NonNull HabitList habitList)
throws JSONException
{
String id = json.getString("id");
JSONObject data = (JSONObject) json.get("data");
JSONArray habitIds = data.getJSONArray("ids");
LinkedList<Habit> selected = habitListFromJSON(habitList, habitIds);
return new UnarchiveHabitsCommand(id, habitList, selected);
}
@Override @Override
public void execute() public void execute()
{ {
for (Habit h : habits) h.setArchived(false); for (Habit h : selected) h.setArchived(false);
habitList.update(habits); habitList.update(selected);
} }
@Override @Override
@@ -89,27 +65,50 @@ public class UnarchiveHabitsCommand extends Command
@Override @Override
@NonNull @NonNull
public JSONObject toJSON() public Record toRecord()
{ {
try return new Record(this);
{
JSONObject root = super.toJSON();
JSONObject data = root.getJSONObject("data");
root.put("event", "UnarchiveHabits");
data.put("ids", habitListToJSON(habits));
return root;
}
catch (JSONException e)
{
throw new RuntimeException(e.getMessage());
}
} }
@Override @Override
public void undo() public void undo()
{ {
for (Habit h : habits) h.setArchived(true); for (Habit h : selected) h.setArchived(true);
habitList.update(habits); habitList.update(selected);
} }
public static class Record
{
@NonNull
public final String id;
@NonNull
public final String event = "Unarchive";
@NonNull
public final List<Long> habits;
public Record(@NonNull UnarchiveHabitsCommand command)
{
id = command.getId();
habits = new LinkedList<>();
for (Habit h : command.selected)
{
if (!h.hasId()) throw new RuntimeException("Habit not saved");
habits.add(h.getId());
}
}
@NonNull
public UnarchiveHabitsCommand toCommand(@NonNull HabitList habitList)
{
List<Habit> selected = new LinkedList<>();
for (Long id : this.habits) selected.add(habitList.getById(id));
UnarchiveHabitsCommand command;
command = new UnarchiveHabitsCommand(habitList, selected);
command.setId(id);
return command;
}
}
} }

View File

@@ -23,12 +23,12 @@ import android.net.*;
import android.support.annotation.*; import android.support.annotation.*;
import org.apache.commons.lang3.builder.*; import org.apache.commons.lang3.builder.*;
import org.json.*;
import java.util.*; import java.util.*;
import javax.inject.*; import javax.inject.*;
import static android.R.attr.*;
import static org.isoron.uhabits.models.Checkmark.*; import static org.isoron.uhabits.models.Checkmark.*;
/** /**
@@ -48,20 +48,10 @@ public class Habit
public static final int YES_NO_HABIT = 0; public static final int YES_NO_HABIT = 0;
@Nullable @Nullable
private Long id; public Long id;
@NonNull @NonNull
private String name; private HabitData data;
@NonNull
private String description;
@NonNull
private Frequency frequency;
private int color;
private boolean archived;
@NonNull @NonNull
private StreakList streaks; private StreakList streaks;
@@ -69,28 +59,16 @@ public class Habit
@NonNull @NonNull
private ScoreList scores; private ScoreList scores;
private int targetType;
private double targetValue;
private int type;
@NonNull @NonNull
private RepetitionList repetitions; private RepetitionList repetitions;
@NonNull @NonNull
private CheckmarkList checkmarks; private CheckmarkList checkmarks;
@NonNull
private String unit;
@Nullable
private Reminder reminder;
private ModelObservable observable = new ModelObservable(); private ModelObservable observable = new ModelObservable();
/** /**
* Constructs a habit with default attributes. * Constructs a habit with default data.
* <p> * <p>
* The habit is not archived, not highlighted, has no reminders and is * The habit is not archived, not highlighted, has no reminders and is
* placed in the last position of the list of habits. * placed in the last position of the list of habits.
@@ -98,16 +76,16 @@ public class Habit
@Inject @Inject
Habit(@NonNull ModelFactory factory) Habit(@NonNull ModelFactory factory)
{ {
this.color = 5; this.data = new HabitData();
this.archived = false; checkmarks = factory.buildCheckmarkList(this);
this.frequency = new Frequency(3, 7); streaks = factory.buildStreakList(this);
this.type = YES_NO_HABIT; scores = factory.buildScoreList(this);
this.name = ""; repetitions = factory.buildRepetitionList(this);
this.description = ""; }
this.targetType = AT_LEAST;
this.targetValue = 100;
this.unit = "";
Habit(@NonNull ModelFactory factory, @NonNull HabitData data)
{
this.data = new HabitData(data);
checkmarks = factory.buildCheckmarkList(this); checkmarks = factory.buildCheckmarkList(this);
streaks = factory.buildStreakList(this); streaks = factory.buildStreakList(this);
scores = factory.buildScoreList(this); scores = factory.buildScoreList(this);
@@ -119,7 +97,7 @@ public class Habit
*/ */
public void clearReminder() public void clearReminder()
{ {
reminder = null; data.reminder = null;
observable.notifyListeners(); observable.notifyListeners();
} }
@@ -130,16 +108,7 @@ public class Habit
*/ */
public void copyFrom(@NonNull Habit model) public void copyFrom(@NonNull Habit model)
{ {
this.name = model.getName(); this.data = new HabitData(model.data);
this.description = model.getDescription();
this.color = model.getColor();
this.archived = model.isArchived();
this.frequency = model.frequency;
this.reminder = model.reminder;
this.type = model.type;
this.targetValue = model.targetValue;
this.targetType = model.targetType;
this.unit = model.unit;
observable.notifyListeners(); observable.notifyListeners();
} }
@@ -163,41 +132,34 @@ public class Habit
@NonNull @NonNull
public Integer getColor() public Integer getColor()
{ {
return color; return data.color;
}
public boolean isCompletedToday()
{
int todayCheckmark = getCheckmarks().getTodayValue();
if (isNumerical()) return todayCheckmark >= targetValue;
else return (todayCheckmark != UNCHECKED);
} }
public void setColor(@NonNull Integer color) public void setColor(@NonNull Integer color)
{ {
this.color = color; data.color = color;
} }
@NonNull @NonNull
public String getDescription() public String getDescription()
{ {
return description; return data.description;
} }
public void setDescription(@NonNull String description) public void setDescription(@NonNull String description)
{ {
this.description = description; data.description = description;
} }
@NonNull @NonNull
public Frequency getFrequency() public Frequency getFrequency()
{ {
return frequency; return data.frequency;
} }
public void setFrequency(@NonNull Frequency frequency) public void setFrequency(@NonNull Frequency frequency)
{ {
this.frequency = frequency; data.frequency = frequency;
} }
@Nullable @Nullable
@@ -214,12 +176,12 @@ public class Habit
@NonNull @NonNull
public String getName() public String getName()
{ {
return name; return data.name;
} }
public void setName(@NonNull String name) public void setName(@NonNull String name)
{ {
this.name = name; data.name = name;
} }
public ModelObservable getObservable() public ModelObservable getObservable()
@@ -240,13 +202,13 @@ public class Habit
@NonNull @NonNull
public Reminder getReminder() public Reminder getReminder()
{ {
if (reminder == null) throw new IllegalStateException(); if (data.reminder == null) throw new IllegalStateException();
return reminder; return data.reminder;
} }
public void setReminder(@Nullable Reminder reminder) public void setReminder(@Nullable Reminder reminder)
{ {
this.reminder = reminder; data.reminder = reminder;
} }
@NonNull @NonNull
@@ -269,30 +231,30 @@ public class Habit
public int getTargetType() public int getTargetType()
{ {
return targetType; return data.targetType;
} }
public void setTargetType(int targetType) public void setTargetType(int targetType)
{ {
if (targetType != AT_LEAST && targetType != AT_MOST) if (targetType != AT_LEAST && targetType != AT_MOST)
throw new IllegalArgumentException(); throw new IllegalArgumentException();
this.targetType = targetType; data.targetType = targetType;
} }
public double getTargetValue() public double getTargetValue()
{ {
return targetValue; return data.targetValue;
} }
public void setTargetValue(double targetValue) public void setTargetValue(double targetValue)
{ {
if(targetValue < 0) throw new IllegalArgumentException(); if (targetValue < 0) throw new IllegalArgumentException();
this.targetValue = targetValue; data.targetValue = targetValue;
} }
public int getType() public int getType()
{ {
return type; return data.type;
} }
public void setType(int type) public void setType(int type)
@@ -300,18 +262,18 @@ public class Habit
if (type != YES_NO_HABIT && type != NUMBER_HABIT) if (type != YES_NO_HABIT && type != NUMBER_HABIT)
throw new IllegalArgumentException(); throw new IllegalArgumentException();
this.type = type; data.type = type;
} }
@NonNull @NonNull
public String getUnit() public String getUnit()
{ {
return unit; return data.unit;
} }
public void setUnit(@NonNull String unit) public void setUnit(@NonNull String unit)
{ {
this.unit = unit; data.unit = unit;
} }
/** /**
@@ -325,6 +287,11 @@ public class Habit
return Uri.parse(s); return Uri.parse(s);
} }
public boolean hasId()
{
return getId() != null;
}
/** /**
* Returns whether the habit has a reminder. * Returns whether the habit has a reminder.
* *
@@ -332,7 +299,7 @@ public class Habit
*/ */
public boolean hasReminder() public boolean hasReminder()
{ {
return reminder != null; return data.reminder != null;
} }
public void invalidateNewerThan(long timestamp) public void invalidateNewerThan(long timestamp)
@@ -344,12 +311,19 @@ public class Habit
public boolean isArchived() public boolean isArchived()
{ {
return archived; return data.archived;
} }
public void setArchived(boolean archived) public void setArchived(boolean archived)
{ {
this.archived = archived; data.archived = archived;
}
public boolean isCompletedToday()
{
int todayCheckmark = getCheckmarks().getTodayValue();
if (isNumerical()) return todayCheckmark >= data.targetValue;
else return (todayCheckmark != UNCHECKED);
} }
public boolean isNumerical() public boolean isNumerical()
@@ -357,79 +331,120 @@ public class Habit
return type == NUMBER_HABIT; return type == NUMBER_HABIT;
} }
public HabitData getData()
{
return new HabitData(data);
}
public static class HabitData
{
@NonNull
public String name;
@NonNull
public String description;
@NonNull
public Frequency frequency;
public int color;
public boolean archived;
public int targetType;
public double targetValue;
public int type;
@NonNull
public String unit;
@Nullable
public Reminder reminder;
public HabitData()
{
this.color = 5;
this.archived = false;
this.frequency = new Frequency(3, 7);
this.type = YES_NO_HABIT;
this.name = "";
this.description = "";
this.targetType = AT_LEAST;
this.targetValue = 100;
this.unit = "";
}
public HabitData(@NonNull HabitData model)
{
this.name = model.name;
this.description = model.description;
this.frequency = model.frequency;
this.color = model.color;
this.archived = model.archived;
this.targetType = model.targetType;
this.targetValue = model.targetValue;
this.type = model.type;
this.unit = model.unit;
this.reminder = model.reminder;
}
@Override @Override
public String toString() public String toString()
{ {
return new ToStringBuilder(this) return new ToStringBuilder(this)
.append("id", id)
.append("name", name) .append("name", name)
.append("description", description) .append("description", description)
.append("frequency", frequency)
.append("color", color) .append("color", color)
.append("archived", archived) .append("archived", archived)
.append("type", type)
.append("targetType", targetType) .append("targetType", targetType)
.append("targetValue", targetValue) .append("targetValue", targetValue)
.append("type", type)
.append("unit", unit) .append("unit", unit)
.append("reminder", reminder)
.toString(); .toString();
} }
@NonNull @Override
public JSONObject toJSON() public boolean equals(Object o)
{ {
try if (this == o) return true;
{
JSONObject json = new JSONObject();
json.put("name", name);
json.put("description", description);
json.put("freqNum", frequency.getNumerator());
json.put("freqDen", frequency.getDenominator());
json.put("color", color);
json.put("type", type);
json.put("targetType", targetType);
json.put("targetValue", targetValue);
json.put("unit", unit);
json.put("archived", archived);
if(reminder != null) if (o == null || getClass() != o.getClass()) return false;
{
json.put("reminderHour", reminder.getHour()); HabitData habitData = (HabitData) o;
json.put("reminderMin", reminder.getMinute());
json.put("reminderDays", reminder.getDays().toInteger()); return new EqualsBuilder()
.append(color, habitData.color)
.append(archived, habitData.archived)
.append(targetType, habitData.targetType)
.append(targetValue, habitData.targetValue)
.append(type, habitData.type)
.append(name, habitData.name)
.append(description, habitData.description)
.append(frequency, habitData.frequency)
.append(unit, habitData.unit)
.append(reminder, habitData.reminder)
.isEquals();
} }
return json; @Override
} public int hashCode()
catch(JSONException e)
{ {
throw new RuntimeException(e.getMessage()); return new HashCodeBuilder(17, 37)
.append(name)
.append(description)
.append(frequency)
.append(color)
.append(archived)
.append(targetType)
.append(targetValue)
.append(type)
.append(unit)
.append(reminder)
.toHashCode();
} }
} }
@NonNull
public static Habit fromJSON(@NonNull JSONObject json,
@NonNull ModelFactory modelFactory)
throws JSONException
{
Habit habit = modelFactory.buildHabit();
habit.name = json.getString("name");
habit.description = json.getString("description");
int freqNum = json.getInt("freqNum");
int freqDen = json.getInt("freqDen");
habit.frequency = new Frequency(freqNum, freqDen);
habit.color = json.getInt("color");
habit.archived = json.getBoolean("archived");
habit.targetValue = json.getInt("targetValue");
habit.targetType = json.getInt("targetType");
habit.unit = json.getString("unit");
habit.type = json.getInt("type");
if(json.has("reminderHour"))
{
int hour = json.getInt("reminderHour");
int min = json.getInt("reminderMin");
int days = json.getInt("reminderDays");
habit.reminder = new Reminder(hour, min, new WeekdayList(days));
}
return habit;
}
} }

View File

@@ -32,6 +32,11 @@ public interface ModelFactory
return new Habit(this); return new Habit(this);
} }
default Habit buildHabit(Habit.HabitData data)
{
return new Habit(this, data);
}
HabitList buildHabitList(); HabitList buildHabitList();
RepetitionList buildRepetitionList(Habit habit); RepetitionList buildRepetitionList(Habit habit);

View File

@@ -102,7 +102,7 @@ public class NotificationTray
if (command instanceof DeleteHabitsCommand) if (command instanceof DeleteHabitsCommand)
{ {
DeleteHabitsCommand deleteCommand = (DeleteHabitsCommand) command; DeleteHabitsCommand deleteCommand = (DeleteHabitsCommand) command;
List<Habit> deleted = deleteCommand.getHabits(); List<Habit> deleted = deleteCommand.getSelected();
for (Habit habit : deleted) for (Habit habit : deleted)
cancel(habit); cancel(habit);
} }

View File

@@ -141,9 +141,7 @@ public class SyncManager
public void postCommand(Command command) public void postCommand(Command command)
{ {
JSONObject msg = command.toJSON(); JSONObject msg = command.toJson();
if (msg == null) return;
Long now = new Date().getTime(); Long now = new Date().getTime();
Event e = new Event(command.getId(), now, msg.toString()); Event e = new Event(command.getId(), now, msg.toString());
e.save(); e.save();
@@ -293,7 +291,7 @@ public class SyncManager
private void executeCommand(JSONObject root) throws JSONException private void executeCommand(JSONObject root) throws JSONException
{ {
Command received = commandParser.fromJSON(root); Command received = commandParser.parse(root);
for (Event e : pendingConfirmation) for (Event e : pendingConfirmation)
{ {
if (e.serverId.equals(received.getId())) if (e.serverId.equals(received.getId()))

View File

@@ -26,11 +26,13 @@ import org.junit.*;
import java.util.*; import java.util.*;
import static junit.framework.Assert.*; import static junit.framework.Assert.*;
import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;
public class ArchiveHabitsCommandTest extends BaseUnitTest public class ArchiveHabitsCommandTest extends BaseUnitTest
{ {
private ArchiveHabitsCommand command; private ArchiveHabitsCommand command;
private Habit habit; private Habit habit;
@Override @Override
@@ -40,8 +42,10 @@ public class ArchiveHabitsCommandTest extends BaseUnitTest
super.setUp(); super.setUp();
habit = fixtures.createShortHabit(); habit = fixtures.createShortHabit();
command = new ArchiveHabitsCommand(habitList, Collections habitList.add(habit);
.singletonList(habit));
command = new ArchiveHabitsCommand(habitList,
Collections.singletonList(habit));
} }
@Test @Test
@@ -58,4 +62,13 @@ public class ArchiveHabitsCommandTest extends BaseUnitTest
command.execute(); command.execute();
assertTrue(habit.isArchived()); assertTrue(habit.isArchived());
} }
@Test
public void testRecord()
{
ArchiveHabitsCommand.Record rec = command.toRecord();
ArchiveHabitsCommand other = rec.toCommand(habitList);
assertThat(other.selected, equalTo(command.selected));
assertThat(other.getId(), equalTo(command.getId()));
}
} }

View File

@@ -32,7 +32,7 @@ public class ChangeHabitColorCommandTest extends BaseUnitTest
{ {
private ChangeHabitColorCommand command; private ChangeHabitColorCommand command;
private LinkedList<Habit> habits; private LinkedList<Habit> selected;
@Override @Override
@Before @Before
@@ -40,16 +40,17 @@ public class ChangeHabitColorCommandTest extends BaseUnitTest
{ {
super.setUp(); super.setUp();
habits = new LinkedList<>(); selected = new LinkedList<>();
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++)
{ {
Habit habit = fixtures.createShortHabit(); Habit habit = fixtures.createShortHabit();
habit.setColor(i + 1); habit.setColor(i + 1);
habits.add(habit); selected.add(habit);
habitList.add(habit);
} }
command = new ChangeHabitColorCommand(habitList, habits, 0); command = new ChangeHabitColorCommand(habitList, selected, 0);
} }
@Test @Test
@@ -67,16 +68,26 @@ public class ChangeHabitColorCommandTest extends BaseUnitTest
checkNewColors(); checkNewColors();
} }
@Test
public void testRecord()
{
ChangeHabitColorCommand.Record rec = command.toRecord();
ChangeHabitColorCommand other = rec.toCommand(habitList);
assertThat(other.getId(), equalTo(command.getId()));
assertThat(other.newColor, equalTo(command.newColor));
assertThat(other.selected, equalTo(command.selected));
}
private void checkNewColors() private void checkNewColors()
{ {
for (Habit h : habits) for (Habit h : selected)
assertThat(h.getColor(), equalTo(0)); assertThat(h.getColor(), equalTo(0));
} }
private void checkOriginalColors() private void checkOriginalColors()
{ {
int k = 0; int k = 0;
for (Habit h : habits) for (Habit h : selected)
assertThat(h.getColor(), equalTo(++k)); assertThat(h.getColor(), equalTo(++k));
} }
} }

View File

@@ -0,0 +1,159 @@
/*
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.commands;
import android.support.annotation.*;
import org.isoron.uhabits.*;
import org.isoron.uhabits.models.*;
import org.json.*;
import org.junit.*;
import java.util.*;
import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;
public class CommandParserTest extends BaseUnitTest
{
@NonNull
private CommandParser parser;
private Habit habit;
private List<Habit> selected;
@Override
@Before
public void setUp()
{
super.setUp();
parser = new CommandParser(habitList, modelFactory);
habit = fixtures.createShortHabit();
selected = Collections.singletonList(habit);
habitList.add(habit);
}
@Test
public void testDecodeArchiveCommand() throws JSONException
{
ArchiveHabitsCommand original, decoded;
original = new ArchiveHabitsCommand(habitList, selected);
decoded = (ArchiveHabitsCommand) parser.parse(original.toJson());
assertThat(decoded.getId(), equalTo(original.getId()));
assertThat(decoded.selected, equalTo(original.selected));
}
@Test
public void testDecodeChangeColorCommand() throws JSONException
{
ChangeHabitColorCommand original, decoded;
original = new ChangeHabitColorCommand(habitList, selected, 20);
decoded = (ChangeHabitColorCommand) parser.parse(original.toJson());
assertThat(decoded.getId(), equalTo(original.getId()));
assertThat(decoded.newColor, equalTo(original.newColor));
assertThat(decoded.selected, equalTo(original.selected));
}
@Test
public void testDecodeCreateHabitCommand() throws JSONException
{
Habit model = modelFactory.buildHabit();
model.setName("JSON");
CreateHabitCommand original, decoded;
original = new CreateHabitCommand(modelFactory, habitList, model);
original.execute();
decoded = (CreateHabitCommand) parser.parse(original.toJson());
assertThat(decoded.getId(), equalTo(original.getId()));
assertThat(decoded.savedId, equalTo(original.savedId));
assertThat(decoded.model.getData(), equalTo(model.getData()));
}
@Test
public void testDecodeCreateRepCommand() throws JSONException
{
CreateRepetitionCommand original, decoded;
original = new CreateRepetitionCommand(habit, 1000, 5);
decoded = (CreateRepetitionCommand) parser.parse(original.toJson());
assertThat(decoded.getId(), equalTo(original.getId()));
assertThat(decoded.timestamp, equalTo(original.timestamp));
assertThat(decoded.value, equalTo(original.value));
assertThat(decoded.habit, equalTo(original.habit));
}
@Test
public void testDecodeDeleteCommand() throws JSONException
{
DeleteHabitsCommand original, decoded;
original = new DeleteHabitsCommand(habitList, selected);
decoded = (DeleteHabitsCommand) parser.parse(original.toJson());
assertThat(decoded.getId(), equalTo(original.getId()));
assertThat(decoded.selected, equalTo(original.selected));
}
@Test
public void testDecodeEditHabitCommand() throws JSONException
{
Habit modified = modelFactory.buildHabit();
modified.setName("Edited JSON");
modified.setColor(2);
EditHabitCommand original, decoded;
original = new EditHabitCommand(modelFactory, habitList, habit, modified);
original.execute();
decoded = (EditHabitCommand) parser.parse(original.toJson());
assertThat(decoded.getId(), equalTo(original.getId()));
assertThat(decoded.savedId, equalTo(original.savedId));
assertThat(decoded.modified.getData(), equalTo(modified.getData()));
}
@Test
public void testDecodeToggleCommand() throws JSONException
{
ToggleRepetitionCommand original, decoded;
original = new ToggleRepetitionCommand(habit, 1000);
decoded = (ToggleRepetitionCommand) parser.parse(original.toJson());
assertThat(decoded.getId(), equalTo(original.getId()));
assertThat(decoded.timestamp, equalTo(original.timestamp));
assertThat(decoded.habit, equalTo(original.habit));
}
@Test
public void testDecodeUnarchiveCommand() throws JSONException
{
UnarchiveHabitsCommand original, decoded;
original = new UnarchiveHabitsCommand(habitList, selected);
decoded = (UnarchiveHabitsCommand) parser.parse(original.toJson());
assertThat(decoded.getId(), equalTo(original.getId()));
assertThat(decoded.selected, equalTo(original.selected));
}
}

View File

@@ -41,6 +41,7 @@ public class CreateHabitCommandTest extends BaseUnitTest
model = fixtures.createEmptyHabit(); model = fixtures.createEmptyHabit();
model.setName("New habit"); model.setName("New habit");
model.setReminder(new Reminder(8, 30, WeekdayList.EVERY_DAY));
command = new CreateHabitCommand(modelFactory, habitList, model); command = new CreateHabitCommand(modelFactory, habitList, model);
} }
@@ -70,5 +71,16 @@ public class CreateHabitCommandTest extends BaseUnitTest
assertThat(habit.getName(), equalTo(model.getName())); assertThat(habit.getName(), equalTo(model.getName()));
} }
@Test
public void testRecord()
{
command.execute();
CreateHabitCommand.Record rec = command.toRecord();
CreateHabitCommand other = rec.toCommand(modelFactory, habitList);
assertThat(other.getId(), equalTo(command.getId()));
assertThat(other.savedId, equalTo(command.savedId));
assertThat(other.model.getData(), equalTo(command.model.getData()));
}
} }

View File

@@ -25,11 +25,12 @@ import org.isoron.uhabits.utils.*;
import org.junit.*; import org.junit.*;
import static junit.framework.Assert.*; import static junit.framework.Assert.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.isoron.uhabits.models.Checkmark.CHECKED_EXPLICITLY; import static org.isoron.uhabits.models.Checkmark.CHECKED_EXPLICITLY;
public class CreateRepetitionCommandTest extends BaseUnitTest public class CreateRepetitionCommandTest extends BaseUnitTest
{ {
private CreateRepetitionCommand command; private CreateRepetitionCommand command;
private Habit habit; private Habit habit;
@@ -43,6 +44,7 @@ public class CreateRepetitionCommandTest extends BaseUnitTest
super.setUp(); super.setUp();
habit = fixtures.createShortHabit(); habit = fixtures.createShortHabit();
habitList.add(habit);
today = DateUtils.getStartOfToday(); today = DateUtils.getStartOfToday();
command = new CreateRepetitionCommand(habit, today, 100); command = new CreateRepetitionCommand(habit, today, 100);
@@ -67,4 +69,16 @@ public class CreateRepetitionCommandTest extends BaseUnitTest
assertNotNull(rep); assertNotNull(rep);
assertEquals(CHECKED_EXPLICITLY, rep.getValue()); assertEquals(CHECKED_EXPLICITLY, rep.getValue());
} }
@Test
public void testRecord()
{
CreateRepetitionCommand.Record rec = command.toRecord();
CreateRepetitionCommand other = rec.toCommand(habitList);
assertThat(command.getId(), equalTo(other.getId()));
assertThat(command.timestamp, equalTo(other.timestamp));
assertThat(command.value, equalTo(other.value));
assertThat(command.habit, equalTo(other.habit));
}
} }

View File

@@ -73,4 +73,13 @@ public class DeleteHabitsCommandTest extends BaseUnitTest
thrown.expect(UnsupportedOperationException.class); thrown.expect(UnsupportedOperationException.class);
command.undo(); command.undo();
} }
@Test
public void testRecord()
{
DeleteHabitsCommand.Record rec = command.toRecord();
DeleteHabitsCommand other = rec.toCommand(habitList);
assertThat(other.getId(), equalTo(command.getId()));
assertThat(other.selected, equalTo(command.selected));
}
} }

View File

@@ -28,7 +28,6 @@ import static org.hamcrest.Matchers.*;
public class EditHabitCommandTest extends BaseUnitTest public class EditHabitCommandTest extends BaseUnitTest
{ {
private EditHabitCommand command; private EditHabitCommand command;
private Habit habit; private Habit habit;
@@ -98,4 +97,19 @@ public class EditHabitCommandTest extends BaseUnitTest
assertThat(habit.getScores().getTodayValue(), assertThat(habit.getScores().getTodayValue(),
lessThan(originalScore)); lessThan(originalScore));
} }
@Test
public void testRecord()
{
command =
new EditHabitCommand(modelFactory, habitList, habit, modified);
EditHabitCommand.Record rec = command.toRecord();
EditHabitCommand other = rec.toCommand(modelFactory, habitList);
assertThat(other.getId(), equalTo(command.getId()));
assertThat(other.savedId, equalTo(command.savedId));
assertThat(other.original.getData(), equalTo(command.original.getData()));
assertThat(other.modified.getData(), equalTo(command.modified.getData()));
}
} }

View File

@@ -25,6 +25,8 @@ import org.isoron.uhabits.utils.*;
import org.junit.*; import org.junit.*;
import static junit.framework.Assert.*; import static junit.framework.Assert.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
public class ToggleRepetitionCommandTest extends BaseUnitTest public class ToggleRepetitionCommandTest extends BaseUnitTest
{ {
@@ -40,6 +42,7 @@ public class ToggleRepetitionCommandTest extends BaseUnitTest
super.setUp(); super.setUp();
habit = fixtures.createShortHabit(); habit = fixtures.createShortHabit();
habitList.add(habit);
today = DateUtils.getStartOfToday(); today = DateUtils.getStartOfToday();
command = new ToggleRepetitionCommand(habit, today); command = new ToggleRepetitionCommand(habit, today);
@@ -59,4 +62,15 @@ public class ToggleRepetitionCommandTest extends BaseUnitTest
command.execute(); command.execute();
assertFalse(habit.getRepetitions().containsTimestamp(today)); assertFalse(habit.getRepetitions().containsTimestamp(today));
} }
@Test
public void testRecord()
{
ToggleRepetitionCommand.Record rec = command.toRecord();
ToggleRepetitionCommand other = rec.toCommand(habitList);
assertThat(command.getId(), equalTo(other.getId()));
assertThat(command.timestamp, equalTo(other.timestamp));
assertThat(command.habit, equalTo(other.habit));
}
} }

View File

@@ -26,6 +26,8 @@ import org.junit.*;
import java.util.*; import java.util.*;
import static junit.framework.Assert.*; import static junit.framework.Assert.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
public class UnarchiveHabitsCommandTest extends BaseUnitTest public class UnarchiveHabitsCommandTest extends BaseUnitTest
{ {
@@ -61,4 +63,13 @@ public class UnarchiveHabitsCommandTest extends BaseUnitTest
command.execute(); command.execute();
assertFalse(habit.isArchived()); assertFalse(habit.isArchived());
} }
@Test
public void testRecord()
{
UnarchiveHabitsCommand.Record rec = command.toRecord();
UnarchiveHabitsCommand other = rec.toCommand(habitList);
assertThat(other.selected, equalTo(command.selected));
assertThat(other.getId(), equalTo(command.getId()));
}
} }