Skip to content

Commit 75b386b

Browse files
committed
Add Java 21 LTS compatibility and fix JavaPoet import generation
Major improvements to ensure production readiness and compatibility: **Java 21 LTS Migration:** - Update devcontainer from Java 25 to Java 21 LTS for better Lombok compatibility - Resolve Java 25 + Lombok compatibility issues (ExceptionInInitializerError) - Add Lombok to annotation processor paths in integration tests **JavaPoet Import Generation Fixes:** - Fix enum type imports: WaypointType, RouteType, Difficulty, GeometryType now properly imported - Fix complex object imports: Waypoint class properly imported in complex list mappings - Update createEnumParseBlock() to use ClassName instead of String for proper type references - Add extractListElementQualifiedType() method for complex object import resolution **Code Generation Quality Improvements:** - Fix primitive field statement termination (wrap in proper CodeBlock statements) - Fix stream operation chaining for nested number lists and complex lists - Improve JavaPoet code structure with proper .add() vs .addStatement() usage - Ensure proper semicolon placement and statement formatting **Real-World Validation:** - Add comprehensive Tourino domain classes for integration testing - Add TourinoMappingTest with 7 validation scenarios - Add JavaPoetFixValidationTest with specific fix validation - Successfully tested with actual Tourino backend compilation - All generated mappers compile without errors and include correct imports **Testing & Integration:** - Update test paths to use correct generated-sources location - Adjust test expectations for improved code generation output - 23 tests passing with full validation coverage Verified working in production environment with Tourino backend.
1 parent e0c6889 commit 75b386b

File tree

15 files changed

+779
-32
lines changed

15 files changed

+779
-32
lines changed

.devcontainer/Dockerfile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
# Use official Maven image with Eclipse Temurin Java 25
2-
FROM maven:3.9.11-eclipse-temurin-25
1+
# Use official Maven image with Eclipse Temurin Java 21 LTS
2+
FROM maven:3.9.11-eclipse-temurin-21
33

44
# Install unzip, zsh and other tools needed
55
RUN apt-get update && apt-get install -y \

