🛢️ 🚨 Implement bulk operations, lint the code

pull/5/head
Alexis Drai 2 years ago
parent 05e15ba5ba
commit 436ebc976b

1
.gitignore vendored

@ -85,3 +85,4 @@ gradle-app.setting
# Others
docs/todos.md
/src/test/resources/application.properties
/docs/sample-dataset/load_data.sh

@ -153,7 +153,7 @@
],
"body": {
"mode": "raw",
"raw": "{\r\n \"nickname\": \"Now with moves\",\r\n \"dob\": \"2023-05-07\",\r\n \"level\": 1,\r\n \"pokedexId\": 172,\r\n \"evoStage\": 1,\r\n \"evoTrack\": [\"PICHU\", \"PIKACHU\", \"RAICHU\"],\r\n \"types\": [\r\n {\r\n \"name\": \"ELECTRIC\",\r\n \"weakAgainst\": [\"GROUND\", \"ROCK\"],\r\n \"effectiveAgainst\": [\"WATER\", \"FLYING\"]\r\n }\r\n ],\r\n \"moveSet\": \r\n [\r\n {\r\n \"id\": \"60a64f7eae945a6e60b0e917\",\r\n \"name\": \"Ember\"\r\n }\r\n ],\r\n \"schemaVersion\": 1\r\n}"
"raw": "{\r\n \"nickname\": \"Blappity-bloop\",\r\n \"dob\": \"2023-05-07\",\r\n \"level\": 1,\r\n \"pokedexId\": 172,\r\n \"evoStage\": 1,\r\n \"evoTrack\": [\"PICHU\", \"PIKACHU\", \"RAICHU\"],\r\n \"types\": [\r\n {\r\n \"name\": \"ELECTRIC\",\r\n \"weakAgainst\": [\"GROUND\", \"ROCK\"],\r\n \"effectiveAgainst\": [\"WATER\", \"FLYING\"]\r\n }\r\n ],\r\n \"moveSet\": \r\n [\r\n {\r\n \"id\": \"60a64f7eae945a6e60b0e917\",\r\n \"name\": \"Ember\"\r\n }\r\n ],\r\n \"schemaVersion\": 1\r\n}"
},
"url": {
"raw": "http://localhost:8080/pokemong",
@ -243,7 +243,7 @@
"method": "DELETE",
"header": [],
"url": {
"raw": "http://localhost:8080/pokemong/60a64f7eae945a6e60b0e911",
"raw": "http://localhost:8080/pokemong/60a64f7eae945a6e60b0e916",
"protocol": "http",
"host": [
"localhost"
@ -251,7 +251,7 @@
"port": "8080",
"path": [
"pokemong",
"60a64f7eae945a6e60b0e911"
"60a64f7eae945a6e60b0e916"
]
}
},

@ -20,7 +20,7 @@ public class MoveCodec extends GenericCodec<Move> {
public MoveCodec() {
this.documentCodec = MongoClientSettings.getDefaultCodecRegistry()
.get(Document.class);
.get(Document.class);
}
@Override
@ -42,8 +42,8 @@ public class MoveCodec extends GenericCodec<Move> {
Type moveType = move.getType();
Document typeDoc = new Document();
typeDoc.put("name",
moveType.getName()
.toString());
moveType.getName()
.toString());
typeDoc.put("weakAgainst", moveType.getWeakAgainst());
typeDoc.put("effectiveAgainst", moveType.getEffectiveAgainst());
doc.put("type", typeDoc);
@ -74,7 +74,7 @@ public class MoveCodec extends GenericCodec<Move> {
Move move = new Move();
move.setId(document.getObjectId("_id")
.toString());
.toString());
move.setSchemaVersion(document.getInteger("schemaVersion"));
@ -100,7 +100,7 @@ public class MoveCodec extends GenericCodec<Move> {
Move move = new Move();
move.setId(document.getObjectId("_id")
.toString());
.toString());
move.setSchemaVersion(document.getInteger("schemaVersion"));

@ -27,7 +27,7 @@ public class PokemongCodec extends GenericCodec<Pokemong> {
public PokemongCodec() {
this.documentCodec = MongoClientSettings.getDefaultCodecRegistry()
.get(Document.class);
.get(Document.class);
}
@Override
@ -42,8 +42,8 @@ public class PokemongCodec extends GenericCodec<Pokemong> {
doc.put("dob",
Date.from(pokemong.getDob()
.atStartOfDay(ZoneId.systemDefault())
.toInstant()));
.atStartOfDay(ZoneId.systemDefault())
.toInstant()));
doc.put("level", pokemong.getLevel());
@ -52,9 +52,9 @@ public class PokemongCodec extends GenericCodec<Pokemong> {
doc.put("evoStage", pokemong.getEvoStage());
List<String> evoTrack = pokemong.getEvoTrack()
.stream()
.map(Enum::name)
.collect(Collectors.toList());
.stream()
.map(Enum::name)
.collect(Collectors.toList());
doc.put("evoTrack", evoTrack);
if (pokemong.getTrainer() != null) {
@ -62,36 +62,36 @@ public class PokemongCodec extends GenericCodec<Pokemong> {
}
List<Document> types = pokemong.getTypes()
.stream()
.map(type -> {
Document typeDoc = new Document();
typeDoc.put("name",
type.getName()
.name());
List<String> weakAgainst = type.getWeakAgainst()
.stream()
.map(Enum::name)
.collect(Collectors.toList());
typeDoc.put("weakAgainst", weakAgainst);
List<String> effectiveAgainst = type.getEffectiveAgainst()
.stream()
.map(Enum::name)
.collect(Collectors.toList());
typeDoc.put("effectiveAgainst", effectiveAgainst);
return typeDoc;
})
.collect(Collectors.toList());
.stream()
.map(type -> {
Document typeDoc = new Document();
typeDoc.put("name",
type.getName()
.name());
List<String> weakAgainst = type.getWeakAgainst()
.stream()
.map(Enum::name)
.collect(Collectors.toList());
typeDoc.put("weakAgainst", weakAgainst);
List<String> effectiveAgainst = type.getEffectiveAgainst()
.stream()
.map(Enum::name)
.collect(Collectors.toList());
typeDoc.put("effectiveAgainst", effectiveAgainst);
return typeDoc;
})
.collect(Collectors.toList());
doc.put("types", types);
List<Document> moveSetDocs = pokemong.getMoveSet()
.stream()
.map(move -> {
Document moveDoc = new Document();
moveDoc.put("_id", new ObjectId(move.getId()));
moveDoc.put("name", move.getName());
return moveDoc;
})
.collect(Collectors.toList());
.stream()
.map(move -> {
Document moveDoc = new Document();
moveDoc.put("_id", new ObjectId(move.getId()));
moveDoc.put("name", move.getName());
return moveDoc;
})
.collect(Collectors.toList());
doc.put("moveSet", moveSetDocs);
documentCodec.encode(writer, doc, encoderContext);
@ -118,7 +118,7 @@ public class PokemongCodec extends GenericCodec<Pokemong> {
Pokemong pokemong = new Pokemong();
pokemong.setId(document.getObjectId("_id")
.toString());
.toString());
pokemong.setSchemaVersion(document.getInteger("schemaVersion"));
@ -127,8 +127,8 @@ public class PokemongCodec extends GenericCodec<Pokemong> {
Date dob = document.getDate("dob");
if (dob != null) {
pokemong.setDob(dob.toInstant()
.atZone(ZoneId.systemDefault())
.toLocalDate());
.atZone(ZoneId.systemDefault())
.toLocalDate());
}
pokemong.setLevel(document.getInteger("level"));
@ -138,9 +138,9 @@ public class PokemongCodec extends GenericCodec<Pokemong> {
pokemong.setEvoStage(document.getInteger("evoStage"));
List<PokemongName> evoTrack = document.getList("evoTrack", String.class)
.stream()
.map(PokemongName::valueOf)
.collect(Collectors.toList());
.stream()
.map(PokemongName::valueOf)
.collect(Collectors.toList());
pokemong.setEvoTrack(evoTrack);
ObjectId trainerId = document.getObjectId("trainer");
@ -149,20 +149,20 @@ public class PokemongCodec extends GenericCodec<Pokemong> {
}
Set<Type> types = document.getList("types", Document.class)
.stream()
.map(TypeCodecUtil::extractType)
.collect(Collectors.toSet());
.stream()
.map(TypeCodecUtil::extractType)
.collect(Collectors.toSet());
pokemong.setTypes(types);
Set<PokemongMove> moveSet = document.getList("moveSet", Document.class)
.stream()
.map(pokemongMoveDoc -> {
PokemongMove move = new PokemongMove();
move.setId(((ObjectId) pokemongMoveDoc.get("_id")).toString());
move.setName(pokemongMoveDoc.getString("name"));
return move;
})
.collect(Collectors.toSet());
.stream()
.map(pokemongMoveDoc -> {
PokemongMove move = new PokemongMove();
move.setId(((ObjectId) pokemongMoveDoc.get("_id")).toString());
move.setName(pokemongMoveDoc.getString("name"));
return move;
})
.collect(Collectors.toSet());
pokemong.setMoveSet(moveSet);
return pokemong;

@ -26,7 +26,50 @@ public class TrainerCodec extends GenericCodec<Trainer> {
public TrainerCodec() {
this.documentCodec = MongoClientSettings.getDefaultCodecRegistry()
.get(Document.class);
.get(Document.class);
}
@NotNull
private static Trainer decodeV1(Document document) {
Trainer trainer = new Trainer();
trainer.setId(document.getObjectId("_id")
.toString());
trainer.setSchemaVersion(document.getInteger("schemaVersion"));
trainer.setName(document.getString("name"));
Date dob = document.getDate("dob");
if (dob != null) {
trainer.setDob(dob.toInstant()
.atZone(ZoneId.systemDefault())
.toLocalDate());
}
trainer.setWins(document.getInteger("wins"));
trainer.setLosses(document.getInteger("losses"));
List<String> pastOpponentsIds = document.getList("pastOpponents", ObjectId.class)
.stream()
.map(ObjectId::toString)
.collect(Collectors.toList());
trainer.setPastOpponents(pastOpponentsIds);
Set<TrainerPokemong> pokemongList = document
.getList("pokemongs", Document.class)
.stream()
.map(pokemongDoc -> {
TrainerPokemong pokemong = new TrainerPokemong();
pokemong.setId(((ObjectId) pokemongDoc.get("_id")).toString());
pokemong.setNickname(pokemongDoc.getString("nickname"));
pokemong.setSpecies(PokemongName.valueOf(pokemongDoc.getString("species")));
return pokemong;
})
.collect(Collectors.toSet());
trainer.setPokemongs(pokemongList);
return trainer;
}
@Override
@ -42,7 +85,7 @@ public class TrainerCodec extends GenericCodec<Trainer> {
LocalDate dob = trainer.getDob();
if (dob != null) {
doc.put("dob", Date.from(dob.atStartOfDay(ZoneId.systemDefault())
.toInstant()));
.toInstant()));
}
doc.put("wins", trainer.getWins());
@ -50,23 +93,23 @@ public class TrainerCodec extends GenericCodec<Trainer> {
doc.put("losses", trainer.getLosses());
List<ObjectId> pastOpponentsIds = trainer.getPastOpponents()
.stream()
.map(ObjectId::new)
.collect(Collectors.toList());
.stream()
.map(ObjectId::new)
.collect(Collectors.toList());
doc.put("pastOpponents", pastOpponentsIds);
List<Document> pokemongListDoc = trainer.getPokemongs()
.stream()
.map(pokemong -> {
Document moveDoc = new Document();
moveDoc.put("_id", new ObjectId(pokemong.getId()));
moveDoc.put("nickname", pokemong.getNickname());
moveDoc.put("species",
pokemong.getSpecies()
.name());
return moveDoc;
})
.collect(Collectors.toList());
.stream()
.map(pokemong -> {
Document moveDoc = new Document();
moveDoc.put("_id", new ObjectId(pokemong.getId()));
moveDoc.put("nickname", pokemong.getNickname());
moveDoc.put("species",
pokemong.getSpecies()
.name());
return moveDoc;
})
.collect(Collectors.toList());
doc.put("pokemongs", pokemongListDoc);
documentCodec.encode(writer, doc, encoderContext);
@ -88,47 +131,4 @@ public class TrainerCodec extends GenericCodec<Trainer> {
default -> throw new IllegalArgumentException("Unsupported schema version: " + schemaVersion);
};
}
@NotNull
private static Trainer decodeV1(Document document) {
Trainer trainer = new Trainer();
trainer.setId(document.getObjectId("_id")
.toString());
trainer.setSchemaVersion(document.getInteger("schemaVersion"));
trainer.setName(document.getString("name"));
Date dob = document.getDate("dob");
if (dob != null) {
trainer.setDob(dob.toInstant()
.atZone(ZoneId.systemDefault())
.toLocalDate());
}
trainer.setWins(document.getInteger("wins"));
trainer.setLosses(document.getInteger("losses"));
List<String> pastOpponentsIds = document.getList("pastOpponents", ObjectId.class)
.stream()
.map(ObjectId::toString)
.collect(Collectors.toList());
trainer.setPastOpponents(pastOpponentsIds);
Set<TrainerPokemong> pokemongList = document
.getList("pokemongs", Document.class)
.stream()
.map(pokemongDoc -> {
TrainerPokemong pokemong = new TrainerPokemong();
pokemong.setId(((ObjectId) pokemongDoc.get("_id")).toString());
pokemong.setNickname(pokemongDoc.getString("nickname"));
pokemong.setSpecies(PokemongName.valueOf(pokemongDoc.getString("species")));
return pokemong;
})
.collect(Collectors.toSet());
trainer.setPokemongs(pokemongList);
return trainer;
}
}

@ -12,15 +12,15 @@ public class TypeCodecUtil {
Type type = new Type();
type.setName(TypeName.valueOf(typeDoc.getString("name")));
List<TypeName> weakAgainst = typeDoc.getList("weakAgainst", String.class)
.stream()
.map(TypeName::valueOf)
.collect(Collectors.toList());
.stream()
.map(TypeName::valueOf)
.collect(Collectors.toList());
type.setWeakAgainst(weakAgainst);
List<TypeName> effectiveAgainst = typeDoc.getList("effectiveAgainst",
String.class)
.stream()
.map(TypeName::valueOf)
.collect(Collectors.toList());
String.class)
.stream()
.map(TypeName::valueOf)
.collect(Collectors.toList());
type.setEffectiveAgainst(effectiveAgainst);
return type;
}

@ -22,24 +22,23 @@ public abstract class GenericController<T extends GenericEntity> {
T entity = service.getOneById(id);
if (entity != null) {
return Response.ok(entity)
.build();
}
else {
.build();
} else {
return Response.status(Response.Status.NOT_FOUND)
.entity("Entity not found for id: " + id)
.build();
.entity("Entity not found for id: " + id)
.build();
}
} catch (IllegalArgumentException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity("Invalid id format: " + id)
.build();
.entity(e.getMessage())
.build();
}
}
@GET
public Response getAll() {
return Response.ok(service.getAll())
.build();
.build();
}
@POST
@ -50,13 +49,13 @@ public abstract class GenericController<T extends GenericEntity> {
T newEntity = service.addOne(entity);
return Response.status(Response.Status.CREATED)
.entity(newEntity)
.build();
.entity(newEntity)
.build();
} catch (NonValidEntityException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(e.getMessage())
.build();
.entity(e.getMessage())
.build();
}
}
@ -70,22 +69,17 @@ public abstract class GenericController<T extends GenericEntity> {
if (updatedEntity != null) {
return Response.status(Response.Status.OK)
.entity(updatedEntity)
.build();
}
else {
.entity(updatedEntity)
.build();
} else {
return Response.status(Response.Status.NOT_FOUND)
.entity("Entity not found for id: " + id)
.build();
.entity("Entity not found for id: " + id)
.build();
}
} catch (IllegalArgumentException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity("Invalid id format: " + id)
.build();
} catch (NonValidEntityException e) {
} catch (IllegalArgumentException | NonValidEntityException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(e.getMessage())
.build();
.entity(e.getMessage())
.build();
}
}
@ -95,12 +89,12 @@ public abstract class GenericController<T extends GenericEntity> {
try {
service.deleteOneById(id);
return Response.ok()
.build();
.build();
} catch (IllegalArgumentException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity("Invalid id format: " + id)
.build();
.entity(e.getMessage())
.build();
}
}
}

