Skip to content

ddb-enhanced: adds EnhancedType parameters to static builder methods of StaticTableSchema and StaticImmutableTableSchema. #4077

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"category": "DynamoDB Enhanced Client",
"contributor": "bmaizels",
"type": "feature",
"description": "Add EnhancedType parameters to static builder methods of StaticTableSchema and StaticImmitableTableSchema"
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,18 @@ static <T> StaticTableSchema.Builder<T> builder(Class<T> itemClass) {
return StaticTableSchema.builder(itemClass);
}

/**
* Returns a builder for the {@link StaticTableSchema} implementation of this interface which allows all attributes,
* tags and table structure to be directly declared in the builder.
*
* @param itemType The {@link EnhancedType} of the item this {@link TableSchema} will map records to.
* @param <T> The type of the item this {@link TableSchema} will map records to.
* @return A newly initialized {@link StaticTableSchema.Builder}.
*/
static <T> StaticTableSchema.Builder<T> builder(EnhancedType<T> itemType) {
return StaticTableSchema.builder(itemType);
}

/**
* Returns a builder for the {@link StaticImmutableTableSchema} implementation of this interface which allows all
* attributes, tags and table structure to be directly declared in the builder.
Expand All @@ -69,6 +81,22 @@ static <T, B> StaticImmutableTableSchema.Builder<T, B> builder(Class<T> immutabl
return StaticImmutableTableSchema.builder(immutableItemClass, immutableBuilderClass);
}

/**
* Returns a builder for the {@link StaticImmutableTableSchema} implementation of this interface which allows all
* attributes, tags and table structure to be directly declared in the builder.
*
* @param immutableItemType The {@link EnhancedType} of the immutable item this {@link TableSchema} will map records to.
* @param immutableBuilderType The {@link EnhancedType} of the class that can be used to construct immutable items this
* {@link TableSchema} maps records to.
* @param <T> The type of the immutable item this {@link TableSchema} will map records to.
* @param <B> The type of the builder used by this {@link TableSchema} to construct immutable items with.
* @return A newly initialized {@link StaticImmutableTableSchema.Builder}
*/
static <T, B> StaticImmutableTableSchema.Builder<T, B> builder(EnhancedType<T> immutableItemType,
EnhancedType<B> immutableBuilderType) {
return StaticImmutableTableSchema.builder(immutableItemType, immutableBuilderType);
}

/**
* Scans a bean class that has been annotated with DynamoDb bean annotations and then returns a
* {@link BeanTableSchema} implementation of this interface that can map records to and from items of that bean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,19 @@ public static <T, B, R> Builder<T, B, R> builder(Class<T> itemClass,
return new Builder<>(attributeType);
}

/**
* Constructs a new builder for this class using supplied types.
* @param itemType The {@link EnhancedType} of the immutable item that this attribute composes.
* @param builderType The {@link EnhancedType} of the builder for the immutable item that this attribute composes.
* @param attributeType A {@link EnhancedType} that represents the type of the value this attribute stores.
* @return A new typed builder for an attribute.
*/
public static <T, B, R> Builder<T, B, R> builder(EnhancedType<T> itemType,
EnhancedType<B> builderType,
EnhancedType<R> attributeType) {
return new Builder<>(attributeType);
}

/**
* Constructs a new builder for this class using supplied types.
* @param itemClass The class of the item that this attribute composes.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,17 @@ private StaticAttribute(Builder<T, R> builder) {
* @return A new typed builder for an attribute.
*/
public static <T, R> Builder<T, R> builder(Class<T> itemClass, EnhancedType<R> attributeType) {
return new Builder<>(itemClass, attributeType);
return new Builder<>(EnhancedType.of(itemClass), attributeType);
}

/**
* Constructs a new builder for this class using supplied types.
* @param itemType The {@link EnhancedType} of the item that this attribute composes.
* @param attributeType A {@link EnhancedType} that represents the type of the value this attribute stores.
* @return A new typed builder for an attribute.
*/
public static <T, R> Builder<T, R> builder(EnhancedType<T> itemType, EnhancedType<R> attributeType) {
return new Builder<>(itemType, attributeType);
}

/**
Expand All @@ -79,7 +89,7 @@ public static <T, R> Builder<T, R> builder(Class<T> itemClass, EnhancedType<R> a
* @return A new typed builder for an attribute.
*/
public static <T, R> Builder<T, R> builder(Class<T> itemClass, Class<R> attributeClass) {
return new Builder<>(itemClass, EnhancedType.of(attributeClass));
return new Builder<>(EnhancedType.of(itemClass), EnhancedType.of(attributeClass));
}

