Skip to content
Open
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,17 @@ 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.ColorHandler
import at.bitfire.synctools.mapping.tasks.handler.DescriptionHandler
import at.bitfire.synctools.mapping.tasks.handler.DmfsTaskFieldHandler
import at.bitfire.synctools.mapping.tasks.handler.DmfsTaskPropertyHandler
import at.bitfire.synctools.mapping.tasks.handler.GeoHandler
import at.bitfire.synctools.mapping.tasks.handler.LocationHandler
import at.bitfire.synctools.mapping.tasks.handler.OrganizerHandler
import at.bitfire.synctools.mapping.tasks.handler.SequenceHandler
import at.bitfire.synctools.mapping.tasks.handler.TitleHandler
import at.bitfire.synctools.mapping.tasks.handler.UidHandler
import at.bitfire.synctools.mapping.tasks.handler.UrlHandler
import at.bitfire.synctools.storage.tasks.DmfsTask.Companion.UNKNOWN_PROPERTY_DATA
import at.bitfire.synctools.storage.tasks.DmfsTaskList
import at.bitfire.synctools.util.AndroidTimeUtils
Expand All @@ -27,8 +33,6 @@ import net.fortuna.ical4j.model.property.DtStart
import net.fortuna.ical4j.model.property.Due
import net.fortuna.ical4j.model.property.Duration
import net.fortuna.ical4j.model.property.ExDate
import net.fortuna.ical4j.model.property.Geo
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
Expand All @@ -39,7 +43,6 @@ import org.dmfs.tasks.contract.TaskContract.Property.Category
import org.dmfs.tasks.contract.TaskContract.Property.Comment
import org.dmfs.tasks.contract.TaskContract.Property.Relation
import org.dmfs.tasks.contract.TaskContract.Tasks
import java.net.URISyntaxException
import java.time.Instant
import java.time.temporal.Temporal
import java.util.logging.Level
Expand All @@ -57,6 +60,12 @@ class DmfsTaskProcessor(
UidHandler(),
TitleHandler(),
SequenceHandler(),
DescriptionHandler(),
LocationHandler(),
GeoHandler(),
ColorHandler(),
UrlHandler(),
OrganizerHandler(),
)

