Skip to content

Commit 9c50013

Browse files
committed
Adding ItemBuilder that can be used to build a Map<String, AttributeValue> for use in PutItemRequest for example.
1 parent 32a5c48 commit 9c50013

File tree

2 files changed

+520
-0
lines changed
  • services/dynamodb/src
    • main/java/software/amazon/awssdk/services/dynamodb/model
    • test/java/software/amazon/awssdk/services/dynamodb/model

2 files changed

+520
-0
lines changed
Lines changed: 379 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,379 @@
1+
/*
2+
* Copyright 2010-2017 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.services.dynamodb.model;
17+
18+
import static java.util.stream.Collectors.toList;
19+
import static software.amazon.awssdk.utils.CollectionUtils.toMap;
20+
21+
import java.nio.ByteBuffer;
22+
import java.util.Arrays;
23+
import java.util.Collection;
24+
import java.util.HashMap;
25+
import java.util.List;
26+
import java.util.Map;
27+
import java.util.stream.Collectors;
28+
import software.amazon.awssdk.annotations.ReviewBeforeRelease;
29+
import software.amazon.awssdk.utils.builder.SdkBuilder;
30+
31+
/**
32+
* Used to build a DynamoDB item map.
33+
*
34+
* For example to pass to a {@link PutItemRequest.Builder#item(Map)}.
35+
*/
36+
@ReviewBeforeRelease("May want to do this a different way")
37+
public final class Item extends HashMap<String, AttributeValue> {
38+
39+
private Item(Builder builder) {
40+
putAll(builder.item);
41+
}
42+
43+
/**
44+
* Create a new instance of the {@link Builder}.
45+
*
46+
* @return a new instance of the {@link Builder}
47+
*/
48+
public static Builder builder() {
49+
return new Builder();
50+
}
51+
52+
public static class Builder implements SdkBuilder<Builder, Item> {
53+
private final Map<String, AttributeValue> item = new HashMap<>();
54+
55+
private Builder() {
56+
}
57+
58+
/**
59+
* Build a {@link Map} representing a DyanmoDB item.
60+
*
61+
* @return a {@link Map} representing a DyanmoDB item
62+
*/
63+
@Override
64+
public Item build() {
65+
return new Item(this);
66+
}
67+
68+
/**
69+
* Adds an {@link AttributeValue} representing a String to the item with the specified key.
70+
*
71+
* Equivalent of:
72+
* <pre><code>
73+
* itemMap.put(key, AttributeValue.builder().s(stringValue).build());
74+
* </code></pre>
75+
*
76+
* @param key the key of this attribute
77+
* @param stringValue the string value of the attribute
78+
* @return the builder for method chaining
79+
*/
80+
public Builder attribute(String key, String stringValue) {
81+
item.put(key, AttributeValue.builder().s(stringValue).build());
82+
return this;
83+
}
84+
85+
/**
86+
* Adds an {@link AttributeValue} representing a Boolean to the item with the specified key.
87+
*
88+
* Equivalent of:
89+
* <pre><code>
90+
* itemMap.put(key, AttributeValue.builder().bool(booleanValue).build());
91+
* </code></pre>
92+
*
93+
* @param key the key of this attribute
94+
* @param booleanValue the boolean value of the attribute
95+
* @return the builder for method chaining
96+
*/
97+
public Builder attribute(String key, Boolean booleanValue) {
98+
item.put(key, AttributeValue.builder().bool(booleanValue).build());
99+
return this;
100+
}
101+
102+
/**
103+
* Adds an {@link AttributeValue} representing a Number to the item with the specified key.
104+
*
105+
* Equivalent of:
106+
* <pre><code>
107+
* itemMap.put(key, AttributeValue.builder().n(String.valueOf(numericValue)).build());
108+
* </code></pre>
109+
*
110+
* @param key the key of this attribute
111+
* @param numericValue the numeric value of the attribute
112+
* @return the builder for method chaining
113+
*/
114+
public Builder attribute(String key, Number numericValue) {
115+
item.put(key, AttributeValue.builder().n(String.valueOf(numericValue)).build());
116+
return this;
117+
}
118+
119+
/**
120+
* Adds an {@link AttributeValue} representing binary data to the item with the specified key.
121+
*
122+
* Equivalent of:
123+
* <pre><code>
124+
* itemMap.put(key, AttributeValue.builder().b(ByteBuffer.wrap(binaryValue)).build());
125+
* </code></pre>
126+
*
127+
* @param key the key of this attribute
128+
* @param binaryValue the binary value of the attribute
129+
* @return the builder for method chaining
130+
*/
131+
public Builder attribute(String key, byte[] binaryValue) {
132+
return attribute(key, ByteBuffer.wrap(binaryValue));
133+
}
134+
135+
/**
136+
* Adds an {@link AttributeValue} representing binary data to the item with the specified key.
137+
*
138+
* Equivalent of:
139+
* <pre><code>
140+
* itemMap.put(key, AttributeValue.builder().b(binaryValue).build());
141+
* </code></pre>
142+
*
143+
* @param key the key of this attribute
144+
* @param binaryValue the binary value of the attribute
145+
* @return the builder for method chaining
146+
*/
147+
public Builder attribute(String key, ByteBuffer binaryValue) {
148+
item.put(key, AttributeValue.builder().b(binaryValue).build());
149+
return this;
150+
}
151+
152+
/**
153+
* Adds an {@link AttributeValue} representing a list of AttributeValues to the item with the specified key.
154+
*
155+
* This will attempt to infer the of of the {@link AttributeValue} for each given {@link Object} in the list
156+
* based on the type. Supported types are:
157+
* <ul>
158+
* <li><strong>{@link AttributeValue}</strong> which is unaltered</li>
159+
* <li><strong>{@link String}</strong> becomes {@link AttributeValue#s()}</li>
160+
* <li><strong>{@link Number}</strong> (and anything that can be automatically boxed to {@link Number} including
161+
* int, long, float etc.) becomes {@link AttributeValue#n()}</li>
162+
* <li><strong>{@link Boolean}</strong> (and bool) becomes {@link AttributeValue#bool()}</li>
163+
* <li><strong>byte[]</strong> becomes {@link AttributeValue#b()}</li>
164+
* <li><strong>{@link ByteBuffer}</strong> becomes {@link AttributeValue#b()}</li>
165+
* <li><strong>{@link List}&lt;Object&gt;</strong> (where the containing objects are one of the types in
166+
* this list) becomes {@link AttributeValue#l()}</li>
167+
* <li><strong>{@link Map}&lt;String, Object&gt;</strong> (where the containing object values are one of the types
168+
* in this list) becomes {@link AttributeValue#m()}</li>
169+
* </ul>
170+
*
171+
* @param key the key of this attribute
172+
* @param values the object values
173+
* @return the builder for method chaining
174+
*/
175+
public Builder attribute(String key, List<?> values) {
176+
item.put(key, fromObject(values));
177+
return this;
178+
}
179+
180+
/**
181+
* Adds an {@link AttributeValue} representing a map of string to AttributeValues to the item with the specified key.
182+
*
183+
* This will attempt to infer the most appropriate {@link AttributeValue} for each given {@link Object} value in the map
184+
* based on the type. Supported types are:
185+
* <ul>
186+
* <li><strong>{@link AttributeValue}</strong> which is unaltered</li>
187+
* <li><strong>{@link String}</strong> becomes {@link AttributeValue#s()}</li>
188+
* <li><strong>{@link Number}</strong> (and anything that can be automatically boxed to {@link Number} including
189+
* int, long, float etc.) becomes {@link AttributeValue#n()}</li>
190+
* <li><strong>{@link Boolean}</strong> (and bool) becomes {@link AttributeValue#bool()}</li>
191+
* <li><strong>byte[]</strong> becomes {@link AttributeValue#b()}</li>
192+
* <li><strong>{@link ByteBuffer}</strong> becomes {@link AttributeValue#b()}</li>
193+
* <li><strong>{@link List}&lt;Object&gt;</strong> (where the containing objects are one of the types in
194+
* this list) becomes {@link AttributeValue#l()}</li>
195+
* <li><strong>{@link Map}&lt;String, Object&gt;</strong> (where the containing object values are one of the types
196+
* in this list) becomes {@link AttributeValue#m()}</li>
197+
* </ul>
198+
*
199+
* @param key the key of this attribute
200+
* @param values the map of key to object
201+
* @return the builder for method chaining
202+
*/
203+
public Builder attribute(String key, Map<String, ?> values) {
204+
item.put(key, fromObject(values));
205+
return this;
206+
}
207+
208+
/**
209+
* Adds an {@link AttributeValue} representing a list of strings to the item with the specified key.
210+
*
211+
* Equivalent of:
212+
* <pre><code>
213+
* itemMap.put(key, AttributeValue.builder().ss(stringValue1, stringValue2, ...).build());
214+
* </code></pre>
215+
*
216+
* @param key the key of this attribute
217+
* @param stringValues the string values of the attribute
218+
* @return the builder for method chaining
219+
*/
220+
public Builder strings(String key, String... stringValues) {
221+
return strings(key, Arrays.asList(stringValues));
222+
}
223+
224+
/**
225+
* Adds an {@link AttributeValue} representing a list of strings to the item with the specified key.
226+
*
227+
* Equivalent of:
228+
* <pre><code>
229+
* itemMap.put(key, AttributeValue.builder().ss(stringValues).build());
230+
* </code></pre>
231+
*
232+
* @param key the key of this attribute
233+
* @param stringValues the string values of the attribute
234+
* @return the builder for method chaining
235+
*/
236+
public Builder strings(String key, Collection<String> stringValues) {
237+
item.put(key, AttributeValue.builder().ss(stringValues).build());
238+
return this;
239+
}
240+
241+
/**
242+
* Adds an {@link AttributeValue} representing a list of numbers to the item with the specified key.
243+
*
244+
* Equivalent of:
245+
* <pre><code>
246+
* itemMap.put(key, AttributeValue.builder().ns(numberValues1, numberValues2, ...).build());
247+
* </code></pre>
248+
*
249+
* @param key the key of this attribute
250+
* @param numberValues the number values of the attribute
251+
* @return the builder for method chaining
252+
*/
253+
public Builder numbers(String key, Number... numberValues) {
254+
return numbers(key, Arrays.asList(numberValues));
255+
}
256+
257+
/**
258+
* Adds an {@link AttributeValue} representing a list of numbers to the item with the specified key.
259+
*
260+
* Equivalent of:
261+
* <pre><code>
262+
* itemMap.put(key, AttributeValue.builder().ns(numberValues).build());
263+
* </code></pre>
264+
*
265+
* @param key the key of this attribute
266+
* @param numberValues the number values of the attribute
267+
* @return the builder for method chaining
268+
*/
269+
public Builder numbers(String key, Collection<? extends Number> numberValues) {
270+
item.put(key, AttributeValue.builder().ns(numberValues.stream().map(String::valueOf).collect(toList())).build());
271+
return this;
272+
}
273+
274+
/**
275+
* Adds an {@link AttributeValue} representing a list of binary data to the item with the specified key.
276+
*
277+
* Equivalent of:
278+
* <pre><code>
279+
* itemMap.put(key, AttributeValue.builder().bs(Arrays.stream(byteArrays)
280+
* .map(ByteBuffer::wrap)
281+
* .collect(Collectors.toList())).build());
282+
* </code></pre>
283+
*
284+
* @param key the key of this attribute
285+
* @param byteArrays the binary values of the attribute
286+
* @return the builder for method chaining
287+
*/
288+
public Builder byteArrays(String key, byte[]... byteArrays) {
289+
return byteArrays(key, Arrays.asList(byteArrays));
290+
}
291+
292+
/**
293+
* Adds an {@link AttributeValue} representing a list of binary data to the item with the specified key.
294+
*
295+
* Equivalent of:
296+
* <pre><code>
297+
* itemMap.put(key, AttributeValue.builder().bs(byteArrays.stream()
298+
* .map(ByteBuffer::wrap)
299+
* .collect(Collectors.toList())).build());
300+
* </code></pre>
301+
*
302+
* @param key the key of this attribute
303+
* @param byteArrays the binary values of the attribute
304+
* @return the builder for method chaining
305+
*/
306+
public Builder byteArrays(String key, Collection<byte[]> byteArrays) {
307+
return byteBuffers(key, byteArrays.stream().map(ByteBuffer::wrap).collect(Collectors.toList()));
308+
}
309+
310+
/**
311+
* Adds an {@link AttributeValue} representing a list of binary data to the item with the specified key.
312+
*
313+
* Equivalent of:
314+
* <pre><code>
315+
* itemMap.put(key, AttributeValue.builder().bs(binaryValues1, binaryValues2, ...)).build());
316+
* </code></pre>
317+
*
318+
* @param key the key of this attribute
319+
* @param byteArrays the binary values of the attribute
320+
* @return the builder for method chaining
321+
*/
322+
public Builder byteBuffers(String key, ByteBuffer... binaryValues) {
323+
return byteBuffers(key, Arrays.asList(binaryValues));
324+
}
325+
326+
/**
327+
* Adds an {@link AttributeValue} representing a list of binary data to the item with the specified key.
328+
*
329+
* Equivalent of:
330+
* <pre><code>
331+
* itemMap.put(key, AttributeValue.builder().bs(binaryValues).build());
332+
* </code></pre>
333+
*
334+
* @param key the key of this attribute
335+
* @param byteArrays the binary values of the attribute
336+
* @return the builder for method chaining
337+
*/
338+
public Builder byteBuffers(String key, Collection<? extends ByteBuffer> binaryValues) {
339+
item.put(key, AttributeValue.builder().bs(binaryValues.stream().collect(toList())).build());
340+
return this;
341+
}
342+
343+
private static AttributeValue fromObject(Object object) {
344+
if (object instanceof AttributeValue) {
345+
return (AttributeValue) object;
346+
}
347+
if (object instanceof String) {
348+
return AttributeValue.builder().s((String) object).build();
349+
}
350+
if (object instanceof Number) {
351+
return AttributeValue.builder().n(String.valueOf((Number) object)).build();
352+
}
353+
if (object instanceof byte[]) {
354+
return AttributeValue.builder().b(ByteBuffer.wrap((byte[]) object)).build();
355+
}
356+
if (object instanceof ByteBuffer) {
357+
return AttributeValue.builder().b((ByteBuffer) object).build();
358+
}
359+
if (object instanceof Boolean) {
360+
return AttributeValue.builder().bool((Boolean) object).build();
361+
}
362+
if (object instanceof List) {
363+
List<AttributeValue> attributeValues = ((List<?>) object).stream()
364+
.map(Builder::fromObject)
365+
.collect(toList());
366+
return AttributeValue.builder().l(attributeValues).build();
367+
}
368+
if (object instanceof Map) {
369+
Map<String, AttributeValue> attributeValues =
370+
((Map<String, ?>) object).entrySet()
371+
.stream()
372+
.map(e -> new SimpleImmutableEntry<>(e.getKey(), fromObject(e.getValue())))
373+
.collect(toMap());
374+
return AttributeValue.builder().m(attributeValues).build();
375+
}
376+
throw new IllegalArgumentException("Unsupported type: " + object.getClass());
377+
}
378+
}
379+
}

0 commit comments

Comments
 (0)