Travail jour 3

Springboot
Alix JEUDI--LEMOINE 1 year ago
parent d600565838
commit 790b121a57

@ -15,6 +15,7 @@
<description>API SAE ScienceQuest</description> <description>API SAE ScienceQuest</description>
<properties> <properties>
<java.version>21</java.version> <java.version>21</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties> </properties>
<dependencies> <dependencies>
<dependency> <dependency>

@ -16,9 +16,11 @@ import org.springframework.core.annotation.Order;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter; import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.util.ContentCachingResponseWrapper;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.nio.charset.StandardCharsets;
@Component @Component
@Order(1) @Order(1)
@ -30,83 +32,41 @@ public class ApplicationFilter extends OncePerRequestFilter {
} }
@Override @Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
throws ServletException, IOException {
// Intercept and modify the JSON response // Intercept and modify the JSON response
JsonInterceptingResponseWrapper responseWrapper = new JsonInterceptingResponseWrapper(response); ContentCachingResponseWrapper responseWrapper = new ContentCachingResponseWrapper(response);
filterChain.doFilter(request, responseWrapper); filterChain.doFilter(request, responseWrapper);
// Check if the response content type is JSON
if (responseWrapper.getContentType() != null && responseWrapper.getContentType().startsWith(MediaType.APPLICATION_JSON_VALUE)) { if (responseWrapper.getContentType() != null && responseWrapper.getContentType().startsWith(MediaType.APPLICATION_JSON_VALUE)) {
try { try {
// Parse the JSON response // Récupération du contenu en byteArray
JsonNode root = objectMapper.readTree(responseWrapper.getContent()); byte[] responseArray = responseWrapper.getContentAsByteArray();
// Check if the _embedded node exists and if it contains the tupleBackedMapList node // Parse JSON
JsonNode root = objectMapper.readTree(new String(responseArray, StandardCharsets.UTF_8));
// Vérification de l'existance du node _embedded && s'il contient un node enfant
JsonNode embeddedNode = root.get("_embedded"); JsonNode embeddedNode = root.get("_embedded");
if (embeddedNode != null && embeddedNode.isObject()) { if (embeddedNode != null && embeddedNode.isObject() && embeddedNode.size() == 1) {
JsonNode tupleBackedMapListNode = embeddedNode.get("tupleBackedMapList"); JsonNode subNode = embeddedNode.elements().next(); // Récupération node enfant
if (tupleBackedMapListNode != null && tupleBackedMapListNode.isArray()) { if (subNode != null && subNode.isArray()) {
ArrayNode tupleBackedMapList = (ArrayNode) tupleBackedMapListNode; ArrayNode subNodeArr = (ArrayNode) subNode;
// Remove the _embedded node // Correction de la profondeur
((ObjectNode) root).remove("_embedded"); ((ObjectNode) root).remove("_embedded");
((ObjectNode) root).set("_embedded", subNodeArr);
// Set the tupleBackedMapList directly to the root
((ObjectNode) root).set("_embedded", tupleBackedMapList);
} }
} }
// Convert the modified JSON back to string // Retour du JSON dans l'objectMapper en String
String modifiedResponseBody = objectMapper.writeValueAsString(root); String modifiedResponseBody = objectMapper.writeValueAsString(root);
// Write the modified JSON back to the response // Ecriture du JSON dans la réponse
response.getOutputStream().write(modifiedResponseBody.getBytes()); response.setCharacterEncoding("UTF-8");
} catch (IOException e) { response.setContentType(MediaType.APPLICATION_JSON_VALUE);
// Handle exception response.getOutputStream().write(modifiedResponseBody.getBytes(StandardCharsets.UTF_8));
e.printStackTrace(); } catch (IOException e) { System.err.println(e.getMessage()); }
}
}
}
private static class JsonInterceptingResponseWrapper extends HttpServletResponseWrapper {
private ByteArrayOutputStream baos = new ByteArrayOutputStream();
public JsonInterceptingResponseWrapper(HttpServletResponse response) {
super(response);
}
@Override
public ServletOutputStream getOutputStream() throws IOException {
return new ServletOutputStreamWrapper(baos);
}
public String getContent() {
return baos.toString();
}
}
private static class ServletOutputStreamWrapper extends ServletOutputStream {
private ByteArrayOutputStream baos;
public ServletOutputStreamWrapper(ByteArrayOutputStream baos) {
this.baos = baos;
}
@Override
public void write(int b) throws IOException {
baos.write(b);
}
@Override
public boolean isReady() {
return true;
}
@Override
public void setWriteListener(WriteListener writeListener) {
throw new UnsupportedOperationException("Not implemented");
} }
} }

