From 4b30e9cfd8d211ffd7ae8afcc702e4b3d7dd82e0 Mon Sep 17 00:00:00 2001 From: Nikita Date: Wed, 21 Feb 2024 13:46:57 +0400 Subject: [PATCH] refactor --- pom.xml | 4 + .../filmorate/FilmorateApplication.java | 6 +- .../filmorate/constant/Constant.java | 12 ++ .../filmorate/controller/FilmController.java | 49 +++++- .../filmorate/controller/UserController.java | 57 ++++++ .../filmorate/exception/HandlerException.java | 15 ++ .../filmorate/exception/ResponseError.java | 10 ++ .../filmorate/exception/ValidException.java | 14 ++ .../practicum/filmorate/model/Film.java | 27 ++- .../practicum/filmorate/model/User.java | 30 ++++ .../filmorate/service/FilmService.java | 47 +++++ .../filmorate/service/UserService.java | 47 +++++ .../filmorate/storage/film/FilmStorage.java | 22 +++ .../storage/film/InMemoryFilmStorage.java | 121 +++++++++++++ .../storage/user/InMemoryUserStorage.java | 165 ++++++++++++++++++ .../filmorate/storage/user/UserStorage.java | 23 +++ .../practicum/filmorate/model/FilmTest.java | 63 +++++++ .../FilmorateApplicationTests.java | 8 +- .../practicum/filmorate/model/UserTest.java | 63 +++++++ 19 files changed, 768 insertions(+), 15 deletions(-) create mode 100644 src/main/java/ru/yandex/practicum/filmorate/constant/Constant.java create mode 100644 src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java create mode 100644 src/main/java/ru/yandex/practicum/filmorate/exception/HandlerException.java create mode 100644 src/main/java/ru/yandex/practicum/filmorate/exception/ResponseError.java create mode 100644 src/main/java/ru/yandex/practicum/filmorate/exception/ValidException.java create mode 100644 src/main/java/ru/yandex/practicum/filmorate/model/User.java create mode 100644 src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java create mode 100644 src/main/java/ru/yandex/practicum/filmorate/service/UserService.java create mode 100644 src/main/java/ru/yandex/practicum/filmorate/storage/film/FilmStorage.java create mode 100644 src/main/java/ru/yandex/practicum/filmorate/storage/film/InMemoryFilmStorage.java create mode 100644 src/main/java/ru/yandex/practicum/filmorate/storage/user/InMemoryUserStorage.java create mode 100644 src/main/java/ru/yandex/practicum/filmorate/storage/user/UserStorage.java create mode 100644 src/test/java/ru/yandex/practicum/filmorate/model/FilmTest.java rename src/test/java/ru/yandex/practicum/filmorate/{ => model}/FilmorateApplicationTests.java (63%) create mode 100644 src/test/java/ru/yandex/practicum/filmorate/model/UserTest.java diff --git a/pom.xml b/pom.xml index 371c29c8..c9429565 100644 --- a/pom.xml +++ b/pom.xml @@ -32,6 +32,10 @@ spring-boot-starter-test test + + org.springframework.boot + spring-boot-starter-validation + diff --git a/src/main/java/ru/yandex/practicum/filmorate/FilmorateApplication.java b/src/main/java/ru/yandex/practicum/filmorate/FilmorateApplication.java index dca451bc..843905e2 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/constant/Constant.java b/src/main/java/ru/yandex/practicum/filmorate/constant/Constant.java new file mode 100644 index 00000000..e4a03002 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/constant/Constant.java @@ -0,0 +1,12 @@ +package ru.yandex.practicum.filmorate.constant; + +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; + +public class Constant { + public static final String SIZE_OF_FILMS = "10"; + public static final String REGEX_LOGIN = "^\\S*$"; + public static final String REGEX_EMAIL = "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"; + public static final LocalDate REGEX_DATE = LocalDate.of(1895, 12, 28); + public static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd"); +} 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 08cf0a18..f0755011 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,54 @@ package ru.yandex.practicum.filmorate.controller; -import org.springframework.web.bind.annotation.RestController; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; +import ru.yandex.practicum.filmorate.model.Film; +import ru.yandex.practicum.filmorate.service.FilmService; +import javax.validation.Valid; +import java.util.List; + +import static ru.yandex.practicum.filmorate.constant.Constant.SIZE_OF_FILMS; + +@RequiredArgsConstructor @RestController +@RequestMapping("/films") public class FilmController { + + private final FilmService filmService; + + @PutMapping("/{id}/like/{userId}") + public Film addLike(@PathVariable int id, @PathVariable int userId) { + return filmService.addLike(id, userId); + } + + @DeleteMapping("/{id}/like/{userId}") + public Film deleteLike(@PathVariable int id, @PathVariable int userId) { + return filmService.deleteLike(id, userId); + } + + @GetMapping("/popular") + public List getTopTenOfFilms(@RequestParam(defaultValue = SIZE_OF_FILMS) String count) { + return filmService.getTopTenOfFilms(count); + } + + @GetMapping("/{id}") + public Film getFilm(@PathVariable int id) { + return filmService.getFilm(id); + } + + @PostMapping + public Film createFilm(@Valid @RequestBody Film film) { + return filmService.createFilm(film); + } + + @PutMapping + public Film updateFilm(@Valid @RequestBody Film film) { + return filmService.updateFilm(film); + } + + @GetMapping + public List getALlFilms() { + return filmService.getALlFilms(); + } } 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 00000000..5600580d --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java @@ -0,0 +1,57 @@ +package ru.yandex.practicum.filmorate.controller; + +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; +import ru.yandex.practicum.filmorate.model.User; +import ru.yandex.practicum.filmorate.service.UserService; + +import javax.validation.Valid; +import java.util.List; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/users") +public class UserController { + + private final UserService userService; + + @PutMapping("/{id}/friends/{friendId}") + public User addFriend(@PathVariable int id, @PathVariable int friendId) { + return userService.addFriend(id, friendId); + } + + @DeleteMapping("/{id}/friends/{friendId}") + public User deleteFriend(@PathVariable int id, @PathVariable int friendId) { + return userService.deleteFriend(id, friendId); + } + + @GetMapping("/{id}/friends/common/{otherId}") + public List getCommonFriends(@PathVariable int id, @PathVariable int otherId) { + return userService.getCommonFriends(id, otherId); + } + + @GetMapping("/{id}/friends") + public List getFriends(@PathVariable int id) { + return userService.getFriends(id); + } + + @PostMapping + public User createUser(@Valid @RequestBody User user) { + return userService.createUser(user); + } + + @GetMapping("/{id}") + public User getUser(@PathVariable int id) { + return userService.getUser(id); + } + + @PutMapping + public User updateUser(@Valid @RequestBody User user) { + return userService.updateUser(user); + } + + @GetMapping + public List getALlUsers() { + return userService.getALlUsers(); + } +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/exception/HandlerException.java b/src/main/java/ru/yandex/practicum/filmorate/exception/HandlerException.java new file mode 100644 index 00000000..cc1eeded --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/exception/HandlerException.java @@ -0,0 +1,15 @@ +package ru.yandex.practicum.filmorate.exception; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +@RestControllerAdvice +public class HandlerException { + @ExceptionHandler(ValidException.class) + public ResponseEntity notFound(ValidException e) { + return new ResponseEntity<>(ResponseError.builder() + .message(e.getMessage()) + .build(), e.getStatus()); + } +} \ No newline at end of file diff --git a/src/main/java/ru/yandex/practicum/filmorate/exception/ResponseError.java b/src/main/java/ru/yandex/practicum/filmorate/exception/ResponseError.java new file mode 100644 index 00000000..bccbc375 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/exception/ResponseError.java @@ -0,0 +1,10 @@ +package ru.yandex.practicum.filmorate.exception; + +import lombok.Builder; +import lombok.Data; + +@Builder +@Data +public class ResponseError { + private String message; +} \ No newline at end of file diff --git a/src/main/java/ru/yandex/practicum/filmorate/exception/ValidException.java b/src/main/java/ru/yandex/practicum/filmorate/exception/ValidException.java new file mode 100644 index 00000000..4ee0601a --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/exception/ValidException.java @@ -0,0 +1,14 @@ +package ru.yandex.practicum.filmorate.exception; + +import lombok.*; +import org.springframework.http.HttpStatus; + +@AllArgsConstructor +@Getter +@ToString +@Setter +@Builder +public class ValidException extends RuntimeException { + private String message; + private HttpStatus status; +} 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 3614a44b..4e01417a 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,25 @@ package ru.yandex.practicum.filmorate.model; -import lombok.Getter; -import lombok.Setter; +import lombok.Builder; +import lombok.Data; -/** - * Film. - */ -@Getter -@Setter +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.Positive; +import javax.validation.constraints.Size; +import java.time.LocalDate; +import java.util.Set; + +@Data +@Builder public class Film { + private Integer id; + @NotEmpty(message = "Имя не может быть пустым") + @Size(max = 255, min = 1, message = "Максимальная длина имени - 255 символов") + private String name; + @Size(max = 200, min = 1, message = "Максимальная длина описания - 200 символов") + private String description; + private LocalDate releaseDate; + @Positive(message = "Продолжительность не может быть отрицательной") + private Integer duration; + private Set likes; } 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 00000000..f9dcd5e6 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/model/User.java @@ -0,0 +1,30 @@ +package ru.yandex.practicum.filmorate.model; + +import lombok.Builder; +import lombok.Data; + +import javax.validation.constraints.Email; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.Past; +import javax.validation.constraints.Pattern; +import java.time.LocalDate; +import java.util.Set; + +import static ru.yandex.practicum.filmorate.constant.Constant.REGEX_EMAIL; +import static ru.yandex.practicum.filmorate.constant.Constant.REGEX_LOGIN; + +@Data +@Builder +public class User { + private Integer id; + @NotEmpty(message = "Почта не может быть пустая") + @Email(regexp = REGEX_EMAIL, message = "В 'email' использованы запрещённые символы") + private String email; + @NotEmpty(message = "Логин не может быть пустым") + @Pattern(regexp = REGEX_LOGIN, message = "В 'login' использованы запрещённые символы") + private String login; + private String name; + @Past(message = "День рождения не может быть указан в будущем") + private LocalDate birthday; + private Set friends; +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java b/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java new file mode 100644 index 00000000..1a9d2780 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java @@ -0,0 +1,47 @@ +package ru.yandex.practicum.filmorate.service; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import ru.yandex.practicum.filmorate.model.Film; +import ru.yandex.practicum.filmorate.storage.film.FilmStorage; + +import java.util.List; + + +@RequiredArgsConstructor +@Service +public class FilmService { + + private final FilmStorage filmStorage; + + public Film getFilm(int id) { + return filmStorage.getFilm(id); + } + + public Film addLike(int id, int userId) { + return filmStorage.addLike(id, userId); + } + + public Film deleteLike(int id, int userId) { + return filmStorage.deleteLike(id, userId); + } + + public List getTopTenOfFilms(String count) { + int count1 = Integer.parseInt(count); + return filmStorage.getTopTenOfFilms(count1); + } + + public Film createFilm(Film film) { + return filmStorage.createFilm(film); + } + + + public Film updateFilm(Film film) { + return filmStorage.updateFilm(film); + } + + + public List getALlFilms() { + return filmStorage.getALlFilms(); + } +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java b/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java new file mode 100644 index 00000000..fe5885b1 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java @@ -0,0 +1,47 @@ +package ru.yandex.practicum.filmorate.service; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import ru.yandex.practicum.filmorate.model.User; +import ru.yandex.practicum.filmorate.storage.user.UserStorage; + +import java.util.List; + +@Service +@RequiredArgsConstructor +public class UserService { + + private final UserStorage userStorage; + + public User addFriend(int id, int friendId) { + return userStorage.addFriend(id, friendId); + } + + public User deleteFriend(int id, int friendId) { + return userStorage.deleteFriend(id, friendId); + } + + public List getCommonFriends(int id, int otherId) { + return userStorage.getCommonFriends(id, otherId); + } + + public List getFriends(int id) { + return userStorage.getFriends(id); + } + + public User createUser(User user) { + return userStorage.createUser(user); + } + + public User updateUser(User user) { + return userStorage.updateUser(user); + } + + public User getUser(int id) { + return userStorage.getUser(id); + } + + public List getALlUsers() { + return userStorage.getALlUsers(); + } +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/film/FilmStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/film/FilmStorage.java new file mode 100644 index 00000000..1a35cd10 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/film/FilmStorage.java @@ -0,0 +1,22 @@ +package ru.yandex.practicum.filmorate.storage.film; + +import ru.yandex.practicum.filmorate.model.Film; + +import java.util.List; + +public interface FilmStorage { + + Film getFilm(int id); + + List getTopTenOfFilms(int count); + + Film addLike(int id, int userId); + + Film deleteLike(int id, int userId); + + Film createFilm(Film film); + + Film updateFilm(Film film); + + List getALlFilms(); +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/film/InMemoryFilmStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/film/InMemoryFilmStorage.java new file mode 100644 index 00000000..fd3923e2 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/film/InMemoryFilmStorage.java @@ -0,0 +1,121 @@ +package ru.yandex.practicum.filmorate.storage.film; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Repository; +import ru.yandex.practicum.filmorate.exception.ValidException; +import ru.yandex.practicum.filmorate.model.Film; +import ru.yandex.practicum.filmorate.storage.user.InMemoryUserStorage; + +import java.time.LocalDate; +import java.util.*; +import java.util.stream.Collectors; + +import static ru.yandex.practicum.filmorate.constant.Constant.FORMATTER; +import static ru.yandex.practicum.filmorate.constant.Constant.REGEX_DATE; + + +@Slf4j +@Repository +@RequiredArgsConstructor +public class InMemoryFilmStorage implements FilmStorage { + private final Map films = new HashMap<>(); + private final InMemoryUserStorage userStorage; + + private Integer id = 0; + + private Integer createId() { + return ++id; + } + + public Film getFilm(int id) { + if (films.containsKey(id)) { + return films.get(id); + } else { + log.info("Фильма с таким id нет"); + throw new ValidException("Фильма с таким id нет", HttpStatus.NOT_FOUND); + } + } + + + public Film addLike(int id, int userId) { + if (films.containsKey(id) && userStorage.doesIdExist(userId)) { + films.get(id).getLikes().add(userId); + return films.get(id); + } else { + log.info("Пользователя или фильма с таким id нет"); + throw new ValidException("Пользователя или фильма с таким id нет", HttpStatus.NOT_FOUND); + } + } + + public Film deleteLike(int id, int userId) { + if (films.containsKey(id) && userStorage.doesIdExist(userId)) { + if (films.get(id).getLikes().contains(userId)) { + films.get(id).getLikes().remove(userId); + return films.get(id); + } else { + log.info("Лайка с таким id нет"); + throw new ValidException("Лайка с таким id нет", HttpStatus.NOT_FOUND); + } + } else { + log.info("Фильма с таким id нет"); + throw new ValidException("Фильма с таким id нет", HttpStatus.NOT_FOUND); + } + } + + public List getTopTenOfFilms(int count) { + return films.values().stream() + .sorted(Comparator.comparingInt(film -> -film.getLikes().size())) + .limit(count) + .collect(Collectors.toList()); + } + + public Film createFilm(Film film) { + if (validDate(film.getReleaseDate())) { + film.setId(createId()); + films.put(film.getId(), film); + film.setLikes(new HashSet<>()); + log.info("Фильм " + film.getName() + " добавлен"); + return film; + + } else { + log.info("Невозможно добавить фильм {} из за года выпуска", film); + throw new ValidException("Невозможно добавить фильм " + film + " из за года выпуска", HttpStatus.BAD_REQUEST); + } + } + + + public Film updateFilm(Film film) { + if (validDate(film.getReleaseDate())) { + if (!films.containsKey(film.getId())) { + log.info("Фильма с таким id нет"); + throw new ValidException("Фильма с таким id нет", HttpStatus.NOT_FOUND); + } else { + if (film.getLikes() == null) { + film.setLikes(new HashSet<>()); + } + films.put(film.getId(), film); + log.info("Фильм {} обновлён", film.getName()); + return film; + } + } else { + log.info("Невозможно добавить фильм {} из за года выпуска", film); + throw new ValidException("Невозможно добавить фильм " + film + " из за года выпуска", HttpStatus.BAD_REQUEST); + } + } + + + public List getALlFilms() { + return new ArrayList<>(films.values()); + } + + private boolean validDate(LocalDate localDate) { + LocalDate date = LocalDate.parse(localDate.format(FORMATTER)); + if (date.isBefore(REGEX_DATE)) { + return false; + } else { + return true; + } + } +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/user/InMemoryUserStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/user/InMemoryUserStorage.java new file mode 100644 index 00000000..9eeed514 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/user/InMemoryUserStorage.java @@ -0,0 +1,165 @@ +package ru.yandex.practicum.filmorate.storage.user; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Repository; +import ru.yandex.practicum.filmorate.exception.ValidException; +import ru.yandex.practicum.filmorate.model.User; + +import java.util.*; + +@Repository +@Slf4j +public class InMemoryUserStorage implements UserStorage { + + private final Map users = new HashMap<>(); + + private Integer id = 0; + + private Integer createId() { + return ++id; + } + + public boolean doesIdExist(int id) { + return users.containsKey(id); + } + + public User getUser(int id) { + if (users.containsKey(id)) { + return users.get(id); + } else { + log.info("Пользователя с таким id нет"); + throw new ValidException("Пользователя с таким id нет", HttpStatus.NOT_FOUND); + } + } + + public List getFriends(int id) { + if (!users.isEmpty()) { + if (users.containsKey(id)) { + List friends = new ArrayList<>(); + for (Integer i : users.get(id).getFriends()) { + friends.add(users.get(i)); + } + return friends; + } else { + log.info("Пользователя с таким id нет"); + throw new ValidException("Пользователя с таким id нет", HttpStatus.NOT_FOUND); + } + } else { + log.info("Пользователя с таким id нет"); + throw new ValidException("Пользователя с таким id нет", HttpStatus.NOT_FOUND); + } + } + + public User addFriend(int id, int friendId) { + if (users.containsKey(id) && users.containsKey(friendId)) { + users.get(id).getFriends().add(friendId); + users.get(friendId).getFriends().add(id); + log.info("Пользователь с id:" + friendId + " успешно добавлен в друзья"); + return users.get(id); + } else { + log.info("Пользователя с таким id нет"); + throw new ValidException("Пользователя с таким id нет", HttpStatus.NOT_FOUND); + } + } + + + public User deleteFriend(int id, int friendId) { + if (!users.isEmpty()) { + if (users.containsKey(id) && users.containsKey(friendId)) { + if (!users.get(id).getFriends().isEmpty() && !users.get(friendId).getFriends().isEmpty()) { + users.get(id).getFriends().remove(friendId); + users.get(friendId).getFriends().remove(id); + log.info("Пользователь с id:" + friendId + " успешно удален из друзей"); + return users.get(id); + } else { + log.info("Пользователя с таким id нет"); + throw new ValidException("Пользователя с таким id нет", HttpStatus.NOT_FOUND); + } + } else { + log.info("Пользователя с таким id нет"); + throw new ValidException("Пользователя с таким id нет", HttpStatus.NOT_FOUND); + } + } else { + log.info("Пользователя с таким id нет"); + throw new ValidException("Пользователя с таким id нет", HttpStatus.NOT_FOUND); + } + } + + public List getCommonFriends(int id, int otherId) { + if (users.containsKey(id) && users.containsKey(otherId)) { + if (!users.get(id).getFriends().isEmpty() && !users.get(otherId).getFriends().isEmpty()) { + List friends = new ArrayList<>(); + for (Integer i : users.get(id).getFriends()) { + i = Integer.parseInt(String.valueOf(i)); + for (Integer ii : users.get(otherId).getFriends()) { + if (i.equals(ii)) { + friends.add(users.get(i)); + } + } + } + if (friends.isEmpty()) { + log.info("Общих друзей нет"); + return new ArrayList<>(); + } else { + return friends; + } + } else { + log.info("Общих друзей нет"); + return new ArrayList<>(); + } + } else { + log.info("Одного из пользователей с таким id нет"); + return new ArrayList<>(); + } + + } + + + public User createUser(User user) { + if (user.getName() == null || user.getName().isEmpty()) { + user.setName(user.getLogin()); + } + user.setId(createId()); + user.setFriends(new HashSet<>()); + users.put(user.getId(), user); + log.info("Пользователь" + user.getName() + " добавлен", HttpStatus.CREATED); + return user; + } + + + public User updateUser(User user) { + if (user.getName() == null || user.getName().isEmpty()) { + user.setName(user.getLogin()); + if (!users.containsKey(user.getId())) { + log.info("Пользователя с таким id нет"); + throw new ValidException("Пользователя с таким id нет", HttpStatus.NOT_FOUND); + } else { + if (user.getFriends() == null) { + user.setFriends(new HashSet<>()); + } + users.put(user.getId(), user); + log.info("Пользователь {} обновлён", user.getName()); + return user; + } + } else if (!user.getName().isBlank()) { + if (!users.containsKey(user.getId())) { + log.info("Пользователя с таким id нет"); + throw new ValidException("Пользователя с таким id нет", HttpStatus.NOT_FOUND); + } else { + if (user.getFriends() == null) { + user.setFriends(new HashSet<>()); + } + users.put(user.getId(), user); + log.info("Пользователь {} обновлён", user.getName()); + return user; + } + } else { + throw new ValidException("В имени присутствуют запрещённые символы", HttpStatus.BAD_REQUEST); + } + } + + public List getALlUsers() { + return new ArrayList<>(users.values()); + } +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/user/UserStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/user/UserStorage.java new file mode 100644 index 00000000..f007e93d --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/user/UserStorage.java @@ -0,0 +1,23 @@ +package ru.yandex.practicum.filmorate.storage.user; + +import ru.yandex.practicum.filmorate.model.User; + +import java.util.List; + +public interface UserStorage { + List getFriends(int id); + + User addFriend(int id, int friendId); + + User deleteFriend(int id, int friendId); + + List getCommonFriends(int id, int otherId); + + User createUser(User user); + + User updateUser(User user); + + List getALlUsers(); + + User getUser(int id); +} diff --git a/src/test/java/ru/yandex/practicum/filmorate/model/FilmTest.java b/src/test/java/ru/yandex/practicum/filmorate/model/FilmTest.java new file mode 100644 index 00000000..79b4d9d2 --- /dev/null +++ b/src/test/java/ru/yandex/practicum/filmorate/model/FilmTest.java @@ -0,0 +1,63 @@ +package ru.yandex.practicum.filmorate.model; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import javax.validation.ConstraintViolation; +import javax.validation.Validation; +import javax.validation.Validator; +import javax.validation.ValidatorFactory; +import java.time.LocalDate; +import java.util.Set; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; + +public class FilmTest { + private Validator validator; + + @BeforeEach + public void startMethod() { + ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); + validator = factory.getValidator(); + } + + @Test + public void whenNameIsBlank_thenValidationFails() { + Film film = Film.builder() + .name("") + .description("Valid Description") + .releaseDate(LocalDate.now()) + .duration(120) + .build(); + Set> violations = validator.validateProperty(film, "name"); + assertFalse(violations.isEmpty()); + assertEquals("Имя не может быть пустым", violations.iterator().next().getMessage()); + } + + @Test + public void whenDescriptionIsInvalid_thenValidationFails() { + Film film = Film.builder() + .name("Valid Name") + .description("") + .releaseDate(LocalDate.now()) + .duration(120) + .build(); + Set> violations = validator.validateProperty(film, "description"); + assertFalse(violations.isEmpty()); + assertEquals("Максимальная длина описания - 200 символов", violations.iterator().next().getMessage()); + } + + @Test + public void whenDurationIsNegative_thenValidationFails() { + Film film = Film.builder() + .name("Valid Name") + .description("Valid Description") + .releaseDate(LocalDate.now()) + .duration(-1) + .build(); + Set> violations = validator.validateProperty(film, "duration"); + assertFalse(violations.isEmpty()); + assertEquals("Продолжительность не может быть отрицательной", violations.iterator().next().getMessage()); + } +} \ No newline at end of file diff --git a/src/test/java/ru/yandex/practicum/filmorate/FilmorateApplicationTests.java b/src/test/java/ru/yandex/practicum/filmorate/model/FilmorateApplicationTests.java similarity index 63% rename from src/test/java/ru/yandex/practicum/filmorate/FilmorateApplicationTests.java rename to src/test/java/ru/yandex/practicum/filmorate/model/FilmorateApplicationTests.java index 660412e8..4fb41e08 100644 --- a/src/test/java/ru/yandex/practicum/filmorate/FilmorateApplicationTests.java +++ b/src/test/java/ru/yandex/practicum/filmorate/model/FilmorateApplicationTests.java @@ -1,4 +1,4 @@ -package ru.yandex.practicum.filmorate; +package ru.yandex.practicum.filmorate.model; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; @@ -6,8 +6,8 @@ @SpringBootTest class FilmorateApplicationTests { - @Test - void contextLoads() { - } + @Test + void contextLoads() { + } } diff --git a/src/test/java/ru/yandex/practicum/filmorate/model/UserTest.java b/src/test/java/ru/yandex/practicum/filmorate/model/UserTest.java new file mode 100644 index 00000000..ccc06491 --- /dev/null +++ b/src/test/java/ru/yandex/practicum/filmorate/model/UserTest.java @@ -0,0 +1,63 @@ +package ru.yandex.practicum.filmorate.model; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import ru.yandex.practicum.filmorate.storage.user.InMemoryUserStorage; +import ru.yandex.practicum.filmorate.storage.user.UserStorage; + +import javax.validation.ConstraintViolation; +import javax.validation.Validation; +import javax.validation.Validator; +import javax.validation.ValidatorFactory; +import java.time.LocalDate; +import java.util.Set; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; + +public class UserTest { + private Validator validator; + private UserStorage controller; + + @BeforeEach + public void startttMethod() { + ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); + validator = factory.getValidator(); + controller = new InMemoryUserStorage(); + } + + @Test + public void whenEmailIsInvalid_thenValidationFails() { + User user = User.builder() + .email("invalid-email") + .login("ValidLogin") + .birthday(LocalDate.of(1990, 1, 1)) + .build(); + Set> violations = validator.validateProperty(user, "email"); + assertFalse(violations.isEmpty()); + assertEquals("В 'email' использованы запрещённые символы", violations.iterator().next().getMessage()); + } + + @Test + public void whenLoginIsInvalid_thenValidationFails() { + User user = User.builder() + .email("valid.email@example.com") + .login("") + .birthday(LocalDate.of(1990, 1, 1)) + .build(); + controller.createUser(user); + assertEquals(user.getLogin(), user.getName()); + } + + @Test + public void whenBirthdayIsInTheFuture_thenValidationFails() { + User user = User.builder() + .email("valid.email@example.com") + .login("ValidLogin") + .birthday(LocalDate.now().plusDays(1)) + .build(); + Set> violations = validator.validateProperty(user, "birthday"); + assertFalse(violations.isEmpty()); + assertEquals("День рождения не может быть указан в будущем", violations.iterator().next().getMessage()); + } +} \ No newline at end of file