Skip to content

Commit

Permalink
Revert "Fixed EnhancedClient UpdateItem operation to make it work on …
Browse files Browse the repository at this point in the history
…nested attributes as well (#5380)" (#5586)

This reverts commit 79394aa.
  • Loading branch information
zoewangg authored Sep 11, 2024
1 parent 3d0e8e9 commit ec4c51b
Show file tree
Hide file tree
Showing 8 changed files with 9 additions and 480 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,13 @@

package software.amazon.awssdk.enhanced.dynamodb.internal;

import static software.amazon.awssdk.enhanced.dynamodb.internal.operations.UpdateItemOperation.NESTED_OBJECT_UPDATE;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import software.amazon.awssdk.annotations.SdkInternalApi;
Expand All @@ -43,7 +40,6 @@ public final class EnhancedClientUtils {
private static final Set<Character> SPECIAL_CHARACTERS = Stream.of(
'*', '.', '-', '#', '+', ':', '/', '(', ')', ' ',
'&', '<', '>', '?', '=', '!', '@', '%', '$', '|').collect(Collectors.toSet());
private static final Pattern NESTED_OBJECT_PATTERN = Pattern.compile(NESTED_OBJECT_UPDATE);

private EnhancedClientUtils() {

Expand Down Expand Up @@ -71,30 +67,18 @@ public static String cleanAttributeName(String key) {
return somethingChanged ? new String(chars) : key;
}

private static boolean isNestedAttribute(String key) {
return key.contains(NESTED_OBJECT_UPDATE);
}

/**
* Creates a key token to be used with an ExpressionNames map.
*/
public static String keyRef(String key) {
String cleanAttributeName = cleanAttributeName(key);
cleanAttributeName = isNestedAttribute(cleanAttributeName) ?
NESTED_OBJECT_PATTERN.matcher(cleanAttributeName).replaceAll(".#AMZN_MAPPED_")
: cleanAttributeName;
return "#AMZN_MAPPED_" + cleanAttributeName;
return "#AMZN_MAPPED_" + cleanAttributeName(key);
}

/**
* Creates a value token to be used with an ExpressionValues map.
*/
public static String valueRef(String value) {
String cleanAttributeName = cleanAttributeName(value);
cleanAttributeName = isNestedAttribute(cleanAttributeName) ?
NESTED_OBJECT_PATTERN.matcher(cleanAttributeName).replaceAll("_")
: cleanAttributeName;
return ":AMZN_MAPPED_" + cleanAttributeName;
return ":AMZN_MAPPED_" + cleanAttributeName(value);
}

public static <T> T readAndTransformSingleItem(Map<String, AttributeValue> itemMap,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,11 @@

package software.amazon.awssdk.enhanced.dynamodb.internal.operations;

import static software.amazon.awssdk.enhanced.dynamodb.internal.EnhancedClientUtils.isNullAttributeValue;
import static software.amazon.awssdk.enhanced.dynamodb.internal.EnhancedClientUtils.readAndTransformSingleItem;
import static software.amazon.awssdk.enhanced.dynamodb.internal.update.UpdateExpressionUtils.operationExpression;
import static software.amazon.awssdk.utils.CollectionUtils.filterMap;

import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
Expand Down Expand Up @@ -55,8 +53,7 @@
public class UpdateItemOperation<T>
implements TableOperation<T, UpdateItemRequest, UpdateItemResponse, UpdateItemEnhancedResponse<T>>,
TransactableWriteOperation<T> {

public static final String NESTED_OBJECT_UPDATE = "_NESTED_ATTR_UPDATE_";

private final Either<UpdateItemEnhancedRequest<T>, TransactUpdateItemEnhancedRequest<T>> request;

private UpdateItemOperation(UpdateItemEnhancedRequest<T> request) {
Expand Down Expand Up @@ -92,14 +89,8 @@ public UpdateItemRequest generateRequest(TableSchema<T> tableSchema,
Boolean ignoreNulls = request.map(r -> Optional.ofNullable(r.ignoreNulls()),
r -> Optional.ofNullable(r.ignoreNulls()))
.orElse(null);

Map<String, AttributeValue> itemMapImmutable = tableSchema.itemToMap(item, Boolean.TRUE.equals(ignoreNulls));

// If ignoreNulls is set to true, check for nested params to be updated
// If needed, Transform itemMap for it to be able to handle them.
Map<String, AttributeValue> itemMap = Boolean.TRUE.equals(ignoreNulls) ?
transformItemToMapForUpdateExpression(itemMapImmutable) : itemMapImmutable;


Map<String, AttributeValue> itemMap = tableSchema.itemToMap(item, Boolean.TRUE.equals(ignoreNulls));
TableMetadata tableMetadata = tableSchema.tableMetadata();

WriteModification transformation =
Expand Down Expand Up @@ -150,58 +141,6 @@ public UpdateItemRequest generateRequest(TableSchema<T> tableSchema,

return requestBuilder.build();
}

/**
* Method checks if a nested object parameter requires an update
* If so flattens out nested params separated by "_NESTED_ATTR_UPDATE_"
* this is consumed by @link EnhancedClientUtils to form the appropriate UpdateExpression
*/
public Map<String, AttributeValue> transformItemToMapForUpdateExpression(Map<String, AttributeValue> itemToMap) {

Map<String, AttributeValue> nestedAttributes = new HashMap<>();

itemToMap.forEach((key, value) -> {
if (value.hasM() && isNotEmptyMap(value.m())) {
nestedAttributes.put(key, value);
}
});

if (!nestedAttributes.isEmpty()) {
Map<String, AttributeValue> itemToMapMutable = new HashMap<>(itemToMap);
nestedAttributes.forEach((key, value) -> {
itemToMapMutable.remove(key);
nestedItemToMap(itemToMapMutable, key, value);
});
return itemToMapMutable;
}

return itemToMap;
}

private Map<String, AttributeValue> nestedItemToMap(Map<String, AttributeValue> itemToMap,
String key,
AttributeValue attributeValue) {
attributeValue.m().forEach((mapKey, mapValue) -> {
String nestedAttributeKey = key + NESTED_OBJECT_UPDATE + mapKey;
if (attributeValueNonNullOrShouldWriteNull(mapValue)) {
if (mapValue.hasM()) {
nestedItemToMap(itemToMap, nestedAttributeKey, mapValue);
} else {
itemToMap.put(nestedAttributeKey, mapValue);
}
}
});
return itemToMap;
}

private boolean isNotEmptyMap(Map<String, AttributeValue> map) {
return !map.isEmpty() && map.values().stream()
.anyMatch(this::attributeValueNonNullOrShouldWriteNull);
}

private boolean attributeValueNonNullOrShouldWriteNull(AttributeValue attributeValue) {
return !isNullAttributeValue(attributeValue);
}

@Override
public UpdateItemEnhancedResponse<T> transformResponse(UpdateItemResponse response,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,13 @@
import static software.amazon.awssdk.enhanced.dynamodb.internal.EnhancedClientUtils.isNullAttributeValue;
import static software.amazon.awssdk.enhanced.dynamodb.internal.EnhancedClientUtils.keyRef;
import static software.amazon.awssdk.enhanced.dynamodb.internal.EnhancedClientUtils.valueRef;
import static software.amazon.awssdk.enhanced.dynamodb.internal.operations.UpdateItemOperation.NESTED_OBJECT_UPDATE;
import static software.amazon.awssdk.utils.CollectionUtils.filterMap;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import software.amazon.awssdk.annotations.SdkInternalApi;
import software.amazon.awssdk.enhanced.dynamodb.TableMetadata;
Expand All @@ -41,8 +39,6 @@
@SdkInternalApi
public final class UpdateExpressionUtils {

private static final Pattern PATTERN = Pattern.compile(NESTED_OBJECT_UPDATE);

private UpdateExpressionUtils() {
}

Expand Down Expand Up @@ -140,12 +136,9 @@ private static Function<String, String> behaviorBasedValue(UpdateBehavior update
/**
* Simple utility method that can create an ExpressionNames map based on a list of attribute names.
*/
private static Map<String, String> expressionNamesFor(String attributeNames) {
if (attributeNames.contains(NESTED_OBJECT_UPDATE)) {
return Arrays.stream(PATTERN.split(attributeNames)).distinct()
.collect(Collectors.toMap(EnhancedClientUtils::keyRef, Function.identity()));
}

return Collections.singletonMap(keyRef(attributeNames), attributeNames);
private static Map<String, String> expressionNamesFor(String... attributeNames) {
return Arrays.stream(attributeNames)
.collect(Collectors.toMap(EnhancedClientUtils::keyRef, Function.identity()));
}

}
Loading

0 comments on commit ec4c51b

Please sign in to comment.