From 0f5f0d2267573b4a7a17f250238ce5e82a54d9d2 Mon Sep 17 00:00:00 2001 From: Ivaylo Ivanov Date: Thu, 19 Mar 2020 18:06:52 +0100 Subject: [PATCH] US02: Make it possible to upload a picture through the API --- .../individual/endpoint/HorseEndpoint.java | 21 ++++++- .../individual/endpoint/dto/HorseDto.java | 17 +++++- .../endpoint/mapper/HorseMapper.java | 4 +- .../assignment/individual/entity/Horse.java | 20 ++++++- .../individual/persistence/FileDao.java | 13 +++++ .../persistence/impl/HorseFileDao.java | 52 ++++++++++++++++++ .../persistence/impl/HorseJdbcDao.java | 20 ++++--- .../individual/service/HorseService.java | 9 +++ .../service/impl/SimpleHorseService.java | 23 ++++++-- .../assignment/individual/util/Validator.java | 14 +++++ backend/src/main/resources/application.yml | 7 +++ .../src/main/resources/sql/createSchema.sql | 1 + .../integration/HorseEndpointTest.java | 41 ++++++++++++-- .../unit/persistence/HorseDaoTestBase.java | 4 +- .../unit/persistence/HorseFileDaoTest.java | 50 +++++++++++++++++ .../unit/service/HorseServiceTest.java | 4 +- .../individual/integration/horse.jpg | Bin 0 -> 54902 bytes 17 files changed, 269 insertions(+), 31 deletions(-) create mode 100644 backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/persistence/FileDao.java create mode 100644 backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/persistence/impl/HorseFileDao.java create mode 100644 backend/src/test/java/at/ac/tuwien/sepm/assignment/individual/unit/persistence/HorseFileDaoTest.java create mode 100644 backend/src/test/resources/at/ac/tuwien/sepm/assignment/individual/integration/horse.jpg diff --git a/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/endpoint/HorseEndpoint.java b/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/endpoint/HorseEndpoint.java index d3d8404..ce2931b 100644 --- a/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/endpoint/HorseEndpoint.java +++ b/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/endpoint/HorseEndpoint.java @@ -12,8 +12,10 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataAccessException; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; import org.springframework.web.server.ResponseStatusException; +import java.io.IOException; import java.lang.invoke.MethodHandles; @RestController @@ -50,7 +52,7 @@ public class HorseEndpoint { return horseMapper.entityToDto(horseService.addHorse(horseEntity)); } catch (ValidationException e) { LOGGER.error(e.getMessage()); - throw new ResponseStatusException(HttpStatus.UNPROCESSABLE_ENTITY, + throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Error during adding new horse: " + e.getMessage(), e); } catch (DataAccessException e) { LOGGER.error(e.getMessage()); @@ -58,4 +60,21 @@ public class HorseEndpoint { "Something went wrong during the communication with the database", e); } } + + @PostMapping(value = "/upload") + @ResponseStatus(HttpStatus.CREATED) + public void addImage(@RequestParam("file") MultipartFile image) { + LOGGER.info("POST " + BASE_URL + "/upload"); + try { + horseService.saveImage(image); + } catch(ValidationException e) { + LOGGER.error(e.getMessage()); + throw new ResponseStatusException(HttpStatus.BAD_REQUEST, + "Unsupported file type provided. Supported file types are jpg and png."); + } catch (IOException e) { + LOGGER.error(e.getMessage()); + throw new ResponseStatusException(HttpStatus.UNPROCESSABLE_ENTITY, + "Something went wrong while uploading the file"); + } + } } diff --git a/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/endpoint/dto/HorseDto.java b/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/endpoint/dto/HorseDto.java index 892feb3..5a39018 100644 --- a/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/endpoint/dto/HorseDto.java +++ b/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/endpoint/dto/HorseDto.java @@ -14,26 +14,29 @@ public class HorseDto extends BaseDto { private short score; private ERace race; private Date birthday; + private String imagePath; private Long owner; public HorseDto() {} - public HorseDto(String name, String description, short score, Date birthday, ERace race, Long owner) { + public HorseDto(String name, String description, short score, Date birthday, ERace race, String imagePath, Long owner) { this.name = name; this.description = description; this.score = score; this.birthday = birthday; this.race = race; + this.imagePath = imagePath; this.owner = owner; } - public HorseDto(Long id, String name, String description, short score, Date birthday, ERace race, LocalDateTime created, LocalDateTime updated, Long owner) { + public HorseDto(Long id, String name, String description, short score, Date birthday, ERace race, String imagePath, LocalDateTime created, LocalDateTime updated, Long owner) { super(id, created, updated); this.name = name; this.description = description; this.score = score; this.birthday = birthday; this.race = race; + this.imagePath = imagePath; this.owner = owner; } @@ -77,6 +80,14 @@ public class HorseDto extends BaseDto { this.race = race; } + public String getImagePath() { + return imagePath; + } + + public void setImagePath(String imagePath) { + this.imagePath = imagePath; + } + public Long getOwner() { return owner; } @@ -96,6 +107,7 @@ public class HorseDto extends BaseDto { Objects.equals(score, h.score) && Objects.equals(birthday, h.birthday) && Objects.equals(race, h.race) && + Objects.equals(imagePath, h.imagePath) && Objects.equals(owner, h.owner); } @@ -113,6 +125,7 @@ public class HorseDto extends BaseDto { ", score='" + score + '\'' + ", birthday='" + df.format(birthday) + '\'' + ", race='" + race + '\'' + + ", imagePath='" + imagePath + '\'' + ", owner_id='" + owner + '\''; } diff --git a/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/endpoint/mapper/HorseMapper.java b/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/endpoint/mapper/HorseMapper.java index f4470ac..2b15116 100644 --- a/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/endpoint/mapper/HorseMapper.java +++ b/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/endpoint/mapper/HorseMapper.java @@ -8,10 +8,10 @@ import org.springframework.stereotype.Component; @Component public class HorseMapper { public HorseDto entityToDto(Horse horse) { - return new HorseDto(horse.getId(), horse.getName(), horse.getDescription(), horse.getScore(), horse.getBirthday(), horse.getRace(), horse.getCreatedAt(), horse.getUpdatedAt(), horse.getOwner()); + return new HorseDto(horse.getId(), horse.getName(), horse.getDescription(), horse.getScore(), horse.getBirthday(), horse.getRace(), horse.getImagePath(), horse.getCreatedAt(), horse.getUpdatedAt(), horse.getOwner()); } public Horse dtoToEntity(HorseDto horse) { - return new Horse(horse.getId(), horse.getName(), horse.getDescription(), horse.getScore(), horse.getBirthday(), horse.getRace(), horse.getOwner()); + return new Horse(horse.getId(), horse.getName(), horse.getDescription(), horse.getScore(), horse.getBirthday(), horse.getRace(), horse.getImagePath(), horse.getOwner()); } } diff --git a/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/entity/Horse.java b/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/entity/Horse.java index 25868d3..c05113a 100644 --- a/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/entity/Horse.java +++ b/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/entity/Horse.java @@ -13,36 +13,40 @@ public class Horse extends BaseEntity { private short score; private ERace race; private Date birthday; + private String imagePath; private Long owner; public Horse() {} - public Horse(String name, String description, short score, Date birthday, ERace race,Long owner) { + public Horse(String name, String description, short score, Date birthday, ERace race, String imagePath, Long owner) { this.name = name; this.description = description; this.score = score; this.birthday = birthday; this.race = race; + this.imagePath = imagePath; this.owner = owner; } - public Horse(Long id, String name, String description, short score, Date birthday, ERace race, Long owner) { + public Horse(Long id, String name, String description, short score, Date birthday, ERace race, String imagePath, Long owner) { super(id); this.name = name; this.description = description; this.score = score; this.birthday = birthday; this.race = race; + this.imagePath = imagePath; this.owner = owner; } - public Horse(Long id, String name, String description, short score, Date birthday, ERace race, Long owner, LocalDateTime created, LocalDateTime updated) { + public Horse(Long id, String name, String description, short score, Date birthday, ERace race, String imagePath, Long owner, LocalDateTime created, LocalDateTime updated) { super(id, created, updated); this.name = name; this.description = description; this.score = score; this.birthday = birthday; this.race = race; + this.imagePath = imagePath; this.owner = owner; } @@ -86,6 +90,14 @@ public class Horse extends BaseEntity { this.race = race; } + public String getImagePath() { + return imagePath; + } + + public void setImagePath(String imagePath) { + this.imagePath = imagePath; + } + public Long getOwner() { return owner; } @@ -105,6 +117,7 @@ public class Horse extends BaseEntity { Objects.equals(score, h.score) && Objects.equals(birthday, h.birthday) && Objects.equals(race, h.race) && + Objects.equals(imagePath, h.imagePath) && Objects.equals(owner, h.owner); } @@ -122,6 +135,7 @@ public class Horse extends BaseEntity { ", score='" + score + '\'' + ", birthday='" + df.format(birthday) + '\'' + ", race='" + race + '\'' + + ", imagePath='" + imagePath + '\'' + ", owner='" + owner + '\''; } diff --git a/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/persistence/FileDao.java b/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/persistence/FileDao.java new file mode 100644 index 0000000..d32bbc1 --- /dev/null +++ b/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/persistence/FileDao.java @@ -0,0 +1,13 @@ +package at.ac.tuwien.sepm.assignment.individual.persistence; + +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; + +public interface FileDao { + /** + * Used for saving files on the local file system + * @param file file to save + */ + void save(MultipartFile file) throws IOException; +} diff --git a/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/persistence/impl/HorseFileDao.java b/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/persistence/impl/HorseFileDao.java new file mode 100644 index 0000000..dae30de --- /dev/null +++ b/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/persistence/impl/HorseFileDao.java @@ -0,0 +1,52 @@ +package at.ac.tuwien.sepm.assignment.individual.persistence.impl; + +import at.ac.tuwien.sepm.assignment.individual.persistence.FileDao; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Repository; +import org.springframework.web.multipart.MultipartFile; + +import java.io.File; +import java.io.IOException; +import java.lang.invoke.MethodHandles; +import java.nio.file.FileSystemException; +import java.nio.file.Files; + +@Repository +public class HorseFileDao implements FileDao { + @Value("${spring.upload.path}") + private String FILE_BASE_PATH; + private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); + public HorseFileDao() {}; + + @Override + public void save(MultipartFile file) throws IOException { + if(file == null || file.getOriginalFilename() == null || file.isEmpty()) + throw new IOException("Cannot save an empty file"); + + if(!file.getContentType().equals("image/jpeg") && !file.getContentType().equals("image/png")) + throw new IOException("Unsupported file type"); + + String fileName = file.getOriginalFilename(); + LOGGER.trace("Writing file to " + FILE_BASE_PATH + fileName); + + try { + // Create directory if it doesn't exist + File uploadDir = new File(FILE_BASE_PATH); + if(!uploadDir.exists()) + uploadDir.mkdir(); + + // Save the file + if(uploadDir.exists()) { + File target = new File(FILE_BASE_PATH + fileName); + Files.write(target.toPath(), file.getBytes()); + } else { + throw new FileSystemException("Base upload directory " + FILE_BASE_PATH + " does not exist"); + } + } catch (Exception e) { + LOGGER.error(e.getMessage()); + throw new IOException("Saving the file failed"); + } + } +} diff --git a/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/persistence/impl/HorseJdbcDao.java b/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/persistence/impl/HorseJdbcDao.java index 6df00f3..b37ae2a 100644 --- a/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/persistence/impl/HorseJdbcDao.java +++ b/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/persistence/impl/HorseJdbcDao.java @@ -50,11 +50,11 @@ public class HorseJdbcDao implements HorseDao { @Override public Horse addHorse(Horse horse) throws DataAccessException { LOGGER.trace("Add horse {}", horse.toString()); - String sql = "INSERT INTO " + TABLE_NAME + "(name, description, score, birthday, race, owner_id, created_at, updated_at) VALUES(?, ?, ?, ?, ?, ?, ?, ?)"; + String sql = "INSERT INTO " + TABLE_NAME + "(name, description, score, birthday, race, image_path, owner_id, created_at, updated_at) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?)"; try { // Check if the constraints are violated - if(horse.getName() == null || horse.getScore() == 0 || horse.getBirthday() == null || horse.getRace() == null) + if(horse.getName() == null || horse.getScore() == 0 || horse.getBirthday() == null || horse.getRace() == null || horse.getImagePath() == null) throw new DataIntegrityViolationException("Required parameters for horse missing"); LocalDateTime currentTime = LocalDateTime.now(); @@ -74,13 +74,15 @@ public class HorseJdbcDao implements HorseDao { ps.setDate(4, horse.getBirthday()); ps.setString(5, horse.getRace().toString()); // Convert to string to be able to save in DB - if(horse.getOwner() == null || horse.getOwner() == 0) - ps.setNull(6, Types.NULL); - else - ps.setObject(6, horse.getOwner()); + ps.setString(6, horse.getImagePath()); - ps.setObject(7, horse.getCreatedAt()); - ps.setObject(8, horse.getUpdatedAt()); + if(horse.getOwner() == null || horse.getOwner() == 0) + ps.setNull(7, Types.NULL); + else + ps.setObject(7, horse.getOwner()); + + ps.setObject(8, horse.getCreatedAt()); + ps.setObject(9, horse.getUpdatedAt()); return ps; }, keyHolder); @@ -98,6 +100,7 @@ public class HorseJdbcDao implements HorseDao { } } + private Horse mapRow(ResultSet resultSet, int i) throws SQLException { final Horse horse = new Horse(); horse.setId(resultSet.getLong("id")); @@ -107,6 +110,7 @@ public class HorseJdbcDao implements HorseDao { horse.setBirthday(resultSet.getDate("birthday")); horse.setRace(ERace.valueOf(resultSet.getString("race"))); // Convert to Enum for usage in objects horse.setOwner(resultSet.getLong("owner_id")); + horse.setImagePath(resultSet.getString("image_path")); horse.setCreatedAt(resultSet.getTimestamp("created_at").toLocalDateTime()); horse.setUpdatedAt(resultSet.getTimestamp("updated_at").toLocalDateTime()); return horse; diff --git a/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/service/HorseService.java b/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/service/HorseService.java index 524a7d5..208753a 100644 --- a/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/service/HorseService.java +++ b/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/service/HorseService.java @@ -2,6 +2,9 @@ package at.ac.tuwien.sepm.assignment.individual.service; import at.ac.tuwien.sepm.assignment.individual.entity.Horse; import at.ac.tuwien.sepm.assignment.individual.exception.NotFoundException; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; public interface HorseService { /** @@ -19,4 +22,10 @@ public interface HorseService { * @throws NotFoundException will be thrown if the horse could not be found in the system. */ Horse addHorse(Horse horse); + + /** + * @param img image to upload + * @throws IOException will be thrown if something goes wrong with saving the file + */ + void saveImage(MultipartFile img) throws IOException; } diff --git a/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/service/impl/SimpleHorseService.java b/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/service/impl/SimpleHorseService.java index 6bd057b..96bd78b 100644 --- a/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/service/impl/SimpleHorseService.java +++ b/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/service/impl/SimpleHorseService.java @@ -1,6 +1,7 @@ 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.persistence.FileDao; import at.ac.tuwien.sepm.assignment.individual.persistence.HorseDao; import at.ac.tuwien.sepm.assignment.individual.service.HorseService; import at.ac.tuwien.sepm.assignment.individual.util.ValidationException; @@ -10,32 +11,42 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataAccessException; import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; +import java.io.IOException; import java.lang.invoke.MethodHandles; -import java.text.SimpleDateFormat; @Service public class SimpleHorseService implements HorseService { private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); - private final HorseDao horseDao; + private final HorseDao horseJdbcDao; + private final FileDao horseFileDao; private final Validator validator; @Autowired - public SimpleHorseService(HorseDao horseDao, Validator validator) { - this.horseDao = horseDao; + public SimpleHorseService(HorseDao horseJdbcDao, FileDao horseFileDao, Validator validator) { + this.horseJdbcDao = horseJdbcDao; + this.horseFileDao = horseFileDao; this.validator = validator; } @Override public Horse findOneById(Long id) { LOGGER.trace("findOneById({})", id); - return horseDao.findOneById(id); + return horseJdbcDao.findOneById(id); } @Override public Horse addHorse(Horse horse) throws ValidationException, DataAccessException { this.validator.validateNewHorse(horse); LOGGER.trace("addHorse({})", horse.toString()); - return horseDao.addHorse(horse); + return horseJdbcDao.addHorse(horse); + } + + @Override + public void saveImage(MultipartFile img) throws ValidationException, IOException { + this.validator.validateHorseImage(img); + LOGGER.trace("saveImage({})", img.getName()); + horseFileDao.save(img); } } diff --git a/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/util/Validator.java b/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/util/Validator.java index 523c960..45e1432 100644 --- a/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/util/Validator.java +++ b/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/util/Validator.java @@ -3,6 +3,7 @@ package at.ac.tuwien.sepm.assignment.individual.util; import at.ac.tuwien.sepm.assignment.individual.entity.Horse; import at.ac.tuwien.sepm.assignment.individual.entity.Owner; import org.springframework.stereotype.Component; +import org.springframework.web.multipart.MultipartFile; @Component public class Validator { @@ -22,5 +23,18 @@ public class Validator { if(horse.getScore() > 5 || horse.getScore() < 1) { throw new ValidationException("Score value " + horse.getScore() + " not allowed. The score must be an integer between 1 and 5"); } + if(!horse.getImagePath().endsWith(".png") && !horse.getImagePath().endsWith(".jpg") && !horse.getImagePath().endsWith(".jpeg")) { + throw new ValidationException("Unsupported file type supplied. Supported file types are jpg and png"); + } } + + public void validateHorseImage(MultipartFile image) throws ValidationException { + if(image == null || image.getContentType() == null || image.isEmpty()) { + throw new ValidationException("No image supplied"); + } + if(!image.getContentType().equals("image/png") && !image.getContentType().equals("image/jpeg")) { + throw new ValidationException("Unsupported file type supplied: " + image.getContentType()); + } + } + } diff --git a/backend/src/main/resources/application.yml b/backend/src/main/resources/application.yml index ea8dc3e..1081fcb 100644 --- a/backend/src/main/resources/application.yml +++ b/backend/src/main/resources/application.yml @@ -15,5 +15,12 @@ spring: h2: console: enabled: true + upload: + path: /tmp/uploads/ + servlet: + multipart: + enabled: true + max-file-size: 10MB + max-request-size: 15MB server: port: 8080 diff --git a/backend/src/main/resources/sql/createSchema.sql b/backend/src/main/resources/sql/createSchema.sql index 4b1d5b2..727d61a 100644 --- a/backend/src/main/resources/sql/createSchema.sql +++ b/backend/src/main/resources/sql/createSchema.sql @@ -17,6 +17,7 @@ CREATE TABLE IF NOT EXISTS horse score TINYINT NOT NULL CHECK(score >= 1 AND score <= 5), birthday DATE NOT NULL, race RACE NOT NULL, + image_path VARCHAR(255) NOT NULL, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL ); diff --git a/backend/src/test/java/at/ac/tuwien/sepm/assignment/individual/integration/HorseEndpointTest.java b/backend/src/test/java/at/ac/tuwien/sepm/assignment/individual/integration/HorseEndpointTest.java index 973b5a7..ddcea3c 100644 --- a/backend/src/test/java/at/ac/tuwien/sepm/assignment/individual/integration/HorseEndpointTest.java +++ b/backend/src/test/java/at/ac/tuwien/sepm/assignment/individual/integration/HorseEndpointTest.java @@ -6,20 +6,25 @@ import at.ac.tuwien.sepm.assignment.individual.endpoint.dto.HorseDto; import at.ac.tuwien.sepm.assignment.individual.enums.ERace; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.web.server.LocalServerPort; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpMethod; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; +import org.springframework.core.io.ClassPathResource; +import org.springframework.http.*; import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.event.annotation.AfterTestMethod; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; import org.springframework.web.client.RestTemplate; +import java.io.File; import java.sql.Date; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @ActiveProfiles("test") public class HorseEndpointTest { + @Value("${spring.upload.path}") + private String FILE_BASE_PATH; private static final RestTemplate REST_TEMPLATE = new RestTemplate(); private static final String BASE_URL = "http://localhost:"; private static final String HORSE_URL = "/horses"; @@ -31,7 +36,7 @@ public class HorseEndpointTest { @DisplayName("Adding a new horse with the correct parameters will return HTTP 201 and the new HorseDto") public void addingNewHorse_correctParameters_shouldReturnStatus201AndHorse() { String birthday = "2020-01-01"; - HorseDto newHorse = new HorseDto("Zephyr", "Nice horse", (short) 4, Date.valueOf(birthday), ERace.APPALOOSA, null); + HorseDto newHorse = new HorseDto("Zephyr", "Nice horse", (short) 4, Date.valueOf(birthday), ERace.APPALOOSA, "files/test.png", null); HttpEntity request = new HttpEntity<>(newHorse); ResponseEntity response = REST_TEMPLATE @@ -43,6 +48,32 @@ public class HorseEndpointTest { assertEquals(newHorse.getDescription(), response.getBody().getDescription()); assertEquals(newHorse.getScore(), response.getBody().getScore()); assertEquals(newHorse.getBirthday().toString(), response.getBody().getBirthday().toString()); + assertEquals(newHorse.getImagePath(), response.getBody().getImagePath()); assertEquals(newHorse.getOwner(), response.getBody().getOwner()); } + + @Test + @DisplayName("Uploading an image in the correct format will return HTTP 201") + public void addingNewImage_correctFormat_shouldReturnStatus201() { + try { + // More information: + // https://www.baeldung.com/spring-rest-template-multipart-upload + // https://github.com/spring-guides/gs-uploading-files/blob/master/complete/src/test/java/com/example/uploadingfiles/FileUploadIntegrationTests.java + + // Get the file + ClassPathResource image = new ClassPathResource("horse.jpg", getClass()); + + // Set the body + MultiValueMap body = new LinkedMultiValueMap<>(); + body.add("file", image); + + // Create the HTTP Entity + HttpEntity> request = new HttpEntity<>(body); + + ResponseEntity response = REST_TEMPLATE.postForEntity(BASE_URL + port + HORSE_URL + "/upload", request, String.class); + assertEquals(HttpStatus.CREATED, response.getStatusCode()); + } finally { + new File(FILE_BASE_PATH + "horse.jpg").delete(); + } + } } diff --git a/backend/src/test/java/at/ac/tuwien/sepm/assignment/individual/unit/persistence/HorseDaoTestBase.java b/backend/src/test/java/at/ac/tuwien/sepm/assignment/individual/unit/persistence/HorseDaoTestBase.java index 27e99f5..2b66366 100644 --- a/backend/src/test/java/at/ac/tuwien/sepm/assignment/individual/unit/persistence/HorseDaoTestBase.java +++ b/backend/src/test/java/at/ac/tuwien/sepm/assignment/individual/unit/persistence/HorseDaoTestBase.java @@ -21,7 +21,7 @@ public abstract class HorseDaoTestBase { @DisplayName("Adding a new horse with the correct parameters should return the horse") public void addingNewHorse_correctParameters_shouldReturnHorse() { String birthday = "2020-01-01"; - Horse newHorse = new Horse("Zephyr", "Nice horse", (short) 4, Date.valueOf(birthday), ERace.APPALOOSA, null); + Horse newHorse = new Horse("Zephyr", "Nice horse", (short) 4, Date.valueOf(birthday), ERace.APPALOOSA, "files/test.png", null); Horse savedHorse = horseDao.addHorse(newHorse); assertEquals(newHorse, savedHorse); } @@ -30,7 +30,7 @@ public abstract class HorseDaoTestBase { @DisplayName("Adding a new horse with the incorrect parameters should throw DataAccessException") public void addingNewHorse_incorrectParameters_shouldThrowDataAccess() { String birthday = "2020-01-01"; - Horse newHorse = new Horse("Zephyr", "Nice horse", (short) 80, Date.valueOf(birthday), null, null); + Horse newHorse = new Horse("Zephyr", "Nice horse", (short) 80, Date.valueOf(birthday), null, null, null); assertThrows(DataAccessException.class, () -> horseDao.addHorse(newHorse)); } diff --git a/backend/src/test/java/at/ac/tuwien/sepm/assignment/individual/unit/persistence/HorseFileDaoTest.java b/backend/src/test/java/at/ac/tuwien/sepm/assignment/individual/unit/persistence/HorseFileDaoTest.java new file mode 100644 index 0000000..f07b9eb --- /dev/null +++ b/backend/src/test/java/at/ac/tuwien/sepm/assignment/individual/unit/persistence/HorseFileDaoTest.java @@ -0,0 +1,50 @@ +package at.ac.tuwien.sepm.assignment.individual.unit.persistence; + +import static org.junit.jupiter.api.Assertions.*; + +import at.ac.tuwien.sepm.assignment.individual.persistence.impl.HorseFileDao; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.mock.web.MockMultipartFile; +import org.springframework.test.context.ActiveProfiles; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; + +@SpringBootTest +@ActiveProfiles("test") +public class HorseFileDaoTest { + @Value("${spring.upload.path}") + private String FILE_BASE_PATH; + @Autowired + HorseFileDao horseFileDao; + + @Test + @DisplayName("Creating a file with the correct type should result in a saved file") + public void savingFile_correctType_shouldWriteFile() throws FileNotFoundException, IOException { + File image = new File("src/test/resources/at/ac/tuwien/sepm/assignment/individual/integration/horse.jpg"); + horseFileDao.save(new MockMultipartFile("file", image.getName(), MediaType.IMAGE_JPEG_VALUE, new FileInputStream(image))); + File savedImage = new File(FILE_BASE_PATH + "horse.jpg"); + assertTrue(savedImage.exists()); + assertTrue(savedImage.isFile()); + } + + @Test + @DisplayName("Creating a file with the correct type should result in a saved file") + public void savingFile_incorrectType_shouldThrowIOException() throws FileNotFoundException, IOException { + File image = new File("src/test/resources/at/ac/tuwien/sepm/assignment/individual/integration/horse.jpg"); + assertThrows(IOException.class, () -> horseFileDao.save(new MockMultipartFile("file", image.getName(), MediaType.TEXT_HTML_VALUE, new FileInputStream(image)))); + } + + @AfterEach + public void cleanup() { + new File(FILE_BASE_PATH + "horse.jpg").delete(); + } +} diff --git a/backend/src/test/java/at/ac/tuwien/sepm/assignment/individual/unit/service/HorseServiceTest.java b/backend/src/test/java/at/ac/tuwien/sepm/assignment/individual/unit/service/HorseServiceTest.java index a229d05..11409de 100644 --- a/backend/src/test/java/at/ac/tuwien/sepm/assignment/individual/unit/service/HorseServiceTest.java +++ b/backend/src/test/java/at/ac/tuwien/sepm/assignment/individual/unit/service/HorseServiceTest.java @@ -29,7 +29,7 @@ public class HorseServiceTest { @DisplayName("Adding a new horse with the correct parameters will return the new horse") public void addingNewHorse_correctParameters_shouldReturnHorse() { String birthday = "2020-01-01"; - Horse newHorse = new Horse("Zephyr", "Nice horse", (short) 4, Date.valueOf(birthday), ERace.APPALOOSA, null); + Horse newHorse = new Horse("Zephyr", "Nice horse", (short) 4, Date.valueOf(birthday), ERace.APPALOOSA, "files/test.png", null); Horse savedHorse = horseService.addHorse(newHorse); assertEquals(newHorse, savedHorse); } @@ -38,7 +38,7 @@ public class HorseServiceTest { @DisplayName("Adding a new horse with the incorrect parameters will throw a ValidationException") public void addingNewHorse_incorrectParameters_shouldThrowValidation() { String birthday = "2020-01-01"; - Horse newHorse = new Horse("Zephyr", "Nice horse", (short) 80, Date.valueOf(birthday), null, null); + Horse newHorse = new Horse("Zephyr", "Nice horse", (short) 80, Date.valueOf(birthday), null, null, null); assertThrows(ValidationException.class, () -> horseService.addHorse(newHorse)); } } diff --git a/backend/src/test/resources/at/ac/tuwien/sepm/assignment/individual/integration/horse.jpg b/backend/src/test/resources/at/ac/tuwien/sepm/assignment/individual/integration/horse.jpg new file mode 100644 index 0000000000000000000000000000000000000000..32110aca9c997f777be6262a55b46b3429a618a7 GIT binary patch literal 54902 zcmb5VganVH!*`FPkk036KBJVLwx5LiG^ zfQ?&3T!deok6(cQzmHtHe&Yu9O=<=j8U}uLW_JGn-{Ic}D*Bt3Z(k|BatTOvnf}rh z`b+=%sW_>qE?>FyUvvL2T)ske>FTxXHz=9xl#Ktv|7B6qOP8-)z4mXO>h_gORF~N5n&9V_QS$f%4_kBBW(ZrX08RO)X%qG9PL$Kfwb||in zN=&f2D)I(kMmuat)Wgzr#yNf{|In~HgTI6wCD0+NV>zO;xaiG5N2yy053=wM zV0MJ?#>+c(?1AX@7I884XCKOI-`>3M>&R?t21UQJl9vqySXg9(Y(ZdMvocV|S9^~; zHI*qz@g;ZQt9y0(_)Bw#GNEsQh=IX}LCwgf#;~wgRzU_O*|FCOX7x(2fplL4eC_I) z^D;OJJWxj(*5b*8hQ`)?WbS0K5(5Xx-B*R9{mVzU!aMmAMnx5ee>>aM^xKk_zK&N_ zUtb5+f-j^}E1oZRE^3^dxx=j>O|u_qb8T?$R`dhB*oNfP42p0)?RlJ_%ghUFxPE!N30hD3 z@^~_BybGcgb5C^0_N+qu^pvqtBbi#5+%#dc zqUCy4@h}Ken{aLVQPn3AV_xmN7`+c}LA~M@G(t8DH~lKlzrtJ#UBTDrl;P`42qit zPfrd6mrg~BMHN}>oEiOkq6ABMFIXyWBOh1|5U)eqnyr9hJ5Y#XM8iTha2*+LCT;<$ z(iO}OHQUu3i5tP|vaI79bp0Lduy+NQ0jIB{jqh57G8S%sS#Id=s<-kFv-ZZh)+&ni zbxdRJ^s-?cui|U&ebO9|5YtSzl-fN(uULy#hu|$YoCFphPx*|x?Rc!r&poi{Iv>@{ zPA&HtGn%s75Az6+eif<%q5_*~J1qAk!2I=X??h!HHXEEcN^ zCVK1Wf^>n4RZLZFl=bqW8mJ#fiEmug8@}0fwtMe^1tp*OcooXEJ>q*^imm(HhMg{L zwDb>i_sp|?$lb=%kn6eZ?b^hbS7yumcH|YUdj2(^JJwD;Rs}|x(%avJ5b?Egq2-aL zg!;v>qtL%<`+wxlB>+?llr5BlA4#^HK_7(M+2>|fwjp1O*Sjl^>5hpmkdKxOl{n5`?^hln zB@~D8L|YF|4oF|Y6t&HJx{;zHuUaR|uu$z>+JFK2=bP^S-mZ=#kw$V|P7SZxDy<7! z&V4X3e4^t~kbCf>y5H@;TGu$HZ*hwImdf*szgSBxYD(Lno^9QlicU|v@Tds8(>NzJ zl$w-abz8UwOGAka#p>l0WGsH*Vm8xx-SMS3MI^N!d?@+vWrMmt3KW~|Vrdr(kr<_V zJx~SbpcllJij*zevf}VZEJ2mlkWZn_L3fr%e(;309v~er5u`(F75&3rL#Fw|#0!fA z9JfW=C$e{PToLP$}et!3N8>$T7!G%d9Z#d&dIV9V%4!IhJZd5+0 zADx$x>Y3TscKfwWs^(eQuW6ZGRS+L}7bmjO+Hv65c%S4gWaD}N z=uJ?(ypp8sZeMAkpNiKT#rRuOfC zb;Y9tUfr#*9tqO9wrz2;>s=8K=>kK+NQFh!Wi@TLfsb2z_3Xt{0ZIS&0o!m($J}IxGS>_mdHe->}XmM7RxZ~3e{*T&@z())B{f~cI$!*ULU)X^k&RqXeGFxnQ<*Kg;Kl{bUG+K|nOyaK` zC!4}xqkMq?&HSMNCEdH*NX ze&IA)tT5OzRYy{lr|m|5XS*8*cAejN*jUG=$$HBT3_lU+OV-L+HK<)DbaHSQb#Bv;vbdu#;<9y zV{+%jv`)(lxp;l>tEdu3x&B(aemM)%hGx>@Q9|&Z{!qZi#N1sWTmgUZQuX3z;!`)s zhZMtH$X0@}vwZP#vys2BoSD~QzxHHK$W;Z3*l;6L=)-knmd&x6CNxiI6@0)>{a4cD z3so+S`tcLAVhwS1<4Qx@Rn)CG8-$I-7`;n@zZ$J;F z^MY2yjFx-&d)mq&EfSWC3C9I2h~p4{q)JWl6>Xuw4RP*!q{$8#L%qU1f&lICvb$a1 z)xMC;+u^+9A1BX-P)9hC!mF`m(|LMu7DoPx*v>pdcElPAH`LJTq1cok;NBtJyqRZ{ zTsQMAI(WiI%4^V`=1mPJ+YDEyW2P}jKP1yuhNGdmi4i;(Ik=>!d(2_OSv6K$RH^iG zM|t8&0r*fRz+MhMZ*Cs;hMD1Lw9;H%Lb2t&_~7un`&E1DKl#U>7~-P7a1~_K>`2%K zxJ~rt{}eq^2~drWI-6G*(=H&t1}%RL*(5D{&5o1F4W^;lnwPMa78aI{%%B<#1i_QG zy=!u}e?_1+q2L47$&G#7iPJ+^JL`@3+t!zdk$2J}ZG0zkE5-0$U@IUry`iC6blcyM z-JnzYtL>$i-KNM_2DP-e2W|V*s}16C_2hJCNxLKXl$C9m2(#a$YJgH{g_EGt*U!>@ zvafAlrdb_FjCOXhHokHa@m+jqIKsy*!koGHmdPsH1SRg#!2PF4ViQ0RAc9b*~mNyYlv)5I(7;%o2Jqy=SvMg8uSdk+VoMFZ!=>?bbxF7R`Z2r7g#FbMRuQ z^GMiho%WBjpFHk$bnLIF`KN)vckmL7?#$IU=c<7E_m>#KVc&eGt5MO4kfwI|CvtEj z12B`XvIqYdTWGKd|DUKg-wizY9GY)oRLBlKFC#ogj(-Y8U9af+);~E~-}iuOO%%i| zwV~)!hfQQJauiPRSFsEZgYQopmmhWiRhX(M>K8-^vzuteFV252qi~tlK3HDF$j1QuO;Idv5<${{`1*CZnw)LN+hx6XRTKldBb<=Tj>1csPEuH zu64zkWaLw?ss7XU7~c2Mwp{21FL&krQj`u3wvi#U=NU*N;Q zis?pg$lI=|sRC^V5q80jmKhPQh!-8g6Jk$`_BMB>Q(LjqE`IKL`J4(zW5w>IPs<@& z8>;>l**_n*VPBE+P&;~&#^9fSp41+;hMn?MeI2)}ZzjFM=hwM2C>m^Z%KIFJ<+-N# zKa?1&tKM0tYC<;FN;Qecqm=3G()T17zNu!`{oXnSt$G_Zt z26bArFg^zQ49Tt<;jhMh8Vk1K-ZqTS8qCm20qiH|d@jw^aaj$fI>wdxRF0EMJjT5D zf|Y#FyTntxXwb{ey>jCVgI)_``2il- zvjZ&8XWNYza`(PyU@XKg{IvbI@0O!-pqW7M( z^}V{qLtlS7q@8oxLcKF#Lw5HCLqq3x9>d4EGzR&Ll|)7R?9<#;WMOBL#me+u`Fdne z)SVlMIgW%nCnJpAM0(9qSL>6ChNF?!OA`-|wu6|Aq4gTFrzf>RxHqU=FJ08W0b-Fv9 z7eFh!I?h4QKepDLAi#bQBlTV-((O)ynl-M6Sk}YqV^Jh5_WZatUbn80&eRtoqr+5u z(h_!dcs3vPr(vXOj4GLRYRfn6<+vu=jxRm!**MKbZvI?CEypSK70n0fx4Q} z?kG(JxE|>Jm5go#q}UQ(2{L0^`+$9PNgD7LaYv=dw3m)lv$Q31leJG+9TjiqvR#Ah z%_dkwq<1XZ^)@TwxBMAZn`K0=J7pIc#W1~90Ra>(o4*xCoVf0X0XGWMwKJCO_LZ{! z%9qBIu1&7_jqMcUAm1}fIh78-_T`6Mo)wH0`#4*yTq!Vlpc>!w^6*#AY_(2a!PWQs zHs82HFD2YQE8_e9Si8x~?}ncz&D0euugU$u^RC=C`+bR(f-QEfGqPkO85$y_;>z`0 z`^(~V7E)P(z7Jb2>%VVthq(O|k!b>fnX*(^jUWt^;mdjDOB~r?cjz@f{ z7g`>C#^FP^Dcf$ibye`DoE&Zg)zKuU53aATv0M_pEid@YKSx(_ZZv&N=msRZ$!E+S z&pzj&^2hx|IPyF+7!dJUXrB8cH>Z}G>UnnG^79<*ypwm|XZevOB&lXF^0)U@fBa{S zk!{3Q$>ifLBjD*;=FlE*=@Vc`w!kOk`e5qh=O<7=p4tr=1ytAHdN8yqN~PbcMa~;{L8~% zss`S~jau2-KFZaBD7LPv$Wj0{AGe(6T>$z}Z*%U|5h&+j7wfV=GTX>eh3A}-^;dt= zhImWBt1l(}`Kcp3J2U%P`Ivq5BT@hQ`dr~RIdZ{v`k;20L(ufV_|~!is*iE)z3$-h z6=A*@*(Pb97Sh_uSx^n4k&|w3;B_%Z>a5qKC-30K)W)wem#7XK47t-;m(q+>=kDYV*^T92>%j6ARYFD@s)jYD zgp?0X80&)?f3=@~maWGEr)HBzXG>i@Hln&JFU64Ny2w#7J`M#P=Z~8{5O&{ulz0_m z6ri$o@sFx-x$Aw1Nawxp(z%WfgCdX17{x052&EWZS2L<(sho6cvt@Big>}+Z?~iE2 z^h2eefjnJRD~29-$EHUnMC4smz+SDJTSH{S9*^{|5!~mGCd232dIy#!ifqgpq`t*( zdH-Ni$h2x3jdJ+t+ZeXk6IgHP%sJ5JK&?(G`-upLW3%Aa2@^l~aZ|33D)g7dY~%UJ>Q zk*3!1j+Gnbs14p7nbEWU^RppUV~Ivu1-lM|jY3|Lk0QouF~pq)x^U}C39D|lw^Apj z6UrU|q%J-InAAF}88)+svK;jz*k)l&R7b7B1E2|0#8fayy@apamnotV$4 zb#+}A@q%6A*}%R+!E%7})9iK}&optaKKtXqro=~Hu}HDPXN^S=rxMw9^6oWd%xf)j zZ9nr_8KuC`-sS8Z^t>LftkiG);He0b;a~pd^Ah5ro2A9Fp5Ri2&8Kh zIVx?_mo6P@%V=_do^BMWtu3RamW7Mg18UK?XkWbF?KSHK6FIA%SuGkQo&9C8j6cXLI}X)#1L!woyY=#`%3v^TZwkXt3Sl8@eTs}E3H3tBnmCc4yR0J?pi z<~U2Be8 z-9BdMZpXH`xtG;^xwIYQVcu;ZMgtq!D!P7lGx%Gt#?X_%rnW56r4>?jol3)i*g2g+xUv5+ca95d6MGSlf`cD*0t4rr`HO7 z!xXIkPPq@3GpmW$o2*#kZy=Y}g8LjY#@)p3ySrWOd*$C+1Het*p741t+HxS4jC#|q z*Xg$v14{L^926Eh8(9rFQaNgy2p4#4eWQN&a2i@9U`@PbNN*tP$L9D3SMs7&k2Az> zaCdhIGLcuFS23iK>;~~)Oa;6KtPn$m2{-t)S`jdxz^_a`0`=+U_XvfOxS88or?R8);yJwYde^ftYBx_35kJ zBU3TCp0Oh~70~gY^Qh{Ss)Ar(XG}ZKjYKoc68CabnU-m#hDo=((7cTi#y1;BnoDBJ zTP|anh5KQ1dNb{pH~?AATsY0TOxbO2rtS}J?r75+RxKH$1J^J$Yng}_+*H*wwf9^( zY|vw-Vu_t>k>s#}seM~&@2luu3acYQM|Jt~rK^;9OVKPvALk<+9eVY@`Y*1*u6CQfWSgOr(p zGr{)hjtR;6gOBVjL*!ITx^1iNhx-%8#$`6}viIOj>$*98<8;G@;jQyl4Tn*?w}$_y ze!RX=6f8;pJH}+HUAx;({71!;d0{rAJHhYkw=uJvr&=#|Ct-ft3$GV>*uFwqBi0ar z>>J9BV*}eQ3L9uMQ`LV|rviV`>Y7Z}C!X~!c8d{KPb~<7l%2wblISr}&VXEU2=h7w zQ>U(%3-NC)k$LW0t@D%0XJ3ciU2?$kZc=JLbv{pYCYL0Co(ZMvOBeT#5lJ!^d^LnB~%V z)x(RrfW(c({K<+0GPR7Bl^&n{`XK-JC2!Td+qMW-V!Dx#$Y0gA*Qwa9L7=hcS^5v2 zYQgT1JR^%>1e&QT%ObN`=#~g3wD%I>wu$@!_mUKzbuBLu0C4mXR1+FM%ViQde>4Pcuj;*#k(x_iKdW zmy;<&MCoOBfXGn!jFZgKde9(2`rAHiZ$P#DOq0J*G!_m=gVOJUv_Ofc$N#7X9=7W` zAJ*Q()8~{SIOj(ZOh~#KG@l$i$N#&rhm9s&n+QG%`{BCX5-qL#=$={{C-s8cA zx&UeLK+h0qCpRH=$Lpy8$m)duVG_z6!iZw0hn3ZQGgaqnF4Kdf;Cp0P&hlcS4w7XL z!Ii*=VlS*LsFz<&K{s}$Yy4PHQ6gzhVe=bTa>49;v!>h`gc>QO`BCHUJIZNn4ZY~z z7j$J>P z~F_FI+|EQi( zg!_MwNYp9$=~aDL|M1?4Iy)Sro0u$EERm(pud*72$yLm^TrOg9IGjG$5?n{x>*Clx zl|^AAXY2{8C6mQdXefejQ3@7*CY@N^g({vk*3P?Po;rU@(tO&c$z zkvR=Tps}|hZFhX1+FWWJ?%pm*7FnZwTJv#LNt-isx8HyNnOm^A7tIbJx--=CjVsIuIVn1AIa;eQK;qvybFYX5gGpV4VE<>ly$D zLNGER|53%LeUr0=Ct+;*#p(?3{U`Wwjd>BDrCTB6_A)^Xg7!L1i%jD%9168pYL896 zAPXoe9D3hqCC`{Yz4607QVDsyA2pueksnKha1BW6yX!$=0)I!~*o#l!;nbaGz8{K4;v`i5KG^uYI^d`>}8SfE6#^XZ2sA*GlG&q>F zBy$NCS-ZylnS$;1oNdjYIp=h!cA(fi?c2h=~5Q_u_Eamj%1WEL2NPE0i z_h0soH09JGu)^v~?J3d5#xyOE04X5Ha{q9nZ$cZuU>yO;Z^NN* zkDA=D3N7-~`Vt#yUc~V^IiOMEU-QI4=cm`2KuO;(F_ti4wUp7%k)|w~$?C46c;Niq z-}Pu**lNeN7dyiO$niqAd2!sJd)1^QXo(&)Xc9lXN4V?Fq({$U^9!nznyiV2RS2Pm zA?eofVm^(x9G^v9$m%=CReKnA>tbxBjGR$P0$fkb=lA@QwS42TC$F!ZiS?Ah$iN#j zIC!$UJJ;c$2FQc0QDqv!ML~Iq-?zK*Qo-Mu(j1iw2E$-`F$y5UL-y60G_{+U2X5q> znWvJHDrG7kKm5}7M1k=cpGL$}=8*ylE$n!RpeLDn%JJDOEh%h6Z7#auHFu z21^{z;zSin_1?;eYYsC&;_Yp6KDBuk`vEog;#!zn{Bhi638dlfmUb?t1@xYUFtAm9 zdx(12jjWBVQR!a<&sA7*IT93;4_xPe;ZK}E1|{1mNyBKoq?do|du(jhfTRw704U8T zjT-)SO_~D4V4ykIL|`O!qjV1Wx}73}WDA2OA3xZ+lAgtuyDE|3TX=$iu!!MgyHT)k zdzICGonafCdk5FSkJUF{er=^|RO)Uwj}}#|3Y5$~NG4A3$TFh!Y`=(`i2);TphvN+ zx5qeAx)LM%DYK!8(L}CzZfLl%3(*&a!%WD(n!~5y91v4>|JVUOlxxPOXu@0N*qlKk zTT%)5mgn%gmI1OcqJFXr!MFe;23tVI$$zv$#s`JPI>Bz4d|a7E2Cb$H47!LG&vn}vA&Tzd%czKxB6NU; z={Px00lpm(QqgZvsmN$iGf_MRDm?(*UldAoej|#FVUF~~&s|n?HaHkm2X!@&>+aRK zW~daLDTsmW_w*JgBim$pT>|Wnr`o7HalcQr+*@Ze%@MY)B@7KxkY|jnC%$$hb9Wl9gYg(ElITvaO)`-zW3rh-PiEAkJe z%ve;Qi97DYo{em8R))H%X&DC6l|%nxGjDv5qK~$PcW+h=_7ix6fC-yDz6Jy6*1a@B z5~V);;NXZtqaARd1x>!Wic^N(mljp{lM&1BbRxtU4KjseoF=w-_r%WY3OQFBJRznL7a6F5+cHHVB>x}u90}t#f5?=8AFcm{96!@M@fP`}WV6PCOdwaB zPA}dBP1A#rtEXLN#GET&{W7cHeMB22I~n0kO!@e5EWg53fV(crN<1@qa>C>(j-5kA z9SRjpyEa+4gQ1v4nXc@YXSHAzke{QQ23KT@2KN4lHD5SyqMmu1%URZ^r&R10dXk5rsFhmx=?1_58%1{RMG zILVE}7h`6kjWR+&g3g@MSZ}3wRyH-sb2zv}3a^Q6Ha(GT!3Z&C6cTJLUj1J0xtTTr z1L@$Un2?O37(#x$Y)i5>KqYrxl1uxtX)%-4sOvo(i!1vc3Hl39RCn&Ipw8}6F0z`v%cw8tAT z)1RuN?l$7$vZ6kfQy+Wf={CiLIa5OX8Iz_kUsyp`0pY>AP(eQzP6q z{ZJ@0vHweuaC*DujEnL6<6;jE0r7mlwR9uFk6$(t0I9c=!NNw`C^vXn9#<8~3!>#+ ze&7_e?rrK0N$>CSEfeSfN%~PRhXnza&O9xVSdAx=69*+2;3;MxBFmgDzb3^Xo*5F=Nqd7QDafTp zx@Z}d60x%QxK4N~wz(L_ORs9?Y;yRMvXIiLain_wF2QMVw(*j8Z z8qZ%Qn+QI@aBP}psR-~llGRmb1A5e~Z!&~i$V3e!gKd>kI)U2bg_haA<51h5ASwN< z(5NTZZvI%^c|9=XN!d#>%!?+#PjX0tNz~!}aGp=EjIL-h1&P4YfC&-BGY33`cNmaz zNRXh;s@`=r#su^JZwg5(DwY1X`#1x5pG+lY`Hj62oGkVQkHVL|l$(J+@qI#Pci zCcja(g(EamfzOGIJmx!Wyl&s&KMGn?V9;T$anYf)w#=`X<0QA% zMjC2{I3(MvAPy$I`6NJpz8c%A3d&XC&Q-S-E~9IAQ2%h zo#?uOQ@&_(7n1fFo+Fu21IFYhn-QuUk7Gtyw0T#QLwR^n`-RMQLzkdm^!T7aYg?dT znqVM11GLLc>hGdj%9G~L8#d=zO2ufXgttOIFZ=4>%+%E^&y^9z*iyFELW$uNZX)Yy zqZD1(n@?}Teh~EMU0)`fpwhWg0>36EwEQ%1l&edV6ZL3~Rv!%1W(v|~5-d#`;4&4= z92~f^pg?mwP^I+wyOVTZn+flM*pqV;m8N-}EL}b%i;~l)H>L9${mOjP=?24JJa#6g zi^?Q-&?;HVIuYh-dZ@j^CC2{s((;|1^hZ%{$9pz5jgo6_9|oQyFYVu@-Yc9y41C;4 zpC*a&P0#pY7A%8DQ0XF@2hzv&MP+I_HBr!c5@35(1?c5D#lsZMdUJKHz;lXt?fmgu znXjt1-(_W+M{Y$klaq1#7l|P z_Y}pN&nM86VlV>mq+jqPlm{QmGZ>?GzP-?g*}?35En| z^3_i%inyb6emc~$V7!0Y~u^Y5HyCZXk zh4gWw`!@9Nx{Oi}d`5jf2jX9=a zeQJh;LWO@+wYTy8o6Y3Tz?Ujz-~mF|$6)6)B~jl!qT0pl)~6%BF%J=$zZAoSsB`B1 zrj(h|kR{@BCn)V%d-$&qd;WROKjzwrYiP4-sr>6?9;An`-}?e7TAiK+Z9offn$@)= zyZ35`|Ngvkk@abn8sH^{`vs-jhYgmZ zhDz$^mT#~JHGlaWh~4-Glpbt6R4>RMCfrKkNpilaHt4(IVF{EOZ;&+D-O2{bth-$_ zc;{!0O1zzjJ)B)wgETQMI=2raN?SNx(e0`q{d=o$;#uafBIaA5{fopS!6Z~gr@yLm z=3h%QU1m-5h21!wZ$;J?rVzm)$C_V@>wyR4P2LLf?x_niF&W0JjT`Rp`EWp5+VH0E5V5e1y>`tbh)C8#C@ebNs+7L$ zK>}yUhJeS6Ewk5bBp_6zg~PO2mzoAlZF&=(9%G>^UeaozD7=2|M9n&h^^!Lxry(eb-5&3WHpET}rz3Fx7G0U%y zGOqkvqF-X|ZDo^wWAU+4)$wOcdV7ROT{l3iW|9k!!-{fQhu0+1@d1gr|yn(+i8EMk7V=e zm)y?iU<@k?pOr2??OE`MTaqKlBbu_4^)#Zx{Y1Er-oi%?8ya-2sLlx4X3{uDpsnq zdO$Ixqo0G>HOOyLe<}oEYXK*i=ZJFlch&);Ooy@E1!Fk;uIJkA zCEp*47fXa=^c*#NgwF=_jFzgy367|JXGAv3*G}wuX%JG!)FW=-V1HaMZt;}#k4mI$ zvP*5ma$Z}*8RdAYnB}@t@imhVgx5;``WL;Ad9upeF0A@7U0CXILtahqNSL}GSN1=u zkz76Qk>7|Q$P;h9z28V5_wz6`G}@8b-)e{?0PAHHUx3S5uPsd_(K7^OR^KW;X^llA zs#4R(elpdEa)e(M7MQM;WnTu1DV>BU%$2aoylv5HVrr3|c8xEh>SY-6Gn!~2i(~af zO0<2047_sk8YD7}(7UMpjQ;s7lTOxjKINX|uU`{e8*n^}^}1!csriW=4h5~Xc~D_t zGJn=|SjBYKlqd50*H&FysOj*bwSXj-9^04dCFj*OKmAsjvLaKXv}*Y#j|=^ZGA+k8 zSEEl$Rc5iyjtkfr!iA<>BJkGXSB#Tke^K_<->QAy!#@YBpd<;xAoK@O+%jJO4%Vnx z{ObJ!1(2ZWewnGEkh;~YnTY9pONE-%)k+pYoi%@vN@g>CZ;O%!N3dtD1bh{Y(oiKR zGI$89u2^;I6Rj#OZ21{>0{YRCER{LiEltPp8 z(NkTa+>QH>A^pEAaF^)m?pHnxvO19dizsCY~b9Awa1y3yxpP0nX z3J0y-7+R0*=is=Q%ryikyHluDnWqDVM6Y<+Kc4Cl<+dIvyvGU`nYOjgldDZ3QIh|t zu0>C6_}nK^pG&-WnsnC|dkVN|d{u>ow?O=Lc%nMv{n*1;z)b_vw?z5uHRXFB*L!?l zIP(pWbW47$c0HOrJ^c{9IPqL6-{vngK8C5?W_1u;$@^MCZT9+)0c1iiX~9Xfr=G3| zgO!jmrVW^h1yI)<``8$}i{c{$vK-8kuuiJ=K94t9_yyxZYQlhv71wQCke)O6)ZGSm zHKFu#;z3|*Z(LNJ^3+#3^-~hu-E}pqw!_J`?lubxogo4G0talvC><50}d$jTEqo;U7C zi4cv$0T28A-u!p~hLw5)`@_Kb+InIrKsq=OccS*ZYcXg@%qmkiHci>6(u~_EL8E%| zAC>g0(~R8^MQ)=?(?DK&09`C#^6{Nm#pznbjPO_pV^md9<=!x$P6qssYWk~~`_BF2y3$fO3#+IBzHiSnr^77En5mTH zS`_iNQ2G|*{YaZwHHswi(^Ck03S&>Xa!Gmq7cO0$0v*`?<&&G+X9l64aMTvDymeP9J@ zizkj9`PTlZj#&`3F=%p86>U_N)Bh;@L1N$bF^dUOPPB2@*Nm|*WAkzR#}C%w+3(ew zN&4BSj50mVygW`8en0JD2u4b^$&Hos0~~uIk_pH7+QKn5mC%k>%}>9nlWZE@ByJ_2 zTiL>~>ycfp5Y{*`Z6*5awyt2{z_t@76H+4e2mX{y@gh8S@?lPhe-qy?B~>CVFUOXB zTK69*C2CA`;*?-A)o@@touyHabdsNb8kdx;fof!-2zHoFAt&Sd@NlEDWCN483@C~% z7C3xHbG5okJ>P5k68BvZ={>!I{Md0D&M{04wF71yf7b#OS@U+jI zIdHi520lLC*Dqe`z=4%!G&WU}K4kCI^|2`v!}_1h9rAXgq>ee`3M`HfVaA9L3+Lex zY`As%F~^5*rgxzgs6*iQtS(Ov>&h6CO_Phk*|ixtc{$Nf2tHxPCWpz%_`@G>29qh< zRXWAO;gAz1v$4|9W5og$o5?v*0|R3gAs12G&K2!qf z!$^O2iC%oFo}eb_%^~j7tm$W@rVCz~9sZ*vu|p;C$sxh`E&0qd!SNr}o3iq+sliW@ zdts%T={Y8;SqbU@n8 zh1lK*p~E#kX8+VU2K-KIFN|!m0O))&ySMM^(~_MU#7dDm5QSfk1L!O+enK#%66NK% zQWK3hZ6C!j%@hhifOM$>$dXsj^dBVM%J;!h);N; zXzw-G*slrt<&MjW-OdAfqKym%cw)1fNAa(*q+j2RbbH9Jiz6E)@%8}m6y6qvl?AV@(MWjd-$S1w<d9k#*396CL6~R>Uo}^*^42}Q)&IVmqqnr);GE*gIo_C^&yC@GfQ?aMG zCEkhpevsE)kup3W|O@>|I8u4Zh04 zyJ1{ocrH(N-8f^>ek-}ip(e$e9(r&)5Bp37!}{UPX9vxsgY=-${W+@g-{axe$Sa+4 zLI+G-21{I|W5c{>?(}_ZxV&2ZjC=E@JmqI7c0?RlW%NLCnxNlUSteRmZ&8s(Yd)A; zjkA03pd~<&PiM1I8(Gm=R5cvDR>{z?qnx3EGij(d6!G>FsF|`@HL}nJytMek@X=$W zjNP*-M)MZkZtw&1L9AVPRK?)Y=DY2JRAf>f`-m}ny6IMUvSCPhf0~Pr&U{Ac1N;lA z;(1rzNAWlNAkA$TRcpJV2G{>OZ=zR|Rw(yh4BKhmd&m3gx_7+tn2`#(wJI5(771{d z3IjX0XP4v?nv!nH)1LjK>hR5_F6_E^NN)Q_C6>WwA-=b~U7%Z5U1ug&?)mobE~tK5 zd@6z&mA2&HV10bT7%69x9l}wsQw$AaDyXWww(7idwEjUcn@lSkP)U4Zdh=Qgy}8M? zksGYkpCa4iIv2-eMl6u?j9~O-%z4P$oXa~C$_CZi9vA-i-u$?GW|Km(z+z@%l@hHS zy{`SP(P(n-Iu8e(?jM^81;so^9)z!v|542+ySn^o_!jzUyN&DS@pj*h2OU5wthw<| zo5Jg-+R}|lbH{0$=OP-t*#q)-{AJ8kAjvCZ&X3mI?rzIp3|yCaz(Jc3eO2zeBmLcI z++pX7y#ssH84S{P?Z#yoe;3{6TjNSeZj7sW)8N;-hF4b?eGNzN{y#ju1yozl^FB-Cc`AffkCp6fXn~T1tTiDORBWe7?W)zBxJfoO|!y zo$O|J=g#ar&-A2Ps~9E$X0GhPC7zxyjOJB7%!>V8N5>!U_VTQ07|+y_jC|c~rRz{i%J#kR^j3Zid}7IwFuV zRqD_oKZ^22&(u<(lG7rKfBoA=$6dj!#GW8t>z<`{^_4sxaRq)@#&kDJs`4fUV;AVN zPU-s&9kQFhvfw9*e<)qcO&<2*dlliIn6vdaQzAz>BoXu>6{i~?KPk|}o7sQHK(|dtYVEu&cido?FTsL~VYs!`eOAjC+FxQ^o})xlmJvuYJX*rnfuBulDfFDkKc%@D@b-`#3CsLEj!^w;XnJfCaZ-J#;D%$a5s&yt)<|mv z!(X+P-MJ+M=Mz136w4C13mfG7m4&c28vf#&X+Dwvhf?3iQwFv8kkE2#HXUYczFA`> zyBwA4aO{?=$sEM(u$$ujHI9Dj+})(xddHES$A*82@F6$UeMdDl+$k8(K$DdY&QJ7) zr$ZWFX6PtXgQPlvoyWRaUJ93IM&=vCVr)S?CW#B@AtHm+H86v$>`Zncbm({2fpjfn z#Kf)i(rXOWfERmhSsBDEndyGS7*mgYj!NzsRqI&yIgcyJ^HgrUFME}TT#qq@ewsJL@+1lqxzf2)pM-F zV}EiT{Q&O~V`EoeHyp3B444=LmV$on!k!OkK z8-xC#L@{*L;u1u?vmzrVn+@ouzc6`uoN(a~Wa6I#wlbg7I5+IH zj<`q{$mlf(Uu7|YPWZNfm32B_YXf7?8xQuUX86bxG>gPV^=XI>>?~?^HBQ}*+VnUvg2hQ6)H z>L1Tx1r#TED==PgEoV4*fMOubkSA0*qS7KnTnMJZ2*8|tBlTVe}AqI#yIQZzC zhUZ5aTc3XmE{ysl7en4>)aMh%-bMd@HY}!F*3;K!c`Q{u!u^C_NUJ^K$}($hAx%HF z)xX!^YqraE$2V{$EMvOP89Lk{K{EVRDu9!}+bmlYPYd%%|Al>dYGZwr*pSUf{rUwB zNY(@=h==$S*y_ZfuIeWa7tV5|U#(wO{pPk()~p#WWAaRe+3QS?bB_0~Gdb5}SKq3P z*-^ew=makGuD-SuWgttIZmqdDuH$|{?uD=CraM(~K9rARJ3uI--Aox}(mhRISi)Ni ziUvqtOc=RH+c0`)uh>YRtYjT+(m|#iMDtz!TzcGxeX`BCpt+n0rH0umq;&SE)0|Tr z`74mJ+}g@IXDMd-H_EWXww6!KZ(d`d;3YeZc4ab&f@X27xOhZ)qRJ2A7qnrD51cqh z4k-GsK%B&1beIil_0=me$j~f4kD-P+3Efs-=*$9h;7jWq@l?n1 zVx}=l<7EG~2wra;(J;d$!5%ZEaVe9iFJ_)d0v&TYklyHu>$G{RM#&mBL_kHZ-!zM{ zdFypVLA{jhJKl1Fj%9eG99f+OSOdBAG1Zx@&Cmx7Ic0-mFvbId(p1 zIV->s)T~yy#HHw|r762q4udpB$pEp2-6L^>z)A~~B(n}+tSsR&FI^@zm5IQQ^Ox^p z4WRGdUYF{SW)U|JzA6$&(Wfx~wVoQ4^;?0IxRSXk{(DYCsaGlHtM@had2MLQJ@rvj zeCJg!YQ$vU7-)*F-B!MDu0L+p_0Ca-dOwz{e@L+C!qbgfOX7R{rraP?c;B?JCy4ns z6$M)N=Ixg0JXZ~lx5@_5ppUatd;Ekqw5c?u9G~6l1QoaG(+Y^q>+Sm#tTIyCRiiiY zYM(@PFrcr}i9quduSMHdls-nP#FJj=*C}ZwXy~aeDAh$-+n|>zg4jSr<+7=QAAXF5 zQ5p6&dX-g0ts0=~sFM2e8;JeVB5hev>lYJ&I@_~(Lk6rr?Clk}!)hJ#mxlB)9b+Od zd_^zbJs?!$b`be9j3_Q)G)_awvZU`ZmWy#=phE>N+@G2{zAp_eK65$oo9Q_3hbM~` z^Jp}Zg}3GD>8yR9Rz?dK*YoG1=D_}PtIwkZ#Dy7~Q8iqsV5I6|aYgx=z4_8FYW~Ch zt-~lZOO}gs%f6B;%CWR8kO^mdiquUXOuLZqstbdf%cuU)o)fk0R;Sb;9U8p+(U@wl zIynQH8N&3}+pJ;I!&9j0?0sOq3~$p1sq&qeJD>3wX%}2k*Xr`(AFjDM@s7oi}Z1AW+nq0ufo5R=uWEIUkOEfL6Ww11B}_)CrN` zr%KIbWRP^Q4_0Z1KpT3b6i;0iTD)Ze^DEBcOagr{u5eo$J1OT1k%B>~LNye_d^x>= zG$~JoqAg1l!%J(#?M68XE0qbt^FFLHUs*0QsssK1XNS|zq^bdA(ODgq~xpl zG|zm?dm`?%fMR_fDLQS?vS6HDGkoVa_S=PWUhB|nwFTjM;O*DYdA%U+COv;p606@O zh$QD>3F!_zE-4?s*1J-f(#v@SL{VWsWaJ8zAzfcs$Xj?Kv(^^}0(Otq+^@|DyZ=PU zJ=s04H4PB#%3rI3xdWZNW5-t6M%EJs0?mTG*&!;^N-wIMg(c3CaW7ZiiyaEhc1AZn zV_X@AjO-z+#Qrl^?=G*I@~gM?N#a+D34B4au)p3D`w!Ot#HACqhM3%4vU>e~=_dnl zL|0g1fZU$S?qc)#>qd_jUkli-AwmGo#dS37^Z-Yp6sbVSv@-o%P+lnwNn8p-8*`H_VU%+#+|eK)CUUqhagt zOH1U%lBUm~y`)6@d&FbgKa_e`~@$lg)Z-xo$O_UtoUHKMqa_<|g{~Nm{5GM3k5Oy#h zE{g_>lYbs~W#EgnTteNh4{OvaiBoD8b9&QUvb52H&J|Qtk;Y;S$DTuw17R1r)d2FY z+(ElN*vS3_?;&aYhjOoRO|d|rDrb#9%C8@;^aT80i{#>F4kadif1&xi+{6Va}6cZtc~h4MqZ=52`fKNLX7Vp8d%sX8{L!KL{ORpy|Z>IC4O zhdHWRS%;35mtJo!Q^&?57UD07`9GAN%YZIzo(|V{&r1JIVi(&Z&s{YMjHnd;L4PPG z?3ElP;)uR1*r|M1tuy8Cz1#rs5kEGA2F|>I@1)@TjkSj)V2Mm7t<3>PAuJNRq@%5v z=v)QRqxx1g{1=%B2VAj{*$jTn_zz|H9lUuN%+jWMjaoyXB?|GU0$>zw?E1%=yDqR# z#zNjHQ+~K2XUXjhNxez%6^*vuA&78iRc<>=BA1&?V{PSLC^y3+RVTA?0yA-nY|nLw zvZeLFMNSzZJ1w>Dv2Fd2pRSn**+wSa`ZDhm0ceb6C{YP%-EjyrTBeW!Qr$u5WQtsj zQJPpn^MQ@!;!gM?BJP%8p&n;W6Nxi%JvPN4&xFVGiiPZrrDdpUTX!*p!Lzpt=2+T0 zID%7FLeQay^YPoSlg{Xhn))Xq_d+6fL-Kd~2#=)*{MV^P(0w8?(h8VKl#P|T6`-qP z2!HoM3TAu_Du3CLZ`m2os%4^reoFN`Gr@VsP9*v{!hcIF(cp5EA@n&G<_=i$B&A_Sm8G=SAoRV&@$f{qc2zpSo^7Gjr zq)G%RCXViRVUc}dQ$<_QjF7&5S=w^CluQbqV*BS{w zn)IS958#$}40Y!d$-H~{h^;`^JQ*HF{qrtprey&O6dHq#oE};nCkq+j9{ZG%sUtID z?vLHN3CEr9(2n~2TBz=9M0bf+@lzX2IvLz&(H%?*wH^Bin0@Uu(sz!|j zBR`uU1Opi2)d;y%c;Qu9JtAYUp?4?%93Bi)}@8aq#e`i`c**2-UJ%AtYrf%b*S zY0vQsIn5O!lsE)S%KIW1_abG2_{S$YL|G!D!{-Ws_Y~|Zc(GfF_EWt6f(@S|ZT_L4 zEu7ljh~&r!6D>K;k5yj?gvnyBMbu8P%DsMC+o&^6X1~+@OVkU6i76*?_rOhft0GtE z%NZ-`z{**oBVrBeMa^LN{QQDEQg9h^{c=mq;UTBJD$ zFASL$B7K3iGjkJNybH9zk11By0tfmGX{v>7{NOk>$GU51MQg?&45~)+`a%1~^+Y@L zf%Stm7_9Vw{=Y?*N$S6~5ExEEBq@jSAodR>MT|xOz@o~~kb#fr z3sd54(OAJjQ}j>UwPh8~G(uE&HAAj|iT)11xe_8?MLD~@HPvi*gM{6|=Tg%q41pjF5Rz )j=A1 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%0D??9$Gav=a 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 YXcz7_-A1785$ld773_MbpbQiL*>^+KQUCw| literal 0 HcmV?d00001