🌊 Manage relationships and cascading

pull/4/head
Alexis Drai 2 years ago
parent af2f90890c
commit 86fe122d0c

@ -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")

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 51 KiB

@ -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<PokemongName> getEvoTrack() {
return evoTrack;
}
public void setEvoTrack(List<PokemongName> 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<PokemongName> getEvoTrack() {
return evoTrack;
}
public Integer getEvoStage() {
return evoStage;
}
public void setEvoStage(Integer evoStage) {
this.evoStage = evoStage;
}
public void setEvoTrack(List<PokemongName> evoTrack) {
this.evoTrack = evoTrack;
}
}

@ -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<Pokemong> {
@ -44,8 +42,4 @@ public class PokemongRepository extends GenericRepository<Pokemong> {
return db.getCollection(Pokemong.COLLECTION_NAME, Pokemong.class);
}
public List<Pokemong> findByTrainer(String trainerId) {
return getCollection().find(eq("trainer", new ObjectId(trainerId)))
.into(new ArrayList<>());
}
}

@ -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<Trainer> {
@ -30,12 +24,6 @@ public class TrainerRepository extends GenericRepository<Trainer> {
setMongoClient(mongoClient);
}
public List<Trainer> findByPokemong(String pokemongId) {
Bson filter = Filters.elemMatch("pokemongs", Filters.eq("_id", new ObjectId(pokemongId)));
return getCollection().find(filter)
.into(new ArrayList<>());
}
@Override
protected MongoCollection<Trainer> getCollection() {
MongoDatabase db = mongoClient.getDatabase(DB_NAME);

@ -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<Pokemong> {
@Inject
MoveService moveService;
@Inject
TrainerService trainerService;
@PostConstruct
public void init() {
setRepository(pokemongRepository);
@ -33,15 +35,34 @@ public class PokemongService extends GenericService<Pokemong> {
@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<Pokemong> {
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<Pokemong> {
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<TrainerPokemong> trainerPokemongs, @Nullable String trainerId) {
for (TrainerPokemong trainerPokemong : trainerPokemongs) {
Pokemong pokemong = getOneById(trainerPokemong.getId());
if (pokemong != null) {
pokemong.setTrainer(trainerId);
updateOne(pokemong);
}
}
}
}

@ -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<Trainer> {
@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<Trainer> {
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");
}

Loading…
Cancel
Save