Skip to content

Commit 1bec887

Browse files
committed
Finishing Task 6
1 parent 3c3d7b1 commit 1bec887

File tree

7 files changed

+356
-1302
lines changed

7 files changed

+356
-1302
lines changed

examples/spring-boot-demo/implementation/src/main/java/com/example/demo/controller/FilmController.java

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
import org.springframework.http.HttpStatus;
1010
import org.springframework.http.ProblemDetail;
1111
import com.example.demo.service.FilmService;
12-
import com.example.demo.dto.FilmResponse;
12+
import com.example.demo.dto.FilmDTO;
13+
import com.example.demo.entity.Film;
1314

1415
import io.swagger.v3.oas.annotations.Operation;
1516
import io.swagger.v3.oas.annotations.Parameter;
@@ -92,7 +93,7 @@ public FilmController(FilmService filmService) {
9293
description = "Successfully retrieved films",
9394
content = @Content(
9495
mediaType = "application/json",
95-
schema = @Schema(implementation = FilmResponse.class)
96+
schema = @Schema(implementation = FilmDTO.class)
9697
)
9798
),
9899
@ApiResponse(
@@ -131,18 +132,18 @@ public ResponseEntity<?> getFilms(
131132
}
132133
}
133134

134-
// Call service layer to get films
135-
List<Map<String, Object>> films = filmService.findFilmsByStartingLetter(startsWith);
135+
// Call service layer to get films as entities
136+
List<Film> films = filmService.findFilmEntitiesByStartingLetter(startsWith);
136137

137138
// Task 4.6: Implement response formatting with films array, count, and filter
138139
// Build filter object
139140
Map<String, Object> filter = new HashMap<>();
140-
if (startsWith != null && !startsWith.trim().isEmpty()) {
141+
if (Objects.nonNull(startsWith) && !startsWith.trim().isEmpty()) {
141142
filter.put("startsWith", startsWith);
142143
}
143144

144-
// Create FilmResponse DTO (Task 4.5)
145-
FilmResponse response = new FilmResponse(films, films.size(), filter);
145+
// Create FilmDTO response (Task 6.6)
146+
FilmDTO response = FilmDTO.fromEntities(films, filter);
146147

147148
// Task 4.8: Implement proper HTTP status code handling
148149
return ResponseEntity.ok(response);
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
package com.example.demo.dto;
2+
3+
import com.fasterxml.jackson.annotation.JsonProperty;
4+
import java.util.List;
5+
import java.util.Map;
6+
7+
/**
8+
* FilmDTO - Comprehensive Data Transfer Object for Film Query API
9+
*
10+
* Task 6.6: Create FilmDTO for data transfer ✅
11+
*
12+
* This DTO represents the complete film query response, replacing FilmResponse.
13+
* It provides a clean separation between entity and response formats.
14+
*
15+
* Complete JSON structure:
16+
* {
17+
* "films": [
18+
* {
19+
* "film_id": 1,
20+
* "title": "ACADEMY DINOSAUR"
21+
* }
22+
* ],
23+
* "count": 46,
24+
* "filter": {
25+
* "startsWith": "A"
26+
* }
27+
* }
28+
*/
29+
public record FilmDTO(
30+
@JsonProperty("films") List<Film> films,
31+
@JsonProperty("count") int count,
32+
@JsonProperty("filter") Map<String, Object> filter
33+
) {
34+
35+
/**
36+
* Individual Film record for the films array
37+
*/
38+
public record Film(
39+
@JsonProperty("film_id") Integer filmId,
40+
@JsonProperty("title") String title
41+
) {
42+
/**
43+
* Factory method to create Film from Film entity
44+
*
45+
* @param entity The Film entity to convert
46+
* @return Film record with mapped data
47+
*/
48+
public static Film fromEntity(com.example.demo.entity.Film entity) {
49+
return new Film(entity.filmId(), entity.title());
50+
}
51+
52+
/**
53+
* Convert Film to Map format for backward compatibility
54+
*
55+
* @return Map representation of the film
56+
*/
57+
public Map<String, Object> toMap() {
58+
Map<String, Object> map = new java.util.HashMap<>();
59+
map.put("film_id", filmId);
60+
map.put("title", title);
61+
return map;
62+
}
63+
}
64+
65+
/**
66+
* Factory method to create FilmDTO from film entities and filter
67+
*
68+
* @param entities List of Film entities to convert
69+
* @param filterMap Map containing filter parameters
70+
* @return FilmDTO instance with complete response structure
71+
*/
72+
public static FilmDTO fromEntities(List<com.example.demo.entity.Film> entities, Map<String, Object> filterMap) {
73+
List<Film> films = entities.stream()
74+
.map(Film::fromEntity)
75+
.toList();
76+
77+
return new FilmDTO(films, films.size(), filterMap);
78+
}
79+
80+
/**
81+
* Factory method to create FilmDTO from Map-based films (for backward compatibility)
82+
*
83+
* @param filmMaps List of film maps
84+
* @param filterMap Map containing filter parameters
85+
* @return FilmDTO instance with complete response structure
86+
*/
87+
public static FilmDTO fromMaps(List<Map<String, Object>> filmMaps, Map<String, Object> filterMap) {
88+
List<Film> films = filmMaps.stream()
89+
.map(map -> new Film(
90+
(Integer) map.get("film_id"),
91+
(String) map.get("title")
92+
))
93+
.toList();
94+
95+
return new FilmDTO(films, films.size(), filterMap);
96+
}
97+
}

examples/spring-boot-demo/implementation/src/main/java/com/example/demo/dto/FilmResponse.java

Lines changed: 0 additions & 33 deletions
This file was deleted.

examples/spring-boot-demo/implementation/src/main/java/com/example/demo/service/FilmService.java

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -33,19 +33,12 @@ public FilmService(FilmRepository filmRepository) {
3333
}
3434

3535
/**
36-
* Task 6.2: Implement findFilmsByStartingLetter(String letter) method ✅
37-
* Task 6.3: Add business validation for letter parameter ✅
38-
* Task 6.4: Implement film filtering logic (case insensitive LIKE query) ✅
39-
* Task 6.7: Implement entity to DTO transformation logic ✅
40-
* Task 6.8: Add empty result handling with appropriate messaging ✅
41-
*
42-
* Retrieves films from the database that start with the specified letter.
43-
* Handles both filtered queries (when letter is provided) and unfiltered queries.
36+
* Get Film entities by starting letter (internal method for controller use)
4437
*
4538
* @param letter Optional starting letter to filter films (A-Z, case insensitive)
46-
* @return List of film maps with film_id and title, empty list if no matches
39+
* @return List of Film entities, empty list if no matches
4740
*/
48-
public List<Map<String, Object>> findFilmsByStartingLetter(String letter) {
41+
public List<Film> findFilmEntitiesByStartingLetter(String letter) {
4942
List<Film> films;
5043

5144
// Task 6.3: Add business validation for letter parameter (already done in controller)
@@ -58,11 +51,8 @@ public List<Map<String, Object>> findFilmsByStartingLetter(String letter) {
5851
films = filmRepository.findAllOrderByTitle();
5952
}
6053

61-
// Task 6.7: Implement entity to DTO transformation logic
62-
// Transform Film entities to Map<String, Object> format expected by controller
63-
return films.stream()
64-
.map(this::filmToMap)
65-
.toList();
54+
// Task 6.8: Add empty result handling with appropriate messaging
55+
return films; // Return entities directly for DTO transformation in controller
6656
}
6757

6858
/**

0 commit comments

Comments
 (0)