/**
Expand Down Expand Up @@ -146,8 +156,8 @@ ImmutableAttribute<T, T, R> toImmutableAttribute() {
public static final class Builder<T, R> {
private final ImmutableAttribute.Builder<T, T, R> delegateBuilder;

private Builder(Class<T> itemClass, EnhancedType<R> type) {
this.delegateBuilder = ImmutableAttribute.builder(itemClass, itemClass, type);
private Builder(EnhancedType<T> itemType, EnhancedType<R> type) {
this.delegateBuilder = ImmutableAttribute.builder(itemType, itemType, type);
}

private Builder(ImmutableAttribute.Builder<T, T, R> delegateBuilder) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ private StaticImmutableTableSchema(Builder<T, B> builder) {
this.newBuilderSupplier = builder.newBuilderSupplier;
this.buildItemFunction = builder.buildItemFunction;
this.tableMetadata = tableMetadataBuilder.build();
this.itemType = EnhancedType.of(builder.itemClass);
this.itemType = builder.itemType;
}

/**
Expand All @@ -220,7 +220,18 @@ private StaticImmutableTableSchema(Builder<T, B> builder) {
* @return A newly initialized builder
*/
public static <T, B> Builder<T, B> builder(Class<T> itemClass, Class<B> builderClass) {
return new Builder<>(itemClass, builderClass);
return new Builder<>(EnhancedType.of(itemClass), EnhancedType.of(builderClass));
}

/**
* Creates a builder for a {@link StaticImmutableTableSchema} typed to specific immutable data item class.
* @param itemType The {@link EnhancedType} of the immutable data item class object that the
* {@link StaticImmutableTableSchema} is to map to.
* @param builderType The builder {@link EnhancedType} that can be used to construct instances of the immutable data item.
* @return A newly initialized builder
*/
public static <T, B> Builder<T, B> builder(EnhancedType<T> itemType, EnhancedType<B> builderType) {
return new Builder<>(itemType, builderType);
}

/**
Expand All @@ -230,8 +241,8 @@ public static <T, B> Builder<T, B> builder(Class<T> itemClass, Class<B> builderC
*/
@NotThreadSafe
public static final class Builder<T, B> {
private final Class<T> itemClass;
private final Class<B> builderClass;
private final EnhancedType<T> itemType;
private final EnhancedType<B> builderType;
private final List<ResolvedImmutableAttribute<T, B>> additionalAttributes = new ArrayList<>();
private final List<FlattenedMapper<T, B, ?>> flattenedMappers = new ArrayList<>();

Expand All @@ -242,9 +253,9 @@ public static final class Builder<T, B> {
private List<AttributeConverterProvider> attributeConverterProviders =
Collections.singletonList(ConverterProviderResolver.defaultConverterProvider());

private Builder(Class<T> itemClass, Class<B> builderClass) {
this.itemClass = itemClass;
this.builderClass = builderClass;
private Builder(EnhancedType<T> itemType, EnhancedType<B> builderType) {
this.itemType = itemType;
this.builderType = builderType;
}

/**
Expand Down Expand Up @@ -285,7 +296,7 @@ public <R> Builder<T, B> addAttribute(EnhancedType<R> attributeType,
Consumer<ImmutableAttribute.Builder<T, B, R>> immutableAttribute) {

ImmutableAttribute.Builder<T, B, R> builder =
ImmutableAttribute.builder(itemClass, builderClass, attributeType);
ImmutableAttribute.builder(itemType, builderType, attributeType);
immutableAttribute.accept(builder);
return addAttribute(builder.build());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,16 @@ private StaticTableSchema(Builder<T> builder) {
* @return A newly initialized builder
*/
public static <T> Builder<T> builder(Class<T> itemClass) {
return new Builder<>(itemClass);
return new Builder<>(EnhancedType.of(itemClass));
}

/**
* Creates a builder for a {@link StaticTableSchema} typed to specific data item class.
* @param itemType The {@link EnhancedType} of the data item class object that the {@link StaticTableSchema} is to map to.
* @return A newly initialized builder
*/
public static <T> Builder<T> builder(EnhancedType<T> itemType) {
return new Builder<>(itemType);
}

/**
Expand All @@ -85,11 +94,11 @@ public static <T> Builder<T> builder(Class<T> itemClass) {
@NotThreadSafe
public static final class Builder<T> {
private final StaticImmutableTableSchema.Builder<T, T> delegateBuilder;
private final Class<T> itemClass;
private final EnhancedType<T> itemType;

private Builder(Class<T> itemClass) {
this.delegateBuilder = StaticImmutableTableSchema.builder(itemClass, itemClass);
this.itemClass = itemClass;
private Builder(EnhancedType<T> itemType) {
this.delegateBuilder = StaticImmutableTableSchema.builder(itemType, itemType);
this.itemType = itemType;
}

/**
Expand Down Expand Up @@ -130,7 +139,7 @@ public Builder<T> attributes(Collection<StaticAttribute<T, ?>> staticAttributes)
*/
public <R> Builder<T> addAttribute(EnhancedType<R> attributeType,
Consumer<StaticAttribute.Builder<T, R>> staticAttribute) {
StaticAttribute.Builder<T, R> builder = StaticAttribute.builder(itemClass, attributeType);
StaticAttribute.Builder<T, R> builder = StaticAttribute.builder(itemType, attributeType);
staticAttribute.accept(builder);
this.delegateBuilder.addAttribute(builder.build().toImmutableAttribute());
return this;
Expand All @@ -142,7 +151,7 @@ public <R> Builder<T> addAttribute(EnhancedType<R> attributeType,
*/
public <R> Builder<T> addAttribute(Class<R> attributeClass,
Consumer<StaticAttribute.Builder<T, R>> staticAttribute) {
StaticAttribute.Builder<T, R> builder = StaticAttribute.builder(itemClass, attributeClass);
StaticAttribute.Builder<T, R> builder = StaticAttribute.builder(itemType, EnhancedType.of(attributeClass));
staticAttribute.accept(builder);
this.delegateBuilder.addAttribute(builder.build().toImmutableAttribute());
return this;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.FakeItem;
import software.amazon.awssdk.enhanced.dynamodb.mapper.BeanTableSchema;
import software.amazon.awssdk.enhanced.dynamodb.mapper.ImmutableTableSchema;
import software.amazon.awssdk.enhanced.dynamodb.mapper.StaticImmutableTableSchema;
import software.amazon.awssdk.enhanced.dynamodb.mapper.StaticTableSchema;
import software.amazon.awssdk.enhanced.dynamodb.mapper.testbeans.InvalidBean;
import software.amazon.awssdk.enhanced.dynamodb.mapper.testbeans.SimpleBean;
Expand All @@ -33,11 +34,31 @@ public class TableSchemaTest {
public ExpectedException exception = ExpectedException.none();

@Test
public void builder_constructsStaticTableSchemaBuilder() {
public void builder_constructsStaticTableSchemaBuilder_fromClass() {
StaticTableSchema.Builder<FakeItem> builder = TableSchema.builder(FakeItem.class);
assertThat(builder).isNotNull();
}

@Test
public void builder_constructsStaticTableSchemaBuilder_fromEnhancedType() {
StaticTableSchema.Builder<FakeItem> builder = TableSchema.builder(EnhancedType.of(FakeItem.class));
assertThat(builder).isNotNull();
}

@Test
public void builder_constructsStaticImmutableTableSchemaBuilder_fromClass() {
StaticImmutableTableSchema.Builder<SimpleImmutable, SimpleImmutable.Builder> builder =
TableSchema.builder(SimpleImmutable.class, SimpleImmutable.Builder.class);
assertThat(builder).isNotNull();
}

@Test
public void builder_constructsStaticImmutableTableSchemaBuilder_fromEnhancedType() {
StaticImmutableTableSchema.Builder<SimpleImmutable, SimpleImmutable.Builder> builder =
TableSchema.builder(EnhancedType.of(SimpleImmutable.class), EnhancedType.of(SimpleImmutable.Builder.class));
assertThat(builder).isNotNull();
}

@Test
public void fromBean_constructsBeanTableSchema() {
BeanTableSchema<SimpleBean> beanBeanTableSchema = TableSchema.fromBean(SimpleBean.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.FakeItem;
import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.FakeItemComposedClass;
import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.FakeItemWithSort;
import software.amazon.awssdk.enhanced.dynamodb.mapper.testimmutables.EntityEnvelopeImmutable;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;

@RunWith(MockitoJUnitRunner.class)
Expand Down Expand Up @@ -801,6 +802,17 @@ public void itemType_returnsCorrectClass() {
assertThat(FakeItem.getTableSchema().itemType(), is(equalTo(EnhancedType.of(FakeItem.class))));
}

@Test
public void itemType_returnsCorrectClassWhenBuiltWithEnhancedType() {
StaticImmutableTableSchema<FakeMappedItem, FakeMappedItem.Builder> tableSchema =
StaticImmutableTableSchema.builder(EnhancedType.of(FakeMappedItem.class),
EnhancedType.of(FakeMappedItem.Builder.class))
.newItemBuilder(FakeMappedItem::builder, FakeMappedItem.Builder::build)
.build();

assertThat(tableSchema.itemType(), is(equalTo(EnhancedType.of(FakeMappedItem.class))));
}

@Test
public void getTableMetadata_hasCorrectFields() {
TableMetadata tableMetadata = FakeItemWithSort.getTableSchema().tableMetadata();
Expand Down Expand Up @@ -1538,6 +1550,27 @@ public void noConverterProvider_handlesCorrectly_whenAttributeConvertersAreSuppl
assertThat(resultMap.get("aString").s(), is(expectedString));
}

@Test
public void builder_canBuildForGenericClassType() {
StaticImmutableTableSchema<EntityEnvelopeImmutable<String>, EntityEnvelopeImmutable.Builder<String>> envelopeTableSchema =
StaticImmutableTableSchema.builder(new EnhancedType<EntityEnvelopeImmutable<String>>() {},
new EnhancedType<EntityEnvelopeImmutable.Builder<String>>() {})
.newItemBuilder(EntityEnvelopeImmutable.Builder::new, EntityEnvelopeImmutable.Builder::build)
.addAttribute(String.class,
a -> a.name("entity")
.getter(EntityEnvelopeImmutable::entity)
.setter(EntityEnvelopeImmutable.Builder::setEntity))
.build();

EntityEnvelopeImmutable<String> testEnvelope = new EntityEnvelopeImmutable<>("test-value");

Map<String, AttributeValue> expectedMap =
Collections.singletonMap("entity", AttributeValue.fromS("test-value"));

assertThat(envelopeTableSchema.itemToMap(testEnvelope, false), equalTo(expectedMap));
assertThat(envelopeTableSchema.mapToItem(expectedMap).entity(), equalTo("test-value"));
}

private <R> void verifyAttribute(EnhancedType<R> attributeType,
Consumer<StaticAttribute.Builder<FakeMappedItem, R>> staticAttribute,
FakeMappedItem fakeMappedItem,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.FakeItem;
import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.FakeItemComposedClass;
import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.FakeItemWithSort;
import software.amazon.awssdk.enhanced.dynamodb.mapper.testbeans.EntityEnvelopeBean;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;

@RunWith(MockitoJUnitRunner.class)
Expand Down Expand Up @@ -799,6 +800,16 @@ public void itemType_returnsCorrectClass() {
assertThat(FakeItem.getTableSchema().itemType(), is(equalTo(EnhancedType.of(FakeItem.class))));
}

@Test
public void itemType_returnsCorrectClassWhenBuiltWithEnhancedType() {
StaticTableSchema<FakeMappedItem> tableSchema = StaticTableSchema.builder(EnhancedType.of(FakeMappedItem.class))
.newItemSupplier(FakeMappedItem::new)
.attributes(ATTRIBUTES)
.build();

assertThat(tableSchema.itemType(), is(equalTo(EnhancedType.of(FakeMappedItem.class))));
}

@Test
public void getTableMetadata_hasCorrectFields() {
TableMetadata tableMetadata = FakeItemWithSort.getTableSchema().tableMetadata();
Expand Down Expand Up @@ -1485,6 +1496,27 @@ public void noConverterProvider_handlesCorrectly_whenAttributeConvertersAreSuppl
assertThat(resultMap.get("aString").s(), is(expectedString));
}

@Test
public void builder_canBuildForGenericClassType() {
StaticTableSchema<EntityEnvelopeBean<String>> envelopeTableSchema =
StaticTableSchema.builder(new EnhancedType<EntityEnvelopeBean<String>>() {})
.newItemSupplier(EntityEnvelopeBean::new)
.addAttribute(String.class,
a -> a.name("entity")
.getter(EntityEnvelopeBean::getEntity)
.setter(EntityEnvelopeBean::setEntity))
.build();

EntityEnvelopeBean<String> testEnvelope = new EntityEnvelopeBean<>();
testEnvelope.setEntity("test-value");

Map<String, AttributeValue> expectedMap =
Collections.singletonMap("entity", AttributeValue.fromS("test-value"));

assertThat(envelopeTableSchema.itemToMap(testEnvelope, false), equalTo(expectedMap));
assertThat(envelopeTableSchema.mapToItem(expectedMap).getEntity(), equalTo("test-value"));
}

private <R> void verifyAttribute(EnhancedType<R> attributeType,
Consumer<StaticAttribute.Builder<FakeMappedItem, R>> staticAttribute,
FakeMappedItem fakeMappedItem,
Expand Down
Loading