Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/bitfireAT/ical4android.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Lang <72232737+patrickunterwegs@users.noreply.github.com>2022-02-16 17:05:00 +0300
committerGitHub <noreply@github.com>2022-02-16 17:05:00 +0300
commit15b08ca5ada8dd354e5b4625477982fc2e608c2a (patch)
treeb049a9250fc6620988519f741361f410e60f78e6
parent9d57f4c3c454bc0dc2779fa39d61a667a7a383bc (diff)
#16 store uid correctly when creating related to entries (#17)
* Ignore RELATED-TO when entry links to itself Closes #14 * Fixed issue with setting a wrong UID that could cause problematic self-references when uploading to the server again Closes #16 * Fixed test
-rw-r--r--src/androidTest/java/at/bitfire/ical4android/JtxCollectionTest.kt141
-rw-r--r--src/main/java/at/bitfire/ical4android/JtxCollection.kt53
-rw-r--r--src/main/java/at/bitfire/ical4android/JtxICalObject.kt1
3 files changed, 158 insertions, 37 deletions
diff --git a/src/androidTest/java/at/bitfire/ical4android/JtxCollectionTest.kt b/src/androidTest/java/at/bitfire/ical4android/JtxCollectionTest.kt
index 807f1bc..d2fad41 100644
--- a/src/androidTest/java/at/bitfire/ical4android/JtxCollectionTest.kt
+++ b/src/androidTest/java/at/bitfire/ical4android/JtxCollectionTest.kt
@@ -93,6 +93,146 @@ class JtxCollectionTest {
}
@Test
+ fun updateRelatedTo_check_update_of_linkedId_CHILD_to_PARENT_is_present() {
+ JtxCollection.create(testAccount, client, cv)
+ val collections = JtxCollection.find(testAccount, client, context, TestJtxCollection.Factory, null, null)
+
+ // insert 2 icalobjects
+ val parentCV = ContentValues().apply {
+ put(JtxContract.JtxICalObject.SUMMARY, "summary")
+ put(JtxContract.JtxICalObject.COMPONENT, JtxContract.JtxICalObject.Component.VJOURNAL.name)
+ put(JtxContract.JtxICalObject.UID, "AAA")
+ put(JtxContract.JtxICalObject.ICALOBJECT_COLLECTIONID, collections[0].id)
+ }
+ val parentUri = client.insert(JtxContract.JtxICalObject.CONTENT_URI.asSyncAdapter(testAccount), parentCV)
+ val childCV = ContentValues().apply {
+ put(JtxContract.JtxICalObject.SUMMARY, "summary")
+ put(JtxContract.JtxICalObject.COMPONENT, JtxContract.JtxICalObject.Component.VJOURNAL.name)
+ put(JtxContract.JtxICalObject.UID, "BBB")
+ put(JtxContract.JtxICalObject.ICALOBJECT_COLLECTIONID, collections[0].id)
+ }
+ val childUri = client.insert(JtxContract.JtxICalObject.CONTENT_URI.asSyncAdapter(testAccount), childCV)
+
+ val icalobjects = collections[0].queryICalObjects(null, null)
+ assertEquals(2, icalobjects.size)
+
+ // link one of them to the other with PARENT reltype
+ val parentRelCV = ContentValues().apply {
+ put(JtxContract.JtxRelatedto.ICALOBJECT_ID, childUri?.lastPathSegment)
+ put(JtxContract.JtxRelatedto.TEXT, "AAA")
+ put(JtxContract.JtxRelatedto.RELTYPE, JtxContract.JtxRelatedto.Reltype.PARENT.name)
+ }
+ client.insert(JtxContract.JtxRelatedto.CONTENT_URI.asSyncAdapter(testAccount), parentRelCV)
+
+ // update related to and check
+ collections[0].updateRelatedTo()
+
+ // check child to parent
+ client.query(
+ JtxContract.JtxRelatedto.CONTENT_URI.asSyncAdapter(testAccount),
+ arrayOf(JtxContract.JtxRelatedto.ICALOBJECT_ID, JtxContract.JtxRelatedto.LINKEDICALOBJECT_ID, JtxContract.JtxRelatedto.TEXT, JtxContract.JtxRelatedto.RELTYPE),
+ "${JtxContract.JtxRelatedto.ICALOBJECT_ID} = ?",
+ arrayOf(childUri?.lastPathSegment),
+ null
+ ).use {
+ assertNotNull(it)
+ assertEquals(1, it?.count)
+ it?.moveToFirst()
+ assertEquals(childUri?.lastPathSegment?.toLong(), it?.getLong(0)) // ICALOBJECT_ID
+ assertEquals(parentUri?.lastPathSegment?.toLong(), it?.getLong(1)) // LINKEDICALOBJECT_ID
+ assertEquals("AAA", it?.getString(2)) // TEXT (UID)
+ assertEquals(JtxContract.JtxRelatedto.Reltype.PARENT.name, it?.getString(3))
+ }
+
+ // check parent to child
+ client.query(
+ JtxContract.JtxRelatedto.CONTENT_URI.asSyncAdapter(testAccount),
+ arrayOf(JtxContract.JtxRelatedto.ICALOBJECT_ID, JtxContract.JtxRelatedto.LINKEDICALOBJECT_ID, JtxContract.JtxRelatedto.TEXT, JtxContract.JtxRelatedto.RELTYPE),
+ "${JtxContract.JtxRelatedto.ICALOBJECT_ID} = ?",
+ arrayOf(parentUri?.lastPathSegment),
+ null
+ ).use {
+ assertNotNull(it)
+ assertEquals(1, it?.count)
+ it?.moveToFirst()
+ assertEquals(parentUri?.lastPathSegment?.toLong(), it?.getLong(0)) // ICALOBJECT_ID
+ assertEquals(childUri?.lastPathSegment?.toLong(), it?.getLong(1)) // LINKEDICALOBJECT_ID
+ assertEquals("BBB", it?.getString(2)) // TEXT (UID)
+ assertEquals(JtxContract.JtxRelatedto.Reltype.CHILD.name, it?.getString(3))
+ }
+ }
+
+ @Test
+ fun updateRelatedTo_check_update_of_linkedId_PARENT_TO_CHILD_is_present() {
+ JtxCollection.create(testAccount, client, cv)
+ val collections = JtxCollection.find(testAccount, client, context, TestJtxCollection.Factory, null, null)
+
+ // insert 2 icalobjects
+ val parentCV = ContentValues().apply {
+ put(JtxContract.JtxICalObject.SUMMARY, "summary")
+ put(JtxContract.JtxICalObject.COMPONENT, JtxContract.JtxICalObject.Component.VJOURNAL.name)
+ put(JtxContract.JtxICalObject.UID, "AAA")
+ put(JtxContract.JtxICalObject.ICALOBJECT_COLLECTIONID, collections[0].id)
+ }
+ val parentUri = client.insert(JtxContract.JtxICalObject.CONTENT_URI.asSyncAdapter(testAccount), parentCV)
+ val childCV = ContentValues().apply {
+ put(JtxContract.JtxICalObject.SUMMARY, "summary")
+ put(JtxContract.JtxICalObject.COMPONENT, JtxContract.JtxICalObject.Component.VJOURNAL.name)
+ put(JtxContract.JtxICalObject.UID, "BBB")
+ put(JtxContract.JtxICalObject.ICALOBJECT_COLLECTIONID, collections[0].id)
+ }
+ val childUri = client.insert(JtxContract.JtxICalObject.CONTENT_URI.asSyncAdapter(testAccount), childCV)
+
+ val icalobjects = collections[0].queryICalObjects(null, null)
+ assertEquals(2, icalobjects.size)
+
+ // link one of them to the other with PARENT reltype
+ val parent2childRelCV = ContentValues().apply {
+ put(JtxContract.JtxRelatedto.ICALOBJECT_ID, parentUri?.lastPathSegment)
+ put(JtxContract.JtxRelatedto.TEXT, "BBB")
+ put(JtxContract.JtxRelatedto.RELTYPE, JtxContract.JtxRelatedto.Reltype.CHILD.name)
+ }
+ client.insert(JtxContract.JtxRelatedto.CONTENT_URI.asSyncAdapter(testAccount), parent2childRelCV)
+
+ // update related to and check
+ collections[0].updateRelatedTo()
+
+ // check child to parent
+ client.query(
+ JtxContract.JtxRelatedto.CONTENT_URI.asSyncAdapter(testAccount),
+ arrayOf(JtxContract.JtxRelatedto.ICALOBJECT_ID, JtxContract.JtxRelatedto.LINKEDICALOBJECT_ID, JtxContract.JtxRelatedto.TEXT, JtxContract.JtxRelatedto.RELTYPE),
+ "${JtxContract.JtxRelatedto.ICALOBJECT_ID} = ?",
+ arrayOf(parentUri?.lastPathSegment),
+ null
+ ).use {
+ assertNotNull(it)
+ assertEquals(1, it?.count)
+ it?.moveToFirst()
+ assertEquals(parentUri?.lastPathSegment?.toLong(), it?.getLong(0)) // ICALOBJECT_ID
+ assertEquals(childUri?.lastPathSegment?.toLong(), it?.getLong(1)) // LINKEDICALOBJECT_ID
+ assertEquals("BBB", it?.getString(2)) // TEXT (UID)
+ assertEquals(JtxContract.JtxRelatedto.Reltype.CHILD.name, it?.getString(3))
+ }
+
+ // check parent to child
+ client.query(
+ JtxContract.JtxRelatedto.CONTENT_URI.asSyncAdapter(testAccount),
+ arrayOf(JtxContract.JtxRelatedto.ICALOBJECT_ID, JtxContract.JtxRelatedto.LINKEDICALOBJECT_ID, JtxContract.JtxRelatedto.TEXT, JtxContract.JtxRelatedto.RELTYPE),
+ "${JtxContract.JtxRelatedto.ICALOBJECT_ID} = ?",
+ arrayOf(childUri?.lastPathSegment),
+ null
+ ).use {
+ assertNotNull(it)
+ assertEquals(1, it?.count)
+ it?.moveToFirst()
+ assertEquals(childUri?.lastPathSegment?.toLong(), it?.getLong(0)) // ICALOBJECT_ID
+ assertEquals(parentUri?.lastPathSegment?.toLong(), it?.getLong(1)) // LINKEDICALOBJECT_ID
+ assertEquals("AAA", it?.getString(2)) // TEXT (UID)
+ assertEquals(JtxContract.JtxRelatedto.Reltype.PARENT.name, it?.getString(3))
+ }
+ }
+
+ @Test
fun getICSForCollection_test() {
val collectionUri = JtxCollection.create(testAccount, client, cv)
assertNotNull(collectionUri)
@@ -115,7 +255,6 @@ class JtxCollectionTest {
client.insert(JtxContract.JtxICalObject.CONTENT_URI.asSyncAdapter(testAccount), cv2)
val ics = collections[0].getICSForCollection()
-
assertTrue(ics.contains(Regex("BEGIN:VCALENDAR(\\n*|\\r*|\\t*|.*)*END:VCALENDAR")))
assertTrue(ics.contains("PRODID:+//IDN bitfire.at//ical4android"))
assertTrue(ics.contains("SUMMARY:summary"))
diff --git a/src/main/java/at/bitfire/ical4android/JtxCollection.kt b/src/main/java/at/bitfire/ical4android/JtxCollection.kt
index 25277b9..fe7515d 100644
--- a/src/main/java/at/bitfire/ical4android/JtxCollection.kt
+++ b/src/main/java/at/bitfire/ical4android/JtxCollection.kt
@@ -175,18 +175,8 @@ open class JtxCollection<out T: JtxICalObject>(val account: Account,
val idOfthisUid = idOfthisUidCursor.getLong(0)
val updateContentValues = ContentValues()
- updateContentValues.put(
- JtxContract.JtxRelatedto.LINKEDICALOBJECT_ID,
- idOfthisUid
- )
-
- client.update(
- JtxContract.JtxRelatedto.CONTENT_URI.asSyncAdapter(
- account
- ),
- updateContentValues,
- "${JtxContract.JtxRelatedto.TEXT} = ? AND ${JtxContract.JtxRelatedto.LINKEDICALOBJECT_ID} = ?",
- arrayOf(uid2upddate, "0")
+ updateContentValues.put(JtxContract.JtxRelatedto.LINKEDICALOBJECT_ID, idOfthisUid)
+ client.update(JtxContract.JtxRelatedto.CONTENT_URI.asSyncAdapter(account), updateContentValues,"${JtxContract.JtxRelatedto.TEXT} = ? AND ${JtxContract.JtxRelatedto.LINKEDICALOBJECT_ID} = ?", arrayOf(uid2upddate, "0")
)
}
}
@@ -198,27 +188,24 @@ open class JtxCollection<out T: JtxICalObject>(val account: Account,
client.query(JtxContract.JtxRelatedto.CONTENT_URI.asSyncAdapter(account), arrayOf(JtxContract.JtxRelatedto.ICALOBJECT_ID, JtxContract.JtxRelatedto.LINKEDICALOBJECT_ID, JtxContract.JtxRelatedto.RELTYPE), "${JtxContract.JtxRelatedto.RELTYPE} = ?", arrayOf(JtxContract.JtxRelatedto.Reltype.PARENT.name), null).use {
cursorAllLinkedParents ->
while (cursorAllLinkedParents?.moveToNext() == true) {
- val icalObjectId = cursorAllLinkedParents.getString(0)
- val linkedIcalObjectId = cursorAllLinkedParents.getString(1)
+ val childId = cursorAllLinkedParents.getString(0)
+ val parentId = cursorAllLinkedParents.getString(1)
- client.query(JtxContract.JtxRelatedto.CONTENT_URI.asSyncAdapter(account), arrayOf(JtxContract.JtxRelatedto.ICALOBJECT_ID, JtxContract.JtxRelatedto.LINKEDICALOBJECT_ID, JtxContract.JtxRelatedto.RELTYPE), "${JtxContract.JtxRelatedto.ICALOBJECT_ID} = ? AND ${JtxContract.JtxRelatedto.LINKEDICALOBJECT_ID} = ? AND ${JtxContract.JtxRelatedto.RELTYPE} = ?", arrayOf(linkedIcalObjectId.toString(), icalObjectId.toString(), JtxContract.JtxRelatedto.Reltype.CHILD.name), null).use { cursor ->
+ client.query(JtxContract.JtxRelatedto.CONTENT_URI.asSyncAdapter(account), arrayOf(JtxContract.JtxRelatedto.ICALOBJECT_ID, JtxContract.JtxRelatedto.LINKEDICALOBJECT_ID, JtxContract.JtxRelatedto.RELTYPE), "${JtxContract.JtxRelatedto.ICALOBJECT_ID} = ? AND ${JtxContract.JtxRelatedto.LINKEDICALOBJECT_ID} = ? AND ${JtxContract.JtxRelatedto.RELTYPE} = ?", arrayOf(parentId.toString(), childId.toString(), JtxContract.JtxRelatedto.Reltype.CHILD.name), null).use { cursor ->
// if the query does not bring any result, then we insert the opposite relationship
if (cursor?.moveToFirst() == false) {
-
//get the UID of the linked entry
- client.query(JtxContract.JtxICalObject.CONTENT_URI.asSyncAdapter(account), arrayOf(JtxContract.JtxICalObject.UID), "${JtxContract.JtxICalObject.ID} = ?", arrayOf(linkedIcalObjectId.toString()), null).use {
+ client.query(JtxContract.JtxICalObject.CONTENT_URI.asSyncAdapter(account), arrayOf(JtxContract.JtxICalObject.UID), "${JtxContract.JtxICalObject.ID} = ?", arrayOf(childId.toString()), null).use {
foundIcalObjectCursor ->
if (foundIcalObjectCursor?.moveToFirst() == true) {
- val uid = foundIcalObjectCursor.getString(0)
-
+ val childUID = foundIcalObjectCursor.getString(0)
val cv = ContentValues().apply {
- put(JtxContract.JtxRelatedto.ICALOBJECT_ID, linkedIcalObjectId)
- put(JtxContract.JtxRelatedto.LINKEDICALOBJECT_ID, icalObjectId)
+ put(JtxContract.JtxRelatedto.ICALOBJECT_ID, parentId)
+ put(JtxContract.JtxRelatedto.LINKEDICALOBJECT_ID, childId)
put(JtxContract.JtxRelatedto.RELTYPE, JtxContract.JtxRelatedto.Reltype.CHILD.name)
- put(JtxContract.JtxRelatedto.TEXT, uid)
+ put(JtxContract.JtxRelatedto.TEXT, childUID)
}
-
client.insert(JtxContract.JtxRelatedto.CONTENT_URI.asSyncAdapter(account), cv)
}
}
@@ -233,30 +220,27 @@ open class JtxCollection<out T: JtxICalObject>(val account: Account,
cursorAllLinkedParents ->
while (cursorAllLinkedParents?.moveToNext() == true) {
- val icalObjectId = cursorAllLinkedParents.getLong(0)
- val linkedIcalObjectId = cursorAllLinkedParents.getLong(1)
+ val parentId = cursorAllLinkedParents.getLong(0)
+ val childId = cursorAllLinkedParents.getLong(1)
- client.query(JtxContract.JtxRelatedto.CONTENT_URI.asSyncAdapter(account), arrayOf(JtxContract.JtxRelatedto.ICALOBJECT_ID, JtxContract.JtxRelatedto.LINKEDICALOBJECT_ID, JtxContract.JtxRelatedto.RELTYPE), "${JtxContract.JtxRelatedto.ICALOBJECT_ID} = ? AND ${JtxContract.JtxRelatedto.LINKEDICALOBJECT_ID} = ? AND ${JtxContract.JtxRelatedto.RELTYPE} = ?", arrayOf(linkedIcalObjectId.toString(), icalObjectId.toString(), JtxContract.JtxRelatedto.Reltype.PARENT.name), null).use {
+ client.query(JtxContract.JtxRelatedto.CONTENT_URI.asSyncAdapter(account), arrayOf(JtxContract.JtxRelatedto.ICALOBJECT_ID, JtxContract.JtxRelatedto.LINKEDICALOBJECT_ID, JtxContract.JtxRelatedto.RELTYPE), "${JtxContract.JtxRelatedto.ICALOBJECT_ID} = ? AND ${JtxContract.JtxRelatedto.LINKEDICALOBJECT_ID} = ? AND ${JtxContract.JtxRelatedto.RELTYPE} = ?", arrayOf(childId.toString(), parentId.toString(), JtxContract.JtxRelatedto.Reltype.PARENT.name), null).use {
cursor ->
// if the query does not bring any result, then we insert the opposite relationship
if (cursor?.moveToFirst() == false) {
//get the UID of the linked entry
- client.query(JtxContract.JtxICalObject.CONTENT_URI.asSyncAdapter(account), arrayOf(JtxContract.JtxICalObject.UID), "${JtxContract.JtxICalObject.ID} = ?", arrayOf(linkedIcalObjectId.toString()), null).use {
+ client.query(JtxContract.JtxICalObject.CONTENT_URI.asSyncAdapter(account), arrayOf(JtxContract.JtxICalObject.UID), "${JtxContract.JtxICalObject.ID} = ?", arrayOf(parentId.toString()), null).use {
foundIcalObjectCursor ->
if(foundIcalObjectCursor?.moveToFirst() == true) {
-
- val uid = foundIcalObjectCursor.getString(0)
-
+ val parentUID = foundIcalObjectCursor.getString(0)
val cv = ContentValues().apply {
- put(JtxContract.JtxRelatedto.ICALOBJECT_ID, linkedIcalObjectId)
- put(JtxContract.JtxRelatedto.LINKEDICALOBJECT_ID, icalObjectId)
+ put(JtxContract.JtxRelatedto.ICALOBJECT_ID, childId)
+ put(JtxContract.JtxRelatedto.LINKEDICALOBJECT_ID, parentId)
put(JtxContract.JtxRelatedto.RELTYPE, JtxContract.JtxRelatedto.Reltype.PARENT.name)
- put(JtxContract.JtxRelatedto.TEXT, uid)
+ put(JtxContract.JtxRelatedto.TEXT, parentUID)
}
-
client.insert(JtxContract.JtxRelatedto.CONTENT_URI.asSyncAdapter(account), cv)
}
}
@@ -266,7 +250,6 @@ open class JtxCollection<out T: JtxICalObject>(val account: Account,
}
}
-
/**
* @return a string with all JtxICalObjects within the collection as iCalendar
*/
diff --git a/src/main/java/at/bitfire/ical4android/JtxICalObject.kt b/src/main/java/at/bitfire/ical4android/JtxICalObject.kt
index 087ca00..054fde1 100644
--- a/src/main/java/at/bitfire/ical4android/JtxICalObject.kt
+++ b/src/main/java/at/bitfire/ical4android/JtxICalObject.kt
@@ -1209,7 +1209,6 @@ duration?.let(props::add)
)
}
-
this.relatedTo.forEach { related ->
val relatedToContentValues = ContentValues().apply {
put(JtxContract.JtxRelatedto.ICALOBJECT_ID, id)