Skip to content

Commit

Permalink
Replace instance_status by distance_from_current, implements #606 (
Browse files Browse the repository at this point in the history
…#607)

This commit replaces the `instance_status` column with a more veratile `distance_from_current` which has additional semantics for upcoming instances.
  • Loading branch information
dmfs authored Jan 2, 2018
1 parent d0ff43e commit ed50e42
Show file tree
Hide file tree
Showing 8 changed files with 73 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1044,30 +1044,14 @@ public interface InstanceColumns
String INSTANCE_ORIGINAL_TIME = "instance_original_time";

/**
* A flag indicating the completion status of an instance. This is one of {@link #INSTANCE_STATUS_CLOSED}, {@link #INSTANCE_STATUS_NEXT} or {@link
* #INSTANCE_STATUS_UPCOMING}.
* The distance of the instance from the current one. For closed instances this is always {@code -1}, for the current instance this is {@code 0}. For
* the instance after the current one this is {@code 1}, for the instance after that one it's {@code 2}, etc..
* <p>
* Value: Integer
* <p>
* read-only
*/
String INSTANCE_STATUS = "instance_status";

/**
* Status of an instance which is completed or cancelled.
*/
int INSTANCE_STATUS_CLOSED = -1;

/**
* Status of the next instance to complete.
*/
int INSTANCE_STATUS_NEXT = 0;

/**
* Status of all instances after the next one.
*/
int INSTANCE_STATUS_UPCOMING = 1;

