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.converters.document;
17 
18 import java.time.Instant;
19 import java.util.HashMap;
20 import java.util.LinkedHashMap;
21 import java.util.List;
22 import java.util.Map;
23 import java.util.stream.Collectors;
24 import software.amazon.awssdk.core.SdkBytes;
25 import software.amazon.awssdk.enhanced.dynamodb.AttributeConverter;
26 import software.amazon.awssdk.enhanced.dynamodb.AttributeConverterProvider;
27 import software.amazon.awssdk.enhanced.dynamodb.AttributeValueType;
28 import software.amazon.awssdk.enhanced.dynamodb.EnhancedType;
29 import software.amazon.awssdk.enhanced.dynamodb.internal.converter.attribute.BigDecimalAttributeConverter;
30 import software.amazon.awssdk.enhanced.dynamodb.internal.converter.attribute.BooleanAttributeConverter;
31 import software.amazon.awssdk.enhanced.dynamodb.internal.converter.attribute.ByteArrayAttributeConverter;
32 import software.amazon.awssdk.enhanced.dynamodb.internal.converter.attribute.EnhancedAttributeValue;
33 import software.amazon.awssdk.enhanced.dynamodb.internal.converter.attribute.InstantAsStringAttributeConverter;
34 import software.amazon.awssdk.enhanced.dynamodb.internal.converter.attribute.ListAttributeConverter;
35 import software.amazon.awssdk.enhanced.dynamodb.internal.converter.attribute.LongAttributeConverter;
36 import software.amazon.awssdk.enhanced.dynamodb.internal.converter.attribute.SetAttributeConverter;
37 import software.amazon.awssdk.enhanced.dynamodb.internal.converter.attribute.StringAttributeConverter;
38 import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
39 
40 public class CustomClassForDocumentAttributeConverter implements AttributeConverter<CustomClassForDocumentAPI> {
41 
42     final static Integer DEFAULT_INCREMENT = 10;
43 
44     @Override
transformFrom(CustomClassForDocumentAPI input)45     public AttributeValue transformFrom(CustomClassForDocumentAPI input) {
46 
47         if(input == null){
48             return null;
49         }
50         Map<String, AttributeValue> attributeValueMap = new LinkedHashMap<>();
51         // Maintain the Alphabetical Order ,so that expected json matches
52         if(input.booleanSet() != null){
53             attributeValueMap.put("booleanSet",
54                                   AttributeValue.fromL(input.booleanSet().stream().map(b -> AttributeValue.fromBool(b)).collect(Collectors.toList())));
55         }
56         if(input.customClassList() != null){
57             attributeValueMap.put("customClassList", convertCustomList(input.customClassList()));
58         }
59         if (input.innerCustomClass() != null){
60             attributeValueMap.put("innerCustomClass", transformFrom(input.innerCustomClass()));
61         }
62         if(input.instantList() != null){
63             attributeValueMap.put("instantList", convertInstantList(input.instantList()));
64         }
65         if(input.longNumber() != null){
66             attributeValueMap.put("longNumber", AttributeValue.fromN(input.longNumber().toString()));
67         }
68         if(input.string() != null){
69             attributeValueMap.put("string", AttributeValue.fromS(input.string()));
70         }
71         if(input.stringSet() != null){
72             attributeValueMap.put("stringSet", AttributeValue.fromSs(input.stringSet().stream().collect(Collectors.toList())));
73         }
74         if(input.bigDecimalSet() != null){
75             attributeValueMap.put("stringSet",
76                                   AttributeValue.fromNs(input.bigDecimalSet().stream().map(b -> b.toString()).collect(Collectors.toList())));
77         }
78         return EnhancedAttributeValue.fromMap(attributeValueMap).toAttributeValue();
79     }
80 
81 
convertCustomList(List<CustomClassForDocumentAPI> customClassForDocumentAPIList)82     private static AttributeValue convertCustomList(List<CustomClassForDocumentAPI> customClassForDocumentAPIList){
83         List<AttributeValue> convertCustomList =
84             customClassForDocumentAPIList.stream().map(customClassForDocumentAPI -> create().transformFrom(customClassForDocumentAPI)).collect(Collectors.toList());
85         return AttributeValue.fromL(convertCustomList);
86 
87     }
88 
convertInstantList(List<Instant> customClassForDocumentAPIList)89     private static AttributeValue convertInstantList(List<Instant> customClassForDocumentAPIList){
90         return ListAttributeConverter.create(InstantAsStringAttributeConverter.create()).transformFrom(customClassForDocumentAPIList);
91     }
92 
93     @Override
transformTo(AttributeValue input)94     public CustomClassForDocumentAPI transformTo(AttributeValue input) {
95 
96         Map<String, AttributeValue> customAttr = input.m();
97 
98         CustomClassForDocumentAPI.Builder builder = CustomClassForDocumentAPI.builder();
99 
100         if (customAttr.get("aBoolean") != null) {
101             builder.aBoolean(BooleanAttributeConverter.create().transformTo(customAttr.get("aBoolean")));
102         }
103         if (customAttr.get("bigDecimal") != null) {
104             builder.bigDecimal(BigDecimalAttributeConverter.create().transformTo(customAttr.get("bigDecimal")));
105         }
106         if (customAttr.get("bigDecimalSet") != null) {
107             builder.bigDecimalSet(SetAttributeConverter.setConverter(BigDecimalAttributeConverter.create()).transformTo(customAttr.get("bigDecimalSet")));
108         }
109         if (customAttr.get("binarySet") != null) {
110             builder.binarySet(SetAttributeConverter.setConverter(ByteArrayAttributeConverter.create()).transformTo(customAttr.get("binarySet")));
111         }
112         if (customAttr.get("binary") != null) {
113             builder.binary(SdkBytes.fromByteArray(ByteArrayAttributeConverter.create().transformTo(customAttr.get("binary"))));
114         }
115         if (customAttr.get("booleanSet") != null) {
116             builder.booleanSet(SetAttributeConverter.setConverter(BooleanAttributeConverter.create()).transformTo(customAttr.get(
117                 "booleanSet")));
118         }
119         if (customAttr.get("customClassList") != null) {
120             builder.customClassList(ListAttributeConverter.create(create()).transformTo(customAttr.get("customClassList")));
121         }
122         if (customAttr.get("instantList") != null) {
123             builder.instantList(ListAttributeConverter.create(AttributeConverterProvider.defaultProvider().converterFor(EnhancedType.of(Instant.class))).transformTo(customAttr.get(
124                 "instantList")));
125         }
126         if (customAttr.get("innerCustomClass") != null) {
127             builder.innerCustomClass(create().transformTo(customAttr.get("innerCustomClass")));
128         }
129         if (customAttr.get("longNumber") != null) {
130             builder.longNumber(LongAttributeConverter.create().transformTo(customAttr.get("longNumber")));
131         }
132         if (customAttr.get("longSet") != null) {
133             builder.longSet(SetAttributeConverter.setConverter(LongAttributeConverter.create()).transformTo(customAttr.get(
134                 "longSet")));
135         }
136         if (customAttr.get("string") != null) {
137             builder.string(StringAttributeConverter.create().transformTo(customAttr.get("string")));
138         }
139         if (customAttr.get("stringSet") != null) {
140             builder.stringSet(SetAttributeConverter.setConverter(StringAttributeConverter.create()).transformTo(customAttr.get(
141                 "stringSet")));
142         }
143         return builder.build();
144     }
145 
create()146     public static CustomClassForDocumentAttributeConverter create() {
147         return new CustomClassForDocumentAttributeConverter();
148     }
149 
150     @Override
type()151     public EnhancedType<CustomClassForDocumentAPI> type() {
152         return EnhancedType.of(CustomClassForDocumentAPI.class);
153     }
154 
155     @Override
attributeValueType()156     public AttributeValueType attributeValueType() {
157         return AttributeValueType.M;
158     }
159 
160 
161 }
162