@ -0,0 +1,83 @@
package fr.iut.sciencequest.sae.controllers;
import org.springframework.data.domain.Page;
import org.springframework.hateoas.CollectionModel;
import org.springframework.hateoas.EntityModel;
import org.springframework.hateoas.Link;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo;
public class Controller {
protected final int PAGE_SIZE = 1;
protected <T> EntityModel<T> getSelfLinkEntityModel(T entity, String method, Object... args) {
Class<?>[] argTypes = new Class[args.length];
for (int i = 0; i < args.length; i++) {
argTypes[i] = args[i].getClass();
}
try {
Link selfLink = linkTo(this.getClass(), this.getClass().getMethod(method, argTypes), args).withSelfRel();
return EntityModel.of(entity, selfLink);
} catch (NoSuchMethodException e) {
System.err.println("Method doesn't exist");
return null;
}
}
protected <T> CollectionModel<T> getSelfLinkCollectionModel(Iterable<T> entities, String method, Object... args) {
Class<?>[] argTypes = new Class[args.length];
for (int i = 0; i < args.length; i++) {
argTypes[i] = args[i].getClass();
}
try {
Link selfLink = linkTo(this.getClass(), this.getClass().getMethod(method, argTypes), args).withSelfRel();
return CollectionModel.of(entities, selfLink);
} catch (NoSuchMethodException e) {
System.err.println("Method doesn't exist");
return null;
}
}
protected <T> CollectionModel<EntityModel<T>> getPageableCollectionModel(Page<T> pagedResult, Integer page, String method, Object... args) {
try {
List<EntityModel<T>> entities = pagedResult.map(EntityModel::of).toList();
Class<?>[] argTypes = new Class[args.length+1];
for (int i = 0; i < args.length; i++) {
argTypes[i] = args[i].getClass();
}
argTypes[args.length] = Optional.class;
Method finalMethod = this.getClass().getMethod(method, argTypes);
List<Object> selfObj = new ArrayList<>(List.of(args)); selfObj.add(page);
Link selfLink = linkTo(this.getClass(), finalMethod, selfObj.toArray()).withSelfRel().expand(page);
CollectionModel<EntityModel<T>> result = CollectionModel.of(entities, selfLink);
if (pagedResult.hasPrevious()) {
List<Object> previousObj = new ArrayList<>(List.of(args)); previousObj.add(pagedResult.previousPageable().getPageNumber());
result.add(linkTo(this.getClass(), finalMethod, previousObj.toArray()).withRel("previous"));
}
if (pagedResult.hasNext()) {
List<Object> nextObj = new ArrayList<>(List.of(args)); nextObj.add(pagedResult.nextPageable().getPageNumber());
result.add(linkTo(this.getClass(), finalMethod, nextObj.toArray()).withRel("next"));
}
return result;
} catch(NoSuchMethodException e) {
System.err.println(e.getMessage());
return null;
}
}
}

