diff --git a/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/DefaultAttributeConverterProvider.java b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/DefaultAttributeConverterProvider.java index 88cfbe39e82f..8f1b3743fb26 100644 --- a/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/DefaultAttributeConverterProvider.java +++ b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/DefaultAttributeConverterProvider.java @@ -157,11 +157,11 @@ private Optional> findConverterInternal(EnhancedType innerType = (EnhancedType) type.rawClassParameters().get(0); AttributeConverter innerConverter = findConverter(innerType) .orElseThrow(() -> new IllegalStateException("Converter not found for " + type)); diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/DefaultAttributeConverterProviderTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/DefaultAttributeConverterProviderTest.java index 417c8fb24547..c7ab43876a7b 100644 --- a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/DefaultAttributeConverterProviderTest.java +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/DefaultAttributeConverterProviderTest.java @@ -18,10 +18,14 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import java.util.Collections; +import java.util.HashMap; import java.util.List; import org.apache.logging.log4j.core.LogEvent; import org.junit.jupiter.api.Test; import org.slf4j.event.Level; +import software.amazon.awssdk.enhanced.dynamodb.mapper.StaticTableSchema; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; public class DefaultAttributeConverterProviderTest { @@ -58,9 +62,135 @@ void findConverter_whenConverterNotFound_logsNoConverter() { } } + @Test + void findConverter_whenConverterIsCached_returnsTheCachedConverter() { + DefaultAttributeConverterProvider provider = DefaultAttributeConverterProvider.create(); + + assertThat(provider.converterFor(EnhancedType.of(String.class))) + .isSameAs(provider.converterFor(EnhancedType.of(String.class))); + } + + @Test + void findConverter_whenMapSubtypeHasSupportedEntries_createsMapConverter() { + DefaultAttributeConverterProvider provider = DefaultAttributeConverterProvider.create(); + EnhancedType> type = new EnhancedType>() { }; + HashMap input = new HashMap<>(); + input.put("one", 1); + + AttributeValue result = provider.converterFor(type).transformFrom(input); + + assertThat(result.m()).containsEntry("one", AttributeValue.builder().n("1").build()); + } + + @Test + void findConverter_whenMapEntryValueIsObject_throwsConverterNotFound() { + DefaultAttributeConverterProvider provider = DefaultAttributeConverterProvider.create(); + + assertThatThrownBy(() -> provider.converterFor(EnhancedType.mapOf(String.class, Object.class))) + .isInstanceOf(IllegalStateException.class) + .hasMessageContaining("Converter not found for EnhancedType(java.util.Map)"); + } + + @Test + void findConverter_whenMapEntryValueHasNoConverter_throwsConverterNotFound() { + DefaultAttributeConverterProvider provider = DefaultAttributeConverterProvider.create(); + + assertThatThrownBy(() -> provider.converterFor(EnhancedType.mapOf(String.class, CustomUnsupportedType.class))) + .isInstanceOf(IllegalStateException.class) + .hasMessageContaining("Converter not found for EnhancedType(java.util.Map)"); + } + + @Test + void findConverter_whenSetHasSupportedEntries_createsSetConverter() { + DefaultAttributeConverterProvider provider = DefaultAttributeConverterProvider.create(); + + assertThat(provider.converterFor(EnhancedType.setOf(String.class)) + .transformFrom(Collections.singleton("value")).ss()) + .containsExactly("value"); + } + + @Test + void findConverter_whenSetEntryHasNoConverter_throwsConverterNotFound() { + DefaultAttributeConverterProvider provider = DefaultAttributeConverterProvider.create(); + + assertThatThrownBy(() -> provider.converterFor(EnhancedType.setOf(CustomUnsupportedType.class))) + .isInstanceOf(IllegalStateException.class) + .hasMessageContaining("Converter not found for EnhancedType(java.util.Set<" + + "software.amazon.awssdk.enhanced.dynamodb.DefaultAttributeConverterProviderTest" + + "$CustomUnsupportedType>)"); + } + + @Test + void findConverter_whenListHasSupportedEntries_createsListConverter() { + DefaultAttributeConverterProvider provider = DefaultAttributeConverterProvider.create(); + + assertThat(provider.converterFor(EnhancedType.listOf(String.class)) + .transformFrom(Collections.singletonList("value")).l()) + .containsExactly(AttributeValue.builder().s("value").build()); + } + + @Test + void findConverter_whenListEntryHasNoConverter_throwsConverterNotFound() { + DefaultAttributeConverterProvider provider = DefaultAttributeConverterProvider.create(); + + assertThatThrownBy(() -> provider.converterFor(EnhancedType.listOf(CustomUnsupportedType.class))) + .isInstanceOf(IllegalStateException.class) + .hasMessageContaining("Converter not found for EnhancedType(java.util.List<" + + "software.amazon.awssdk.enhanced.dynamodb.DefaultAttributeConverterProviderTest" + + "$CustomUnsupportedType>)"); + } + + @Test + void findConverter_whenTypeIsEnum_createsEnumConverter() { + DefaultAttributeConverterProvider provider = DefaultAttributeConverterProvider.create(); + + assertThat(provider.converterFor(EnhancedType.of(TestEnum.class)).transformFrom(TestEnum.VALUE).s()) + .isEqualTo("VALUE"); + } + + @Test + void findConverter_whenTypeHasTableSchema_createsDocumentConverter() { + DefaultAttributeConverterProvider provider = DefaultAttributeConverterProvider.create(); + TableSchema schema = StaticTableSchema.builder(TestDocument.class) + .newItemSupplier(TestDocument::new) + .addAttribute(String.class, a -> a.name("value") + .getter(TestDocument::value) + .setter(TestDocument::value)) + .build(); + + assertThat(provider.converterFor(EnhancedType.documentOf(TestDocument.class, schema)) + .transformFrom(new TestDocument("value")).m()) + .containsEntry("value", AttributeValue.builder().s("value").build()); + } + /** * A custom type with no converter registered for it. */ private static class CustomUnsupportedType { } + + private enum TestEnum { + VALUE + } + + private static final class TestDocument { + private String value; + + private TestDocument() { + } + + private TestDocument(String value) { + this.value = value; + } + + private String value() { + return value; + } + + private void value(String value) { + this.value = value; + } + } }