Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,18 @@ import android.content.Entity
import at.bitfire.ical4android.Task
import at.bitfire.ical4android.UnknownProperty
import at.bitfire.synctools.mapping.tasks.builder.AllDayBuilder
import at.bitfire.synctools.mapping.tasks.builder.ColorBuilder
import at.bitfire.synctools.mapping.tasks.builder.DescriptionBuilder
import at.bitfire.synctools.mapping.tasks.builder.DmfsTaskFieldBuilder
import at.bitfire.synctools.mapping.tasks.builder.DueBuilder
import at.bitfire.synctools.mapping.tasks.builder.DurationBuilder
import at.bitfire.synctools.mapping.tasks.builder.GeoBuilder
import at.bitfire.synctools.mapping.tasks.builder.LocationBuilder
import at.bitfire.synctools.mapping.tasks.builder.OrganizerBuilder
import at.bitfire.synctools.mapping.tasks.builder.RecurrenceFieldsBuilder
import at.bitfire.synctools.mapping.tasks.builder.StartTimeBuilder
import at.bitfire.synctools.mapping.tasks.builder.TitleBuilder
import at.bitfire.synctools.mapping.tasks.builder.UrlBuilder
import at.bitfire.synctools.storage.BatchOperation.CpoBuilder
import at.bitfire.synctools.storage.tasks.DmfsTask.Companion.COLUMN_ETAG
import at.bitfire.synctools.storage.tasks.DmfsTask.Companion.COLUMN_FLAGS
Expand All @@ -26,7 +32,6 @@ import at.bitfire.synctools.storage.tasks.TasksBatchOperation
import at.bitfire.synctools.util.AlarmTriggerCalculator
import net.fortuna.ical4j.model.Parameter
import net.fortuna.ical4j.model.Property
import net.fortuna.ical4j.model.parameter.Email
import net.fortuna.ical4j.model.parameter.RelType
import net.fortuna.ical4j.model.parameter.Related
import net.fortuna.ical4j.model.property.Action
Expand Down Expand Up @@ -60,6 +65,15 @@ class DmfsTaskBuilder(
) {

private val fieldBuilders: Array<DmfsTaskFieldBuilder> = arrayOf(
// content fields
TitleBuilder(),
DescriptionBuilder(),
LocationBuilder(),
GeoBuilder(),
ColorBuilder(),
UrlBuilder(),
OrganizerBuilder(),
// status fields (still inline below)
// time fields and recurrence
TitleBuilder(),
AllDayBuilder(),
Expand Down Expand Up @@ -104,34 +118,13 @@ class DmfsTaskBuilder(
builder .withValue(Tasks._UID, task.uid)
.withValue(Tasks._DIRTY, 0)
.withValue(Tasks.SYNC_VERSION, task.sequence)
.withValue(Tasks.LOCATION, task.location)
.withValue(Tasks.GEO, task.geoPosition?.let { "${it.longitude},${it.latitude}" })
.withValue(Tasks.DESCRIPTION, task.description)
.withValue(Tasks.TASK_COLOR, task.color)
.withValue(Tasks.URL, task.url)

.withValue(Tasks._SYNC_ID, syncId)
.withValue(COLUMN_FLAGS, flags)
.withValue(COLUMN_ETAG, eTag)

// parent_id will be re-calculated when the relation row is inserted (if there is any)
.withValue(Tasks.PARENT_ID, null)

// organizer
// Note: big method – maybe split? Depends on how we want to proceed with refactoring.

task.organizer?.let { organizer ->
val uri = organizer.calAddress
val email = if (uri.scheme.equals("mailto", true))
uri.schemeSpecificPart
else
organizer.getParameter<Email>(Parameter.EMAIL).getOrNull()?.value
if (email != null)
builder.withValue(Tasks.ORGANIZER, email)
else
logger.warning("Ignoring ORGANIZER without email address (not supported by Android)")
}

// Priority, classification
builder
.withValue(Tasks.PRIORITY, task.priority)
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.builder

import android.content.Entity
import at.bitfire.ical4android.Task
import org.dmfs.tasks.contract.TaskContract.Tasks

class ColorBuilder : DmfsTaskFieldBuilder {

override fun build(from: Task, to: Entity) {
to.entityValues.put(Tasks.TASK_COLOR, from.color)
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* 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.builder

import android.content.Entity
import at.bitfire.ical4android.Task
import at.bitfire.vcard4android.Utils.trimToNull
import org.dmfs.tasks.contract.TaskContract.Tasks

class DescriptionBuilder : DmfsTaskFieldBuilder {

override fun build(from: Task, to: Entity) {
to.entityValues.put(Tasks.DESCRIPTION, from.description.trimToNull())
}

}
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.builder

import android.content.Entity
import at.bitfire.ical4android.Task
import org.dmfs.tasks.contract.TaskContract.Tasks

class GeoBuilder : DmfsTaskFieldBuilder {

override fun build(from: Task, to: Entity) {
to.entityValues.put(Tasks.GEO, from.geoPosition?.let { "${it.longitude},${it.latitude}" })
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* 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.builder

import android.content.Entity
import at.bitfire.ical4android.Task
import at.bitfire.vcard4android.Utils.trimToNull
import org.dmfs.tasks.contract.TaskContract.Tasks

class LocationBuilder : DmfsTaskFieldBuilder {

override fun build(from: Task, to: Entity) {
to.entityValues.put(Tasks.LOCATION, from.location.trimToNull())
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* 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.builder

import android.content.Entity
import at.bitfire.ical4android.Task
import net.fortuna.ical4j.model.Parameter
import net.fortuna.ical4j.model.parameter.Email
import org.dmfs.tasks.contract.TaskContract.Tasks
import java.util.logging.Level
import java.util.logging.Logger
import kotlin.jvm.optionals.getOrNull

class OrganizerBuilder : DmfsTaskFieldBuilder {

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

override fun build(from: Task, to: Entity) {
val organizer = from.organizer
if (organizer == null) {
to.entityValues.putNull(Tasks.ORGANIZER)
return
}

val uri = organizer.calAddress
val email = if (uri.scheme.equals("mailto", true))
uri.schemeSpecificPart
else
organizer.getParameter<Email>(Parameter.EMAIL).getOrNull()?.value

if (email != null)
to.entityValues.put(Tasks.ORGANIZER, email)
else {
logger.log(Level.WARNING, "Ignoring ORGANIZER without email address (not supported by Android)", organizer)
to.entityValues.putNull(Tasks.ORGANIZER)
}
}

}
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.builder

import android.content.Entity
import at.bitfire.ical4android.Task
import org.dmfs.tasks.contract.TaskContract.Tasks

class UrlBuilder : DmfsTaskFieldBuilder {

override fun build(from: Task, to: Entity) {
to.entityValues.put(Tasks.URL, from.url)
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* 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.builder

import android.content.ContentValues
import android.content.Entity
import androidx.core.content.contentValuesOf
import at.bitfire.ical4android.Task
import at.bitfire.synctools.test.assertContentValuesEqual
import org.dmfs.tasks.contract.TaskContract.Tasks
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner

@RunWith(RobolectricTestRunner::class)
class ColorBuilderTest {

private val builder = ColorBuilder()

@Test
fun `No COLOR`() {
val result = Entity(ContentValues())
builder.build(
from = Task(),
to = result
)
assertContentValuesEqual(contentValuesOf(
Tasks.TASK_COLOR to null
), result.entityValues)
}

@Test
fun `COLOR is set`() {
val result = Entity(ContentValues())
builder.build(
from = Task(color = 0xFF112233.toInt()),
to = result
)
assertContentValuesEqual(contentValuesOf(
Tasks.TASK_COLOR to 0xFF112233.toInt()
), result.entityValues)
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* 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.builder

import android.content.ContentValues
import android.content.Entity
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.Assert.assertTrue
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner

@RunWith(RobolectricTestRunner::class)
class DescriptionBuilderTest {

private val builder = DescriptionBuilder()

@Test
fun `No DESCRIPTION`() {
val result = Entity(ContentValues())
builder.build(
from = Task(),
to = result
)
assertTrue(result.entityValues.containsKey(Tasks.DESCRIPTION))
assertNull(result.entityValues.get(Tasks.DESCRIPTION))
}

@Test
fun `DESCRIPTION is blank`() {
val result = Entity(ContentValues())
builder.build(
from = Task(description = ""),
to = result
)
assertTrue(result.entityValues.containsKey(Tasks.DESCRIPTION))
assertNull(result.entityValues.get(Tasks.DESCRIPTION))
}

@Test
fun `DESCRIPTION is text`() {
val result = Entity(ContentValues())
builder.build(
from = Task(description = "Task Details"),
to = result
)
assertEquals("Task Details", result.entityValues.getAsString(Tasks.DESCRIPTION))
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* 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.builder

import android.content.ContentValues
import android.content.Entity
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.Assert.assertTrue
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner

@RunWith(RobolectricTestRunner::class)
class GeoBuilderTest {

private val builder = GeoBuilder()

@Test
fun `No GEO`() {
val result = Entity(ContentValues())
builder.build(
from = Task(),
to = result
)
assertTrue(result.entityValues.containsKey(Tasks.GEO))
assertNull(result.entityValues.get(Tasks.GEO))
}

@Test
fun `GEO is set`() {
val result = Entity(ContentValues())
builder.build(
from = Task(geoPosition = Geo(48.2.toBigDecimal(), 16.3.toBigDecimal())),
to = result
)
assertEquals("16.3,48.2", result.entityValues.getAsString(Tasks.GEO))
}

}
Loading
Loading