private val propertyHandlers: Map<String, DmfsTaskPropertyHandler> = mapOf(
Expand All @@ -70,30 +79,8 @@ class DmfsTaskProcessor(
for (handler in fieldHandlers)
handler.process(values, to)

to.location = values.getAsString(Tasks.LOCATION)
to.userAgents += taskList.providerName.packageName

values.getAsString(Tasks.GEO)?.takeIf { it.contains(",") }?.let { geo ->
val (lng, lat) = geo.split(',')
try {
to.geoPosition = Geo(lat.toBigDecimal(), lng.toBigDecimal())
} catch (e: NumberFormatException) {
logger.log(Level.WARNING, "Invalid GEO value: $geo", e)
}
}

to.description = values.getAsString(Tasks.DESCRIPTION)
to.color = values.getAsInteger(Tasks.TASK_COLOR)
to.url = values.getAsString(Tasks.URL)

values.getAsString(Tasks.ORGANIZER)?.let {
try {
to.organizer = Organizer("mailto:$it")
} catch(e: URISyntaxException) {
logger.log(Level.WARNING, "Invalid ORGANIZER email", e)
}
}

values.getAsInteger(Tasks.PRIORITY)?.let { to.priority = it }

// Note: big method – maybe split? Depends on how we want to proceed with refactoring.
Expand Down
Original file line number Diff line number Diff line change
@@ -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 ColorHandler : DmfsTaskFieldHandler {

override fun process(from: ContentValues, to: Task) {
to.color = from.getAsInteger(Tasks.TASK_COLOR)
}

}
Original file line number Diff line number Diff line change
@@ -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 DescriptionHandler : DmfsTaskFieldHandler {

override fun process(from: ContentValues, to: Task) {
to.description = from.getAsString(Tasks.DESCRIPTION)
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* 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.Geo
import org.dmfs.tasks.contract.TaskContract.Tasks
import java.util.logging.Level
import java.util.logging.Logger

class GeoHandler : DmfsTaskFieldHandler {

private val logger
get() = Logger.getLogger(javaClass.name)

override fun process(from: ContentValues, to: Task) {
val geo = from.getAsString(Tasks.GEO) ?: return
val commaIdx = geo.indexOf(',')
if (commaIdx < 0) return
val lng = geo.substring(0, commaIdx)
val lat = geo.substring(commaIdx + 1)
try {
to.geoPosition = Geo(lat.toBigDecimal(), lng.toBigDecimal())
} catch (e: NumberFormatException) {
logger.log(Level.WARNING, "Invalid GEO value: $geo", e)
}
}

}
Original file line number Diff line number Diff line change
@@ -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 LocationHandler : DmfsTaskFieldHandler {

override fun process(from: ContentValues, to: Task) {
to.location = from.getAsString(Tasks.LOCATION)
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* 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.Organizer
import org.dmfs.tasks.contract.TaskContract.Tasks
import java.net.URISyntaxException
import java.util.logging.Level
import java.util.logging.Logger

class OrganizerHandler : DmfsTaskFieldHandler {

private val logger
get() = Logger.getLogger(javaClass.name)

override fun process(from: ContentValues, to: Task) {
val email = from.getAsString(Tasks.ORGANIZER) ?: return
try {
to.organizer = Organizer("mailto:$email")
} catch (e: URISyntaxException) {
logger.log(Level.WARNING, "Invalid ORGANIZER email", e)
}
}

}
Original file line number Diff line number Diff line change
@@ -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 UrlHandler : DmfsTaskFieldHandler {

override fun process(from: ContentValues, to: Task) {
to.url = from.getAsString(Tasks.URL)
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* 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 ColorHandlerTest {

private val handler = ColorHandler()

@Test
fun `No COLOR`() {
val task = Task()
handler.process(ContentValues(), task)
assertNull(task.color)
}

@Test
fun `COLOR set`() {
val task = Task()
handler.process(contentValuesOf(Tasks.TASK_COLOR to 0xFF112233.toInt()), task)
assertEquals(0xFF112233.toInt(), task.color)
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* 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 DescriptionHandlerTest {

private val handler = DescriptionHandler()

@Test
fun `No DESCRIPTION`() {
val task = Task()
handler.process(ContentValues(), task)
assertNull(task.description)
}

@Test
fun `DESCRIPTION set`() {
val task = Task()
handler.process(contentValuesOf(Tasks.DESCRIPTION to "Task details"), task)
assertEquals("Task details", task.description)
}

}
Original file line number Diff line number Diff line change
@@ -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.Geo
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 GeoHandlerTest {

private val handler = GeoHandler()

@Test
fun `No GEO`() {
val task = Task()
handler.process(ContentValues(), task)
assertNull(task.geoPosition)
}

@Test
fun `GEO is set`() {
val task = Task()
handler.process(contentValuesOf(Tasks.GEO to "16.3,48.2"), task)
assertEquals(Geo(48.2.toBigDecimal(), 16.3.toBigDecimal()), task.geoPosition)
}

@Test
fun `GEO with trailing comma is ignored`() {
val task = Task()
handler.process(contentValuesOf(Tasks.GEO to "16.3,"), task)
assertNull(task.geoPosition)
}

@Test
fun `GEO without comma is ignored`() {
val task = Task()
handler.process(contentValuesOf(Tasks.GEO to "invalid"), task)
assertNull(task.geoPosition)
}

@Test
fun `GEO with invalid number is ignored`() {
val task = Task()
handler.process(contentValuesOf(Tasks.GEO to "not,a-number"), task)
assertNull(task.geoPosition)
}

}
Loading
Loading