From e9c468fdc8b35d8c57d5ca3344036e9794aebb83 Mon Sep 17 00:00:00 2001 From: "alexis.drai@etu.uca.fr" Date: Sat, 27 May 2023 03:08:19 +0200 Subject: [PATCH] :construction: :necktie: Implement Move, polish Pokemong, create Generics --- .gitignore | 3 + build.gradle | 84 +++--- docs/DB.md | 46 ++- .../java/fr/uca/iut/codecs/GenericCodec.java | 89 +++--- .../fr/uca/iut/codecs/move/MoveCodec.java | 78 +++++ .../iut/codecs/move/MoveCodecProvider.java | 18 ++ .../iut/codecs/pokemong/PokemongCodec.java | 276 ++++++++++-------- .../pokemong/PokemongCodecProvider.java | 32 +- .../uca/iut/codecs/trainer/TrainerCodec.java | 140 +++++---- .../codecs/trainer/TrainerCodecProvider.java | 34 ++- .../fr/uca/iut/codecs/type/TypeCodec.java | 67 ----- .../iut/codecs/type/TypeCodecProvider.java | 16 - .../fr/uca/iut/codecs/type/TypeCodecUtil.java | 27 ++ .../iut/controllers/GenericController.java | 108 +++++++ .../uca/iut/controllers/MoveController.java | 22 ++ .../iut/controllers/PokemongController.java | 124 ++------ .../fr/uca/iut/entities/GenericEntity.java | 64 ++-- src/main/java/fr/uca/iut/entities/Move.java | 118 ++++---- .../java/fr/uca/iut/entities/Pokemong.java | 240 +++++++-------- .../fr/uca/iut/entities/PokemongMove.java | 16 + .../java/fr/uca/iut/entities/Trainer.java | 146 +++++---- src/main/java/fr/uca/iut/entities/Type.java | 109 +++---- src/main/java/fr/uca/iut/package-info.java | 4 + .../iut/repositories/GenericRepository.java | 64 ++++ .../uca/iut/repositories/MoveRepository.java | 32 ++ .../iut/repositories/PokemongRepository.java | 100 +++---- .../fr/uca/iut/services/GenericService.java | 51 ++++ .../java/fr/uca/iut/services/MoveService.java | 88 ++++++ .../fr/uca/iut/services/PokemongService.java | 166 ++++++----- .../java/fr/uca/iut/utils/StringUtils.java | 7 + .../uca/iut/utils/enums/MoveCategoryName.java | 7 + .../iut/utils/{ => enums}/PokemongName.java | 2 +- .../uca/iut/utils/{ => enums}/TypeName.java | 2 +- .../exceptions/NonValidEntityException.java | 7 + src/main/resources/application.properties | 2 +- 35 files changed, 1401 insertions(+), 988 deletions(-) create mode 100644 src/main/java/fr/uca/iut/codecs/move/MoveCodec.java create mode 100644 src/main/java/fr/uca/iut/codecs/move/MoveCodecProvider.java delete mode 100644 src/main/java/fr/uca/iut/codecs/type/TypeCodec.java delete mode 100644 src/main/java/fr/uca/iut/codecs/type/TypeCodecProvider.java create mode 100644 src/main/java/fr/uca/iut/codecs/type/TypeCodecUtil.java create mode 100644 src/main/java/fr/uca/iut/controllers/GenericController.java create mode 100644 src/main/java/fr/uca/iut/controllers/MoveController.java create mode 100644 src/main/java/fr/uca/iut/entities/PokemongMove.java create mode 100644 src/main/java/fr/uca/iut/package-info.java create mode 100644 src/main/java/fr/uca/iut/repositories/GenericRepository.java create mode 100644 src/main/java/fr/uca/iut/repositories/MoveRepository.java create mode 100644 src/main/java/fr/uca/iut/services/GenericService.java create mode 100644 src/main/java/fr/uca/iut/services/MoveService.java create mode 100644 src/main/java/fr/uca/iut/utils/StringUtils.java create mode 100644 src/main/java/fr/uca/iut/utils/enums/MoveCategoryName.java rename src/main/java/fr/uca/iut/utils/{ => enums}/PokemongName.java (99%) rename src/main/java/fr/uca/iut/utils/{ => enums}/TypeName.java (87%) create mode 100644 src/main/java/fr/uca/iut/utils/exceptions/NonValidEntityException.java diff --git a/.gitignore b/.gitignore index 8c967c2..afff217 100644 --- a/.gitignore +++ b/.gitignore @@ -81,3 +81,6 @@ gradle-app.setting # Cache of project .gradletasknamecache + +# Others +docs/todos.md \ No newline at end of file diff --git a/build.gradle b/build.gradle index 5091209..e1dcfc9 100644 --- a/build.gradle +++ b/build.gradle @@ -1,43 +1,41 @@ -plugins { - id 'java' - id 'io.quarkus' -} - -repositories { - mavenCentral() - mavenLocal() -} - -dependencies { - // FIXME "Provides transitive vulnerable dependency maven:org.jboss.resteasy:resteasy-core:6.2.1.Final - // CVE-2023-0482 7.8 Creation of Temporary File With Insecure Permissions vulnerability with medium severity found - // Results powered by Checkmarx(c)" - implementation enforcedPlatform("${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:${quarkusPlatformVersion}") - implementation 'io.quarkus:quarkus-resteasy:3.0.0.Alpha6' - implementation 'io.quarkus:quarkus-resteasy-jackson:3.0.0.Alpha6' - implementation 'io.quarkus:quarkus-arc:3.0.0.Alpha6' - implementation 'io.quarkus:quarkus-mongodb-client:3.0.0.Alpha6' - implementation 'org.mongodb:mongodb-driver-sync:4.9.1' - testImplementation 'io.quarkus:quarkus-junit5:3.0.0.Alpha6' - testImplementation 'io.rest-assured:rest-assured:5.3.0' -} - -group 'fr.uca.iut' -version '1.0-SNAPSHOT' - -java { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 -} - -test { - systemProperty "java.util.logging.manager", "org.jboss.logmanager.LogManager" -} -compileJava { - options.encoding = 'UTF-8' - options.compilerArgs << '-parameters' -} - -compileTestJava { - options.encoding = 'UTF-8' -} +plugins { + id 'java' + id 'io.quarkus' +} + +repositories { + mavenCentral() + mavenLocal() +} + +dependencies { + implementation enforcedPlatform("${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:${quarkusPlatformVersion}") + implementation 'io.quarkus:quarkus-resteasy:3.0.0.Alpha6' + implementation 'io.quarkus:quarkus-resteasy-jackson:3.0.0.Alpha6' + implementation 'io.quarkus:quarkus-arc:3.0.0.Alpha6' + implementation 'io.quarkus:quarkus-mongodb-client:3.0.0.Alpha6' + implementation 'org.mongodb:mongodb-driver-sync:4.9.1' + implementation 'org.jetbrains:annotations:24.0.0' + testImplementation 'io.quarkus:quarkus-junit5:3.0.0.Alpha6' + testImplementation 'io.rest-assured:rest-assured:5.3.0' +} + +group 'fr.uca.iut' +version '1.0-SNAPSHOT' + +java { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 +} + +test { + systemProperty "java.util.logging.manager", "org.jboss.logmanager.LogManager" +} +compileJava { + options.encoding = 'UTF-8' + options.compilerArgs << '-parameters' +} + +compileTestJava { + options.encoding = 'UTF-8' +} diff --git a/docs/DB.md b/docs/DB.md index ce5bce5..1ffb967 100644 --- a/docs/DB.md +++ b/docs/DB.md @@ -6,11 +6,11 @@ * _id: ObjectId * name: string - * (_indexed_: would be queried often in a dashboard situation) + * (_indexed_: would often be queried in a dashboard situation) * dob: date * wins: int * losses: int -* past_opponents: array of ObjectId (references to other trainers) +* pastOpponents: array of ObjectId (references to other trainers) * (_indexed_: reflexivity would make deep queries quite slow, so it seems worthwhile) * pokemongs: array of ObjectId (references to owned pokemongs) + denormalizing on "nickname" and "species" * (_indexed_: to improve speed when querying non-denormalized fields) @@ -18,58 +18,56 @@ ### pokemongs collection * _id: ObjectId -* nickname: string +* nickname: string? * dob: date * level: int -* pokedex_id: int -* evo_stage: int +* pokedexId: int +* evoStage: int + * (_indexed_: "species" is calculated as evo_track[evo_stage], and would often be queried) +* evoTrack: array of strings (therefore "species" is evo_track[evo_stage], and "evo_base" is evo_track[0]) * (_indexed_: "species" is calculated as evo_track[evo_stage], and would be queried often) -* evo_track: array of strings (therefore "species" is evo_track[evo_stage], and "evo_base" is evo_track[0]) - * (_indexed_: "species" is calculated as evo_track[evo_stage], and xould be queried often) -* is_mega_evolved: boolean - * **polymorphic**: this field is only here for mature_pokemongs, i.e. pokemongs who have reached their last evo_stage * trainer: ObjectId? (reference to a trainer) (but can be "wild" instead, if ref is null) * (_indexed_: could be queried often in a dashboard situation) * types: embedded type, or array of embedded types - * (_indexed_: would be queried often in a dashboard situation) -* move_set: array of ObjectId (references to known moves) + denormalizing on "name" + * (_indexed_: would often be queried in a dashboard situation) +* moveSet: array of ObjectId (references to known moves) + denormalizing on "name" ### moves collection * _id: ObjectId * name: string - * (_indexed_: would be queried often in a dashboard situation) + * (_indexed_: would often be queried in a dashboard situation) * category: string (can be "physical", "special", or "status") * pp: int * power: int - * (_indexed_: would be used often in sorts, in a dashboard situation) + * (_indexed_: would often be used in sorts, in a dashboard situation) * accuracy: int * type: embedded type - * (_indexed_: would be queried often in a dashboard situation) + * (_indexed_: would often be queried in a dashboard situation) ### types collection * _id: ObjectId * name: string - * (_indexed_: would be queried often in a dashboard situation) -* weak_against: array of strings (denormalized type names) -* effective_against: array of strings (denormalized type names) + * (_indexed_: would often be queried in a dashboard situation) +* weakAgainst: array of strings (denormalized type names) +* effectiveAgainst: array of strings (denormalized type names) ## Relationships -* trainers.past_opponents: one-to-many and reflexive +* trainers.pastOpponents: one-to-many and reflexive * => referencing * trainers.pokemongs: one-to-many * => referencing + denormalizing on "nickname" and "species" * pokemongs.trainer: many-to-one * => referencing -* pokemongs.types: one-to-few [1;2] but will also need to be queried independently - * => denormalizing on all fields -* pokemongs.move_set: one-to-few [1;4] but will also need to be queried independently +* pokemongs.types: one-to-few [1;2] + * => embedding +* pokemongs.moveSet: one-to-few [1;4] but will also need to be queried independently * => referencing + denormalizing on "name" -* moves.type: one-to-one [1;1] but will also need to be queried independently - * => denormalizing on all fields -* types.weak_against & types.effective_against: one-to-few but reflexive +* moves.type: one-to-one [1;1] + * => embedding +* types.weakAgainst & types.effectiveAgainst: one-to-few, but reflexive * => denormalizing on "name" \ No newline at end of file diff --git a/src/main/java/fr/uca/iut/codecs/GenericCodec.java b/src/main/java/fr/uca/iut/codecs/GenericCodec.java index c948176..25faad3 100644 --- a/src/main/java/fr/uca/iut/codecs/GenericCodec.java +++ b/src/main/java/fr/uca/iut/codecs/GenericCodec.java @@ -1,48 +1,41 @@ -package fr.uca.iut.codecs; - -import com.mongodb.MongoClientSettings; -import fr.uca.iut.entities.GenericEntity; -import org.bson.*; -import org.bson.codecs.Codec; -import org.bson.codecs.CollectibleCodec; -import org.bson.codecs.DecoderContext; -import org.bson.codecs.EncoderContext; -import org.bson.types.ObjectId; - -public abstract class GenericCodec implements CollectibleCodec { - private final Codec documentCodec; - protected GenericCodec() { - this.documentCodec = MongoClientSettings.getDefaultCodecRegistry() - .get(Document.class); - } - - public Codec getDocumentCodec() { - return documentCodec; - } - @Override - public abstract void encode(BsonWriter writer, T entity, EncoderContext encoderContext); - - @Override - public abstract Class getEncoderClass(); - - @Override - public T generateIdIfAbsentFromDocument(T document) { - if (!documentHasId(document)) { - document.setId(new ObjectId().toString()); - } - return document; - } - - @Override - public boolean documentHasId(T document) { - return document.getId() != null; - } - - @Override - public BsonValue getDocumentId(T document) { - return new BsonObjectId(new ObjectId(document.getId())); - } - - @Override - public abstract T decode(BsonReader reader, DecoderContext decoderContext); -} +package fr.uca.iut.codecs; + +import fr.uca.iut.entities.GenericEntity; +import org.bson.BsonObjectId; +import org.bson.BsonReader; +import org.bson.BsonValue; +import org.bson.BsonWriter; +import org.bson.codecs.CollectibleCodec; +import org.bson.codecs.DecoderContext; +import org.bson.codecs.EncoderContext; +import org.bson.types.ObjectId; + +public abstract class GenericCodec implements CollectibleCodec { + + @Override + public abstract void encode(BsonWriter writer, T entity, EncoderContext encoderContext); + + @Override + public abstract Class getEncoderClass(); + + @Override + public T generateIdIfAbsentFromDocument(T document) { + if (!documentHasId(document)) { + document.setId(new ObjectId().toString()); + } + return document; + } + + @Override + public boolean documentHasId(T document) { + return document.getId() != null; + } + + @Override + public BsonValue getDocumentId(T document) { + return new BsonObjectId(new ObjectId(document.getId())); + } + + @Override + public abstract T decode(BsonReader reader, DecoderContext decoderContext); +} diff --git a/src/main/java/fr/uca/iut/codecs/move/MoveCodec.java b/src/main/java/fr/uca/iut/codecs/move/MoveCodec.java new file mode 100644 index 0000000..13b7ec8 --- /dev/null +++ b/src/main/java/fr/uca/iut/codecs/move/MoveCodec.java @@ -0,0 +1,78 @@ +package fr.uca.iut.codecs.move; + +import com.mongodb.MongoClientSettings; +import fr.uca.iut.codecs.GenericCodec; +import fr.uca.iut.codecs.type.TypeCodecUtil; +import fr.uca.iut.entities.Move; +import fr.uca.iut.entities.Type; +import fr.uca.iut.utils.enums.MoveCategoryName; +import org.bson.BsonReader; +import org.bson.BsonWriter; +import org.bson.Document; +import org.bson.codecs.Codec; +import org.bson.codecs.DecoderContext; +import org.bson.codecs.EncoderContext; +import org.bson.types.ObjectId; + +public class MoveCodec extends GenericCodec { + private final Codec documentCodec; + + public MoveCodec() { + this.documentCodec = MongoClientSettings.getDefaultCodecRegistry() + .get(Document.class); + } + + @Override + public void encode(BsonWriter writer, Move move, EncoderContext encoderContext) { + Document doc = new Document(); + + doc.put("_id", new ObjectId(move.getId())); + + doc.put("name", move.getName()); + + doc.put("category", move.getCategory()); + + doc.put("power", move.getPower()); + + doc.put("accuracy", move.getAccuracy()); + + Type moveType = move.getType(); + Document typeDoc = new Document(); + typeDoc.put("name", + moveType.getName() + .toString()); + typeDoc.put("weakAgainst", moveType.getWeakAgainst()); + typeDoc.put("effectiveAgainst", moveType.getEffectiveAgainst()); + doc.put("type", typeDoc); + + documentCodec.encode(writer, doc, encoderContext); + } + + @Override + public Class getEncoderClass() { + return Move.class; + } + + @Override + public Move decode(BsonReader reader, DecoderContext decoderContext) { + Document document = documentCodec.decode(reader, decoderContext); + Move move = new Move(); + + move.setId(document.getObjectId("_id") + .toString()); + + move.setName(document.getString("name")); + + move.setCategory(MoveCategoryName.valueOf(document.getString("category"))); + + move.setPower(document.getInteger("power")); + + move.setAccuracy(document.getInteger("accuracy")); + + Document typeDoc = (Document) document.get("type"); + + move.setType(TypeCodecUtil.extractType(typeDoc)); + + return move; + } +} diff --git a/src/main/java/fr/uca/iut/codecs/move/MoveCodecProvider.java b/src/main/java/fr/uca/iut/codecs/move/MoveCodecProvider.java new file mode 100644 index 0000000..312afd9 --- /dev/null +++ b/src/main/java/fr/uca/iut/codecs/move/MoveCodecProvider.java @@ -0,0 +1,18 @@ +package fr.uca.iut.codecs.move; + +import com.mongodb.lang.Nullable; +import fr.uca.iut.entities.Move; +import org.bson.codecs.Codec; +import org.bson.codecs.configuration.CodecProvider; +import org.bson.codecs.configuration.CodecRegistry; + +public class MoveCodecProvider implements CodecProvider { + @Nullable + @Override + public Codec get(Class clazz, CodecRegistry registry) { + if (clazz.equals(Move.class)) { + return (Codec) new MoveCodec(); + } + return null; + } +} diff --git a/src/main/java/fr/uca/iut/codecs/pokemong/PokemongCodec.java b/src/main/java/fr/uca/iut/codecs/pokemong/PokemongCodec.java index 0610934..0b4b948 100644 --- a/src/main/java/fr/uca/iut/codecs/pokemong/PokemongCodec.java +++ b/src/main/java/fr/uca/iut/codecs/pokemong/PokemongCodec.java @@ -1,127 +1,149 @@ -package fr.uca.iut.codecs.pokemong; - -import com.mongodb.MongoClientSettings; -import fr.uca.iut.codecs.GenericCodec; -import fr.uca.iut.entities.Pokemong; -import fr.uca.iut.entities.Type; -import fr.uca.iut.utils.PokemongName; -import fr.uca.iut.utils.TypeName; -import org.bson.*; -import org.bson.codecs.*; -import org.bson.types.ObjectId; - -import java.time.ZoneId; -import java.util.*; -import java.util.stream.Collectors; - -public class PokemongCodec extends GenericCodec { - private final Codec documentCodec; - - public PokemongCodec() { - this.documentCodec = MongoClientSettings.getDefaultCodecRegistry() - .get(Document.class); - } - - @Override - public void encode(BsonWriter writer, Pokemong pokemong, EncoderContext encoderContext) { - Document doc = new Document(); - doc.put("_id", new ObjectId(pokemong.getId())); - doc.put("nickname", pokemong.getNickname()); - doc.put("dob", - Date.from(pokemong.getDob() - .atStartOfDay(ZoneId.systemDefault()) - .toInstant())); - doc.put("level", pokemong.getLevel()); - doc.put("pokedexId", pokemong.getPokedexId()); - doc.put("evoStage", pokemong.getEvoStage()); - List evoTrack = Optional.ofNullable(pokemong.getEvoTrack()) - .orElse(Collections.emptyList()) - .stream() - .map(Enum::name) - .collect(Collectors.toList()); - - doc.put("evoTrack", evoTrack); - doc.put("isMegaEvolved", pokemong.getMegaEvolved()); - doc.put("trainer", pokemong.getTrainer()); - List types = Optional.ofNullable(pokemong.getTypes()) - .orElse(Collections.emptyList()) - .stream() - .map(type -> { - Document typeDoc = new Document(); - typeDoc.put("name", - type.getName() - .name()); - List weakAgainst = type.getWeakAgainst() - .stream() - .map(Enum::name) - .collect(Collectors.toList()); - typeDoc.put("weakAgainst", weakAgainst); - List effectiveAgainst = type.getEffectiveAgainst() - .stream() - .map(Enum::name) - .collect(Collectors.toList()); - typeDoc.put("effectiveAgainst", effectiveAgainst); - return typeDoc; - }) - .collect(Collectors.toList()); - doc.put("types", types); - doc.put("moveSet", pokemong.getMoveSet()); - documentCodec.encode(writer, doc, encoderContext); - } - - @Override - public Class getEncoderClass() { - return Pokemong.class; - } - - @Override - public Pokemong decode(BsonReader reader, DecoderContext decoderContext) { - Document document = documentCodec.decode(reader, decoderContext); - Pokemong pokemong = new Pokemong(); - pokemong.setId(document.getObjectId("_id").toString()); - pokemong.setNickname(document.getString("nickname")); - Date dob = document.getDate("dob"); - if (dob != null) { - pokemong.setDob(dob.toInstant() - .atZone(ZoneId.systemDefault()) - .toLocalDate()); - } - pokemong.setPokedexId(document.getInteger("pokedexId")); - pokemong.setEvoStage(document.getInteger("evoStage")); - List evoTrack = Optional.ofNullable((List) document.get("evoTrack")) - .orElse(Collections.emptyList()) - .stream() - .map(PokemongName::valueOf) - .collect(Collectors.toList()); - pokemong.setEvoTrack(evoTrack); - pokemong.setMegaEvolved(document.getBoolean("isMegaEvolved")); - pokemong.setTrainer(document.getObjectId("trainer")); - List types = Optional.ofNullable((List) document.get("types")) - .orElse(Collections.emptyList()) - .stream() - .map(typeDoc -> { - Type type = new Type(); - type.setName(TypeName.valueOf(typeDoc.getString("name"))); - List weakAgainst = Optional - .ofNullable((List) typeDoc.get("weakAgainst")) - .orElse(Collections.emptyList()) - .stream() - .map(TypeName::valueOf) - .collect(Collectors.toList()); - type.setWeakAgainst(weakAgainst); - List effectiveAgainst = Optional - .ofNullable((List) typeDoc.get("effectiveAgainst")) - .orElse(Collections.emptyList()) - .stream() - .map(TypeName::valueOf) - .collect(Collectors.toList()); - type.setEffectiveAgainst(effectiveAgainst); - return type; - }) - .collect(Collectors.toList()); - pokemong.setTypes(types); - pokemong.setMoveSet(Optional.ofNullable(document.getList("moveSet", ObjectId.class)) - .orElse(Collections.emptyList())); - return pokemong; - } -} +package fr.uca.iut.codecs.pokemong; + +import com.mongodb.MongoClientSettings; +import fr.uca.iut.codecs.GenericCodec; +import fr.uca.iut.codecs.type.TypeCodecUtil; +import fr.uca.iut.entities.Pokemong; +import fr.uca.iut.entities.PokemongMove; +import fr.uca.iut.entities.Type; +import fr.uca.iut.utils.enums.PokemongName; +import org.bson.BsonReader; +import org.bson.BsonWriter; +import org.bson.Document; +import org.bson.codecs.Codec; +import org.bson.codecs.DecoderContext; +import org.bson.codecs.EncoderContext; +import org.bson.types.ObjectId; + +import java.time.ZoneId; +import java.util.Date; +import java.util.List; +import java.util.stream.Collectors; + +public class PokemongCodec extends GenericCodec { + private final Codec documentCodec; + + public PokemongCodec() { + this.documentCodec = MongoClientSettings.getDefaultCodecRegistry() + .get(Document.class); + } + + @Override + public void encode(BsonWriter writer, Pokemong pokemong, EncoderContext encoderContext) { + Document doc = new Document(); + + doc.put("_id", new ObjectId(pokemong.getId())); + + doc.put("nickname", pokemong.getNickname()); + + doc.put("dob", + Date.from(pokemong.getDob() + .atStartOfDay(ZoneId.systemDefault()) + .toInstant())); + + doc.put("level", pokemong.getLevel()); + + doc.put("pokedexId", pokemong.getPokedexId()); + + doc.put("evoStage", pokemong.getEvoStage()); + + List evoTrack = pokemong.getEvoTrack() + .stream() + .map(Enum::name) + .collect(Collectors.toList()); + doc.put("evoTrack", evoTrack); + + doc.put("trainer", pokemong.getTrainer()); + + List types = pokemong.getTypes() + .stream() + .map(type -> { + Document typeDoc = new Document(); + typeDoc.put("name", + type.getName() + .name()); + List weakAgainst = type.getWeakAgainst() + .stream() + .map(Enum::name) + .collect(Collectors.toList()); + typeDoc.put("weakAgainst", weakAgainst); + List effectiveAgainst = type.getEffectiveAgainst() + .stream() + .map(Enum::name) + .collect(Collectors.toList()); + typeDoc.put("effectiveAgainst", effectiveAgainst); + return typeDoc; + }) + .collect(Collectors.toList()); + doc.put("types", types); + + List 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()); + doc.put("moveSet", moveSetDocs); + + documentCodec.encode(writer, doc, encoderContext); + } + + @Override + public Class getEncoderClass() { + return Pokemong.class; + } + + @Override + public Pokemong decode(BsonReader reader, DecoderContext decoderContext) { + Document document = documentCodec.decode(reader, decoderContext); + Pokemong pokemong = new Pokemong(); + + pokemong.setId(document.getObjectId("_id") + .toString()); + + pokemong.setNickname(document.getString("nickname")); + + Date dob = document.getDate("dob"); + if (dob != null) { + pokemong.setDob(dob.toInstant() + .atZone(ZoneId.systemDefault()) + .toLocalDate()); + } + + pokemong.setLevel(document.getInteger("level")); + + pokemong.setPokedexId(document.getInteger("pokedexId")); + + pokemong.setEvoStage(document.getInteger("evoStage")); + + List evoTrack = document.getList("evoTrack", String.class) + .stream() + .map(PokemongName::valueOf) + .collect(Collectors.toList()); + pokemong.setEvoTrack(evoTrack); + + pokemong.setTrainer(document.getObjectId("trainer")); + + List types = document.getList("types", Document.class) + .stream() + .map(TypeCodecUtil::extractType) + .collect(Collectors.toList()); + pokemong.setTypes(types); + + List 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.toList()); + pokemong.setMoveSet(moveSet); + + return pokemong; + } +} diff --git a/src/main/java/fr/uca/iut/codecs/pokemong/PokemongCodecProvider.java b/src/main/java/fr/uca/iut/codecs/pokemong/PokemongCodecProvider.java index 376412f..7327c19 100644 --- a/src/main/java/fr/uca/iut/codecs/pokemong/PokemongCodecProvider.java +++ b/src/main/java/fr/uca/iut/codecs/pokemong/PokemongCodecProvider.java @@ -1,16 +1,18 @@ -package fr.uca.iut.codecs.pokemong; - -import fr.uca.iut.entities.Pokemong; -import org.bson.codecs.Codec; -import org.bson.codecs.configuration.CodecProvider; -import org.bson.codecs.configuration.CodecRegistry; - -public class PokemongCodecProvider implements CodecProvider { - @Override - public Codec get(Class clazz, CodecRegistry registry) { - if (clazz.equals(Pokemong.class)) { - return (Codec) new PokemongCodec(); - } - return null; - } +package fr.uca.iut.codecs.pokemong; + +import com.mongodb.lang.Nullable; +import fr.uca.iut.entities.Pokemong; +import org.bson.codecs.Codec; +import org.bson.codecs.configuration.CodecProvider; +import org.bson.codecs.configuration.CodecRegistry; + +public class PokemongCodecProvider implements CodecProvider { + @Nullable + @Override + public Codec get(Class clazz, CodecRegistry registry) { + if (clazz.equals(Pokemong.class)) { + return (Codec) new PokemongCodec(); + } + return null; + } } \ No newline at end of file diff --git a/src/main/java/fr/uca/iut/codecs/trainer/TrainerCodec.java b/src/main/java/fr/uca/iut/codecs/trainer/TrainerCodec.java index ea2a396..d5c2fb9 100644 --- a/src/main/java/fr/uca/iut/codecs/trainer/TrainerCodec.java +++ b/src/main/java/fr/uca/iut/codecs/trainer/TrainerCodec.java @@ -1,57 +1,83 @@ -package fr.uca.iut.codecs.trainer; - -import com.mongodb.MongoClientSettings; -import fr.uca.iut.codecs.GenericCodec; -import fr.uca.iut.entities.Trainer; -import org.bson.*; -import org.bson.codecs.Codec; -import org.bson.codecs.DecoderContext; -import org.bson.codecs.EncoderContext; -import org.bson.types.ObjectId; - -import java.time.ZoneId; -import java.util.Date; - -public class TrainerCodec extends GenericCodec { - private final Codec documentCodec; - - public TrainerCodec() { - this.documentCodec = MongoClientSettings.getDefaultCodecRegistry() - .get(Document.class); - } - - @Override - public void encode(BsonWriter writer, Trainer trainer, EncoderContext encoderContext) { - Document doc = new Document(); - doc.put("_id", new ObjectId(trainer.getId())); - doc.put("name", trainer.getName()); - doc.put("dob", Date.from(trainer.getDob().atStartOfDay(ZoneId.systemDefault()).toInstant())); - doc.put("wins", trainer.getWins()); - doc.put("losses", trainer.getLosses()); - doc.put("pastOpponents", trainer.getPastOpponents()); - doc.put("pokemongs", trainer.getPokemongs()); - documentCodec.encode(writer, doc, encoderContext); - } - - @Override - public Class getEncoderClass() { - return Trainer.class; - } - - @Override - public Trainer decode(BsonReader reader, DecoderContext decoderContext) { - Document document = documentCodec.decode(reader, decoderContext); - Trainer trainer = new Trainer(); - trainer.setId(document.getObjectId("_id").toString()); - 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", 0)); - trainer.setLosses(document.getInteger("losses", 0)); - trainer.setPastOpponents(document.getList("pastOpponents", ObjectId.class)); - trainer.setPokemongs(document.getList("pokemongs", ObjectId.class)); - return trainer; - } -} +package fr.uca.iut.codecs.trainer; + +import com.mongodb.MongoClientSettings; +import fr.uca.iut.codecs.GenericCodec; +import fr.uca.iut.entities.Trainer; +import org.bson.BsonReader; +import org.bson.BsonWriter; +import org.bson.Document; +import org.bson.codecs.Codec; +import org.bson.codecs.DecoderContext; +import org.bson.codecs.EncoderContext; +import org.bson.types.ObjectId; + +import java.time.LocalDate; +import java.time.ZoneId; +import java.util.Date; + +public class TrainerCodec extends GenericCodec { + private final Codec documentCodec; + + public TrainerCodec() { + this.documentCodec = MongoClientSettings.getDefaultCodecRegistry() + .get(Document.class); + } + + @Override + public void encode(BsonWriter writer, Trainer trainer, EncoderContext encoderContext) { + Document doc = new Document(); + + doc.put("_id", new ObjectId(trainer.getId())); + + doc.put("name", trainer.getName()); + + LocalDate dob = trainer.getDob(); + if (dob != null) { + doc.put("dob", Date.from(dob.atStartOfDay(ZoneId.systemDefault()) + .toInstant())); + } + + doc.put("wins", trainer.getWins()); + + doc.put("losses", trainer.getLosses()); + + doc.put("pastOpponents", trainer.getPastOpponents()); + + doc.put("pokemongs", trainer.getPokemongs()); + + documentCodec.encode(writer, doc, encoderContext); + } + + @Override + public Class getEncoderClass() { + return Trainer.class; + } + + @Override + public Trainer decode(BsonReader reader, DecoderContext decoderContext) { + Document document = documentCodec.decode(reader, decoderContext); + Trainer trainer = new Trainer(); + + trainer.setId(document.getObjectId("_id") + .toString()); + + 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")); + + trainer.setPastOpponents(document.getList("pastOpponents", ObjectId.class)); + + trainer.setPokemongs(document.getList("pokemongs", ObjectId.class)); + + return trainer; + } +} diff --git a/src/main/java/fr/uca/iut/codecs/trainer/TrainerCodecProvider.java b/src/main/java/fr/uca/iut/codecs/trainer/TrainerCodecProvider.java index 80c178e..0c3e37a 100644 --- a/src/main/java/fr/uca/iut/codecs/trainer/TrainerCodecProvider.java +++ b/src/main/java/fr/uca/iut/codecs/trainer/TrainerCodecProvider.java @@ -1,16 +1,18 @@ -package fr.uca.iut.codecs.trainer; - -import fr.uca.iut.entities.Trainer; -import org.bson.codecs.Codec; -import org.bson.codecs.configuration.CodecProvider; -import org.bson.codecs.configuration.CodecRegistry; - -public class TrainerCodecProvider implements CodecProvider { - @Override - public Codec get(Class clazz, CodecRegistry registry) { - if (clazz.equals(Trainer.class)) { - return (Codec) new TrainerCodec(); - } - return null; - } -} +package fr.uca.iut.codecs.trainer; + +import com.mongodb.lang.Nullable; +import fr.uca.iut.entities.Trainer; +import org.bson.codecs.Codec; +import org.bson.codecs.configuration.CodecProvider; +import org.bson.codecs.configuration.CodecRegistry; + +public class TrainerCodecProvider implements CodecProvider { + @Nullable + @Override + public Codec get(Class clazz, CodecRegistry registry) { + if (clazz.equals(Trainer.class)) { + return (Codec) new TrainerCodec(); + } + return null; + } +} diff --git a/src/main/java/fr/uca/iut/codecs/type/TypeCodec.java b/src/main/java/fr/uca/iut/codecs/type/TypeCodec.java deleted file mode 100644 index 8b01381..0000000 --- a/src/main/java/fr/uca/iut/codecs/type/TypeCodec.java +++ /dev/null @@ -1,67 +0,0 @@ -package fr.uca.iut.codecs.type; - -import com.mongodb.MongoClientSettings; -import fr.uca.iut.entities.Type; -import fr.uca.iut.utils.TypeName; -import org.bson.*; -import org.bson.codecs.Codec; -import org.bson.codecs.DecoderContext; -import org.bson.codecs.EncoderContext; - -import java.util.List; -import java.util.Optional; -import java.util.stream.Collectors; - -public class TypeCodec implements Codec { - private final Codec documentCodec; - - public TypeCodec() { - this.documentCodec = MongoClientSettings.getDefaultCodecRegistry() - .get(Document.class); - } - - @Override - public void encode(BsonWriter writer, Type type, EncoderContext encoderContext) { - Document doc = new Document(); - Optional.ofNullable(type.getName()) - .map(Enum::name) - .ifPresent(name -> doc.put("name", name)); - - Optional.ofNullable(type.getWeakAgainst()) - .map(weakAgainst -> weakAgainst.stream().map(Enum::name).collect(Collectors.toList())) - .ifPresent(weakAgainst -> doc.put("weakAgainst", weakAgainst)); - - Optional.ofNullable(type.getEffectiveAgainst()) - .map(effectiveAgainst -> effectiveAgainst.stream().map(Enum::name).collect(Collectors.toList())) - .ifPresent(effectiveAgainst -> doc.put("effectiveAgainst", effectiveAgainst)); - - documentCodec.encode(writer, doc, encoderContext); - } - - @Override - public Class getEncoderClass() { - return Type.class; - } - - @Override - public Type decode(BsonReader reader, DecoderContext decoderContext) { - Document document = documentCodec.decode(reader, decoderContext); - Type type = new Type(); - - Optional.ofNullable(document.getString("name")) - .map(TypeName::valueOf) - .ifPresent(type::setName); - - Optional.ofNullable(document.get("weakAgainst")) - .filter(obj -> obj instanceof List) - .map(obj -> ((List) obj).stream().map(TypeName::valueOf).collect(Collectors.toList())) - .ifPresent(type::setWeakAgainst); - - Optional.ofNullable(document.get("effectiveAgainst")) - .filter(obj -> obj instanceof List) - .map(obj -> ((List) obj).stream().map(TypeName::valueOf).collect(Collectors.toList())) - .ifPresent(type::setEffectiveAgainst); - - return type; - } -} diff --git a/src/main/java/fr/uca/iut/codecs/type/TypeCodecProvider.java b/src/main/java/fr/uca/iut/codecs/type/TypeCodecProvider.java deleted file mode 100644 index 4a75c95..0000000 --- a/src/main/java/fr/uca/iut/codecs/type/TypeCodecProvider.java +++ /dev/null @@ -1,16 +0,0 @@ -package fr.uca.iut.codecs.type; - -import fr.uca.iut.entities.Type; -import org.bson.codecs.Codec; -import org.bson.codecs.configuration.CodecProvider; -import org.bson.codecs.configuration.CodecRegistry; - -public class TypeCodecProvider implements CodecProvider { - @Override - public Codec get(Class clazz, CodecRegistry registry) { - if (clazz.equals(Type.class)) { - return (Codec) new TypeCodec(); - } - return null; - } -} diff --git a/src/main/java/fr/uca/iut/codecs/type/TypeCodecUtil.java b/src/main/java/fr/uca/iut/codecs/type/TypeCodecUtil.java new file mode 100644 index 0000000..bd45965 --- /dev/null +++ b/src/main/java/fr/uca/iut/codecs/type/TypeCodecUtil.java @@ -0,0 +1,27 @@ +package fr.uca.iut.codecs.type; + +import fr.uca.iut.entities.Type; +import fr.uca.iut.utils.enums.TypeName; +import org.bson.Document; + +import java.util.List; +import java.util.stream.Collectors; + +public class TypeCodecUtil { + public static Type extractType(Document typeDoc) { + Type type = new Type(); + type.setName(TypeName.valueOf(typeDoc.getString("name"))); + List weakAgainst = typeDoc.getList("weakAgainst", String.class) + .stream() + .map(TypeName::valueOf) + .collect(Collectors.toList()); + type.setWeakAgainst(weakAgainst); + List effectiveAgainst = typeDoc.getList("effectiveAgainst", + String.class) + .stream() + .map(TypeName::valueOf) + .collect(Collectors.toList()); + type.setEffectiveAgainst(effectiveAgainst); + return type; + } +} diff --git a/src/main/java/fr/uca/iut/controllers/GenericController.java b/src/main/java/fr/uca/iut/controllers/GenericController.java new file mode 100644 index 0000000..70b30d2 --- /dev/null +++ b/src/main/java/fr/uca/iut/controllers/GenericController.java @@ -0,0 +1,108 @@ +package fr.uca.iut.controllers; + +import fr.uca.iut.entities.GenericEntity; +import fr.uca.iut.services.GenericService; +import fr.uca.iut.utils.exceptions.NonValidEntityException; +import jakarta.ws.rs.*; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; + +public abstract class GenericController { + + protected GenericService service; + + public void setService(GenericService service) { + this.service = service; + } + + @GET + @Path("/{id}") + public Response getOneById(@PathParam("id") String id) { + try { + T entity = service.getOneById(id); + if (entity != null) { + return Response.ok(entity) + .build(); + } + else { + return Response.status(Response.Status.NOT_FOUND) + .entity("Entity not found for id: " + id) + .build(); + } + } catch (IllegalArgumentException e) { + return Response.status(Response.Status.BAD_REQUEST) + .entity("Invalid id format: " + id) + .build(); + } + } + + @GET + public Response getAll() { + return Response.ok(service.getAll()) + .build(); + } + + @POST + @Consumes(MediaType.APPLICATION_JSON) + public Response createOne(T entity) { + + try { + service.validateOne(entity); + T newEntity = service.addOne(entity); + + return Response.status(Response.Status.CREATED) + .entity(newEntity) + .build(); + + } catch (NonValidEntityException e) { + return Response.status(Response.Status.BAD_REQUEST) + .entity(e.getMessage()) + .build(); + } + } + + @PUT + @Path("/{id}") + @Consumes(MediaType.APPLICATION_JSON) + public Response updateOne(@PathParam("id") String id, T entity) { + try { + service.validateOne(entity); + entity.setId(id); + T updatedEntity = service.updateOne(entity); + + if (updatedEntity != null) { + return Response.status(Response.Status.OK) + .entity(updatedEntity) + .build(); + } + else { + return Response.status(Response.Status.NOT_FOUND) + .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) { + return Response.status(Response.Status.BAD_REQUEST) + .entity(e.getMessage()) + .build(); + } + } + + @DELETE + @Path("/{id}") + public Response deleteOneById(@PathParam("id") String id) { + try { + service.deleteOneById(id); + return Response.ok() + .build(); + + } catch (IllegalArgumentException e) { + return Response.status(Response.Status.BAD_REQUEST) + .entity("Invalid id format: " + id) + .build(); + } + } +} diff --git a/src/main/java/fr/uca/iut/controllers/MoveController.java b/src/main/java/fr/uca/iut/controllers/MoveController.java new file mode 100644 index 0000000..ff4dbaf --- /dev/null +++ b/src/main/java/fr/uca/iut/controllers/MoveController.java @@ -0,0 +1,22 @@ +package fr.uca.iut.controllers; + +import fr.uca.iut.entities.Move; +import fr.uca.iut.services.MoveService; +import jakarta.annotation.PostConstruct; +import jakarta.inject.Inject; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.core.MediaType; + +@Path("/move") +@Produces(MediaType.APPLICATION_JSON) +public class MoveController extends GenericController { + + @Inject + MoveService moveService; + + @PostConstruct + public void init() { + setService(moveService); + } +} diff --git a/src/main/java/fr/uca/iut/controllers/PokemongController.java b/src/main/java/fr/uca/iut/controllers/PokemongController.java index 9032f87..43f4000 100644 --- a/src/main/java/fr/uca/iut/controllers/PokemongController.java +++ b/src/main/java/fr/uca/iut/controllers/PokemongController.java @@ -1,102 +1,22 @@ -package fr.uca.iut.controllers; - -import fr.uca.iut.entities.Pokemong; -import fr.uca.iut.services.PokemongService; -import jakarta.inject.Inject; -import jakarta.ws.rs.*; -import jakarta.ws.rs.core.MediaType; -import jakarta.ws.rs.core.Response; - -@Path("/pokemong") -@Produces(MediaType.APPLICATION_JSON) -public class PokemongController { - - @Inject - PokemongService pokemongService; - - @GET - @Path("/{id}") - public Response getPokemong(@PathParam("id") String id) { - try { - Pokemong pokemong = pokemongService.getPokemong(id); - if (pokemong != null) { - return Response.ok(pokemong) - .build(); - } - else { - return Response.status(Response.Status.NOT_FOUND) - .entity("Pokemong not found for id: " + id) - .build(); - } - } catch (IllegalArgumentException e) { - return Response.status(Response.Status.BAD_REQUEST) - .entity("Invalid id format: " + id) - .build(); - } - } - - @GET - public Response getAllPokemongs() { - return Response.ok(pokemongService.getAllPokemongs()) - .build(); - } - - @POST - @Consumes(MediaType.APPLICATION_JSON) - public Response createPokemong(Pokemong pokemong) { - - if (pokemongService.isNotMature(pokemong)) { - pokemong.setMegaEvolved(null); - } - - Pokemong newPokemong = pokemongService.addPokemong(pokemong); - - return Response.status(Response.Status.CREATED) - .entity(newPokemong) - .build(); - } - - @PUT - @Path("/{id}") - @Consumes(MediaType.APPLICATION_JSON) - public Response updatePokemong(@PathParam("id") String id, Pokemong pokemong) { - try { - if (pokemongService.isNotMature(pokemong)) { - pokemong.setMegaEvolved(null); - } - - pokemong.setId(id); - Pokemong updatedPokemong = pokemongService.updatePokemong(pokemong); - - if (updatedPokemong != null) { - return Response.status(Response.Status.OK) - .entity(updatedPokemong) - .build(); - } - else { - return Response.status(Response.Status.NOT_FOUND) - .entity("Pokemong not found for id: " + id) - .build(); - } - } catch (IllegalArgumentException e) { - return Response.status(Response.Status.BAD_REQUEST) - .entity("Invalid id format: " + id) - .build(); - } - } - - @DELETE - @Path("/{id}") - public Response deletePokemong(@PathParam("id") String id) { - try { - pokemongService.deletePokemong(id); - return Response.ok() - .build(); - - } catch (IllegalArgumentException e) { - return Response.status(Response.Status.BAD_REQUEST) - .entity("Invalid id format: " + id) - .build(); - } - } -} +package fr.uca.iut.controllers; + +import fr.uca.iut.entities.Pokemong; +import fr.uca.iut.services.PokemongService; +import jakarta.annotation.PostConstruct; +import jakarta.inject.Inject; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.core.MediaType; + +@Path("/pokemong") +@Produces(MediaType.APPLICATION_JSON) +public class PokemongController extends GenericController { + + @Inject + PokemongService pokemongService; + + @PostConstruct + public void init() { + setService(pokemongService); + } +} diff --git a/src/main/java/fr/uca/iut/entities/GenericEntity.java b/src/main/java/fr/uca/iut/entities/GenericEntity.java index bcfbf04..f98460a 100644 --- a/src/main/java/fr/uca/iut/entities/GenericEntity.java +++ b/src/main/java/fr/uca/iut/entities/GenericEntity.java @@ -1,32 +1,32 @@ -package fr.uca.iut.entities; - -import org.bson.codecs.pojo.annotations.BsonId; - -import java.util.Objects; - -public abstract class GenericEntity { - - @BsonId - private String id; - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - @Override - public int hashCode() { - return Objects.hash(id); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - GenericEntity entity = (GenericEntity) o; - return Objects.equals(id, entity.id); - } -} +package fr.uca.iut.entities; + +import org.bson.codecs.pojo.annotations.BsonId; + +import java.util.Objects; + +public abstract class GenericEntity { + + @BsonId + private String id; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + @Override + public int hashCode() { + return Objects.hash(id); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + GenericEntity entity = (GenericEntity) o; + return Objects.equals(id, entity.id); + } +} diff --git a/src/main/java/fr/uca/iut/entities/Move.java b/src/main/java/fr/uca/iut/entities/Move.java index d0dacc0..da98c37 100644 --- a/src/main/java/fr/uca/iut/entities/Move.java +++ b/src/main/java/fr/uca/iut/entities/Move.java @@ -1,65 +1,55 @@ -package fr.uca.iut.entities; - -import org.bson.codecs.pojo.annotations.BsonId; - -public class Move extends GenericEntity { - public static final String COLLECTION_NAME = "moves"; - - @BsonId - private String id; - private String name; - private String category; - private Integer power; - private Integer accuracy; - private Type type; - - public Move() {} - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getCategory() { - return category; - } - - public void setCategory(String category) { - this.category = category; - } - - public Integer getPower() { - return power; - } - - public void setPower(Integer power) { - this.power = power; - } - - public Integer getAccuracy() { - return accuracy; - } - - public void setAccuracy(Integer accuracy) { - this.accuracy = accuracy; - } - - public Type getType() { - return type; - } - - public void setType(Type type) { - this.type = type; - } +package fr.uca.iut.entities; + +import fr.uca.iut.utils.enums.MoveCategoryName; + +public class Move extends GenericEntity { + public static final String COLLECTION_NAME = "moves"; + + private String name; + private MoveCategoryName category; + private Integer power; + private Integer accuracy; + private Type type; + + public Move() {} + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public MoveCategoryName getCategory() { + return category; + } + + public void setCategory(MoveCategoryName category) { + this.category = category; + } + + public Integer getPower() { + return power; + } + + public void setPower(Integer power) { + this.power = power; + } + + public Integer getAccuracy() { + return accuracy; + } + + public void setAccuracy(Integer accuracy) { + this.accuracy = accuracy; + } + + public Type getType() { + return type; + } + + public void setType(Type type) { + this.type = type; + } } \ No newline at end of file diff --git a/src/main/java/fr/uca/iut/entities/Pokemong.java b/src/main/java/fr/uca/iut/entities/Pokemong.java index d55deee..4d08a1f 100644 --- a/src/main/java/fr/uca/iut/entities/Pokemong.java +++ b/src/main/java/fr/uca/iut/entities/Pokemong.java @@ -1,119 +1,121 @@ -package fr.uca.iut.entities; - -import fr.uca.iut.utils.PokemongName; -import org.bson.codecs.pojo.annotations.BsonId; -import org.bson.types.ObjectId; - -import java.time.LocalDate; -import java.util.List; - -public class Pokemong extends GenericEntity { - public static final String COLLECTION_NAME = "pokemongs"; - @BsonId - private String id; - private String nickname; - private LocalDate dob; - private Integer level; - private Integer pokedexId; - private Integer evoStage; - private List evoTrack; - private Boolean isMegaEvolved; - private ObjectId trainer; - private List types; // TODO Bound this within [1;2] (in controller) - private List moveSet; // TODO Bound this within [1;4] (in controller) and denormalize move "name" - - public Pokemong() {} - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getNickname() { - return nickname; - } - - public void setNickname(String nickname) { - this.nickname = nickname; - } - - public LocalDate getDob() { - return dob; - } - - public void setDob(LocalDate dob) { - this.dob = dob; - } - - public Integer getLevel() { - return level; - } - - public void setLevel(Integer level) { - this.level = level; - } - - public Integer getPokedexId() { - return pokedexId; - } - - public void setPokedexId(Integer pokedexId) { - 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; - } - - public Boolean getMegaEvolved() { - return isMegaEvolved; - } - - public void setMegaEvolved(Boolean megaEvolved) { - isMegaEvolved = megaEvolved; - } - - public ObjectId getTrainer() { - return trainer; - } - - public void setTrainer(ObjectId trainer) { - this.trainer = trainer; - } - - // TODO take particular care with collections - - // TODO study the question of encapsulation when it comes to using these dependencies... - public List getTypes() { - return types; - } - - public void setTypes(List types) { - this.types = types; - } - - public List getMoveSet() { - return moveSet; - } - - public void setMoveSet(List moveSet) { - this.moveSet = moveSet; - } - -} - +package fr.uca.iut.entities; + +import com.mongodb.lang.Nullable; +import fr.uca.iut.utils.enums.PokemongName; +import org.bson.types.ObjectId; + +import java.time.LocalDate; +import java.util.Collections; +import java.util.List; + +public class Pokemong extends GenericEntity { + public static final String COLLECTION_NAME = "pokemongs"; + + @Nullable + private String nickname; + private LocalDate dob; + private Integer level; + private Integer pokedexId; + private Integer evoStage; + private List evoTrack; + @Nullable + private ObjectId trainer; + private List types; + + /** + * pokemong.moveSet: [{_id: ObjectId, name: String}] + */ + private List moveSet; + + public Pokemong() {} + + @Nullable + public String getNickname() { + return nickname; + } + + public void setNickname(@Nullable String nickname) { + this.nickname = nickname; + } + + public LocalDate getDob() { + return dob; + } + + public void setDob(LocalDate dob) { + this.dob = dob; + } + + public Integer getLevel() { + return level; + } + + public void setLevel(Integer level) { + this.level = level; + } + + public Integer getPokedexId() { + return pokedexId; + } + + public void setPokedexId(Integer pokedexId) { + 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 ObjectId getTrainer() { + return trainer; + } + + public void setTrainer(@Nullable ObjectId trainer) { + this.trainer = trainer; + } + + public List getTypes() { + return Collections.unmodifiableList(types); + } + + public void setTypes(List types) { + this.types = types; + } + + public List getMoveSet() { + return Collections.unmodifiableList(moveSet); + } + + public void setMoveSet(List moveSet) { + this.moveSet = moveSet; + } + + public void removeMove(String id) { + PokemongMove pokemongMove = new PokemongMove(); + pokemongMove.setId(id); + moveSet.remove(pokemongMove); + } + + public void updateMove(String id, String name) { + for (PokemongMove move : moveSet) { + if (move.getId().equals(id)) { + move.setName(name); + break; + } + } + } +} + diff --git a/src/main/java/fr/uca/iut/entities/PokemongMove.java b/src/main/java/fr/uca/iut/entities/PokemongMove.java new file mode 100644 index 0000000..13c4c31 --- /dev/null +++ b/src/main/java/fr/uca/iut/entities/PokemongMove.java @@ -0,0 +1,16 @@ +package fr.uca.iut.entities; + +public class PokemongMove extends GenericEntity { + + private String name; + + public PokemongMove() {} + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/src/main/java/fr/uca/iut/entities/Trainer.java b/src/main/java/fr/uca/iut/entities/Trainer.java index 7b920e3..0512698 100644 --- a/src/main/java/fr/uca/iut/entities/Trainer.java +++ b/src/main/java/fr/uca/iut/entities/Trainer.java @@ -1,78 +1,68 @@ -package fr.uca.iut.entities; - -import org.bson.codecs.pojo.annotations.BsonId; -import org.bson.types.ObjectId; - -import java.time.LocalDate; -import java.util.List; - -public class Trainer extends GenericEntity { - public static final String COLLECTION_NAME = "trainers"; - - @BsonId - private String id; - private String name; - private LocalDate dob; - private Integer wins; - private Integer losses; - private List pastOpponents; - private List pokemongs; - - public Trainer() {} - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public LocalDate getDob() { - return dob; - } - - public void setDob(LocalDate dob) { - this.dob = dob; - } - - public Integer getWins() { - return wins; - } - - public void setWins(Integer wins) { - this.wins = wins; - } - - public Integer getLosses() { - return losses; - } - - public void setLosses(Integer losses) { - this.losses = losses; - } - - public List getPastOpponents() { - return pastOpponents; - } - - public void setPastOpponents(List pastOpponents) { - this.pastOpponents = pastOpponents; - } - - public List getPokemongs() { - return pokemongs; - } - - public void setPokemongs(List pokemongs) { - this.pokemongs = pokemongs; - } -} +package fr.uca.iut.entities; + +import org.bson.types.ObjectId; + +import java.time.LocalDate; +import java.util.Collections; +import java.util.List; + +public class Trainer extends GenericEntity { + public static final String COLLECTION_NAME = "trainers"; + + private String name; + private LocalDate dob; + private Integer wins; + private Integer losses; + private List pastOpponents; + private List pokemongs; + + public Trainer() {} + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public LocalDate getDob() { + return dob; + } + + public void setDob(LocalDate dob) { + this.dob = dob; + } + + public Integer getWins() { + return wins; + } + + public void setWins(Integer wins) { + this.wins = wins; + } + + public Integer getLosses() { + return losses; + } + + public void setLosses(Integer losses) { + this.losses = losses; + } + + public List getPastOpponents() { + return Collections.unmodifiableList(pastOpponents); + } + + public void setPastOpponents(List pastOpponents) { + this.pastOpponents = pastOpponents; + } + + public List getPokemongs() { + return Collections.unmodifiableList(pokemongs); + } + + public void setPokemongs(List pokemongs) { + this.pokemongs = pokemongs; + } +} diff --git a/src/main/java/fr/uca/iut/entities/Type.java b/src/main/java/fr/uca/iut/entities/Type.java index 6eb5756..f9e3022 100644 --- a/src/main/java/fr/uca/iut/entities/Type.java +++ b/src/main/java/fr/uca/iut/entities/Type.java @@ -1,55 +1,56 @@ -package fr.uca.iut.entities; - -import fr.uca.iut.utils.TypeName; - -import java.util.List; -import java.util.Objects; - -public class Type { - - private TypeName name; - private List weakAgainst; - private List effectiveAgainst; - - public Type() {} - - public TypeName getName() { - return name; - } - - public void setName(TypeName name) { - this.name = name; - } - - public List getWeakAgainst() { - return weakAgainst; - } - - public void setWeakAgainst(List weakAgainst) { - this.weakAgainst = weakAgainst; - } - - public List getEffectiveAgainst() { - return effectiveAgainst; - } - - public void setEffectiveAgainst(List effectiveAgainst) { - this.effectiveAgainst = effectiveAgainst; - } - - @Override - public int hashCode() { - return Objects.hash(name, weakAgainst, effectiveAgainst); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - 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); - } - +package fr.uca.iut.entities; + +import fr.uca.iut.utils.enums.TypeName; + +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +public class Type { + + private TypeName name; + private List weakAgainst; + private List effectiveAgainst; + + public Type() {} + + public TypeName getName() { + return name; + } + + public void setName(TypeName name) { + this.name = name; + } + + public List getWeakAgainst() { + return Collections.unmodifiableList(weakAgainst); + } + + public void setWeakAgainst(List weakAgainst) { + this.weakAgainst = weakAgainst; + } + + public List getEffectiveAgainst() { + return Collections.unmodifiableList(effectiveAgainst); + } + + public void setEffectiveAgainst(List effectiveAgainst) { + this.effectiveAgainst = effectiveAgainst; + } + + @Override + public int hashCode() { + return Objects.hash(name, weakAgainst, effectiveAgainst); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + 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); + } + } \ No newline at end of file diff --git a/src/main/java/fr/uca/iut/package-info.java b/src/main/java/fr/uca/iut/package-info.java new file mode 100644 index 0000000..3d301f9 --- /dev/null +++ b/src/main/java/fr/uca/iut/package-info.java @@ -0,0 +1,4 @@ +@NonNullApi +package fr.uca.iut; + +import com.mongodb.lang.NonNullApi; diff --git a/src/main/java/fr/uca/iut/repositories/GenericRepository.java b/src/main/java/fr/uca/iut/repositories/GenericRepository.java new file mode 100644 index 0000000..e8d47a3 --- /dev/null +++ b/src/main/java/fr/uca/iut/repositories/GenericRepository.java @@ -0,0 +1,64 @@ +package fr.uca.iut.repositories; + +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoCollection; +import com.mongodb.client.model.ReplaceOptions; +import com.mongodb.lang.Nullable; +import fr.uca.iut.entities.GenericEntity; +import org.bson.Document; +import org.bson.types.ObjectId; +import org.eclipse.microprofile.config.inject.ConfigProperty; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; + +import static com.mongodb.client.model.Filters.eq; + +public abstract class GenericRepository { + protected MongoClient mongoClient; + @ConfigProperty(name = "quarkus.mongodb.database") + String DB_NAME; + + public void setMongoClient(MongoClient mongoClient) { + this.mongoClient = mongoClient; + } + + @Nullable + public T findById(String id) { + return getCollection().find(eq("_id", new ObjectId(id))) + .first(); + } + + protected abstract MongoCollection getCollection(); + + public void persist(@NotNull T entity) { + getCollection().insertOne(entity); + } + + public List listAll() { + return getCollection().find() + .into(new ArrayList<>()); + } + + public void persistOrUpdate(@NotNull T entity) { + getCollection().replaceOne( + eq("_id", new ObjectId(entity.getId())), + entity, + new ReplaceOptions().upsert(true) + ); + } + + public void delete(@NotNull T entity) { + getCollection().deleteOne(eq("_id", new ObjectId(entity.getId()))); + } + + public boolean existsById(String id) { + // FIXME Can't post trainers anymore: "Caused by: java.lang.IllegalArgumentException: hexString can not be null + // at org.bson.assertions.Assertions.notNull(Assertions.java:37) + // at org.bson.types.ObjectId.parseHexString(ObjectId.java:418) + // at org.bson.types.ObjectId.(ObjectId.java:205)" + Document query = new Document("_id", new ObjectId(id)); + return getCollection().countDocuments(query) > 0; + } +} diff --git a/src/main/java/fr/uca/iut/repositories/MoveRepository.java b/src/main/java/fr/uca/iut/repositories/MoveRepository.java new file mode 100644 index 0000000..8bf48e0 --- /dev/null +++ b/src/main/java/fr/uca/iut/repositories/MoveRepository.java @@ -0,0 +1,32 @@ +package fr.uca.iut.repositories; + +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoCollection; +import com.mongodb.client.MongoDatabase; +import fr.uca.iut.entities.Move; +import jakarta.annotation.PostConstruct; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; + +@ApplicationScoped +public class MoveRepository extends GenericRepository { + + // FIXME? + /** + * Warns that "Unsatisfied dependency: no bean matches the injection point" + * but the app works + */ + @Inject + MongoClient mongoClient; + + @PostConstruct + public void init() { + setMongoClient(mongoClient); + } + + @Override + protected MongoCollection getCollection() { + MongoDatabase db = mongoClient.getDatabase(DB_NAME); + return db.getCollection(Move.COLLECTION_NAME, Move.class); + } +} diff --git a/src/main/java/fr/uca/iut/repositories/PokemongRepository.java b/src/main/java/fr/uca/iut/repositories/PokemongRepository.java index f60ec5d..da598cd 100644 --- a/src/main/java/fr/uca/iut/repositories/PokemongRepository.java +++ b/src/main/java/fr/uca/iut/repositories/PokemongRepository.java @@ -1,58 +1,42 @@ -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.ReplaceOptions; -import fr.uca.iut.entities.Pokemong; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.inject.Inject; -import org.bson.types.ObjectId; -import org.eclipse.microprofile.config.inject.ConfigProperty; - -import java.util.ArrayList; -import java.util.List; - -import static com.mongodb.client.model.Filters.eq; - -@ApplicationScoped -public class PokemongRepository { - - // FIXME? or suppress warning: "Unsatisfied dependency: no bean matches the injection point" - @Inject - MongoClient mongoClient; - - @ConfigProperty(name = "quarkus.mongodb.database") - String DB_NAME; - - private MongoCollection getCollection() { - MongoDatabase db = mongoClient.getDatabase(DB_NAME); - return db.getCollection(Pokemong.COLLECTION_NAME, Pokemong.class); - } - - public Pokemong findById(String id) { - return getCollection().find(eq("_id", new ObjectId(id))) - .first(); - } - - public void persist(Pokemong pokemong) { - getCollection().insertOne(pokemong); - } - - public List listAll() { - return getCollection().find() - .into(new ArrayList<>()); - } - - public void delete(Pokemong pokemong) { - getCollection().deleteOne(eq("_id", new ObjectId(pokemong.getId()))); - } - - public void persistOrUpdate(Pokemong pokemong) { - getCollection().replaceOne( - eq("_id", new ObjectId(pokemong.getId())), - pokemong, - new ReplaceOptions().upsert(true) - ); - } -} +package fr.uca.iut.repositories; + +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoCollection; +import com.mongodb.client.MongoDatabase; +import fr.uca.iut.entities.Pokemong; +import jakarta.annotation.PostConstruct; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; + +import java.util.ArrayList; +import java.util.List; + +import static com.mongodb.client.model.Filters.eq; + +@ApplicationScoped +public class PokemongRepository extends GenericRepository { + + // FIXME? + /** + * Warns that "Unsatisfied dependency: no bean matches the injection point" + * but the app works + */ + @Inject + MongoClient mongoClient; + + @PostConstruct + public void init() { + setMongoClient(mongoClient); + } + + @Override + protected MongoCollection getCollection() { + MongoDatabase db = mongoClient.getDatabase(DB_NAME); + return db.getCollection(Pokemong.COLLECTION_NAME, Pokemong.class); + } + + public List findByMove(String moveId) { + return getCollection().find(eq("moveSet.id", moveId)) + .into(new ArrayList<>()); + } +} diff --git a/src/main/java/fr/uca/iut/services/GenericService.java b/src/main/java/fr/uca/iut/services/GenericService.java new file mode 100644 index 0000000..3bd1435 --- /dev/null +++ b/src/main/java/fr/uca/iut/services/GenericService.java @@ -0,0 +1,51 @@ +package fr.uca.iut.services; + +import com.mongodb.lang.Nullable; +import fr.uca.iut.entities.GenericEntity; +import fr.uca.iut.repositories.GenericRepository; +import fr.uca.iut.utils.exceptions.NonValidEntityException; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +public abstract class GenericService { + + protected GenericRepository repository; + + public void setRepository(GenericRepository repository) { + this.repository = repository; + } + + public T addOne(@NotNull T entity) { + repository.persist(entity); + return entity; + } + + @Nullable + public T getOneById(String id) { + return repository.findById(id); + } + + public List getAll() { + return repository.listAll(); + } + + public void deleteOneById(String id) { + T entity = repository.findById(id); + if (entity != null) { + repository.delete(entity); + } + } + + @Nullable + public abstract T updateOne(@NotNull T entity); + + /** + * Override me and start with `super.validateOne(entity);` + */ + public void validateOne(T entity) { + if (entity == null) { + throw new NonValidEntityException("entity was null"); + } + } +} diff --git a/src/main/java/fr/uca/iut/services/MoveService.java b/src/main/java/fr/uca/iut/services/MoveService.java new file mode 100644 index 0000000..0276e10 --- /dev/null +++ b/src/main/java/fr/uca/iut/services/MoveService.java @@ -0,0 +1,88 @@ +package fr.uca.iut.services; + +import com.mongodb.lang.Nullable; +import fr.uca.iut.entities.Move; +import fr.uca.iut.entities.Pokemong; +import fr.uca.iut.repositories.MoveRepository; +import fr.uca.iut.utils.StringUtils; +import fr.uca.iut.utils.exceptions.NonValidEntityException; +import jakarta.annotation.PostConstruct; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +@ApplicationScoped +public class MoveService extends GenericService { + + @Inject + MoveRepository moveRepository; + + @PostConstruct + public void init() { + setRepository(moveRepository); + } + + @Inject + PokemongService pokemongService; + + @Override + public void deleteOneById(String id) { + super.deleteOneById(id); + // FIXME the deleted move does not get its PokemongMove deleted from any Pokemong's moveset in DB after a move is deleted + List pokemongs = pokemongService.findByMove(id); + for (Pokemong pokemong : pokemongs) { + pokemong.removeMove(id); + pokemongService.updateOne(pokemong); + } + } + + @Override + @Nullable + public Move updateOne(@NotNull Move move) { + Move existingMove = moveRepository.findById(move.getId()); + if (existingMove != null) { + existingMove.setName(move.getName()); + // FIXME the updated name does not appear in DB after a move is updated + List pokemongs = pokemongService.findByMove(move.getId()); + for (Pokemong pokemong : pokemongs) { + pokemong.updateMove(move.getId(), move.getName()); + pokemongService.updateOne(pokemong); + } + + existingMove.setPower(move.getPower()); + existingMove.setCategory(move.getCategory()); + existingMove.setAccuracy(move.getAccuracy()); + existingMove.setType(move.getType()); + moveRepository.persistOrUpdate(existingMove); + } + return existingMove; + } + + @Override + public void validateOne(Move move) { + + super.validateOne(move); + + if (StringUtils.isBlankString(move.getName())) { + throw new NonValidEntityException("move name was null, blank or empty"); + } + + if (move.getPower() == null || move.getPower() < 0) { + throw new NonValidEntityException("move power was null or negative"); + } + + if (move.getCategory() == null) { + throw new NonValidEntityException("move category was null or invalid"); + } + + if (move.getAccuracy() == null || move.getAccuracy() < 0) { + throw new NonValidEntityException("move accuracy was null or negative"); + } + + if (move.getType() == null) { + throw new NonValidEntityException("move type was null or invalid"); + } + } +} diff --git a/src/main/java/fr/uca/iut/services/PokemongService.java b/src/main/java/fr/uca/iut/services/PokemongService.java index b7d47a5..0836776 100644 --- a/src/main/java/fr/uca/iut/services/PokemongService.java +++ b/src/main/java/fr/uca/iut/services/PokemongService.java @@ -1,65 +1,101 @@ -package fr.uca.iut.services; - -import fr.uca.iut.entities.Pokemong; -import fr.uca.iut.repositories.PokemongRepository; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.inject.Inject; - -import java.util.List; - -@ApplicationScoped -public class PokemongService { - - @Inject - PokemongRepository pokemongRepository; - - public Pokemong addPokemong(Pokemong pokemong) { - pokemongRepository.persist(pokemong); - return pokemong; - } - - public Pokemong getPokemong(String id) { - return pokemongRepository.findById(id); - } - - public List getAllPokemongs() { - return pokemongRepository.listAll(); - } - - public void deletePokemong(String id) { - Pokemong pokemong = pokemongRepository.findById(id); - if (pokemong != null) { - pokemongRepository.delete(pokemong); - } - } - - public Pokemong updatePokemong(Pokemong pokemong) { - Pokemong existingPokemong = pokemongRepository.findById(pokemong.getId()); - if (existingPokemong != null) { - existingPokemong.setNickname(pokemong.getNickname()); - existingPokemong.setDob(pokemong.getDob()); - existingPokemong.setLevel(pokemong.getLevel()); - existingPokemong.setPokedexId(pokemong.getPokedexId()); - existingPokemong.setEvoStage(pokemong.getEvoStage()); - existingPokemong.setEvoTrack(pokemong.getEvoTrack()); - existingPokemong.setMegaEvolved(pokemong.getMegaEvolved()); - existingPokemong.setTrainer(pokemong.getTrainer()); - existingPokemong.setTypes(pokemong.getTypes()); - existingPokemong.setMoveSet(pokemong.getMoveSet()); - pokemongRepository.persistOrUpdate(existingPokemong); - } - return existingPokemong; - } - - public boolean isNotMature(Pokemong pokemong) { - return pokemong == null - || pokemong.getEvoStage() == null - || pokemong.getEvoTrack() == null - || pokemong.getEvoTrack() - .isEmpty() - || (pokemong.getEvoStage() != pokemong.getEvoTrack() - .size() - 1); - } - - // TODO PATCH ? -} +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.repositories.MoveRepository; +import fr.uca.iut.repositories.PokemongRepository; +import fr.uca.iut.utils.exceptions.NonValidEntityException; +import jakarta.annotation.PostConstruct; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +@ApplicationScoped +public class PokemongService extends GenericService { + + @Inject + PokemongRepository pokemongRepository; + @Inject + MoveRepository moveRepository; + + @PostConstruct + public void init() { + setRepository(pokemongRepository); + } + + @Override + @Nullable + public Pokemong updateOne(@NotNull Pokemong pokemong) { + Pokemong existingPokemong = pokemongRepository.findById(pokemong.getId()); + if (existingPokemong != null) { + existingPokemong.setNickname(pokemong.getNickname()); + existingPokemong.setDob(pokemong.getDob()); + existingPokemong.setLevel(pokemong.getLevel()); + existingPokemong.setPokedexId(pokemong.getPokedexId()); + existingPokemong.setEvoStage(pokemong.getEvoStage()); + existingPokemong.setEvoTrack(pokemong.getEvoTrack()); + existingPokemong.setTrainer(pokemong.getTrainer()); + existingPokemong.setTypes(pokemong.getTypes()); + existingPokemong.setMoveSet(pokemong.getMoveSet()); + pokemongRepository.persistOrUpdate(existingPokemong); + } + return existingPokemong; + } + + public List findByMove(String id) { + return pokemongRepository.findByMove(id); + } + + @Override + public void validateOne(Pokemong pokemong) { + + super.validateOne(pokemong); + + if (pokemong.getDob() == null) { + throw new NonValidEntityException("pokemong date of birth was null or invalid"); + } + + if (pokemong.getLevel() == null || pokemong.getLevel() < 1) { + throw new NonValidEntityException("pokemong level was null or less than 1"); + } + + if (pokemong.getPokedexId() == null || pokemong.getPokedexId() < 1) { + throw new NonValidEntityException("pokemong pokedex id was null or less than 1"); + } + + if (pokemong.getEvoStage() == null || pokemong.getEvoStage() < 0) { + throw new NonValidEntityException("pokemong evo stage was null or negative"); + } + + if (pokemong.getEvoTrack() == null) { + throw new NonValidEntityException("pokemong evo track was null or invalid"); + } + + List types = pokemong.getTypes(); + if (types == null + || types.size() == 0 + || types.size() > 2) + { + throw new NonValidEntityException("pokemong types was null or empty or had more than 2 types"); + } + + List moveSet = pokemong.getMoveSet(); + if (moveSet == null + || moveSet.size() == 0 + || moveSet.size() > 4) + { + throw new NonValidEntityException("pokemong move set was null or empty or had more than 4 moves"); + } + + for (PokemongMove move : moveSet) { + String moveId = move.getId(); + if (moveId == null || !moveRepository.existsById(moveId)) { + throw new NonValidEntityException("move with id " + moveId + " does not exist"); + } + } + } +} diff --git a/src/main/java/fr/uca/iut/utils/StringUtils.java b/src/main/java/fr/uca/iut/utils/StringUtils.java new file mode 100644 index 0000000..cca45b6 --- /dev/null +++ b/src/main/java/fr/uca/iut/utils/StringUtils.java @@ -0,0 +1,7 @@ +package fr.uca.iut.utils; + +public class StringUtils { + public static boolean isBlankString(String string) { + return string == null || string.isBlank(); + } +} diff --git a/src/main/java/fr/uca/iut/utils/enums/MoveCategoryName.java b/src/main/java/fr/uca/iut/utils/enums/MoveCategoryName.java new file mode 100644 index 0000000..dd1466c --- /dev/null +++ b/src/main/java/fr/uca/iut/utils/enums/MoveCategoryName.java @@ -0,0 +1,7 @@ +package fr.uca.iut.utils.enums; + +public enum MoveCategoryName { + PHYSICAL, + SPECIAL, + STATUS +} diff --git a/src/main/java/fr/uca/iut/utils/PokemongName.java b/src/main/java/fr/uca/iut/utils/enums/PokemongName.java similarity index 99% rename from src/main/java/fr/uca/iut/utils/PokemongName.java rename to src/main/java/fr/uca/iut/utils/enums/PokemongName.java index dcd0723..a6296c0 100644 --- a/src/main/java/fr/uca/iut/utils/PokemongName.java +++ b/src/main/java/fr/uca/iut/utils/enums/PokemongName.java @@ -1,4 +1,4 @@ -package fr.uca.iut.utils; +package fr.uca.iut.utils.enums; public enum PokemongName { BULBASAUR, diff --git a/src/main/java/fr/uca/iut/utils/TypeName.java b/src/main/java/fr/uca/iut/utils/enums/TypeName.java similarity index 87% rename from src/main/java/fr/uca/iut/utils/TypeName.java rename to src/main/java/fr/uca/iut/utils/enums/TypeName.java index 3383d2d..757b1c6 100644 --- a/src/main/java/fr/uca/iut/utils/TypeName.java +++ b/src/main/java/fr/uca/iut/utils/enums/TypeName.java @@ -1,4 +1,4 @@ -package fr.uca.iut.utils; +package fr.uca.iut.utils.enums; public enum TypeName { NORMAL, diff --git a/src/main/java/fr/uca/iut/utils/exceptions/NonValidEntityException.java b/src/main/java/fr/uca/iut/utils/exceptions/NonValidEntityException.java new file mode 100644 index 0000000..2d0bf42 --- /dev/null +++ b/src/main/java/fr/uca/iut/utils/exceptions/NonValidEntityException.java @@ -0,0 +1,7 @@ +package fr.uca.iut.utils.exceptions; + +public class NonValidEntityException extends RuntimeException { + public NonValidEntityException(String message) { + super(message); + } +} \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 6ba7462..6e2722d 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,2 +1,2 @@ -quarkus.mongodb.connection-string=mongodb+srv://:@..mongodb.net +quarkus.mongodb.connection-string=mongodb+srv://:@..mongodb.net quarkus.mongodb.database= \ No newline at end of file