String DISTANCE_FROM_CURRENT = "distance_from_current";
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ public void testSingleInsert()
new IsNull(Instances.INSTANCE_DUE_SORTING),
new IsNull(Instances.INSTANCE_DURATION),
new IsNull(Tasks.TZ),
new EqArg(Instances.INSTANCE_STATUS, Instances.INSTANCE_STATUS_NEXT)
new EqArg(Instances.DISTANCE_FROM_CURRENT, 0)
))
));
}
Expand Down Expand Up @@ -193,7 +193,7 @@ public void testMultipleInserts()
new IsNull(Instances.INSTANCE_DUE_SORTING),
new IsNull(Instances.INSTANCE_DURATION),
new IsNull(Tasks.TZ),
new EqArg(Instances.INSTANCE_STATUS, Instances.INSTANCE_STATUS_NEXT)
new EqArg(Instances.DISTANCE_FROM_CURRENT, 0)
)),
new AssertRelated<>(new InstanceTable(mAuthority), Instances.TASK_ID, task2, new AllOf(
new IsNull(Instances.INSTANCE_START),
Expand All @@ -203,7 +203,7 @@ public void testMultipleInserts()
new IsNull(Instances.INSTANCE_DUE_SORTING),
new IsNull(Instances.INSTANCE_DURATION),
new IsNull(Tasks.TZ),
new EqArg(Instances.INSTANCE_STATUS, Instances.INSTANCE_STATUS_NEXT)
new EqArg(Instances.DISTANCE_FROM_CURRENT, 0)
)),
new AssertRelated<>(new InstanceTable(mAuthority), Instances.TASK_ID, task3, new AllOf(
new IsNull(Instances.INSTANCE_START),
Expand All @@ -213,7 +213,7 @@ public void testMultipleInserts()
new IsNull(Instances.INSTANCE_DUE_SORTING),
new IsNull(Instances.INSTANCE_DURATION),
new IsNull(Tasks.TZ),
new EqArg(Instances.INSTANCE_STATUS, Instances.INSTANCE_STATUS_NEXT)
new EqArg(Instances.DISTANCE_FROM_CURRENT, 0)
))
));
}
Expand Down Expand Up @@ -245,7 +245,7 @@ public void testInsertTaskWithStartAndDue()
new EqArg(Instances.INSTANCE_DUE_SORTING, due.shiftTimeZone(TimeZone.getDefault()).getInstance()),
new EqArg(Instances.INSTANCE_DURATION, due.getTimestamp() - start.getTimestamp()),
new EqArg(Tasks.TZ, start.isAllDay() ? "UTC" : start.getTimeZone().getID()),
new EqArg(Instances.INSTANCE_STATUS, Instances.INSTANCE_STATUS_NEXT)
new EqArg(Instances.DISTANCE_FROM_CURRENT, 0)
))
));
}
Expand Down Expand Up @@ -278,7 +278,7 @@ public void testInsertTaskWithStartAndDueUpdateStatus()
new EqArg(Instances.INSTANCE_DUE_SORTING, due.shiftTimeZone(TimeZone.getDefault()).getInstance()),
new EqArg(Instances.INSTANCE_DURATION, due.getTimestamp() - start.getTimestamp()),
new EqArg(Tasks.TZ, start.isAllDay() ? "UTC" : start.getTimeZone().getID()),
new EqArg(Instances.INSTANCE_STATUS, Instances.INSTANCE_STATUS_CLOSED)
new EqArg(Instances.DISTANCE_FROM_CURRENT, -1)
))
));
}
Expand Down Expand Up @@ -314,7 +314,7 @@ public void testInsertTaskWithStartAndDueMovedForward()
new EqArg(Instances.INSTANCE_DUE_SORTING, dueNew.shiftTimeZone(TimeZone.getDefault()).getInstance()),
new EqArg(Instances.INSTANCE_DURATION, dueNew.getTimestamp() - startNew.getTimestamp()),
new EqArg(Tasks.TZ, start.isAllDay() ? "UTC" : start.getTimeZone().getID()),
new EqArg(Instances.INSTANCE_STATUS, Instances.INSTANCE_STATUS_NEXT)
new EqArg(Instances.DISTANCE_FROM_CURRENT, 0)
))
));
}
Expand Down Expand Up @@ -350,7 +350,7 @@ public void testInsertTaskWithStartAndDueMovedBackwards()
new EqArg(Instances.INSTANCE_DUE_SORTING, dueNew.shiftTimeZone(TimeZone.getDefault()).getInstance()),
new EqArg(Instances.INSTANCE_DURATION, dueNew.getTimestamp() - startNew.getTimestamp()),
new EqArg(Tasks.TZ, start.isAllDay() ? "UTC" : start.getTimeZone().getID()),
new EqArg(Instances.INSTANCE_STATUS, Instances.INSTANCE_STATUS_NEXT)
new EqArg(Instances.DISTANCE_FROM_CURRENT, 0)
))
));
}
Expand Down Expand Up @@ -382,7 +382,7 @@ public void testInsertTaskWithStartAndDueAddedAfterwards()
new EqArg(Instances.INSTANCE_DUE_SORTING, due.shiftTimeZone(TimeZone.getDefault()).getInstance()),
new EqArg(Instances.INSTANCE_DURATION, due.getTimestamp() - start.getTimestamp()),
new EqArg(Tasks.TZ, start.isAllDay() ? "UTC" : start.getTimeZone().getID()),
new EqArg(Instances.INSTANCE_STATUS, Instances.INSTANCE_STATUS_NEXT)
new EqArg(Instances.DISTANCE_FROM_CURRENT, 0)
))
));
}
Expand Down Expand Up @@ -415,7 +415,7 @@ public void testInsertWithStartAndDuration()
new EqArg(Instances.INSTANCE_DUE_SORTING, start.addDuration(duration).shiftTimeZone(TimeZone.getDefault()).getInstance()),
new EqArg(Instances.INSTANCE_ORIGINAL_TIME, 0),
new EqArg(Tasks.TZ, "UTC"),
new EqArg(Instances.INSTANCE_STATUS, Instances.INSTANCE_STATUS_NEXT)
new EqArg(Instances.DISTANCE_FROM_CURRENT, 0)
))
));
}
Expand Down Expand Up @@ -452,7 +452,7 @@ public void testInsertWithStartAndDurationChangeTimeZone()
new EqArg(Instances.INSTANCE_DUE_SORTING, start.addDuration(duration).shiftTimeZone(TimeZone.getDefault()).getInstance()),
new EqArg(Instances.INSTANCE_ORIGINAL_TIME, 0),
new EqArg(Tasks.TZ, "America/New_York"),
new EqArg(Instances.INSTANCE_STATUS, Instances.INSTANCE_STATUS_NEXT)
new EqArg(Instances.DISTANCE_FROM_CURRENT, 0)
))
));
}
Expand Down Expand Up @@ -493,7 +493,7 @@ public void testUpdateDue() throws Exception
new EqArg(Instances.INSTANCE_DUE_SORTING, due2.shiftTimeZone(TimeZone.getDefault()).getInstance()),
new EqArg(Instances.INSTANCE_ORIGINAL_TIME, 0),
new EqArg(Tasks.TZ, "UTC"),
new EqArg(Instances.INSTANCE_STATUS, Instances.INSTANCE_STATUS_NEXT)
new EqArg(Instances.DISTANCE_FROM_CURRENT, 0)
))
));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ public interface CategoriesMapping
+ TaskContract.Instances.INSTANCE_DUE_SORTING + " INTEGER, "
+ TaskContract.Instances.INSTANCE_DURATION + " INTEGER, "
+ TaskContract.Instances.INSTANCE_ORIGINAL_TIME + " INTEGER DEFAULT 0, "
+ TaskContract.Instances.INSTANCE_STATUS + " INTEGER DEFAULT " + TaskContract.Instances.INSTANCE_STATUS_NEXT + ");";
+ TaskContract.Instances.DISTANCE_FROM_CURRENT + " INTEGER DEFAULT 0);";

