diff --git a/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/endpoint/OwnerEndpoint.java b/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/endpoint/OwnerEndpoint.java index ae7a46b..0e6678f 100644 --- a/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/endpoint/OwnerEndpoint.java +++ b/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/endpoint/OwnerEndpoint.java @@ -1,6 +1,8 @@ package at.ac.tuwien.sepm.assignment.individual.endpoint; +import at.ac.tuwien.sepm.assignment.individual.endpoint.dto.HorseDto; import at.ac.tuwien.sepm.assignment.individual.endpoint.dto.OwnerDto; +import at.ac.tuwien.sepm.assignment.individual.endpoint.mapper.HorseMapper; import at.ac.tuwien.sepm.assignment.individual.endpoint.mapper.OwnerMapper; import at.ac.tuwien.sepm.assignment.individual.entity.Owner; import at.ac.tuwien.sepm.assignment.individual.exception.NotFoundException; @@ -28,11 +30,13 @@ public class OwnerEndpoint { private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); private final OwnerService ownerService; private final OwnerMapper ownerMapper; + private final HorseMapper horseMapper; @Autowired - public OwnerEndpoint(OwnerService ownerService, OwnerMapper ownerMapper) { + public OwnerEndpoint(OwnerService ownerService, OwnerMapper ownerMapper, HorseMapper horseMapper) { this.ownerService = ownerService; this.ownerMapper = ownerMapper; + this.horseMapper = horseMapper; } @GetMapping(value = "/{id}") @@ -65,6 +69,18 @@ public class OwnerEndpoint { } } + @GetMapping(value="/{id}/horses") + @ResponseStatus(HttpStatus.OK) + public List getOwnedHorses(@PathVariable("id") Long id) { + LOGGER.info("GET " + BASE_URL + "/{}/horses", id); + try { + return horseMapper.entityListToDtoList(ownerService.getOwnedHorses(id)); + } catch (NotFoundException e) { + LOGGER.error(e.getMessage()); + throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Either the owner does not exist or has no horses assigned"); + } + } + @PostMapping @ResponseStatus(HttpStatus.CREATED) public OwnerDto addOwner(@RequestBody OwnerDto owner) { diff --git a/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/persistence/OwnerDao.java b/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/persistence/OwnerDao.java index cc93184..11b00dd 100644 --- a/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/persistence/OwnerDao.java +++ b/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/persistence/OwnerDao.java @@ -1,5 +1,6 @@ package at.ac.tuwien.sepm.assignment.individual.persistence; +import at.ac.tuwien.sepm.assignment.individual.entity.Horse; import at.ac.tuwien.sepm.assignment.individual.entity.Owner; import at.ac.tuwien.sepm.assignment.individual.exception.NotFoundException; import org.springframework.dao.DataAccessException; @@ -32,6 +33,14 @@ public interface OwnerDao { */ List getFiltered(Map filters) throws NotFoundException; + /** + * @param id of the owner whose horses the database should obtain + * @return a list of all horses that the specified owner owns + * @throws NotFoundException will be thrown if the owner owns no horses or if the owner could not be found + * @throws DataAccessException will be thrown if something goes wrong during the database access + */ + List getOwnedHorses(Long id) throws NotFoundException; + /** * @param owner that specifies the owner to add * @return the newly created owner diff --git a/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/persistence/impl/OwnerJdbcDao.java b/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/persistence/impl/OwnerJdbcDao.java index 744b074..a0f0b42 100644 --- a/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/persistence/impl/OwnerJdbcDao.java +++ b/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/persistence/impl/OwnerJdbcDao.java @@ -94,6 +94,18 @@ public class OwnerJdbcDao implements OwnerDao { return owners; } + @Override + public List getOwnedHorses(Long id) throws NotFoundException { + LOGGER.trace("Get all horses for owner with id " + id); + final String sql = "SELECT * FROM " + HORSE_TABLE_NAME + " WHERE owner_id=?"; + + List horses = jdbcTemplate.query(sql, new Object[] {id}, BeanPropertyRowMapper.newInstance(Horse.class)); + + if (horses.isEmpty()) throw new NotFoundException("Could not find horses for owner with id " + id); + + return horses; + } + @Override public Owner addOwner(Owner owner) { LOGGER.trace("Add owner {}", owner); diff --git a/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/service/OwnerService.java b/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/service/OwnerService.java index 3b765da..112817e 100644 --- a/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/service/OwnerService.java +++ b/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/service/OwnerService.java @@ -1,5 +1,6 @@ package at.ac.tuwien.sepm.assignment.individual.service; +import at.ac.tuwien.sepm.assignment.individual.entity.Horse; import at.ac.tuwien.sepm.assignment.individual.entity.Owner; import at.ac.tuwien.sepm.assignment.individual.exception.NotFoundException; import at.ac.tuwien.sepm.assignment.individual.util.ValidationException; @@ -33,6 +34,14 @@ public interface OwnerService { */ List getFiltered(Map filters) throws NotFoundException, ValidationException; + /** + * @param id of the owner whose horses the database should obtain + * @return a list of all horses that the specified owner owns + * @throws NotFoundException will be thrown if the owner owns no horses or if the owner could not be found + * @throws DataAccessException will be thrown if something goes wrong during the database access + */ + List getOwnedHorses(Long id) throws NotFoundException; + /** * @param owner to create * @return the new owner diff --git a/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/service/impl/SimpleOwnerService.java b/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/service/impl/SimpleOwnerService.java index f6c4195..e4ebe8b 100644 --- a/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/service/impl/SimpleOwnerService.java +++ b/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/service/impl/SimpleOwnerService.java @@ -1,5 +1,6 @@ package at.ac.tuwien.sepm.assignment.individual.service.impl; +import at.ac.tuwien.sepm.assignment.individual.entity.Horse; import at.ac.tuwien.sepm.assignment.individual.entity.Owner; import at.ac.tuwien.sepm.assignment.individual.exception.NotFoundException; import at.ac.tuwien.sepm.assignment.individual.persistence.OwnerDao; @@ -49,6 +50,12 @@ public class SimpleOwnerService implements OwnerService { return ownerDao.getFiltered(filters); } + @Override + public List getOwnedHorses(Long id) throws NotFoundException { + LOGGER.trace("getOwnedHorses({})", id); + return ownerDao.getOwnedHorses(id); + } + @Override public Owner addOwner(Owner owner) throws ValidationException, DataAccessException { LOGGER.trace("addOwner({})", owner); diff --git a/backend/src/test/java/at/ac/tuwien/sepm/assignment/individual/integration/OwnerEndpointTest.java b/backend/src/test/java/at/ac/tuwien/sepm/assignment/individual/integration/OwnerEndpointTest.java index 163d8aa..9df6938 100644 --- a/backend/src/test/java/at/ac/tuwien/sepm/assignment/individual/integration/OwnerEndpointTest.java +++ b/backend/src/test/java/at/ac/tuwien/sepm/assignment/individual/integration/OwnerEndpointTest.java @@ -118,6 +118,46 @@ public class OwnerEndpointTest { .exchange(builder.toUriString(), HttpMethod.GET, null, new ParameterizedTypeReference() {})); } + @Test + @DisplayName("Getting horses of an owner with one horse should return HTTP 200 and the horse") + public void gettingHorsesOfOwner_oneHorseAssigned_shouldReturnStatus200AndHorse() { + // Create the owner + OwnerDto newOwner = new OwnerDto("Chad"); + + HttpEntity request = new HttpEntity<>(newOwner); + OwnerDto savedOwner = REST_TEMPLATE + .exchange(BASE_URL + port + OWNER_URL, HttpMethod.POST, request, OwnerDto.class).getBody(); + + // Create the horse + HorseDto newHorse = new HorseDto("Zephyr", "Nice horse", (short) 4, Date.valueOf("2020-01-01"), ERace.APPALOOSA, "files/test.png", savedOwner.getId()); + + request = new HttpEntity(newHorse); + ResponseEntity savedHorse = REST_TEMPLATE.exchange(BASE_URL + port + HORSE_URL, HttpMethod.POST, request, HorseDto.class); + + ResponseEntity> allHorses = REST_TEMPLATE + .exchange(BASE_URL + port + OWNER_URL + "/" + savedOwner.getId() + "/horses", HttpMethod.GET, null, new ParameterizedTypeReference>() {}); + + // Temporary, until db mapping is fixed + savedHorse.getBody().setOwner(null); + + assertEquals(allHorses.getStatusCode(), HttpStatus.OK); + assertTrue(allHorses.getBody().contains(savedHorse.getBody())); + } + + @Test + @DisplayName("Getting horses of an owner without horses should return HTTP 404") + public void gettingHorsesOfOwner_noHorsesAssigned_shouldReturnStatus404() { + // Create the owner + OwnerDto newOwner = new OwnerDto("Chad"); + + HttpEntity request = new HttpEntity<>(newOwner); + OwnerDto savedOwner = REST_TEMPLATE + .exchange(BASE_URL + port + OWNER_URL, HttpMethod.POST, request, OwnerDto.class).getBody(); + + assertThrows(HttpClientErrorException.NotFound.class, () -> REST_TEMPLATE + .exchange(BASE_URL + port + OWNER_URL + "/" + savedOwner.getId() + "/horses", HttpMethod.GET, null, new ParameterizedTypeReference>() {})); + } + @Test @DisplayName("Adding a new owner with the correct parameters will return HTTP 201 and the new OwnerDto") public void addingNewOwner_correctParameters_shouldReturnStatus201AndOwner() { @@ -157,7 +197,7 @@ public class OwnerEndpointTest { } @Test - @DisplayName("Deleting an existing owner without owners will return HTTP 204") + @DisplayName("Deleting an existing owner without horses will return HTTP 204") public void deletingOwner_existingNoOwnersOwned_shouldReturnStatus204() { // Create the owner OwnerDto newOwner = new OwnerDto("Chad"); diff --git a/backend/src/test/java/at/ac/tuwien/sepm/assignment/individual/unit/persistence/OwnerDaoTestBase.java b/backend/src/test/java/at/ac/tuwien/sepm/assignment/individual/unit/persistence/OwnerDaoTestBase.java index 02d7a4d..520cb43 100644 --- a/backend/src/test/java/at/ac/tuwien/sepm/assignment/individual/unit/persistence/OwnerDaoTestBase.java +++ b/backend/src/test/java/at/ac/tuwien/sepm/assignment/individual/unit/persistence/OwnerDaoTestBase.java @@ -77,6 +77,28 @@ public abstract class OwnerDaoTestBase { () -> ownerDao.findOneById(0L)); } + @Test + @DisplayName("Getting horses of owner with one horse should return the Horse") + public void gettingHorsesOfOwner_oneHorseAssigned_shouldReturnHorse() { + Owner savedOwner = ownerDao.addOwner(new Owner("Brad")); + + // Create the horse + Horse newHorse = new Horse("Zephyr", "Nice horse", (short) 4, Date.valueOf("2020-01-01"), ERace.APPALOOSA, "files/test.png", savedOwner.getId()); + Horse savedHorse = horseDao.addHorse(newHorse); + + // Temporary, until the database mapping is fixed + savedHorse.setOwner(null); + assertTrue(ownerDao.getOwnedHorses(savedOwner.getId()).contains(newHorse)); + } + + @Test + @DisplayName("Getting horses of owner without horses should throw NotFoundException") + public void gettingHorsesOfOwner_noHorsesAssigned_shouldThrowNotFound() { + Owner savedOwner = ownerDao.addOwner(new Owner("Brad")); + + assertThrows(NotFoundException.class, () -> ownerDao.getOwnedHorses(savedOwner.getId())); + } + @Test @DisplayName("Adding a new owner with the correct parameters should return the owner") public void addingNewOwner_correctParameters_shouldReturnOwner() {