diff --git a/avro-builder/tests/codegen-110/src/main/avro/vs110/TestCollections.avsc b/avro-builder/tests/codegen-110/src/main/avro/vs110/TestCollections.avsc index 6e3b6f58..a47652f9 100644 --- a/avro-builder/tests/codegen-110/src/main/avro/vs110/TestCollections.avsc +++ b/avro-builder/tests/codegen-110/src/main/avro/vs110/TestCollections.avsc @@ -78,6 +78,16 @@ "type": "array", "items": "int" } + }, + { + "name": "unionOfIntMap", + "type": [ + "null", + { + "type": "map", + "values": "int" + } + ] } ], "type": "record" diff --git a/avro-builder/tests/codegen-111/src/main/avro/vs111/TestCollections.avsc b/avro-builder/tests/codegen-111/src/main/avro/vs111/TestCollections.avsc index ebbb6de3..31d8bf28 100644 --- a/avro-builder/tests/codegen-111/src/main/avro/vs111/TestCollections.avsc +++ b/avro-builder/tests/codegen-111/src/main/avro/vs111/TestCollections.avsc @@ -79,6 +79,16 @@ "type": "array", "items": "int" } + }, + { + "name": "unionOfIntMap", + "type": [ + "null", + { + "type": "map", + "values": "int" + } + ] } ], "type": "record" diff --git a/avro-builder/tests/codegen-14/src/main/avro/vs14/TestCollections.avsc b/avro-builder/tests/codegen-14/src/main/avro/vs14/TestCollections.avsc index c8cb8cbe..bb529c94 100644 --- a/avro-builder/tests/codegen-14/src/main/avro/vs14/TestCollections.avsc +++ b/avro-builder/tests/codegen-14/src/main/avro/vs14/TestCollections.avsc @@ -79,6 +79,16 @@ "type": "array", "items": "int" } + }, + { + "name": "unionOfIntMap", + "type": [ + "null", + { + "type": "map", + "values": "int" + } + ] } ], "type": "record" diff --git a/avro-builder/tests/codegen-15/src/main/avro/vs15/TestCollections.avsc b/avro-builder/tests/codegen-15/src/main/avro/vs15/TestCollections.avsc index e4d4fe3a..5e79b217 100644 --- a/avro-builder/tests/codegen-15/src/main/avro/vs15/TestCollections.avsc +++ b/avro-builder/tests/codegen-15/src/main/avro/vs15/TestCollections.avsc @@ -79,6 +79,16 @@ "type": "array", "items": "int" } + }, + { + "name": "unionOfIntMap", + "type": [ + "null", + { + "type": "map", + "values": "int" + } + ] } ], "type": "record" diff --git a/avro-builder/tests/codegen-16/src/main/avro/vs16/TestCollections.avsc b/avro-builder/tests/codegen-16/src/main/avro/vs16/TestCollections.avsc index 3e5832ad..a79e1144 100644 --- a/avro-builder/tests/codegen-16/src/main/avro/vs16/TestCollections.avsc +++ b/avro-builder/tests/codegen-16/src/main/avro/vs16/TestCollections.avsc @@ -79,6 +79,16 @@ "type": "array", "items": "int" } + }, + { + "name": "unionOfIntMap", + "type": [ + "null", + { + "type": "map", + "values": "int" + } + ] } ], "type": "record" diff --git a/avro-builder/tests/codegen-17/src/main/avro/vs17/TestCollections.avsc b/avro-builder/tests/codegen-17/src/main/avro/vs17/TestCollections.avsc index ac9430f1..717c97dd 100644 --- a/avro-builder/tests/codegen-17/src/main/avro/vs17/TestCollections.avsc +++ b/avro-builder/tests/codegen-17/src/main/avro/vs17/TestCollections.avsc @@ -79,6 +79,16 @@ "type": "array", "items": "int" } + }, + { + "name": "unionOfIntMap", + "type": [ + "null", + { + "type": "map", + "values": "int" + } + ] } ], "type": "record" diff --git a/avro-builder/tests/codegen-18/src/main/avro/vs18/TestCollections.avsc b/avro-builder/tests/codegen-18/src/main/avro/vs18/TestCollections.avsc index 42fa056f..3fbbd583 100644 --- a/avro-builder/tests/codegen-18/src/main/avro/vs18/TestCollections.avsc +++ b/avro-builder/tests/codegen-18/src/main/avro/vs18/TestCollections.avsc @@ -79,6 +79,16 @@ "type": "array", "items": "int" } + }, + { + "name": "unionOfIntMap", + "type": [ + "null", + { + "type": "map", + "values": "int" + } + ] } ], "type": "record" diff --git a/avro-builder/tests/codegen-19/src/main/avro/vs19/TestCollections.avsc b/avro-builder/tests/codegen-19/src/main/avro/vs19/TestCollections.avsc index 2651f92e..7c9f39d0 100644 --- a/avro-builder/tests/codegen-19/src/main/avro/vs19/TestCollections.avsc +++ b/avro-builder/tests/codegen-19/src/main/avro/vs19/TestCollections.avsc @@ -79,6 +79,16 @@ "type": "array", "items": "int" } + }, + { + "name": "unionOfIntMap", + "type": [ + "null", + { + "type": "map", + "values": "int" + } + ] } ], "type": "record" diff --git a/avro-builder/tests/codegen-charseq-method/src/main/avro/charseqmethod/TestCollections.avsc b/avro-builder/tests/codegen-charseq-method/src/main/avro/charseqmethod/TestCollections.avsc index 9dcaac88..81933b9e 100644 --- a/avro-builder/tests/codegen-charseq-method/src/main/avro/charseqmethod/TestCollections.avsc +++ b/avro-builder/tests/codegen-charseq-method/src/main/avro/charseqmethod/TestCollections.avsc @@ -79,6 +79,16 @@ "type": "array", "items": "int" } + }, + { + "name": "unionOfIntMap", + "type": [ + "null", + { + "type": "map", + "values": "int" + } + ] } ], "type": "record" diff --git a/avro-builder/tests/codegen-no-utf8-in-putbyindex/src/main/avro/charseqmethod/TestCollections.avsc b/avro-builder/tests/codegen-no-utf8-in-putbyindex/src/main/avro/charseqmethod/TestCollections.avsc index e8b8e730..9e9a56ba 100644 --- a/avro-builder/tests/codegen-no-utf8-in-putbyindex/src/main/avro/charseqmethod/TestCollections.avsc +++ b/avro-builder/tests/codegen-no-utf8-in-putbyindex/src/main/avro/charseqmethod/TestCollections.avsc @@ -79,6 +79,16 @@ "type": "array", "items": "int" } + }, + { + "name": "unionOfIntMap", + "type": [ + "null", + { + "type": "map", + "values": "int" + } + ] } ], "type": "record" diff --git a/avro-builder/tests/tests-allavro/src/test/java/com/linkedin/avroutil1/builder/SpecificRecordTest.java b/avro-builder/tests/tests-allavro/src/test/java/com/linkedin/avroutil1/builder/SpecificRecordTest.java index 302c7b40..77ce4898 100644 --- a/avro-builder/tests/tests-allavro/src/test/java/com/linkedin/avroutil1/builder/SpecificRecordTest.java +++ b/avro-builder/tests/tests-allavro/src/test/java/com/linkedin/avroutil1/builder/SpecificRecordTest.java @@ -1493,6 +1493,11 @@ public void testRecordWithCharSeqStringTypeForMethods() throws Exception { put("key1", Arrays.asList("val1", "val2")); put("key2", Arrays.asList("val10", "val20")); }}; + + Map mapOfInt = new HashMap() {{ + put("key1", 1); + put("key2", 2); + }}; charseqmethod.TestCollections.Builder testCollectionsBuilder = charseqmethod.TestCollections.newBuilder() .setStr(str) .setStrAr(Arrays.asList(str)) @@ -1501,7 +1506,8 @@ public void testRecordWithCharSeqStringTypeForMethods() throws Exception { .setArOfMap(Arrays.asList(mapCharSeq)) .setUnionOfMap(mapCharSeq) .setArOfUnionOfStr(Arrays.asList(str)) - .setArOfMapOfUnionOfArray(Arrays.asList(mapOfList)).setIntAr(Arrays.asList(1, 2, 3)); + .setArOfMapOfUnionOfArray(Arrays.asList(mapOfList)).setIntAr(Arrays.asList(1, 2, 3)) + .setUnionOfIntMap(mapOfInt); charseqmethod.TestCollections testCollections = testCollectionsBuilder.build(); @@ -1840,7 +1846,8 @@ public void testNewBuilder() throws Exception { .setArOfMap(instance.getArOfMap()) .setUnionOfMap(instance.getUnionOfMap()) .setArOfUnionOfStr(instance.getArOfUnionOfStr()) - .setArOfMapOfUnionOfArray(instance.getArOfMapOfUnionOfArray()); + .setArOfMapOfUnionOfArray(instance.getArOfMapOfUnionOfArray()) + .setUnionOfIntMap(instance.getUnionOfIntMap()); TestCollections.newBuilder(builder); diff --git a/avro-codegen/src/main/java/com/linkedin/avroutil1/codegen/SpecificRecordClassGenerator.java b/avro-codegen/src/main/java/com/linkedin/avroutil1/codegen/SpecificRecordClassGenerator.java index f5fc5845..8bc63746 100644 --- a/avro-codegen/src/main/java/com/linkedin/avroutil1/codegen/SpecificRecordClassGenerator.java +++ b/avro-codegen/src/main/java/com/linkedin/avroutil1/codegen/SpecificRecordClassGenerator.java @@ -1116,7 +1116,7 @@ private String getSerializedCustomDecodeBlock(SpecificRecordGenerationConfig con codeBlockBuilder.addStatement("$L.add($L)", arrayVarName, arrayElementVarName) .endControlFlow() .endControlFlow() - .addStatement("$L = com.linkedin.avroutil1.compatibility.collectiontransformer.ListTransformer.getUtf8List($L)", fieldName, arrayVarName); + .addStatement("$L = com.linkedin.avroutil1.compatibility.collectiontransformer.ListTransformer.convertToUtf8($L)", fieldName, arrayVarName); serializedCodeBlock = codeBlockBuilder.build().toString(); @@ -1165,7 +1165,7 @@ private String getSerializedCustomDecodeBlock(SpecificRecordGenerationConfig con codeBlockBuilder.addStatement("$L.put($L,$L)", mapVarName, mapKeyVarName, mapValueVarName) .endControlFlow() .endControlFlow() - .addStatement("$L = com.linkedin.avroutil1.compatibility.collectiontransformer.MapTransformer.getUtf8Map($L)", fieldName, mapVarName);; + .addStatement("$L = com.linkedin.avroutil1.compatibility.collectiontransformer.MapTransformer.convertToUtf8($L)", fieldName, mapVarName);; serializedCodeBlock = codeBlockBuilder.build().toString(); @@ -1581,9 +1581,8 @@ private void addGetByIndexMethod(TypeSpec.Builder classBuilder, AvroRecordSchema SpecificRecordGeneratorUtil.isCollectionSchemaValuePrimitive(field.getSchema())); } else if (SpecificRecordGeneratorUtil.isMapTransformerApplicable(field.getSchema())) { switchBuilder.addStatement( - "case $L: return com.linkedin.avroutil1.compatibility.collectiontransformer.MapTransformer.get$LMap(this.$L, $L)", - fieldIndex++, config.getDefaultMethodStringRepresentation().getJsonValue(), escapedFieldName, - SpecificRecordGeneratorUtil.isCollectionSchemaValuePrimitive(field.getSchema())); + "case $L: return com.linkedin.avroutil1.compatibility.collectiontransformer.MapTransformer.get$LMap(this.$L)", + fieldIndex++, config.getDefaultMethodStringRepresentation().getJsonValue(), escapedFieldName); } else if (field.getSchema() != null && AvroType.UNION.equals(field.getSchema().type())) { switchBuilder.addStatement("case $L:", fieldIndex++); @@ -1610,9 +1609,8 @@ private void addGetByIndexMethod(TypeSpec.Builder classBuilder, AvroRecordSchema } else if (SpecificRecordGeneratorUtil.isMapTransformerApplicable(unionMemberSchema.getSchema())) { switchBuilder.beginControlFlow("else if($1L instanceof $2T)", escapedFieldName, Map.class) .addStatement( - "return com.linkedin.avroutil1.compatibility.collectiontransformer.MapTransformer.get$1LMap($2L, $3L)", - config.getDefaultMethodStringRepresentation().getJsonValue(), escapedFieldName, - SpecificRecordGeneratorUtil.isCollectionSchemaValuePrimitive(field.getSchema())) + "return com.linkedin.avroutil1.compatibility.collectiontransformer.MapTransformer.get$1LMap($2L)", + config.getDefaultMethodStringRepresentation().getJsonValue(), escapedFieldName) .endControlFlow(); } } @@ -1826,9 +1824,9 @@ private MethodSpec getGetterMethodSpec(AvroSchemaField field, SpecificRecordGene SpecificRecordGeneratorUtil.isCollectionSchemaValuePrimitive(field.getSchema())); } else if (SpecificRecordGeneratorUtil.isMapTransformerApplicable(field.getSchema())) { methodSpecBuilder.addStatement( - "return com.linkedin.avroutil1.compatibility.collectiontransformer.MapTransformer.get$LMap(this.$L, $L)", + "return com.linkedin.avroutil1.compatibility.collectiontransformer.MapTransformer.get$LMap(this.$L)", config.getDefaultMethodStringRepresentation().getJsonValue(), - escapedFieldName, SpecificRecordGeneratorUtil.isCollectionSchemaValuePrimitive(field.getSchema())); + escapedFieldName); } else if (field.getSchema() != null && AvroType.UNION.equals(field.getSchema().type())) { methodSpecBuilder.beginControlFlow("if (this.$1L == null)", escapedFieldName) @@ -1852,9 +1850,8 @@ private MethodSpec getGetterMethodSpec(AvroSchemaField field, SpecificRecordGene } else if (SpecificRecordGeneratorUtil.isMapTransformerApplicable(unionMemberSchema.getSchema())) { methodSpecBuilder.beginControlFlow("else if($1L instanceof $2T)", escapedFieldName, Map.class) .addStatement( - "return com.linkedin.avroutil1.compatibility.collectiontransformer.MapTransformer.get$2LMap($1L, $3L)", - escapedFieldName, config.getDefaultMethodStringRepresentation().getJsonValue(), - SpecificRecordGeneratorUtil.isCollectionSchemaValuePrimitive(field.getSchema())) + "return com.linkedin.avroutil1.compatibility.collectiontransformer.MapTransformer.get$2LMap($1L)", + escapedFieldName, config.getDefaultMethodStringRepresentation().getJsonValue()) .endControlFlow(); } } diff --git a/helper/helper/src/main/java/com/linkedin/avroutil1/compatibility/collectiontransformer/CharSequenceMapView.java b/helper/helper/src/main/java/com/linkedin/avroutil1/compatibility/collectiontransformer/CharSequenceMapView.java deleted file mode 100644 index eb73cb13..00000000 --- a/helper/helper/src/main/java/com/linkedin/avroutil1/compatibility/collectiontransformer/CharSequenceMapView.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2024 LinkedIn Corp. - * Licensed under the BSD 2-Clause License (the "License"). - * See License in the project root for license information. - */ -package com.linkedin.avroutil1.compatibility.collectiontransformer; - -import java.util.AbstractMap; -import java.util.Collection; -import java.util.Collections; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; -import org.apache.avro.util.Utf8; - - -/** - * View of Utf8 Map to allow get as String while still allowing put to reflect on the original object. - */ -public class CharSequenceMapView extends AbstractMap { - - private Map utf8Map; - - public CharSequenceMapView(Map utf8Map) { - this.utf8Map = utf8Map; - } - - @Override - public Set> entrySet() { - return Collections.unmodifiableSet(utf8Map.entrySet().stream() - .collect(Collectors.toMap( - entry -> (CharSequence) String.valueOf(entry.getKey()), - entry -> (CharSequence) String.valueOf(entry.getValue()) - )) - .entrySet()); - } - - @Override - public CharSequence put(CharSequence key, CharSequence value) { - Utf8 utf8Key = new Utf8(key.toString()); - Utf8 utf8Value = new Utf8(value.toString()); - Utf8 previousValue = utf8Map.put(utf8Key, utf8Value); - return previousValue != null ? (CharSequence) String.valueOf(previousValue) : null; - } - - @Override - public Set keySet() { - return Collections.unmodifiableSet(utf8Map.keySet().stream() - .map(CharSequence::toString) - .collect(Collectors.toSet())); - } - - @Override - public Collection values() { - return Collections.unmodifiableCollection(utf8Map.values().stream() - .map(CharSequence::toString) - .collect(Collectors.toList())); - } - - @Override - public int size() { - return utf8Map.size(); - } - - @Override - public boolean isEmpty() { - return utf8Map.isEmpty(); - } - - @Override - public boolean containsKey(Object key) { - return utf8Map.containsKey(new Utf8(String.valueOf(key))); - } - - @Override - public boolean containsValue(Object value) { - return utf8Map.containsValue(new Utf8(String.valueOf(value))); - } - - @Override - public CharSequence get(Object key) { - Utf8 utf8Key = new Utf8(String.valueOf(key)); - Utf8 utf8Value = utf8Map.get(utf8Key); - return utf8Value != null ? (CharSequence) String.valueOf(utf8Value) : null; - } - - @Override - public CharSequence remove(Object key) { - Utf8 utf8Key = new Utf8(String.valueOf(key)); - Utf8 previousValue = utf8Map.remove(utf8Key); - return previousValue != null ? (CharSequence) String.valueOf(previousValue) : null; - } - - @Override - public void putAll(Map m) { - m.forEach((key, value) -> { - Utf8 utf8Key = new Utf8(String.valueOf(key)); - Utf8 utf8Value = new Utf8(String.valueOf(value)); - utf8Map.put(utf8Key, utf8Value); - }); - } -} diff --git a/helper/helper/src/main/java/com/linkedin/avroutil1/compatibility/collectiontransformer/CollectionTransformerUtil.java b/helper/helper/src/main/java/com/linkedin/avroutil1/compatibility/collectiontransformer/CollectionTransformerUtil.java index 39b02247..f2c1a96d 100644 --- a/helper/helper/src/main/java/com/linkedin/avroutil1/compatibility/collectiontransformer/CollectionTransformerUtil.java +++ b/helper/helper/src/main/java/com/linkedin/avroutil1/compatibility/collectiontransformer/CollectionTransformerUtil.java @@ -8,7 +8,6 @@ import com.linkedin.avroutil1.compatibility.StringUtils; import java.util.List; -import java.util.Map; import org.apache.avro.util.Utf8; @@ -47,37 +46,4 @@ public static List createCharSequenceListView(List utf8List) public static List createUtf8ListView(List utf8List) { return new Utf8ListView(utf8List); } - - /** - * Returns a {@link StringMapView} for the given map of {@link Utf8} objects. - * @param utf8Map map of {@link Utf8} objects - * @return a {@link StringMapView} for the given map of {@link Utf8} objects - */ - public static Map createStringMapView(Map utf8Map) { - if (utf8Map == null) { - return null; - } - return new StringMapView(utf8Map); - } - - /** - * Returns a {@link CharSequenceMapView} for the given map of {@link Utf8} objects. - * @param utf8Map map of {@link Utf8} objects - * @return a {@link CharSequenceMapView} for the given map of {@link Utf8} objects - */ - public static Map createUtf8MapView(Map utf8Map) { - return utf8Map; - } - - /** - * Returns a {@link CharSequenceMapView} for the given map of {@link Utf8} objects. - * @param utf8Map map of {@link Utf8} objects - * @return a {@link CharSequenceMapView} for the given map of {@link Utf8} objects - */ - public static Map createCharSequenceMapView(Map utf8Map) { - if (utf8Map == null) { - return null; - } - return new CharSequenceMapView(utf8Map); - } } diff --git a/helper/helper/src/main/java/com/linkedin/avroutil1/compatibility/collectiontransformer/MapTransformer.java b/helper/helper/src/main/java/com/linkedin/avroutil1/compatibility/collectiontransformer/MapTransformer.java index ad732d1b..68c0195d 100644 --- a/helper/helper/src/main/java/com/linkedin/avroutil1/compatibility/collectiontransformer/MapTransformer.java +++ b/helper/helper/src/main/java/com/linkedin/avroutil1/compatibility/collectiontransformer/MapTransformer.java @@ -11,7 +11,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import org.apache.avro.util.Utf8; public class MapTransformer { @@ -29,9 +28,6 @@ public static Map getCharSequenceMap(Object mapObj) { } public static Map getUtf8Map(Object mapObj, boolean isPrimitiveCollection) { - if(isPrimitiveCollection) { - return CollectionTransformerUtil.createUtf8MapView((Map) mapObj); - } if (mapObj == null) { return null; } @@ -61,9 +57,6 @@ public static Map getUtf8Map(Object mapObj, boolean isPrimitiveCollection) { } public static Map getStringMap(Object mapObj, boolean isPrimitiveCollection) { - if(isPrimitiveCollection) { - return CollectionTransformerUtil.createStringMapView((Map) mapObj); - } if (mapObj == null) { return null; } @@ -92,9 +85,6 @@ public static Map getStringMap(Object mapObj, boolean isPrimitiveCollection) { } public static Map getCharSequenceMap(Object mapObj, boolean isPrimitiveCollection) { - if(isPrimitiveCollection) { - return CollectionTransformerUtil.createCharSequenceMapView((Map) mapObj); - } if (mapObj == null) { return null; } diff --git a/helper/helper/src/main/java/com/linkedin/avroutil1/compatibility/collectiontransformer/StringMapView.java b/helper/helper/src/main/java/com/linkedin/avroutil1/compatibility/collectiontransformer/StringMapView.java deleted file mode 100644 index 19c0a500..00000000 --- a/helper/helper/src/main/java/com/linkedin/avroutil1/compatibility/collectiontransformer/StringMapView.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2024 LinkedIn Corp. - * Licensed under the BSD 2-Clause License (the "License"). - * See License in the project root for license information. - */ -package com.linkedin.avroutil1.compatibility.collectiontransformer; - -import java.util.AbstractMap; -import java.util.Collection; -import java.util.Collections; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; -import org.apache.avro.util.Utf8; - - -/** - * View of Utf8 Map to allow get as String while still allowing put to reflect on the original object. - */ -public class StringMapView extends AbstractMap { - - private Map utf8Map; - - public StringMapView(Map utf8Map) { - this.utf8Map = utf8Map; - } - - @Override - public Set> entrySet() { - return Collections.unmodifiableSet(utf8Map.entrySet().stream() - .collect(Collectors.toMap( - entry -> String.valueOf(entry.getKey()), - entry -> String.valueOf(entry.getValue()) - )) - .entrySet()); - } - - @Override - public String put(String key, String value) { - Utf8 utf8Key = new Utf8(key); - Utf8 utf8Value = new Utf8(value); - Utf8 previousValue = utf8Map.put(utf8Key, utf8Value); - return previousValue != null ? String.valueOf(previousValue) : null; - } - - @Override - public Set keySet() { - return Collections.unmodifiableSet(utf8Map.keySet().stream() - .map(String::valueOf) - .collect(Collectors.toSet())); - } - - @Override - public Collection values() { - return Collections.unmodifiableCollection(utf8Map.values().stream() - .map(String::valueOf) - .collect(Collectors.toList())); - } - - @Override - public int size() { - return utf8Map.size(); - } - - @Override - public boolean isEmpty() { - return utf8Map.isEmpty(); - } - - @Override - public boolean containsKey(Object key) { - return utf8Map.containsKey(new Utf8(String.valueOf(key))); - } - - @Override - public boolean containsValue(Object value) { - return utf8Map.containsValue(new Utf8(String.valueOf(value))); - } - - @Override - public String get(Object key) { - Utf8 utf8Key = new Utf8(String.valueOf(key)); - Utf8 utf8Value = utf8Map.get(utf8Key); - return utf8Value != null ? String.valueOf(utf8Value) : null; - } - - @Override - public String remove(Object key) { - Utf8 utf8Key = new Utf8(String.valueOf(key)); - Utf8 previousValue = utf8Map.remove(utf8Key); - return previousValue != null ? String.valueOf(previousValue) : null; - } - - @Override - public void putAll(Map m) { - m.forEach((key, value) -> { - Utf8 utf8Key = new Utf8(key); - Utf8 utf8Value = new Utf8(value); - utf8Map.put(utf8Key, utf8Value); - }); - } -}