Commit 5ff6ed34 authored by Breixo Senra's avatar Breixo Senra

Falta menu de vet

parent 3ef867d3
CREATE DATABASE IF NOT EXISTS `xcs`;
USE `xcs`;
DROP TABLE IF EXISTS `Pet`;
DROP TABLE IF EXISTS `User`;
DROP TABLE IF EXISTS `pet_vet`;
DROP TABLE IF EXISTS `vaccination`;
DROP TABLE IF EXISTS `vaccine`;
DROP TABLE IF EXISTS `identifier`;
DROP TABLE IF EXISTS `pet`;
DROP TABLE IF EXISTS `user`;
--
-- Table structure for table `User`
--
CREATE TABLE `User` (
CREATE TABLE `user` (
`role` varchar(5) NOT NULL,
`login` varchar(100) NOT NULL,
`password` varchar(32) NOT NULL,
`password` varchar(128) NOT NULL,
PRIMARY KEY (`login`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Table structure for table `Pet`
--
CREATE TABLE `Pet` (
`id` int(11) NOT NULL AUTO_INCREMENT,
CREATE TABLE `pet` (
`id` int NOT NULL AUTO_INCREMENT,
`animal` varchar(4) NOT NULL,
`birth` datetime NOT NULL,
`name` varchar(100) NOT NULL,
`owner` varchar(100) NOT NULL,
`vet` varchar(100) NOT NULL,
PRIMARY KEY (`id`),
KEY `FK_Pet_Owner` (`owner`),
KEY `FK_Pet_Vet` (`vet`),
CONSTRAINT `FK_Pet_Owner_login` FOREIGN KEY (`owner`) REFERENCES `User` (`login`)
CONSTRAINT `FK_Pet_Vet_login` FOREIGN KEY (`vet`) REFERENCES `User` (`login`)
CONSTRAINT `FK_Pet_Vaccination_id` FOREIGN KEY (`vaccination`) REFERENCES `Vaccination` (`id`)
CONSTRAINT `FK_Pet_Owner_login` FOREIGN KEY (`owner`) REFERENCES `user` (`login`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Table structure for table `Pet`
-- Table structure for table `pet_vet`
--
CREATE TABLE `Vaccine` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(100) NOT NULL,
`owner` varchar(100) NOT NULL,
PRIMARY KEY (`id`),
KEY `FK_Pet_Owner` (`owner`),
CONSTRAINT `FK_Pet_Owner_login` FOREIGN KEY (`owner`) REFERENCES `User` (`login`)
CREATE TABLE `pet_vet` (
`pet_id` int NOT NULL,
`vet_login` varchar(100) NOT NULL,
PRIMARY KEY (`pet_id`,`vet_login`),
CONSTRAINT `FK_PetVet_Pet` FOREIGN KEY (`pet_id`) REFERENCES `pet` (`id`),
CONSTRAINT `FK_PetVet_Vet` FOREIGN KEY (`vet_login`) REFERENCES `user` (`login`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Table structure for table `Vaccination`
-- Table structure for table `identifier`
--
CREATE TABLE `Vaccination` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(100) NOT NULL,
`owner` varchar(100) NOT NULL,
`date` date NOT NULL,
PRIMARY KEY (`date`),
KEY `FK_Vaccination_Pet` (`pet`),
KEY `FK_Vaccination_Vaccine` (`owner`),
CONSTRAINT `FK_Vaccination_Pet_id` FOREIGN KEY (`petId`) REFERENCES `Pet` (`id`)
CONSTRAINT `FK_Vaccination_Vaccine_id` FOREIGN KEY (`vaccineId`) REFERENCES `Vaccine` (`id`)
CREATE TABLE `identifier` (
`value` varchar(32) NOT NULL,
`type` varchar(4) NOT NULL,
`pet_id` int DEFAULT NULL,
PRIMARY KEY (`value`),
KEY `FK_Identifier_Pet` (`pet_id`),
CONSTRAINT `FK_Identifier_Pet` FOREIGN KEY (`pet_id`) REFERENCES `pet` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Table structure for table `vaccine`
--
CREATE TABLE `vaccine` (
`VACCINE_TYPE` varchar(31) NOT NULL,
`id` bigint NOT NULL AUTO_INCREMENT,
`name` varchar(128) NOT NULL,
`doses` int DEFAULT NULL,
`periode` int DEFAULT NULL,
`periodicType` varchar(6) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Table structure for table `vaccination`
--
CREATE TABLE `vaccination` (
`id` bigint NOT NULL AUTO_INCREMENT,
`date` date DEFAULT NULL,
`pet_id` int DEFAULT NULL,
`vaccine_id` bigint DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `FK_Vacc_Pet` (`pet_id`),
KEY `FK_Vacc_Vaccine` (`vaccine_id`),
CONSTRAINT `FK_Vacc_Pet` FOREIGN KEY (`pet_id`) REFERENCES `pet` (`id`),
CONSTRAINT `FK_Vacc_Vaccine` FOREIGN KEY (`vaccine_id`) REFERENCES `vaccine` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Users
--
INSERT INTO `user` (role, login, password) VALUES
('ADMIN','jose','a3f6f4b40b24e2fd61f08923ed452f34'),
('OWNER','owner1','a3f6f4b40b24e2fd61f08923ed452f34'),
('OWNER','owner2','a3f6f4b40b24e2fd61f08923ed452f34'),
('OWNER','owner3','a3f6f4b40b24e2fd61f08923ed452f34'),
('OWNER','owner4','a3f6f4b40b24e2fd61f08923ed452f34'),
('OWNER','owner5','a3f6f4b40b24e2fd61f08923ed452f34'),
('OWNER','owner6','a3f6f4b40b24e2fd61f08923ed452f34'),
('OWNER','owner7','a3f6f4b40b24e2fd61f08923ed452f34'),
('OWNER','owner8','a3f6f4b40b24e2fd61f08923ed452f34'),
('OWNER','owner9','a3f6f4b40b24e2fd61f08923ed452f34'),
('OWNER','owner10','a3f6f4b40b24e2fd61f08923ed452f34D'),
('VET','vet1','a3f6f4b40b24e2fd61f08923ed452f34'),
('VET','vet2','a3f6f4b40b24e2fd61f08923ed452f34'),
('VET','vet3','a3f6f4b40b24e2fd61f08923ed452f34');
--
-- Pets
--
INSERT INTO `pet` (animal,birth,name,owner) VALUES
('DOG','2020-01-01 12:00:00','Bobby','owner1'),
('CAT','2020-02-01 12:00:00','Mimi','owner1'),
('BIRD','2020-03-01 12:00:00','Paco','owner1'),
('DOG','2020-04-01 12:00:00','Rocky','owner2'),
('CAT','2020-05-01 12:00:00','Luna','owner2'),
('BIRD','2020-06-01 12:00:00','Kiwi','owner2'),
('DOG','2020-07-01 12:00:00','Max','owner3'),
('CAT','2020-08-01 12:00:00','Nala','owner3'),
('BIRD','2020-09-01 12:00:00','Sunny','owner3'),
('DOG','2020-10-01 12:00:00','Leo','owner4'),
('CAT','2020-11-01 12:00:00','Lola','owner4'),
('BIRD','2020-12-01 12:00:00','Tweety','owner4'),
('DOG','2021-01-01 12:00:00','Toby','owner5'),
('CAT','2021-02-01 12:00:00','Bella','owner5'),
('BIRD','2021-03-01 12:00:00','Angel','owner5');
--
-- Identifiers
--
INSERT INTO `identifier` (value,type,pet_id) VALUES
('ID00001','TAG',1),
('ID00002','CHIP',1),
('ID00003','TAG',2),
('ID00004','CHIP',2),
('ID00005','TAG',3),
('ID00006','CHIP',3),
('ID00007','TAG',4),
('ID00008','CHIP',4),
('ID00009','TAG',5),
('ID00010','CHIP',5),
('ID00011','TAG',6),
('ID00012','CHIP',6),
('ID00013','TAG',7),
('ID00014','CHIP',7),
('ID00015','TAG',8),
('ID00016','CHIP',8),
('ID00017','TAG',9),
('ID00018','CHIP',9);
--
-- User creation
-- Pet-Vet relations
--
CREATE USER IF NOT EXISTS xcs@localhost IDENTIFIED BY 'xcs';
GRANT ALL PRIVILEGES ON xcs.* TO xcs@localhost;
FLUSH PRIVILEGES;
INSERT INTO `pet_vet` (pet_id,vet_login) VALUES
(1,'vet1'),(2,'vet1'),(3,'vet1'),
(4,'vet2'),(5,'vet2'),(6,'vet2'),
(7,'vet3'),(8,'vet3'),(9,'vet3');
--
-- Data for table `User`
-- Vaccines
--
INSERT INTO `User` (role, login, password) VALUES
('ADMIN','jose','a3f6f4b40b24e2fd61f08923ed452f34'),
('OWNER','ana','22beeae33e9b2657f9610621502cd7a4'),
('OWNER','juan','b4fbb95580592697dc71488a1f19277e'),
('OWNER','lorena','05009e420932c21e5a68f5ef1aadd530'),
('OWNER','pepe','b43b4d046860b2bd945bca2597bf9f07');
INSERT INTO `vaccine` (VACCINE_TYPE,name,doses,periode,periodicType) VALUES
('MONODOSE','VacunaUno',NULL,NULL,NULL),
('MULTIDOSE','VacunaPeriodica',20,NULL,NULL),
('PERIODIC','Periodica',NULL,7,'DAYS');
--
-- Data for table `Pet`
-- Vaccinations
--
INSERT INTO `Pet` (animal, birth, name, owner) VALUES
('CAT','2000-01-01 01:01:01','Pepecat','pepe'),
('CAT','2000-01-01 01:01:01','Max','juan'),
('DOG','2000-01-01 01:01:01','Juandog','juan'),
('CAT','2000-01-01 01:01:01','Anacat','ana'),
('DOG','2000-01-01 01:01:01','Max','ana'),
('BIRD','2000-01-01 01:01:01','Anabird','ana');
INSERT INTO `vaccination` (date,pet_id,vaccine_id) VALUES
('2025-10-01',1,1),
('2025-10-02',2,2),
('2025-10-03',3,3),
('2025-10-04',4,1),
('2025-10-05',5,2),
('2025-10-06',6,3),
('2025-10-07',7,1),
('2025-10-08',8,2),
('2025-10-09',9,3);
package es.uvigo.esei.xcs.rest;
import javax.ejb.EJB;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import es.uvigo.esei.xcs.service.AdministratorService;
import es.uvigo.esei.xcs.service.EmailService;
/**
* REST resource for administrator operations.
*
* Provides endpoints for listing users and sending test emails.
* Accessible under the path "/admin".
*
* @author Breixo
*/
@Path("admin")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public class AdministratorResource {
@EJB
AdministratorService service;
private AdministratorService service;
@EJB
EmailService emailService;
private EmailService emailService;
/**
* Returns a paginated list of users managed by the administrator.
*
* @param page index of the page (0-based)
* @param pageSize number of users per page
* @return HTTP 200 with the list of users
*/
@GET
public Response list(@QueryParam("page") int page, @QueryParam("pageSize") int pageSize) {
return Response.ok(this.service.list(page, pageSize)).build();
}
/**
* Sends a test email for verification purposes.
*
* @return HTTP 200 if the email was sent successfully
*/
@POST
public Response sendEmail() {
this.emailService.send("email@fake.email", "Topic", "Text Message");
return Response.ok().build();
}
}
package es.uvigo.esei.xcs.rest;
import java.net.URI;
import javax.ejb.EJB;
import javax.persistence.EntityExistsException;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
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.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.*;
import javax.ws.rs.core.*;
import es.uvigo.esei.xcs.domain.entities.IdentifierType;
import es.uvigo.esei.xcs.domain.entities.Owner;
......@@ -27,135 +14,137 @@ import es.uvigo.esei.xcs.service.OwnerService;
import static java.util.Objects.requireNonNull;
/**
* Resource that represents the owners in the application.
* REST resource that manages owners and their related pets and vaccinations.
* Provides CRUD operations and pagination.
*
* @author Miguel Reboiro Jato
* Accessible under the path "/owner".
*
* @author Breixo
*/
@Path("owner")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public class OwnerResource {
@EJB
private OwnerService service;
@Context
private UriInfo uriInfo;
/**
* Returns the owner identified by the login.
* Returns the owner identified by the given login.
*
* @param login the login of an owner.
* @return an {@code OK} response containing the {@link Owner} with the
* provided login.
* @throws IllegalArgumentException if {@code login} is {@code null} or
* if it does not correspond with any owner.
* @param login unique login of the owner.
* @return HTTP 200 with the owner data.
* @throws IllegalArgumentException if the login is null or not found.
*/
@GET
@Path("{login}")
public Response get(@PathParam("login") String login) {
if (login == null)
throw new IllegalArgumentException("login can't be null");
final Owner owner = this.service.get(login);
if (owner == null)
throw new IllegalArgumentException("Owner not found: " + login);
else
return Response.ok(owner).build();
return Response.ok(owner).build();
}
/**
* Returns the list of owners stored in the application.
* Returns a paginated list of owners.
*
* @return an {@code OK} response containing the list of owners stored in
* the application.
* @param page 0-based page index.
* @param pageSize number of results per page.
* @return HTTP 200 with the list of owners.
*/
@GET
public Response list(@QueryParam("page") int page, @QueryParam("pageSize") int pageSize) {
return Response.ok(this.service.list(page, pageSize)).build();
}
/**
* Creates a new owner. This owner may include a list of pets, that will be
* also created.
* Creates a new owner (and optionally its pets).
*
* @param ownerData a new owner to be stored.
* @return a {@code CREATED} response with the URI of the new owner in the
* {@code Location} header.
* @throws IllegalArgumentException if owner is {@code null} or if an owner
* with the same login already exists.
* @param ownerData data of the new owner.
* @return HTTP 201 with the URI of the created owner.
* @throws IllegalArgumentException if the data is null or already exists.
*/
@POST
public Response create(OwnerCreationData ownerData) {
if (ownerData == null) {
throw new IllegalArgumentException("ownerData can't be null");
}
if (ownerData == null)
throw new IllegalArgumentException("ownerData can't be null");
try {
final Owner newOwner = this.service.create(ownerData.toOwner());
final URI ownerUri = uriInfo.getAbsolutePathBuilder()
.path(newOwner.getLogin())
.build();
.build();
return Response.created(ownerUri).build();
} catch (EntityExistsException eee) {
throw new IllegalArgumentException("The owner already exists");
}
}
/**
* Updates an owner. This owner may include a list of pets, that will be
* also created or updated. If the owner does not exists it will be created.
* Updates an existing owner and its pets.
*
* @param ownerData an owner to be updated.
* @return an empty {@code OK} response.
* @throws IllegalArgumentException if owner is {@code null}.
* @param login owner login.
* @param ownerData updated owner data.
* @return HTTP 200 when updated successfully.
* @throws IllegalArgumentException if login or data are null.
*/
@Path("{login}")
@PUT
@Path("{login}")
public Response update(@PathParam("login") String login, OwnerEditionData ownerData) {
requireNonNull(login, "login can't be null");
requireNonNull(ownerData, "ownerData can't be null");
final Owner owner = this.service.get(login);
ownerData.assignData(owner);
this.service.update(owner);
return Response.ok().build();
requireNonNull(ownerData, "ownerData can't be null");
final Owner owner = this.service.get(login);
ownerData.assignData(owner);
this.service.update(owner);
return Response.ok().build();
}
/**
* Deletes an owner.
* Deletes the owner identified by the given login.
*
* @param login the login of the owner to be deleted.
* @return an empty {@code OK} response.
* @throws IllegalArgumentException if {@code login} is {@code null} or if
* it does not identifies a valid owner.
* @param login owner login.
* @return HTTP 200 when deletion succeeds.
* @throws IllegalArgumentException if login is null.
*/
@Path("{login}")
@DELETE
@Path("{login}")
public Response delete(@PathParam("login") String login) {
if (login == null)
throw new IllegalArgumentException("login can't be null");
this.service.remove(login);
this.service.remove(login);
return Response.ok().build();
}
@Path("pet/{petIdentifierType}/{petIdentifierValue}/vaccination")
/**
* Returns the vaccinations for a pet identified by type and value.
*
* @param petIdentifierType type of identifier.
* @param petIdentifierValue value of the identifier.
* @param page 0-based page index.
* @param pageSize number of results per page.
* @return HTTP 200 with the list of vaccinations.
*/
@GET
@Path("pet/{petIdentifierType}/{petIdentifierValue}/vaccination")
public Response listVaccinations(
@PathParam("petIdentifierType") IdentifierType petIdentifierType,
@PathParam("petIdentifierValue") String petIdentifierValue,
@QueryParam("page") int page,
@QueryParam("pageSize") int pageSize
) {
@PathParam("petIdentifierType") IdentifierType petIdentifierType,
@PathParam("petIdentifierValue") String petIdentifierValue,
@QueryParam("page") int page,
@QueryParam("pageSize") int pageSize) {
return Response.ok(this.service.getVaccinationsFromOwnPet(
//login,
petIdentifierType,
petIdentifierValue,
page,
petIdentifierType,
petIdentifierValue,
page,
pageSize
)).build();
}
}
package es.uvigo.esei.xcs.rest;
import java.net.URI;
import javax.ejb.EJB;
import javax.ejb.EJBAccessException;
import javax.persistence.EntityExistsException;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue;
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.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.*;
import javax.ws.rs.core.*;
import es.uvigo.esei.xcs.domain.entities.Pet;
import es.uvigo.esei.xcs.rest.entity.PetData;
import es.uvigo.esei.xcs.service.PetService;
/**
* Resource that represents the pets in the application.
* REST resource that manages pets in the application.
* Provides CRUD operations, pagination, and access control.
* Accessible under the path "/pet".
*
* Only the pet's owner or authorized roles can modify or delete a pet.
* Access violations throw SecurityException.
*
* @author Miguel Reboiro Jato
* @author Breixo
*/
@Path("pet")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public class PetResource {
@EJB
private PetService service;
@Context
private UriInfo uriInfo;
/**
* Returns the owner identified by the login.
* Returns a pet by its identifier.
*
* @param id the identified of a pet.
* @return an {@code OK} response containing the {@link Pet} with the
* provided identifier.
* @throws SecurityException if the current owner does not owns the pet.
* @param id pet ID.
* @return HTTP 200 with pet data.
* @throws SecurityException if current user is not the pet's owner.
* @throws IllegalArgumentException if pet not found.
*/
@Path("{id}")
@GET
public Response get(@PathParam("id") Long id) throws SecurityException {
try {
final Pet pet = this.service.get(id);
if (pet == null)
throw new IllegalArgumentException("Pet not found: " + id);
else
return Response.ok(pet).build();
return Response.ok(pet).build();
} catch (EJBAccessException eae) {
throw new SecurityException(eae);
}
}
/**
* Returns the complete list of pets of the current owner.
*
* @return an {@code OK} response containing the complete list of pets of
* the current owner.
* Returns a paginated list of all pets.
*
* @param page 0-based page index.
* @param pageSize number of results per page.
* @return HTTP 200 with list of pets.
*/
@GET
@Path("lista")
public Response getAll(
@QueryParam("page") @DefaultValue("0") int page,
@QueryParam("pageSize") @DefaultValue("10") int pageSize) {
public Response getAll(@QueryParam("page") @DefaultValue("0") int page,
@QueryParam("pageSize") @DefaultValue("10") int pageSize) {
return Response.ok(this.service.getAll(page, pageSize)).build();
}
/**
* Returns a paginated list of pets owned by the current user.
*
* @param page 0-based page index.
* @param pageSize number of results per page.
* @return HTTP 200 with list of current owner's pets.
*/
@GET
public Response list(
@QueryParam("page") @DefaultValue("0") int page,
@QueryParam("pageSize") @DefaultValue("10") int pageSize) {
public Response list(@QueryParam("page") @DefaultValue("0") int page,
@QueryParam("pageSize") @DefaultValue("10") int pageSize) {
return Response.ok(this.service.list(page, pageSize)).build();
}
/**
* Creates a new pet owned by the current user.
* Creates a new pet for the current user.
*
* @param petData a new owner to be stored.
* @return a {@code CREATED} response with the URI of the new pet in the
* {@code Location} header.
* @throws IllegalArgumentException if pet is {@code null} or if a pet with
* the same identifier already exists.
* @throws SecurityException if the pet already has an owner and it is not
* the current user. If the pet has no owner, this exception will be never
* thrown.
* @param petData data for the new pet.
* @return HTTP 201 with Location header pointing to the new pet.
* @throws IllegalArgumentException if petData is null or pet already exists.
* @throws SecurityException if current user cannot own this pet.
*/
@POST
public Response create(PetData petData) throws SecurityException {
if (petData == null)
throw new IllegalArgumentException("pet can't be null");
try {
final Pet pet = this.service.create(petData.toPet());
final URI petUri = uriInfo.getAbsolutePathBuilder()
.path(String.valueOf(pet.getId()))
.build();
.build();
return Response.created(petUri).build();
} catch (EntityExistsException eee) {
throw new IllegalArgumentException("The pet already exists");
......@@ -115,51 +105,45 @@ public class PetResource {
throw new SecurityException(eae);
}
}
/**
* Updates the information of a pet. If the pet is not stored, it will be
* created.
* Updates an existing pet's data.
*
* @param id the identifier of the pet to be modified.
* @param petData a pet to be updated.
* @return an empty {@code OK} response.
* @throws IllegalArgumentException if pet is {@code null} of it has no
* owner.
* @throws SecurityException if the pet's owner is not the current user.
* @param id pet ID.
* @param petData updated pet data.
* @return HTTP 200 when updated successfully.
* @throws IllegalArgumentException if petData is null or pet has no owner.
* @throws SecurityException if current user is not pet's owner.
*/
@Path("{id}")
@Path("{id}")
@PUT
public Response update(@PathParam("id") Long id, PetData petData) throws SecurityException {
if (petData == null)
throw new IllegalArgumentException("pet can't be null");
try {
final Pet pet = this.service.get(id);
petData.assignData(pet);
final Pet pet = this.service.get(id);
petData.assignData(pet);
this.service.update(pet);
return Response.ok().build();
} catch (EJBAccessException eae) {
throw new SecurityException(eae);
}
}
/**
* Deletes a pet.
* Deletes a pet by its ID.
*
* @param id the identifier of the pet to be deleted.
* @return an empty {@code OK} response.
* @throws IllegalArgumentException if there is no pet with the provided
* identifier.
* @throws SecurityException if the pet's owner is not the current user.
* @param id pet ID.
* @return HTTP 200 when deleted successfully.
* @throws IllegalArgumentException if pet does not exist.
* @throws SecurityException if current user is not pet's owner.
*/
@Path("{id}")
@DELETE
public Response delete(@PathParam("id") Long id) throws SecurityException {
try {
this.service.remove(id);
return Response.ok().build();
} catch (EJBAccessException eae) {
throw new SecurityException(eae);
......
......@@ -3,21 +3,21 @@ package es.uvigo.esei.xcs.rest;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.ejb.EJB;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import es.uvigo.esei.xcs.domain.entities.Vaccination;
import es.uvigo.esei.xcs.service.VaccinationService;
/**
* REST resource for managing pet vaccinations.
* Provides endpoints to check if a vaccination can be applied and to create vaccinations.
* Accessible under the path "/vaccination".
*
* @author Breixo
*/
@Path("vaccination")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
......@@ -26,32 +26,43 @@ public class VaccinationResource {
@EJB
private VaccinationService vaccinationService;
/**
* Checks if a pet can be vaccinated with a specific vaccine today.
*
* @param petId the ID of the pet.
* @param vaccineId the ID of the vaccine.
* @return HTTP 200 with a boolean indicating if vaccination is allowed.
*/
@GET
@Path("canVaccinate/{petId}/{vaccineId}")
public Response canVaccinate(
@PathParam("petId") Long petId,
@PathParam("vaccineId") Long vaccineId
) {
public Response canVaccinate(@PathParam("petId") Long petId,
@PathParam("vaccineId") Long vaccineId) {
Date now = new Date();
Boolean result = vaccinationService.canVaccinate(petId, vaccineId, now);
return Response.ok(result).build();
}
/**
* Creates a vaccination for a pet with a given vaccine.
*
* @param petId the ID of the pet.
* @param vaccineId the ID of the vaccine.
* @param textDate optional date in yyyy-MM-dd format. Defaults to today if null.
* @return HTTP 200 with the created Vaccination, or HTTP 400 if invalid input.
*/
@POST
@Path("create/{petId}/{vaccineId}")
public Response createVaccination(
@PathParam("petId") Long petId,
@PathParam("vaccineId") Long vaccineId,
@QueryParam("date") String textDate
) {
public Response createVaccination(@PathParam("petId") Long petId,
@PathParam("vaccineId") Long vaccineId,
@QueryParam("date") String textDate) {
Date date = new Date();
if (textDate != null) {
try {
date = new SimpleDateFormat("yyyy-MM-dd").parse(textDate);
} catch (ParseException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity("Invalid date format, expected yyyy-MM-dd").build();
.entity("Invalid date format, expected yyyy-MM-dd")
.build();
}
}
......@@ -60,8 +71,8 @@ public class VaccinationResource {
return Response.ok(vaccination).build();
} catch (IllegalArgumentException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(e.getMessage()).build();
.entity(e.getMessage())
.build();
}
}
}
package es.uvigo.esei.xcs.rest;
import static java.util.Objects.requireNonNull;
import java.net.URI;
import javax.ejb.EJB;
import javax.ws.rs.*;
......@@ -12,6 +11,10 @@ import es.uvigo.esei.xcs.rest.entity.VaccineCreationData;
import es.uvigo.esei.xcs.rest.entity.VaccineEditionData;
import es.uvigo.esei.xcs.service.VaccineService;
/**
* REST resource for managing vaccines.
* Provides endpoints to list, create, update, and delete vaccines.
*/
@Path("vaccine")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
......@@ -23,12 +26,26 @@ public class VaccineResource {
@Context
private UriInfo uriInfo;
/**
* Returns a paginated list of vaccines.
*
* @param page 0-based page index.
* @param pageSize number of items per page.
* @return HTTP 200 with the list of vaccines.
*/
@GET
public Response list(@QueryParam("page") @DefaultValue("0") int page,
@QueryParam("pageSize") @DefaultValue("10") int pageSize) {
return Response.ok(vaccineService.list(page, pageSize)).build();
}
/**
* Creates a new vaccine.
*
* @param vaccineData data to create the vaccine.
* @return HTTP 201 with the URI of the created vaccine.
* @throws IllegalArgumentException if vaccineData is null.
*/
@POST
public Response create(VaccineCreationData vaccineData) {
requireNonNull(vaccineData, "vaccineData can't be null");
......@@ -42,7 +59,15 @@ public class VaccineResource {
URI uri = uriInfo.getAbsolutePathBuilder().path(String.valueOf(vaccine.getId())).build();
return Response.created(uri).build();
}
/**
* Updates only the name of an existing vaccine.
*
* @param id vaccine ID.
* @param newName new name for the vaccine.
* @return HTTP 200 with the updated vaccine.
* @throws IllegalArgumentException if newName is null.
*/
@PUT
@Path("{id}/name")
public Response updateName(@PathParam("id") Long id, String newName) {
......@@ -51,7 +76,14 @@ public class VaccineResource {
return Response.ok(updated).build();
}
/**
* Updates all editable fields of an existing vaccine.
*
* @param id vaccine ID.
* @param vaccineData data to update.
* @return HTTP 200 when updated successfully.
* @throws IllegalArgumentException if vaccineData is null.
*/
@PUT
@Path("{id}")
public Response update(@PathParam("id") Long id, VaccineEditionData vaccineData) {
......@@ -62,6 +94,13 @@ public class VaccineResource {
return Response.ok().build();
}
/**
* Deletes a vaccine by its ID.
*
* @param id vaccine ID.
* @return HTTP 200 when deleted successfully.
* @throws IllegalArgumentException if vaccine does not exist.
*/
@DELETE
@Path("{id}")
public Response delete(@PathParam("id") Long id) {
......
package es.uvigo.esei.xcs.rest;
import static java.util.Objects.requireNonNull;
import java.net.URI;
import java.util.Date;
import javax.ejb.EJB;
import javax.ejb.EJBAccessException;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue;
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.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.*;
import javax.ws.rs.core.*;
import es.uvigo.esei.xcs.domain.entities.IdentifierType;
import es.uvigo.esei.xcs.domain.entities.Vaccination;
......@@ -39,201 +25,265 @@ import es.uvigo.esei.xcs.service.VetService;
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public class VetResource {
@EJB
private VetService vetService;
@EJB
private PetService petService;
@EJB
private VaccineService vaccineService;
@EJB
private VaccinationService vaccinationService;
@Context
private UriInfo uriInfo;
@GET
@Path("{login}")
public Response get(@PathParam("login") String login) {
return Response.ok(vetService.get(login)).build();
}
@GET
public Response list() {
return Response.ok(vetService.list()).build();
}
@POST
public Response create(VetData vetData) {
requireNonNull(vetData);
try {
final Vet vet = this.vetService.create(vetData.toVet());
final URI vetUri = uriInfo.getAbsolutePathBuilder()
.path(vet.getLogin()).build();
return Response.created(vetUri).build();
} catch (Exception e) {
throw new SecurityException(e);
}
}
@Path("{login}")
@DELETE
public Response delete(@PathParam("login") String login) {
try {
this.vetService.remove(login);
return Response.ok().build();
} catch (EJBAccessException e) {
throw new SecurityException(e);
}
}
@GET
@Path("pets")
public Response listPets(
@QueryParam("page") @DefaultValue("0") int page,
@QueryParam("pageSize") @DefaultValue("10") int pageSize
) {
return Response.ok(this.vetService.getPets(page, pageSize)).build();
}
@GET
@Path("pets/{petId}")
public Response getPet(@PathParam("petId") Long petId) {
return Response.ok(this.petService.get(petId)).build();
}
@GET
@Path("vaccine")
public Response listVaccines(@QueryParam("page") int page, @QueryParam("pageSize") int pageSize) {
return Response.ok(this.vaccineService.list(page, pageSize)).build();
}
@POST
@Path("vaccine")
public Response createVaccine(VaccineCreationData vaccineData) {
Vaccine vaccine = this.vaccineService.create(
vaccineData.getName(),
vaccineData.getType(),
vaccineData.getDoses(),
vaccineData.getPeriodicType(),
vaccineData.getPeriode()
);
return Response.ok(vaccine).build();
}
@Path("vaccine/{id}")
@PUT
public Response updateVaccine(@PathParam("id") Long id, VaccineEditionData vaccineData) {
if (vaccineData == null) {
throw new IllegalArgumentException("vaccineData can't be null");
}
final Vaccine vaccine = this.vaccineService.get(id);
vaccineData.assignData(vaccine);
this.vaccineService.update(vaccine);
return Response.ok().build();
}
@Path("vaccine/{id}")
@DELETE
public Response deleteVaccine(@PathParam("id") Long id) {
try {
this.vaccineService.remove(id);
return Response.ok().build();
} catch (EJBAccessException e) {
throw new SecurityException(e);
}
}
@Path("pet/{petIdentifierType}/{petIdentifierValue}/vaccination")
@GET
public Response listVaccinations(
@PathParam("petIdentifierType") IdentifierType petIdentifierType,
@PathParam("petIdentifierValue") String petIdentifierValue,
@QueryParam("page") int page,
@QueryParam("pageSize") int pageSize
) {
return Response.ok(this.vetService.getVaccinationsFromOwnPet(
//login,
petIdentifierType,
petIdentifierValue,
page,
pageSize
)).build();
}
@Path("vaccination")
@POST
public Response registerVaccination(
@QueryParam("date") Date date,
VaccinationCreationData vaccinationData
) {
if (date == null) {
date = new Date();
}
Vaccination vaccination = this.vaccinationService.create(
vaccinationData.getPetId(),
vaccinationData.getVaccineId(),
date
);
final URI vaccinationUri = uriInfo.getAbsolutePathBuilder()
.path(String.valueOf(vaccination.getId())).build();
return Response.created(vaccinationUri).build();
}
@POST
@Path("/assign/pets/{petId}")
public Response assignVetToPet(
@PathParam("petId") Long petId
) {
requireNonNull(petId, "petId can't be null");
try {
petService.assignVetToPet(petId);
return Response.ok()
.build();
} catch (IllegalArgumentException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(e.getMessage())
.build();
}
}
@DELETE
@Path("{login}/unassign/pets/{petId}")
public Response unassignVetFromPet(
@PathParam("petId") Long petId
) {
requireNonNull(petId, "petId can't be null");
try {
petService.unassignVetFromPet(petId);
return Response.ok()
.build();
} catch (IllegalArgumentException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(e.getMessage())
.build();
}
}
@EJB
private VetService vetService;
@EJB
private PetService petService;
@EJB
private VaccineService vaccineService;
@EJB
private VaccinationService vaccinationService;
@Context
private UriInfo uriInfo;
/**
* Returns a vet by login.
*
* @param login vet login.
* @return HTTP 200 with the vet.
*/
@GET
@Path("{login}")
public Response get(@PathParam("login") String login) {
return Response.ok(vetService.get(login)).build();
}
/**
* Returns the list of all vets.
*
* @return HTTP 200 with the list of vets.
*/
@GET
public Response list() {
return Response.ok(vetService.list()).build();
}
/**
* Creates a new vet.
*
* @param vetData data of the vet to create.
* @return HTTP 201 with the URI of the created vet.
* @throws SecurityException if creation fails.
*/
@POST
public Response create(VetData vetData) {
requireNonNull(vetData, "vetData can't be null");
try {
final Vet vet = this.vetService.create(vetData.toVet());
final URI vetUri = uriInfo.getAbsolutePathBuilder()
.path(vet.getLogin()).build();
return Response.created(vetUri).build();
} catch (Exception e) {
throw new SecurityException(e);
}
}
/**
* Deletes a vet by login.
*
* @param login vet login.
* @return HTTP 200 when deleted successfully.
* @throws SecurityException if deletion fails due to access control.
*/
@Path("{login}")
@DELETE
public Response delete(@PathParam("login") String login) {
try {
this.vetService.remove(login);
return Response.ok().build();
} catch (EJBAccessException e) {
throw new SecurityException(e);
}
}
/**
* Returns a paginated list of pets for the current vet.
*
* @param page 0-based page index.
* @param pageSize number of pets per page.
* @return HTTP 200 with the list of pets.
*/
@GET
@Path("pets")
public Response listPets(@QueryParam("page") @DefaultValue("0") int page,
@QueryParam("pageSize") @DefaultValue("10") int pageSize) {
return Response.ok(this.vetService.getPets(page, pageSize)).build();
}
/**
* Returns a specific pet by ID.
*
* @param petId pet ID.
* @return HTTP 200 with the pet.
*/
@GET
@Path("pets/{petId}")
public Response getPet(@PathParam("petId") Long petId) {
return Response.ok(this.petService.get(petId)).build();
}
/**
* Returns a paginated list of vaccines.
*
* @param page 0-based page index.
* @param pageSize number of vaccines per page.
* @return HTTP 200 with the list of vaccines.
*/
@GET
@Path("vaccine")
public Response listVaccines(@QueryParam("page") int page,
@QueryParam("pageSize") int pageSize) {
return Response.ok(this.vaccineService.list(page, pageSize)).build();
}
/**
* Creates a new vaccine.
*
* @param vaccineData data to create the vaccine.
* @return HTTP 200 with the created vaccine.
*/
@POST
@Path("vaccine")
public Response createVaccine(VaccineCreationData vaccineData) {
Vaccine vaccine = this.vaccineService.create(
vaccineData.getName(),
vaccineData.getType(),
vaccineData.getDoses(),
vaccineData.getPeriodicType(),
vaccineData.getPeriode()
);
return Response.ok(vaccine).build();
}
/**
* Updates a vaccine.
*
* @param id vaccine ID.
* @param vaccineData data to update the vaccine.
* @return HTTP 200 when updated successfully.
* @throws IllegalArgumentException if vaccineData is null.
*/
@Path("vaccine/{id}")
@PUT
public Response updateVaccine(@PathParam("id") Long id, VaccineEditionData vaccineData) {
requireNonNull(vaccineData, "vaccineData can't be null");
final Vaccine vaccine = this.vaccineService.get(id);
vaccineData.assignData(vaccine);
this.vaccineService.update(vaccine);
return Response.ok().build();
}
/**
* Deletes a vaccine by ID.
*
* @param id vaccine ID.
* @return HTTP 200 when deleted successfully.
* @throws SecurityException if deletion fails due to access control.
*/
@Path("vaccine/{id}")
@DELETE
public Response deleteVaccine(@PathParam("id") Long id) {
try {
this.vaccineService.remove(id);
return Response.ok().build();
} catch (EJBAccessException e) {
throw new SecurityException(e);
}
}
/**
* Returns paginated list of vaccinations of a pet owned by the current vet.
*
* @param petIdentifierType type of the pet's identifier.
* @param petIdentifierValue value of the pet's identifier.
* @param page 0-based page index.
* @param pageSize number of vaccinations per page.
* @return HTTP 200 with the list of vaccinations.
*/
@Path("pet/{petIdentifierType}/{petIdentifierValue}/vaccination")
@GET
public Response listVaccinations(@PathParam("petIdentifierType") IdentifierType petIdentifierType,
@PathParam("petIdentifierValue") String petIdentifierValue,
@QueryParam("page") int page,
@QueryParam("pageSize") int pageSize) {
return Response.ok(this.vetService.getVaccinationsFromOwnPet(
petIdentifierType,
petIdentifierValue,
page,
pageSize
)).build();
}
/**
* Registers a new vaccination for a pet.
*
* @param date date of vaccination, if null current date is used.
* @param vaccinationData data for the vaccination.
* @return HTTP 201 with the URI of the created vaccination.
*/
@Path("vaccination")
@POST
public Response registerVaccination(@QueryParam("date") Date date,
VaccinationCreationData vaccinationData) {
if (date == null) {
date = new Date();
}
Vaccination vaccination = this.vaccinationService.create(
vaccinationData.getPetId(),
vaccinationData.getVaccineId(),
date
);
final URI vaccinationUri = uriInfo.getAbsolutePathBuilder()
.path(String.valueOf(vaccination.getId())).build();
return Response.created(vaccinationUri).build();
}
/**
* Assigns the current vet to a pet.
*
* @param petId pet ID.
* @return HTTP 200 when assigned successfully.
* @throws IllegalArgumentException if petId is null or pet not found.
*/
@POST
@Path("/assign/pets/{petId}")
public Response assignVetToPet(@PathParam("petId") Long petId) {
requireNonNull(petId, "petId can't be null");
try {
petService.assignVetToPet(petId);
return Response.ok().build();
} catch (IllegalArgumentException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(e.getMessage())
.build();
}
}
/**
* Unassigns the current vet from a pet.
*
* @param petId pet ID.
* @return HTTP 200 when unassigned successfully.
* @throws IllegalArgumentException if petId is null or pet not found.
*/
@DELETE
@Path("{login}/unassign/pets/{petId}")
public Response unassignVetFromPet(@PathParam("petId") Long petId) {
requireNonNull(petId, "petId can't be null");
try {
petService.unassignVetFromPet(petId);
return Response.ok().build();
} catch (IllegalArgumentException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(e.getMessage())
.build();
}
}
}
package es.uvigo.esei.xcs.service;
import static java.util.Objects.requireNonNull;
import java.util.List;
......@@ -12,49 +11,62 @@ import javax.persistence.PersistenceContext;
import es.uvigo.esei.xcs.domain.entities.Administrator;
import es.uvigo.esei.xcs.domain.entities.User;
/**
* EJB for managing Administrator entities.
* Provides CRUD operations and paginated user listing.
*
* Accessible only to ADMIN users.
*
* @author Breixo Senra
*/
@Stateless
@RolesAllowed("ADMIN")
public class AdministratorService {
@PersistenceContext
EntityManager em;
public Administrator get(int id) {
return em.find(Administrator.class, id);
}
public List<User> list(int page, int pageSize){
if (page < 0) {
throw new IllegalArgumentException("The page can't be negative");
}
if (pageSize <= 0) {
throw new IllegalArgumentException("The page size can't be negative or zero");
}
return em.createQuery("SELECT DISTINCT u FROM User u", User.class)
.setFirstResult(page * pageSize)
.setMaxResults(pageSize)
.getResultList();
}
public Administrator create(Administrator administrator) {
requireNonNull(Administrator.class, "Administrator can't be null");
em.persist(administrator);
return administrator;
}
public Administrator update(Administrator administrator) {
requireNonNull(Administrator.class, "Administrator can't be null");
return em.merge(administrator);
}
public void remove(int id) {
em.remove(this.get(id));
}
@PersistenceContext
private EntityManager em;
/**
* Returns an administrator by its ID.
*/
public Administrator get(int id) {
return em.find(Administrator.class, id);
}
/**
* Returns a paginated list of all users.
*/
public List<User> list(int page, int pageSize) {
if (page < 0) throw new IllegalArgumentException("The page can't be negative");
if (pageSize <= 0) throw new IllegalArgumentException("The page size can't be negative or zero");
return em.createQuery("SELECT DISTINCT u FROM User u", User.class)
.setFirstResult(page * pageSize)
.setMaxResults(pageSize)
.getResultList();
}
/**
* Persists a new administrator entity.
*/
public Administrator create(Administrator administrator) {
requireNonNull(administrator, "Administrator can't be null");
em.persist(administrator);
return administrator;
}
/**
* Updates an existing administrator.
*/
public Administrator update(Administrator administrator) {
requireNonNull(administrator, "Administrator can't be null");
return em.merge(administrator);
}
/**
* Removes an administrator by ID.
*/
public void remove(int id) {
em.remove(this.get(id));
}
}
......@@ -7,46 +7,64 @@ import javax.ejb.Singleton;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
/**
* Singleton EJB that maintains counters for pets and vaccines.
*
* Counts are initialized from the database and kept in memory.
* Thread-safe access is ensured through read/write locks.
*
* @author Breixo
*/
@Singleton
public class CounterService {
@PersistenceContext
EntityManager em;
private EntityManager em;
private Long vaccineCounter;
private Long petCounter;
/**
* Initializes counters with the current counts from the database.
*/
@PostConstruct
public void init() {
this.petCounter = em
.createQuery("SELECT COUNT(p) FROM Pet p", Long.class)
.getSingleResult();
this.vaccineCounter = em
.createQuery("SELECT COUNT(v) FROM Vaccine v", Long.class)
.getSingleResult();
this.petCounter = em.createQuery("SELECT COUNT(p) FROM Pet p", Long.class)
.getSingleResult();
this.vaccineCounter = em.createQuery("SELECT COUNT(v) FROM Vaccine v", Long.class)
.getSingleResult();
}
/**
* Increments the pet counter by one.
*/
@Lock(LockType.WRITE)
public void incrementPetCounter() {
this.petCounter++;
}
/**
* Increments the vaccine counter by one.
*/
@Lock(LockType.WRITE)
public void incrementVaccineCounter() {
this.vaccineCounter++;
}
/**
* Returns the current pet counter value.
*/
@Lock(LockType.READ)
public Long getPetCounter() {
return this.petCounter;
}
/**
* Returns the current vaccine counter value.
*/
@Lock(LockType.READ)
public Long getVaccineCounter() {
return this.vaccineCounter;
}
}
......@@ -7,21 +7,40 @@ import javax.persistence.PersistenceContext;
import es.uvigo.esei.xcs.domain.entities.Identifier;
import static java.util.Objects.requireNonNull;
/**
* EJB for managing Identifier entities.
* Provides basic operations for creation and removal.
*
* @author Breixo Senra
*/
@Stateless
public class IdentifierService {
@PersistenceContext
EntityManager em;
public Identifier create(Identifier identifier) {
requireNonNull(identifier, "Identifier can't be null");
em.persist(identifier);
return identifier;
}
public void remove(String value) {
Identifier identifier = em.find(Identifier.class, value);
em.remove(identifier);
}
@PersistenceContext
private EntityManager em;
/**
* Persists a new identifier.
*
* @param identifier the Identifier entity to persist.
* @return the persisted Identifier entity.
* @throws NullPointerException if {@code identifier} is null.
*/
public Identifier create(Identifier identifier) {
requireNonNull(identifier, "Identifier can't be null");
em.persist(identifier);
return identifier;
}
/**
* Removes an identifier by its value.
*
* @param value the identifier value.
*/
public void remove(String value) {
Identifier identifier = em.find(Identifier.class, value);
if (identifier != null) {
em.remove(identifier);
}
}
}
......@@ -5,7 +5,6 @@ import static java.util.Objects.requireNonNull;
import java.security.Principal;
import java.util.List;
import javax.annotation.security.PermitAll;
import javax.annotation.security.RolesAllowed;
import javax.ejb.Stateless;
import javax.inject.Inject;
......@@ -13,183 +12,179 @@ import javax.persistence.EntityExistsException;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import es.uvigo.esei.xcs.domain.entities.Identifier;
import es.uvigo.esei.xcs.domain.entities.IdentifierType;
import es.uvigo.esei.xcs.domain.entities.Owner;
import es.uvigo.esei.xcs.domain.entities.Pet;
import es.uvigo.esei.xcs.domain.entities.Vaccination;
/**
* EJB for the Owners. Only administrators have access to this class.
* EJB for managing Owners and their pets. Access is restricted to ADMIN and OWNER roles.
*
* @author Miguel Reboiro Jato
* @author Breixo Senra
*/
@Stateless
@RolesAllowed({"ADMIN", "OWNER"})
public class OwnerService {
@PersistenceContext
private EntityManager em;
@Inject
private Principal currentUser;
public int countAll() {
Long count = em.createQuery("SELECT COUNT(o) FROM Owner o", Long.class)
.getSingleResult();
return count.intValue();
}
/**
* Returns the owner identified by {@code login}. If there is no owner with
* the specified login, {@code null} will be returned.
*
* @param login the login of an owner.
* @return the owner with the provided login or {@code null} if there is no
* owner with the specified login.
* @throws IllegalArgumentException if {@code login} is {@code null} or it
* does not identifies a valid owner.
*/
public Owner get(String login) {
return em.find(Owner.class, login);
}
/**
* Returns the complete list of owners.
*
* @return the complete list of owners.
*/
public List<Owner> list(int first, int pageSize) {
if (first < 0) throw new IllegalArgumentException("First can't be negative");
if (pageSize <= 0) throw new IllegalArgumentException("Page size must be positive");
return em.createQuery("SELECT o FROM Owner o", Owner.class)
.setFirstResult(first)
.setMaxResults(pageSize)
.getResultList();
}
/**
* Returns the list of owners that have a pet with the specified name.
*
* @param petName a pet's name.
* @return the list of owners that have a pet with the specified name. The
* list may be empty if any owner has a pet with the specified name.
* @throws IllegalArgumentException if {@code petName} is {@code null}.
*/
public List<Owner> findByPetName(String petName) {
if (petName == null)
throw new IllegalArgumentException("petName can't be null");
final String query = "SELECT o FROM Owner o JOIN o.pets p " +
"WHERE p.name = :petName";
return em.createQuery(query, Owner.class)
.setParameter("petName", petName)
.getResultList();
}
/**
* Creates a new owner. If the owner already has pets, they will be created
* too.
*
* @param owner a new owner to be stored.
* @return the persistent version of the owner created.
* @throws IllegalArgumentException if {@code owner} is {@code null}.
* @throws EntityExistsException if an owner with the same login already
* exists.
*/
public Owner create(Owner owner) {
if (owner == null)
throw new IllegalArgumentException("owner can't be null");
this.em.persist(owner);
return owner;
}
/**
* Updates a new owner. If the owner is not stored, it will be persisted.
*
* @param owner an owner to be updated.
* @return the updated owner.
* @throws IllegalArgumentException if {@code owner} is {@code null}.
*/
public Owner update(Owner owner) {
if (owner == null)
throw new IllegalArgumentException("owner can't be null");
return em.merge(owner);
}
/**
* Deletes an owner.
*
* @param login the login of the owner to be deleted.
* @throws IllegalArgumentException if {@code login} is {@code null} or if
* it does not identifies a valid owner.
*/
public void remove(String login) {
Owner owner = this.get(login);
em.remove(owner);
}
/**
* Returns the list of pets of an owner.
*
* @param login the login of the owner that owns the pets.
* @return the list of pets of an owner.
* @throws IllegalArgumentException if {@code login} is {@code null} or it
* does not identifies a valid owner.
*/
public List<Pet> getPets(String login, int first, int pageSize) {
if (first < 0) throw new IllegalArgumentException("First can't be negative");
if (pageSize <= 0) throw new IllegalArgumentException("Page size must be positive");
return em.createQuery("SELECT p FROM Owner o "
+ "JOIN o.pets p "
+ "WHERE "
+ "o.login = :login",
Pet.class)
.setFirstResult(first)
.setMaxResults(pageSize)
.setParameter("login", login)
.getResultList();
}
public List<Vaccination> getVaccinationsFromOwnPet(
IdentifierType identifierType,
String identifierValue,
int page,
int pageSize
){
requireNonNull(identifierType, "pet's identifier type can't be null");
requireNonNull(identifierValue, "pet's identifier value can't be null");
if (page < 0) {
throw new IllegalArgumentException("The page can't be negative");
}
if (pageSize <= 0) {
throw new IllegalArgumentException("The page size can't be negative or zero");
}
return em.createQuery(
"SELECT v FROM Owner o "
+ "JOIN o.pets p "
+ "JOIN p.identifiers i "
+ "JOIN p.vaccinations v "
+ "WHERE "
+ "o.login = :login AND "
+ "i.type = :identifierType AND "
+ "i.value = :identifierValue",
Vaccination.class)
.setParameter("login", currentUser.getName())
.setParameter("identifierType", identifierType)
.setParameter("identifierValue", identifierValue)
.setFirstResult(page * pageSize)
.setMaxResults(pageSize)
.getResultList();
}
@PersistenceContext
private EntityManager em;
@Inject
private Principal currentUser;
/**
* Counts all owners in the system.
*
* @return the total number of owners.
*/
public int countAll() {
Long count = em.createQuery("SELECT COUNT(o) FROM Owner o", Long.class)
.getSingleResult();
return count.intValue();
}
/**
* Returns the owner identified by {@code login}.
*
* @param login the login of an owner.
* @return the owner with the provided login or {@code null} if not found.
* @throws IllegalArgumentException if {@code login} is {@code null}.
*/
public Owner get(String login) {
return em.find(Owner.class, login);
}
/**
* Returns a paginated list of owners.
*
* @param first the starting index (0-based) of the first owner.
* @param pageSize the maximum number of owners to return.
* @return the list of owners in the specified page.
* @throws IllegalArgumentException if {@code first} is negative or {@code pageSize} is not positive.
*/
public List<Owner> list(int first, int pageSize) {
if (first < 0) throw new IllegalArgumentException("First can't be negative");
if (pageSize <= 0) throw new IllegalArgumentException("Page size must be positive");
return em.createQuery("SELECT o FROM Owner o", Owner.class)
.setFirstResult(first)
.setMaxResults(pageSize)
.getResultList();
}
/**
* Returns the list of owners that have a pet with the specified name.
*
* @param petName the name of the pet.
* @return the list of owners with a pet matching the name.
* @throws IllegalArgumentException if {@code petName} is {@code null}.
*/
public List<Owner> findByPetName(String petName) {
if (petName == null)
throw new IllegalArgumentException("petName can't be null");
final String query = "SELECT o FROM Owner o JOIN o.pets p WHERE p.name = :petName";
return em.createQuery(query, Owner.class)
.setParameter("petName", petName)
.getResultList();
}
/**
* Creates a new owner along with any pets associated.
*
* @param owner the owner to create.
* @return the persistent version of the created owner.
* @throws IllegalArgumentException if {@code owner} is {@code null}.
* @throws EntityExistsException if an owner with the same login already exists.
*/
public Owner create(Owner owner) {
if (owner == null)
throw new IllegalArgumentException("owner can't be null");
this.em.persist(owner);
return owner;
}
/**
* Updates an existing owner. If the owner does not exist, it will be persisted.
*
* @param owner the owner to update.
* @return the updated owner.
* @throws IllegalArgumentException if {@code owner} is {@code null}.
*/
public Owner update(Owner owner) {
if (owner == null)
throw new IllegalArgumentException("owner can't be null");
return em.merge(owner);
}
/**
* Deletes an owner by login.
*
* @param login the login of the owner to delete.
* @throws IllegalArgumentException if {@code login} is {@code null}.
*/
public void remove(String login) {
Owner owner = this.get(login);
em.remove(owner);
}
/**
* Returns a paginated list of pets of the specified owner.
*
* @param login the login of the owner.
* @param first the starting index (0-based).
* @param pageSize the maximum number of pets to return.
* @return the list of pets for the owner.
* @throws IllegalArgumentException if {@code login} is {@code null}, {@code first} is negative, or {@code pageSize} is not positive.
*/
public List<Pet> getPets(String login, int first, int pageSize) {
if (first < 0) throw new IllegalArgumentException("First can't be negative");
if (pageSize <= 0) throw new IllegalArgumentException("Page size must be positive");
return em.createQuery("SELECT p FROM Owner o JOIN o.pets p WHERE o.login = :login", Pet.class)
.setFirstResult(first)
.setMaxResults(pageSize)
.setParameter("login", login)
.getResultList();
}
/**
* Returns a paginated list of vaccinations for a pet of the current user, identified by an identifier type and value.
*
* @param identifierType the type of the pet's identifier.
* @param identifierValue the value of the pet's identifier.
* @param page the 0-based page index.
* @param pageSize the maximum number of vaccinations per page.
* @return the list of vaccinations.
* @throws NullPointerException if {@code identifierType} or {@code identifierValue} is {@code null}.
* @throws IllegalArgumentException if {@code page} is negative or {@code pageSize} is not positive.
*/
public List<Vaccination> getVaccinationsFromOwnPet(
IdentifierType identifierType,
String identifierValue,
int page,
int pageSize
) {
requireNonNull(identifierType, "pet's identifier type can't be null");
requireNonNull(identifierValue, "pet's identifier value can't be null");
if (page < 0) throw new IllegalArgumentException("The page can't be negative");
if (pageSize <= 0) throw new IllegalArgumentException("The page size can't be negative or zero");
return em.createQuery(
"SELECT v FROM Owner o " +
"JOIN o.pets p " +
"JOIN p.identifiers i " +
"JOIN p.vaccinations v " +
"WHERE o.login = :login AND i.type = :identifierType AND i.value = :identifierValue",
Vaccination.class)
.setParameter("login", currentUser.getName())
.setParameter("identifierType", identifierType)
.setParameter("identifierValue", identifierValue)
.setFirstResult(page * pageSize)
.setMaxResults(pageSize)
.getResultList();
}
}
......@@ -2,12 +2,10 @@ package es.uvigo.esei.xcs.service;
import static java.util.Objects.requireNonNull;
import java.io.Console;
import java.security.Principal;
import java.util.Date;
import java.util.List;
import javax.annotation.security.PermitAll;
import javax.annotation.security.RolesAllowed;
import javax.ejb.EJB;
import javax.ejb.EJBAccessException;
......@@ -19,242 +17,245 @@ import javax.persistence.PersistenceContext;
import es.uvigo.esei.xcs.domain.entities.AnimalType;
import es.uvigo.esei.xcs.domain.entities.Owner;
import es.uvigo.esei.xcs.domain.entities.Pet;
import es.uvigo.esei.xcs.domain.entities.Vaccination;
import es.uvigo.esei.xcs.domain.entities.Vaccine;
import es.uvigo.esei.xcs.domain.entities.Vet;
/**
* EJB for the Pets. Only owners have access to this class, and only to their
* own pets.
* EJB for managing Pets. Access is restricted to VET and OWNER roles.
* Owners can only access their own pets.
*
* @author Miguel Reboiro Jato
* @author Breixo Senra
*/
@Stateless
@RolesAllowed({"VET", "OWNER"})
public class PetService {
@Inject
private Principal currentUser;
@EJB
private EmailService emailService;
@PersistenceContext
private EntityManager em;
/**
* Returns a pet identified by the provided id. If an owner tries to access
* a pet that does now own, an {@link EJBAccessException} will be thrown.
*
* @param id the identified of a pet.
* @return a pet identified by the provided identifier or {@code null} if no
* pet exists with the provided identifier.
* @throws EJBAccessException if the current owner does not owns the pet.
*/
/*public Pet get(Long id) {
final Pet pet = em.find(Pet.class, id);
if (pet == null) {
return null;
} else if (pet.getOwner().getLogin().equals(this.currentOwner.getName())) {
return pet;
} else {
throw new EJBAccessException("Pet's owner is not the current principal");
}
}*/
public int countAll() {
Long count = em.createQuery("SELECT COUNT(p) FROM Pet p", Long.class)
.getSingleResult();
return count.intValue();
}
public Pet get(Long id) {
return em.find(Pet.class, id);
}
/*public List<Pet> getAll(int page, int pageSize) {
if (page < 0) {
throw new IllegalArgumentException("The page can't be negative");
}
if (pageSize <= 0) {
throw new IllegalArgumentException("The page size can't be negative or zero");
}
return em.createQuery("SELECT p FROM Pet p", Pet.class)
.setFirstResult(page * pageSize)
.setMaxResults(pageSize)
.getResultList();
}*/
public List<Pet> getAll(int first, int pageSize) {
if (first < 0) throw new IllegalArgumentException("First can't be negative");
if (pageSize <= 0) throw new IllegalArgumentException("Page size must be positive");
return em.createQuery("SELECT p FROM Pet p", Pet.class)
.setFirstResult(first) // no multiplicar por pageSize
.setMaxResults(pageSize)
.getResultList();
}
/**
* Returns the complete list of pets of the current owner.
*
* @return the complete list of pets of the current owner.
*/
public List<Pet> list(int page, int pageSize) {
if (page < 0) {
throw new IllegalArgumentException("The page can't be negative");
}
if (pageSize <= 0) {
throw new IllegalArgumentException("The page size can't be negative or zero");
}
return em.createQuery("SELECT p FROM Pet p WHERE p.owner.login = :login", Pet.class)
.setFirstResult(page * pageSize)
.setMaxResults(pageSize)
.setParameter("login", currentUser.getName())
.getResultList();
}
/**
* Creates a new pet owned by the current user.
*
* @param pet a new pet to be stored.
* @return the persistent version of the pet created.
* @throws EJBAccessException if the pet already has an owner and it is not
* the current user. If the pet has no owner, this exception will be never
* thrown.
* @throws IllegalArgumentException if a pet with the same identifier
* already exists.
*/
public Pet create(Pet pet) {
requireNonNull(pet, "Pet can't be null");
final Owner owner = em.find(Owner.class, currentUser.getName());
if (pet.getOwner() != null && !pet.getOwner().getLogin().equals(owner.getLogin())) {
throw new EJBAccessException("Pet's owner is not the current principal");
} else {
pet.setOwner(owner);
this.em.persist(pet);
return pet;
}
}
public Pet createPet(String name, AnimalType animal, Date birth) {
Owner owner = em.find(Owner.class, currentUser.getName());
Pet pet = new Pet(name, animal, birth, owner);
this.em.persist(pet);
return pet;
}
@Inject
private Principal currentUser;
@EJB
private EmailService emailService;
@PersistenceContext
private EntityManager em;
/**
* Counts all pets in the system.
*
* @return the total number of pets.
*/
public int countAll() {
Long count = em.createQuery("SELECT COUNT(p) FROM Pet p", Long.class)
.getSingleResult();
return count.intValue();
}
/**
* Returns a pet identified by the provided id.
*
* @param id the identifier of the pet.
* @return the pet or {@code null} if not found.
*/
public Pet get(Long id) {
return em.find(Pet.class, id);
}
/**
* Returns a paginated list of all pets (0-based first index).
*
* @param first the starting index of the first pet.
* @param pageSize the maximum number of pets to return.
* @return a list of pets.
* @throws IllegalArgumentException if {@code first} is negative or {@code pageSize} is not positive.
*/
public List<Pet> getAll(int first, int pageSize) {
if (first < 0) throw new IllegalArgumentException("First can't be negative");
if (pageSize <= 0) throw new IllegalArgumentException("Page size must be positive");
return em.createQuery("SELECT p FROM Pet p", Pet.class)
.setFirstResult(first)
.setMaxResults(pageSize)
.getResultList();
}
/**
* Returns a paginated list of pets belonging to the current owner (0-based page index).
*
* @param page the 0-based page index.
* @param pageSize the maximum number of pets per page.
* @return the list of pets of the current owner.
* @throws IllegalArgumentException if {@code page} is negative or {@code pageSize} is not positive.
*/
public List<Pet> list(int page, int pageSize) {
if (page < 0) throw new IllegalArgumentException("The page can't be negative");
if (pageSize <= 0) throw new IllegalArgumentException("The page size must be negative or zero");
return em.createQuery("SELECT p FROM Pet p WHERE p.owner.login = :login", Pet.class)
.setFirstResult(page * pageSize)
.setMaxResults(pageSize)
.setParameter("login", currentUser.getName())
.getResultList();
}
/**
* Creates a new pet for the current owner.
*
* @param pet the pet to create.
* @return the persistent version of the pet.
* @throws IllegalArgumentException if {@code pet} is null.
* @throws EJBAccessException if the pet already has an owner different from the current user.
*/
public Pet create(Pet pet) {
requireNonNull(pet, "Pet can't be null");
final Owner owner = em.find(Owner.class, currentUser.getName());
if (pet.getOwner() != null && !pet.getOwner().getLogin().equals(owner.getLogin())) {
throw new EJBAccessException("Pet's owner is not the current principal");
} else {
pet.setOwner(owner);
em.persist(pet);
return pet;
}
}
/**
* Convenience method to create a new pet with basic attributes.
*/
public Pet createPet(String name, AnimalType animal, Date birth) {
Owner owner = em.find(Owner.class, currentUser.getName());
Pet pet = new Pet(name, animal, birth, owner);
em.persist(pet);
return pet;
}
/**
* Updates an existing pet. If the pet does not exist, it will be persisted.
*
* @param pet the pet to update.
* @return the updated pet.
* @throws IllegalArgumentException if the pet has no owner.
* @throws EJBAccessException if the pet's owner is not the current user.
*/
public Pet update(Pet pet) {
if (pet.getOwner() == null)
throw new IllegalArgumentException("Pet must have an owner");
if (pet.getOwner().getLogin().equals(currentUser.getName())) {
return em.merge(pet);
} else {
throw new EJBAccessException("Pet's owner is not the current principal");
}
}
/**
* Deletes a pet.
*
* @param id the identifier of the pet.
* @throws IllegalArgumentException if no pet exists with the provided id.
* @throws EJBAccessException if the pet's owner is not the current user.
*/
public void remove(Long id) {
final Pet pet = this.get(id);
pet.setOwner(null);
em.remove(pet);
}
/**
* Returns a paginated list of vaccines for a given pet.
*
* @param id the identifier of the pet.
* @param page the 0-based page index.
* @param pageSize the maximum number of vaccines per page.
* @return the list of vaccines associated with the pet.
* @throws IllegalArgumentException if {@code page} is negative or {@code pageSize} is not positive.
*/
public List<Vaccine> getVaccinesByPetId(Long id, int page, int pageSize) {
if (page < 0) throw new IllegalArgumentException("The page can't be negative");
if (pageSize <= 0) throw new IllegalArgumentException("The page size can't be negative or zero");
return em.createQuery("SELECT v.pet FROM Vaccination v WHERE v.pet.id = :id", Vaccine.class)
.setFirstResult(page * pageSize)
.setMaxResults(pageSize)
.setParameter("id", id)
.getResultList();
}
/**
* Assigns the current vet to a pet.
*
* @param petId the identifier of the pet.
* @throws NullPointerException if {@code petId} is null.
* @throws IllegalArgumentException if the pet or vet does not exist.
*/
@RolesAllowed("VET")
public void assignVetToPet(Long petId) {
requireNonNull(petId, "Pet ID can't be null");
Pet pet = em.find(Pet.class, petId);
if (pet == null) throw new IllegalArgumentException("Pet not found");
Vet vet = em.find(Vet.class, currentUser.getName());
if (vet == null) throw new IllegalArgumentException("Vet not found");
pet.addVet(vet);
pet.internalAddVet(vet);
em.merge(pet);
}
/**
* Updates the information of a pet. If the pet is not stored, it will be
* created.
* Unassigns the current vet from a pet.
*
* @param pet a pet to be updated.
* @return the updated pet.
* @throws IllegalArgumentException if the pet has no owner.
* @throws EJBAccessException if the pet's owner is not the current user.
* @param petId the identifier of the pet.
* @throws NullPointerException if {@code petId} is null.
* @throws IllegalArgumentException if the pet or vet does not exist.
*/
public Pet update(Pet pet) {
if (pet.getOwner() == null)
throw new IllegalArgumentException("Pet must have an owner");
if (pet.getOwner().getLogin().equals(this.currentUser.getName())) {
return em.merge(pet);
} else {
throw new EJBAccessException("Pet's owner is not the current principal");
}
}
@RolesAllowed("VET")
public void unassignVetFromPet(Long petId) {
requireNonNull(petId, "Pet ID can't be null");
Pet pet = em.find(Pet.class, petId);
if (pet == null) throw new IllegalArgumentException("Pet not found");
Vet vet = em.find(Vet.class, currentUser.getName());
if (vet == null) throw new IllegalArgumentException("Vet not found");
pet.removeVet(vet);
pet.internalRemoveVet(vet);
em.merge(pet);
}
/**
* Deletes a pet.
* Returns the current authenticated user (Principal).
*
* @param id the identifier of the pet to be deleted.
* @throws IllegalArgumentException if there is no pet with the provided
* identifier.
* @throws EJBAccessException if the pet's owner is not the current user.
* @return the current Principal.
*/
public void remove(Long id) {
final Pet pet = this.get(id);
pet.setOwner(null);
em.remove(pet);
}
public List<Vaccine> getVaccinesByPetId(Long id, int page, int pageSize){
if (page < 0) {
throw new IllegalArgumentException("The page can't be negative");
}
if (pageSize <= 0) {
throw new IllegalArgumentException("The page size can't be negative or zero");
}
return em.createQuery("SELECT v.pet FROM Vaccination v WHERE v.pet.id = :id", Vaccine.class)
.setFirstResult(page * pageSize)
.setMaxResults(pageSize)
.getResultList();
}
@RolesAllowed("VET")
public void assignVetToPet(Long petId) {
requireNonNull(petId, "Pet ID can't be null");
//requireNonNull(vetLogin, "Vet login can't be null");
Pet pet = em.find(Pet.class, petId);
if (pet == null)
throw new IllegalArgumentException("Pet not found");
Vet vet = em.find(Vet.class, currentUser.getName());
if (vet == null)
throw new IllegalArgumentException("Vet not found");
pet.addVet(vet);
pet.internalAddVet(vet);
em.merge(pet);
}
@RolesAllowed("VET")
public void unassignVetFromPet(Long petId) {
requireNonNull(petId, "Pet ID can't be null");
//requireNonNull(vetLogin, "Vet login can't be null");
Pet pet = em.find(Pet.class, petId);
if (pet == null)
throw new IllegalArgumentException("Pet not found");
Vet vet = em.find(Vet.class, currentUser.getName());
if (vet == null)
throw new IllegalArgumentException("Vet not found");
pet.removeVet(vet);
pet.internalRemoveVet(vet);
em.merge(pet);
}
public Principal getCurrentUser() {
return this.currentUser;
}
@RolesAllowed("VET")
public boolean isAssignedToCurrentVet(Long petId) {
requireNonNull(petId, "Pet ID can't be null");
Long count = em.createQuery(
"SELECT COUNT(p) FROM Pet p JOIN p.vets v WHERE p.id = :petId AND v.login = :login",
Long.class
)
.setParameter("petId", petId)
.setParameter("login", currentUser.getName())
.getSingleResult();
return count > 0;
}
public Principal getCurrentUser() {
return this.currentUser;
}
/**
* Checks if the current vet is assigned to a given pet.
*
* @param petId the identifier of the pet.
* @return {@code true} if the current vet is assigned to the pet, {@code false} otherwise.
* @throws NullPointerException if {@code petId} is null.
*/
@RolesAllowed("VET")
public boolean isAssignedToCurrentVet(Long petId) {
requireNonNull(petId, "Pet ID can't be null");
Long count = em.createQuery(
"SELECT COUNT(p) FROM Pet p JOIN p.vets v WHERE p.id = :petId AND v.login = :login",
Long.class
)
.setParameter("petId", petId)
.setParameter("login", currentUser.getName())
.getSingleResult();
return count > 0;
}
}
......@@ -13,52 +13,80 @@ import javax.persistence.PersistenceContext;
import es.uvigo.esei.xcs.domain.entities.User;
/**
* EJB for managing users. Access is restricted to OWNER, ADMIN, and VET roles.
* Provides basic CRUD operations with paginated listing.
*
* @author Breixo Senra
*/
@Stateless
@RolesAllowed({"OWNER", "ADMIN", "VET"})
public class UserService {
@PersistenceContext
private EntityManager em;
@Inject
private Principal principal;
/**
* Returns the current user entity.
*
* @return the entity with the information of the current user.
*/
public User getCurrentUser() {
return this.em.find(User.class, this.principal.getName());
}
public User get(String login) {
return this.em.find(User.class, login);
}
public List<User> list(int page, int pageSize){
if (page < 0) {
throw new IllegalArgumentException("The page can't be negative");
}
if (pageSize <= 0) {
throw new IllegalArgumentException("The page size can't be negative or zero");
}
return this.em.createQuery("SELECT DISTINCT u FROM User u", User.class)
.setFirstResult(page * pageSize)
.setMaxResults(pageSize)
.getResultList();
}
public User create(User user) {
requireNonNull(user, "User can't be null");
this.em.persist(user);
return user;
}
public void remove(String login) {
User user = this.get(login);
this.em.remove(user);
}
@PersistenceContext
private EntityManager em;
@Inject
private Principal principal;
/**
* Returns the entity of the currently authenticated user.
*
* @return the current User entity.
*/
public User getCurrentUser() {
return this.em.find(User.class, this.principal.getName());
}
/**
* Returns a user by login.
*
* @param login the login of the user.
* @return the User entity, or {@code null} if not found.
*/
public User get(String login) {
return this.em.find(User.class, login);
}
/**
* Returns a paginated list of users (0-based page index).
*
* @param page the 0-based page index.
* @param pageSize the maximum number of users per page.
* @return a list of users.
* @throws IllegalArgumentException if {@code page} is negative or {@code pageSize} is not positive.
*/
public List<User> list(int page, int pageSize) {
if (page < 0) throw new IllegalArgumentException("The page can't be negative");
if (pageSize <= 0) throw new IllegalArgumentException("The page size can't be negative or zero");
return this.em.createQuery("SELECT DISTINCT u FROM User u", User.class)
.setFirstResult(page * pageSize)
.setMaxResults(pageSize)
.getResultList();
}
/**
* Persists a new user.
*
* @param user the User entity to create.
* @return the persisted User.
* @throws NullPointerException if {@code user} is null.
*/
public User create(User user) {
requireNonNull(user, "User can't be null");
this.em.persist(user);
return user;
}
/**
* Removes a user by login.
*
* @param login the login of the user to remove.
* @throws IllegalArgumentException if no user exists with the provided login.
*/
public void remove(String login) {
User user = this.get(login);
this.em.remove(user);
}
}
......@@ -4,11 +4,8 @@ import java.util.Date;
import static java.util.Objects.requireNonNull;
import java.security.Principal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.List;
import javax.annotation.security.PermitAll;
import javax.annotation.security.RolesAllowed;
import javax.ejb.EJB;
import javax.ejb.Stateless;
......@@ -22,120 +19,154 @@ import es.uvigo.esei.xcs.domain.entities.Pet;
import es.uvigo.esei.xcs.domain.entities.Vaccination;
import es.uvigo.esei.xcs.domain.entities.Vaccine;
/**
* EJB for managing Vaccinations. Access is restricted to VET role.
* Provides CRUD operations and rules to check if a pet can be vaccinated.
*
* @author Breixo Senra
*/
@Stateless
@RolesAllowed("VET")
//@PermitAll
public class VaccinationService {
@Inject
private Principal currentUser;
@PersistenceContext
EntityManager em;
@EJB
private EmailService emailService;
public Vaccination get(int vaccinationId) {
return em.find(Vaccination.class, vaccinationId);
}
public List<Vaccination> list(int page, int pageSize){
if (page < 0) {
throw new IllegalArgumentException("The page can't be negative");
}
if (pageSize <= 0) {
throw new IllegalArgumentException("The page size can't be negative or zero");
}
return em.createQuery("SELECT DISTINCT v FROM Vaccination v", Vaccination.class)
.setFirstResult(page * pageSize)
.setMaxResults(pageSize)
.getResultList();
}
public Vaccination create(Long petId, Long vaccineId, Date date) {
Pet pet = requireNonNull(em.find(Pet.class, petId), "Pet can't be null");
Vaccine vaccine = requireNonNull(em.find(Vaccine.class, vaccineId), "Vaccine can't be null");
if (!canVaccinate(petId, vaccineId, date)) {
throw new IllegalArgumentException("This vaccination cannot be created due to vaccine rules");
}
Vaccination vaccination = new Vaccination(pet, vaccine, date);
em.persist(vaccination);
emailService.send(
pet.getOwner().getLogin(),
pet.getName() + " ha sido vacunado con " + vaccine.getName(),
pet.getName() + " ha sido vacunado con " + vaccine.getName()
);
return vaccination;
}
public Vaccination updateDate(int vaccinationId, Date date) {
Vaccination vaccination = em.find(Vaccination.class, vaccinationId);
requireNonNull(vaccination, "Vaccination can't be null");
vaccination.setDate(date);
return em.merge(vaccination);
}
public void remove(int vaccinationId) {
Vaccination vaccination = this.get(vaccinationId);
requireNonNull(vaccination, "Vaccination can't be null");
em.remove(vaccination);
}
public Boolean canVaccinate(Long petId, Long vaccineId, Date date) {
Pet pet = em.find(Pet.class, petId);
Vaccine vaccine = em.find(Vaccine.class, vaccineId);
if (pet == null || vaccine == null) return false;
List<Vaccination> prevVaccinations = em.createQuery(
"SELECT v FROM Vaccination v WHERE v.pet.id = :petId AND v.vaccine.id = :vaccineId ORDER BY v.date DESC",
Vaccination.class)
.setParameter("petId", petId)
.setParameter("vaccineId", vaccineId)
.getResultList();
if (vaccine instanceof MultidoseVaccine) {
MultidoseVaccine multi = (MultidoseVaccine) vaccine;
Integer doses = multi.getDoses();
if (doses == null) return false;
return prevVaccinations.size() < doses;
} else if (vaccine instanceof PeriodicVaccine) {
PeriodicVaccine periodic = (PeriodicVaccine) vaccine;
if (prevVaccinations.isEmpty()) return true;
Vaccination last = prevVaccinations.get(0);
if (last.getDate() == null || date == null) return false;
long diffDays;
switch (periodic.getPeriodicType()) {
case YEARS:
diffDays = periodic.getPeriode() * 365L;
break;
case MONTHS:
diffDays = periodic.getPeriode() * 30L;
break;
case DAYS:
diffDays = periodic.getPeriode();
break;
default:
return false;
}
long diffMillis = date.getTime() - last.getDate().getTime();
return diffMillis >= diffDays * 24L * 60L * 60L * 1000L;
} else { // MONODOSE
return prevVaccinations.isEmpty();
}
}
@Inject
private Principal currentUser;
@PersistenceContext
private EntityManager em;
@EJB
private EmailService emailService;
/**
* Returns a vaccination by its ID.
*
* @param vaccinationId the identifier of the vaccination.
* @return the Vaccination entity, or {@code null} if not found.
*/
public Vaccination get(int vaccinationId) {
return em.find(Vaccination.class, vaccinationId);
}
/**
* Returns a paginated list of vaccinations (0-based page index).
*
* @param page the 0-based page index.
* @param pageSize the maximum number of vaccinations per page.
* @return a list of Vaccination entities.
* @throws IllegalArgumentException if {@code page} is negative or {@code pageSize} is not positive.
*/
public List<Vaccination> list(int page, int pageSize) {
if (page < 0) throw new IllegalArgumentException("The page can't be negative");
if (pageSize <= 0) throw new IllegalArgumentException("The page size can't be negative or zero");
return em.createQuery("SELECT DISTINCT v FROM Vaccination v", Vaccination.class)
.setFirstResult(page * pageSize)
.setMaxResults(pageSize)
.getResultList();
}
/**
* Creates a new vaccination for a pet with a given vaccine and date.
* Sends an email notification to the pet's owner.
*
* @param petId the identifier of the pet.
* @param vaccineId the identifier of the vaccine.
* @param date the date of the vaccination.
* @return the persisted Vaccination entity.
* @throws NullPointerException if {@code pet} or {@code vaccine} is null.
* @throws IllegalArgumentException if the vaccination cannot be created due to vaccine rules.
*/
public Vaccination create(Long petId, Long vaccineId, Date date) {
Pet pet = requireNonNull(em.find(Pet.class, petId), "Pet can't be null");
Vaccine vaccine = requireNonNull(em.find(Vaccine.class, vaccineId), "Vaccine can't be null");
if (!canVaccinate(petId, vaccineId, date)) {
throw new IllegalArgumentException("This vaccination cannot be created due to vaccine rules");
}
Vaccination vaccination = new Vaccination(pet, vaccine, date);
em.persist(vaccination);
emailService.send(
pet.getOwner().getLogin(),
pet.getName() + " ha sido vacunado con " + vaccine.getName(),
pet.getName() + " ha sido vacunado con " + vaccine.getName()
);
return vaccination;
}
/**
* Updates the date of an existing vaccination.
*
* @param vaccinationId the identifier of the vaccination.
* @param date the new date.
* @return the updated Vaccination entity.
* @throws NullPointerException if the vaccination does not exist.
*/
public Vaccination updateDate(int vaccinationId, Date date) {
Vaccination vaccination = em.find(Vaccination.class, vaccinationId);
requireNonNull(vaccination, "Vaccination can't be null");
vaccination.setDate(date);
return em.merge(vaccination);
}
/**
* Removes a vaccination by its ID.
*
* @param vaccinationId the identifier of the vaccination.
* @throws NullPointerException if the vaccination does not exist.
*/
public void remove(int vaccinationId) {
Vaccination vaccination = this.get(vaccinationId);
requireNonNull(vaccination, "Vaccination can't be null");
em.remove(vaccination);
}
/**
* Checks whether a pet can be vaccinated with a given vaccine on a given date.
*
* @param petId the identifier of the pet.
* @param vaccineId the identifier of the vaccine.
* @param date the intended vaccination date.
* @return {@code true} if vaccination is allowed, {@code false} otherwise.
*/
public Boolean canVaccinate(Long petId, Long vaccineId, Date date) {
Pet pet = em.find(Pet.class, petId);
Vaccine vaccine = em.find(Vaccine.class, vaccineId);
if (pet == null || vaccine == null) return false;
List<Vaccination> prevVaccinations = em.createQuery(
"SELECT v FROM Vaccination v WHERE v.pet.id = :petId AND v.vaccine.id = :vaccineId ORDER BY v.date DESC",
Vaccination.class)
.setParameter("petId", petId)
.setParameter("vaccineId", vaccineId)
.getResultList();
if (vaccine instanceof MultidoseVaccine) {
MultidoseVaccine multi = (MultidoseVaccine) vaccine;
Integer doses = multi.getDoses();
if (doses == null) return false;
return prevVaccinations.size() < doses;
} else if (vaccine instanceof PeriodicVaccine) {
PeriodicVaccine periodic = (PeriodicVaccine) vaccine;
if (prevVaccinations.isEmpty()) return true;
Vaccination last = prevVaccinations.get(0);
if (last.getDate() == null || date == null) return false;
long diffDays;
switch (periodic.getPeriodicType()) {
case YEARS: diffDays = periodic.getPeriode() * 365L; break;
case MONTHS: diffDays = periodic.getPeriode() * 30L; break;
case DAYS: diffDays = periodic.getPeriode(); break;
default: return false;
}
long diffMillis = date.getTime() - last.getDate().getTime();
return diffMillis >= diffDays * 24L * 60L * 60L * 1000L;
} else { // Monodose
return prevVaccinations.isEmpty();
}
}
}
package es.uvigo.esei.xcs.service;
import java.util.List;
import javax.annotation.security.PermitAll;
import javax.annotation.security.RolesAllowed;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
......@@ -17,114 +14,157 @@ import es.uvigo.esei.xcs.domain.entities.PeriodicVaccine;
import es.uvigo.esei.xcs.domain.entities.Pet;
import es.uvigo.esei.xcs.domain.entities.Vaccine;
/**
* EJB for managing Vaccines. Access is restricted to VET role.
* Provides CRUD operations, creation of different vaccine types,
* and retrieval of vaccinated pets with pagination.
*
* @author Breixo Senra
*/
@Stateless
@RolesAllowed("VET")
public class VaccineService {
@PersistenceContext
private EntityManager em;
public Vaccine get(Long id) {
final Vaccine vaccine = em.find(Vaccine.class, id);
return vaccine;
}
public List<Vaccine> list(int page, int pageSize){
if (page < 0) {
throw new IllegalArgumentException("The page can't be negative");
}
if (pageSize <= 0) {
throw new IllegalArgumentException("The page size can't be negative or zero");
}
return em.createQuery("SELECT v FROM Vaccine v", Vaccine.class)
.setFirstResult(page * pageSize)
.setMaxResults(pageSize)
.getResultList();
}
public Vaccine create(String name, String type, Integer doses, String periodicTypeString, Integer periode) {
switch(type) {
case "MONODOSE":
MonodoseVaccine monodoseVaccine = new MonodoseVaccine(name);
em.persist(monodoseVaccine);
return monodoseVaccine;
case "MULTIDOSE":
MultidoseVaccine multidoseVaccine = new MultidoseVaccine(name, doses);
em.persist(multidoseVaccine);
return multidoseVaccine;
case "PERIODIC":
PeriodicType periodicType = null;
if (periodicTypeString != null) {
periodicType = PeriodicType.valueOf(periodicTypeString);
}
PeriodicVaccine periodicVaccine = new PeriodicVaccine(name, periodicType, periode);
em.persist(periodicVaccine);
return periodicVaccine;
default: throw new IllegalArgumentException("Tipo de vacuna desconocido");
}
}
public Vaccine update(Vaccine vaccine) {
if (vaccine == null)
throw new IllegalArgumentException("vaccine can't be null");
return em.merge(vaccine);
}
public Vaccine updateName(Long id, String newName) {
if (id == null || newName == null || newName.trim().isEmpty())
throw new IllegalArgumentException("Id o nombre inválido");
Vaccine vaccine = em.find(Vaccine.class, id);
if (vaccine == null)
throw new IllegalArgumentException("Vacuna no encontrada");
vaccine.setName(newName);
return em.merge(vaccine);
}
public void remove(Long id) {
final Vaccine vaccine = this.get(id);
em.remove(vaccine);
}
public List<Pet> getVaccinatedPetsByVaccine(int vaccineId, int page, int pageSize){
if (page < 0) {
throw new IllegalArgumentException("The page can't be negative");
}
if (pageSize <= 0) {
throw new IllegalArgumentException("The page size can't be negative or zero");
}
return em.createQuery("SELECT v.pet FROM Vaccination v "
+ "WHERE v.vaccine.id = :vaccineId", Pet.class)
.setFirstResult(page * pageSize)
.setMaxResults(pageSize)
.setParameter("vaccineId", vaccineId)
.getResultList();
}
public List<Pet> getVaccinatedPetsByVaccineName(String vaccineName, int page, int pageSize){
if (page < 0) {
throw new IllegalArgumentException("The page can't be negative");
}
if (pageSize <= 0) {
throw new IllegalArgumentException("The page size can't be negative or zero");
}
return em.createQuery("SELECT v.pet FROM Vaccination v\r\n"
+ "WHERE v.vaccine.name = :vaccineName", Pet.class)
.setFirstResult(page * pageSize)
.setMaxResults(pageSize)
.setParameter("vaccineName", vaccineName)
.getResultList();
}
@PersistenceContext
private EntityManager em;
/**
* Returns a vaccine by its ID.
*
* @param id the identifier of the vaccine.
* @return the Vaccine entity, or {@code null} if not found.
*/
public Vaccine get(Long id) {
return em.find(Vaccine.class, id);
}
/**
* Returns a paginated list of vaccines (0-based page index).
*
* @param page the 0-based page index.
* @param pageSize the maximum number of vaccines per page.
* @return a list of Vaccine entities.
* @throws IllegalArgumentException if {@code page} is negative or {@code pageSize} is not positive.
*/
public List<Vaccine> list(int page, int pageSize) {
if (page < 0) throw new IllegalArgumentException("The page can't be negative");
if (pageSize <= 0) throw new IllegalArgumentException("The page size can't be negative or zero");
return em.createQuery("SELECT v FROM Vaccine v", Vaccine.class)
.setFirstResult(page * pageSize)
.setMaxResults(pageSize)
.getResultList();
}
/**
* Creates a vaccine of a specific type.
*
* @param name the name of the vaccine.
* @param type the type of vaccine ("MONODOSE", "MULTIDOSE", "PERIODIC").
* @param doses the number of doses (for MULTIDOSE).
* @param periodicTypeString the periodic type string (for PERIODIC).
* @param periode the period length (for PERIODIC).
* @return the created Vaccine entity.
* @throws IllegalArgumentException if the type is unknown.
*/
public Vaccine create(String name, String type, Integer doses, String periodicTypeString, Integer periode) {
switch(type) {
case "MONODOSE":
MonodoseVaccine monodoseVaccine = new MonodoseVaccine(name);
em.persist(monodoseVaccine);
return monodoseVaccine;
case "MULTIDOSE":
MultidoseVaccine multidoseVaccine = new MultidoseVaccine(name, doses);
em.persist(multidoseVaccine);
return multidoseVaccine;
case "PERIODIC":
PeriodicType periodicType = null;
if (periodicTypeString != null) {
periodicType = PeriodicType.valueOf(periodicTypeString);
}
PeriodicVaccine periodicVaccine = new PeriodicVaccine(name, periodicType, periode);
em.persist(periodicVaccine);
return periodicVaccine;
default: throw new IllegalArgumentException("Unknown vaccine type");
}
}
/**
* Updates an existing vaccine.
*
* @param vaccine the Vaccine entity to update.
* @return the updated Vaccine entity.
* @throws IllegalArgumentException if {@code vaccine} is null.
*/
public Vaccine update(Vaccine vaccine) {
if (vaccine == null) throw new IllegalArgumentException("vaccine can't be null");
return em.merge(vaccine);
}
/**
* Updates the name of a vaccine.
*
* @param id the identifier of the vaccine.
* @param newName the new name.
* @return the updated Vaccine entity.
* @throws IllegalArgumentException if the id or name is invalid or the vaccine is not found.
*/
public Vaccine updateName(Long id, String newName) {
if (id == null || newName == null || newName.trim().isEmpty())
throw new IllegalArgumentException("Id or name invalid");
Vaccine vaccine = em.find(Vaccine.class, id);
if (vaccine == null) throw new IllegalArgumentException("Vaccine not found");
vaccine.setName(newName);
return em.merge(vaccine);
}
/**
* Removes a vaccine by its ID.
*
* @param id the identifier of the vaccine.
*/
public void remove(Long id) {
final Vaccine vaccine = this.get(id);
em.remove(vaccine);
}
/**
* Returns a paginated list of pets vaccinated with a specific vaccine ID.
*
* @param vaccineId the identifier of the vaccine.
* @param page the 0-based page index.
* @param pageSize the maximum number of pets per page.
* @return a list of Pet entities.
*/
public List<Pet> getVaccinatedPetsByVaccine(int vaccineId, int page, int pageSize) {
if (page < 0) throw new IllegalArgumentException("The page can't be negative");
if (pageSize <= 0) throw new IllegalArgumentException("The page size can't be negative or zero");
return em.createQuery("SELECT v.pet FROM Vaccination v WHERE v.vaccine.id = :vaccineId", Pet.class)
.setFirstResult(page * pageSize)
.setMaxResults(pageSize)
.setParameter("vaccineId", vaccineId)
.getResultList();
}
/**
* Returns a paginated list of pets vaccinated with a specific vaccine name.
*
* @param vaccineName the name of the vaccine.
* @param page the 0-based page index.
* @param pageSize the maximum number of pets per page.
* @return a list of Pet entities.
*/
public List<Pet> getVaccinatedPetsByVaccineName(String vaccineName, int page, int pageSize) {
if (page < 0) throw new IllegalArgumentException("The page can't be negative");
if (pageSize <= 0) throw new IllegalArgumentException("The page size can't be negative or zero");
return em.createQuery("SELECT v.pet FROM Vaccination v WHERE v.vaccine.name = :vaccineName", Pet.class)
.setFirstResult(page * pageSize)
.setMaxResults(pageSize)
.setParameter("vaccineName", vaccineName)
.getResultList();
}
}
......@@ -5,7 +5,6 @@ import static java.util.Objects.requireNonNull;
import java.security.Principal;
import java.util.List;
import javax.annotation.security.PermitAll;
import javax.annotation.security.RolesAllowed;
import javax.ejb.Stateless;
import javax.inject.Inject;
......@@ -17,113 +16,155 @@ import es.uvigo.esei.xcs.domain.entities.Pet;
import es.uvigo.esei.xcs.domain.entities.Vaccination;
import es.uvigo.esei.xcs.domain.entities.Vet;
/**
* EJB for managing Vet entities. Access is restricted to VET role.
* Provides CRUD operations, retrieval of assigned pets and vaccinations
* with pagination support.
*
* @author Breixo Senra
*/
@Stateless
@RolesAllowed("VET")
public class VetService {
@Inject
private Principal currentUser;
@PersistenceContext
EntityManager em;
public int countPets() {
Long count = em.createQuery(
"SELECT COUNT(p) FROM Vet v JOIN v.pets p WHERE v.login = :login", Long.class)
.setParameter("login", currentUser.getName())
.getSingleResult();
return count.intValue();
}
public Vet get(String login) {
return em.find(Vet.class, login);
}
public List<Vet> list(){
return em.createQuery("SELECT DISTINCT v FROM Vet v", Vet.class)
.getResultList();
}
public List<Vet> findByPetName(String petName, int page, int pageSize){
requireNonNull(petName, "Pet's name can't be null");
if (page < 0) {
throw new IllegalArgumentException("The page can't be negative");
}
if (pageSize <= 0) {
throw new IllegalArgumentException("The page size can't be negative or zero");
}
return this.em.createQuery("SELECT DISTINCT v FROM Vet v JOIN v.pets p "
+ "WHERE p.name = :petName", Vet.class)
.setFirstResult(page * pageSize)
.setMaxResults(pageSize)
.setParameter("petName", petName)
.getResultList();
}
public Vet create(Vet vet) {
requireNonNull(Vet.class, "Vet can't be null");
em.persist(vet);
return vet;
}
public Vet update(Vet vet) {
requireNonNull(Vet.class, "Vet can't be null");
return em.merge(vet);
}
public void remove(String login) {
em.remove(this.get(login));
}
public List<Pet> getPets(int first , int pageSize) {
if (first < 0) throw new IllegalArgumentException("First can't be negative");
if (pageSize <= 0) throw new IllegalArgumentException("Page size must be positive");
return this.em.createQuery("SELECT DISTINCT p FROM Vet v JOIN v.pets p "
+ "WHERE v.login = :login", Pet.class)
.setFirstResult(first)
.setMaxResults(pageSize)
.setParameter("login", currentUser.getName())
.getResultList();
}
public List<Vaccination> getVaccinationsFromOwnPet(
IdentifierType identifierType,
String identifierValue,
int page,
int pageSize
){
requireNonNull(identifierType, "pet's identifier type can't be null");
requireNonNull(identifierValue, "pet's identifier value can't be null");
if (page < 0) {
throw new IllegalArgumentException("The page can't be negative");
}
if (pageSize <= 0) {
throw new IllegalArgumentException("The page size can't be negative or zero");
}
return em.createQuery(
"SELECT v FROM Vet vet "
+ "JOIN vet.pets p "
+ "JOIN p.identifiers i "
+ "JOIN p.vaccinations v "
+ "WHERE "
+ "vet.login = :login AND "
+ "i.type = :identifierType AND "
+ "i.value = :identifierValue",
Vaccination.class)
.setParameter("login", currentUser.getName())
.setParameter("identifierType", identifierType)
.setParameter("identifierValue", identifierValue)
.setFirstResult(page * pageSize)
.setMaxResults(pageSize)
.getResultList();
}
@Inject
private Principal currentUser;
@PersistenceContext
private EntityManager em;
/**
* Counts the number of pets assigned to the current vet.
*
* @return the number of pets assigned to the current vet.
*/
public int countPets() {
Long count = em.createQuery(
"SELECT COUNT(p) FROM Vet v JOIN v.pets p WHERE v.login = :login", Long.class)
.setParameter("login", currentUser.getName())
.getSingleResult();
return count.intValue();
}
/**
* Returns a vet by login.
*
* @param login the login of the vet.
* @return the Vet entity, or {@code null} if not found.
*/
public Vet get(String login) {
return em.find(Vet.class, login);
}
/**
* Returns a list of all vets.
*
* @return a list of Vet entities.
*/
public List<Vet> list() {
return em.createQuery("SELECT DISTINCT v FROM Vet v", Vet.class)
.getResultList();
}
/**
* Returns a paginated list of vets that have a pet with the given name.
*
* @param petName the name of the pet.
* @param page the 0-based page index.
* @param pageSize the maximum number of vets per page.
* @return a list of Vet entities.
*/
public List<Vet> findByPetName(String petName, int page, int pageSize) {
requireNonNull(petName, "Pet's name can't be null");
if (page < 0) throw new IllegalArgumentException("The page can't be negative");
if (pageSize <= 0) throw new IllegalArgumentException("The page size can't be negative or zero");
return em.createQuery("SELECT DISTINCT v FROM Vet v JOIN v.pets p WHERE p.name = :petName", Vet.class)
.setFirstResult(page * pageSize)
.setMaxResults(pageSize)
.setParameter("petName", petName)
.getResultList();
}
/**
* Creates a new vet.
*
* @param vet the Vet entity to create.
* @return the persisted Vet entity.
*/
public Vet create(Vet vet) {
requireNonNull(vet, "Vet can't be null");
em.persist(vet);
return vet;
}
/**
* Updates an existing vet.
*
* @param vet the Vet entity to update.
* @return the updated Vet entity.
*/
public Vet update(Vet vet) {
requireNonNull(vet, "Vet can't be null");
return em.merge(vet);
}
/**
* Removes a vet by login.
*
* @param login the login of the vet to remove.
*/
public void remove(String login) {
em.remove(this.get(login));
}
/**
* Returns a paginated list of pets assigned to the current vet.
*
* @param first the index of the first pet (0-based).
* @param pageSize the maximum number of pets per page.
* @return a list of Pet entities.
*/
public List<Pet> getPets(int first, int pageSize) {
if (first < 0) throw new IllegalArgumentException("First can't be negative");
if (pageSize <= 0) throw new IllegalArgumentException("Page size must be positive");
return em.createQuery("SELECT DISTINCT p FROM Vet v JOIN v.pets p WHERE v.login = :login", Pet.class)
.setFirstResult(first)
.setMaxResults(pageSize)
.setParameter("login", currentUser.getName())
.getResultList();
}
/**
* Returns a paginated list of vaccinations for a pet owned by the current vet.
*
* @param identifierType the type of the pet's identifier.
* @param identifierValue the value of the pet's identifier.
* @param page the 0-based page index.
* @param pageSize the maximum number of vaccinations per page.
* @return a list of Vaccination entities.
*/
public List<Vaccination> getVaccinationsFromOwnPet(
IdentifierType identifierType,
String identifierValue,
int page,
int pageSize) {
requireNonNull(identifierType, "Pet's identifier type can't be null");
requireNonNull(identifierValue, "Pet's identifier value can't be null");
if (page < 0) throw new IllegalArgumentException("The page can't be negative");
if (pageSize <= 0) throw new IllegalArgumentException("The page size can't be negative or zero");
return em.createQuery(
"SELECT v FROM Vet vet JOIN vet.pets p JOIN p.identifiers i JOIN p.vaccinations v " +
"WHERE vet.login = :login AND i.type = :identifierType AND i.value = :identifierValue",
Vaccination.class)
.setParameter("login", currentUser.getName())
.setParameter("identifierType", identifierType)
.setParameter("identifierValue", identifierValue)
.setFirstResult(page * pageSize)
.setMaxResults(pageSize)
.getResultList();
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment