This is an automated email from the ASF dual-hosted git repository.

wenjun pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/seatunnel.git


The following commit(s) were added to refs/heads/dev by this push:
     new 36754cccfa [Fix] Fix ReadonlyConfig lose key error (#5565)
36754cccfa is described below

commit 36754cccfae569bce45d45cd21208238792d610c
Author: Jia Fan <[email protected]>
AuthorDate: Thu Sep 28 16:52:47 2023 +0800

    [Fix] Fix ReadonlyConfig lose key error (#5565)
---
 .../api/configuration/util/ConfigUtil.java         | 34 +++++++++++++-
 .../api/configuration/util/ConfigUtilTest.java     | 52 ++++++++++++++++++++++
 2 files changed, 84 insertions(+), 2 deletions(-)

diff --git 
a/seatunnel-api/src/main/java/org/apache/seatunnel/api/configuration/util/ConfigUtil.java
 
b/seatunnel-api/src/main/java/org/apache/seatunnel/api/configuration/util/ConfigUtil.java
index a172cddfc0..097d6d10ae 100644
--- 
a/seatunnel-api/src/main/java/org/apache/seatunnel/api/configuration/util/ConfigUtil.java
+++ 
b/seatunnel-api/src/main/java/org/apache/seatunnel/api/configuration/util/ConfigUtil.java
@@ -113,7 +113,7 @@ public class ConfigUtil {
                 } else if (propertiesMap.get(tempPrefix) instanceof String) {
                     loadPropertiesStyleMap(temp).put("", 
propertiesMap.get(tempPrefix));
                 } else {
-                    ((Map) 
propertiesMap.get(tempPrefix)).putAll(loadPropertiesStyleMap(temp));
+                    mergeTwoMap((Map) propertiesMap.get(tempPrefix), 
loadPropertiesStyleMap(temp));
                 }
             } else {
                 propertiesMap.put(tempPrefix, loadPropertiesStyleObject(temp));
@@ -122,6 +122,30 @@ public class ConfigUtil {
         }
     }
 
+    private static void mergeTwoMap(Map<String, Object> base, Map<String, 
Object> merged) {
+        for (Map.Entry<String, Object> entry : merged.entrySet()) {
+            if (base.containsKey(entry.getKey())) {
+                if (base.get(entry.getKey()) instanceof Map && 
entry.getValue() instanceof Map) {
+                    mergeTwoMap((Map) base.get(entry.getKey()), (Map) 
entry.getValue());
+                } else if (base.get(entry.getKey()) instanceof Map) {
+                    ((Map) base.get(entry.getKey())).put("", entry.getValue());
+                } else if (entry.getValue() instanceof Map) {
+                    Map<String, Object> child = new LinkedHashMap<>();
+                    child.put("", base.get(entry.getKey()));
+                    child.putAll((Map) entry.getValue());
+                    base.put(entry.getKey(), child);
+                } else {
+                    throw new IllegalArgumentException(
+                            String.format(
+                                    "Duplicate key '%s' in config file, value 
'%s' and value '%s'",
+                                    entry.getKey(), base.get(entry.getKey()), 
entry.getValue()));
+                }
+            } else {
+                base.put(entry.getKey(), entry.getValue());
+            }
+        }
+    }
+
     private static List<Object> loadPropertiesStyleList(Map<List<String>, 
String> properties) {
         List<Object> propertiesList = new ArrayList<>();
         Map<List<String>, String> temp = new LinkedHashMap<>();
@@ -148,8 +172,14 @@ public class ConfigUtil {
     }
 
     private static Object loadPropertiesStyleObject(Map<List<String>, String> 
properties) {
-        if (properties.containsKey(null)) {
+        if (properties.containsKey(null) && properties.size() == 1) {
             return StringEscapeUtils.unescapeJava(properties.get(null));
+        } else if (properties.containsKey(null)) {
+            if (properties.containsKey(null)) {
+                properties.put(Collections.singletonList(""), 
properties.get(null));
+                properties.remove(null);
+            }
+            return loadPropertiesStyleMap(properties);
         } else if (properties.entrySet().stream().anyMatch(kv -> 
kv.getKey().get(0).equals("1"))) {
             return loadPropertiesStyleList(properties);
         } else {
diff --git 
a/seatunnel-api/src/test/java/org/apache/seatunnel/api/configuration/util/ConfigUtilTest.java
 
b/seatunnel-api/src/test/java/org/apache/seatunnel/api/configuration/util/ConfigUtilTest.java
index a826842412..357bda78b5 100644
--- 
a/seatunnel-api/src/test/java/org/apache/seatunnel/api/configuration/util/ConfigUtilTest.java
+++ 
b/seatunnel-api/src/test/java/org/apache/seatunnel/api/configuration/util/ConfigUtilTest.java
@@ -38,6 +38,7 @@ import java.net.URISyntaxException;
 import java.nio.file.Paths;
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -139,4 +140,55 @@ public class ConfigUtilTest {
         Assertions.assertEquals(
                 ((Map) ((List) value.get("source")).get(0)).get("start_mode"), 
expect);
     }
+
+    @Test
+    public void testSamePrefixDifferentSuffixKey() {
+        Map<String, Object> config = new LinkedHashMap<>();
+        config.put(
+                "fs.s3a.aws.credentials.provider",
+                "org.apache.hadoop.fs.s3a.SimpleAWSCredentialsProvider");
+        config.put("other", "value");
+        config.put("fs.s3a.endpoint", "s3.cn-northwest-1.amazonaws.com.cn");
+        Map<String, Object> result = ConfigUtil.treeMap(config);
+        Map<String, Object> s3aMap =
+                (Map<String, Object>) ((Map<String, Object>) 
result.get("fs")).get("s3a");
+        Assertions.assertTrue(s3aMap.containsKey("aws"));
+        Assertions.assertTrue(s3aMap.containsKey("endpoint"));
+        Assertions.assertEquals(2, s3aMap.size());
+    }
+
+    @Test
+    public void testSamePrefixDifferentValueType() {
+        Map<String, Object> config = new LinkedHashMap<>();
+        config.put("start.mode", "CONSUME_FROM_TIMESTAMP");
+        config.put("other", "value");
+        config.put("start.mode.timestamp", "1667179890315");
+        Map<String, Object> result = ConfigUtil.treeMap(config);
+        Map<String, Object> s3aMap =
+                (Map<String, Object>) ((Map<String, Object>) 
result.get("start")).get("mode");
+        Assertions.assertTrue(s3aMap.containsKey(""));
+        Assertions.assertTrue(s3aMap.containsKey("timestamp"));
+        Assertions.assertEquals(2, s3aMap.size());
+
+        config.clear();
+        config.put("start.mode", "CONSUME_FROM_TIMESTAMP");
+        config.put("start.mode.timestamp", "1667179890315");
+        Map<String, Object> result2 = ConfigUtil.treeMap(config);
+        Map<String, Object> s3aMap2 =
+                (Map<String, Object>) ((Map<String, Object>) 
result2.get("start")).get("mode");
+        Assertions.assertTrue(s3aMap2.containsKey(""));
+        Assertions.assertTrue(s3aMap2.containsKey("timestamp"));
+        Assertions.assertEquals(2, s3aMap2.size());
+
+        config.clear();
+        config.put("start.mode", "CONSUME_FROM_TIMESTAMP");
+        config.put("start.mode.timestamp.test1", "1667179890315");
+        config.put("start.mode.timestamp.test2", "1667179890315");
+        Map<String, Object> result3 = ConfigUtil.treeMap(config);
+        Map<String, Object> s3aMap3 =
+                (Map<String, Object>) ((Map<String, Object>) 
result3.get("start")).get("mode");
+        Assertions.assertTrue(s3aMap3.containsKey(""));
+        Assertions.assertTrue(s3aMap3.containsKey("timestamp"));
+        Assertions.assertEquals(2, s3aMap3.size());
+    }
 }

Reply via email to