public static String[] splitByFirstLevel(String str, char splitter) {
        int level = 0;
        int start = 0;
        List<String> list = new LinkedList<>();
        char[] cStr = str.toCharArray();
        for (int i = 0; i < cStr.length; i++) {
            char c = cStr[i];
            if (c == '<' || c == '(') {
                level++;
            } else if (c == '>' || c == ')') {
                level--;
            } else if (c == splitter && level == 0) {
                list.add(str.substring(start, i).trim());
                start = i + 1;
            }
        }

        if (start < cStr.length) {
            list.add(str.substring(start, cStr.length).trim());
        }
        return list.toArray(new String[] {});
    }
@Test
    public void testSplitByFirstLevel() {
        // Test for struct
        String str = "a: int, b: struct<a: int, b: double>";
        String[] result = ColumnTypeConverter.splitByFirstLevel(str, ',');
        String[] expected = new String[] {"a: int", "b: struct<a: int, b: double>"};
        Assert.assertArrayEquals(result, expected);

        // Test for map
        str = "int, struct<a:int,b:double>";
        result = ColumnTypeConverter.splitByFirstLevel(str, ',');
        expected = new String[] {"int", "struct<a:int,b:double>"};
        Assert.assertArrayEquals(result, expected);

        str = "b: struct<a: int, b: double>";
        result = ColumnTypeConverter.splitByFirstLevel(str, ':');
        expected = new String[] {"b", "struct<a: int, b: double>"};
        Assert.assertArrayEquals(result, expected);
    }