Skip to content

Commit

Permalink
Respect existing overrides, implements #952 (#974)
Browse files Browse the repository at this point in the history
  • Loading branch information
dmfs authored Feb 10, 2021
1 parent c2cf2f2 commit b389651
Show file tree
Hide file tree
Showing 14 changed files with 507 additions and 66 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -648,6 +648,134 @@ public void testRRuleWithOverride() throws InvalidRecurrenceRuleException
}


/**
* Test RRULE with overridden instance (inserted into the tasks table) and a completed 1st instance.
*/
@Test
public void testRRuleWith2ndOverrideAndCompleted1st() throws InvalidRecurrenceRuleException
{
RowSnapshot<TaskLists> taskList = new VirtualRowSnapshot<>(new LocalTaskListsTable(mAuthority));
Table<Instances> instancesTable = new InstanceTable(mAuthority);
RowSnapshot<Tasks> task = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority)));
RowSnapshot<Tasks> taskOverride = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority)));

Duration hour = new Duration(1, 0, 3600 /* 1 hour */);
DateTime start = DateTime.parse("20180104T123456Z");
DateTime due = start.addDuration(hour);

Duration day = new Duration(1, 1, 0);

DateTime localStart = start.shiftTimeZone(TimeZone.getDefault());
DateTime localDue = due.shiftTimeZone(TimeZone.getDefault());

DateTime second = localStart.addDuration(day);
DateTime third = second.addDuration(day);
DateTime fourth = third.addDuration(day);
DateTime fifth = fourth.addDuration(day);

assertThat(new Seq<>(
new Put<>(taskList, new EmptyRowData<>()),
new Put<>(task,
new Composite<>(
new TimeData<>(start, due),
new TitleData("original"),
new RRuleTaskData(new RecurrenceRule("FREQ=DAILY;COUNT=5", RecurrenceRule.RfcMode.RFC2445_LAX)))),
// the override moves the instance by an hour
new Put<>(taskOverride, new Composite<>(
new TimeData<>(second.addDuration(hour), second.addDuration(hour).addDuration(hour)),
new TitleData("override"),
new OriginalInstanceData(task, second))),
new Put<>(task, new StatusData<>(Tasks.STATUS_COMPLETED))),
resultsIn(mClient,
new Assert<>(task,
new Composite<>(
new TimeData<>(start, due),
new CharSequenceRowData<>(Tasks.TITLE, "original"),
new CharSequenceRowData<>(Tasks.RRULE, "FREQ=DAILY;COUNT=5"),
new StatusData<>(Tasks.STATUS_COMPLETED))),
new Assert<>(taskOverride,
new Composite<>(
new TimeData<>(second.addDuration(hour), second.addDuration(hour).addDuration(hour)),
new CharSequenceRowData<>(Tasks.TITLE, "override"),
new OriginalInstanceData(task, second))),
// 1st (completed) instance:
new Counted<>(1, new AssertRelated<>(instancesTable, Instances.TASK_ID, task,
new InstanceTestData(localStart, localDue, new Present<>(start), -1),
new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, start.getTimestamp()))),
// 2nd instance (now the current one):
new Counted<>(1, new AssertRelated<>(instancesTable, Instances.TASK_ID, taskOverride,
new InstanceTestData(
second.addDuration(hour),
second.addDuration(hour).addDuration(hour),
new Present<>(second), 0)))));
}


/**
* Test RRULE with overridden instance (inserted into the tasks table) and a deleted 1st instance.
*/
@Test
public void testRRuleWith2ndOverrideAndDeleted1st() throws InvalidRecurrenceRuleException
{
RowSnapshot<TaskLists> taskList = new VirtualRowSnapshot<>(new LocalTaskListsTable(mAuthority));
Table<Instances> instancesTable = new InstanceTable(mAuthority);
RowSnapshot<Tasks> task = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority)));
RowSnapshot<Tasks> taskOverride = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority)));

Duration hour = new Duration(1, 0, 3600 /* 1 hour */);
DateTime start = DateTime.parse("20180104T123456Z");
DateTime due = start.addDuration(hour);

Duration day = new Duration(1, 1, 0);

DateTime localStart = start.shiftTimeZone(TimeZone.getDefault());
DateTime localDue = due.shiftTimeZone(TimeZone.getDefault());

DateTime second = localStart.addDuration(day);
DateTime third = second.addDuration(day);
DateTime fourth = third.addDuration(day);
DateTime fifth = fourth.addDuration(day);

