From 4e23d913d14d144aca0b92387b666c9448d8111d Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Sat, 22 Nov 2025 00:47:43 +0100 Subject: [PATCH] feat: RecipeController with GET, POST, PUT, DELETE TODO: WebSockets updates should be propagated after POST/PUT/DELETE operations --- .../java/server/api/RecipeController.java | 121 ++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 server/src/main/java/server/api/RecipeController.java diff --git a/server/src/main/java/server/api/RecipeController.java b/server/src/main/java/server/api/RecipeController.java new file mode 100644 index 0000000..4a81057 --- /dev/null +++ b/server/src/main/java/server/api/RecipeController.java @@ -0,0 +1,121 @@ +package server.api; + +import commons.Recipe; + +import org.springframework.data.domain.PageRequest; +import org.springframework.http.ResponseEntity; + +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import server.database.RecipeRepository; + +import java.util.List; +import java.util.Optional; + +@RestController +@RequestMapping("/recipe") +public class RecipeController { + private final RecipeRepository recipeRepository; // JPA repository used in this controller + + public RecipeController(RecipeRepository recipeRepository) { + this.recipeRepository = recipeRepository; + } + + /** + * Mapping for GET /recipe/{id} + *

+ * Gets a specific recipe by its unique id. + *

+ * @param id id of the recipe + * @return The recipe if it exists in the repository; otherwise returns 404 Not Found status + */ + @GetMapping("/recipe/{id}") + public ResponseEntity getRecipe(@PathVariable Long id) { + if (!recipeRepository.existsById(id)) { + return ResponseEntity.notFound().build(); + } + return ResponseEntity.ok(recipeRepository.findById(id).get()); + } + + /** + * Mapping for GET /recipes(?limit=) + *

+ * If the limit parameter is unspecified, return all recipes in the repository. + * @param limit Integer limit of items you want to get + * @return The list of recipes + */ + @GetMapping("/recipes") + public ResponseEntity> getRecipes(@RequestParam Optional limit) { + if (limit.isPresent()) { + return ResponseEntity.ok( + recipeRepository.findAll( + PageRequest.of(0, limit.get()) + ).toList()); + } + return ResponseEntity.ok(recipeRepository.findAll()); + } + + /** + * Mapping for POST /recipe/{id} + * @param id The recipe id to replace + * @param recipe The new recipe to be replaced from the original + * @return The changed recipe; returns 400 Bad Request if the recipe does not exist + */ + @PostMapping("/recipe/{id}") + public ResponseEntity updateRecipe(@PathVariable Long id, @RequestBody Recipe recipe) { + if (!recipeRepository.existsById(id)) { + return ResponseEntity.badRequest().build(); + } + + // TODO: Send WS update to all subscribers with the updated recipe + + return ResponseEntity.ok(recipeRepository.save(recipe)); + } + + /** + * Mapping for PUT /recipe/new + *

+ * Inserts a new recipe into the repository + *

+ * @param recipe The new recipe as a request body + * @return 200 OK with the recipe you added; or 400 Bad Request if the recipe already exists + */ + @PutMapping("/recipe/new") + public ResponseEntity createRecipe(@RequestBody Recipe recipe) { + if (recipeRepository.existsById(recipe.getId())) { + return ResponseEntity.badRequest().build(); + } + + // TODO: Send WS update to all subscribers with the new recipe + + return ResponseEntity.ok(recipeRepository.save(recipe)); + } + + /** + * Mapping for DELETE /recipe/{id} + *

+ * Deletes a recipe identified by its id. + *

+ * @param id The id of the recipe to be deleted. + * @return 200 OK with the recipe that was deleted; or 400 Bad Request if the recipe doesn't exist. + */ + @DeleteMapping("/recipe/{id}") + public ResponseEntity deleteRecipe(@PathVariable Long id) { + if (!recipeRepository.existsById(id)) { + return ResponseEntity.badRequest().build(); + } + Recipe removedRecipe = recipeRepository.findById(id).get(); + recipeRepository.delete(removedRecipe); + + // TODO: Send WS update to propagate deletion + return ResponseEntity.ok(removedRecipe); + } +}