Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bugfix/bco#77 review protobuf merge from usage to avoid list entry dublication #83

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 @@ -426,5 +426,41 @@ object ProtoBufBuilderProcessor {
}
}

/**
* This method clears all repeated fields from the given message before the `mergeFrom` is performed.
* This functionality can be useful, since `mergeFrom` would always duplicate all repeated fields
* which can be avoided by using this function instead.
* @param message the message to merge from.
*/
@JvmStatic
fun <MB : Message.Builder> MB.mergeFromWithoutRepeatedFields(builder: Message.Builder): MB =
// we should not modify the passed builder, so we need to transform it into a message first.
mergeFromWithoutRepeatedFields(builder.build())

/**
* This method clears all repeated fields from the given message before the `mergeFrom` is performed.
* This functionality can be useful, since `mergeFrom` would always duplicate all repeated fields
* which can be avoided by using this function instead.
* @param message the message to merge from.
*/
@JvmStatic
fun <MB : Message.Builder> MB.mergeFromWithoutRepeatedFields(message: Message): MB =
message.toBuilder()
.let { messageBuilder -> messageBuilder.clearRepeatedFields() }
.let { messageBuilder -> mergeFrom(messageBuilder.build()) as MB }

/**
* This method recursively clears all repeated fields from the builder instance.
*/
@JvmStatic
fun <MB : Message.Builder> MB.clearRepeatedFields(): MB = also { builder ->
allFields.keys.forEach { descriptor ->
descriptor
.takeIf { it.isRepeated }
?.also {clearField(it) ; return@forEach }
descriptor
.takeIf { it.javaType == Descriptors.FieldDescriptor.JavaType.MESSAGE }
?.also { builder.getFieldBuilder(it).clearRepeatedFields() }
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package org.openbase.jul.extension.protobuf

import io.kotest.matchers.comparables.shouldBeEqualComparingTo
import io.kotest.matchers.ints.shouldBeExactly
import org.junit.jupiter.api.Test

import org.openbase.jul.extension.protobuf.ProtoBufBuilderProcessor.clearRepeatedFields
import org.openbase.jul.extension.protobuf.ProtoBufBuilderProcessor.mergeFromWithoutRepeatedFields
import org.openbase.type.domotic.action.ActionDescriptionType.ActionDescription
import org.openbase.type.language.MultiLanguageTextType.MultiLanguageText

internal class ProtoBufBuilderProcessorTest {

companion object {
private const val DE = "de"
private const val EN = "en"
private const val ES = "es"
private const val EN_DOG = "dog"
private const val DE_DOG = "hund"
private const val ES_DOG = "perro"
}

@Test
fun `should remove repeated fields` () {
ActionDescription.newBuilder().also {
it.descriptionBuilder.addAllEntry(
mutableListOf(
MultiLanguageText.MapFieldEntry.newBuilder().setKey(DE).setValue(DE_DOG).build(),
MultiLanguageText.MapFieldEntry.newBuilder().setKey(EN).setValue(EN_DOG).build(),
MultiLanguageText.MapFieldEntry.newBuilder().setKey(ES).setValue(ES_DOG).build(),
)
).build()
}.clearRepeatedFields().apply {
descriptionBuilder.entryCount shouldBeExactly 0
}
}

@Test
fun `should only merge from non-repeated fields`() {
val originBuilder = ActionDescription.newBuilder().also {
it.descriptionBuilder.addAllEntry(
mutableListOf(
MultiLanguageText.MapFieldEntry.newBuilder().setKey(DE).setValue(DE_DOG).build(),
MultiLanguageText.MapFieldEntry.newBuilder().setKey(EN).setValue(EN_DOG).build(),
)
).build()
}

val builderToMerge = ActionDescription.newBuilder().also {
it.descriptionBuilder.addAllEntry(
mutableListOf(
MultiLanguageText.MapFieldEntry.newBuilder().setKey(ES).setValue(ES_DOG).build(),
)
).build()
}

originBuilder.mergeFromWithoutRepeatedFields(builderToMerge).apply {
descriptionBuilder.entryCount shouldBeExactly 2
descriptionBuilder.entryBuilderList[0].key shouldBeEqualComparingTo DE
descriptionBuilder.entryBuilderList[0].value shouldBeEqualComparingTo DE_DOG
descriptionBuilder.entryBuilderList[1].key shouldBeEqualComparingTo EN
descriptionBuilder.entryBuilderList[1].value shouldBeEqualComparingTo EN_DOG
}
}
}