Repository: ImFlog/schema-registry-plugin
Pull request #115 (2023-01-30 09:54:51)

fix: fix management of embedded local reference
Hello again,

I started testing the new release of the plugin with our use-cases.
And I noticed, their was a case not managed by the the new implementation of local reference.
We have a use case of local reference that have reference to another local reference.
So I made a small change, to iterate through all "FIELD" within a Json object is present.

I update the test, to test this use case. Failed before the modification, it is green now.

@ImFlog let me know what you think of this fix :)!


Patch:
diff --git a/src/main/kotlin/com/github/imflog/schema/registry/parser/AvroSchemaParser.kt b/src/main/kotlin/com/github/imflog/schema/registry/parser/AvroSchemaParser.kt
index f9b83b6..60cf476 100644
--- a/src/main/kotlin/com/github/imflog/schema/registry/parser/AvroSchemaParser.kt
+++ b/src/main/kotlin/com/github/imflog/schema/registry/parser/AvroSchemaParser.kt
@@ -22,30 +22,14 @@ class AvroSchemaParser(
 
     override val schemaType: SchemaType = SchemaType.AVRO
 
+    private val keysToUpdate: Collection<String> = listOf(TYPE, ITEMS, VALUES, FIELDS)
+
     override fun resolveLocalReferences(
         subject: String,
         schemaContent: String,
         localReferences: List<LocalReference>
     ): String {
-        val jsonObj = JSONObject(schemaContent)
-        if (jsonObj.has(FIELDS)) {
-            jsonObj.put(FIELDS,
-                JSONArray(jsonObj
-                    .getJSONArray(FIELDS)
-                    .map { if (it is JSONObject) replaceLocalReference(it, localReferences) else it }
-                )
-            )
-        }
-        return jsonObj.toString()
-    }
-
-    private fun replaceLocalReference(jsonObject: JSONObject, localReferences: List<LocalReference>): JSONObject {
-        when {
-            jsonObject.has(TYPE) -> jsonObject.put(TYPE, replaceType(jsonObject.get(TYPE), localReferences))
-            jsonObject.has(ITEMS) -> jsonObject.put(ITEMS, replaceType(jsonObject.get(ITEMS), localReferences))
-            jsonObject.has(VALUES) -> jsonObject.put(VALUES, replaceType(jsonObject.get(VALUES), localReferences))
-        }
-        return jsonObject
+        return replaceType(JSONObject(schemaContent),localReferences).toString()
     }
 
     private fun replaceType(type: Any, localReferences: List<LocalReference>): Any {
@@ -53,11 +37,16 @@ class AvroSchemaParser(
             is String -> localReferences
                 .filter { it.name == type }
                 .map { JSONObject(it.content(rootDir)) }
-                .map { replaceLocalReference(it, localReferences) }
+                .map { replaceType(it, localReferences) }
                 .firstOrNull() ?: type
 
             is JSONArray -> JSONArray(type.map { replaceType(it, localReferences) })
-            is JSONObject -> replaceLocalReference(type, localReferences)
+            is JSONObject -> {
+                type.keySet()
+                    .filter { keysToUpdate.contains(it) }
+                    .forEach { type.put(it, replaceType(type.get(it), localReferences)) }
+                return type
+            }
             else -> type
         }
     }


Test patch:
diff --git a/src/test/kotlin/com/github/imflog/schema/registry/tasks/compatibility/CompatibilityTaskActionTest.kt b/src/test/kotlin/com/github/imflog/schema/registry/tasks/compatibility/CompatibilityTaskActionTest.kt
index 12e0e0b..66e06ba 100644
--- a/src/test/kotlin/com/github/imflog/schema/registry/tasks/compatibility/CompatibilityTaskActionTest.kt
+++ b/src/test/kotlin/com/github/imflog/schema/registry/tasks/compatibility/CompatibilityTaskActionTest.kt
@@ -198,13 +198,30 @@ class CompatibilityTaskActionTest {
         )
 
         folderRule.newFolder("src", "main", "avro", "local")
+        File(folderRule.root, "src/main/avro/local/country.avsc").writeText(
+            """{
+                    "type": "enum",
+                    "name": "Country",
+                    "symbols": [
+                        "UNKNOWN",
+                        "FR",
+                        "DE",
+                        "UK",
+                        "IT",
+                        "ES",
+                        "US"
+                  ],
+                  "default": "UNKNOWN"
+                }"""
+        )
         File(folderRule.root, "src/main/avro/local/address.avsc").writeText(
             """{
                     "type": "record",
                     "name": "Address",
                     "fields": [
                         {"name": "city", "type": "string" },
-                        {"name": "street", "type": "Street" }
+                        {"name": "street", "type": "Street" },
+                        {"name": "country", "type": "Country" }
                     ]
                 }"""
         )
@@ -228,6 +245,7 @@ class CompatibilityTaskActionTest {
                 SchemaType.AVRO
             )
                 .addReference("Street", "Street", 1)
+                .addLocalReference("Country", "src/main/avro/local/country.avsc")
                 .addLocalReference("Address", "src/main/avro/local/address.avsc")
         )