Merge branch 'mourning-recipes' into 'main'
Mourning recipes See merge request cse1105/2025-2026/teams/csep-team-76!65
This commit is contained in:
commit
f6d5551408
5 changed files with 61 additions and 20 deletions
|
|
@ -127,7 +127,7 @@ public class FoodpalApplicationCtrl implements LocaleAware {
|
||||||
};
|
};
|
||||||
case DeleteRecipeMessage _ -> (m) -> {
|
case DeleteRecipeMessage _ -> (m) -> {
|
||||||
DeleteRecipeMessage drm = (DeleteRecipeMessage) m;
|
DeleteRecipeMessage drm = (DeleteRecipeMessage) m;
|
||||||
logger.info("Server informs us of the deletion of recipe with ID: " + drm.getRecipeId());
|
logger.info("Server informs us of the deletion of recipe: " + drm.getRecipe());
|
||||||
return handleDeleteRecipeMessage(drm);
|
return handleDeleteRecipeMessage(drm);
|
||||||
};
|
};
|
||||||
case FavouriteRecipeMessage _ -> (m) -> {
|
case FavouriteRecipeMessage _ -> (m) -> {
|
||||||
|
|
@ -160,12 +160,28 @@ public class FoodpalApplicationCtrl implements LocaleAware {
|
||||||
return new ImmutablePair<>(recipe.getId(), recipe);
|
return new ImmutablePair<>(recipe.getId(), recipe);
|
||||||
}
|
}
|
||||||
private Pair<Long, Recipe> handleDeleteRecipeMessage(DeleteRecipeMessage drm) {
|
private Pair<Long, Recipe> handleDeleteRecipeMessage(DeleteRecipeMessage drm) {
|
||||||
this.recipeList.getItems().remove(findRecipeById(drm.getRecipeId()).orElseThrow(
|
Recipe recipe = drm.getRecipe();
|
||||||
() -> new InvalidModificationException("Invalid recipe id during delete: " + drm.getRecipeId())
|
|
||||||
|
// If it's not pending means other client deleted.
|
||||||
|
boolean externalDelete = !dataService.isPending(recipe.getId());
|
||||||
|
|
||||||
|
this.recipeList.getItems().remove(findRecipeById(recipe.getId()).orElseThrow(
|
||||||
|
() -> new InvalidModificationException("Invalid recipe id during delete: " + recipe.getId())
|
||||||
));
|
));
|
||||||
dataService.add(drm.getRecipeId());
|
|
||||||
// TODO Make it an Optional<Recipe> so that we don't need to touch Null?
|
// Show an alert to mourn a lost comrade (recipe).
|
||||||
return new ImmutablePair<>(drm.getRecipeId(), null);
|
if (externalDelete && config.isFavourite(recipe.getId())) {
|
||||||
|
Alert alert = new Alert(Alert.AlertType.INFORMATION);
|
||||||
|
alert.setTitle("Mourn your loss!!!");
|
||||||
|
alert.setHeaderText(null);
|
||||||
|
|
||||||
|
alert.setContentText("Your most beloved recipe by the name of \"" +
|
||||||
|
recipe.getName() + "\" has been removed.");
|
||||||
|
alert.showAndWait();
|
||||||
|
}
|
||||||
|
|
||||||
|
dataService.add(recipe.getId());
|
||||||
|
return new ImmutablePair<>(recipe.getId(), recipe);
|
||||||
}
|
}
|
||||||
// TODO Implementation
|
// TODO Implementation
|
||||||
private Pair<Long, Recipe> handleFavouriteRecipeMessage(FavouriteRecipeMessage frm) {
|
private Pair<Long, Recipe> handleFavouriteRecipeMessage(FavouriteRecipeMessage frm) {
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,12 @@ public class WebSocketDataService<ID, Value> {
|
||||||
logger.info("Item " + id + " pending propagation. Adding to pending register.");
|
logger.info("Item " + id + " pending propagation. Adding to pending register.");
|
||||||
return pendingRegister.putIfAbsent(id, future) == null;
|
return pendingRegister.putIfAbsent(id, future) == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean add(ID id) {
|
public boolean add(ID id) {
|
||||||
return add(id, (_) -> {});
|
return add(id, (_) -> {});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isPending(ID id) {
|
||||||
|
return pendingRegister.containsKey(id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,19 @@
|
||||||
package commons.ws.messages;
|
package commons.ws.messages;
|
||||||
|
|
||||||
|
import commons.Recipe;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Message sent when a recipe is deleted.
|
* Message sent when a recipe is deleted.
|
||||||
*
|
*
|
||||||
* @see commons.ws.messages.Message.Type#RECIPE_DELETE
|
* @see commons.ws.messages.Message.Type#RECIPE_DELETE
|
||||||
*/
|
*/
|
||||||
public class DeleteRecipeMessage implements Message {
|
public class DeleteRecipeMessage implements Message {
|
||||||
private Long recipeId;
|
private Recipe recipe;
|
||||||
|
|
||||||
public DeleteRecipeMessage() {} // for jackson
|
public DeleteRecipeMessage() {} // for jackson
|
||||||
|
|
||||||
public DeleteRecipeMessage(Long recipeId) {
|
public DeleteRecipeMessage(Recipe recipe) {
|
||||||
this.recipeId = recipeId;
|
this.recipe = recipe;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -20,16 +22,16 @@ public class DeleteRecipeMessage implements Message {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the ID of the deleted recipe.
|
* Get the deleted recipe.
|
||||||
*
|
*
|
||||||
* @return The ID of the deleted recipe.
|
* @return The deleted recipe.
|
||||||
*/
|
*/
|
||||||
public Long getRecipeId() {
|
public Recipe getRecipe() {
|
||||||
return recipeId;
|
return recipe;
|
||||||
}
|
}
|
||||||
|
|
||||||
// for jackson
|
// for jackson
|
||||||
public void setRecipeId(Long recipeId) {
|
public void setRecipe(Recipe recipe) {
|
||||||
this.recipeId = recipeId;
|
this.recipe = recipe;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -145,10 +145,11 @@ public class RecipeController {
|
||||||
@DeleteMapping("/recipe/{id}")
|
@DeleteMapping("/recipe/{id}")
|
||||||
public ResponseEntity<Boolean> deleteRecipe(@PathVariable Long id) {
|
public ResponseEntity<Boolean> deleteRecipe(@PathVariable Long id) {
|
||||||
logger.info("DELETE /recipe/" + id + " called.");
|
logger.info("DELETE /recipe/" + id + " called.");
|
||||||
if (!recipeService.delete(id)) {
|
Optional<Recipe> recipe = recipeService.delete(id);
|
||||||
|
if (recipe.isEmpty()) {
|
||||||
return ResponseEntity.badRequest().build();
|
return ResponseEntity.badRequest().build();
|
||||||
}
|
}
|
||||||
messagingTemplate.convertAndSend(Topics.RECIPES, new DeleteRecipeMessage(id)); // Send to WS.
|
messagingTemplate.convertAndSend(Topics.RECIPES, new DeleteRecipeMessage(recipe.get())); // Send to WS.
|
||||||
return ResponseEntity.ok(true);
|
return ResponseEntity.ok(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -75,11 +75,28 @@ public class RecipeService {
|
||||||
return Optional.of(saveWithDependencies(recipe));
|
return Optional.of(saveWithDependencies(recipe));
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean delete(Long id) {
|
/**
|
||||||
|
* Deletes a recipe by id and returns the deleted object.
|
||||||
|
* @param id id of the recipe to delete.
|
||||||
|
* @return The deleted recipe (deep copy).
|
||||||
|
*/
|
||||||
|
public Optional<Recipe> delete(Long id) {
|
||||||
// TODO: Propagate deletion to ingredients.
|
// TODO: Propagate deletion to ingredients.
|
||||||
if (!recipeRepository.existsById(id)) return false;
|
Optional<Recipe> recipe = recipeRepository.findById(id);
|
||||||
|
if (recipe.isEmpty()) return Optional.empty();
|
||||||
|
|
||||||
|
// Make deep copy before removal. ( Had some lazy loading issues otherwise )
|
||||||
|
Recipe r = recipe.get();
|
||||||
|
Recipe copy = new Recipe(
|
||||||
|
r.getId(),
|
||||||
|
r.getName(),
|
||||||
|
r.getLocale(),
|
||||||
|
List.copyOf(r.getIngredients()),
|
||||||
|
List.copyOf(r.getPreparationSteps())
|
||||||
|
);
|
||||||
|
|
||||||
recipeRepository.deleteById(id);
|
recipeRepository.deleteById(id);
|
||||||
return true;
|
return Optional.of(copy);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Recipe saveWithDependencies(Recipe recipe) {
|
private Recipe saveWithDependencies(Recipe recipe) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue