diff --git a/lib/src/main/kotlin/at/bitfire/synctools/mapping/tasks/DmfsTaskProcessor.kt b/lib/src/main/kotlin/at/bitfire/synctools/mapping/tasks/DmfsTaskProcessor.kt index 67a4c220..bce83537 100644 --- a/lib/src/main/kotlin/at/bitfire/synctools/mapping/tasks/DmfsTaskProcessor.kt +++ b/lib/src/main/kotlin/at/bitfire/synctools/mapping/tasks/DmfsTaskProcessor.kt @@ -11,9 +11,14 @@ import at.bitfire.ical4android.Task import at.bitfire.ical4android.UnknownProperty import at.bitfire.ical4android.util.TimeApiExtensions.toLocalDate import at.bitfire.synctools.mapping.tasks.handler.AlarmsHandler +import at.bitfire.synctools.mapping.tasks.handler.ClassificationHandler +import at.bitfire.synctools.mapping.tasks.handler.CompletedHandler import at.bitfire.synctools.mapping.tasks.handler.DmfsTaskFieldHandler import at.bitfire.synctools.mapping.tasks.handler.DmfsTaskPropertyHandler +import at.bitfire.synctools.mapping.tasks.handler.PercentCompleteHandler +import at.bitfire.synctools.mapping.tasks.handler.PriorityHandler import at.bitfire.synctools.mapping.tasks.handler.SequenceHandler +import at.bitfire.synctools.mapping.tasks.handler.StatusHandler import at.bitfire.synctools.mapping.tasks.handler.TitleHandler import at.bitfire.synctools.mapping.tasks.handler.UidHandler import at.bitfire.synctools.storage.tasks.DmfsTask.Companion.UNKNOWN_PROPERTY_DATA @@ -21,8 +26,6 @@ import at.bitfire.synctools.storage.tasks.DmfsTaskList import at.bitfire.synctools.util.AndroidTimeUtils import net.fortuna.ical4j.model.TimeZoneRegistryFactory import net.fortuna.ical4j.model.parameter.RelType -import net.fortuna.ical4j.model.property.Clazz -import net.fortuna.ical4j.model.property.Completed import net.fortuna.ical4j.model.property.DtStart import net.fortuna.ical4j.model.property.Due import net.fortuna.ical4j.model.property.Duration @@ -32,7 +35,6 @@ import net.fortuna.ical4j.model.property.Organizer import net.fortuna.ical4j.model.property.RDate import net.fortuna.ical4j.model.property.RRule import net.fortuna.ical4j.model.property.RelatedTo -import net.fortuna.ical4j.model.property.Status import org.dmfs.tasks.contract.TaskContract.Properties import org.dmfs.tasks.contract.TaskContract.Property.Alarm import org.dmfs.tasks.contract.TaskContract.Property.Category @@ -57,6 +59,11 @@ class DmfsTaskProcessor( UidHandler(), TitleHandler(), SequenceHandler(), + PriorityHandler(), + ClassificationHandler(), + StatusHandler(), + CompletedHandler(), + PercentCompleteHandler(), ) private val propertyHandlers: Map = mapOf( @@ -94,27 +101,8 @@ class DmfsTaskProcessor( } } - values.getAsInteger(Tasks.PRIORITY)?.let { to.priority = it } - // Note: big method – maybe split? Depends on how we want to proceed with refactoring. - to.classification = when (values.getAsInteger(Tasks.CLASSIFICATION)) { - Tasks.CLASSIFICATION_PUBLIC -> Clazz(Clazz.VALUE_PUBLIC) - Tasks.CLASSIFICATION_PRIVATE -> Clazz(Clazz.VALUE_PRIVATE) - Tasks.CLASSIFICATION_CONFIDENTIAL -> Clazz(Clazz.VALUE_CONFIDENTIAL) - else -> null - } - - values.getAsLong(Tasks.COMPLETED)?.let { to.completedAt = Completed(Instant.ofEpochMilli(it)) } - values.getAsInteger(Tasks.PERCENT_COMPLETE)?.let { to.percentComplete = it } - - to.status = when (values.getAsInteger(Tasks.STATUS)) { - Tasks.STATUS_IN_PROCESS -> Status(Status.VALUE_IN_PROCESS) - Tasks.STATUS_COMPLETED -> Status(Status.VALUE_COMPLETED) - Tasks.STATUS_CANCELLED -> Status(Status.VALUE_CANCELLED) - else -> Status(Status.VALUE_NEEDS_ACTION) - } - val allDay = (values.getAsInteger(Tasks.IS_ALLDAY) ?: 0) != 0 val tzID = values.getAsString(Tasks.TZ) diff --git a/lib/src/main/kotlin/at/bitfire/synctools/mapping/tasks/handler/ClassificationHandler.kt b/lib/src/main/kotlin/at/bitfire/synctools/mapping/tasks/handler/ClassificationHandler.kt new file mode 100644 index 00000000..a9c6c720 --- /dev/null +++ b/lib/src/main/kotlin/at/bitfire/synctools/mapping/tasks/handler/ClassificationHandler.kt @@ -0,0 +1,25 @@ +/* + * This file is part of bitfireAT/synctools which is released under GPLv3. + * Copyright © All Contributors. See the LICENSE and AUTHOR files in the root directory for details. + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package at.bitfire.synctools.mapping.tasks.handler + +import android.content.ContentValues +import at.bitfire.ical4android.Task +import net.fortuna.ical4j.model.property.Clazz +import org.dmfs.tasks.contract.TaskContract.Tasks + +class ClassificationHandler : DmfsTaskFieldHandler { + + override fun process(from: ContentValues, to: Task) { + to.classification = when (from.getAsInteger(Tasks.CLASSIFICATION)) { + Tasks.CLASSIFICATION_PUBLIC -> Clazz(Clazz.VALUE_PUBLIC) + Tasks.CLASSIFICATION_PRIVATE -> Clazz(Clazz.VALUE_PRIVATE) + Tasks.CLASSIFICATION_CONFIDENTIAL -> Clazz(Clazz.VALUE_CONFIDENTIAL) + else -> null + } + } + +} diff --git a/lib/src/main/kotlin/at/bitfire/synctools/mapping/tasks/handler/CompletedHandler.kt b/lib/src/main/kotlin/at/bitfire/synctools/mapping/tasks/handler/CompletedHandler.kt new file mode 100644 index 00000000..e7e0e1a4 --- /dev/null +++ b/lib/src/main/kotlin/at/bitfire/synctools/mapping/tasks/handler/CompletedHandler.kt @@ -0,0 +1,23 @@ +/* + * This file is part of bitfireAT/synctools which is released under GPLv3. + * Copyright © All Contributors. See the LICENSE and AUTHOR files in the root directory for details. + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package at.bitfire.synctools.mapping.tasks.handler + +import android.content.ContentValues +import at.bitfire.ical4android.Task +import net.fortuna.ical4j.model.property.Completed +import org.dmfs.tasks.contract.TaskContract.Tasks +import java.time.Instant + +class CompletedHandler : DmfsTaskFieldHandler { + + override fun process(from: ContentValues, to: Task) { + from.getAsLong(Tasks.COMPLETED)?.let { epochMillis -> + to.completedAt = Completed(Instant.ofEpochMilli(epochMillis)) + } + } + +} diff --git a/lib/src/main/kotlin/at/bitfire/synctools/mapping/tasks/handler/PercentCompleteHandler.kt b/lib/src/main/kotlin/at/bitfire/synctools/mapping/tasks/handler/PercentCompleteHandler.kt new file mode 100644 index 00000000..d6b09887 --- /dev/null +++ b/lib/src/main/kotlin/at/bitfire/synctools/mapping/tasks/handler/PercentCompleteHandler.kt @@ -0,0 +1,21 @@ +/* + * This file is part of bitfireAT/synctools which is released under GPLv3. + * Copyright © All Contributors. See the LICENSE and AUTHOR files in the root directory for details. + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package at.bitfire.synctools.mapping.tasks.handler + +import android.content.ContentValues +import at.bitfire.ical4android.Task +import org.dmfs.tasks.contract.TaskContract.Tasks + +class PercentCompleteHandler : DmfsTaskFieldHandler { + + override fun process(from: ContentValues, to: Task) { + from.getAsInteger(Tasks.PERCENT_COMPLETE)?.let { percent -> + to.percentComplete = percent + } + } + +} diff --git a/lib/src/main/kotlin/at/bitfire/synctools/mapping/tasks/handler/PriorityHandler.kt b/lib/src/main/kotlin/at/bitfire/synctools/mapping/tasks/handler/PriorityHandler.kt new file mode 100644 index 00000000..68905cc2 --- /dev/null +++ b/lib/src/main/kotlin/at/bitfire/synctools/mapping/tasks/handler/PriorityHandler.kt @@ -0,0 +1,19 @@ +/* + * This file is part of bitfireAT/synctools which is released under GPLv3. + * Copyright © All Contributors. See the LICENSE and AUTHOR files in the root directory for details. + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package at.bitfire.synctools.mapping.tasks.handler + +import android.content.ContentValues +import at.bitfire.ical4android.Task +import org.dmfs.tasks.contract.TaskContract.Tasks + +class PriorityHandler : DmfsTaskFieldHandler { + + override fun process(from: ContentValues, to: Task) { + from.getAsInteger(Tasks.PRIORITY)?.let { to.priority = it } + } + +} diff --git a/lib/src/main/kotlin/at/bitfire/synctools/mapping/tasks/handler/StatusHandler.kt b/lib/src/main/kotlin/at/bitfire/synctools/mapping/tasks/handler/StatusHandler.kt new file mode 100644 index 00000000..6df65f5e --- /dev/null +++ b/lib/src/main/kotlin/at/bitfire/synctools/mapping/tasks/handler/StatusHandler.kt @@ -0,0 +1,25 @@ +/* + * This file is part of bitfireAT/synctools which is released under GPLv3. + * Copyright © All Contributors. See the LICENSE and AUTHOR files in the root directory for details. + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package at.bitfire.synctools.mapping.tasks.handler + +import android.content.ContentValues +import at.bitfire.ical4android.Task +import net.fortuna.ical4j.model.property.Status +import org.dmfs.tasks.contract.TaskContract.Tasks + +class StatusHandler : DmfsTaskFieldHandler { + + override fun process(from: ContentValues, to: Task) { + to.status = when (from.getAsInteger(Tasks.STATUS)) { + Tasks.STATUS_IN_PROCESS -> Status(Status.VALUE_IN_PROCESS) + Tasks.STATUS_COMPLETED -> Status(Status.VALUE_COMPLETED) + Tasks.STATUS_CANCELLED -> Status(Status.VALUE_CANCELLED) + else -> Status(Status.VALUE_NEEDS_ACTION) + } + } + +} diff --git a/lib/src/test/kotlin/at/bitfire/synctools/mapping/tasks/handler/ClassificationHandlerTest.kt b/lib/src/test/kotlin/at/bitfire/synctools/mapping/tasks/handler/ClassificationHandlerTest.kt new file mode 100644 index 00000000..83fc4f0a --- /dev/null +++ b/lib/src/test/kotlin/at/bitfire/synctools/mapping/tasks/handler/ClassificationHandlerTest.kt @@ -0,0 +1,60 @@ +/* + * This file is part of bitfireAT/synctools which is released under GPLv3. + * Copyright © All Contributors. See the LICENSE and AUTHOR files in the root directory for details. + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package at.bitfire.synctools.mapping.tasks.handler + +import android.content.ContentValues +import androidx.core.content.contentValuesOf +import at.bitfire.ical4android.Task +import net.fortuna.ical4j.model.property.Clazz +import org.dmfs.tasks.contract.TaskContract.Tasks +import org.junit.Assert.assertEquals +import org.junit.Assert.assertNull +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner + +@RunWith(RobolectricTestRunner::class) +class ClassificationHandlerTest { + + private val handler = ClassificationHandler() + + @Test + fun `No CLASSIFICATION`() { + val task = Task() + handler.process(ContentValues(), task) + assertNull(task.classification) + } + + @Test + fun `CLASSIFICATION_PUBLIC maps to CLASS PUBLIC`() { + val task = Task() + handler.process(contentValuesOf(Tasks.CLASSIFICATION to Tasks.CLASSIFICATION_PUBLIC), task) + assertEquals(Clazz(Clazz.VALUE_PUBLIC), task.classification) + } + + @Test + fun `CLASSIFICATION_PRIVATE maps to CLASS PRIVATE`() { + val task = Task() + handler.process(contentValuesOf(Tasks.CLASSIFICATION to Tasks.CLASSIFICATION_PRIVATE), task) + assertEquals(Clazz(Clazz.VALUE_PRIVATE), task.classification) + } + + @Test + fun `CLASSIFICATION_CONFIDENTIAL maps to CLASS CONFIDENTIAL`() { + val task = Task() + handler.process(contentValuesOf(Tasks.CLASSIFICATION to Tasks.CLASSIFICATION_CONFIDENTIAL), task) + assertEquals(Clazz(Clazz.VALUE_CONFIDENTIAL), task.classification) + } + + @Test + fun `Unknown CLASSIFICATION maps to null`() { + val task = Task() + handler.process(contentValuesOf(Tasks.CLASSIFICATION to 99), task) + assertNull(task.classification) + } + +} diff --git a/lib/src/test/kotlin/at/bitfire/synctools/mapping/tasks/handler/CompletedHandlerTest.kt b/lib/src/test/kotlin/at/bitfire/synctools/mapping/tasks/handler/CompletedHandlerTest.kt new file mode 100644 index 00000000..a9dcdfb6 --- /dev/null +++ b/lib/src/test/kotlin/at/bitfire/synctools/mapping/tasks/handler/CompletedHandlerTest.kt @@ -0,0 +1,41 @@ +/* + * This file is part of bitfireAT/synctools which is released under GPLv3. + * Copyright © All Contributors. See the LICENSE and AUTHOR files in the root directory for details. + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package at.bitfire.synctools.mapping.tasks.handler + +import android.content.ContentValues +import androidx.core.content.contentValuesOf +import at.bitfire.ical4android.Task +import net.fortuna.ical4j.model.property.Completed +import org.dmfs.tasks.contract.TaskContract.Tasks +import org.junit.Assert.assertEquals +import org.junit.Assert.assertNull +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import java.time.Instant + +@RunWith(RobolectricTestRunner::class) +class CompletedHandlerTest { + + private val handler = CompletedHandler() + + @Test + fun `No COMPLETED leaves completedAt null`() { + val task = Task() + handler.process(ContentValues(), task) + assertNull(task.completedAt) + } + + @Test + fun `COMPLETED epoch millis is mapped correctly`() { + val task = Task() + val epochMillis = 1_700_000_000_000L + handler.process(contentValuesOf(Tasks.COMPLETED to epochMillis), task) + assertEquals(Completed(Instant.ofEpochMilli(epochMillis)), task.completedAt) + } + +} diff --git a/lib/src/test/kotlin/at/bitfire/synctools/mapping/tasks/handler/PercentCompleteHandlerTest.kt b/lib/src/test/kotlin/at/bitfire/synctools/mapping/tasks/handler/PercentCompleteHandlerTest.kt new file mode 100644 index 00000000..ff7600dd --- /dev/null +++ b/lib/src/test/kotlin/at/bitfire/synctools/mapping/tasks/handler/PercentCompleteHandlerTest.kt @@ -0,0 +1,45 @@ +/* + * This file is part of bitfireAT/synctools which is released under GPLv3. + * Copyright © All Contributors. See the LICENSE and AUTHOR files in the root directory for details. + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package at.bitfire.synctools.mapping.tasks.handler + +import android.content.ContentValues +import androidx.core.content.contentValuesOf +import at.bitfire.ical4android.Task +import org.dmfs.tasks.contract.TaskContract.Tasks +import org.junit.Assert.assertEquals +import org.junit.Assert.assertNull +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner + +@RunWith(RobolectricTestRunner::class) +class PercentCompleteHandlerTest { + + private val handler = PercentCompleteHandler() + + @Test + fun `No PERCENT_COMPLETE leaves percentComplete null`() { + val task = Task() + handler.process(ContentValues(), task) + assertNull(task.percentComplete) + } + + @Test + fun `PERCENT_COMPLETE 0 is mapped correctly`() { + val task = Task() + handler.process(contentValuesOf(Tasks.PERCENT_COMPLETE to 0), task) + assertEquals(0, task.percentComplete) + } + + @Test + fun `PERCENT_COMPLETE 100 is mapped correctly`() { + val task = Task() + handler.process(contentValuesOf(Tasks.PERCENT_COMPLETE to 100), task) + assertEquals(100, task.percentComplete) + } + +} diff --git a/lib/src/test/kotlin/at/bitfire/synctools/mapping/tasks/handler/PriorityHandlerTest.kt b/lib/src/test/kotlin/at/bitfire/synctools/mapping/tasks/handler/PriorityHandlerTest.kt new file mode 100644 index 00000000..d317cfa1 --- /dev/null +++ b/lib/src/test/kotlin/at/bitfire/synctools/mapping/tasks/handler/PriorityHandlerTest.kt @@ -0,0 +1,58 @@ +/* + * This file is part of bitfireAT/synctools which is released under GPLv3. + * Copyright © All Contributors. See the LICENSE and AUTHOR files in the root directory for details. + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package at.bitfire.synctools.mapping.tasks.handler + +import android.content.ContentValues +import androidx.core.content.contentValuesOf +import at.bitfire.ical4android.Task +import org.dmfs.tasks.contract.TaskContract.Tasks +import org.junit.Assert.assertEquals +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner + +@RunWith(RobolectricTestRunner::class) +class PriorityHandlerTest { + + private val handler = PriorityHandler() + + @Test + fun `No PRIORITY leaves priority at default (0)`() { + val task = Task() + handler.process(ContentValues(), task) + assertEquals(0, task.priority) + } + + @Test + fun `PRIORITY is 0 (undefined)`() { + val task = Task() + handler.process(contentValuesOf(Tasks.PRIORITY to 0), task) + assertEquals(0, task.priority) + } + + @Test + fun `PRIORITY is 1 (high)`() { + val task = Task() + handler.process(contentValuesOf(Tasks.PRIORITY to 1), task) + assertEquals(1, task.priority) + } + + @Test + fun `PRIORITY is 5 (medium)`() { + val task = Task() + handler.process(contentValuesOf(Tasks.PRIORITY to 5), task) + assertEquals(5, task.priority) + } + + @Test + fun `PRIORITY is 9 (low)`() { + val task = Task() + handler.process(contentValuesOf(Tasks.PRIORITY to 9), task) + assertEquals(9, task.priority) + } + +} diff --git a/lib/src/test/kotlin/at/bitfire/synctools/mapping/tasks/handler/StatusHandlerTest.kt b/lib/src/test/kotlin/at/bitfire/synctools/mapping/tasks/handler/StatusHandlerTest.kt new file mode 100644 index 00000000..b52eae17 --- /dev/null +++ b/lib/src/test/kotlin/at/bitfire/synctools/mapping/tasks/handler/StatusHandlerTest.kt @@ -0,0 +1,66 @@ +/* + * This file is part of bitfireAT/synctools which is released under GPLv3. + * Copyright © All Contributors. See the LICENSE and AUTHOR files in the root directory for details. + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package at.bitfire.synctools.mapping.tasks.handler + +import android.content.ContentValues +import androidx.core.content.contentValuesOf +import at.bitfire.ical4android.Task +import net.fortuna.ical4j.model.property.Status +import org.dmfs.tasks.contract.TaskContract.Tasks +import org.junit.Assert.assertEquals +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner + +@RunWith(RobolectricTestRunner::class) +class StatusHandlerTest { + + private val handler = StatusHandler() + + @Test + fun `No STATUS defaults to NEEDS-ACTION`() { + val task = Task() + handler.process(ContentValues(), task) + assertEquals(Status(Status.VALUE_NEEDS_ACTION), task.status) + } + + @Test + fun `STATUS_NEEDS_ACTION maps to NEEDS-ACTION`() { + val task = Task() + handler.process(contentValuesOf(Tasks.STATUS to Tasks.STATUS_NEEDS_ACTION), task) + assertEquals(Status(Status.VALUE_NEEDS_ACTION), task.status) + } + + @Test + fun `STATUS_IN_PROCESS maps to IN-PROCESS`() { + val task = Task() + handler.process(contentValuesOf(Tasks.STATUS to Tasks.STATUS_IN_PROCESS), task) + assertEquals(Status(Status.VALUE_IN_PROCESS), task.status) + } + + @Test + fun `STATUS_COMPLETED maps to COMPLETED`() { + val task = Task() + handler.process(contentValuesOf(Tasks.STATUS to Tasks.STATUS_COMPLETED), task) + assertEquals(Status(Status.VALUE_COMPLETED), task.status) + } + + @Test + fun `STATUS_CANCELLED maps to CANCELLED`() { + val task = Task() + handler.process(contentValuesOf(Tasks.STATUS to Tasks.STATUS_CANCELLED), task) + assertEquals(Status(Status.VALUE_CANCELLED), task.status) + } + + @Test + fun `Unknown STATUS defaults to NEEDS-ACTION`() { + val task = Task() + handler.process(contentValuesOf(Tasks.STATUS to 99), task) + assertEquals(Status(Status.VALUE_NEEDS_ACTION), task.status) + } + +}