Skip to content
This repository was archived by the owner on May 26, 2026. It is now read-only.

Commit 8c2df1f

Browse files
authored
Extract sync/identity field builders from DmfsTaskBuilder (#358)
* Extract sync/identity field builders from DmfsTaskBuilder Extract UidBuilder, SyncIdBuilder, ETagBuilder, SyncFlagsBuilder, SequenceBuilder, and DirtyBuilder from the inline code in DmfsTaskBuilder.buildTask(). Each builder is added to fieldBuilders and the corresponding withValue() calls are removed from DmfsTaskBuilder. # Conflicts: # lib/src/main/kotlin/at/bitfire/synctools/mapping/tasks/DmfsTaskBuilder.kt # Conflicts: # lib/src/main/kotlin/at/bitfire/synctools/mapping/tasks/DmfsTaskBuilder.kt * Rename DirtyAndDeletedBuilder to DirtyBuilder
1 parent 6b61523 commit 8c2df1f

13 files changed

Lines changed: 407 additions & 11 deletions

File tree

lib/src/main/kotlin/at/bitfire/synctools/mapping/tasks/DmfsTaskBuilder.kt

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,23 @@ import at.bitfire.ical4android.UnknownProperty
1313
import at.bitfire.synctools.mapping.tasks.builder.AllDayBuilder
1414
import at.bitfire.synctools.mapping.tasks.builder.ColorBuilder
1515
import at.bitfire.synctools.mapping.tasks.builder.DescriptionBuilder
16+
import at.bitfire.synctools.mapping.tasks.builder.DirtyBuilder
1617
import at.bitfire.synctools.mapping.tasks.builder.DmfsTaskFieldBuilder
1718
import at.bitfire.synctools.mapping.tasks.builder.DueBuilder
1819
import at.bitfire.synctools.mapping.tasks.builder.DurationBuilder
20+
import at.bitfire.synctools.mapping.tasks.builder.ETagBuilder
1921
import at.bitfire.synctools.mapping.tasks.builder.GeoBuilder
2022
import at.bitfire.synctools.mapping.tasks.builder.LocationBuilder
2123
import at.bitfire.synctools.mapping.tasks.builder.OrganizerBuilder
2224
import at.bitfire.synctools.mapping.tasks.builder.RecurrenceFieldsBuilder
25+
import at.bitfire.synctools.mapping.tasks.builder.SequenceBuilder
2326
import at.bitfire.synctools.mapping.tasks.builder.StartTimeBuilder
27+
import at.bitfire.synctools.mapping.tasks.builder.SyncFlagsBuilder
28+
import at.bitfire.synctools.mapping.tasks.builder.SyncIdBuilder
2429
import at.bitfire.synctools.mapping.tasks.builder.TitleBuilder
30+
import at.bitfire.synctools.mapping.tasks.builder.UidBuilder
2531
import at.bitfire.synctools.mapping.tasks.builder.UrlBuilder
2632
import at.bitfire.synctools.storage.BatchOperation.CpoBuilder
27-
import at.bitfire.synctools.storage.tasks.DmfsTask.Companion.COLUMN_ETAG
28-
import at.bitfire.synctools.storage.tasks.DmfsTask.Companion.COLUMN_FLAGS
2933
import at.bitfire.synctools.storage.tasks.DmfsTask.Companion.UNKNOWN_PROPERTY_DATA
3034
import at.bitfire.synctools.storage.tasks.DmfsTaskList
3135
import at.bitfire.synctools.storage.tasks.TasksBatchOperation
@@ -65,6 +69,13 @@ class DmfsTaskBuilder(
6569
) {
6670

6771
private val fieldBuilders: Array<DmfsTaskFieldBuilder> = arrayOf(
72+
// main task row fields
73+
UidBuilder(),
74+
SyncIdBuilder(syncId),
75+
ETagBuilder(eTag),
76+
SyncFlagsBuilder(flags),
77+
SequenceBuilder(),
78+
DirtyBuilder(),
6879
// content fields
6980
TitleBuilder(),
7081
DescriptionBuilder(),
@@ -73,14 +84,13 @@ class DmfsTaskBuilder(
7384
ColorBuilder(),
7485
UrlBuilder(),
7586
OrganizerBuilder(),
76-
// status fields (still inline below)
7787
// time fields and recurrence
78-
TitleBuilder(),
7988
AllDayBuilder(),
8089
StartTimeBuilder(),
8190
DueBuilder(),
8291
DurationBuilder(),
8392
RecurrenceFieldsBuilder(),
93+
// status (still inline below)
8494
// property sub-rows (still inline below via insertProperties)
8595
)
8696

@@ -115,13 +125,6 @@ class DmfsTaskBuilder(
115125

116126
// old builders
117127

118-
builder .withValue(Tasks._UID, task.uid)
119-
.withValue(Tasks._DIRTY, 0)
120-
.withValue(Tasks.SYNC_VERSION, task.sequence)
121-
.withValue(Tasks._SYNC_ID, syncId)
122-
.withValue(COLUMN_FLAGS, flags)
123-
.withValue(COLUMN_ETAG, eTag)
124-
125128
// parent_id will be re-calculated when the relation row is inserted (if there is any)
126129
.withValue(Tasks.PARENT_ID, null)
127130

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
* This file is part of bitfireAT/synctools which is released under GPLv3.
3+
* Copyright © All Contributors. See the LICENSE and AUTHOR files in the root directory for details.
4+
* SPDX-License-Identifier: GPL-3.0-or-later
5+
*/
6+
7+
package at.bitfire.synctools.mapping.tasks.builder
8+
9+
import android.content.Entity
10+
import at.bitfire.ical4android.Task
11+
import org.dmfs.tasks.contract.TaskContract.Tasks
12+
13+
class DirtyBuilder : DmfsTaskFieldBuilder {
14+
15+
override fun build(from: Task, to: Entity) {
16+
// DIRTY is always unset when we create or update a task row
17+
to.entityValues.put(Tasks._DIRTY, 0)
18+
}
19+
20+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
* This file is part of bitfireAT/synctools which is released under GPLv3.
3+
* Copyright © All Contributors. See the LICENSE and AUTHOR files in the root directory for details.
4+
* SPDX-License-Identifier: GPL-3.0-or-later
5+
*/
6+
7+
package at.bitfire.synctools.mapping.tasks.builder
8+
9+
import android.content.Entity
10+
import at.bitfire.ical4android.Task
11+
import at.bitfire.synctools.storage.tasks.DmfsTask.Companion.COLUMN_ETAG
12+
13+
class ETagBuilder(
14+
private val eTag: String?
15+
) : DmfsTaskFieldBuilder {
16+
17+
override fun build(from: Task, to: Entity) {
18+
to.entityValues.put(COLUMN_ETAG, eTag)
19+
}
20+
21+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
* This file is part of bitfireAT/synctools which is released under GPLv3.
3+
* Copyright © All Contributors. See the LICENSE and AUTHOR files in the root directory for details.
4+
* SPDX-License-Identifier: GPL-3.0-or-later
5+
*/
6+
7+
package at.bitfire.synctools.mapping.tasks.builder
8+
9+
import android.content.Entity
10+
import at.bitfire.ical4android.Task
11+
import org.dmfs.tasks.contract.TaskContract.Tasks
12+
13+
class SequenceBuilder : DmfsTaskFieldBuilder {
14+
15+
override fun build(from: Task, to: Entity) {
16+
/* When we build the SYNC_VERSION column from a real task, we set the sequence to 0 (not null), so that we
17+
can distinguish it from tasks which have been created locally and have never been uploaded yet. */
18+
to.entityValues.put(Tasks.SYNC_VERSION, from.sequence ?: 0)
19+
}
20+
21+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
* This file is part of bitfireAT/synctools which is released under GPLv3.
3+
* Copyright © All Contributors. See the LICENSE and AUTHOR files in the root directory for details.
4+
* SPDX-License-Identifier: GPL-3.0-or-later
5+
*/
6+
7+
package at.bitfire.synctools.mapping.tasks.builder
8+
9+
import android.content.Entity
10+
import at.bitfire.ical4android.Task
11+
import at.bitfire.synctools.storage.tasks.DmfsTask.Companion.COLUMN_FLAGS
12+
13+
class SyncFlagsBuilder(
14+
private val flags: Int
15+
) : DmfsTaskFieldBuilder {
16+
17+
override fun build(from: Task, to: Entity) {
18+
to.entityValues.put(COLUMN_FLAGS, flags)
19+
}
20+
21+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
* This file is part of bitfireAT/synctools which is released under GPLv3.
3+
* Copyright © All Contributors. See the LICENSE and AUTHOR files in the root directory for details.
4+
* SPDX-License-Identifier: GPL-3.0-or-later
5+
*/
6+
7+
package at.bitfire.synctools.mapping.tasks.builder
8+
9+
import android.content.Entity
10+
import at.bitfire.ical4android.Task
11+
import org.dmfs.tasks.contract.TaskContract.Tasks
12+
13+
class SyncIdBuilder(
14+
private val syncId: String?
15+
) : DmfsTaskFieldBuilder {
16+
17+
override fun build(from: Task, to: Entity) {
18+
to.entityValues.put(Tasks._SYNC_ID, syncId)
19+
}
20+
21+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*
2+
* This file is part of bitfireAT/synctools which is released under GPLv3.
3+
* Copyright © All Contributors. See the LICENSE and AUTHOR files in the root directory for details.
4+
* SPDX-License-Identifier: GPL-3.0-or-later
5+
*/
6+
7+
package at.bitfire.synctools.mapping.tasks.builder
8+
9+
import android.content.Entity
10+
import at.bitfire.ical4android.Task
11+
import org.dmfs.tasks.contract.TaskContract.Tasks
12+
13+
class UidBuilder : DmfsTaskFieldBuilder {
14+
15+
override fun build(from: Task, to: Entity) {
16+
to.entityValues.put(Tasks._UID, from.uid)
17+
}
18+
19+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* This file is part of bitfireAT/synctools which is released under GPLv3.
3+
* Copyright © All Contributors. See the LICENSE and AUTHOR files in the root directory for details.
4+
* SPDX-License-Identifier: GPL-3.0-or-later
5+
*/
6+
7+
package at.bitfire.synctools.mapping.tasks.builder
8+
9+
import android.content.ContentValues
10+
import android.content.Entity
11+
import androidx.core.content.contentValuesOf
12+
import at.bitfire.ical4android.Task
13+
import at.bitfire.synctools.test.assertContentValuesEqual
14+
import org.dmfs.tasks.contract.TaskContract.Tasks
15+
import org.junit.Test
16+
import org.junit.runner.RunWith
17+
import org.robolectric.RobolectricTestRunner
18+
19+
@RunWith(RobolectricTestRunner::class)
20+
class DirtyBuilderTest {
21+
22+
private val builder = DirtyBuilder()
23+
24+
@Test
25+
fun `DIRTY is set to 0`() {
26+
val result = Entity(ContentValues())
27+
builder.build(
28+
from = Task(),
29+
to = result
30+
)
31+
assertContentValuesEqual(contentValuesOf(
32+
Tasks._DIRTY to 0
33+
), result.entityValues)
34+
}
35+
36+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* This file is part of bitfireAT/synctools which is released under GPLv3.
3+
* Copyright © All Contributors. See the LICENSE and AUTHOR files in the root directory for details.
4+
* SPDX-License-Identifier: GPL-3.0-or-later
5+
*/
6+
7+
package at.bitfire.synctools.mapping.tasks.builder
8+
9+
import android.content.ContentValues
10+
import android.content.Entity
11+
import androidx.core.content.contentValuesOf
12+
import at.bitfire.ical4android.Task
13+
import at.bitfire.synctools.storage.tasks.DmfsTask.Companion.COLUMN_ETAG
14+
import at.bitfire.synctools.test.assertContentValuesEqual
15+
import org.junit.Test
16+
import org.junit.runner.RunWith
17+
import org.robolectric.RobolectricTestRunner
18+
19+
@RunWith(RobolectricTestRunner::class)
20+
class ETagBuilderTest {
21+
22+
@Test
23+
fun `ETag is set`() {
24+
val result = Entity(ContentValues())
25+
ETagBuilder(eTag = "some-etag").build(
26+
from = Task(),
27+
to = result
28+
)
29+
assertContentValuesEqual(contentValuesOf(
30+
COLUMN_ETAG to "some-etag"
31+
), result.entityValues)
32+
}
33+
34+
@Test
35+
fun `ETag is null`() {
36+
val result = Entity(ContentValues())
37+
ETagBuilder(eTag = null).build(
38+
from = Task(),
39+
to = result
40+
)
41+
assertContentValuesEqual(contentValuesOf(
42+
COLUMN_ETAG to null
43+
), result.entityValues)
44+
}
45+
46+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
* This file is part of bitfireAT/synctools which is released under GPLv3.
3+
* Copyright © All Contributors. See the LICENSE and AUTHOR files in the root directory for details.
4+
* SPDX-License-Identifier: GPL-3.0-or-later
5+
*/
6+
7+
package at.bitfire.synctools.mapping.tasks.builder
8+
9+
import android.content.ContentValues
10+
import android.content.Entity
11+
import androidx.core.content.contentValuesOf
12+
import at.bitfire.ical4android.Task
13+
import at.bitfire.synctools.test.assertContentValuesEqual
14+
import org.dmfs.tasks.contract.TaskContract.Tasks
15+
import org.junit.Test
16+
import org.junit.runner.RunWith
17+
import org.robolectric.RobolectricTestRunner
18+
19+
@RunWith(RobolectricTestRunner::class)
20+
class SequenceBuilderTest {
21+
22+
private val builder = SequenceBuilder()
23+
24+
@Test
25+
fun `No SEQUENCE defaults to 0`() {
26+
val result = Entity(ContentValues())
27+
builder.build(
28+
from = Task(),
29+
to = result
30+
)
31+
assertContentValuesEqual(contentValuesOf(
32+
Tasks.SYNC_VERSION to 0
33+
), result.entityValues)
34+
}
35+
36+
@Test
37+
fun `SEQUENCE is 0`() {
38+
val result = Entity(ContentValues())
39+
builder.build(
40+
from = Task().also { it.sequence = 0 },
41+
to = result
42+
)
43+
assertContentValuesEqual(contentValuesOf(
44+
Tasks.SYNC_VERSION to 0
45+
), result.entityValues)
46+
}
47+
48+
@Test
49+
fun `SEQUENCE is 1`() {
50+
val result = Entity(ContentValues())
51+
builder.build(
52+
from = Task().also { it.sequence = 1 },
53+
to = result
54+
)
55+
assertContentValuesEqual(contentValuesOf(
56+
Tasks.SYNC_VERSION to 1
57+
), result.entityValues)
58+
}
59+
60+
}

0 commit comments

Comments
 (0)