assertThat(new Seq<>(
new Put<>(taskList, new EmptyRowData<>()),
new Put<>(task,
new Composite<>(
new TimeData<>(start, due),
new TitleData("original"),
new RRuleTaskData(new RecurrenceRule("FREQ=DAILY;COUNT=5", RecurrenceRule.RfcMode.RFC2445_LAX)))),
// the override moves the instance by an hour
new Put<>(taskOverride, new Composite<>(
new TimeData<>(second.addDuration(hour), second.addDuration(hour).addDuration(hour)),
new TitleData("override"),
new OriginalInstanceData(task, second))),
// delete 1st instance
new BulkDelete<>(instancesTable, new AllOf<>(
new ReferringTo<>(Instances.TASK_ID, task),
new EqArg<>(Instances.DISTANCE_FROM_CURRENT, "0")))),
resultsIn(mClient,
new Assert<>(task,
new Composite<>(
new TimeData<>(start, due),
new CharSequenceRowData<>(Tasks.TITLE, "original"),
new CharSequenceRowData<>(Tasks.RRULE, "FREQ=DAILY;COUNT=5"),
new CharSequenceRowData<>(Tasks.EXDATE, start.toString()),
new StatusData<>(Tasks.STATUS_DEFAULT))),
new Assert<>(taskOverride,
new Composite<>(
new TimeData<>(second.addDuration(hour), second.addDuration(hour).addDuration(hour)),
new CharSequenceRowData<>(Tasks.TITLE, "override"),
new OriginalInstanceData(task, second))),
// no instances point to the original task
new Counted<>(0, new AssertRelated<>(instancesTable, Instances.TASK_ID, task)),
// 2nd instance (now the current one):
new Counted<>(1, new AssertRelated<>(instancesTable, Instances.TASK_ID, taskOverride,
new InstanceTestData(
second.addDuration(hour),
second.addDuration(hour).addDuration(hour),
new Present<>(second), 0)))));
}


/**
* Test RRULE with overridden instance (via update on the instances table). This time we don't override the date time fields and expect the instance to
* inherit the original instance start and due (instead of the master start and due)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,8 @@ public DateTime getFrom(ContentValues values)
// if the time stamp is null we return null
return null;
}
// create a new Time for the given time zone, falling back to UTC if none is given
String timezone = mTzField == null ? null : values.getAsString(mTzField);
DateTime value = new DateTime(timezone == null ? DateTime.UTC : TimeZone.getTimeZone(timezone), timestamp);
DateTime value = new DateTime(timezone == null ? null : TimeZone.getTimeZone(timezone), timestamp);

// cache mAlldayField locally
String allDayField = mAllDayField;
Expand Down Expand Up @@ -128,9 +127,8 @@ public DateTime getFrom(Cursor cursor)

Long timestamp = cursor.getLong(tsIdx);

// create a new Time for the given time zone, falling back to UTC if none is given
String timezone = mTzField == null ? null : cursor.getString(tzIdx);
DateTime value = new DateTime(timezone == null ? DateTime.UTC : TimeZone.getTimeZone(timezone), timestamp);
DateTime value = new DateTime(timezone == null ? null : TimeZone.getTimeZone(timezone), timestamp);

// set the allday flag appropriately
Integer allDayInt = adIdx < 0 ? null : cursor.getInt(adIdx);
Expand Down Expand Up @@ -208,8 +206,7 @@ else if (cursor != null && (adIdx = cursor.getColumnIndex(mAllDayField)) >= 0)
}
}

// create a new Time for the given time zone, falling back to UTC if none is given
DateTime value = new DateTime(timeZoneId == null ? DateTime.UTC : TimeZone.getTimeZone(timeZoneId), timestamp);
DateTime value = new DateTime(timeZoneId == null ? null : TimeZone.getTimeZone(timeZoneId), timestamp);

if (allDay != 0)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import org.dmfs.jems.optional.adapters.FirstPresent;
import org.dmfs.jems.optional.elementary.NullSafe;
import org.dmfs.jems.predicate.composite.AnyOf;
import org.dmfs.jems.predicate.composite.Not;
import org.dmfs.provider.tasks.TaskDatabaseHelper;
import org.dmfs.provider.tasks.model.CursorContentValuesInstanceAdapter;
import org.dmfs.provider.tasks.model.CursorContentValuesTaskAdapter;
Expand Down Expand Up @@ -195,7 +196,7 @@ private InstanceAdapter detachAll(SQLiteDatabase db, InstanceAdapter entityAdapt
{
// remove the RRULE but keep a mask for the old start
masterTask.set(TaskAdapter.EXDATE,
new Joined<>(new SingletonIterable<>(oldStart), new Sieved<>(oldStart::equals, masterTask.valueOf(TaskAdapter.EXDATE))));
new Joined<>(new SingletonIterable<>(oldStart), new Sieved<>(new Not<>(oldStart::equals), masterTask.valueOf(TaskAdapter.EXDATE))));
masterTask.set(TaskAdapter.RRULE, null);
}
else
Expand Down
Loading

0 comments on commit b389651

Please sign in to comment.