/**
* SQL command to create a trigger to clean up data of removed tasks.
Expand Down Expand Up @@ -770,8 +770,7 @@ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)

if (oldVersion < 18)
{
db.execSQL(
"alter table " + Tables.INSTANCES + " add column " + TaskContract.Instances.INSTANCE_STATUS + " integer default " + TaskContract.Instances.INSTANCE_STATUS_NEXT + ";");
db.execSQL("alter table " + Tables.INSTANCES + " add column " + TaskContract.Instances.DISTANCE_FROM_CURRENT + " integer default 0;");
}

// upgrade FTS
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,19 @@


/**
* A {@link Single} of the instance status {@link ContentValues} of an instance.
* A {@link Single} of the instance distance {@link ContentValues} of an instance.
*
* @author Marten Gajda
*/
public final class Stated extends DelegatingSingle<ContentValues>
public final class Distant extends DelegatingSingle<ContentValues>
{

public Stated(boolean closed, Single<ContentValues> delegate)
public Distant(int distance, Single<ContentValues> delegate)
{
super(() ->
{
ContentValues values = delegate.value();
values.put(TaskContract.Instances.INSTANCE_STATUS,
closed ? TaskContract.Instances.INSTANCE_STATUS_CLOSED : TaskContract.Instances.INSTANCE_STATUS_NEXT);
values.put(TaskContract.Instances.DISTANCE_FROM_CURRENT, distance);
return values;
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@

/**
* A {@link Single} of instance data {@link ContentValues}. It initializes most columns with {@code null} values, except for {@link
* TaskContract.Instances#TASK_ID} which is left out and {@link TaskContract.Instances#INSTANCE_ORIGINAL_TIME} which is initialized with {@code 0}.
* TaskContract.Instances#TASK_ID} which is left out, {@link TaskContract.Instances#INSTANCE_ORIGINAL_TIME} which is initialized with {@code 0} and {@link
* TaskContract.Instances#DISTANCE_FROM_CURRENT} which is initialized with {@code 0} as well.
*
* @author Marten Gajda
*/
Expand All @@ -39,7 +40,7 @@ public ContentValues value()
values.putNull(TaskContract.Instances.INSTANCE_DUE);
values.putNull(TaskContract.Instances.INSTANCE_DUE_SORTING);
values.putNull(TaskContract.Instances.INSTANCE_DURATION);
values.put(TaskContract.Instances.INSTANCE_STATUS, TaskContract.Instances.INSTANCE_STATUS_NEXT);
values.put(TaskContract.Instances.DISTANCE_FROM_CURRENT, 0);
values.put(TaskContract.Instances.INSTANCE_ORIGINAL_TIME, 0);
return values;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@
import org.dmfs.optional.adapters.FirstPresent;
import org.dmfs.optional.composite.Zipped;
import org.dmfs.provider.tasks.model.TaskAdapter;
import org.dmfs.provider.tasks.processors.tasks.instancedata.Distant;
import org.dmfs.provider.tasks.processors.tasks.instancedata.DueDated;
import org.dmfs.provider.tasks.processors.tasks.instancedata.Enduring;
import org.dmfs.provider.tasks.processors.tasks.instancedata.Overridden;
import org.dmfs.provider.tasks.processors.tasks.instancedata.StartDated;
import org.dmfs.provider.tasks.processors.tasks.instancedata.Stated;
import org.dmfs.provider.tasks.processors.tasks.instancedata.VanillaInstanceData;
import org.dmfs.rfc5545.DateTime;

Expand Down Expand Up @@ -63,7 +63,7 @@ public Iterator<Single<ContentValues>> iterator()
new NullSafe<>(mTaskAdapter.valueOf(TaskAdapter.DUE)),
new Zipped<>(start, new NullSafe<>(mTaskAdapter.valueOf(TaskAdapter.DURATION)), DateTime::addDuration)));

Single<ContentValues> baseData = new Stated(mTaskAdapter.valueOf(TaskAdapter.IS_CLOSED),
Single<ContentValues> baseData = new Distant(mTaskAdapter.valueOf(TaskAdapter.IS_CLOSED) ? -1 : 0,
new Enduring(new DueDated(effectiveDue, new StartDated(start, new VanillaInstanceData()))));

// TODO: implement support for recurrence, for now we only return the first instance
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright 2017 dmfs GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.dmfs.provider.tasks.processors.tasks.instancedata;

import android.content.ContentValues;

import org.dmfs.tasks.contract.TaskContract;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;

import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;


/**
* @author Marten Gajda
*/
@RunWith(RobolectricTestRunner.class)
@Config(manifest = Config.NONE)
public class DistantTest
{

@Test
public void test() throws Exception
{
ContentValues instanceData = new Distant(100, ContentValues::new).value();
assertThat(instanceData.get(TaskContract.Instances.DISTANCE_FROM_CURRENT), is(100));
assertThat(instanceData.size(), is(1));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public void testValue() throws Exception
assertThat(values.get(TaskContract.Instances.INSTANCE_DUE), nullValue());
assertThat(values.get(TaskContract.Instances.INSTANCE_DUE_SORTING), nullValue());
assertThat(values.get(TaskContract.Instances.INSTANCE_DURATION), nullValue());
assertThat(values.get(TaskContract.Instances.INSTANCE_STATUS), is(TaskContract.Instances.INSTANCE_STATUS_NEXT));
assertThat(values.get(TaskContract.Instances.DISTANCE_FROM_CURRENT), is(0));
assertThat(values.get(TaskContract.Instances.INSTANCE_ORIGINAL_TIME), is(0));
assertThat(values.size(), is(7));
}
Expand Down

0 comments on commit ed50e42

Please sign in to comment.