-
Notifications
You must be signed in to change notification settings - Fork 0
feat: implement Phase 6 – update, delete, and relationship management… #15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
06d98c8
feat: implement Phase 6 – update, delete, and relationship management…
jfontdev 6472203
feat: add JPA properties for Hibernate default batch fetch size, this…
jfontdev 0cad66a
feat: add validation annotations to TrackPatchRequestDTO and update p…
jfontdev 1ccde15
feat: improve TrackServiceImpl by enhancing tag management and ensuri…
jfontdev 12efde0
fix: use imported Comparator in TrackServiceImpl mapToResponseDTO
Copilot b5b46d5
Update src/main/java/com/jfontdev/trackstack/controller/TagController…
jfontdev 354b69f
Update src/main/java/com/jfontdev/trackstack/controller/PlaylistContr…
jfontdev 74746ba
Update src/main/java/com/jfontdev/trackstack/service/impl/TrackServic…
jfontdev 40ee495
fix: add @Size validations to TagPatchRequestDTO and PlaylistPatchReq…
Copilot 3875140
Initial plan
Copilot 006667c
Merge pull request #16 from jfontdev/copilot/sub-pr-15
jfontdev 7f69b40
feat: enhance cache eviction in deleteTrack method to include playlists
jfontdev 6e93dae
feat: update cache eviction strategy in TagServiceImpl and TrackServi…
jfontdev 8ea21ae
feat: add validation constraints to TrackRequestDTO and TrackUpdateRe…
jfontdev b85d903
feat: add validation constraints to Playlist and Tag DTOs for improve…
jfontdev 7355c04
feat: add validation tests for Playlist and Tag APIs to ensure data i…
jfontdev 5dae0b0
feat: return unmodifiable views of tracks and tags in Playlist and Tr…
jfontdev 687151f
Update src/main/java/com/jfontdev/trackstack/exception/GlobalExceptio…
jfontdev fdcd023
Update src/main/java/com/jfontdev/trackstack/dto/track/TrackUpdateReq…
jfontdev d8d3660
Update src/main/java/com/jfontdev/trackstack/dto/track/TrackRequestDT…
jfontdev File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,2 @@ | ||
| wrapperVersion=3.3.4 | ||
| distributionType=only-script | ||
| distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.11/apache-maven-3.9.11-bin.zip | ||
| distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip | ||
| wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
178 changes: 140 additions & 38 deletions
178
src/main/java/com/jfontdev/trackstack/controller/PlaylistController.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,38 +1,140 @@ | ||
| package com.jfontdev.trackstack.controller; | ||
|
|
||
| import com.jfontdev.trackstack.dto.playlist.PlaylistRequestDTO; | ||
| import com.jfontdev.trackstack.dto.playlist.PlaylistResponseDTO; | ||
| import com.jfontdev.trackstack.service.PlaylistService; | ||
| import jakarta.validation.Valid; | ||
| import org.springframework.http.HttpStatus; | ||
| import org.springframework.http.ResponseEntity; | ||
| import org.springframework.web.bind.annotation.*; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| @RestController | ||
| @RequestMapping("/api/playlists") | ||
| public class PlaylistController { | ||
|
|
||
| private final PlaylistService playlistService; | ||
|
|
||
| public PlaylistController(PlaylistService playlistService) { | ||
| this.playlistService = playlistService; | ||
| } | ||
|
|
||
| @PostMapping | ||
| public ResponseEntity<PlaylistResponseDTO> create(@Valid @RequestBody PlaylistRequestDTO dto) { | ||
| PlaylistResponseDTO response = playlistService.createPlaylist(dto); | ||
| return ResponseEntity.status(HttpStatus.CREATED).body(response); | ||
| } | ||
|
|
||
| @GetMapping("/{id}") | ||
| public PlaylistResponseDTO getById(@PathVariable Long id) { | ||
| return playlistService.getPlaylistById(id); | ||
| } | ||
|
|
||
| @GetMapping | ||
| public List<PlaylistResponseDTO> getAll() { | ||
| return playlistService.getAllPlaylists(); | ||
| } | ||
| } | ||
| package com.jfontdev.trackstack.controller; | ||
|
|
||
| import com.jfontdev.trackstack.dto.playlist.PlaylistPatchRequestDTO; | ||
| import com.jfontdev.trackstack.dto.playlist.PlaylistRequestDTO; | ||
| import com.jfontdev.trackstack.dto.playlist.PlaylistResponseDTO; | ||
| import com.jfontdev.trackstack.dto.playlist.PlaylistUpdateRequestDTO; | ||
| import com.jfontdev.trackstack.service.PlaylistService; | ||
| import jakarta.validation.Valid; | ||
| import org.springframework.http.HttpStatus; | ||
| import org.springframework.http.ResponseEntity; | ||
| import org.springframework.web.bind.annotation.*; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| /** | ||
| * REST controller for managing playlists. | ||
| * <p> | ||
| * Provides endpoints for full CRUD operations on playlists, as well as | ||
| * track relationship management. This controller delegates all business | ||
| * logic to the {@link PlaylistService} and only handles HTTP concerns | ||
| * (request binding, status codes, response formatting). | ||
| */ | ||
| @RestController | ||
| @RequestMapping("/api/playlists") | ||
| public class PlaylistController { | ||
|
|
||
| private final PlaylistService playlistService; | ||
|
|
||
| /** | ||
| * Constructs a new {@code PlaylistController} with the required service. | ||
| * | ||
| * @param playlistService the service handling playlist business logic | ||
| */ | ||
| public PlaylistController(PlaylistService playlistService) { | ||
| this.playlistService = playlistService; | ||
| } | ||
|
|
||
| /** | ||
| * Creates a new playlist. | ||
| * | ||
| * @param dto the validated request body containing playlist details | ||
| * @return 201 Created with the newly created playlist | ||
| */ | ||
| @PostMapping | ||
| public ResponseEntity<PlaylistResponseDTO> create(@Valid @RequestBody PlaylistRequestDTO dto) { | ||
| PlaylistResponseDTO response = playlistService.createPlaylist(dto); | ||
| return ResponseEntity.status(HttpStatus.CREATED).body(response); | ||
| } | ||
|
|
||
| /** | ||
| * Retrieves a playlist by its ID. | ||
| * | ||
| * @param id the playlist's unique identifier | ||
| * @return 200 OK with the playlist details (including tracks), or 404 if not found | ||
| */ | ||
| @GetMapping("/{id}") | ||
| public PlaylistResponseDTO getById(@PathVariable Long id) { | ||
| return playlistService.getPlaylistById(id); | ||
| } | ||
|
|
||
| /** | ||
| * Retrieves all playlists. | ||
| * | ||
| * @return 200 OK with a list of all playlists (each including their tracks) | ||
| */ | ||
| @GetMapping | ||
| public List<PlaylistResponseDTO> getAll() { | ||
| return playlistService.getAllPlaylists(); | ||
| } | ||
|
|
||
| /** | ||
| * Fully updates an existing playlist (PUT semantics). | ||
| * <p> | ||
| * All fields in the request body replace the existing values. | ||
| * | ||
| * @param id the playlist's unique identifier | ||
| * @param dto the validated request body containing the new playlist details | ||
| * @return 200 OK with the updated playlist, or 404 if not found | ||
| */ | ||
| @PutMapping("/{id}") | ||
| public PlaylistResponseDTO update(@PathVariable Long id, @Valid @RequestBody PlaylistUpdateRequestDTO dto) { | ||
| return playlistService.updatePlaylist(id, dto); | ||
| } | ||
|
|
||
| /** | ||
| * Partially updates an existing playlist (PATCH semantics). | ||
| * <p> | ||
| * Only non-null fields in the request body are applied to the existing playlist. | ||
| * | ||
| * @param id the playlist's unique identifier | ||
| * @param dto the validated request body containing the fields to update | ||
| * @return 200 OK with the updated playlist, or 404 if not found | ||
| */ | ||
| @PatchMapping("/{id}") | ||
| public PlaylistResponseDTO patch(@PathVariable Long id, @Valid @RequestBody PlaylistPatchRequestDTO dto) { | ||
| return playlistService.patchPlaylist(id, dto); | ||
| } | ||
|
|
||
| /** | ||
| * Deletes a playlist by its ID. | ||
| * <p> | ||
| * The tracks themselves are not deleted -- only the playlist and its | ||
| * track associations are removed (handled by ON DELETE CASCADE at the | ||
| * database level). | ||
| * | ||
| * @param id the playlist's unique identifier | ||
| * @return 204 No Content on success, or 404 if not found | ||
| */ | ||
| @DeleteMapping("/{id}") | ||
| public ResponseEntity<Void> delete(@PathVariable Long id) { | ||
| playlistService.deletePlaylist(id); | ||
| return ResponseEntity.noContent().build(); | ||
| } | ||
|
|
||
| /** | ||
| * Adds a track to a playlist. | ||
| * | ||
| * @param id the playlist's unique identifier | ||
| * @param trackId the track's unique identifier | ||
| * @return 200 OK with the updated playlist (including the new track), or 404 if | ||
| * either the playlist or track is not found | ||
| */ | ||
| @PutMapping("/{id}/tracks/{trackId}") | ||
| public PlaylistResponseDTO addTrack(@PathVariable Long id, @PathVariable Long trackId) { | ||
| return playlistService.addTrackToPlaylist(id, trackId); | ||
| } | ||
|
|
||
| /** | ||
| * Removes a track from a playlist. | ||
| * | ||
| * @param id the playlist's unique identifier | ||
| * @param trackId the track's unique identifier | ||
| * @return 200 OK with the updated playlist (without the removed track), or 404 if | ||
| * either the playlist or track is not found | ||
| */ | ||
| @DeleteMapping("/{id}/tracks/{trackId}") | ||
| public PlaylistResponseDTO removeTrack(@PathVariable Long id, @PathVariable Long trackId) { | ||
| return playlistService.removeTrackFromPlaylist(id, trackId); | ||
| } | ||
| } |
152 changes: 113 additions & 39 deletions
152
src/main/java/com/jfontdev/trackstack/controller/TagController.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,39 +1,113 @@ | ||
| package com.jfontdev.trackstack.controller; | ||
|
|
||
|
|
||
| import com.jfontdev.trackstack.dto.tag.TagRequestDTO; | ||
| import com.jfontdev.trackstack.dto.tag.TagResponseDTO; | ||
| import com.jfontdev.trackstack.service.TagService; | ||
| import jakarta.validation.Valid; | ||
| import org.springframework.http.HttpStatus; | ||
| import org.springframework.http.ResponseEntity; | ||
| import org.springframework.web.bind.annotation.*; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| @RestController | ||
| @RequestMapping("/api/tags") | ||
| public class TagController { | ||
|
|
||
| private final TagService tagService; | ||
|
|
||
| public TagController(TagService tagService) { | ||
| this.tagService = tagService; | ||
| } | ||
|
|
||
| @PostMapping | ||
| public ResponseEntity<TagResponseDTO> create(@Valid @RequestBody TagRequestDTO dto) { | ||
| TagResponseDTO response = tagService.createTag(dto); | ||
| return ResponseEntity.status(HttpStatus.CREATED).body(response); | ||
| } | ||
|
|
||
| @GetMapping("/{id}") | ||
| public TagResponseDTO getById(@PathVariable Long id) { | ||
| return tagService.getTagById(id); | ||
| } | ||
|
|
||
| @GetMapping | ||
| public List<TagResponseDTO> getAll() { | ||
| return tagService.getAllTags(); | ||
| } | ||
| } | ||
| package com.jfontdev.trackstack.controller; | ||
|
|
||
| import com.jfontdev.trackstack.dto.tag.TagPatchRequestDTO; | ||
| import com.jfontdev.trackstack.dto.tag.TagRequestDTO; | ||
| import com.jfontdev.trackstack.dto.tag.TagResponseDTO; | ||
| import com.jfontdev.trackstack.dto.tag.TagUpdateRequestDTO; | ||
| import com.jfontdev.trackstack.service.TagService; | ||
| import jakarta.validation.Valid; | ||
| import org.springframework.http.HttpStatus; | ||
| import org.springframework.http.ResponseEntity; | ||
| import org.springframework.web.bind.annotation.*; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| /** | ||
| * REST controller for managing tags. | ||
| * <p> | ||
| * Provides endpoints for full CRUD operations on tags. This controller | ||
| * delegates all business logic to the {@link TagService} and only handles | ||
| * HTTP concerns (request binding, status codes, response formatting). | ||
| */ | ||
| @RestController | ||
| @RequestMapping("/api/tags") | ||
| public class TagController { | ||
|
|
||
| private final TagService tagService; | ||
|
|
||
| /** | ||
| * Constructs a new {@code TagController} with the required service. | ||
| * | ||
| * @param tagService the service handling tag business logic | ||
| */ | ||
| public TagController(TagService tagService) { | ||
| this.tagService = tagService; | ||
| } | ||
|
|
||
| /** | ||
| * Creates a new tag. | ||
| * | ||
| * @param dto the validated request body containing tag details | ||
| * @return 201 Created with the newly created tag | ||
| */ | ||
| @PostMapping | ||
| public ResponseEntity<TagResponseDTO> create(@Valid @RequestBody TagRequestDTO dto) { | ||
| TagResponseDTO response = tagService.createTag(dto); | ||
| return ResponseEntity.status(HttpStatus.CREATED).body(response); | ||
| } | ||
|
|
||
| /** | ||
| * Retrieves a tag by its ID. | ||
| * | ||
| * @param id the tag's unique identifier | ||
| * @return 200 OK with the tag details, or 404 if not found | ||
| */ | ||
| @GetMapping("/{id}") | ||
| public TagResponseDTO getById(@PathVariable Long id) { | ||
| return tagService.getTagById(id); | ||
| } | ||
|
|
||
| /** | ||
| * Retrieves all tags. | ||
| * | ||
| * @return 200 OK with a list of all tags | ||
| */ | ||
| @GetMapping | ||
| public List<TagResponseDTO> getAll() { | ||
| return tagService.getAllTags(); | ||
| } | ||
|
|
||
| /** | ||
| * Fully updates an existing tag (PUT semantics). | ||
| * <p> | ||
| * The tag name in the request body replaces the existing value. | ||
| * The new name must remain unique. | ||
| * | ||
| * @param id the tag's unique identifier | ||
| * @param dto the validated request body containing the new tag details | ||
| * @return 200 OK with the updated tag, or 404 if not found | ||
| */ | ||
| @PutMapping("/{id}") | ||
| public TagResponseDTO update(@PathVariable Long id, @Valid @RequestBody TagUpdateRequestDTO dto) { | ||
| return tagService.updateTag(id, dto); | ||
| } | ||
|
|
||
| /** | ||
| * Partially updates an existing tag (PATCH semantics). | ||
| * <p> | ||
| * Only non-null fields in the request body are applied to the existing tag. | ||
| * | ||
| * @param id the tag's unique identifier | ||
| * @param dto the validated request body containing the fields to update | ||
| * @return 200 OK with the updated tag, or 404 if not found | ||
| */ | ||
| @PatchMapping("/{id}") | ||
| public TagResponseDTO patch(@PathVariable Long id, @Valid @RequestBody TagPatchRequestDTO dto) { | ||
| return tagService.patchTag(id, dto); | ||
| } | ||
|
|
||
| /** | ||
| * Deletes a tag by its ID. | ||
| * <p> | ||
| * Also removes all track associations for this tag (handled by | ||
| * ON DELETE CASCADE at the database level). | ||
| * | ||
| * @param id the tag's unique identifier | ||
| * @return 204 No Content on success, or 404 if not found | ||
| */ | ||
| @DeleteMapping("/{id}") | ||
| public ResponseEntity<Void> delete(@PathVariable Long id) { | ||
| tagService.deleteTag(id); | ||
| return ResponseEntity.noContent().build(); | ||
| } | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.