From 4ac5ab2e0434e43a7fe6bef0e6a2faa7d386bc7c Mon Sep 17 00:00:00 2001 From: Ryan Rossez <ryan.rossez@outlook.fr> Date: Tue, 18 Feb 2020 15:48:54 +0100 Subject: [PATCH] =?UTF-8?q?Pizza=20sans=20ingr=C3=A9dients=20fonctionnel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fr/ulille/iut/pizzaland/beans/Pizza.java | 117 +++++++++++ .../fr/ulille/iut/pizzaland/dao/PizzaDao.java | 56 ++++++ .../pizzaland/dto/IngredientCreateDto.java | 1 + .../iut/pizzaland/dto/IngredientDto.java | 2 + .../iut/pizzaland/dto/PizzaCreateDto.java | 28 +++ .../fr/ulille/iut/pizzaland/dto/PizzaDto.java | 45 +++++ .../pizzaland/resources/PizzaResource.java | 118 +++++++++++ src/main/resources/ingredients.json | 1 + src/main/resources/pizza.json | 5 + .../iut/pizzaland/IngredientResourceTest.java | 4 +- .../iut/pizzaland/PizzaResourceTest.java | 190 ++++++++++++++++++ 11 files changed, 565 insertions(+), 2 deletions(-) create mode 100644 src/main/java/fr/ulille/iut/pizzaland/beans/Pizza.java create mode 100644 src/main/java/fr/ulille/iut/pizzaland/dao/PizzaDao.java create mode 100644 src/main/java/fr/ulille/iut/pizzaland/dto/PizzaCreateDto.java create mode 100644 src/main/java/fr/ulille/iut/pizzaland/dto/PizzaDto.java create mode 100644 src/main/java/fr/ulille/iut/pizzaland/resources/PizzaResource.java create mode 100644 src/main/resources/pizza.json create mode 100644 src/test/java/fr/ulille/iut/pizzaland/PizzaResourceTest.java diff --git a/src/main/java/fr/ulille/iut/pizzaland/beans/Pizza.java b/src/main/java/fr/ulille/iut/pizzaland/beans/Pizza.java new file mode 100644 index 0000000..e4fb47f --- /dev/null +++ b/src/main/java/fr/ulille/iut/pizzaland/beans/Pizza.java @@ -0,0 +1,117 @@ +package fr.ulille.iut.pizzaland.beans; + +import java.util.ArrayList; +import java.util.List; + +import fr.ulille.iut.pizzaland.dto.*; + +public class Pizza { + private long id; + private String name; + private List<Ingredient> ingredients = new ArrayList<Ingredient>(); + + public Pizza() { + } + + public Pizza(long id, String name) { + this.id = id; + this.name = name; + this.ingredients=new ArrayList<Ingredient>(); + } + + public Pizza(long id, String name,List<Ingredient> ingredients){ + this.id=id; + this.name=name; + this.ingredients=ingredients; + } + + public void setId(long id) { + this.id = id; + } + + public long getId() { + return id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public void setIngredients(List<Ingredient> ingredients){ + this.ingredients = ingredients; + } + + public void addIngredients(Ingredient ingredient){ + this.ingredients.add(ingredient); + } + + public void removeIngredients(Ingredient ingredient){ + this.ingredients.remove(ingredient); + } + + public List<Ingredient> getIngredients(){ + return this.ingredients; + } + + public static PizzaDto toDto(Pizza i) { + PizzaDto dto = new PizzaDto(); + dto.setId(i.getId()); + dto.setName(i.getName()); + + return dto; + } + + public static Pizza fromDto(PizzaDto dto) { + Pizza pizza = new Pizza(); + pizza.setId(dto.getId()); + pizza.setName(dto.getName()); + + return pizza; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Pizza other = (Pizza) obj; + if (id != other.id) + return false; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + return true; + } + + @Override + public String toString() { + String res = "Pizza [id=" + id + ", name=" + name + "] "; + for (Ingredient i : ingredients ){ + res+=i.toString(); + } + return res; + } + + public static PizzaCreateDto toCreateDto(Pizza pizza) { + PizzaCreateDto dto = new PizzaCreateDto(); + dto.setName(pizza.getName()); + + return dto; + } + + public static Pizza fromPizzaCreateDto(PizzaCreateDto dto) { + Pizza pizza = new Pizza(); + pizza.setName(dto.getName()); + + return pizza; + } + } diff --git a/src/main/java/fr/ulille/iut/pizzaland/dao/PizzaDao.java b/src/main/java/fr/ulille/iut/pizzaland/dao/PizzaDao.java new file mode 100644 index 0000000..39a1d9d --- /dev/null +++ b/src/main/java/fr/ulille/iut/pizzaland/dao/PizzaDao.java @@ -0,0 +1,56 @@ +package fr.ulille.iut.pizzaland.dao; + +import java.util.List; + +import org.jdbi.v3.sqlobject.config.RegisterBeanMapper; +import org.jdbi.v3.sqlobject.statement.GetGeneratedKeys; +import org.jdbi.v3.sqlobject.statement.SqlQuery; +import org.jdbi.v3.sqlobject.statement.SqlUpdate; +import org.jdbi.v3.sqlobject.transaction.Transaction; + +import fr.ulille.iut.pizzaland.beans.Pizza; +public interface PizzaDao { + + @SqlUpdate("CREATE TABLE IF NOT EXISTS pizzas (id INTEGER PRIMARY KEY, name VARCHAR UNIQUE NOT NULL)") + void createPizzaTable(); + + @SqlUpdate("CREATE TABLE IF NOT EXISTS pizzaIngredientAssociation(idIngredient INTEGER, idPizza INTEGER, constraint pk_pizzaIA Primary key(idIngredient,idPizza))") + void createAssociationTable(); + + @Transaction + default void createPizzaAndAssociationTable(){ + createAssociationTable(); + createPizzaTable(); + } + + @SqlUpdate("DROP TABLE IF EXISTS pizzas") + void dropPizzaTable(); + @SqlUpdate("DROP TABLE IF EXISTS pizzaIngredientAssociation") + void dropIngredientAssociationTable(); + + @Transaction + default void deletePizzaAndAssociationTable(){ + dropIngredientAssociationTable(); + dropPizzaTable(); + } + + @SqlUpdate("INSERT INTO pizzas (name) VALUES (:name)") + @GetGeneratedKeys + long insert(String name); + + @SqlQuery("SELECT * FROM pizzas") + @RegisterBeanMapper(Pizza.class) + List<Pizza> getAll(); + + @SqlQuery("SELECT * FROM pizzas WHERE id = :id") + @RegisterBeanMapper(Pizza.class) + Pizza findById(long id); + + @SqlQuery("SELECT * FROM pizzas WHERE name = :name") + @RegisterBeanMapper(Pizza.class) + Pizza findByName(String name); + + @SqlUpdate("DELETE FROM pizzas WHERE id = :id") + void remove(long id); + +} \ No newline at end of file diff --git a/src/main/java/fr/ulille/iut/pizzaland/dto/IngredientCreateDto.java b/src/main/java/fr/ulille/iut/pizzaland/dto/IngredientCreateDto.java index b2a0dfd..9d3de51 100644 --- a/src/main/java/fr/ulille/iut/pizzaland/dto/IngredientCreateDto.java +++ b/src/main/java/fr/ulille/iut/pizzaland/dto/IngredientCreateDto.java @@ -12,4 +12,5 @@ public class IngredientCreateDto { public String getName() { return name; } + } diff --git a/src/main/java/fr/ulille/iut/pizzaland/dto/IngredientDto.java b/src/main/java/fr/ulille/iut/pizzaland/dto/IngredientDto.java index f649021..2ebee6d 100644 --- a/src/main/java/fr/ulille/iut/pizzaland/dto/IngredientDto.java +++ b/src/main/java/fr/ulille/iut/pizzaland/dto/IngredientDto.java @@ -21,5 +21,7 @@ public class IngredientDto { public String getName() { return name; } + + } \ No newline at end of file diff --git a/src/main/java/fr/ulille/iut/pizzaland/dto/PizzaCreateDto.java b/src/main/java/fr/ulille/iut/pizzaland/dto/PizzaCreateDto.java new file mode 100644 index 0000000..19cce89 --- /dev/null +++ b/src/main/java/fr/ulille/iut/pizzaland/dto/PizzaCreateDto.java @@ -0,0 +1,28 @@ +package fr.ulille.iut.pizzaland.dto; + +import java.util.List; + +import fr.ulille.iut.pizzaland.beans.Ingredient; + +public class PizzaCreateDto { + private String name; + private List<Ingredient> ingredients; + + public PizzaCreateDto() {} + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setIngredients(List<Ingredient> ingredients){ + this.ingredients = ingredients; + } + + public List<Ingredient> getIngredients(){ + return this.ingredients; + } +} \ No newline at end of file diff --git a/src/main/java/fr/ulille/iut/pizzaland/dto/PizzaDto.java b/src/main/java/fr/ulille/iut/pizzaland/dto/PizzaDto.java new file mode 100644 index 0000000..aae5865 --- /dev/null +++ b/src/main/java/fr/ulille/iut/pizzaland/dto/PizzaDto.java @@ -0,0 +1,45 @@ +package fr.ulille.iut.pizzaland.dto; + +import java.util.List; + +import fr.ulille.iut.pizzaland.beans.Ingredient; + +public class PizzaDto { + private long id; + private String name; + private List<Ingredient> ingredients; + + public PizzaDto() {} + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setIngredients(List<Ingredient> ingredients){ + this.ingredients = ingredients; + } + + public void addIngredients(Ingredient ingredient){ + this.ingredients.add(ingredient); + } + + public void removeIngredients(Ingredient ingredient){ + this.ingredients.remove(ingredient); + } + + public List<Ingredient> getIngredients(){ + return this.ingredients; + } + } \ No newline at end of file diff --git a/src/main/java/fr/ulille/iut/pizzaland/resources/PizzaResource.java b/src/main/java/fr/ulille/iut/pizzaland/resources/PizzaResource.java new file mode 100644 index 0000000..b462022 --- /dev/null +++ b/src/main/java/fr/ulille/iut/pizzaland/resources/PizzaResource.java @@ -0,0 +1,118 @@ +package fr.ulille.iut.pizzaland.resources; + +import java.net.URI; +import java.util.List; +import java.util.ArrayList; +import java.util.logging.Logger; +import java.util.stream.Collectors; + +import fr.ulille.iut.pizzaland.beans.Pizza; +import fr.ulille.iut.pizzaland.BDDFactory; +import fr.ulille.iut.pizzaland.dao.PizzaDao; + +import javax.ws.rs.POST; +import javax.ws.rs.DELETE; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.PathParam; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; + +import fr.ulille.iut.pizzaland.dto.PizzaCreateDto; +import fr.ulille.iut.pizzaland.dto.PizzaDto; + +@Path("/pizzas") +public class PizzaResource { + private static final Logger LOGGER = Logger.getLogger(PizzaResource.class.getName()); + + List<PizzaDto> listPizzas=new ArrayList<PizzaDto>(); + + private PizzaDao pizzas; + + + @Context + public UriInfo uriInfo; + + public PizzaResource() { + pizzas = BDDFactory.buildDao(PizzaDao.class); + pizzas.createPizzaAndAssociationTable(); + } + + @GET + public List<PizzaDto> getAll() { + LOGGER.info("PizzaResource:getAll"); + List<Pizza> lp = pizzas.getAll(); + List<PizzaDto> l= new ArrayList<PizzaDto>(); + for (Pizza pizza: lp){ + l.add(Pizza.toDto(pizza)); + } + return l; + } + + + @GET + @Path("{id}") + public PizzaDto getOnePizza(@PathParam("id") long id) { + LOGGER.info("getOnePizza(" + id + ")"); + try { + Pizza pizza= pizzas.findById(id); + return Pizza.toDto(pizza); + } + catch ( Exception e ) { + // Cette exception générera une réponse avec une erreur 404 + throw new WebApplicationException(Response.Status.NOT_FOUND); + } + } + + + +@POST +public Response createPizza(PizzaCreateDto pizzaCreateDto) { + Pizza existing = pizzas.findByName(pizzaCreateDto.getName()); + if ( existing != null ) { + throw new WebApplicationException(Response.Status.CONFLICT); + } + + try { + Pizza pizza = Pizza.fromPizzaCreateDto(pizzaCreateDto); + long id = pizzas.insert(pizza.getName()); + pizza.setId(id); + PizzaDto pizzaDto = Pizza.toDto(pizza); + + URI uri = uriInfo.getAbsolutePathBuilder().path("" + id).build(); + + return Response.created(uri).entity(pizzaDto).build(); + } + catch ( Exception e ) { + e.printStackTrace(); + throw new WebApplicationException(Response.Status.NOT_ACCEPTABLE); + } +} + + @DELETE + @Path("{id}") + public Response deletePizza(@PathParam("id") long id) { + if ( pizzas.findById(id) == null ) { + throw new WebApplicationException(Response.Status.NOT_FOUND); + } + + pizzas.remove(id); + + return Response.status(Response.Status.ACCEPTED).build(); + } + + @GET + @Path("{id}/name") + public String getPizzaName(@PathParam("id") long id) { + Pizza pizza = pizzas.findById(id); + if ( pizza == null ) { + throw new WebApplicationException(Response.Status.NOT_FOUND); + } + + return pizza.getName(); +} + + +} \ No newline at end of file diff --git a/src/main/resources/ingredients.json b/src/main/resources/ingredients.json index fdc8446..78f1058 100644 --- a/src/main/resources/ingredients.json +++ b/src/main/resources/ingredients.json @@ -3,6 +3,7 @@ { "name": "jambon"}, { "name": "champignons"}, { "name": "olives"}, +{ "name":"saumon"}, { "name": "tomate"}, { "name": "merguez"}, { "name": "lardons"}, diff --git a/src/main/resources/pizza.json b/src/main/resources/pizza.json new file mode 100644 index 0000000..4e81a2f --- /dev/null +++ b/src/main/resources/pizza.json @@ -0,0 +1,5 @@ +[ +{"name":"calzone","ingredient":"tomate"}, +{"name":"savoyarde","ingredient":"fromage"}, +{"name":"nordique","ingredient":"saumon"} +] \ No newline at end of file diff --git a/src/test/java/fr/ulille/iut/pizzaland/IngredientResourceTest.java b/src/test/java/fr/ulille/iut/pizzaland/IngredientResourceTest.java index 5f1f971..8b8c7ee 100644 --- a/src/test/java/fr/ulille/iut/pizzaland/IngredientResourceTest.java +++ b/src/test/java/fr/ulille/iut/pizzaland/IngredientResourceTest.java @@ -71,7 +71,7 @@ public class IngredientResourceTest extends JerseyTest { // On vérifie que la liste est bien vide assertEquals(0, ingredients.size()); } - + @Test public void testGetExistingIngredient() { @@ -91,7 +91,7 @@ public class IngredientResourceTest extends JerseyTest { @Test public void testGetNotExistingPizza() { - Response response = target("/pizzas/125").request().get(); + Response response = target("/ingredients/125").request().get(); assertEquals(Response.Status.NOT_FOUND.getStatusCode(),response.getStatus()); } diff --git a/src/test/java/fr/ulille/iut/pizzaland/PizzaResourceTest.java b/src/test/java/fr/ulille/iut/pizzaland/PizzaResourceTest.java new file mode 100644 index 0000000..830519e --- /dev/null +++ b/src/test/java/fr/ulille/iut/pizzaland/PizzaResourceTest.java @@ -0,0 +1,190 @@ +package fr.ulille.iut.pizzaland; + +import fr.ulille.iut.pizzaland.ApiV1; +import fr.ulille.iut.pizzaland.dao.*; +import fr.ulille.iut.pizzaland.dto.*; +import fr.ulille.iut.pizzaland.beans.*; +import fr.ulille.iut.pizzaland.resources.*; + +import org.glassfish.jersey.test.JerseyTest; +import org.glassfish.jersey.test.TestProperties; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import javax.ws.rs.client.Entity; +import javax.ws.rs.core.GenericType; +import javax.ws.rs.core.Application; +import javax.ws.rs.core.Response; + +import static org.junit.Assert.assertEquals; + +import java.util.List; +import java.util.logging.Logger; + +/* + * JerseyTest facilite l'écriture des tests en donnant accès aux + * méthodes de l'interface javax.ws.rs.client.Client. + * la méthode configure() permet de démarrer la ressource à tester + */ +public class PizzaResourceTest extends JerseyTest { + private static final Logger LOGGER = Logger.getLogger(PizzaResourceTest.class.getName()); + private PizzaDao dao; + + @Override + protected Application configure() { + BDDFactory.setJdbiForTests(); + return new ApiV1(); + } + + // Les méthodes setEnvUp() et tearEnvDown() serviront à terme à initialiser la base de données + // et les DAO + + // https://stackoverflow.com/questions/25906976/jerseytest-and-junit-throws-nullpointerexception + @Before + public void setEnvUp() { + dao = BDDFactory.buildDao(PizzaDao.class); + dao.createPizzaAndAssociationTable(); + } + + @After + public void tearEnvDown() throws Exception { + dao.deletePizzaAndAssociationTable(); + } + + @Test + public void testGetEmptyList() { + // La méthode target() permet de préparer une requête sur une URI. + // La classe Response permet de traiter la réponse HTTP reçue. + Response response = target("/pizzas").request().get(); + + // On vérifie le code de la réponse (200 = OK) + assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); + + // On vérifie la valeur retournée (liste vide) + // L'entité (readEntity() correspond au corps de la réponse HTTP. + // La classe javax.ws.rs.core.GenericType<T> permet de définir le type + // de la réponse lue quand on a un type complexe (typiquement une liste). + List<PizzaDto> pizza; + pizza = response.readEntity(new GenericType<List<PizzaDto>>(){}); + + // On vérifie que la liste est bien vide + assertEquals(0, pizza.size()); + } + + @Test + public void testGetExistingPizza() { + + Pizza pizza = new Pizza(); + pizza.setName("Chorizo"); + + long id = dao.insert(pizza.getName()); + pizza.setId(id); + + Response response = target("/pizzas/" + id).request().get(); + + assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); + + Pizza result = Pizza.fromDto(response.readEntity(PizzaDto.class)); + assertEquals(pizza, result); + } + + @Test + public void testGetNotExistingPizza() { + Response response = target("/pizzas/125").request().get(); + assertEquals(Response.Status.NOT_FOUND.getStatusCode(),response.getStatus()); + } + + @Test + public void testCreatePizza() { + PizzaCreateDto PizzaCreateDto = new PizzaCreateDto(); + PizzaCreateDto.setName("Chorizo"); + + Response response = target("/pizzas") + .request() + .post(Entity.json(PizzaCreateDto)); + + // On vérifie le code de status à 201 + assertEquals(Response.Status.CREATED.getStatusCode(), response.getStatus()); + + PizzaDto returnedEntity = response.readEntity(PizzaDto.class); + + // On vérifie que le champ d'entête Location correspond à + // l'URI de la nouvelle entité + assertEquals(target("/pizzas/" + + returnedEntity.getId()).getUri(), response.getLocation()); + + // On vérifie que le nom correspond + assertEquals(returnedEntity.getName(), PizzaCreateDto.getName()); + } + + @Test + public void testCreateSamePizza() { + PizzaCreateDto pizzaCreateDto = new PizzaCreateDto(); + pizzaCreateDto.setName("Chorizo"); + dao.insert(pizzaCreateDto.getName()); + + Response response = target("/pizzas") + .request() + .post(Entity.json(pizzaCreateDto)); + + assertEquals(Response.Status.CONFLICT.getStatusCode(), response.getStatus()); + } + + @Test + public void testCreatePizzaWithoutName() { + PizzaCreateDto pizzaCreateDto = new PizzaCreateDto(); + + Response response = target("/pizzas") + .request() + .post(Entity.json(pizzaCreateDto)); + + assertEquals(Response.Status.NOT_ACCEPTABLE.getStatusCode(), response.getStatus()); + } + //////////////////////////// + @Test + public void testDeleteExistingPizza() { + Pizza pizza = new Pizza(); + pizza.setName("Chorizo"); + long id = dao.insert(pizza.getName()); + pizza.setId(id); + + Response response = target("/pizzas/" + id).request().delete(); + + assertEquals(Response.Status.ACCEPTED.getStatusCode(), response.getStatus()); + + Pizza result = dao.findById(id); + assertEquals(result, null); + } + + @Test + public void testDeleteNotExistingPizza() { + Response response = target("/pizzas/125").request().delete(); + assertEquals(Response.Status.NOT_FOUND.getStatusCode(),response.getStatus()); + } + + @Test + public void testGetPizzaName() { + Pizza pizza = new Pizza(); + pizza.setName("mozzarella"); + long id = dao.insert(pizza.getName()); + + Response response = target("pizzas/" + id + "/name").request().get(); + + assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); + + assertEquals("mozzarella", response.readEntity(String.class)); + } + + @Test + public void testGetNotExistingPizzaName() { + Response response = target("pizzas/125/name").request().get(); + + assertEquals(Response.Status.NOT_FOUND.getStatusCode(), response.getStatus()); + } + + @Test + public void testGetPizzaIngredients(){ + + } + } -- GitLab