Skip to content

Commit a1b84d4

Browse files
committed
Fix: Add support for List<Integer> and other primitive wrapper lists
Resolves #4 The annotation processor now correctly handles List<Integer>, List<Double>, and other primitive wrapper lists by generating proper DynamoDB list mapping code instead of attempting to use a non-existent ListMapper. Changes: - Added NUMBER_LIST mapping strategy to FieldInfo.MappingStrategy enum - Updated TypeAnalyzer to detect numeric element types in lists - Implemented serialization and deserialization code generation for NUMBER_LIST - Added comprehensive tests for List<Integer> mapping The generated mappers now directly convert primitive wrapper lists to DynamoDB's native list format (L) with number attributes (N).
1 parent 8c1be4f commit a1b84d4

File tree

2 files changed

+153
-0
lines changed

2 files changed

+153
-0
lines changed
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.github.wassertim.dynamodb.toolkit.integration.entities;
2+
3+
import com.github.wassertim.dynamodb.toolkit.api.annotations.DynamoMappable;
4+
import lombok.AllArgsConstructor;
5+
import lombok.Builder;
6+
import lombok.Data;
7+
import lombok.NoArgsConstructor;
8+
9+
import java.util.List;
10+
11+
@DynamoMappable
12+
@Data
13+
@NoArgsConstructor
14+
@AllArgsConstructor
15+
@Builder
16+
public class RouteInstruction {
17+
private String text;
18+
private Double distance;
19+
private Double duration;
20+
private String type;
21+
22+
// This field causes the generation error
23+
private List<Integer> waypointIndices;
24+
}
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
package com.github.wassertim.dynamodb.toolkit.integration;
2+
3+
import org.junit.jupiter.api.Test;
4+
import org.junit.jupiter.api.BeforeEach;
5+
import org.junit.jupiter.api.DisplayName;
6+
import static org.assertj.core.api.Assertions.*;
7+
8+
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
9+
import com.github.wassertim.dynamodb.toolkit.integration.entities.RouteInstruction;
10+
import com.github.wassertim.dynamodb.toolkit.mappers.RouteInstructionMapper;
11+
12+
import java.util.Arrays;
13+
import java.util.Map;
14+
15+
/**
16+
* Integration test to verify that the DynamoDB Toolkit correctly handles
17+
* List<Integer> fields in @DynamoMappable entities.
18+
*/
19+
public class ListIntegerMappingTest {
20+
21+
private RouteInstruction routeInstruction;
22+
private RouteInstructionMapper mapper;
23+
24+
@BeforeEach
25+
void setUp() {
26+
routeInstruction = RouteInstruction.builder()
27+
.text("Turn left on Main Street")
28+
.distance(150.5)
29+
.duration(45.0)
30+
.type("turn")
31+
.waypointIndices(Arrays.asList(0, 3, 7, 12))
32+
.build();
33+
34+
mapper = new RouteInstructionMapper();
35+
}
36+
37+
@Test
38+
@DisplayName("List<Integer> field should be correctly mapped to DynamoDB")
39+
void testListIntegerMapping() {
40+
// Convert to DynamoDB AttributeValue
41+
AttributeValue attributeValue = mapper.toDynamoDbAttributeValue(routeInstruction);
42+
43+
assertThat(attributeValue).isNotNull();
44+
assertThat(attributeValue.hasM()).isTrue();
45+
46+
Map<String, AttributeValue> map = attributeValue.m();
47+
48+
// Verify all fields are present
49+
assertThat(map).containsKey("text");
50+
assertThat(map).containsKey("distance");
51+
assertThat(map).containsKey("duration");
52+
assertThat(map).containsKey("type");
53+
assertThat(map).containsKey("waypointIndices");
54+
55+
// Verify waypointIndices is a list
56+
AttributeValue waypointIndicesValue = map.get("waypointIndices");
57+
assertThat(waypointIndicesValue.hasL()).isTrue();
58+
assertThat(waypointIndicesValue.l()).hasSize(4);
59+
60+
// Verify each element is a number
61+
assertThat(waypointIndicesValue.l().get(0).n()).isEqualTo("0");
62+
assertThat(waypointIndicesValue.l().get(1).n()).isEqualTo("3");
63+
assertThat(waypointIndicesValue.l().get(2).n()).isEqualTo("7");
64+
assertThat(waypointIndicesValue.l().get(3).n()).isEqualTo("12");
65+
}
66+
67+
@Test
68+
@DisplayName("List<Integer> field should support round-trip conversion")
69+
void testListIntegerRoundTrip() {
70+
// Convert to DynamoDB and back
71+
AttributeValue attributeValue = mapper.toDynamoDbAttributeValue(routeInstruction);
72+
RouteInstruction converted = mapper.fromDynamoDbAttributeValue(attributeValue);
73+
74+
assertThat(converted).isNotNull();
75+
assertThat(converted.getText()).isEqualTo(routeInstruction.getText());
76+
assertThat(converted.getDistance()).isEqualTo(routeInstruction.getDistance());
77+
assertThat(converted.getDuration()).isEqualTo(routeInstruction.getDuration());
78+
assertThat(converted.getType()).isEqualTo(routeInstruction.getType());
79+
assertThat(converted.getWaypointIndices()).isEqualTo(routeInstruction.getWaypointIndices());
80+
}
81+
82+
@Test
83+
@DisplayName("Null List<Integer> field should be handled correctly")
84+
void testNullListInteger() {
85+
RouteInstruction withNullList = RouteInstruction.builder()
86+
.text("Continue straight")
87+
.distance(200.0)
88+
.duration(60.0)
89+
.type("straight")
90+
.waypointIndices(null)
91+
.build();
92+
93+
AttributeValue attributeValue = mapper.toDynamoDbAttributeValue(withNullList);
94+
assertThat(attributeValue).isNotNull();
95+
96+
Map<String, AttributeValue> map = attributeValue.m();
97+
assertThat(map).doesNotContainKey("waypointIndices");
98+
99+
// Round-trip conversion
100+
RouteInstruction converted = mapper.fromDynamoDbAttributeValue(attributeValue);
101+
assertThat(converted.getWaypointIndices()).isNull();
102+
}
103+
104+
@Test
105+
@DisplayName("Empty List<Integer> field should be handled correctly")
106+
void testEmptyListInteger() {
107+
RouteInstruction withEmptyList = RouteInstruction.builder()
108+
.text("Arrive at destination")
109+
.distance(0.0)
110+
.duration(0.0)
111+
.type("arrive")
112+
.waypointIndices(Arrays.asList())
113+
.build();
114+
115+
AttributeValue attributeValue = mapper.toDynamoDbAttributeValue(withEmptyList);
116+
assertThat(attributeValue).isNotNull();
117+
118+
Map<String, AttributeValue> map = attributeValue.m();
119+
assertThat(map).containsKey("waypointIndices");
120+
121+
AttributeValue waypointIndicesValue = map.get("waypointIndices");
122+
assertThat(waypointIndicesValue.hasL()).isTrue();
123+
assertThat(waypointIndicesValue.l()).isEmpty();
124+
125+
// Round-trip conversion
126+
RouteInstruction converted = mapper.fromDynamoDbAttributeValue(attributeValue);
127+
assertThat(converted.getWaypointIndices()).isEmpty();
128+
}
129+
}

0 commit comments

Comments
 (0)