@ -13,7 +13,8 @@ public class Move extends GenericVersionedEntity {
private Integer accuracy;
private Type type;
public Move() {}
public Move() {
}
public String getName() {
return name;

@ -31,7 +31,8 @@ public class Pokemong extends GenericVersionedEntity {
*/
private Set<PokemongMove> moveSet;
public Pokemong() {}
public Pokemong() {
}
@Nullable
public String getNickname() {
@ -100,8 +101,7 @@ public class Pokemong extends GenericVersionedEntity {
public void updateMove(String id, String name) {
for (PokemongMove move : moveSet) {
if (move.getId()
.equals(id))
{
.equals(id)) {
move.setName(name);
break;
}
@ -116,6 +116,10 @@ public class Pokemong extends GenericVersionedEntity {
return Collections.unmodifiableList(evoTrack);
}
public void setEvoTrack(List<PokemongName> evoTrack) {
this.evoTrack = evoTrack;
}
public Integer getEvoStage() {
return evoStage;
}
@ -123,9 +127,5 @@ public class Pokemong extends GenericVersionedEntity {
public void setEvoStage(Integer evoStage) {
this.evoStage = evoStage;
}
public void setEvoTrack(List<PokemongName> evoTrack) {
this.evoTrack = evoTrack;
}
}

@ -18,7 +18,8 @@ public class Trainer extends GenericVersionedEntity {
private List<String> pastOpponents;
private Set<TrainerPokemong> pokemongs;
public Trainer() {}
public Trainer() {
}
public String getName() {
return name;
@ -72,7 +73,7 @@ public class Trainer extends GenericVersionedEntity {
pokemongs.add(trainerPokemong);
}
public void removePokemong(TrainerPokemong trainerPokemong) {
pokemongs.remove(trainerPokemong);
public void removePokemong(String id) {
pokemongs.removeIf(trainerPokemong -> trainerPokemong.getId().equals(id));
}
}

@ -6,7 +6,8 @@ public class PokemongMove extends GenericEntity {
private String name;
public PokemongMove() {}
public PokemongMove() {
}
public String getName() {
return name;

@ -10,7 +10,8 @@ public class TrainerPokemong extends GenericEntity {
private PokemongName species;
public TrainerPokemong() {}
public TrainerPokemong() {
}
@Nullable
public String getNickname() {

@ -11,7 +11,8 @@ public class Type {
private List<TypeName> weakAgainst;
private List<TypeName> effectiveAgainst;
public Type() {}
public Type() {
}
public TypeName getName() {
return name;
@ -48,8 +49,8 @@ public class Type {
if (o == null || getClass() != o.getClass()) return false;
Type type = (Type) o;
return Objects.equals(name, type.name) &&
Objects.equals(weakAgainst, type.weakAgainst) &&
Objects.equals(effectiveAgainst, type.effectiveAgainst);
Objects.equals(weakAgainst, type.weakAgainst) &&
Objects.equals(effectiveAgainst, type.effectiveAgainst);
}
}

@ -2,7 +2,9 @@ package fr.uca.iut.repositories;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.model.ReplaceOneModel;
import com.mongodb.client.model.ReplaceOptions;
import com.mongodb.client.model.WriteModel;
import com.mongodb.lang.Nullable;
import fr.uca.iut.entities.GenericEntity;
import org.bson.Document;
@ -27,7 +29,7 @@ public abstract class GenericRepository<T extends GenericEntity> {
@Nullable
public T findById(String id) {
return getCollection().find(eq("_id", new ObjectId(id)))
.first();
.first();
}
protected abstract MongoCollection<T> getCollection();
@ -38,7 +40,7 @@ public abstract class GenericRepository<T extends GenericEntity> {
public List<T> listAll() {
return getCollection().find()
.into(new ArrayList<>());
.into(new ArrayList<>());
}
public void persistOrUpdate(@NotNull T entity) {
@ -49,6 +51,21 @@ public abstract class GenericRepository<T extends GenericEntity> {
);
}
public void updateAll(@NotNull List<T> entities) {
List<WriteModel<T>> updates = new ArrayList<>();
for (T entity : entities) {
updates.add(
new ReplaceOneModel<>(
eq("_id", new ObjectId(entity.getId())),
entity,
new ReplaceOptions().upsert(true)
)
);
}
getCollection().bulkWrite(updates);
}
public void delete(@NotNull T entity) {
getCollection().deleteOne(eq("_id", new ObjectId(entity.getId())));
}

@ -33,7 +33,7 @@ public class PokemongRepository extends GenericRepository<Pokemong> {
public List<Pokemong> findByMove(String moveId) {
Bson filter = Filters.elemMatch("moveSet", Filters.eq("_id", new ObjectId(moveId)));
return getCollection().find(filter)
.into(new ArrayList<>());
.into(new ArrayList<>());
}
@Override

@ -48,11 +48,20 @@ public abstract class GenericService<T extends GenericEntity> {
}
/**
* Override me and start with `super.validateOne(entity);`
* Override me
*/
@Nullable
public T updateOne(@NotNull T entity) {
validateOne(entity);
return entity;
}
public void updateAll(List<T> entities) {
if (!entities.isEmpty()) {
for (T entity : entities) {
validateOne(entity);
}
repository.updateAll(entities);
}
}
}

@ -74,18 +74,20 @@ public class MoveService extends GenericService<Move> {
@Override
public List<Move> getAll() {
return super.getAll()
.stream()
.map(this::migrateToV2)
.collect(Collectors.toList());
.stream()
.map(this::migrateToV2)
.collect(Collectors.toList());
}
@Override
public void deleteOneById(String id) {
List<Pokemong> pokemongs = pokemongService.findByMove(id);
List<Pokemong> pokemongsToUpdate = new ArrayList<>();
for (Pokemong pokemong : pokemongs) {
pokemong.removeMove(id);
pokemongService.updateOne(pokemong);
pokemongsToUpdate.add(pokemong);
}
pokemongService.updateAll(pokemongsToUpdate);
super.deleteOneById(id);
}
@ -95,15 +97,9 @@ public class MoveService extends GenericService<Move> {
super.updateOne(move);
Move existingMove = moveRepository.findById(move.getId());
if (existingMove != null) {
if (!existingMove.getName()
.equals(move.getName()))
{
if (!existingMove.getName().equals(move.getName())) {
existingMove.setName(move.getName());
List<Pokemong> pokemongs = pokemongService.findByMove(move.getId());
for (Pokemong pokemong : pokemongs) {
pokemong.updateMove(move.getId(), move.getName());
pokemongService.updateOne(pokemong);
}
batchUpdatePokemongTrainers(move);
}
existingMove.setPower(move.getPower());
@ -115,6 +111,16 @@ public class MoveService extends GenericService<Move> {
return existingMove;
}
private void batchUpdatePokemongTrainers(@NotNull Move move) {
List<Pokemong> pokemongs = pokemongService.findByMove(move.getId());
List<Pokemong> pokemongsToUpdate = new ArrayList<>();
for (Pokemong pokemong : pokemongs) {
pokemong.updateMove(move.getId(), move.getName());
pokemongsToUpdate.add(pokemong);
}
pokemongService.updateAll(pokemongsToUpdate);
}
/**
* We want to migrate the documents incrementally, so we upgrade the
* schema version if it is less than the current schema version,

@ -84,17 +84,15 @@ public class PokemongService extends GenericService<Pokemong> {
Set<Type> types = pokemong.getTypes();
if (types == null
|| types.size() == 0
|| types.size() > 2)
{
|| types.size() == 0
|| types.size() > 2) {
errors.add("pokemong types was null or empty or had more than 2 types");
}
Set<PokemongMove> moveSet = pokemong.getMoveSet();
if (moveSet == null) {
errors.add("pokemong move set was null");
}
else {
} else {
if (moveSet.size() == 0 || moveSet.size() > 4) {
errors.add("pokemong move set was empty or had more than 4 moves");
}
@ -114,8 +112,7 @@ public class PokemongService extends GenericService<Pokemong> {
}
if (pokemong.getSchemaVersion() == null ||
!Objects.equals(pokemong.getSchemaVersion(), Pokemong.LATEST_SCHEMA_VERSION))
{
!Objects.equals(pokemong.getSchemaVersion(), Pokemong.LATEST_SCHEMA_VERSION)) {
errors.add(
"pokemong schema version was null or not the latest version: " + Pokemong.LATEST_SCHEMA_VERSION);
}
@ -131,9 +128,7 @@ public class PokemongService extends GenericService<Pokemong> {
if (pokemong != null && pokemong.getTrainer() != null) {
Trainer trainer = trainerService.getOneById(pokemong.getTrainer());
if (trainer != null) {
trainer.getPokemongs()
.removeIf(trainerPokemong -> trainerPokemong.getId()
.equals(id));
trainer.removePokemong(id);
trainerService.updateOne(trainer);
}
}
@ -163,32 +158,41 @@ public class PokemongService extends GenericService<Pokemong> {
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);
}
}
updateTrainerPokemong(existingPokemong, nicknameChanged, evoStageChanged, evoTrackChanged);
}
}
return existingPokemong;
}
private void updateTrainerPokemong(
@NotNull Pokemong existingPokemong,
boolean nicknameChanged,
boolean evoStageChanged,
boolean 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);
}
}
}
public List<Pokemong> findByMove(String id) {
return pokemongRepository.findByMove(id);
}
@ -204,14 +208,15 @@ public class PokemongService extends GenericService<Pokemong> {
}
public void batchUpdatePokemongTrainers(@NotNull Set<TrainerPokemong> trainerPokemongs,
@Nullable String trainerId)
{
@Nullable String trainerId) {
List<Pokemong> pokemongsToUpdate = new ArrayList<>();
for (TrainerPokemong trainerPokemong : trainerPokemongs) {
Pokemong pokemong = getOneById(trainerPokemong.getId());
if (pokemong != null && !Objects.equals(pokemong.getTrainer(), trainerId)) {
pokemong.setTrainer(trainerId);
updateOne(pokemong);
pokemongsToUpdate.add(pokemong);
}
}
updateAll(pokemongsToUpdate);
}
}

@ -33,7 +33,7 @@ public class TrainerService extends GenericService<Trainer> {
public Trainer addOne(@NotNull Trainer trainer) {
Trainer persistedTrainer = super.addOne(trainer);
// If this trainer gained pokemongs, that pokemong's ex-trainer if any needs to lose said pokemong
// If this trainer gained pokemongs, that pokemong's ex-trainer if any needs to lose said pokemongs
transferNewlyArrivedTrainerPokemongs(new HashSet<>(), persistedTrainer.getPokemongs());
// all owned pokemongs gain this trainer's reference
pokemongService.batchUpdatePokemongTrainers(trainer.getPokemongs(), trainer.getId());
@ -68,8 +68,7 @@ public class TrainerService extends GenericService<Trainer> {
if (pastOpponents == null) {
errors.add("trainer past opponents collection was null");
}
else {
} else {
for (String trainerId : pastOpponents) {
if (StringUtils.isBlankStringOrNull(trainerId)) {
errors.add("trainer past opponents collection contained an invalid id: " + trainerId);
@ -81,24 +80,21 @@ public class TrainerService extends GenericService<Trainer> {
if (pokemongs == null) {
errors.add("trainer pokemongs collection was null or invalid");
}
else {
} else {
for (TrainerPokemong pokemong : pokemongs) {
String pokemongId = pokemong.getId();
if (StringUtils.isBlankStringOrNull(pokemongId) || !pokemongService.existsById(pokemongId)) {
errors.add("pokemong with id " + pokemongId + " does not exist");
}
else {
} else {
if (!pokemongService.isEvoValid(pokemongId, pokemong.getSpecies())) {
errors.add("pokemong with id " + pokemongId + " cannot be a " +
pokemong.getSpecies());
pokemong.getSpecies());
}
Pokemong pokemongBehind = pokemongService.getOneById(pokemongId);
if (pokemong.getNickname() != null
&& pokemongBehind != null
&& !pokemong.getNickname()
.equals(pokemongBehind.getNickname()))
{
&& pokemongBehind != null
&& !pokemong.getNickname()
.equals(pokemongBehind.getNickname())) {
errors.add("pokemong with id " + pokemongId + " already has a nickname");
}
}
@ -106,8 +102,7 @@ public class TrainerService extends GenericService<Trainer> {
}
if (trainer.getSchemaVersion() == null ||
!Objects.equals(trainer.getSchemaVersion(), Trainer.LATEST_SCHEMA_VERSION))
{
!Objects.equals(trainer.getSchemaVersion(), Trainer.LATEST_SCHEMA_VERSION)) {
errors.add("trainer schema version was null or not the latest version: " + Trainer.LATEST_SCHEMA_VERSION);
}
@ -148,16 +143,16 @@ public class TrainerService extends GenericService<Trainer> {
// all old pokemongs who are not there anymore lose their trainer reference
pokemongService.batchUpdatePokemongTrainers(
oldPokemongs.stream()
.filter(tp -> !newPokemongs.contains(tp))
.collect(Collectors.toSet()),
.filter(tp -> !newPokemongs.contains(tp))
.collect(Collectors.toSet()),
null);
// If this trainer gained a pokemong, that pokemong's ex-trainer if any needs to lose said pokemong
transferNewlyArrivedTrainerPokemongs(oldPokemongs, newPokemongs);
// all new pokemongs who were not there before gain this trainer's reference
pokemongService.batchUpdatePokemongTrainers(
newPokemongs.stream()
.filter(tp -> !oldPokemongs.contains(tp))
.collect(Collectors.toSet()),
.filter(tp -> !oldPokemongs.contains(tp))
.collect(Collectors.toSet()),
existingTrainer.getId());
}
return existingTrainer;
@ -166,23 +161,25 @@ public class TrainerService extends GenericService<Trainer> {
private void transferNewlyArrivedTrainerPokemongs(
@NotNull Set<TrainerPokemong> oldPokemongs,
@NotNull Set<TrainerPokemong> newPokemongs
)
{
for (TrainerPokemong tp : newPokemongs) {
if (oldPokemongs.isEmpty() || !oldPokemongs.contains(tp)) {
Pokemong pokemong = pokemongService.getOneById(tp.getId());
) {
List<Trainer> trainersToUpdate = new ArrayList<>();
for (TrainerPokemong newTrainerPokemong : newPokemongs) {
if (oldPokemongs.isEmpty() || !oldPokemongs.contains(newTrainerPokemong)) {
Pokemong pokemong = pokemongService.getOneById(newTrainerPokemong.getId());
if (pokemong != null) {
String oldTrainerId = pokemong.getTrainer();
// If the pokemong already had a trainer, remove it from the old trainer's pokemongs list
if (oldTrainerId != null) {
Trainer oldTrainer = getOneById(oldTrainerId);
if (oldTrainer != null) {
oldTrainer.removePokemong(tp);
updateOne(oldTrainer);
oldTrainer.removePokemong(newTrainerPokemong.getId());
trainersToUpdate.add(oldTrainer);
}
}
}
}
}
updateAll(trainersToUpdate);
}
}

Loading…
Cancel
Save