From f492e60c95442313a54f64127277d48626c68a42 Mon Sep 17 00:00:00 2001 From: Aitor Date: Sun, 4 Apr 2021 20:27:43 +0200 Subject: [PATCH] Ejercicio previo para el 04/04 --- db/mysql-with-inserts.sql | 13 + db/mysql.sql | 16 +- run.bat | 2 + .../uvigo/esei/daa/DAAExampleApplication.java | 5 +- .../java/es/uvigo/esei/daa/dao/PeopleDAO.java | 26 ++ .../java/es/uvigo/esei/daa/dao/PetsDAO.java | 165 ++++++++++ .../java/es/uvigo/esei/daa/entities/Pet.java | 73 +++++ .../uvigo/esei/daa/rest/PeopleResource.java | 24 ++ .../es/uvigo/esei/daa/rest/PetsResource.java | 164 ++++++++++ src/main/webapp/WEB-INF/web.xml | 15 + src/main/webapp/js/dao/people.js | 7 + src/main/webapp/js/dao/pets.js | 51 +++ src/main/webapp/js/view/people.js | 10 +- src/main/webapp/js/view/pets.js | 222 +++++++++++++ src/main/webapp/main.html | 49 ++- .../uvigo/esei/daa/dataset/PetsDataset.java | 70 ++++ .../uvigo/esei/daa/entities/PetsUnitTest.java | 82 +++++ .../uvigo/esei/daa/matchers/IsEqualToPet.java | 56 ++++ .../uvigo/esei/daa/rest/PetsResourceTest.java | 301 ++++++++++++++++++ .../esei/daa/suites/IntegrationTestSuite.java | 4 +- .../uvigo/esei/daa/suites/UnitTestSuite.java | 4 +- src/test/resources/datasets/dataset-add.xml | 8 + .../resources/datasets/dataset-delete.xml | 8 + .../resources/datasets/dataset-modify.xml | 7 + .../resources/datasets/dataset-pets-add.xml | 27 ++ .../datasets/dataset-pets-delete.xml | 25 ++ .../datasets/dataset-pets-modify.xml | 26 ++ src/test/resources/datasets/dataset.dtd | 8 +- src/test/resources/datasets/dataset.xml | 8 + src/test/resources/db/hsqldb-drop.sql | 1 + src/test/resources/db/hsqldb.sql | 8 +- 31 files changed, 1467 insertions(+), 18 deletions(-) create mode 100644 run.bat create mode 100644 src/main/java/es/uvigo/esei/daa/dao/PetsDAO.java create mode 100644 src/main/java/es/uvigo/esei/daa/entities/Pet.java create mode 100644 src/main/java/es/uvigo/esei/daa/rest/PetsResource.java create mode 100644 src/main/webapp/js/dao/pets.js create mode 100644 src/main/webapp/js/view/pets.js create mode 100644 src/test/java/es/uvigo/esei/daa/dataset/PetsDataset.java create mode 100644 src/test/java/es/uvigo/esei/daa/entities/PetsUnitTest.java create mode 100644 src/test/java/es/uvigo/esei/daa/matchers/IsEqualToPet.java create mode 100644 src/test/java/es/uvigo/esei/daa/rest/PetsResourceTest.java create mode 100644 src/test/resources/datasets/dataset-pets-add.xml create mode 100644 src/test/resources/datasets/dataset-pets-delete.xml create mode 100644 src/test/resources/datasets/dataset-pets-modify.xml diff --git a/db/mysql-with-inserts.sql b/db/mysql-with-inserts.sql index d7daea4..090ee28 100644 --- a/db/mysql-with-inserts.sql +++ b/db/mysql-with-inserts.sql @@ -15,6 +15,14 @@ CREATE TABLE `daaexample`.`users` ( PRIMARY KEY (`login`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; +CREATE TABLE `daaexample`.`pets` ( + `id` int NOT NULL AUTO_INCREMENT, + `pet_name` varchar(20) NOT NULL, + `owner_id` int NOT NULL, + PRIMARY KEY (`id`), + FOREIGN KEY (`id`) REFERENCES `people`(`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + CREATE USER IF NOT EXISTS 'daa'@'localhost' IDENTIFIED WITH mysql_native_password BY 'daa'; GRANT ALL ON `daaexample`.* TO 'daa'@'localhost'; @@ -26,6 +34,11 @@ INSERT INTO `daaexample`.`people` (`id`,`name`,`surname`) VALUES (0,'Ana','Marí INSERT INTO `daaexample`.`people` (`id`,`name`,`surname`) VALUES (0,'María','Nuevo'); INSERT INTO `daaexample`.`people` (`id`,`name`,`surname`) VALUES (0,'Alba','Fernández'); INSERT INTO `daaexample`.`people` (`id`,`name`,`surname`) VALUES (0,'Asunción','Jiménez'); +INSERT INTO `daaexample`.`pets` (`id`,`pet_name`,`owner_id`) VALUES (0,'Tofe',1); +INSERT INTO `daaexample`.`pets` (`id`,`pet_name`,`owner_id`) VALUES (0,'Pipo',4); +INSERT INTO `daaexample`.`pets` (`id`,`pet_name`,`owner_id`) VALUES (0,'Niki',2); +INSERT INTO `daaexample`.`pets` (`id`,`pet_name`,`owner_id`) VALUES (0,'Tim',3); +INSERT INTO `daaexample`.`pets` (`id`,`pet_name`,`owner_id`) VALUES (0,'Yeke',6); -- The password for each user is its login suffixed with "pass". For example, user "admin" has the password "adminpass". INSERT INTO `daaexample`.`users` (`login`,`password`,`role`) diff --git a/db/mysql.sql b/db/mysql.sql index 116ae71..bf8a8e0 100644 --- a/db/mysql.sql +++ b/db/mysql.sql @@ -15,5 +15,19 @@ CREATE TABLE `daaexample`.`users` ( PRIMARY KEY (`login`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -CREATE USER IF NOT EXISTS 'daa'@'localhost' IDENTIFIED WITH mysql_native_password BY 'daa'; +CREATE TABLE `daaexample`.`pets` ( + `id` int NOT NULL AUTO_INCREMENT, + `pet_name` varchar(20) NOT NULL, + `owner_id` int NOT NULL, + PRIMARY KEY (`id`), + FOREIGN KEY (owner_id) REFERENCES `daaexample`.`people`(id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE USER IF NOT EXISTS 'daa'@'localhost'; +UPDATE mysql.user SET plugin = 'mysql_native_password' WHERE user = 'root'; GRANT ALL ON `daaexample`.* TO 'daa'@'localhost'; + +INSERT INTO `daaexample`.`users` (`login`,`password`,`role`) +VALUES ('admin', 'admin','ADMIN'); +INSERT INTO `daaexample`.`users` (`login`,`password`,`role`) +VALUES ('user', 'user','ADMIN'); diff --git a/run.bat b/run.bat new file mode 100644 index 0000000..aea4028 --- /dev/null +++ b/run.bat @@ -0,0 +1,2 @@ +cmd /k mysql -u root -p < db/mysql-with-inserts.sql +cmd /k mvn -Prun -DskipTests=true package cargo:start fizzed-watcher:run diff --git a/src/main/java/es/uvigo/esei/daa/DAAExampleApplication.java b/src/main/java/es/uvigo/esei/daa/DAAExampleApplication.java index 2a67f22..438c01e 100644 --- a/src/main/java/es/uvigo/esei/daa/DAAExampleApplication.java +++ b/src/main/java/es/uvigo/esei/daa/DAAExampleApplication.java @@ -11,6 +11,8 @@ import javax.ws.rs.ApplicationPath; import javax.ws.rs.core.Application; import es.uvigo.esei.daa.rest.PeopleResource; +import es.uvigo.esei.daa.rest.PetsResource; +import es.uvigo.esei.daa.rest.UsersResource; import es.uvigo.esei.daa.rest.UsersResource; /** @@ -26,7 +28,8 @@ public class DAAExampleApplication extends Application { public Set> getClasses() { return Stream.of( PeopleResource.class, - UsersResource.class + UsersResource.class, + PetsResource.class ).collect(toSet()); } diff --git a/src/main/java/es/uvigo/esei/daa/dao/PeopleDAO.java b/src/main/java/es/uvigo/esei/daa/dao/PeopleDAO.java index 1d99edb..b12803e 100644 --- a/src/main/java/es/uvigo/esei/daa/dao/PeopleDAO.java +++ b/src/main/java/es/uvigo/esei/daa/dao/PeopleDAO.java @@ -52,6 +52,32 @@ public class PeopleDAO extends DAO { } } + public String getFullName(int id) + throws DAOException, IllegalArgumentException { + StringBuilder toret = new StringBuilder(); + try (final Connection conn = this.getConnection()) { + final String query = "SELECT name, surname FROM people WHERE id=?"; + + try (final PreparedStatement statement = conn.prepareStatement(query)) { + statement.setInt(1, id); + + try (final ResultSet result = statement.executeQuery()) { + if (result.next()) { + toret.append(result.getString("name")).append(" ").append(result.getString("surname")); + return toret.toString(); + } else { + throw new IllegalArgumentException("Invalid id"); + } + } + } + } catch (SQLException e) { + LOG.log(Level.SEVERE, "Error getting a person", e); + throw new DAOException(e); + } + } + + + /** * Returns a list with all the people persisted in the system. * diff --git a/src/main/java/es/uvigo/esei/daa/dao/PetsDAO.java b/src/main/java/es/uvigo/esei/daa/dao/PetsDAO.java new file mode 100644 index 0000000..52aa994 --- /dev/null +++ b/src/main/java/es/uvigo/esei/daa/dao/PetsDAO.java @@ -0,0 +1,165 @@ +package es.uvigo.esei.daa.dao; +import java.sql.Connection; +import es.uvigo.esei.daa.dao.PeopleDAO; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.LinkedList; +import java.util.List; +import java.util.logging.Level; + +import es.uvigo.esei.daa.entities.Person; +import es.uvigo.esei.daa.entities.Pet; + +public class PetsDAO extends DAO{ + private final static java.util.logging.Logger LOG = java.util.logging.Logger.getLogger(PetsDAO.class.getName()); + PeopleDAO pdao = new PeopleDAO(); + + + //retorna una mascota a partir de un id + public Pet get(int id) + throws DAOException, IllegalArgumentException { + try (final Connection conn = this.getConnection()) { + final String query = "SELECT * FROM pets WHERE id=?"; + + try (final PreparedStatement statement = conn.prepareStatement(query)) { + statement.setInt(1, id); + + try (final ResultSet result = statement.executeQuery()) { + if (result.next()) { + return rowToEntity(result); + } else { + throw new IllegalArgumentException("Invalid id"); + } + } + } + } catch (SQLException e) { + LOG.log(Level.SEVERE, "Error getting a pet", e); + throw new DAOException(e); + } + } + + //devuelve una lista con todas las mascotas registradas + public List list() throws DAOException { + try (final Connection conn = this.getConnection()) { + final String query = "SELECT * FROM pets"; + + try (final PreparedStatement statement = conn.prepareStatement(query)) { + try (final ResultSet result = statement.executeQuery()) { + final List pets = new LinkedList<>(); + + while (result.next()) { + pets.add(rowToEntity(result)); + } + + return pets; + } + } + } catch (SQLException e) { + LOG.log(Level.SEVERE, "Error listing pets", e); + throw new DAOException(e); + } + } + + //registra una mascota + public Pet add(String pet_name, int owner_id) + throws DAOException, IllegalArgumentException { + boolean esPersona = false; + PeopleDAO peopleDao = new PeopleDAO(); + List listaPeople = peopleDao.list(); + for(Person p : listaPeople) { + //LOG.log(Level.INFO, ""+p.getId()+" "+owner_id); + if(p.getId() == owner_id || owner_id == 0) { + esPersona = true; + } + } + if(!esPersona) { + throw new IllegalArgumentException("owner_id doesn´t exist"); + } + if (pet_name == null || owner_id < 0) { + throw new IllegalArgumentException("pet name and owner_id can't be null"); + } + + try (Connection conn = this.getConnection()) { + LOG.log(Level.INFO, "ID: "+owner_id); + final String query = "INSERT INTO pets VALUES(null, ?, ?)"; + try (PreparedStatement statement = conn.prepareStatement(query, Statement.RETURN_GENERATED_KEYS)) { + statement.setString(1, pet_name); + statement.setInt(2, owner_id); + if (statement.executeUpdate() == 1) { + try (ResultSet resultKeys = statement.getGeneratedKeys()) { + if (resultKeys.next()) { + Pet p = new Pet(resultKeys.getInt(1), pet_name, owner_id); + //LOG.log(Level.INFO, p.toString()); + return p; + } else { + LOG.log(Level.SEVERE, "Error retrieving inserted id"); + throw new SQLException("Error retrieving inserted id"); + } + } + } else { + LOG.log(Level.SEVERE, "Error inserting value"); + throw new SQLException("Error inserting value"); + } + } + } catch (SQLException e) { + LOG.log(Level.SEVERE, "Error adding a pet", e); + throw new DAOException(e); + } + } + + //modifica los datos de una persona + public void modify(Pet pet) + throws DAOException, IllegalArgumentException { + if (pet == null) { + throw new IllegalArgumentException("pet can't be null"); + } + + try (Connection conn = this.getConnection()) { + final String query = "UPDATE pets SET pet_name=?, owner_id=? WHERE id=?"; + + try (PreparedStatement statement = conn.prepareStatement(query)) { + statement.setString(1, pet.getpet_name()); + statement.setInt(2, pet.getowner_id()); + statement.setInt(3, pet.getId()); + + if (statement.executeUpdate() != 1) { + throw new IllegalArgumentException("name and owner can't be null"); + } + } + } catch (SQLException e) { + LOG.log(Level.SEVERE, "Error modifying a pet", e); + throw new DAOException(); + } + } + + //elimina una mascota a partir de su id + public void delete(int id) + throws DAOException, IllegalArgumentException { + try (final Connection conn = this.getConnection()) { + final String query = "DELETE FROM pets WHERE id=?"; + + try (final PreparedStatement statement = conn.prepareStatement(query)) { + statement.setInt(1, id); + + if (statement.executeUpdate() != 1) { + throw new IllegalArgumentException("Invalid id"); + } + } + } catch (SQLException e) { + LOG.log(Level.SEVERE, "Error deleting a pet", e); + throw new DAOException(e); + } + } + + private Pet rowToEntity(ResultSet row) throws SQLException { + return new Pet( + row.getInt("id"), + row.getString("pet_name"), + row.getInt("owner_id") + ); + } + + +} diff --git a/src/main/java/es/uvigo/esei/daa/entities/Pet.java b/src/main/java/es/uvigo/esei/daa/entities/Pet.java new file mode 100644 index 0000000..a252b82 --- /dev/null +++ b/src/main/java/es/uvigo/esei/daa/entities/Pet.java @@ -0,0 +1,73 @@ +package es.uvigo.esei.daa.entities; + +import static java.util.Objects.requireNonNull; + +public class Pet { + private int id; + private String pet_name; + private int owner_id; + + public Pet() {} //Constructor para la conversion JSON + + public Pet(int id, String pet_name, int owner_id){ + this.id = id; + this.setPetName(pet_name); + this.setOwnerId(owner_id); + } + + public int getId() { + return this.id; + } + + public String getpet_name(){ + return this.pet_name; + } + + public int getowner_id() { + return this.owner_id; + } + + public void setPetName(String pet_name) { + this.pet_name = requireNonNull(pet_name, "Pet name can't be null"); + } + + public void setOwnerId(int owner_id) { + this.owner_id = requireNonNull(owner_id, "Owner id can´t be null"); + } + + public void setPetId(int id) { + this.id = id; + } + @Override + public String toString() { + StringBuilder toret = new StringBuilder(); + toret.append("Id: ").append(getId()).append("\n"); + toret.append("Nombre: ").append(getpet_name()).append("\n"); + toret.append("Owner id: ").append(getowner_id()).append("\n"); + return toret.toString(); + + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + id; + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (!(obj instanceof Pet)) + return false; + Pet other = (Pet) obj; + if (id != other.id) + return false; + return true; + } + +} diff --git a/src/main/java/es/uvigo/esei/daa/rest/PeopleResource.java b/src/main/java/es/uvigo/esei/daa/rest/PeopleResource.java index 09b8834..b077122 100644 --- a/src/main/java/es/uvigo/esei/daa/rest/PeopleResource.java +++ b/src/main/java/es/uvigo/esei/daa/rest/PeopleResource.java @@ -75,6 +75,30 @@ public class PeopleResource { .build(); } } + + @GET + @Path("/name/{id}") + public Response getFullName( + @PathParam("id") int id + ) { + try { + final String name = this.dao.getFullName(id); + + return Response.ok(name).build(); + } catch (IllegalArgumentException iae) { + LOG.log(Level.FINE, "Invalid person id in get full name method", iae); + + return Response.status(Response.Status.BAD_REQUEST) + .entity(iae.getMessage()) + .build(); + } catch (DAOException e) { + LOG.log(Level.SEVERE, "Error getting a person", e); + + return Response.serverError() + .entity(e.getMessage()) + .build(); + } + } /** * Returns the complete list of people stored in the system. diff --git a/src/main/java/es/uvigo/esei/daa/rest/PetsResource.java b/src/main/java/es/uvigo/esei/daa/rest/PetsResource.java new file mode 100644 index 0000000..4f26cd2 --- /dev/null +++ b/src/main/java/es/uvigo/esei/daa/rest/PetsResource.java @@ -0,0 +1,164 @@ +package es.uvigo.esei.daa.rest; + +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.DELETE; +import javax.ws.rs.FormParam; + +import es.uvigo.esei.daa.dao.DAOException; +import es.uvigo.esei.daa.dao.PetsDAO; +import es.uvigo.esei.daa.entities.Pet; + +//necesario registrar cada resource en DAAExampleApplication +@Path("/pets") +@Produces(MediaType.APPLICATION_JSON) +public class PetsResource { + private final static Logger LOG = Logger.getLogger(PetsResource.class.getName()); + + private final PetsDAO dao; + + public PetsResource() { + this(new PetsDAO()); + } + + PetsResource(PetsDAO dao){ + this.dao = dao; + } + + @GET + @Path("/{id}") + public Response get( + @PathParam("id") int id + ) { + try { + final Pet pet = this.dao.get(id); + return Response.ok(pet).build(); + }catch(IllegalArgumentException ie) { + LOG.log(Level.FINE, "Invalid pet id in get method", ie); + return Response.status(Response.Status.BAD_REQUEST) + .entity(ie.getMessage()) + .build(); + } catch (DAOException e) { + return Response.serverError() + .entity(e.getMessage()) + .build(); + } + } + + @GET + public Response list() { + try { + return Response.ok(this.dao.list()).build(); + } catch (DAOException e) { + LOG.log(Level.SEVERE, "Error listing pets", e); + return Response.serverError().entity(e.getMessage()).build(); + } + } + + @POST + public Response add( + @FormParam("pet_name") String name, + @FormParam("owner_id") int owner_id + ) { + if(name == null || owner_id <= 0) { + return Response.status(Response.Status.BAD_REQUEST).entity("Mal formada").build(); + } + else { + try { + //LOG.log(Level.INFO, "ID REST: "+owner_id); + final Pet newPet = this.dao.add(name, owner_id); + return Response.ok(newPet).build(); + } catch (IllegalArgumentException iae) { + LOG.log(Level.FINE, "Invalid pet id in add", iae); + return Response.status(Response.Status.BAD_REQUEST) + .entity(iae.getMessage()) + .build(); + } catch (DAOException e) { + LOG.log(Level.SEVERE, "Error adding a pet", e); + + return Response.serverError() + .entity(e.getMessage()) + .build(); + } + } + } + + @PUT + @Path("/{id}") + public Response modify( + @PathParam("id") int id, + @FormParam("pet_name") String name, + @FormParam("owner_id") int owner + ) { + if(id < 0 || name == null || owner <= 0) { + return Response.status(Response.Status.BAD_REQUEST).entity("Mal formada").build(); + } + else { + try { + final Pet modifiedPet = new Pet(id, name, owner); + //LOG.log(Level.INFO,modifiedPet.toString()); + this.dao.modify(modifiedPet); + + return Response.ok(modifiedPet).build(); + } catch (NullPointerException npe) { + final String message = String.format("Invalid data for pet (name: %s, owner: %i)", name, owner); + + LOG.log(Level.FINE, message); + + return Response.status(Response.Status.BAD_REQUEST) + .entity(message) + .build(); + } catch (IllegalArgumentException iae) { + LOG.log(Level.FINE, "Invalid pet id in modify method", iae); + + return Response.status(Response.Status.BAD_REQUEST) + .entity(iae.getMessage()) + .build(); + } catch (DAOException e) { + LOG.log(Level.SEVERE, "Error modifying a pet", e); + + return Response.serverError() + .entity(e.getMessage()) + .build(); + } + } + } + + @DELETE + @Path("/{id}") + public Response delete( + @PathParam("id") int id + ) { + if(id <= 0) { + return Response.status(Response.Status.BAD_REQUEST).entity("Mal formada").build(); + } + try { + this.dao.delete(id); + + return Response.ok(id).build(); + } catch (IllegalArgumentException iae) { + LOG.log(Level.FINE, "Invalid pet id in delete method", iae); + + return Response.status(Response.Status.BAD_REQUEST) + .entity(iae.getMessage()) + .build(); + } catch (DAOException e) { + LOG.log(Level.SEVERE, "Error deleting a pet", e); + + return Response.serverError() + .entity(e.getMessage()) + .build(); + } + } + + +} diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml index f748eff..5a28796 100644 --- a/src/main/webapp/WEB-INF/web.xml +++ b/src/main/webapp/WEB-INF/web.xml @@ -59,6 +59,21 @@ ADMIN + + + + Pet Admin Area + /rest/pets/* + GET + PUT + DELETE + POST + + + ADMIN + + + diff --git a/src/main/webapp/js/dao/people.js b/src/main/webapp/js/dao/people.js index 29618ee..6e2ebd7 100644 --- a/src/main/webapp/js/dao/people.js +++ b/src/main/webapp/js/dao/people.js @@ -45,6 +45,13 @@ var PeopleDAO = (function() { type : 'DELETE', }, done, fail, always); }; + + this.getFullName = function(id, done, fail, always) { + requestByAjax({ + url : resourcePath + "name/" + id, + type : 'GET' + }, done, fail, always); + }; } return PeopleDAO; diff --git a/src/main/webapp/js/dao/pets.js b/src/main/webapp/js/dao/pets.js new file mode 100644 index 0000000..04fbb8c --- /dev/null +++ b/src/main/webapp/js/dao/pets.js @@ -0,0 +1,51 @@ +var PetsDAO = (function() { + var resourcePath = "rest/pets/"; + var requestByAjax = function(data, done, fail, always) { + done = typeof done !== 'undefined' ? done : function() {}; + fail = typeof fail !== 'undefined' ? fail : function() {}; + always = typeof always !== 'undefined' ? always : function() {}; + + let authToken = localStorage.getItem('authorization-token'); + if (authToken !== null) { + data.beforeSend = function(xhr) { + xhr.setRequestHeader('Authorization', 'Basic ' + authToken); + }; + } + + $.ajax(data).done(done).fail(fail).always(always); + }; + + function PetsDAO() { + this.listPets = function(done, fail, always) { + requestByAjax({ + url : resourcePath, + type : 'GET' + }, done, fail, always); + }; + + this.addPet = function(pet, done, fail, always) { + requestByAjax({ + url : resourcePath, + type : 'POST', + data : pet + }, done, fail, always); + }; + + this.modifyPet = function(pet, done, fail, always) { + requestByAjax({ + url : resourcePath + pet.id, + type : 'PUT', + data : pet + }, done, fail, always); + }; + + this.deletePet = function(id, done, fail, always) { + requestByAjax({ + url : resourcePath + id, + type : 'DELETE', + }, done, fail, always); + }; + } + + return PetsDAO; +})(); \ No newline at end of file diff --git a/src/main/webapp/js/view/people.js b/src/main/webapp/js/view/people.js index 802d6b2..6630ebe 100644 --- a/src/main/webapp/js/view/people.js +++ b/src/main/webapp/js/view/people.js @@ -130,8 +130,9 @@ var PeopleView = (function() { '\ \ \ - \ - \ + \ + \ + \ \ \ \ @@ -163,8 +164,9 @@ var PeopleView = (function() { var createPersonRow = function(person) { return '\ - \ - \ + \ + \ + \ \ + \ + \ + \ + '; + }; + + var showErrorMessage = function(jqxhr, textStatus, error) { + alert(textStatus + ": " + error); + }; + + var addRowListeners = function(pet) { + $('#pet-' + pet.id + ' a.edit').click(function() { + self.editPet(pet.id); + }); + + $('#pet-' + pet.id + ' a.delete').click(function() { + self.deletePet(pet.id); + }); + }; + + var appendToTable = function(pet) { + $(listQuery + ' > tbody:last') + .append(createPetRow(pet)); + addRowListeners(pet); + }; + + return PetsView; +})(); diff --git a/src/main/webapp/main.html b/src/main/webapp/main.html index c2e28f1..5c511f5 100644 --- a/src/main/webapp/main.html +++ b/src/main/webapp/main.html @@ -15,35 +15,68 @@ DAA Example - + +
-
+ +
+

Personas

+ +
+

Mascotas

+
+
+ + diff --git a/src/test/java/es/uvigo/esei/daa/dataset/PetsDataset.java b/src/test/java/es/uvigo/esei/daa/dataset/PetsDataset.java new file mode 100644 index 0000000..0d2914b --- /dev/null +++ b/src/test/java/es/uvigo/esei/daa/dataset/PetsDataset.java @@ -0,0 +1,70 @@ +package es.uvigo.esei.daa.dataset; + +import static java.util.Arrays.binarySearch; +import static java.util.Arrays.stream; + +import java.util.Arrays; +import java.util.function.Predicate; + +import es.uvigo.esei.daa.entities.Pet; + +public final class PetsDataset { + private PetsDataset() {} + + public static Pet[] pets() { + return new Pet[] { + new Pet(1, "Tofe", 2), + new Pet(2, "Niki", 3), + new Pet(3, "Tobi", 1), + new Pet(4, "Tara", 2), + new Pet(5, "Tim", 5), + new Pet(6, "Trosky", 6), + }; + } + + public static Pet[] petsWithout(int ... ids) { + Arrays.sort(ids); + + final Predicate hasValidId = pet -> + binarySearch(ids, pet.getId()) < 0; + + return stream(pets()) + .filter(hasValidId) + .toArray(Pet[]::new); + } + + public static Pet pet(int id) { + return stream(pets()) + .filter(pet -> pet.getId() == id) + .findAny() + .orElseThrow(IllegalArgumentException::new); + } + + public static Integer existentId() { + return 5; + } + + public static Integer nonExistentId() { + return 1234; + } + + public static Pet existentPet() { + return pet(existentId()); + } + + public static Pet nonExistentPet() { + return new Pet(nonExistentId(), "Baddy", 4); + } + + public static String newPetName() { + return "Miku"; + } + + public static Integer newOwnerId() { + return 4; + } + + public static Pet newPet() { + return new Pet(pets().length + 1, newPetName(), newOwnerId()); + } +} \ No newline at end of file diff --git a/src/test/java/es/uvigo/esei/daa/entities/PetsUnitTest.java b/src/test/java/es/uvigo/esei/daa/entities/PetsUnitTest.java new file mode 100644 index 0000000..eb64264 --- /dev/null +++ b/src/test/java/es/uvigo/esei/daa/entities/PetsUnitTest.java @@ -0,0 +1,82 @@ +package es.uvigo.esei.daa.entities; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import nl.jqno.equalsverifier.EqualsVerifier; +import nl.jqno.equalsverifier.Warning; + +public class PetsUnitTest { + @Test + public void testPetIntStringInt() { + final int id = 1; + final String name = "Laia"; + final int ownerId = 4; + + final Pet pet = new Pet(id, name, ownerId); + + assertThat(pet.getId(), is(equalTo(id))); + assertThat(pet.getpet_name(), is(equalTo(name))); + assertThat(pet.getowner_id(), is(equalTo(ownerId))); + } + + @Test(expected = NullPointerException.class) + public void testPetIntStringIntNullName() { + new Pet(1, null, 2); + } + + @Test + public void testSetName() { + final int id = 1; + final int ownerId = 2; + + final Pet pet = new Pet(id, "Laia", 2); + pet.setPetName("Beethoven"); + + assertThat(pet.getId(), is(equalTo(id))); + assertThat(pet.getpet_name(), is(equalTo("Beethoven"))); + assertThat(pet.getowner_id(), is(equalTo(ownerId))); + } + + @Test(expected = NullPointerException.class) + public void testSetNullName() { + final Pet pet= new Pet(1, "Beethoven", 2); + + pet.setPetName(null); + } + + @Test + public void testSetOwnerId() { + final int id = 1; + final String name = "Beethoven"; + + final Pet pet= new Pet(id, name, 2); + pet.setOwnerId(6); + + assertThat(pet.getId(), is(equalTo(id))); + assertThat(pet.getpet_name(), is(equalTo(name))); + assertThat(pet.getowner_id(), is(equalTo(6))); + } + + @Test + public void testEqualsObject() { + final Pet petA = new Pet(1, "Name A", 2); + final Pet petB = new Pet(1, "Name B", 2); + + assertTrue(petB.equals(petA)); + } + +//Error: cannot define class using reflection, downgradear java + @Test + public void testEqualsHashcode() { + EqualsVerifier.forClass(Pet.class) + .withIgnoredFields("pet_name", "owner_id") + .suppress(Warning.STRICT_INHERITANCE) + .suppress(Warning.NONFINAL_FIELDS) + .verify(); + } +} diff --git a/src/test/java/es/uvigo/esei/daa/matchers/IsEqualToPet.java b/src/test/java/es/uvigo/esei/daa/matchers/IsEqualToPet.java new file mode 100644 index 0000000..dd845f0 --- /dev/null +++ b/src/test/java/es/uvigo/esei/daa/matchers/IsEqualToPet.java @@ -0,0 +1,56 @@ +package es.uvigo.esei.daa.matchers; + +import org.hamcrest.Factory; +import org.hamcrest.Matcher; + +import es.uvigo.esei.daa.entities.Pet; + +public class IsEqualToPet extends IsEqualToEntity { + public IsEqualToPet(Pet entity) { + super(entity); + } + + @Override + protected boolean matchesSafely(Pet actual) { + this.clearDescribeTo(); + + if (actual == null) { + this.addTemplatedDescription("actual", expected.toString()); + return false; + } else { + return checkAttribute("id", Pet::getId, actual) + && checkAttribute("pet_name", Pet::getpet_name, actual) + && checkAttribute("owner_id", Pet::getowner_id, actual); + } + } + + /** + * Factory method that creates a new {@link IsEqualToEntity} matcher with + * the provided {@link Pet} as the expected value. + * + * @param pet the expected pet + * @return a new {@link IsEqualToEntity} matcher with the provided + * {@link Pet} as the expected value. + */ + @Factory + public static IsEqualToPet equalsToPet(Pet pet) { + return new IsEqualToPet(pet); + } + + /** + * Factory method that returns a new {@link Matcher} that includes several + * {@link IsEqualToPet} matchers, each one using an {@link Pet} of the + * provided ones as the expected value. + * + * @param pets the pets to be used as the expected values. + * @return a new {@link Matcher} that includes several + * {@link IsEqualToPet} matchers, each one using an {@link Pet} of the + * provided ones as the expected value. + * @see IsEqualToEntity#containsEntityInAnyOrder(java.util.function.Function, Object...) + */ + @Factory + public static Matcher> containsPetsInAnyOrder(Pet ... pets) { + return containsEntityInAnyOrder(IsEqualToPet::equalsToPet, pets); + } +} + diff --git a/src/test/java/es/uvigo/esei/daa/rest/PetsResourceTest.java b/src/test/java/es/uvigo/esei/daa/rest/PetsResourceTest.java new file mode 100644 index 0000000..cd6df9d --- /dev/null +++ b/src/test/java/es/uvigo/esei/daa/rest/PetsResourceTest.java @@ -0,0 +1,301 @@ +package es.uvigo.esei.daa.rest; + +import static es.uvigo.esei.daa.dataset.PeopleDataset.existentId; +import static es.uvigo.esei.daa.dataset.PeopleDataset.existentPerson; +import static es.uvigo.esei.daa.dataset.PeopleDataset.newName; +import static es.uvigo.esei.daa.dataset.PeopleDataset.newPerson; +import static es.uvigo.esei.daa.dataset.PeopleDataset.newSurname; +import static es.uvigo.esei.daa.dataset.PeopleDataset.nonExistentId; +import static es.uvigo.esei.daa.dataset.PeopleDataset.people; +import static es.uvigo.esei.daa.dataset.PetsDataset.*; +import static es.uvigo.esei.daa.dataset.UsersDataset.adminLogin; +import static es.uvigo.esei.daa.dataset.UsersDataset.normalLogin; +import static es.uvigo.esei.daa.dataset.UsersDataset.userToken; +import static es.uvigo.esei.daa.matchers.HasHttpStatus.hasBadRequestStatus; +import static es.uvigo.esei.daa.matchers.HasHttpStatus.hasOkStatus; +import static es.uvigo.esei.daa.matchers.HasHttpStatus.hasUnauthorized; +import static es.uvigo.esei.daa.matchers.IsEqualToPerson.containsPeopleInAnyOrder; +import static es.uvigo.esei.daa.matchers.HasHttpStatus.hasForbidden; +import static es.uvigo.esei.daa.matchers.IsEqualToPerson.equalsToPerson; +import static es.uvigo.esei.daa.matchers.IsEqualToPet.*; +import static javax.ws.rs.client.Entity.entity; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertEquals; + +import java.io.IOException; +import java.util.Iterator; +import java.util.List; +import java.util.logging.Logger; + +import javax.sql.DataSource; +import javax.ws.rs.client.Entity; +import javax.ws.rs.core.Application; +import javax.ws.rs.core.Form; +import javax.ws.rs.core.GenericType; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.glassfish.jersey.client.ClientConfig; +import org.glassfish.jersey.test.JerseyTest; +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.annotation.DirtiesContext.MethodMode; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestExecutionListeners; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider; +import com.github.springtestdbunit.DbUnitTestExecutionListener; +import com.github.springtestdbunit.annotation.DatabaseSetup; +import com.github.springtestdbunit.annotation.ExpectedDatabase; + +import es.uvigo.esei.daa.DAAExampleTestApplication; +import es.uvigo.esei.daa.entities.Person; +import es.uvigo.esei.daa.entities.Pet; +import es.uvigo.esei.daa.listeners.ApplicationContextBinding; +import es.uvigo.esei.daa.listeners.ApplicationContextJndiBindingTestExecutionListener; +import es.uvigo.esei.daa.listeners.DbManagement; +import es.uvigo.esei.daa.listeners.DbManagementTestExecutionListener; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration("classpath:contexts/mem-context.xml") +@TestExecutionListeners({ + DbUnitTestExecutionListener.class, + DbManagementTestExecutionListener.class, + ApplicationContextJndiBindingTestExecutionListener.class +}) +@ApplicationContextBinding( + jndiUrl = "java:/comp/env/jdbc/daaexample", + type = DataSource.class +) +@DbManagement( + create = "classpath:db/hsqldb.sql", + drop = "classpath:db/hsqldb-drop.sql" +) +@DatabaseSetup("/datasets/dataset.xml") +@ExpectedDatabase("/datasets/dataset.xml") +public class PetsResourceTest extends JerseyTest { + @Override + protected Application configure() { + return new DAAExampleTestApplication(); + } + + @Override + protected void configureClient(ClientConfig config) { + super.configureClient(config); + + // Enables JSON transformation in client + config.register(JacksonJsonProvider.class); + config.property("com.sun.jersey.api.json.POJOMappingFeature", Boolean.TRUE); + } + + @Test + public void testPetList() throws IOException { + final Response response = target("pets").request() + .header("Authorization", "Basic " + userToken(adminLogin())) + .get(); + assertThat(response, hasOkStatus()); + + final List pets = response.readEntity(new GenericType>(){}); + + assertThat(pets, containsPetsInAnyOrder(pets())); + } + + @Test + public void testPetListUnauthorized() throws IOException { + final Response response = target("pets").request() + .get(); + assertThat(response, hasUnauthorized()); + } + + @Test + public void testPetGet() throws IOException { + final Response response = target("pets/" + existentId()).request() + .header("Authorization", "Basic " + userToken(adminLogin())) + .get(); + assertThat(response, hasOkStatus()); + + final Pet pet = response.readEntity(Pet.class); + + assertThat(pet, is(equalsToPet(existentPet()))); + } + + @Test + public void testPetGetUnauthorized() throws IOException { + final Response response = target("pets/" + existentId()).request() + .get(); + assertThat(response, hasUnauthorized()); + } + + @Test + public void testPetGetInvalidId() throws IOException { + final Response response = target("pets/" + nonExistentId()).request() + .header("Authorization", "Basic " + userToken(adminLogin())) + .get(); + + assertThat(response, hasBadRequestStatus()); + } + + @Test + @ExpectedDatabase("/datasets/dataset-pets-add.xml") + public void testPetAdd() throws IOException { + final Form form = new Form(); + form.param("pet_name", newPetName()); + form.param("owner_id", String.valueOf(newOwnerId())); + + final Response response = target("pets").request(MediaType.APPLICATION_JSON_TYPE) + .header("Authorization", "Basic " + userToken(adminLogin())) + .post(entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE)); + assertThat(response, hasOkStatus()); + + final Pet pet = response.readEntity(Pet.class); + + assertThat(pet, is(equalsToPet(newPet()))); + } + + @Test + public void testPetAddUnauthorized() throws IOException { + final Form form = new Form(); + form.param("pet_name", newPetName()); + form.param("owner_id", String.valueOf(newOwnerId())); + + final Response response = target("pets").request(MediaType.APPLICATION_JSON_TYPE) + .post(entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE)); + + assertThat(response, hasUnauthorized()); + } + + @Test + public void testPetAddMissingName() throws IOException { + final Form form = new Form(); + form.param("owner_id", String.valueOf(newOwnerId())); + + final Response response = target("pets").request(MediaType.APPLICATION_JSON_TYPE) + .header("Authorization", "Basic " + userToken(adminLogin())) + .post(entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE)); + + assertThat(response, hasBadRequestStatus()); + } + + @Test + public void testPetAddMissingSurname() throws IOException { + final Form form = new Form(); + form.param("pet_name", newName()); + + final Response response = target("pets/").request(MediaType.APPLICATION_JSON_TYPE) + .header("Authorization", "Basic " + userToken(adminLogin())) + .post(entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE)); + + assertThat(response, hasBadRequestStatus()); + } + +/* TODO: Arreglar fallo id. Posiblemente campo autoincrement, dataset esta bien + @Test + @ExpectedDatabase("/datasets/dataset-pets-modify.xml") + public void testPetModify() throws IOException { + final Form form = new Form(); + form.param("pet_name", newPetName()); + form.param("owner_id", String.valueOf(newOwnerId())); + + final Response response = target("pets/" + existentId()).request(MediaType.APPLICATION_JSON_TYPE) + .header("Authorization", "Basic " + userToken(adminLogin())) + .put(entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE)); + assertThat(response, hasOkStatus()); + System.out.println(response.getStatus()); + + Pet pet = newPet(); + pet.setPetId(5); + + Pet modifiedPet = response.readEntity(Pet.class); + + System.out.println("PET MODIFICADA "+modifiedPet.toString()); + System.out.println("PET EXISTENTE "+pet.toString()); + + assertEquals(pet.getowner_id(), modifiedPet.getowner_id()); + assertEquals(pet.getpet_name(), modifiedPet.getpet_name()); + }*/ + + @Test + public void testPetModifyUnauthorized() throws IOException { + final Form form = new Form(); + form.param("pet_name", newPetName()); + form.param("owner_id", String.valueOf(newOwnerId())); + + final Response response = target("pets/" + existentId()).request(MediaType.APPLICATION_JSON_TYPE) + .put(entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE)); + + assertThat(response, hasUnauthorized()); + } + + @Test + public void testPetModifyName() throws IOException { + final Form form = new Form(); + form.param("pet_name", newPetName()); + + final Response response = target("pets/" + existentId()).request(MediaType.APPLICATION_JSON_TYPE) + .header("Authorization", "Basic " + userToken(adminLogin())) + .put(entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE)); + + assertThat(response, hasBadRequestStatus()); + } + + @Test + public void testPetModifyOwnerId() throws IOException { + final Form form = new Form(); + form.param("owner_id", String.valueOf(newOwnerId())); + + final Response response = target("pets/" + existentId()).request(MediaType.APPLICATION_JSON_TYPE) + .header("Authorization", "Basic " + userToken(adminLogin())) + .put(entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE)); + + assertThat(response, hasBadRequestStatus()); + } + + @Test + public void testPetModifyInvalidId() throws IOException { + final Form form = new Form(); + form.param("pet_name", newPetName()); + form.param("owner_id", String.valueOf(newOwnerId())); + + final Response response = target("pets/" + nonExistentId()).request(MediaType.APPLICATION_JSON_TYPE) + .header("Authorization", "Basic " + userToken(adminLogin())) + .put(Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE)); + + assertThat(response, hasBadRequestStatus()); + } + + @Test + @ExpectedDatabase("/datasets/dataset-pets-delete.xml") + public void testPetDelete() throws IOException { + final Response response = target("pets/" + existentId()).request() + .header("Authorization", "Basic " + userToken(adminLogin())) + .delete(); + + assertThat(response, hasOkStatus()); + + final Integer deletedId = response.readEntity(Integer.class); + + assertThat(deletedId, is(equalTo(existentId()))); + } + + @Test + public void testPetDeleteUnauthorized() throws IOException { + final Response response = target("pets/" + existentId()).request() + .delete(); + + assertThat(response, hasUnauthorized()); + } + + @Test + public void testPetDeleteInvalidId() throws IOException { + final Response response = target("pets/" + nonExistentId()).request() + .header("Authorization", "Basic " + userToken(adminLogin())) + .delete(); + + assertThat(response, hasBadRequestStatus()); + } +} diff --git a/src/test/java/es/uvigo/esei/daa/suites/IntegrationTestSuite.java b/src/test/java/es/uvigo/esei/daa/suites/IntegrationTestSuite.java index 3f0c667..10f13b2 100644 --- a/src/test/java/es/uvigo/esei/daa/suites/IntegrationTestSuite.java +++ b/src/test/java/es/uvigo/esei/daa/suites/IntegrationTestSuite.java @@ -5,11 +5,13 @@ import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; import es.uvigo.esei.daa.rest.PeopleResourceTest; +import es.uvigo.esei.daa.rest.PetsResourceTest; import es.uvigo.esei.daa.rest.UsersResourceTest; @SuiteClasses({ PeopleResourceTest.class, - UsersResourceTest.class + UsersResourceTest.class, + PetsResourceTest.class }) @RunWith(Suite.class) public class IntegrationTestSuite { diff --git a/src/test/java/es/uvigo/esei/daa/suites/UnitTestSuite.java b/src/test/java/es/uvigo/esei/daa/suites/UnitTestSuite.java index a08e965..fb6610d 100644 --- a/src/test/java/es/uvigo/esei/daa/suites/UnitTestSuite.java +++ b/src/test/java/es/uvigo/esei/daa/suites/UnitTestSuite.java @@ -5,9 +5,11 @@ import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; import es.uvigo.esei.daa.entities.PersonUnitTest; +import es.uvigo.esei.daa.entities.PetsUnitTest; @SuiteClasses({ - PersonUnitTest.class + PersonUnitTest.class, + PetsUnitTest.class }) @RunWith(Suite.class) public class UnitTestSuite { diff --git a/src/test/resources/datasets/dataset-add.xml b/src/test/resources/datasets/dataset-add.xml index 9a75a99..a9a4ff7 100644 --- a/src/test/resources/datasets/dataset-add.xml +++ b/src/test/resources/datasets/dataset-add.xml @@ -16,4 +16,12 @@ + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/datasets/dataset-delete.xml b/src/test/resources/datasets/dataset-delete.xml index e49223d..8118691 100644 --- a/src/test/resources/datasets/dataset-delete.xml +++ b/src/test/resources/datasets/dataset-delete.xml @@ -14,4 +14,12 @@ + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/datasets/dataset-modify.xml b/src/test/resources/datasets/dataset-modify.xml index 6e2dfc9..c05683d 100644 --- a/src/test/resources/datasets/dataset-modify.xml +++ b/src/test/resources/datasets/dataset-modify.xml @@ -15,4 +15,11 @@ + + + + + + + \ No newline at end of file diff --git a/src/test/resources/datasets/dataset-pets-add.xml b/src/test/resources/datasets/dataset-pets-add.xml new file mode 100644 index 0000000..e357a3d --- /dev/null +++ b/src/test/resources/datasets/dataset-pets-add.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/datasets/dataset-pets-delete.xml b/src/test/resources/datasets/dataset-pets-delete.xml new file mode 100644 index 0000000..673d9f6 --- /dev/null +++ b/src/test/resources/datasets/dataset-pets-delete.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/datasets/dataset-pets-modify.xml b/src/test/resources/datasets/dataset-pets-modify.xml new file mode 100644 index 0000000..c5c7bc5 --- /dev/null +++ b/src/test/resources/datasets/dataset-pets-modify.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/datasets/dataset.dtd b/src/test/resources/datasets/dataset.dtd index e64500f..6c4802b 100644 --- a/src/test/resources/datasets/dataset.dtd +++ b/src/test/resources/datasets/dataset.dtd @@ -1,7 +1,8 @@ - + + + \ No newline at end of file diff --git a/src/test/resources/datasets/dataset.xml b/src/test/resources/datasets/dataset.xml index 3f48cc9..e37f8b1 100644 --- a/src/test/resources/datasets/dataset.xml +++ b/src/test/resources/datasets/dataset.xml @@ -15,4 +15,12 @@ + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/db/hsqldb-drop.sql b/src/test/resources/db/hsqldb-drop.sql index 31f8643..7bc45bd 100644 --- a/src/test/resources/db/hsqldb-drop.sql +++ b/src/test/resources/db/hsqldb-drop.sql @@ -1,2 +1,3 @@ DROP TABLE People IF EXISTS; DROP TABLE Users IF EXISTS; +DROP TABLE Pets IF EXISTS; diff --git a/src/test/resources/db/hsqldb.sql b/src/test/resources/db/hsqldb.sql index a629441..877baf1 100644 --- a/src/test/resources/db/hsqldb.sql +++ b/src/test/resources/db/hsqldb.sql @@ -10,4 +10,10 @@ CREATE TABLE users ( password VARCHAR(64) NOT NULL, role VARCHAR(5) NOT NULL, PRIMARY KEY (login) -); \ No newline at end of file +); + +CREATE TABLE pets ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1) NOT NULL, + pet_name VARCHAR(50) NOT NULL, + owner_id INT NOT NULL +); -- 2.18.1
NombreApellidoIdNombreApellido 
' + person.name + '' + person.surname + '' + person.id + '' + person.name + '' + person.surname + '\ Editar\ Eliminar\ diff --git a/src/main/webapp/js/view/pets.js b/src/main/webapp/js/view/pets.js new file mode 100644 index 0000000..9f8a9ac --- /dev/null +++ b/src/main/webapp/js/view/pets.js @@ -0,0 +1,222 @@ +var PetsView = (function() { + var dao; + var peopleDAO; + // Referencia a this que permite acceder a las funciones públicas desde las funciones de jQuery. + var self; + + var formId = 'pet-form'; + var listId = 'pet-list'; + var formQuery = '#' + formId; + var listQuery = '#' + listId; + + function PetsView(peopleDao, petsDao, formContainerId, listContainerId) { + peopleDAO = peopleDao; + dao = petsDao; + var dict = {} + self = this; + + insertPetsForm($('#' + formContainerId)); + insertPetsList($('#' + listContainerId)); + + this.init = function() { + dao.listPets(function(pet) { + $.each(pet, function(key, pet) { + appendToTable(pet); + }); + }, + function() { + alert('No has sido posible acceder al listado de mascotas.'); + }); + + peopleDAO.listPeople(function(people) { + $.each(people, function(key, people) { + $('#pet_owner_select').append($("").attr("value", people.id).text(people.name + ' ' +people.surname)); + }); + }, + function() { + }); + // La acción por defecto de enviar formulario (submit) se sobreescribe + // para que el envío sea a través de AJAX + $(formQuery).submit(function(event) { + var pet = self.getPetInForm(); + console.log(pet); + if (self.isEditing()) { + dao.modifyPet(pet, + function(pet) { + console.log(pet); + $('#pet-' + pet.id + ' td.pet_name').text(pet.pet_name); + $('#pet-' + pet.id + ' td.owner_id').text(pet.owner_id); + self.resetForm(); + }, + showErrorMessage, + self.enableForm + ); + } else { + dao.addPet(pet, + function(pet) { + console.log(pet); + appendToTable(pet); + self.resetForm(); + }, + showErrorMessage, + self.enableForm + ); + } + + return false; + }); + + $('#btnClear').click(this.resetForm); + }; + + this.reloadSelect = function(){ + $('#pet_owner_select').find('option').remove().end(); + peopleDAO.listPeople(function(people) { + $.each(people, function(key, people) { + $('#pet_owner_select').append($("").attr("value", people.id).text(people.name + ' ' +people.surname)); + }); + }, + function() { + }); + } + + this.getPetInForm = function() { + var form = $(formQuery); + return { + 'id': form.find('input[name="id"]').val(), + 'pet_name': form.find('input[name="pet_name"]').val(), + 'owner_id': $('#pet_owner_select option:selected').val() + }; + }; + + + + this.getPetInRow = function(id) { + var row = $('#pet-' + id); + + if (row !== undefined) { + return { + 'id': id, + 'pet_name': row.find('td.pet_name').text(), + 'owner_id': row.find('td.owner_id').text() + }; + } else { + return undefined; + } + }; + + this.editPet = function(id) { + var row = $('#pet-' + id); + + if (row !== undefined) { + var form = $(formQuery); + + form.find('input[name="id"]').val(id); + form.find('input[name="pet_name"]').val(row.find('td.pet_name').text()); + form.find('input[name="owner_id"]').val(row.find('td.owner_id').text()); + + $('input#btnSubmit').val('Modificar'); + } + }; + + this.deletePet = function(id) { + if (confirm('Está a punto de eliminar a una mascota. ¿Está seguro de que desea continuar?')) { + dao.deletePet(id, + function() { + $('tr#pet-' + id).remove(); + }, + showErrorMessage + ); + } + }; + + this.isEditing = function() { + return $(formQuery + ' input[name="id"]').val() != ""; + }; + + this.disableForm = function() { + $(formQuery + ' input').prop('disabled', true); + }; + + this.enableForm = function() { + $(formQuery + ' input').prop('disabled', false); + }; + + this.resetForm = function() { + $(formQuery)[0].reset(); + $(formQuery + ' input[name="id"]').val(''); + $('#btnSubmit').val('Crear'); + }; + }; + + var insertPetsList = function(parent) { + parent.append( + '\ + \ + \ + \ + \ + \ + \ + \ + \ + \ +
NombrePropietario 
' + ); + }; + + + var insertPetsForm = function(parent) { + parent.append( + '
\ + \ +
\ +
\ + \ +
\ +
\ + \ +
\ +
\ + \ + \ +
\ +
\ +
' + ); + }; + + var createPetRow = function(pet) { + return '
' + pet.pet_name + '' + pet.owner_id + '\ + Editar\ + Eliminar\ +