@ -3,6 +3,7 @@ package fr.iut.sciencequest.sae.controllers;
import fr.iut.sciencequest.sae.entities.Difficulte; import fr.iut.sciencequest.sae.entities.Difficulte;
import fr.iut.sciencequest.sae.services.DifficulteService; import fr.iut.sciencequest.sae.services.DifficulteService;
import org.springframework.hateoas.CollectionModel;
import org.springframework.hateoas.EntityModel; import org.springframework.hateoas.EntityModel;
import org.springframework.hateoas.Link; import org.springframework.hateoas.Link;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
@ -18,8 +19,7 @@ import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn;
@RestController @RestController
@RequestMapping("/api/v1/difficultes") @RequestMapping("/api/v1/difficultes")
public class DifficulteController { public class DifficulteController extends Controller {
public final DifficulteService difficulteService; public final DifficulteService difficulteService;
public DifficulteController(DifficulteService difficulteService){ public DifficulteController(DifficulteService difficulteService){
@ -28,8 +28,7 @@ public class DifficulteController {
@GetMapping(produces = MediaType.APPLICATION_JSON_VALUE) @GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseStatus(HttpStatus.OK) @ResponseStatus(HttpStatus.OK)
public EntityModel<Iterable<Difficulte>> getAllDifficultes(){ public CollectionModel<Difficulte> getAllDifficultes() {
Link selfLink = linkTo(methodOn(DifficulteController.class).getAllDifficultes()).withSelfRel(); return getSelfLinkCollectionModel(this.difficulteService.findAll(), "getAllDifficultes");
return EntityModel.of(this.difficulteService.findAll(), selfLink);
} }
} }

@ -8,8 +8,7 @@ import org.springframework.web.bind.annotation.*;
@RestController @RestController
@RequestMapping("/api/v1/indices") @RequestMapping("/api/v1/indices")
public class IndiceController { public class IndiceController extends Controller {
private final IndiceService indiceService; private final IndiceService indiceService;
public IndiceController(IndiceService indiceService) { public IndiceController(IndiceService indiceService) {

@ -17,9 +17,7 @@ import java.util.Optional;
@RestController @RestController
@RequestMapping("/api/v1/partie") @RequestMapping("/api/v1/partie")
public class PartieController { public class PartieController extends Controller {
private static final int PAGE_SIZE = 5;
private final PartieRepository partieRepository; private final PartieRepository partieRepository;
public PartieController(PartieRepository partieRepository) { public PartieController(PartieRepository partieRepository) {
@ -30,7 +28,7 @@ public class PartieController {
public EntityModel<Optional<Partie>> getPartie(@PathVariable int id, HttpServletRequest request) { public EntityModel<Optional<Partie>> getPartie(@PathVariable int id, HttpServletRequest request) {
Optional<Partie> partieOptional = this.partieRepository.findById(id); Optional<Partie> partieOptional = this.partieRepository.findById(id);
Partie partie = partieOptional.orElseThrow(() -> Partie partie = partieOptional.orElseThrow(() ->
new PartieNotFoundException("Partie introuvable avec l'ID : " + id) new PartieNotFoundException("Partie", id)
); );
Link selfLink = linkTo(methodOn(PartieController.class).getPartie(id,request)).withSelfRel(); Link selfLink = linkTo(methodOn(PartieController.class).getPartie(id,request)).withSelfRel();

@ -2,58 +2,29 @@ package fr.iut.sciencequest.sae.controllers;
import fr.iut.sciencequest.sae.entities.Question; import fr.iut.sciencequest.sae.entities.Question;
import fr.iut.sciencequest.sae.exceptions.IncorrectPageException; import fr.iut.sciencequest.sae.exceptions.IncorrectPageException;
import fr.iut.sciencequest.sae.repositories.QuestionRepository; import fr.iut.sciencequest.sae.services.QuestionService;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.hateoas.CollectionModel; import org.springframework.hateoas.CollectionModel;
import org.springframework.hateoas.EntityModel; import org.springframework.hateoas.EntityModel;
import org.springframework.hateoas.Link;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Optional; import java.util.Optional;
import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo;
import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn;
@RestController @RestController
@RequestMapping("/api/v1/questions") @RequestMapping("/api/v1/questions")
public class QuestionController { public class QuestionController extends Controller {
private final QuestionService questionService;
private static final int PAGE_SIZE = 10;
private final QuestionRepository questionRepository;
public QuestionController(QuestionRepository questionRepository) { public QuestionController(QuestionService questionService) {
this.questionRepository = questionRepository; this.questionService = questionService;
} }
@RequestMapping(method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) @RequestMapping(method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody @ResponseBody
public CollectionModel<EntityModel<Question>> getAllQuestions(@RequestParam(name = "page") Optional<Integer> page, HttpServletRequest request) { public CollectionModel<EntityModel<Question>> getAllQuestions(@RequestParam(name = "page") Optional<Integer> page) {
try { try {
Pageable paging = PageRequest.of(page.orElse(0), PAGE_SIZE); return getPageableCollectionModel(questionService.findAll(page.orElse(0)), page.orElse(0), "getAllQuestions");
Page<Question> pagedResult = questionRepository.findAll(paging);
List<EntityModel<Question>> questions = pagedResult.map(EntityModel::of).toList();
Link selfLink = linkTo(methodOn(QuestionController.class).getAllQuestions(page, request)).withSelfRel().expand(page.map(Object::toString).orElse("0"));
CollectionModel<EntityModel<Question>> result = CollectionModel.of(questions, selfLink);
if (pagedResult.hasPrevious()) {
Link prevLink = linkTo(methodOn(QuestionController.class).getAllQuestions(Optional.of(pagedResult.previousPageable().getPageNumber()), request)).withRel("previous");
result.add(prevLink.expand(pagedResult.previousPageable().getPageNumber()));
}
if (pagedResult.hasNext()) {
Link nextLink = linkTo(methodOn(QuestionController.class).getAllQuestions(Optional.of(pagedResult.nextPageable().getPageNumber()), request)).withRel("next");
result.add(nextLink.expand(pagedResult.nextPageable().getPageNumber()));
}
return result;
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
throw new IncorrectPageException("numéro de page incorrect"); throw new IncorrectPageException("numéro de page incorrect");
} }

@ -1,97 +1,61 @@
package fr.iut.sciencequest.sae.controllers; package fr.iut.sciencequest.sae.controllers;
import fr.iut.sciencequest.sae.entities.Scientifique; import fr.iut.sciencequest.sae.entities.scientifique.Scientifique;
import fr.iut.sciencequest.sae.entities.indice.IIndiceidAndLibelleOnlyProjection; import fr.iut.sciencequest.sae.entities.indice.IIndiceidAndLibelleAndScientifiqueIdOnlyProjection;
import fr.iut.sciencequest.sae.entities.indice.Indice; import fr.iut.sciencequest.sae.entities.indice.Indice;
import fr.iut.sciencequest.sae.entities.indice.IValidateOnlyLibelle; import fr.iut.sciencequest.sae.entities.indice.IValidateOnlyLibelle;
import fr.iut.sciencequest.sae.exceptions.IncorrectPageException; import fr.iut.sciencequest.sae.exceptions.IncorrectPageException;
import fr.iut.sciencequest.sae.services.IndiceService; import fr.iut.sciencequest.sae.services.IndiceService;
import fr.iut.sciencequest.sae.services.interfaces.IScientifiqueService; import fr.iut.sciencequest.sae.services.interfaces.IScientifiqueService;
import org.springframework.data.domain.Page; import org.springframework.data.projection.ProjectionFactory;
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
import org.springframework.hateoas.CollectionModel; import org.springframework.hateoas.CollectionModel;
import org.springframework.hateoas.EntityModel; import org.springframework.hateoas.EntityModel;
import org.springframework.hateoas.Link;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional; import java.util.Optional;
import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo; import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo;
import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn;
@RestController @RestController
@RequestMapping("/api/v1/scientifiques") @RequestMapping("/api/v1/scientifiques")
public class ScientifiqueController { public class ScientifiqueController extends Controller {
private final IScientifiqueService scientifiqueService; private final IScientifiqueService scientifiqueService;
private final IndiceService indiceService; private final IndiceService indiceService;
private final int PAGE_SIZE = 1;
public ScientifiqueController(IScientifiqueService scientifiqueService, IndiceService indiceService) { public ScientifiqueController(IScientifiqueService scientifiqueService, IndiceService indiceService) {
this.scientifiqueService = scientifiqueService; this.scientifiqueService = scientifiqueService;
this.indiceService = indiceService; this.indiceService = indiceService;
} }
private <T> CollectionModel<EntityModel<T>> getPageableCollectionModel(Page<T> pagedResult, Integer page, Method method, Object... args) {
List<EntityModel<T>> entities = pagedResult.map(EntityModel::of).toList();
List<Object> selfObj = new ArrayList<>(List.of(args)); selfObj.add(page);
Link selfLink = linkTo(ScientifiqueController.class, method, selfObj.toArray()).withSelfRel().expand(page);
CollectionModel<EntityModel<T>> result = CollectionModel.of(entities, selfLink);
if (pagedResult.hasPrevious()) {
List<Object> previousObj = new ArrayList<>(List.of(args)); previousObj.add(pagedResult.previousPageable().getPageNumber());
result.add(linkTo(ScientifiqueController.class, method, previousObj.toArray()).withRel("previous"));
}
if (pagedResult.hasNext()) {
List<Object> nextObj = new ArrayList<>(List.of(args)); nextObj.add(pagedResult.nextPageable().getPageNumber());
result.add(linkTo(ScientifiqueController.class, method, nextObj.toArray()).withRel("next"));
}
return result;
}
@GetMapping(produces = MediaType.APPLICATION_JSON_VALUE) @GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public CollectionModel<EntityModel<Scientifique>> getAllScientists(@RequestParam(name = "page") Optional<Integer> page) { public CollectionModel<EntityModel<Scientifique>> getAllScientists(@RequestParam(name = "page") Optional<Integer> page) {
try { try {
Page<Scientifique> pagedResult = this.scientifiqueService.findAll(page.orElse(0)); return getPageableCollectionModel(this.scientifiqueService.findAll(page.orElse(0)), page.orElse(0),"getAllScientists");
return getPageableCollectionModel(pagedResult, page.orElse(0), ScientifiqueController.class.getMethod("getAllScientists", Optional.class));
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
throw new IncorrectPageException("numéro de page incorrect"); throw new IncorrectPageException("numéro de page incorrect");
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
} }
} }
@GetMapping(value = "/{id}", produces = MediaType.APPLICATION_JSON_VALUE) @GetMapping(value = "/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody public EntityModel<Scientifique> getScientistById(@PathVariable Integer id) {
public EntityModel<Scientifique> getScientistById(@PathVariable int id) { return getSelfLinkEntityModel(this.scientifiqueService.findById(id), "getScientistById", id);
Link selfLink = linkTo(methodOn(ScientifiqueController.class).getScientistById(id)).withSelfRel();
return EntityModel.of(this.scientifiqueService.findById(id), selfLink);
} }
@GetMapping(value="/{id}/indices", produces = MediaType.APPLICATION_JSON_VALUE) @GetMapping(value="/{id}/indices", produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody public CollectionModel<IIndiceidAndLibelleAndScientifiqueIdOnlyProjection> getScientistHints(@PathVariable Integer id) {
public CollectionModel<IIndiceidAndLibelleOnlyProjection> getScientistHints(@PathVariable int id) { return getSelfLinkCollectionModel(this.scientifiqueService.getLinkedIndicesByScientifiqueId(id), "getScientistHints", id);
Link selfLink = linkTo(methodOn(ScientifiqueController.class).getScientistHints(id)).withSelfRel();
return CollectionModel.of(this.scientifiqueService.getLinkedIndicesByScientifiqueId(id), selfLink);
} }
@PostMapping(value="/{id}/indices", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) @PostMapping(value="/{id}/indices", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseStatus(HttpStatus.CREATED) @ResponseStatus(HttpStatus.CREATED)
public Indice postIndice(@PathVariable int id, @Validated(IValidateOnlyLibelle.class) @RequestBody Indice indice){ public IIndiceidAndLibelleAndScientifiqueIdOnlyProjection postIndice(@PathVariable Integer id, @Validated(IValidateOnlyLibelle.class) @RequestBody Indice indice){
indice.setScientifique(this.scientifiqueService.findById(id)); indice.setScientifique(this.scientifiqueService.findById(id));
return this.indiceService.create(indice); indice = this.indiceService.create(indice);
return indice.toProjection(IIndiceidAndLibelleAndScientifiqueIdOnlyProjection.class);
} }
} }

@ -3,13 +3,15 @@ package fr.iut.sciencequest.sae.controllers;
import fr.iut.sciencequest.sae.entities.Thematique; import fr.iut.sciencequest.sae.entities.Thematique;
import fr.iut.sciencequest.sae.services.interfaces.IThematiqueService; import fr.iut.sciencequest.sae.services.interfaces.IThematiqueService;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import org.springframework.hateoas.CollectionModel;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
@RestController @RestController
@RequestMapping("/api/v1/thematiques") @RequestMapping("/api/v1/thematiques")
public class ThematiqueController { public class ThematiqueController extends Controller {
private final IThematiqueService thematiqueService; private final IThematiqueService thematiqueService;
public ThematiqueController(IThematiqueService thematiqueService) { public ThematiqueController(IThematiqueService thematiqueService) {
@ -18,8 +20,8 @@ public class ThematiqueController {
@GetMapping(produces = MediaType.APPLICATION_JSON_VALUE) @GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseStatus(HttpStatus.OK) @ResponseStatus(HttpStatus.OK)
public Iterable<Thematique> getAllThematiques() { public CollectionModel<Thematique> getAllThematiques() {
return this.thematiqueService.findAll(); return getSelfLinkCollectionModel(this.thematiqueService.findAll(), "getAllThematiques");
} }
//TODO : gestion des erreurs remontées par @Valid //TODO : gestion des erreurs remontées par @Valid

@ -13,7 +13,7 @@ import lombok.NoArgsConstructor;
@Data @Data
@Entity @Entity
@Table(name="admin") @Table(name="admin")
public class Admin { public class Admin extends BaseEntity {
@Id @Id
@NotNull @NotNull
@GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(strategy = GenerationType.IDENTITY)

@ -0,0 +1,12 @@
package fr.iut.sciencequest.sae.entities;
import org.springframework.data.projection.ProjectionFactory;
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
public abstract class BaseEntity implements IToProjection {
public <T> T toProjection(Class<T> projectionType){
ProjectionFactory pf = new SpelAwareProxyProjectionFactory();
return pf.createProjection(projectionType, this);
}
}

@ -13,7 +13,7 @@ import lombok.NoArgsConstructor;
@Data @Data
@Entity @Entity
@Table(name="difficulte") @Table(name="difficulte")
public class Difficulte { public class Difficulte extends BaseEntity {
@Id @Id
@NotNull @NotNull
@GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(strategy = GenerationType.IDENTITY)

@ -0,0 +1,5 @@
package fr.iut.sciencequest.sae.entities;
public interface IToProjection {
public <T> T toProjection(Class<T> projectionType);
}

@ -5,7 +5,7 @@ import jakarta.persistence.*;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@AllArgsConstructor @AllArgsConstructor
@Data @Data

@ -7,14 +7,13 @@ import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import org.springframework.boot.context.properties.bind.DefaultValue;
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
@Data @Data
@Entity @Entity
@Table(name="jeu") @Table(name="jeu")
public class Jeu { public class Jeu extends BaseEntity {
@Id @Id
@NotNull @NotNull
@GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(strategy = GenerationType.IDENTITY)

@ -13,7 +13,7 @@ import lombok.NoArgsConstructor;
@Inheritance ( strategy = InheritanceType.JOINED) @Inheritance ( strategy = InheritanceType.JOINED)
@Entity @Entity
@Table(name="joueur") @Table(name="joueur")
public abstract class Joueur { public abstract class Joueur extends BaseEntity {
@Id @Id
@NotNull @NotNull
@GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(strategy = GenerationType.IDENTITY)

@ -4,17 +4,14 @@ import jakarta.persistence.*;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import java.util.Set;
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
@Data @Data
@Entity @Entity
@Table(name="partie") @Table(name="partie")
public class Partie { public class Partie extends BaseEntity {
@Id @Id
@NotNull @NotNull
@GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(strategy = GenerationType.IDENTITY)

@ -5,6 +5,8 @@ import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import java.util.List; import java.util.List;
@ -14,7 +16,7 @@ import java.util.List;
@Data @Data
@Entity @Entity
@Table(name="question") @Table(name="question")
public class Question { public class Question extends BaseEntity {
@Id @Id
@NotNull @NotNull
@GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(strategy = GenerationType.IDENTITY)
@ -23,6 +25,7 @@ public class Question {
@NotEmpty @NotEmpty
@OneToMany(mappedBy = "id") @OneToMany(mappedBy = "id")
@Fetch(FetchMode.JOIN) // Sinon crash (Could not write JSON: failed to lazily initialize a collection of role)
private List<Reponse> reponses; private List<Reponse> reponses;
} }

@ -11,7 +11,7 @@ import lombok.NoArgsConstructor;
@Data @Data
@Entity @Entity
@Table(name="reponse") @Table(name="reponse")
public class Reponse { public class Reponse extends BaseEntity {
@Id @Id
@NotNull @NotNull
@GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(strategy = GenerationType.IDENTITY)

@ -3,7 +3,6 @@ package fr.iut.sciencequest.sae.entities;
import jakarta.persistence.*; import jakarta.persistence.*;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
@ -14,7 +13,7 @@ import lombok.NoArgsConstructor;
@Data @Data
@Entity @Entity
@Table(name="thematique") @Table(name="thematique")
public class Thematique { public class Thematique extends BaseEntity {
@Id @Id
@GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(strategy = GenerationType.IDENTITY)
private int id; private int id;

@ -0,0 +1,10 @@
package fr.iut.sciencequest.sae.entities.indice;
import fr.iut.sciencequest.sae.entities.scientifique.IScientifiqueIdOnlyProjection;
public interface IIndiceidAndLibelleAndScientifiqueIdOnlyProjection {
int getId();
String getLibelle();
IScientifiqueIdOnlyProjection getScientifique();
}

@ -1,6 +0,0 @@
package fr.iut.sciencequest.sae.entities.indice;
public interface IIndiceidAndLibelleOnlyProjection {
int getId();
String getLibelle();
}

@ -1,6 +1,7 @@
package fr.iut.sciencequest.sae.entities.indice; package fr.iut.sciencequest.sae.entities.indice;
import fr.iut.sciencequest.sae.entities.Scientifique; import fr.iut.sciencequest.sae.entities.BaseEntity;
import fr.iut.sciencequest.sae.entities.scientifique.Scientifique;
import jakarta.persistence.*; import jakarta.persistence.*;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
@ -13,7 +14,7 @@ import lombok.NoArgsConstructor;
@Data @Data
@Entity @Entity
@Table(name="indice") @Table(name="indice")
public class Indice { public class Indice extends BaseEntity {
@Id @Id
@GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(strategy = GenerationType.IDENTITY)
private int id; private int id;
@ -21,7 +22,6 @@ public class Indice {
@NotBlank(groups = {IValidateOnlyLibelle.class}) @NotBlank(groups = {IValidateOnlyLibelle.class})
private String libelle; private String libelle;
@ManyToOne @ManyToOne
@NotNull @NotNull
@JoinColumn(name="idscientifique", nullable = false) @JoinColumn(name="idscientifique", nullable = false)

@ -0,0 +1,5 @@
package fr.iut.sciencequest.sae.entities.scientifique;
public interface IScientifiqueIdOnlyProjection {
int getId();
}

@ -1,5 +1,9 @@
package fr.iut.sciencequest.sae.entities; package fr.iut.sciencequest.sae.entities.scientifique;
import fr.iut.sciencequest.sae.entities.BaseEntity;
import fr.iut.sciencequest.sae.entities.Difficulte;
import fr.iut.sciencequest.sae.entities.Sexe;
import fr.iut.sciencequest.sae.entities.Thematique;
import jakarta.persistence.*; import jakarta.persistence.*;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
@ -19,7 +23,7 @@ import java.util.Date;
@Data @Data
@Entity @Entity
@Table(name = "scientifique") @Table(name = "scientifique")
public class Scientifique { public class Scientifique extends BaseEntity {
@Id @Id
@NotNull @NotNull
@GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(strategy = GenerationType.IDENTITY)

@ -5,8 +5,8 @@ import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.ResponseStatus;
@ResponseStatus(HttpStatus.NOT_FOUND) @ResponseStatus(HttpStatus.NOT_FOUND)
public class PartieNotFoundException extends RuntimeException{ public class PartieNotFoundException extends EntityNotFoundException{
public PartieNotFoundException(String message) { public PartieNotFoundException(String message, int id) {
super(message); super(message, id);
} }
} }

@ -1,6 +1,6 @@
package fr.iut.sciencequest.sae.repositories; package fr.iut.sciencequest.sae.repositories;
import fr.iut.sciencequest.sae.entities.Scientifique; import fr.iut.sciencequest.sae.entities.scientifique.Scientifique;
import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;

@ -1,6 +1,6 @@
package fr.iut.sciencequest.sae.services; package fr.iut.sciencequest.sae.services;
import fr.iut.sciencequest.sae.entities.indice.IIndiceidAndLibelleOnlyProjection; import fr.iut.sciencequest.sae.entities.indice.IIndiceidAndLibelleAndScientifiqueIdOnlyProjection;
import fr.iut.sciencequest.sae.entities.indice.Indice; import fr.iut.sciencequest.sae.entities.indice.Indice;
import fr.iut.sciencequest.sae.exceptions.DuplicatedIdException; import fr.iut.sciencequest.sae.exceptions.DuplicatedIdException;
import fr.iut.sciencequest.sae.exceptions.notFound.IndiceNotFoundException; import fr.iut.sciencequest.sae.exceptions.notFound.IndiceNotFoundException;
@ -18,8 +18,8 @@ public class IndiceService implements IIndiceService {
} }
@Override @Override
public Iterable<IIndiceidAndLibelleOnlyProjection> findByScientifiqueId(int id) { public Iterable<IIndiceidAndLibelleAndScientifiqueIdOnlyProjection> findByScientifiqueId(int id) {
return this.indiceRepository.findByScientifiqueId(id, IIndiceidAndLibelleOnlyProjection.class); return this.indiceRepository.findByScientifiqueId(id, IIndiceidAndLibelleAndScientifiqueIdOnlyProjection.class);
} }
@Override @Override

@ -0,0 +1,4 @@
package fr.iut.sciencequest.sae.services;
public class PartieService {
}

@ -0,0 +1,25 @@
package fr.iut.sciencequest.sae.services;
import fr.iut.sciencequest.sae.entities.Question;
import fr.iut.sciencequest.sae.repositories.QuestionRepository;
import fr.iut.sciencequest.sae.services.interfaces.IQuestionService;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
@Service
public class QuestionService implements IQuestionService {
private static final int PAGE_SIZE = 1;
private final QuestionRepository questionRepository;
public QuestionService(QuestionRepository questionRepository) {
this.questionRepository = questionRepository;
}
@Override
public Page<Question> findAll(Integer page) {
Pageable paging = PageRequest.of(page, PAGE_SIZE);
return questionRepository.findAll(paging);
}
}

@ -1,7 +1,7 @@
package fr.iut.sciencequest.sae.services; package fr.iut.sciencequest.sae.services;
import fr.iut.sciencequest.sae.entities.Scientifique; import fr.iut.sciencequest.sae.entities.scientifique.Scientifique;
import fr.iut.sciencequest.sae.entities.indice.IIndiceidAndLibelleOnlyProjection; import fr.iut.sciencequest.sae.entities.indice.IIndiceidAndLibelleAndScientifiqueIdOnlyProjection;
import fr.iut.sciencequest.sae.exceptions.notFound.ScientifiqueNotFoundException; import fr.iut.sciencequest.sae.exceptions.notFound.ScientifiqueNotFoundException;
import fr.iut.sciencequest.sae.repositories.ScientifiqueRepository; import fr.iut.sciencequest.sae.repositories.ScientifiqueRepository;
import fr.iut.sciencequest.sae.services.interfaces.IScientifiqueService; import fr.iut.sciencequest.sae.services.interfaces.IScientifiqueService;
@ -47,7 +47,7 @@ public class ScientifiqueService implements IScientifiqueService {
} }
@Override @Override
public Iterable<IIndiceidAndLibelleOnlyProjection> getLinkedIndicesByScientifiqueId(int id){ public Iterable<IIndiceidAndLibelleAndScientifiqueIdOnlyProjection> getLinkedIndicesByScientifiqueId(int id){
if(!this.scientifiqueRepository.existsById(id)){ if(!this.scientifiqueRepository.existsById(id)){
throw new ScientifiqueNotFoundException(id); throw new ScientifiqueNotFoundException(id);
} }

@ -1,10 +1,10 @@
package fr.iut.sciencequest.sae.services.interfaces; package fr.iut.sciencequest.sae.services.interfaces;
import fr.iut.sciencequest.sae.entities.indice.IIndiceidAndLibelleOnlyProjection; import fr.iut.sciencequest.sae.entities.indice.IIndiceidAndLibelleAndScientifiqueIdOnlyProjection;
import fr.iut.sciencequest.sae.entities.indice.Indice; import fr.iut.sciencequest.sae.entities.indice.Indice;
public interface IIndiceService { public interface IIndiceService {
Iterable<IIndiceidAndLibelleOnlyProjection> findByScientifiqueId(int id); Iterable<IIndiceidAndLibelleAndScientifiqueIdOnlyProjection> findByScientifiqueId(int id);
Indice update(Indice indice); Indice update(Indice indice);
Indice create(Indice indice); Indice create(Indice indice);
} }

@ -0,0 +1,5 @@
package fr.iut.sciencequest.sae.services.interfaces;
public class IPartieService {
}

@ -0,0 +1,8 @@
package fr.iut.sciencequest.sae.services.interfaces;
import fr.iut.sciencequest.sae.entities.Question;
import org.springframework.data.domain.Page;
public interface IQuestionService {
Page<Question> findAll(Integer page);
}

@ -1,7 +1,7 @@
package fr.iut.sciencequest.sae.services.interfaces; package fr.iut.sciencequest.sae.services.interfaces;
import fr.iut.sciencequest.sae.entities.Scientifique; import fr.iut.sciencequest.sae.entities.scientifique.Scientifique;
import fr.iut.sciencequest.sae.entities.indice.IIndiceidAndLibelleOnlyProjection; import fr.iut.sciencequest.sae.entities.indice.IIndiceidAndLibelleAndScientifiqueIdOnlyProjection;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
public interface IScientifiqueService { public interface IScientifiqueService {
@ -13,5 +13,5 @@ public interface IScientifiqueService {
Scientifique findById(int id); Scientifique findById(int id);
Iterable<IIndiceidAndLibelleOnlyProjection> getLinkedIndicesByScientifiqueId(int id); Iterable<IIndiceidAndLibelleAndScientifiqueIdOnlyProjection> getLinkedIndicesByScientifiqueId(int id);
} }

@ -0,0 +1,3 @@
Manifest-Version: 1.0
Main-Class: fr.iut.sciencequest.sae.SaeApplication

@ -154,9 +154,9 @@ VALUES
('Quel mathématicienne utilisa comme nom d"emprunt « Antoine Auguste Le Blanc » ?'); ('Quel mathématicienne utilisa comme nom d"emprunt « Antoine Auguste Le Blanc » ?');
-- Indices -- Indices
INSERT INTO Indice (id, libelle, idscientifique) VALUES INSERT INTO Indice (libelle, idscientifique) VALUES
(1, 'Indice pour aider', 1), ('Indice pour aider', 1),
(2, 'S''appelle Marie', 1); ('S''appelle Marie', 1);
-- Réponses -- Réponses
INSERT INTO Reponse(reponse, idQuestion, idScientifique) INSERT INTO Reponse(reponse, idQuestion, idScientifique)

Loading…
Cancel
Save