diff --git a/pom.xml b/pom.xml index 0cad031..9522a8a 100644 --- a/pom.xml +++ b/pom.xml @@ -22,6 +22,11 @@ spring-boot-starter-web + + org.springframework.boot + spring-boot-starter-validation + + org.projectlombok lombok diff --git a/src/main/java/ru/yandex/practicum/filmorate/FilmorateApplication.java b/src/main/java/ru/yandex/practicum/filmorate/FilmorateApplication.java index dca451b..843905e 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/FilmorateApplication.java +++ b/src/main/java/ru/yandex/practicum/filmorate/FilmorateApplication.java @@ -5,8 +5,8 @@ @SpringBootApplication public class FilmorateApplication { - public static void main(String[] args) { - SpringApplication.run(FilmorateApplication.class, args); - } + public static void main(String[] args) { + SpringApplication.run(FilmorateApplication.class, args); + } } diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java b/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java index 08cf0a1..752734a 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java @@ -1,7 +1,65 @@ package ru.yandex.practicum.filmorate.controller; -import org.springframework.web.bind.annotation.RestController; +import jakarta.validation.Valid; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.*; +import ru.yandex.practicum.filmorate.exception.ValidationException; +import ru.yandex.practicum.filmorate.model.Film; + +import java.time.LocalDate; +import java.time.Month; +import java.util.Collection; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; @RestController +@RequestMapping("/films") +@Slf4j public class FilmController { + private final Map films = new ConcurrentHashMap<>(); + private int nextId = 1; + + @GetMapping + public Collection getFilms() { + return films.values(); + } + + + @PostMapping + public Film createFilm(@Valid @RequestBody Film film) throws ValidationException { + LocalDate date = LocalDate.of(1895, Month.DECEMBER, 28); + if (film.getName() == null || film.getName().isEmpty()) { + throw new ValidationException("Название фильма не может быть пустым"); + } + if (film.getDescription() == null || film.getDescription().length() > 200) { + throw new ValidationException("Максимальная длина описания — 200 символов"); + } + if (film.getReleaseDate().isBefore(date)) { + throw new ValidationException("Дата релиза — не раньше 28 декабря 1895 года"); + } + if (film.getDuration() <= 0) { + throw new ValidationException("Продолжительность фильма должна быть положительным числом"); + } + film.setId(getNextId()); + films.put(film.getId(), film); + log.debug("Фильм успешно добавлен"); + return film; + + } + + @PutMapping + public Film updateFilm(@RequestBody Film newFilm) throws ValidationException { + + if (newFilm.getId() != null && films.containsKey(newFilm.getId())) { + films.put(newFilm.getId(), newFilm); + log.debug("Фильм успешно изменён"); + return newFilm; + } + throw new ValidationException("Некорректный Id"); + } + + private int getNextId() { + return nextId++; + + } } diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java b/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java new file mode 100644 index 0000000..3d67a63 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java @@ -0,0 +1,63 @@ +package ru.yandex.practicum.filmorate.controller; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.*; +import ru.yandex.practicum.filmorate.exception.ValidationException; +import ru.yandex.practicum.filmorate.model.User; + +import java.time.LocalDate; +import java.util.Collection; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +@RestController +@RequestMapping("/users") +@Slf4j +public class UserController { + private final Map users = new ConcurrentHashMap<>(); + private int nextId = 1; + + @GetMapping + public Collection getUsers() { + return users.values(); + } + + @PostMapping + public User createUser(@RequestBody User user) throws ValidationException { + if (user.getEmail().isEmpty() || !user.getEmail().contains("@")) { + throw new ValidationException("Электронная почта не может быть пустой и должна содержать символ @"); + } + if (user.getLogin() == null || user.getLogin().isEmpty() || user.getLogin().contains(" ")) { + throw new ValidationException("Логин не может быть пустым и содержать пробелы"); + } + if (user.getName() == null) { + user.setName(user.getLogin()); + } + if (user.getBirthday().isAfter(LocalDate.now())) { + throw new ValidationException("Дата рождения не может быть в будущем"); + } + user.setId(getNextId()); + users.put(user.getId(), user); + log.debug("Пользователь успешно добавлен"); + return user; + } + + @PutMapping + public User updateUser(@RequestBody User newUser) throws ValidationException { + + if (newUser.getId() != null && users.containsKey(newUser.getId())) { + users.put(newUser.getId(), newUser); + log.debug("Пользователь успешно изменён"); + return newUser; + } + + throw new ValidationException("Некорректный Id"); + + } + + + private int getNextId() { + return nextId++; + + } +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/exception/ValidationException.java b/src/main/java/ru/yandex/practicum/filmorate/exception/ValidationException.java new file mode 100644 index 0000000..fd0100a --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/exception/ValidationException.java @@ -0,0 +1,7 @@ +package ru.yandex.practicum.filmorate.exception; + +public class ValidationException extends Exception { + public ValidationException(String message) { + super(message); + } +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/model/Film.java b/src/main/java/ru/yandex/practicum/filmorate/model/Film.java index 3614a44..8063357 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/model/Film.java +++ b/src/main/java/ru/yandex/practicum/filmorate/model/Film.java @@ -1,12 +1,22 @@ package ru.yandex.practicum.filmorate.model; import lombok.Getter; +import lombok.NoArgsConstructor; import lombok.Setter; +import java.time.LocalDate; + /** * Film. */ @Getter @Setter +@NoArgsConstructor public class Film { + private Integer id; + private String name; + private String description; + private LocalDate releaseDate; + private Long duration; + } diff --git a/src/main/java/ru/yandex/practicum/filmorate/model/User.java b/src/main/java/ru/yandex/practicum/filmorate/model/User.java new file mode 100644 index 0000000..a489737 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/model/User.java @@ -0,0 +1,19 @@ +package ru.yandex.practicum.filmorate.model; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.time.LocalDate; + +@Getter +@Setter +@NoArgsConstructor +public class User { + private Integer id; + private String email; + private String login; + private String name; + private LocalDate birthday; + +} diff --git a/src/test/java/ru/yandex/practicum/filmorate/controller/FilmControllerTest.java b/src/test/java/ru/yandex/practicum/filmorate/controller/FilmControllerTest.java new file mode 100644 index 0000000..af87af4 --- /dev/null +++ b/src/test/java/ru/yandex/practicum/filmorate/controller/FilmControllerTest.java @@ -0,0 +1,89 @@ +package ru.yandex.practicum.filmorate.controller; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import ru.yandex.practicum.filmorate.exception.ValidationException; +import ru.yandex.practicum.filmorate.model.Film; + +import java.time.LocalDate; +import java.util.Collection; + +import static org.junit.jupiter.api.Assertions.*; + +@SpringBootTest +public class FilmControllerTest { + + @Autowired + private FilmController filmController; + + @Test + public void returnFilmsTest() throws ValidationException { + Film film1 = new Film(); + film1.setName("filmName1"); + film1.setDescription("Descr1"); + film1.setReleaseDate(LocalDate.of(2023, 12, 15)); + film1.setDuration(168L); + + Film film2 = new Film(); + film2.setName("filmName2"); + film2.setDescription("Descr2"); + film2.setReleaseDate(LocalDate.of(2023, 12, 15)); + film2.setDuration(168L); + + filmController.createFilm(film1); + filmController.createFilm(film2); + + Collection films = filmController.getFilms(); + + assertTrue(films.contains(film1)); + assertTrue(films.contains(film2)); + } + + @Test + void filmsValidTest() throws ValidationException { + Film film = new Film(); + film.setName("filmName1"); + film.setDescription("Descr1"); + film.setReleaseDate(LocalDate.of(2023, 12, 15)); + film.setDuration(168L); + + Film savedFilm = filmController.createFilm(film); + + assertNotNull(savedFilm.getId()); + assertEquals("filmName1", savedFilm.getName()); + assertEquals("Descr1", savedFilm.getDescription()); + assertEquals(LocalDate.of(2023, 12, 15), savedFilm.getReleaseDate()); + assertEquals(168L, savedFilm.getDuration()); + + film.setName(null); + assertThrows(ValidationException.class, () -> filmController.createFilm(film)); + + film.setName("filmName1"); + film.setDescription("1111111111111111111111111111111111111111111111111111111111111111111" + "111111111111111111111111111111111111111111111111111111111111111111111111111111111" + "111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"); + assertThrows(ValidationException.class, () -> filmController.createFilm(film)); + + film.setDescription("Descr1"); + film.setReleaseDate(LocalDate.of(1894, 12, 15)); + assertThrows(ValidationException.class, () -> filmController.createFilm(film)); + + film.setReleaseDate(LocalDate.of(2023, 12, 15)); + film.setDuration(-1L); + assertThrows(ValidationException.class, () -> filmController.createFilm(film)); + } + + @Test + void updateFilmTest() throws ValidationException { + Film film = new Film(); + film.setName("filmName1"); + film.setDescription("Descr1"); + film.setReleaseDate(LocalDate.of(2023, 12, 15)); + film.setDuration(168L); + + filmController.createFilm(film); + + Film filmUpdate = new Film(); + filmUpdate.setId(8); + assertThrows(ValidationException.class, () -> filmController.updateFilm(filmUpdate)); + } +} diff --git a/src/test/java/ru/yandex/practicum/filmorate/controller/UserControllerTest.java b/src/test/java/ru/yandex/practicum/filmorate/controller/UserControllerTest.java new file mode 100644 index 0000000..8f40a1a --- /dev/null +++ b/src/test/java/ru/yandex/practicum/filmorate/controller/UserControllerTest.java @@ -0,0 +1,99 @@ +package ru.yandex.practicum.filmorate.controller; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import ru.yandex.practicum.filmorate.exception.ValidationException; +import ru.yandex.practicum.filmorate.model.User; + +import java.time.LocalDate; +import java.util.Collection; + +import static org.junit.jupiter.api.Assertions.*; + + +@SpringBootTest +public class UserControllerTest { + + + @Autowired + private UserController userController = new UserController(); + + @Test + public void returnsUsersTest() throws ValidationException { + User user1 = new User(); + user1.setEmail("user1@yandex.ru"); + user1.setLogin("user1"); + user1.setName("User1"); + user1.setBirthday(LocalDate.of(1999, 8, 6)); + + User user2 = new User(); + user2.setEmail("user2@yandex.ru"); + user2.setLogin("user2"); + user2.setName("User2"); + user2.setBirthday(LocalDate.of(1991, 3, 20)); + + userController.createUser(user1); + userController.createUser(user2); + + Collection users = userController.getUsers(); + + assertTrue(users.contains(user1)); + assertTrue(users.contains(user2)); + } + + @Test + void userValidTest() throws ValidationException { + User user = new User(); + user.setEmail("user1@yandex.ru"); + user.setLogin("user1"); + user.setName("user1"); + user.setBirthday(LocalDate.of(1999, 8, 6)); + + User savedUser1 = userController.createUser(user); + + assertNotNull(savedUser1.getId()); + assertEquals("user1@yandex.ru", savedUser1.getEmail()); + assertEquals("user1", savedUser1.getLogin()); + assertEquals("user1", savedUser1.getName()); + assertEquals(LocalDate.of(1999, 8, 6), savedUser1.getBirthday()); + + user.setEmail("12345"); + assertThrows(ValidationException.class, () -> userController.createUser(user)); + + user.setEmail("user3.com"); + assertThrows(ValidationException.class, () -> userController.createUser(user)); + + user.setEmail("user1@yandex.ru"); + user.setLogin(""); + assertThrows(ValidationException.class, () -> userController.createUser(user)); + + user.setLogin(null); + assertThrows(ValidationException.class, () -> userController.createUser(user)); + + user.setLogin("user 1"); + assertThrows(ValidationException.class, () -> userController.createUser(user)); + + user.setBirthday(LocalDate.now().plusMonths(5)); + assertThrows(ValidationException.class, () -> userController.createUser(user)); + } + + @Test + void updateUserTest() throws ValidationException { + User user1 = new User(); + user1.setEmail("user1@yandex.ru"); + user1.setLogin("user1"); + user1.setName(null); + user1.setBirthday(LocalDate.of(1999, 8, 6)); + + userController.createUser(user1); + + User userUpdate = new User(); + userUpdate.setEmail("user1@yandex.ru"); + userUpdate.setLogin("user1"); + userUpdate.setName(null); + userUpdate.setBirthday(LocalDate.of(1999, 8, 6)); + userUpdate.setId(8); + assertThrows(ValidationException.class, () -> userController.updateUser(userUpdate)); + } +}