From cbebbe2cf2ffe8f60434bb030bc39a8b80850c7a Mon Sep 17 00:00:00 2001 From: visoulier Date: Wed, 27 Mar 2024 19:34:43 +0100 Subject: [PATCH] correction creation partie, ajout dto correspondant --- .../sae/controllers/PartieController.java | 18 ++++++- .../controllers/request/PartieRequest.java | 2 +- .../sae/dto/joueur/JoueurSimpleDTO.java | 23 +++++++++ .../sae/dto/partie/PartieDTO.java | 5 +- .../iut/sciencequest/sae/entities/Joueur.java | 6 ++- .../iut/sciencequest/sae/entities/Partie.java | 12 +++-- .../notFound/JeuNotFoundException.java | 4 ++ .../notFound/JoueurNotFoundException.java | 11 ++++ .../notFound/PartieNotFoundException.java | 4 +- .../sciencequest/sae/services/JeuService.java | 22 ++++++++ .../sae/services/JoueurService.java | 21 ++++++++ .../sae/services/PartieService.java | 51 +++++++------------ .../src/main/resources/schema.sql | 50 ++++++++++++++---- 13 files changed, 174 insertions(+), 55 deletions(-) create mode 100644 SpringBootProject/src/main/java/fr/iut/sciencequest/sae/dto/joueur/JoueurSimpleDTO.java create mode 100644 SpringBootProject/src/main/java/fr/iut/sciencequest/sae/exceptions/notFound/JoueurNotFoundException.java create mode 100644 SpringBootProject/src/main/java/fr/iut/sciencequest/sae/services/JeuService.java create mode 100644 SpringBootProject/src/main/java/fr/iut/sciencequest/sae/services/JoueurService.java diff --git a/SpringBootProject/src/main/java/fr/iut/sciencequest/sae/controllers/PartieController.java b/SpringBootProject/src/main/java/fr/iut/sciencequest/sae/controllers/PartieController.java index fad9c1b..f075efe 100644 --- a/SpringBootProject/src/main/java/fr/iut/sciencequest/sae/controllers/PartieController.java +++ b/SpringBootProject/src/main/java/fr/iut/sciencequest/sae/controllers/PartieController.java @@ -3,20 +3,30 @@ package fr.iut.sciencequest.sae.controllers; import fr.iut.sciencequest.sae.assemblers.PartieModelAssembler; import fr.iut.sciencequest.sae.controllers.request.PartieRequest; import fr.iut.sciencequest.sae.dto.partie.PartieDTO; +import fr.iut.sciencequest.sae.entities.Joueur; import fr.iut.sciencequest.sae.entities.Partie; +import fr.iut.sciencequest.sae.services.JeuService; +import fr.iut.sciencequest.sae.services.JoueurService; import fr.iut.sciencequest.sae.services.PartieService; +import jakarta.validation.Valid; import lombok.AllArgsConstructor; import org.modelmapper.ModelMapper; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.*; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + @RestController @AllArgsConstructor @RequestMapping("/api/v1/partie") public class PartieController { private final PartieModelAssembler partieModelAssembler; private final PartieService partieService; + private final JoueurService joueurService; + private final JeuService jeuService; private final ModelMapper modelMapper; @RequestMapping(value = "/{id}",method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) @@ -27,8 +37,12 @@ public class PartieController { @RequestMapping(method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) @ResponseStatus(HttpStatus.CREATED) - public Partie createPartie(@RequestBody PartieRequest request) { - return this.partieService.create(request.getIdJeu(), request.getPseudo(), request.getThematiques(), request.getIdDifficulte()); + public PartieDTO createPartie(@RequestBody @Valid PartieRequest request) { + Partie partie = new Partie(); + partie.setJeu(this.jeuService.findById(request.getIdJeu())); + partie.setJoueurs(List.of(this.joueurService.findById(request.getIdJoueur()))); + partie = this.partieService.create(partie); + return this.modelMapper.map(partie, PartieDTO.class); } } diff --git a/SpringBootProject/src/main/java/fr/iut/sciencequest/sae/controllers/request/PartieRequest.java b/SpringBootProject/src/main/java/fr/iut/sciencequest/sae/controllers/request/PartieRequest.java index 75a690f..b909a7d 100644 --- a/SpringBootProject/src/main/java/fr/iut/sciencequest/sae/controllers/request/PartieRequest.java +++ b/SpringBootProject/src/main/java/fr/iut/sciencequest/sae/controllers/request/PartieRequest.java @@ -7,7 +7,7 @@ import java.util.List; @Data public class PartieRequest { private Integer idJeu; - private String pseudo; + private int idJoueur; private List thematiques; private Integer idDifficulte; } diff --git a/SpringBootProject/src/main/java/fr/iut/sciencequest/sae/dto/joueur/JoueurSimpleDTO.java b/SpringBootProject/src/main/java/fr/iut/sciencequest/sae/dto/joueur/JoueurSimpleDTO.java new file mode 100644 index 0000000..0e1d975 --- /dev/null +++ b/SpringBootProject/src/main/java/fr/iut/sciencequest/sae/dto/joueur/JoueurSimpleDTO.java @@ -0,0 +1,23 @@ +package fr.iut.sciencequest.sae.dto.joueur; + +import com.fasterxml.jackson.annotation.JsonInclude; +import fr.iut.sciencequest.sae.dto.partie.PartieDTO; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.*; +import org.springframework.hateoas.RepresentationModel; + + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = false) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class JoueurSimpleDTO extends RepresentationModel { + @NotNull + private Integer id; + + @NotBlank + private String pseudo; +} diff --git a/SpringBootProject/src/main/java/fr/iut/sciencequest/sae/dto/partie/PartieDTO.java b/SpringBootProject/src/main/java/fr/iut/sciencequest/sae/dto/partie/PartieDTO.java index 127d781..965c457 100644 --- a/SpringBootProject/src/main/java/fr/iut/sciencequest/sae/dto/partie/PartieDTO.java +++ b/SpringBootProject/src/main/java/fr/iut/sciencequest/sae/dto/partie/PartieDTO.java @@ -1,13 +1,14 @@ package fr.iut.sciencequest.sae.dto.partie; import fr.iut.sciencequest.sae.dto.jeu.JeuDTO; -import fr.iut.sciencequest.sae.dto.joueur.JoueurDTO; +import fr.iut.sciencequest.sae.dto.joueur.JoueurSimpleDTO; import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; import lombok.*; import org.springframework.hateoas.RepresentationModel; import java.util.List; +import java.util.Set; @Data @@ -21,7 +22,7 @@ public class PartieDTO extends RepresentationModel { @NotEmpty private String codeInvitation; @NotEmpty - private List joueurs; + private List joueurs; @NotNull private JeuDTO jeu; } diff --git a/SpringBootProject/src/main/java/fr/iut/sciencequest/sae/entities/Joueur.java b/SpringBootProject/src/main/java/fr/iut/sciencequest/sae/entities/Joueur.java index 362f7b6..341f94c 100644 --- a/SpringBootProject/src/main/java/fr/iut/sciencequest/sae/entities/Joueur.java +++ b/SpringBootProject/src/main/java/fr/iut/sciencequest/sae/entities/Joueur.java @@ -1,10 +1,13 @@ package fr.iut.sciencequest.sae.entities; +import com.fasterxml.jackson.annotation.JsonBackReference; import com.fasterxml.jackson.annotation.JsonIgnore; import jakarta.persistence.*; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; +import org.hibernate.annotations.Fetch; +import org.hibernate.annotations.FetchMode; @AllArgsConstructor @NoArgsConstructor @@ -20,8 +23,9 @@ public class Joueur { @Column(unique = true) private String pseudo; + @JsonBackReference @ManyToOne @JoinColumn(name = "idpartie") - @JsonIgnore + @Fetch(FetchMode.JOIN) private Partie partie; } diff --git a/SpringBootProject/src/main/java/fr/iut/sciencequest/sae/entities/Partie.java b/SpringBootProject/src/main/java/fr/iut/sciencequest/sae/entities/Partie.java index 852af5a..58f2026 100644 --- a/SpringBootProject/src/main/java/fr/iut/sciencequest/sae/entities/Partie.java +++ b/SpringBootProject/src/main/java/fr/iut/sciencequest/sae/entities/Partie.java @@ -1,5 +1,7 @@ package fr.iut.sciencequest.sae.entities; +import com.fasterxml.jackson.annotation.JsonBackReference; +import com.fasterxml.jackson.annotation.JsonManagedReference; import jakarta.persistence.*; import lombok.AllArgsConstructor; import lombok.Data; @@ -18,19 +20,21 @@ public class Partie { @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; - @Column(name = "codeinvitation", unique = true, nullable = false) + @Column(name = "codeinvitation", unique = true, nullable = false) //default value : see Schema.sql private String codeInvitation; - @OneToMany(mappedBy = "partie", fetch = FetchType.EAGER) + @JsonManagedReference + @OneToMany(cascade = CascadeType.MERGE, fetch = FetchType.EAGER) + @JoinColumn(name = "idpartie") private List joueurs; @ManyToOne @JoinColumn(name="idjeu", nullable = false) private Jeu jeu; - @Column(name = "status") + @Column(name = "status") //default value : see Schema.sql private String status; - @Column(name = "datecreation") + @Column(name = "datecreation") //default value : see Schema.sql private Date dateCreation; } diff --git a/SpringBootProject/src/main/java/fr/iut/sciencequest/sae/exceptions/notFound/JeuNotFoundException.java b/SpringBootProject/src/main/java/fr/iut/sciencequest/sae/exceptions/notFound/JeuNotFoundException.java index 9db3b94..ec444da 100644 --- a/SpringBootProject/src/main/java/fr/iut/sciencequest/sae/exceptions/notFound/JeuNotFoundException.java +++ b/SpringBootProject/src/main/java/fr/iut/sciencequest/sae/exceptions/notFound/JeuNotFoundException.java @@ -1,5 +1,9 @@ package fr.iut.sciencequest.sae.exceptions.notFound; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(HttpStatus.NOT_FOUND) public class JeuNotFoundException extends EntityNotFoundException{ public JeuNotFoundException(int id) { super("Jeu", id); diff --git a/SpringBootProject/src/main/java/fr/iut/sciencequest/sae/exceptions/notFound/JoueurNotFoundException.java b/SpringBootProject/src/main/java/fr/iut/sciencequest/sae/exceptions/notFound/JoueurNotFoundException.java new file mode 100644 index 0000000..876d0b2 --- /dev/null +++ b/SpringBootProject/src/main/java/fr/iut/sciencequest/sae/exceptions/notFound/JoueurNotFoundException.java @@ -0,0 +1,11 @@ +package fr.iut.sciencequest.sae.exceptions.notFound; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(HttpStatus.NOT_FOUND) +public class JoueurNotFoundException extends EntityNotFoundException{ + public JoueurNotFoundException(int id) { + super("Joueur", id); + } +} diff --git a/SpringBootProject/src/main/java/fr/iut/sciencequest/sae/exceptions/notFound/PartieNotFoundException.java b/SpringBootProject/src/main/java/fr/iut/sciencequest/sae/exceptions/notFound/PartieNotFoundException.java index 27b8dd1..43f00be 100644 --- a/SpringBootProject/src/main/java/fr/iut/sciencequest/sae/exceptions/notFound/PartieNotFoundException.java +++ b/SpringBootProject/src/main/java/fr/iut/sciencequest/sae/exceptions/notFound/PartieNotFoundException.java @@ -6,7 +6,7 @@ import org.springframework.web.bind.annotation.ResponseStatus; @ResponseStatus(HttpStatus.NOT_FOUND) public class PartieNotFoundException extends EntityNotFoundException{ - public PartieNotFoundException(String message, int id) { - super(message, id); + public PartieNotFoundException(int id) { + super("partie", id); } } diff --git a/SpringBootProject/src/main/java/fr/iut/sciencequest/sae/services/JeuService.java b/SpringBootProject/src/main/java/fr/iut/sciencequest/sae/services/JeuService.java new file mode 100644 index 0000000..2778cfb --- /dev/null +++ b/SpringBootProject/src/main/java/fr/iut/sciencequest/sae/services/JeuService.java @@ -0,0 +1,22 @@ +package fr.iut.sciencequest.sae.services; + +import fr.iut.sciencequest.sae.entities.Jeu; +import fr.iut.sciencequest.sae.entities.Joueur; +import fr.iut.sciencequest.sae.exceptions.notFound.JeuNotFoundException; +import fr.iut.sciencequest.sae.exceptions.notFound.JoueurNotFoundException; +import fr.iut.sciencequest.sae.repositories.JeuRepository; +import fr.iut.sciencequest.sae.repositories.JoueurRepository; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Service; + +@AllArgsConstructor +@Service +public class JeuService { + private final JeuRepository jeuRepository; + + public Jeu findById(int id) { + return this.jeuRepository.findById(id).orElseThrow(() -> + new JeuNotFoundException(id) + ); + } +} diff --git a/SpringBootProject/src/main/java/fr/iut/sciencequest/sae/services/JoueurService.java b/SpringBootProject/src/main/java/fr/iut/sciencequest/sae/services/JoueurService.java new file mode 100644 index 0000000..3e6e0a9 --- /dev/null +++ b/SpringBootProject/src/main/java/fr/iut/sciencequest/sae/services/JoueurService.java @@ -0,0 +1,21 @@ +package fr.iut.sciencequest.sae.services; + +import fr.iut.sciencequest.sae.entities.Joueur; +import fr.iut.sciencequest.sae.entities.Thematique; +import fr.iut.sciencequest.sae.exceptions.notFound.JoueurNotFoundException; +import fr.iut.sciencequest.sae.exceptions.notFound.ThematiqueNotFoundException; +import fr.iut.sciencequest.sae.repositories.JoueurRepository; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Service; + +@AllArgsConstructor +@Service +public class JoueurService { + private final JoueurRepository joueurRepository; + + public Joueur findById(int id) { + return this.joueurRepository.findById(id).orElseThrow(() -> + new JoueurNotFoundException(id) + ); + } +} diff --git a/SpringBootProject/src/main/java/fr/iut/sciencequest/sae/services/PartieService.java b/SpringBootProject/src/main/java/fr/iut/sciencequest/sae/services/PartieService.java index abe2e74..f3501b9 100644 --- a/SpringBootProject/src/main/java/fr/iut/sciencequest/sae/services/PartieService.java +++ b/SpringBootProject/src/main/java/fr/iut/sciencequest/sae/services/PartieService.java @@ -1,10 +1,11 @@ package fr.iut.sciencequest.sae.services; -import fr.iut.sciencequest.sae.entities.Joueur; -import fr.iut.sciencequest.sae.entities.Partie; +import fr.iut.sciencequest.sae.entities.*; +import fr.iut.sciencequest.sae.exceptions.DuplicatedIdException; import fr.iut.sciencequest.sae.exceptions.MalformedPartyException; import fr.iut.sciencequest.sae.exceptions.notFound.JeuNotFoundException; import fr.iut.sciencequest.sae.exceptions.notFound.PartieNotFoundException; +import fr.iut.sciencequest.sae.exceptions.notFound.ThematiqueNotFoundException; import fr.iut.sciencequest.sae.repositories.*; import jakarta.persistence.EntityManager; import jakarta.persistence.PersistenceContext; @@ -24,47 +25,31 @@ public class PartieService { private final UtilisateurRepository utilisateurRepository; private final ThematiqueRepository thematiqueRepository; private final DifficulteRepository difficulteRepository; + private final JoueurService joueurService; @PersistenceContext private EntityManager entityManager; public Partie findById(int id) { return this.partieRepository.findById(id).orElseThrow(() -> - new PartieNotFoundException("Partie", id) + new PartieNotFoundException(id) ); } - @Transactional - public Partie create(Integer idJeu, String pseudo, List thematiques, Integer idDifficulte) { - // Création du joueur - Joueur joueur = new Joueur(); - joueur.setPseudo(pseudo); - - // Sauvegarder le joueur - joueur = joueurRepository.save(joueur); - - // Création de la partie - Partie partie = new Partie( - 0, - entityManager.createNativeQuery("SELECT make_uid()").getSingleResult().toString(), - List.of(joueur), - jeuRepository.findById(idJeu).orElseThrow(() -> new JeuNotFoundException(idJeu)), - "pending", - new Date() - ); - - // Sauvegarder la partie pour générer le codeInvitation - partie = partieRepository.save(partie); - - // Modification du joueur pour ajouter la partie - entityManager.createNativeQuery("UPDATE joueur SET idpartie = ? WHERE id = ?") - .setParameter(1, partie.getId()) - .setParameter(2, joueur.getId()) - .executeUpdate(); + public Partie update(Partie partie){ + if(!this.partieRepository.existsById(partie.getId())){ + throw new PartieNotFoundException(partie.getId()); + } + Partie savedPartie = this.partieRepository.save(partie); + return this.findById(savedPartie.getId()); + } - // Récupérer la partie mise à jour avec le joueur - return partieRepository.findById(partie.getId()) - .orElseThrow(MalformedPartyException::new); + public Partie create(Partie partie){ + if(partie.getId() != null && this.partieRepository.existsById(partie.getId())){ + throw new DuplicatedIdException(); + } + Partie savedPartie = this.partieRepository.save(partie); + return this.findById(savedPartie.getId()); } } diff --git a/SpringBootProject/src/main/resources/schema.sql b/SpringBootProject/src/main/resources/schema.sql index 8b219b0..359d9fb 100644 --- a/SpringBootProject/src/main/resources/schema.sql +++ b/SpringBootProject/src/main/resources/schema.sql @@ -111,10 +111,10 @@ CREATE OR REPLACE FUNCTION make_uid() RETURNS text AS CREATE TABLE Partie( id SERIAL PRIMARY KEY, - codeInvitation varchar(5) NOT NULL UNIQUE, + codeInvitation varchar(5) UNIQUE DEFAULT make_uid(), idJeu integer REFERENCES Jeu(id), - status varchar(128) NOT NULL DEFAULT 'pending', - dateCreation timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP + status varchar(128) DEFAULT 'pending', + dateCreation timestamp DEFAULT CURRENT_TIMESTAMP ); -- JOUEUR @@ -150,6 +150,35 @@ CREATE TABLE Decouvrir( PRIMARY KEY (idUtilisateur, idScientifique) ); +-- TRIGGERS + + + +CREATE OR REPLACE FUNCTION force_default_partie() + RETURNS TRIGGER +AS ' + DECLARE + BEGIN + IF OLD.codeInvitation IS NULL THEN + NEW.codeInvitation = make_uid(); + END IF; + IF OLD.status IS NULL THEN + NEW.status = ''pending''; + END IF; + IF OLD.dateCreation IS NULL THEN + NEW.dateCreation = CURRENT_TIMESTAMP; + END IF; + RETURN NEW; + END; + ' +LANGUAGE plpgsql; + +CREATE TRIGGER check_force_default_partie + BEFORE INSERT + ON Partie + FOR EACH ROW +EXECUTE PROCEDURE force_default_partie(); + -- INSERTS @@ -174,8 +203,8 @@ VALUES -- Indices INSERT INTO Indice (libelle, idscientifique) VALUES - ('Indice pour aider', 1), - ('S''appelle Marie', 1); + ('Indice pour aider', 1), + ('S''appelle Marie', 1); -- Réponses INSERT INTO Reponse(reponse, idQuestion, idScientifique) @@ -184,8 +213,12 @@ VALUES ('Albert Einstein', 2, 2), ('Sophie Germain', 3, 3); + +-- Partie +INSERT INTO Partie(codeInvitation, idJeu) VALUES ('abcde', 1); + -- Utilisateurs -INSERT INTO Joueur(pseudo) VALUES ('moi, le meilleur joueur du monde'); --id = 1 +INSERT INTO Joueur(pseudo, idPartie) VALUES ('moi, le meilleur joueur du monde', 1); --id = 1 INSERT INTO Utilisateur(idJoueur,email,password) VALUES (1, 'joueur','$2y$10$juGnlWC9cS19popEKLZsYeir0Jl39k6hDl0dpaCix00FDcdiEbtmS'); -- mdp = test @@ -194,7 +227,4 @@ INSERT INTO decouvrir(idUtilisateur,idScientifique) VALUES (1,1); -- Admin INSERT INTO Admin(id,email,password) VALUES (1, 'admin','$2y$10$juGnlWC9cS19popEKLZsYeir0Jl39k6hDl0dpaCix00FDcdiEbtmS'); --- mdp = test - --- Partie -INSERT INTO Partie(codeInvitation, idJeu) VALUES ('abcde', 1); \ No newline at end of file +-- mdp = test \ No newline at end of file