integration-tests/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,11 @@
9090
<artifactId>dynamodb-toolkit</artifactId>
9191
<version>${dynamodb-toolkit.version}</version>
9292
</path>
93+
<path>
94+
<groupId>org.projectlombok</groupId>
95+
<artifactId>lombok</artifactId>
96+
<version>${lombok.version}</version>
97+
</path>
9398
</annotationProcessorPaths>
9499
</configuration>
95100
</plugin>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package com.tourino.domain;
2+
3+
/**
4+
* Enumeration of route difficulty levels for user classification.
5+
*/
6+
public enum Difficulty {
7+
EASY("Easy - suitable for beginners"),
8+
MODERATE("Moderate - some experience required"),
9+
HARD("Hard - experienced users only"),
10+
EXPERT("Expert - professional level");
11+
12+
private final String description;
13+
14+
Difficulty(String description) {
15+
this.description = description;
16+
}
17+
18+
/**
19+
* Gets the human-readable description of this difficulty level.
20+
* @return the difficulty description
21+
*/
22+
public String getDescription() {
23+
return description;
24+
}
25+
}
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
package com.tourino.domain;
2+
3+
import com.github.wassertim.dynamodb.toolkit.api.annotations.AttributeType;
4+
import com.github.wassertim.dynamodb.toolkit.api.annotations.PartitionKey;
5+
import com.github.wassertim.dynamodb.toolkit.api.annotations.SortKey;
6+
import com.github.wassertim.dynamodb.toolkit.api.annotations.Table;
7+
import com.github.wassertim.dynamodb.toolkit.api.annotations.DynamoMappable;
8+
import lombok.AllArgsConstructor;
9+
import lombok.Builder;
10+
import lombok.Data;
11+
import lombok.NoArgsConstructor;
12+
13+
import java.time.Instant;
14+
import java.util.List;
15+
16+
/**
17+
* Main user route entity for persistent route management.
18+
* Represents a user's saved route with full lifecycle support and rich metadata.
19+
*/
20+
@DynamoMappable
21+
@Data
22+
@NoArgsConstructor
23+
@AllArgsConstructor
24+
@Builder(toBuilder = true)
25+
@Table(name = "routes")
26+
public class Route {
27+
28+
/**
29+
* User ID - partition key for data isolation and efficient queries.
30+
*/
31+
@PartitionKey(attributeType = AttributeType.STRING)
32+
private String userId;
33+
34+
/**
35+
* Unique route identifier - UUID for global uniqueness.
36+
*/
37+
@SortKey(attributeType = AttributeType.STRING)
38+
private String routeId;
39+
40+
/**
41+
* User-defined route name (3-100 characters).
42+
*/
43+
private String name;
44+
45+
/**
46+
* Optional description providing additional context about the route.
47+
*/
48+
private String description;
49+
50+
/**
51+
* Route type classification for filtering and organization.
52+
*/
53+
private RouteType type;
54+
55+
/**
56+
* Difficulty level assessment for user guidance.
57+
*/
58+
private Difficulty difficulty;
59+
60+
/**
61+
* The routing profile used for route calculation (e.g., "cycling-regular", "walking", "driving-car").
62+
* This preserves the exact calculation parameters used and ensures route consistency.
63+
*/
64+
private String routingProfile;
65+
66+
/**
67+
* Ordered collection of waypoints defining the route path.
68+
*/
69+
private List<Waypoint> waypoints;
70+
71+
/**
72+
* Route geometry containing path coordinates and shape data.
73+
*/
74+
private RouteGeometry routeGeometry;
75+
76+
/**
77+
* Calculated route statistics and measurements.
78+
*/
79+
private RouteMetadata metadata;
80+
81+
82+
/**
83+
* Route creation timestamp for audit trail.
84+
*/
85+
private Instant createdAt;
86+
87+
/**
88+
* Last modification timestamp for change tracking.
89+
*/
90+
private Instant updatedAt;
91+
92+
/**
93+
* Last accessed timestamp for usage analytics and recent route queries.
94+
*/
95+
private Instant lastUsed;
96+
97+
/**
98+
* User-defined tags for route categorization and search.
99+
*/
100+
private List<String> tags;
101+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package com.tourino.domain;
2+
3+
import com.tourino.domain.enums.GeometryType;
4+
import com.github.wassertim.dynamodb.toolkit.api.annotations.DynamoMappable;
5+
import lombok.Builder;
6+
import lombok.Data;
7+
8+
import java.util.List;
9+
10+
/**
11+
* Domain value object representing route geometry as GeoJSON LineString.
12+
*/
13+
@DynamoMappable
14+
@Data
15+
@Builder
16+
public class RouteGeometry {
17+
18+
/**
19+
* GeoJSON type (always LINESTRING for routes).
20+
*/
21+
@Builder.Default
22+
private final GeometryType type = GeometryType.LINESTRING;
23+
24+
/**
25+
* Array of coordinate pairs [longitude, latitude] defining the route path.
26+
*/
27+
private final List<List<Double>> coordinates;
28+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package com.tourino.domain;
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+
/**
10+
* Value object containing route calculation metadata and statistics.
11+
* Stores numeric values for calculations, not formatted strings.
12+
*/
13+
@DynamoMappable
14+
@Data
15+
@NoArgsConstructor
16+
@AllArgsConstructor
17+
@Builder
18+
public class RouteMetadata {
19+
20+
/**
21+
* Total route distance in meters.
22+
*/
23+
private Double distance;
24+
25+
/**
26+
* Total route duration in seconds.
27+
*/
28+
private Double duration;
29+
30+
/**
31+
* Total elevation gain in meters.
32+
*/
33+
private Double elevationGain;
34+
35+
/**
36+
* Total elevation loss in meters.
37+
*/
38+
private Double elevationLoss;
39+
40+
/**
41+
* Minimum elevation in meters.
42+
*/
43+
private Double minElevation;
44+
45+
/**
46+
* Maximum elevation in meters.
47+
*/
48+
private Double maxElevation;
49+
50+
/**
51+
* Average speed in kilometers per hour.
52+
*/
53+
private Double averageSpeed;
54+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package com.tourino.domain;
2+
3+
/**
4+
* Enumeration of route types for categorizing user routes.
5+
*/
6+
public enum RouteType {
7+
WALKING("walking"),
8+
CYCLING("cycling"),
9+
CYCLING_REGULAR("cycling-regular"),
10+
DRIVING("driving-car"),
11+
HIKING("foot-hiking"),
12+
MOUNTAIN_BIKING("cycling-mountain"),
13+
RUNNING("foot-running"),
14+
WHEELCHAIR("wheelchair");
15+
16+
private final String profile;
17+
18+
RouteType(String profile) {
19+
this.profile = profile;
20+
}
21+
22+
/**
23+
* Gets the OpenRouteService profile name for this route type.
24+
* @return the profile name used in route calculations
25+
*/
26+
public String getProfile() {
27+
return profile;
28+
}
29+
30+
/**
31+
* Creates RouteType from profile string.
32+
* @param profile the profile string
33+
* @return the corresponding RouteType
34+
* @throws IllegalArgumentException if profile doesn't match any route type
35+
*/
36+
public static RouteType fromProfile(String profile) {
37+
for (RouteType routeType : RouteType.values()) {
38+
if (routeType.profile.equals(profile)) {
39+
return routeType;
40+
}
41+
}
42+
throw new IllegalArgumentException("Unknown RouteType profile: " + profile);
43+
}
44+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package com.tourino.domain;
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+
/**
10+
* Enhanced waypoint entity with coordinates, metadata, and type information.
11+
*/
12+
@DynamoMappable
13+
@Data
14+
@NoArgsConstructor
15+
@AllArgsConstructor
16+
@Builder
17+
public class Waypoint {
18+
19+
/**
20+
* Latitude coordinate in decimal degrees.
21+
*/
22+
private double lat;
23+
24+
/**
25+
* Longitude coordinate in decimal degrees.
26+
*/
27+
private double lng;
28+
29+
/**
30+
* Display name for this waypoint (e.g., "Home", "Office", "Mountain Peak").
31+
*/
32+
private String name;
33+
34+
/**
35+
* Optional description providing additional context about this waypoint.
36+
*/
37+
private String description;
38+
39+
/**
40+
* Type classification for this waypoint.
41+
*/
42+
private WaypointType type;
43+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package com.tourino.domain;
2+
3+
/**
4+
* Enumeration of waypoint types for classification and UI display.
5+
*/
6+
public enum WaypointType {
7+
START("Starting point"),
8+
END("Destination"),
9+
INTERMEDIATE("Intermediate stop"),
10+
LANDMARK("Point of interest"),
11+
CHECKPOINT("Checkpoint"),
12+
ACCOMMODATION("Hotel/accommodation"),
13+
RESTAURANT("Restaurant/food"),
14+
GAS_STATION("Gas station"),
15+
PARKING("Parking area"),
16+
VIEWPOINT("Scenic viewpoint"),
17+
EMERGENCY("Emergency services");
18+
19+
private final String description;
20+
21+
WaypointType(String description) {
22+
this.description = description;
23+
}
24+
25+
/**
26+
* Gets the human-readable description of this waypoint type.
27+
* @return the waypoint type description
28+
*/
29+
public String getDescription() {
30+
return description;
31+
}
32+
}

0 commit comments

Comments
 (0)