diff --git a/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/document/EnhancedDocument.java b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/document/EnhancedDocument.java index 6455d4ebd08b..1e6f9f152027 100644 --- a/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/document/EnhancedDocument.java +++ b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/document/EnhancedDocument.java @@ -24,7 +24,9 @@ import software.amazon.awssdk.core.SdkNumber; import software.amazon.awssdk.enhanced.dynamodb.AttributeConverter; import software.amazon.awssdk.enhanced.dynamodb.AttributeConverterProvider; +import software.amazon.awssdk.enhanced.dynamodb.DefaultAttributeConverterProvider; import software.amazon.awssdk.enhanced.dynamodb.EnhancedType; +import software.amazon.awssdk.enhanced.dynamodb.internal.document.DefaultEnhancedDocument; /** * Interface representing Document API for DynamoDB. Document API operations are used to carry open content i.e. data with no @@ -37,6 +39,9 @@ @SdkPublicApi public interface EnhancedDocument { + DefaultAttributeConverterProvider defaultProvider = DefaultAttributeConverterProvider.create(); + + /** * Convenience factory method - instantiates an EnhancedDocument from the given JSON String. * @@ -44,8 +49,13 @@ public interface EnhancedDocument { * @return A new instance of EnhancedDocument. */ static EnhancedDocument fromJson(String json) { - // TODO : return default implementation - return null; + if (json == null) { + return null; + } + return DefaultEnhancedDocument.builder() + .json(json) + .addAttributeConverterProvider(defaultProvider) + .build(); } /** @@ -55,16 +65,20 @@ static EnhancedDocument fromJson(String json) { * @return A new instance of EnhancedDocument. */ static EnhancedDocument fromMap(Map attributes) { - // TODO : return default implementation - return null; + if (attributes == null) { + return null; + } + DefaultEnhancedDocument.DefaultBuilder defaultBuilder = DefaultEnhancedDocument.builder(); + attributes.entrySet().forEach(key -> defaultBuilder.add(key.getKey(), key.getValue())); + return defaultBuilder.addAttributeConverterProvider(defaultProvider) + .build(); } /** * Creates a default builder for {@link EnhancedDocument}. */ static Builder builder() { - // TODO : return default implementation - return null; + return DefaultEnhancedDocument.builder(); } /** diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/document/DefaultEnhancedDocumentTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/document/DefaultEnhancedDocumentTest.java index aa28a8489276..a8dc3bbf2661 100644 --- a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/document/DefaultEnhancedDocumentTest.java +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/document/DefaultEnhancedDocumentTest.java @@ -60,6 +60,12 @@ public class DefaultEnhancedDocumentTest { static final String SIMPLE_STRING = "stringValue"; static final String SIMPLE_STRING_KEY = "stringKey"; static final String SIMPLE_INT_NUMBER = "10"; + public static final String ARRAY_AND_MAP_IN_JSON = "{\"numberKey\": 1," + + "\"numberList\": " + "[1, 2, 3]," + + "\"mapKey\": " + + "{\"1\": [\"a\", \"b\", \"c\"]," + + "\"2\": 1}" + + "}"; private static Stream attributeValueMapsCorrespondingDocuments() { @@ -201,13 +207,7 @@ private static Stream attributeValueMapsCorrespondingDocuments() { mapFromKeyValuePairs(Pair.of(EnhancedType.listOf(String.class), Arrays.asList(STRINGS_ARRAY)), Pair.of(EnhancedType.of(Integer.class), 1)))) , documentBuilder() - .json( - "{\"numberKey\": 1," - + "\"numberList\": " + "[1, 2, 3]," - + "\"mapKey\": " - + "{\"1\": [\"a\", \"b\", \"c\"]," - + "\"2\": 1}" - + "}") + .json(ARRAY_AND_MAP_IN_JSON) .build() , "{\"numberKey\": 1,\"numberList\": [1, 2, 3],\"mapKey\": {\"1\": [\"a\", \"b\", \"c\"],\"2\": 1}}"), diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/document/EnhancedDocumentTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/document/EnhancedDocumentTest.java new file mode 100644 index 000000000000..71c09e514492 --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/document/EnhancedDocumentTest.java @@ -0,0 +1,112 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.enhanced.dynamodb.document; + +import static software.amazon.awssdk.enhanced.dynamodb.document.DefaultEnhancedDocumentTest.ARRAY_AND_MAP_IN_JSON; +import static org.assertj.core.api.Assertions.assertThat; +import static software.amazon.awssdk.enhanced.dynamodb.document.DefaultEnhancedDocumentTest.NUMBER_STRING_ARRAY; +import static software.amazon.awssdk.enhanced.dynamodb.document.DefaultEnhancedDocumentTest.STRINGS_ARRAY; + +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import software.amazon.awssdk.enhanced.dynamodb.EnhancedType; + +public class EnhancedDocumentTest { + + static String INNER_JSON = "{\"1\": [\"a\", \"b\", \"c\"],\"2\": 1}"; + + private static Stream documentsCreatedFromStaticMethods() { + Map map = getStringObjectMap(); + return Stream.of( + Arguments.of(EnhancedDocument.fromJson(ARRAY_AND_MAP_IN_JSON)), + Arguments.of(EnhancedDocument.fromMap(map))); + } + + private static Map getStringObjectMap() { + Map map = new LinkedHashMap<>(); + map.put("numberKey", 1); + map.put("numberList", Arrays.asList(1, 2, 3)); + Map innerMap = new LinkedHashMap<>(); + map.put("mapKey", innerMap); + + innerMap.put("1", Arrays.asList(STRINGS_ARRAY)); + innerMap.put("2", 1); + return map; + } + + @ParameterizedTest + @MethodSource("documentsCreatedFromStaticMethods") + void createFromJson(EnhancedDocument enhancedDocument) { + assertThat(enhancedDocument.toJson()).isEqualTo(ARRAY_AND_MAP_IN_JSON); + + enhancedDocument.getJson("mapKey").equals(INNER_JSON); + + assertThat(enhancedDocument.getSdkNumber("numberKey").intValue()).isEqualTo(1); + + assertThat(enhancedDocument.getList("numberList") + .stream() + .map( o ->Integer.parseInt(o.toString()) ) + .collect(Collectors.toList())) + .isEqualTo(Arrays.stream(NUMBER_STRING_ARRAY) + .map(s -> Integer.parseInt(s)) + .collect(Collectors.toList())); + + assertThat(enhancedDocument.getList("numberList", EnhancedType.of(String.class))) + .isEqualTo(Arrays.asList(NUMBER_STRING_ARRAY)); + + + assertThat(enhancedDocument.getMapAsDocument("mapKey").toJson()) + .isEqualTo(EnhancedDocument.fromJson(INNER_JSON).toJson()); + + // This is same as V1, where the Json List of String is identified as List of Strings rather than set of string + assertThat(enhancedDocument.getMapAsDocument("mapKey").getList("1")).isEqualTo(Arrays.asList(STRINGS_ARRAY)); + assertThat(enhancedDocument.getMapAsDocument("mapKey").getStringSet("1")).isNull(); + } + + @Test + public void nullArgsInStaticConstructor(){ + assertThat(EnhancedDocument.fromMap(null)).isNull(); + assertThat(EnhancedDocument.fromJson(null)).isNull(); + } + + @Test + void accessingStringSetFromBuilderMethods(){ + + Set stringSet = Stream.of(STRINGS_ARRAY).collect(Collectors.toSet()); + EnhancedDocument enhancedDocument = EnhancedDocument.builder() + .addStringSet("stringSet", stringSet) + .build(); + + assertThat(enhancedDocument.getStringSet("stringSet")).isEqualTo(stringSet); + assertThat(enhancedDocument.getList("stringSet")).isNull(); + } + + @Test + void toBuilderOverwritingOldJson(){ + EnhancedDocument document = EnhancedDocument.fromJson(ARRAY_AND_MAP_IN_JSON); + assertThat(document.toJson()).isEqualTo(ARRAY_AND_MAP_IN_JSON); + EnhancedDocument fromBuilder = document.toBuilder().json(INNER_JSON).build(); + assertThat(fromBuilder.toJson()).isEqualTo(INNER_JSON); + } +}