Skip to content

Commit 642ae05

Browse files
authored
UpdateExpression API (#2900)
UpdateExpression API
1 parent d976753 commit 642ae05

File tree

11 files changed

+1496
-0
lines changed

11 files changed

+1496
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package software.amazon.awssdk.enhanced.dynamodb.update;
17+
18+
import java.util.Collections;
19+
import java.util.HashMap;
20+
import java.util.Map;
21+
import software.amazon.awssdk.annotations.SdkPublicApi;
22+
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
23+
import software.amazon.awssdk.utils.Validate;
24+
25+
/**
26+
* A representation of a single {@link UpdateExpression} ADD action.
27+
* <p>
28+
* At a minimum, this action must contain a path string referencing the attribute that should be acted upon and a value string
29+
* referencing the value to be added to the attribute. The value should be substituted with tokens using the
30+
* ':value_token' syntax and values associated with the token must be explicitly added to the expressionValues map.
31+
* Consult the DynamoDB UpdateExpression documentation for details on this action.
32+
* <p>
33+
* Optionally, attribute names can be substituted with tokens using the '#name_token' syntax. If tokens are used in the
34+
* expression then the names associated with those tokens must be explicitly added to the expressionNames map
35+
* that is also stored on this object.
36+
* <p>
37+
* Example:-
38+
* <pre>
39+
* {@code
40+
* AddUpdateAction addAction = AddUpdateAction.builder()
41+
* .path("#a")
42+
* .value(":b")
43+
* .putExpressionName("#a", "attributeA")
44+
* .putExpressionValue(":b", myAttributeValue)
45+
* .build();
46+
* }
47+
* </pre>
48+
*/
49+
@SdkPublicApi
50+
public final class AddUpdateAction implements UpdateAction {
51+
52+
private final String path;
53+
private final String value;
54+
private final Map<String, String> expressionNames;
55+
private final Map<String, AttributeValue> expressionValues;
56+
57+
private AddUpdateAction(Builder builder) {
58+
this.path = Validate.paramNotNull(builder.path, "path");
59+
this.value = Validate.paramNotNull(builder.value, "value");
60+
this.expressionValues = wrapSecure(Validate.paramNotNull(builder.expressionValues, "expressionValues"));
61+
this.expressionNames = wrapSecure(builder.expressionNames != null ? builder.expressionNames : new HashMap<>());
62+
}
63+
64+
private static <T, U> Map<T, U> wrapSecure(Map<T, U> map) {
65+
return Collections.unmodifiableMap(new HashMap<>(map));
66+
}
67+
68+
/**
69+
* Constructs a new builder for {@link AddUpdateAction}.
70+
*
71+
* @return a new builder.
72+
*/
73+
public static Builder builder() {
74+
return new Builder();
75+
}
76+
77+
public String path() {
78+
return path;
79+
}
80+
81+
public String value() {
82+
return value;
83+
}
84+
85+
public Map<String, String> expressionNames() {
86+
return expressionNames;
87+
}
88+
89+
public Map<String, AttributeValue> expressionValues() {
90+
return expressionValues;
91+
}
92+
93+
@Override
94+
public boolean equals(Object o) {
95+
if (this == o) {
96+
return true;
97+
}
98+
if (o == null || getClass() != o.getClass()) {
99+
return false;
100+
}
101+
102+
AddUpdateAction that = (AddUpdateAction) o;
103+
104+
if (path != null ? ! path.equals(that.path) : that.path != null) {
105+
return false;
106+
}
107+
if (value != null ? ! value.equals(that.value) : that.value != null) {
108+
return false;
109+
}
110+
if (expressionValues != null ? ! expressionValues.equals(that.expressionValues) :
111+
that.expressionValues != null) {
112+
return false;
113+
}
114+
return expressionNames != null ? expressionNames.equals(that.expressionNames) : that.expressionNames == null;
115+
}
116+
117+
@Override
118+
public int hashCode() {
119+
int result = path != null ? path.hashCode() : 0;
120+
result = 31 * result + (value != null ? value.hashCode() : 0);
121+
result = 31 * result + (expressionValues != null ? expressionValues.hashCode() : 0);
122+
result = 31 * result + (expressionNames != null ? expressionNames.hashCode() : 0);
123+
return result;
124+
}
125+
126+
/**
127+
* A builder for {@link AddUpdateAction}
128+
*/
129+
public static final class Builder {
130+
131+
private String path;
132+
private String value;
133+
private Map<String, String> expressionNames;
134+
private Map<String, AttributeValue> expressionValues;
135+
136+
/**
137+
* A string expression representing the attribute to be acted upon
138+
*/
139+
public Builder path(String path) {
140+
this.path = path;
141+
return this;
142+
}
143+
144+
/**
145+
* A string expression representing the value used in the action. The value must be represented as an
146+
* expression attribute value token.
147+
*/
148+
public Builder value(String value) {
149+
this.value = value;
150+
return this;
151+
}
152+
153+
/**
154+
* Sets the 'expression values' token map that maps from value references (expression attribute values) to
155+
* DynamoDB AttributeValues, overriding any existing values.
156+
* The value reference should always start with ':' (colon).
157+
*
158+
* @see #putExpressionValue(String, AttributeValue)
159+
*/
160+
public Builder expressionValues(Map<String, AttributeValue> expressionValues) {
161+
this.expressionValues = expressionValues == null ? null : new HashMap<>(expressionValues);
162+
return this;
163+
}
164+
165+
/**
166+
* Adds a single element to the 'expression values' token map.
167+
*
168+
* @see #expressionValues(Map)
169+
*/
170+
public Builder putExpressionValue(String key, AttributeValue value) {
171+
if (this.expressionValues == null) {
172+
this.expressionValues = new HashMap<>();
173+
}
174+
175+
this.expressionValues.put(key, value);
176+
return this;
177+
}
178+
179+
/**
180+
* Sets the optional 'expression names' token map, overriding any existing values. Use if the attribute
181+
* references in the path expression are token ('expression attribute names') prepended with the
182+
* '#' (pound) sign. It should map from token name to real attribute name.
183+
*
184+
* @see #putExpressionName(String, String)
185+
*/
186+
public Builder expressionNames(Map<String, String> expressionNames) {
187+
this.expressionNames = expressionNames == null ? null : new HashMap<>(expressionNames);
188+
return this;
189+
}
190+
191+
/**
192+
* Adds a single element to the optional 'expression names' token map.
193+
*
194+
* @see #expressionNames(Map)
195+
*/
196+
public Builder putExpressionName(String key, String value) {
197+
if (this.expressionNames == null) {
198+
this.expressionNames = new HashMap<>();
199+
}
200+
this.expressionNames.put(key, value);
201+
return this;
202+
}
203+
204+
/**
205+
* Builds an {@link AddUpdateAction} based on the values stored in this builder.
206+
*/
207+
public AddUpdateAction build() {
208+
return new AddUpdateAction(this);
209+
}
210+
}
211+
}

0 commit comments

Comments
 (0)