diff --git a/docs/DB.md b/docs/DB.md index 930d36c..f7dfcb2 100644 --- a/docs/DB.md +++ b/docs/DB.md @@ -55,12 +55,12 @@ ## Relationships - Trainer - - [ ] trainers.pastOpponents: one-to-many and reflexive + - [x] trainers.pastOpponents: one-to-many and reflexive * => referencing - - [ ] trainers.pokemongs: one-to-many + - [x] trainers.pokemongs: one-to-many * => referencing + denormalizing on "nickname" and "species" - Pokemong - - [ ] pokemongs.trainer: many-to-one + - [x] pokemongs.trainer: many-to-one * => referencing - [x] pokemongs.types: one-to-few [1;2] * => embedding @@ -76,12 +76,12 @@ ## Cascades - Pokemong - - [ ] delete ~> trainer.pokemongs - - [ ] update ~> trainer.pokemongs (denormalizing on "nickname" and "species") - - [ ] create ~> trainer.pokemongs + - [x] delete ~> trainer.pokemongs + - [x] update ~> trainer.pokemongs (denormalizing on "nickname" and "species") + - [x] create ~> trainer.pokemongs - Trainer - - [ ] delete ~> pokemong.trainer - - [ ] create ~> pokemong.trainer + - [x] delete ~> pokemong.trainer + - [x] create ~> pokemong.trainer - Move - [x] delete ~> pokemong.moveSet - [x] update ~> pokemong.moveSet (denormalizing on "name") diff --git a/docs/nosql_uml.png b/docs/nosql_uml.png index 0979200..e32ec6f 100644 Binary files a/docs/nosql_uml.png and b/docs/nosql_uml.png differ diff --git a/src/main/java/fr/uca/iut/entities/Pokemong.java b/src/main/java/fr/uca/iut/entities/Pokemong.java index bd7c153..1acd9e4 100644 --- a/src/main/java/fr/uca/iut/entities/Pokemong.java +++ b/src/main/java/fr/uca/iut/entities/Pokemong.java @@ -62,22 +62,6 @@ public class Pokemong extends GenericEntity { this.pokedexId = pokedexId; } - public Integer getEvoStage() { - return evoStage; - } - - public void setEvoStage(Integer evoStage) { - this.evoStage = evoStage; - } - - public List getEvoTrack() { - return evoTrack; - } - - public void setEvoTrack(List evoTrack) { - this.evoTrack = evoTrack; - } - @Nullable public String getTrainer() { return trainer; @@ -119,5 +103,25 @@ public class Pokemong extends GenericEntity { } } } + + public PokemongName getSpecies() { + return getEvoTrack().get(getEvoStage()); + } + + public List getEvoTrack() { + return evoTrack; + } + + public Integer getEvoStage() { + return evoStage; + } + + public void setEvoStage(Integer evoStage) { + this.evoStage = evoStage; + } + + public void setEvoTrack(List evoTrack) { + this.evoTrack = evoTrack; + } } diff --git a/src/main/java/fr/uca/iut/repositories/PokemongRepository.java b/src/main/java/fr/uca/iut/repositories/PokemongRepository.java index a0d920b..3da2595 100644 --- a/src/main/java/fr/uca/iut/repositories/PokemongRepository.java +++ b/src/main/java/fr/uca/iut/repositories/PokemongRepository.java @@ -14,8 +14,6 @@ import org.bson.types.ObjectId; import java.util.ArrayList; import java.util.List; -import static com.mongodb.client.model.Filters.eq; - @ApplicationScoped public class PokemongRepository extends GenericRepository { @@ -44,8 +42,4 @@ public class PokemongRepository extends GenericRepository { return db.getCollection(Pokemong.COLLECTION_NAME, Pokemong.class); } - public List findByTrainer(String trainerId) { - return getCollection().find(eq("trainer", new ObjectId(trainerId))) - .into(new ArrayList<>()); - } } diff --git a/src/main/java/fr/uca/iut/repositories/TrainerRepository.java b/src/main/java/fr/uca/iut/repositories/TrainerRepository.java index 12d4cf3..35ff7ed 100644 --- a/src/main/java/fr/uca/iut/repositories/TrainerRepository.java +++ b/src/main/java/fr/uca/iut/repositories/TrainerRepository.java @@ -3,16 +3,10 @@ package fr.uca.iut.repositories; import com.mongodb.client.MongoClient; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoDatabase; -import com.mongodb.client.model.Filters; import fr.uca.iut.entities.Trainer; import jakarta.annotation.PostConstruct; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; -import org.bson.conversions.Bson; -import org.bson.types.ObjectId; - -import java.util.ArrayList; -import java.util.List; @ApplicationScoped public class TrainerRepository extends GenericRepository { @@ -30,12 +24,6 @@ public class TrainerRepository extends GenericRepository { setMongoClient(mongoClient); } - public List findByPokemong(String pokemongId) { - Bson filter = Filters.elemMatch("pokemongs", Filters.eq("_id", new ObjectId(pokemongId))); - return getCollection().find(filter) - .into(new ArrayList<>()); - } - @Override protected MongoCollection getCollection() { MongoDatabase db = mongoClient.getDatabase(DB_NAME); diff --git a/src/main/java/fr/uca/iut/services/PokemongService.java b/src/main/java/fr/uca/iut/services/PokemongService.java index f33f40d..ae9afd9 100644 --- a/src/main/java/fr/uca/iut/services/PokemongService.java +++ b/src/main/java/fr/uca/iut/services/PokemongService.java @@ -1,9 +1,7 @@ package fr.uca.iut.services; import com.mongodb.lang.Nullable; -import fr.uca.iut.entities.Pokemong; -import fr.uca.iut.entities.PokemongMove; -import fr.uca.iut.entities.Type; +import fr.uca.iut.entities.*; import fr.uca.iut.repositories.PokemongRepository; import fr.uca.iut.utils.StringUtils; import fr.uca.iut.utils.enums.PokemongName; @@ -15,6 +13,7 @@ import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; +import java.util.Objects; import java.util.Set; @ApplicationScoped @@ -26,6 +25,9 @@ public class PokemongService extends GenericService { @Inject MoveService moveService; + @Inject + TrainerService trainerService; + @PostConstruct public void init() { setRepository(pokemongRepository); @@ -33,15 +35,34 @@ public class PokemongService extends GenericService { @Override public Pokemong addOne(@NotNull Pokemong pokemong) { - // TODO if this pokemong has a trainer, make sure that the trainer's "pokemongs" field gets updated accordingly. - // (add a TrainerPokemong to the list, update the trainer) - return super.addOne(pokemong); + Pokemong persistedPokemong = super.addOne(pokemong); + + Trainer trainer = trainerService.getOneById(pokemong.getTrainer()); + if (trainer != null) { + TrainerPokemong trainerPokemong = new TrainerPokemong(); + trainerPokemong.setId(pokemong.getId()); + trainerPokemong.setNickname(pokemong.getNickname()); + trainerPokemong.setSpecies(pokemong.getSpecies()); + trainer.getPokemongs() + .add(trainerPokemong); + trainerService.updateOne(trainer); + } + return persistedPokemong; } @Override public void deleteOneById(String id) { + Pokemong pokemong = getOneById(id); + if (pokemong != null && pokemong.getTrainer() != null) { + Trainer trainer = trainerService.getOneById(pokemong.getTrainer()); + if (trainer != null) { + trainer.getPokemongs() + .removeIf(trainerPokemong -> trainerPokemong.getId() + .equals(id)); + trainerService.updateOne(trainer); + } + } super.deleteOneById(id); - // TODO also delete any corresponding PokemongTrainer among trainers } @Override @@ -49,19 +70,45 @@ public class PokemongService extends GenericService { public Pokemong updateOne(@NotNull Pokemong pokemong) { Pokemong existingPokemong = pokemongRepository.findById(pokemong.getId()); if (existingPokemong != null) { + boolean nicknameChanged = !Objects.equals(existingPokemong.getNickname(), pokemong.getNickname()); + boolean evoStageChanged = !Objects.equals(existingPokemong.getEvoStage(), pokemong.getEvoStage()); + boolean evoTrackChanged = !Objects.equals(existingPokemong.getEvoTrack(), pokemong.getEvoTrack()); + existingPokemong.setNickname(pokemong.getNickname()); - // TODO if nickname changed also update any corresponding PokemongTrainer's nickname existingPokemong.setDob(pokemong.getDob()); existingPokemong.setLevel(pokemong.getLevel()); existingPokemong.setPokedexId(pokemong.getPokedexId()); existingPokemong.setEvoStage(pokemong.getEvoStage()); - // TODO if evoStage changed, also update any corresponding PokemongTrainer's species existingPokemong.setEvoTrack(pokemong.getEvoTrack()); - // TODO if evoTrack changed, also update any corresponding PokemongTrainer's species existingPokemong.setTrainer(pokemong.getTrainer()); existingPokemong.setTypes(pokemong.getTypes()); existingPokemong.setMoveSet(pokemong.getMoveSet()); + pokemongRepository.persistOrUpdate(existingPokemong); + + if (nicknameChanged || evoStageChanged || evoTrackChanged) { + Trainer trainer = trainerService.getOneById(existingPokemong.getTrainer()); + if (trainer != null) { + TrainerPokemong trainerPokemong = trainer.getPokemongs() + .stream() + .filter(tp -> tp.getId() + .equals(existingPokemong.getId())) + .findFirst() + .orElse(null); + + if (trainerPokemong != null) { + if (nicknameChanged) { + trainerPokemong.setNickname(existingPokemong.getNickname()); + } + + if (evoStageChanged || evoTrackChanged) { + trainerPokemong.setSpecies(existingPokemong.getSpecies()); + } + + trainerService.updateOne(trainer); + } + } + } } return existingPokemong; } @@ -136,11 +183,20 @@ public class PokemongService extends GenericService { public boolean isEvoValid(String id, PokemongName species) { Pokemong pokemong = pokemongRepository.findById(id); - return pokemong != null && pokemong.getEvoTrack() - .get(pokemong.getEvoStage()) == species; + return pokemong != null && pokemong.getSpecies() == species; } public boolean existsById(String pokemongId) { return repository.existsById(pokemongId); } + + public void batchUpdatePokemongTrainers(List trainerPokemongs, @Nullable String trainerId) { + for (TrainerPokemong trainerPokemong : trainerPokemongs) { + Pokemong pokemong = getOneById(trainerPokemong.getId()); + if (pokemong != null) { + pokemong.setTrainer(trainerId); + updateOne(pokemong); + } + } + } } diff --git a/src/main/java/fr/uca/iut/services/TrainerService.java b/src/main/java/fr/uca/iut/services/TrainerService.java index 8d40eba..65d8a88 100644 --- a/src/main/java/fr/uca/iut/services/TrainerService.java +++ b/src/main/java/fr/uca/iut/services/TrainerService.java @@ -1,6 +1,7 @@ package fr.uca.iut.services; import com.mongodb.lang.Nullable; +import fr.uca.iut.entities.Pokemong; import fr.uca.iut.entities.Trainer; import fr.uca.iut.entities.TrainerPokemong; import fr.uca.iut.repositories.TrainerRepository; @@ -30,15 +31,22 @@ public class TrainerService extends GenericService { @Override public Trainer addOne(@NotNull Trainer trainer) { - // TODO if this trainer has a pokemong, make sure that the pokemong's "trainer" field gets updated accordingly - // no validation, pokemongs can changes trainers easily in this app - return super.addOne(trainer); + Trainer persistedTrainer = super.addOne(trainer); + + pokemongService.batchUpdatePokemongTrainers(trainer.getPokemongs(), trainer.getId()); + + return persistedTrainer; } @Override public void deleteOneById(String id) { + Trainer trainer = getOneById(id); + + if (trainer != null) { + pokemongService.batchUpdatePokemongTrainers(trainer.getPokemongs(), null); + } + super.deleteOneById(id); - // TODO set trainer reference to null in any pokemong who may have it in their "trainer" field } @Nullable @@ -109,10 +117,11 @@ public class TrainerService extends GenericService { errors.add("pokemong with id " + pokemongId + " cannot be a " + pokemong.getSpecies()); } + Pokemong pokemongBehind = pokemongService.getOneById(pokemongId); if (pokemong.getNickname() != null + && pokemongBehind != null && !pokemong.getNickname() - .equals(pokemongService.getOneById(pokemongId) - .getNickname())) + .equals(pokemongBehind.getNickname())) { errors.add("pokemong with id " + pokemongId + " already has a nickname"); }