Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
75cb67a
Adding new Interface EnhancedDocument (#3702)
joviegas Jan 21, 2023
92ca159
Merge branch 'master' into feature/master/joviegas_document_db_impl
joviegas Jan 25, 2023
01436d3
DefaultEnhancedDocument implementation (#3718)
joviegas Feb 1, 2023
aa3444a
Merge branch 'master' into feature/master/joviegas_document_db_impl
joviegas Feb 8, 2023
d957736
Implement Static factory methods of EnhancedDocument (#3752)
joviegas Feb 8, 2023
27d1948
Merge branch 'master' into feature/master/joviegas_document_db_impl
joviegas Feb 8, 2023
764fc02
DocumentTableSchema Implementation (#3758)
joviegas Feb 16, 2023
fcbc4ae
Merge branch 'master' into feature/master/joviegas_document_db_impl
joviegas Feb 16, 2023
a1f7443
Merge branch 'master' into feature/master/joviegas_document_db_impl
joviegas Feb 20, 2023
7e936ac
The builder for EnhancedDocument should not rely on the order in whic…
joviegas Feb 22, 2023
a9407dd
Merge branch 'master' into feature/master/joviegas_document_db_impl
joviegas Feb 23, 2023
5c683e5
Merge branch 'master' into feature/master/joviegas_document_db_impl
joviegas Mar 6, 2023
0c074c0
Handled surface api comments of removing Generic access as Objects (#…
joviegas Mar 9, 2023
80fe9c1
Remove extra spaces in Json and make it same as Items as in V1 (#3835)
joviegas Mar 15, 2023
b60c4fc
Merge branch 'master' into feature/master/joviegas_document_db_impl
joviegas Mar 15, 2023
5e15af7
Delete unwanted class
joviegas Mar 16, 2023
fc88544
Functional Test Cases for Document DDB API and Surface API Review 2 c…
joviegas Mar 20, 2023
6db71c2
Merge branch 'master' into feature/master/joviegas_document_db_impl
joviegas Mar 20, 2023
3557d15
Handled PR comments, \n 1. Moved DocumentTableSchema from mapper to d…
joviegas Mar 22, 2023
73e9459
Removed @inherit wherever not required
joviegas Mar 23, 2023
5da0e01
Merge branch 'master' into feature/master/joviegas_document_db_impl
joviegas Mar 23, 2023
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
Expand Up @@ -20,9 +20,9 @@
import java.util.Map;
import software.amazon.awssdk.annotations.SdkPublicApi;
import software.amazon.awssdk.annotations.ThreadSafe;
import software.amazon.awssdk.enhanced.dynamodb.document.DocumentTableSchema;
import software.amazon.awssdk.enhanced.dynamodb.document.EnhancedDocument;
import software.amazon.awssdk.enhanced.dynamodb.mapper.BeanTableSchema;
import software.amazon.awssdk.enhanced.dynamodb.mapper.DocumentTableSchema;
import software.amazon.awssdk.enhanced.dynamodb.mapper.ImmutableTableSchema;
import software.amazon.awssdk.enhanced.dynamodb.mapper.StaticImmutableTableSchema;
import software.amazon.awssdk.enhanced.dynamodb.mapper.StaticTableSchema;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* permissions and limitations under the License.
*/

package software.amazon.awssdk.enhanced.dynamodb.mapper;
package software.amazon.awssdk.enhanced.dynamodb.document;

import java.util.ArrayList;
import java.util.Arrays;
Expand All @@ -34,9 +34,10 @@
import software.amazon.awssdk.enhanced.dynamodb.EnhancedType;
import software.amazon.awssdk.enhanced.dynamodb.TableMetadata;
import software.amazon.awssdk.enhanced.dynamodb.TableSchema;
import software.amazon.awssdk.enhanced.dynamodb.document.EnhancedDocument;
import software.amazon.awssdk.enhanced.dynamodb.internal.converter.ConverterProviderResolver;
import software.amazon.awssdk.enhanced.dynamodb.internal.document.DefaultEnhancedDocument;
import software.amazon.awssdk.enhanced.dynamodb.mapper.StaticImmutableTableSchema;
import software.amazon.awssdk.enhanced.dynamodb.mapper.StaticTableMetadata;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;


Expand All @@ -53,7 +54,7 @@
* DocumentTableSchema documentTableSchema = DocumentTableSchema.builder()
* .primaryKey("sampleHashKey", AttributeValueType.S)
* .sortKey("sampleSortKey", AttributeValueType.S)
* .attributeConverterProviders(customAttributeConveter, AttributeConverterProvider.defaultProvider())
* .attributeConverterProviders(customAttributeConverter, AttributeConverterProvider.defaultProvider())
* .build();
*}
* <p> DocumentTableSchema can also be created without specifying primaryKey and sortKey in which cases the
Expand All @@ -80,6 +81,9 @@ public static Builder builder() {
return new Builder();
}

/**
* {@inheritdoc}
*/
@Override
public EnhancedDocument mapToItem(Map<String, AttributeValue> attributeMap) {
if (attributeMap == null) {
Expand All @@ -93,12 +97,14 @@ public EnhancedDocument mapToItem(Map<String, AttributeValue> attributeMap) {
}

/**
* @param item The modelled Java object to convert into a map of attributes.
* @param ignoreNulls This flag is of no use for Document API, unlike Java objects where default value of undefined Object is
* null , and since Enhanced client knows the Schemas this flag is used to decide whether to send Null
* Attribute Value or not send the attribute at all, However, in case of Document API the Enhanced client
* is not aware of the Schema, thus any fields which are not set explicitly will always be ignored.
* @return
* {@inheritDoc}
*
* This flag does not have significance for the Document API, unlike Java objects where the default value of an undefined
* Object is null.In contrast to mapped classes, where a schema is present, the DocumentSchema is unaware of the entire
* schema.Therefore, if an attribute is not present, it signifies that it is null, and there is no need to handle it in a
* separate way.However, if the user explicitly wants to nullify certain attributes, then the user needs to set those
* attributes as null in the Document that needs to be updated.
*
*/
@Override
public Map<String, AttributeValue> itemToMap(EnhancedDocument item, boolean ignoreNulls) {
Expand All @@ -119,6 +125,9 @@ private List<AttributeConverterProvider> mergeAttributeConverterProviders(Enhanc
return attributeConverterProviders;
}

/**
* {@inheritDoc}
*/
@Override
public Map<String, AttributeValue> itemToMap(EnhancedDocument item, Collection<String> attributes) {
if (item.toMap() == null) {
Expand All @@ -132,6 +141,9 @@ public Map<String, AttributeValue> itemToMap(EnhancedDocument item, Collection<S
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
}

/**
* {@inheritdoc}
*/
@Override
public AttributeValue attributeValue(EnhancedDocument item, String attributeName) {
if (item == null || item.toMap() == null) {
Expand All @@ -145,21 +157,33 @@ public AttributeValue attributeValue(EnhancedDocument item, String attributeName
.get(attributeName);
}

/**
* {@inheritdoc}
*/
@Override
public TableMetadata tableMetadata() {
return tableMetadata;
}

/**
* {@inheritdoc}
*/
@Override
public EnhancedType<EnhancedDocument> itemType() {
return EnhancedType.of(EnhancedDocument.class);
}

/**
* {@inheritdoc}
*/
@Override
public List<String> attributeNames() {
return tableMetadata.keyAttributes().stream().map(key -> key.name()).collect(Collectors.toList());
}

/**
* {@inheritdoc}
*/
@Override
public boolean isAbstract() {
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,10 @@ static EnhancedDocument fromJson(String json) {
*/
static EnhancedDocument fromAttributeValueMap(Map<String, AttributeValue> attributeValueMap) {
Validate.paramNotNull(attributeValueMap, "attributeValueMap");
return ((DefaultEnhancedDocument.DefaultBuilder) DefaultEnhancedDocument.builder())
.attributeValueMap(attributeValueMap)
.attributeConverterProviders(defaultProvider())
.build();
return DefaultEnhancedDocument.builder()
.attributeValueMap(attributeValueMap)
.attributeConverterProviders(defaultProvider())
.build();
}

/**
Expand Down Expand Up @@ -560,6 +560,15 @@ interface Builder {
*/
Builder json(String json);

/**
* Sets the attributes of the document builder to those specified in the provided from a AttributeValue Map, and
* completely replaces any previously set attributes.
*
* @param attributeValueMap - Map with Attributes as String keys and AttributeValue as Value.
* @return Builder instance to construct a {@link EnhancedDocument}
*/
Builder attributeValueMap(Map<String, AttributeValue> attributeValueMap);

/**
* Builds an instance of {@link EnhancedDocument}.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,13 @@
@SdkInternalApi
public class DefaultEnhancedDocument implements EnhancedDocument {

private static final IllegalStateException NULL_SET_ERROR = new IllegalStateException("Set must not have null values.");
private static final Lazy<IllegalStateException> NULL_SET_ERROR = new Lazy<>(
() -> new IllegalStateException("Set must not have null values."));

private static final JsonItemAttributeConverter JSON_ATTRIBUTE_CONVERTER = JsonItemAttributeConverter.create();
private static final String VALIDATE_TYPE_ERROR = "Values of type %s are not supported by this API, please use the "
+ "%s%s API instead";
private static final AttributeValue NULL_ATTRIBUTE_VALUE = AttributeValue.fromNul(true);
private final Map<String, Object> nonAttributeValueMap;
private final Map<String, EnhancedType> enhancedTypeMap;
private final List<AttributeConverterProvider> attributeConverterProviders;
Expand Down Expand Up @@ -116,8 +119,11 @@ public List<AttributeConverterProvider> attributeConverterProviders() {

@Override
public boolean isNull(String attributeName) {
return isPresent(attributeName) && (nonAttributeValueMap.get(attributeName) == null
|| AttributeValue.fromNul(true).equals(nonAttributeValueMap.get(attributeName)));
if (!isPresent(attributeName)) {
return false;
}
Object attributeValue = nonAttributeValueMap.get(attributeName);
return attributeValue == null || NULL_ATTRIBUTE_VALUE.equals(attributeValue);
}

@Override
Expand Down Expand Up @@ -242,7 +248,7 @@ private Map<String, AttributeValue> initializeAttributeValueMap() {
Validate.notEmpty(this.attributeConverterProviders, "attributeConverterProviders");
this.nonAttributeValueMap.forEach((k, v) -> {
if (v == null) {
result.put(k, AttributeValue.fromNul(true));
result.put(k, NULL_ATTRIBUTE_VALUE);
} else {

result.put(k, toAttributeValue(v, enhancedTypeMap.getOrDefault(k, EnhancedType.of(v.getClass()))));
Expand Down Expand Up @@ -289,12 +295,10 @@ public Builder putObject(String attributeName, Object value) {
}

private Builder putObject(String attributeName, Object value, boolean ignoreNullValue) {

if (!ignoreNullValue) {
checkInvalidAttribute(attributeName, value);
} else {
Validate.paramNotNull(attributeName, "attributeName");
Validate.paramNotBlank(attributeName.trim(), "attributeName");
validateAttributeName(attributeName);
}
enhancedTypeMap.remove(attributeName);
nonAttributeValueMap.remove(attributeName);
Expand Down Expand Up @@ -331,7 +335,7 @@ public Builder putNull(String attributeName) {
public Builder putStringSet(String attributeName, Set<String> values) {
checkInvalidAttribute(attributeName, values);
if (values.stream().anyMatch(Objects::isNull)) {
throw NULL_SET_ERROR;
throw NULL_SET_ERROR.getValue();
}
return put(attributeName, values, EnhancedType.setOf(String.class));
}
Expand All @@ -342,7 +346,7 @@ public Builder putNumberSet(String attributeName, Set<Number> values) {
Set<SdkNumber> sdkNumberSet =
values.stream().map(number -> {
if (number == null) {
throw NULL_SET_ERROR;
throw NULL_SET_ERROR.getValue();
}
return SdkNumber.fromString(number.toString());
}).collect(Collectors.toCollection(LinkedHashSet::new));
Expand All @@ -353,7 +357,7 @@ public Builder putNumberSet(String attributeName, Set<Number> values) {
public Builder putBytesSet(String attributeName, Set<SdkBytes> values) {
checkInvalidAttribute(attributeName, values);
if (values.stream().anyMatch(Objects::isNull)) {
throw NULL_SET_ERROR;
throw NULL_SET_ERROR.getValue();
}
return put(attributeName, values, EnhancedType.setOf(SdkBytes.class));
}
Expand Down Expand Up @@ -436,6 +440,7 @@ public Builder json(String json) {
return this;
}

@Override
public Builder attributeValueMap(Map<String, AttributeValue> attributeValueMap) {
Validate.paramNotNull(attributeConverterProviders, "attributeValueMap");
nonAttributeValueMap.clear();
Expand All @@ -458,11 +463,15 @@ private static AttributeValue getAttributeValueFromJson(String json) {
}

private static void checkInvalidAttribute(String attributeName, Object value) {
Validate.paramNotNull(attributeName, "attributeName");
Validate.paramNotBlank(attributeName.trim(), "attributeName");
validateAttributeName(attributeName);
Validate.notNull(value, "Value for %s must not be null. Use putNull API to insert a Null value", attributeName);
}

private static void validateAttributeName(String attributeName) {
Validate.isTrue(attributeName != null && !attributeName.trim().isEmpty(),
"Attribute name must not be null or empty.");
}

}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,56 +40,4 @@ public <T> AttributeConverter<T> converterFor(EnhancedType<T> enhancedType) {
public static CustomAttributeForDocumentConverterProvider create(){
return new CustomAttributeForDocumentConverterProvider();
}


private static class CustomStringAttributeConverter implements AttributeConverter<String> {

final static String DEFAULT_SUFFIX = "-custom";

@Override
public AttributeValue transformFrom(String input) {
return EnhancedAttributeValue.fromString(input + DEFAULT_SUFFIX).toAttributeValue();
}

@Override
public String transformTo(AttributeValue input) {
return input.s();
}

@Override
public EnhancedType<String> type() {
return EnhancedType.of(String.class);
}

@Override
public AttributeValueType attributeValueType() {
return AttributeValueType.S;
}
}

private static class CustomIntegerAttributeCo implements AttributeConverter<Integer> {

final static Integer DEFAULT_INCREMENT = 10;

@Override
public AttributeValue transformFrom(Integer input) {
return EnhancedAttributeValue.fromNumber(IntegerStringConverter.create().toString(input + DEFAULT_INCREMENT))
.toAttributeValue();
}

@Override
public Integer transformTo(AttributeValue input) {
return Integer.valueOf(input.n());
}

@Override
public EnhancedType<Integer> type() {
return EnhancedType.of(Integer.class);
}

@Override
public AttributeValueType attributeValueType() {
return AttributeValueType.N;
}
}
}
Loading