US10: Add a method to the owner API that allows the user to get the horses owned by a specific owner

This commit is contained in:
Ivaylo Ivanov 2020-03-25 15:12:02 +01:00
parent 9b1f7bcfa0
commit 89e5f7980a
7 changed files with 117 additions and 2 deletions

View File

@ -1,6 +1,8 @@
package at.ac.tuwien.sepm.assignment.individual.endpoint; 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.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.endpoint.mapper.OwnerMapper;
import at.ac.tuwien.sepm.assignment.individual.entity.Owner; 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.exception.NotFoundException;
@ -28,11 +30,13 @@ public class OwnerEndpoint {
private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
private final OwnerService ownerService; private final OwnerService ownerService;
private final OwnerMapper ownerMapper; private final OwnerMapper ownerMapper;
private final HorseMapper horseMapper;
@Autowired @Autowired
public OwnerEndpoint(OwnerService ownerService, OwnerMapper ownerMapper) { public OwnerEndpoint(OwnerService ownerService, OwnerMapper ownerMapper, HorseMapper horseMapper) {
this.ownerService = ownerService; this.ownerService = ownerService;
this.ownerMapper = ownerMapper; this.ownerMapper = ownerMapper;
this.horseMapper = horseMapper;
} }
@GetMapping(value = "/{id}") @GetMapping(value = "/{id}")
@ -65,6 +69,18 @@ public class OwnerEndpoint {
} }
} }
@GetMapping(value="/{id}/horses")
@ResponseStatus(HttpStatus.OK)
public List<HorseDto> 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 @PostMapping
@ResponseStatus(HttpStatus.CREATED) @ResponseStatus(HttpStatus.CREATED)
public OwnerDto addOwner(@RequestBody OwnerDto owner) { public OwnerDto addOwner(@RequestBody OwnerDto owner) {

View File

@ -1,5 +1,6 @@
package at.ac.tuwien.sepm.assignment.individual.persistence; 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.entity.Owner;
import at.ac.tuwien.sepm.assignment.individual.exception.NotFoundException; import at.ac.tuwien.sepm.assignment.individual.exception.NotFoundException;
import org.springframework.dao.DataAccessException; import org.springframework.dao.DataAccessException;
@ -32,6 +33,14 @@ public interface OwnerDao {
*/ */
List<Owner> getFiltered(Map<String, String> filters) throws NotFoundException; List<Owner> getFiltered(Map<String, String> 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<Horse> getOwnedHorses(Long id) throws NotFoundException;
/** /**
* @param owner that specifies the owner to add * @param owner that specifies the owner to add
* @return the newly created owner * @return the newly created owner

View File

@ -94,6 +94,18 @@ public class OwnerJdbcDao implements OwnerDao {
return owners; return owners;
} }
@Override
public List<Horse> 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<Horse> 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 @Override
public Owner addOwner(Owner owner) { public Owner addOwner(Owner owner) {
LOGGER.trace("Add owner {}", owner); LOGGER.trace("Add owner {}", owner);

View File

@ -1,5 +1,6 @@
package at.ac.tuwien.sepm.assignment.individual.service; 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.entity.Owner;
import at.ac.tuwien.sepm.assignment.individual.exception.NotFoundException; import at.ac.tuwien.sepm.assignment.individual.exception.NotFoundException;
import at.ac.tuwien.sepm.assignment.individual.util.ValidationException; import at.ac.tuwien.sepm.assignment.individual.util.ValidationException;
@ -33,6 +34,14 @@ public interface OwnerService {
*/ */
List<Owner> getFiltered(Map<String, String> filters) throws NotFoundException, ValidationException; List<Owner> getFiltered(Map<String, String> 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<Horse> getOwnedHorses(Long id) throws NotFoundException;
/** /**
* @param owner to create * @param owner to create
* @return the new owner * @return the new owner

View File

@ -1,5 +1,6 @@
package at.ac.tuwien.sepm.assignment.individual.service.impl; 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.entity.Owner;
import at.ac.tuwien.sepm.assignment.individual.exception.NotFoundException; import at.ac.tuwien.sepm.assignment.individual.exception.NotFoundException;
import at.ac.tuwien.sepm.assignment.individual.persistence.OwnerDao; import at.ac.tuwien.sepm.assignment.individual.persistence.OwnerDao;
@ -49,6 +50,12 @@ public class SimpleOwnerService implements OwnerService {
return ownerDao.getFiltered(filters); return ownerDao.getFiltered(filters);
} }
@Override
public List<Horse> getOwnedHorses(Long id) throws NotFoundException {
LOGGER.trace("getOwnedHorses({})", id);
return ownerDao.getOwnedHorses(id);
}
@Override @Override
public Owner addOwner(Owner owner) throws ValidationException, DataAccessException { public Owner addOwner(Owner owner) throws ValidationException, DataAccessException {
LOGGER.trace("addOwner({})", owner); LOGGER.trace("addOwner({})", owner);

View File

@ -118,6 +118,46 @@ public class OwnerEndpointTest {
.exchange(builder.toUriString(), HttpMethod.GET, null, new ParameterizedTypeReference<OwnerDto>() {})); .exchange(builder.toUriString(), HttpMethod.GET, null, new ParameterizedTypeReference<OwnerDto>() {}));
} }
@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<OwnerDto> 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<HorseDto> savedHorse = REST_TEMPLATE.exchange(BASE_URL + port + HORSE_URL, HttpMethod.POST, request, HorseDto.class);
ResponseEntity<List<HorseDto>> allHorses = REST_TEMPLATE
.exchange(BASE_URL + port + OWNER_URL + "/" + savedOwner.getId() + "/horses", HttpMethod.GET, null, new ParameterizedTypeReference<List<HorseDto>>() {});
// 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<OwnerDto> 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<List<HorseDto>>() {}));
}
@Test @Test
@DisplayName("Adding a new owner with the correct parameters will return HTTP 201 and the new OwnerDto") @DisplayName("Adding a new owner with the correct parameters will return HTTP 201 and the new OwnerDto")
public void addingNewOwner_correctParameters_shouldReturnStatus201AndOwner() { public void addingNewOwner_correctParameters_shouldReturnStatus201AndOwner() {
@ -157,7 +197,7 @@ public class OwnerEndpointTest {
} }
@Test @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() { public void deletingOwner_existingNoOwnersOwned_shouldReturnStatus204() {
// Create the owner // Create the owner
OwnerDto newOwner = new OwnerDto("Chad"); OwnerDto newOwner = new OwnerDto("Chad");

View File

@ -77,6 +77,28 @@ public abstract class OwnerDaoTestBase {
() -> ownerDao.findOneById(0L)); () -> 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 @Test
@DisplayName("Adding a new owner with the correct parameters should return the owner") @DisplayName("Adding a new owner with the correct parameters should return the owner")
public void addingNewOwner_correctParameters_shouldReturnOwner() { public void addingNewOwner_correctParameters_shouldReturnOwner() {