From 6ecd13c091d66c8cd54e1f55ade82709d278c27a Mon Sep 17 00:00:00 2001 From: Viktor64 Date: Mon, 20 Jan 2025 19:25:02 +0400 Subject: [PATCH 01/11] =?UTF-8?q?1)=20=D0=A1=D0=BE=D0=B7=D0=B4=D0=B0=D0=BB?= =?UTF-8?q?=20=D0=BD=D0=BE=D0=B2=D1=83=D1=8E=20=D0=B2=D0=B5=D1=82=D0=BA?= =?UTF-8?q?=D1=83=20add-friends-likes.=202)=20=D0=A1=D0=BE=D0=B7=D0=B4?= =?UTF-8?q?=D0=B0=D0=BB=20=D0=B8=D0=BD=D1=82=D0=B5=D1=80=D1=84=D0=B5=D0=B9?= =?UTF-8?q?=D1=81=D1=8B=20FilmStorage=20=D0=B8=20UserStorage,=20=D0=B2=20?= =?UTF-8?q?=D0=BA=D0=BE=D1=82=D0=BE=D1=80=D1=8B=D1=85=20=D0=B1=D1=83=D0=B4?= =?UTF-8?q?=D1=83=D1=82=20=D0=BE=D0=BF=D1=80=D0=B5=D0=B4=D0=B5=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D1=8B=20=D0=BC=D0=B5=D1=82=D0=BE=D0=B4=D1=8B=20=D0=B4?= =?UTF-8?q?=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F,=20?= =?UTF-8?q?=D1=83=D0=B4=D0=B0=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B8=20?= =?UTF-8?q?=D0=BC=D0=BE=D0=B4=D0=B8=D1=84=D0=B8=D0=BA=D0=B0=D1=86=D0=B8?= =?UTF-8?q?=D0=B8=20=D0=BE=D0=B1=D1=8A=D0=B5=D0=BA=D1=82=D0=BE=D0=B2.=203)?= =?UTF-8?q?=20=D0=A1=D0=BE=D0=B7=D0=B4=D0=B0=D0=BB=20=D0=BA=D0=BB=D0=B0?= =?UTF-8?q?=D1=81=D1=81=D1=8B=20InMemoryFilmStorage=20=D0=B8=20InMemoryUse?= =?UTF-8?q?rStorage,=20=D0=B8=D0=BC=D0=BF=D0=BB=D0=B5=D0=BC=D0=B5=D0=BD?= =?UTF-8?q?=D1=82=D0=B8=D1=80=D1=83=D1=8E=D1=89=D0=B8=D0=B5=20=D0=BD=D0=BE?= =?UTF-8?q?=D0=B2=D1=8B=D0=B5=20=D0=B8=D0=BD=D1=82=D0=B5=D1=80=D1=84=D0=B5?= =?UTF-8?q?=D0=B9=D1=81=D1=8B,=20=D0=B8=20=D0=BF=D0=B5=D1=80=D0=B5=D0=BD?= =?UTF-8?q?=D0=B5=D1=81=20=D0=B2=D1=81=D1=8E=20=D0=BB=D0=BE=D0=B3=D0=B8?= =?UTF-8?q?=D0=BA=D1=83=20=D1=85=D1=80=D0=B0=D0=BD=D0=B5=D0=BD=D0=B8=D1=8F?= =?UTF-8?q?,=20=D0=BE=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D1=8F=20=D0=B8=20=D0=BF=D0=BE=D0=B8=D1=81=D0=BA=D0=B0=20=D0=BE?= =?UTF-8?q?=D0=B1=D1=8A=D0=B5=D0=BA=D1=82=D0=BE=D0=B2.=204)=20=D0=A1=D0=BE?= =?UTF-8?q?=D0=B7=D0=B4=D0=B0=D0=BB=20UserService=20=D0=B8=20FilmService?= =?UTF-8?q?=20=D0=B4=D0=BB=D1=8F=20=D0=BE=D0=B1=D0=B5=D1=81=D0=BF=D0=B5?= =?UTF-8?q?=D1=87=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B2=D0=BE=D0=B7=D0=BC=D0=BE?= =?UTF-8?q?=D0=B6=D0=BD=D0=BE=D1=81=D1=82=D0=B8=20=D0=BF=D0=BE=D0=BB=D1=8C?= =?UTF-8?q?=D0=B7=D0=BE=D0=B2=D0=B0=D1=82=D0=B5=D0=BB=D1=8F=D0=BC=20=D0=B4?= =?UTF-8?q?=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D1=8F=D1=82=D1=8C=20=D0=B4=D1=80?= =?UTF-8?q?=D1=83=D0=B3=20=D0=B4=D1=80=D1=83=D0=B3=D0=B0=20=D0=B2=20=D0=B4?= =?UTF-8?q?=D1=80=D1=83=D0=B7=D1=8C=D1=8F=20=D0=B8=20=D1=81=D1=82=D0=B0?= =?UTF-8?q?=D0=B2=D0=B8=D1=82=D1=8C=20=D1=84=D0=B8=D0=BB=D1=8C=D0=BC=D0=B0?= =?UTF-8?q?=D0=BC=20=D0=BB=D0=B0=D0=B9=D0=BA=D0=B8.=205)=20=D0=A1=D0=BE?= =?UTF-8?q?=D0=B7=D0=B4=D0=B0=D0=BB=20=D0=BA=D0=BB=D0=B0=D1=81=D1=81=20Val?= =?UTF-8?q?idationService=20=D0=B4=D0=BB=D1=8F=20=D1=84=D0=BE=D0=BA=D1=83?= =?UTF-8?q?=D1=81=D0=B8=D1=80=D0=BE=D0=B2=D0=BA=D0=B8=20=D0=BD=D0=B0=20?= =?UTF-8?q?=D0=BF=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D0=BA=D0=B5=20=D0=BA=D0=BE?= =?UTF-8?q?=D0=BD=D0=BA=D1=80=D0=B5=D1=82=D0=BD=D1=8B=D1=85=20=D0=BF=D1=80?= =?UTF-8?q?=D0=B0=D0=B2=D0=B8=D0=BB=20=D0=B2=D0=B0=D0=BB=D0=B8=D0=B4=D0=B0?= =?UTF-8?q?=D1=86=D0=B8=D0=B8=20=D0=B4=D0=B0=D0=BD=D0=BD=D1=8B=D1=85=20?= =?UTF-8?q?=D0=B2=20=D0=B8=D0=B7=D0=BE=D0=BB=D1=8F=D1=86=D0=B8=D0=B8:=20?= =?UTF-8?q?=D0=9F=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D0=BA=D0=B8=20=D0=B4=D0=BB?= =?UTF-8?q?=D0=B8=D0=BD=D1=8B=20=D0=BE=D0=BF=D0=B8=D1=81=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D1=8F=20=D1=84=D0=B8=D0=BB=D1=8C=D0=BC=D0=B0,=20=D0=92=D0=B0?= =?UTF-8?q?=D0=BB=D0=B8=D0=B4=D0=B0=D1=86=D0=B8=D0=B8=20=D0=B8=D0=BC=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=20=D1=84=D0=B8=D0=BB=D1=8C=D0=BC=D0=B0,=20=D0=9F?= =?UTF-8?q?=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D0=BA=D0=B8=20email=20=D0=BF?= =?UTF-8?q?=D0=BE=D0=BB=D1=8C=D0=B7=D0=BE=D0=B2=D0=B0=D1=82=D0=B5=D0=BB?= =?UTF-8?q?=D1=8F,=20=D0=92=D0=B0=D0=BB=D0=B8=D0=B4=D0=B0=D1=86=D0=B8?= =?UTF-8?q?=D0=B8=20=D0=BB=D0=BE=D0=B3=D0=B8=D0=BD=D0=B0=20=D0=B8=20=D1=82?= =?UTF-8?q?.=D0=B4.=206)=20=D0=A1=D0=BE=D0=B7=D0=B4=D0=B0=D0=BB=20=D1=82?= =?UTF-8?q?=D0=B5=D1=81=D1=82=D1=8B=20=D0=BD=D0=B0=20=D0=BD=D0=BE=D0=B2?= =?UTF-8?q?=D1=83=D1=8E=20=D1=84=D0=B8=D1=87=D1=83:=20=D1=82=D0=B5=D1=81?= =?UTF-8?q?=D1=82=D1=8B=20=D1=84=D0=B8=D0=BB=D1=8C=D0=BC=D0=B0,=20=D1=82?= =?UTF-8?q?=D0=B5=D1=81=D1=82=D1=8B=20=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7=D0=BE?= =?UTF-8?q?=D0=B2=D0=B0=D1=82=D0=B5=D0=BB=D1=8F,=20=D1=82=D0=B5=D1=81?= =?UTF-8?q?=D1=82=D1=8B=20=D0=BB=D0=B0=D0=B9=D0=BA=D0=BE=D0=B2,=20=D1=82?= =?UTF-8?q?=D0=B5=D1=81=D1=82=D1=8B=20=D0=B4=D1=80=D1=83=D0=B7=D0=B5=D0=B9?= =?UTF-8?q?.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 5 + .../filmorate/controller/FilmController.java | 27 ++- .../filmorate/controller/UserController.java | 27 +++ .../practicum/filmorate/model/Film.java | 2 + .../filmorate/model/LikeComparator.java | 29 +++ .../practicum/filmorate/model/User.java | 12 + .../filmorate/service/FilmService.java | 89 ++++++++ .../filmorate/service/UserService.java | 112 ++++++++++ .../filmorate/service/ValidationService.java | 138 ++++++++++++ .../filmorate/storage/FilmStorage.java | 20 ++ .../storage/InMemoryFilmStorage.java | 65 ++++++ .../storage/InMemoryUserStorage.java | 82 +++++++ .../filmorate/storage/UserStorage.java | 30 +++ src/main/resources/application.properties | 2 +- .../filmorate/ValidationServiceTests.java | 206 ++++++++++++++++++ 15 files changed, 842 insertions(+), 4 deletions(-) create mode 100644 src/main/java/ru/yandex/practicum/filmorate/model/LikeComparator.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/service/ValidationService.java create mode 100644 src/main/java/ru/yandex/practicum/filmorate/storage/FilmStorage.java create mode 100644 src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryFilmStorage.java create mode 100644 src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorage.java create mode 100644 src/main/java/ru/yandex/practicum/filmorate/storage/UserStorage.java create mode 100644 src/test/java/ru/yandex/practicum/filmorate/ValidationServiceTests.java diff --git a/pom.xml b/pom.xml index 4eed7f0..33ec9a6 100644 --- a/pom.xml +++ b/pom.xml @@ -55,6 +55,11 @@ org.springframework.boot spring-boot-starter-validation + + org.zalando + logbook-spring-boot-starter + 3.7.2 + 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 f16ce6b..87f7d3a 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java @@ -3,10 +3,13 @@ import org.springframework.http.HttpStatus; import ru.yandex.practicum.filmorate.exceptions.UserNotFoundException; import ru.yandex.practicum.filmorate.exceptions.ValidationException; - -import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.*; import ru.yandex.practicum.filmorate.model.Film; +import ru.yandex.practicum.filmorate.service.FilmService; + +import java.util.Collection; + +import org.slf4j.LoggerFactory; import org.slf4j.Logger; import jakarta.validation.Valid; @@ -20,10 +23,10 @@ @RestController @RequestMapping("/films") public class FilmController { - private final Map films = new HashMap<>(); private final LocalDate dayOfCreationCinema = LocalDate.of(1895, 12, 28); private static final Logger log = LoggerFactory.getLogger(FilmController.class); + private FilmService filmService; private Long getNextId() { long currentMaxId = films.keySet() @@ -75,4 +78,22 @@ public Film updateFilm(@Valid @RequestBody Film film) { log.error("Фильм с id = {} не найден", film.getId()); throw new UserNotFoundException("Фильм с id = " + film.getId() + " не найден"); } + + @PutMapping("/{id}/like/{userId}") + public void addLike(@PathVariable long userId, @PathVariable long id) { + log.info("Добавлен лайк пользователем с id: " + userId + ". К фильму с id: " + id); + filmService.addLike(userId, id); + } + + @DeleteMapping("/{id}/like/{userId}") + public void deleteLike(@PathVariable long userId, @PathVariable long id) { + filmService.deleteLike(userId, id); + log.info("Удален лайк пользователем с id: " + userId + ". К фильму с id: " + id); + } + + @GetMapping("/popular") + public Collection getPopularFilms(@RequestParam(required = false, defaultValue = "10") Integer count) { + log.info("Получен список популярных фильмов"); + return filmService.getPopularFilms(count); + } } diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java b/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java index e4c632a..4d16d5d 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java @@ -9,6 +9,7 @@ import ru.yandex.practicum.filmorate.model.User; import jakarta.validation.Valid; +import ru.yandex.practicum.filmorate.service.UserService; import java.util.*; @@ -19,6 +20,8 @@ public class UserController { private final Set emails = new HashSet<>(); private final Set logins = new HashSet<>(); private static final Logger log = LoggerFactory.getLogger(UserController.class); + private UserService userService; + private Long getNextId() { long currentMaxId = users.keySet() @@ -92,4 +95,28 @@ public User updateUser(@Valid @RequestBody User newUser) { log.error("Пользователь с id {} не найден", newUser.getId()); throw new UserNotFoundException("Пользователь с id =" + newUser.getId() + " не найден"); } + + @PutMapping("/{id}/friends/{friendId}") + public void addFriend(@PathVariable long id, @PathVariable long friendId) { + log.info("Пошел процесс добавления друга с id:" + friendId + ". Пользователем id:" + id); + userService.addFriend(id, friendId); + } + + @DeleteMapping("/{id}/friends/{friendId}") + public void deleteFriend(@PathVariable long id, @PathVariable long friendId) { + log.info("Пошел процесс удаления друга с id:" + friendId + ". Пользователем id:" + id); + userService.deleteFriend(id, friendId); + } + + @GetMapping("/{id}/friends") + public Collection allIdFriends(@PathVariable long id) { + log.info("Идет процесс получения друзей у пользователя с id: " + id); + return userService.allIdFriends(id); + } + + @GetMapping("/{id}/friends/common/{otherId}") + public Collection generalFriends(@PathVariable long id, @PathVariable long otherId) { + log.info("Идет процесс получения общих друзей у пользователя с id: " + id + ". C пользователя с id: " + otherId); + return userService.generalFriends(id, otherId); + } } \ No newline at end of file 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 211690c..e54b48e 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/model/Film.java +++ b/src/main/java/ru/yandex/practicum/filmorate/model/Film.java @@ -5,6 +5,7 @@ import ru.yandex.practicum.filmorate.validation.ReleaseDateValidation; import java.time.LocalDate; +import java.util.Set; @Data public class Film { @@ -24,4 +25,5 @@ public class Film { @NotNull(message = "Длительность не может быть пустой") @PositiveOrZero(message = "Длительность фильма должна быть больше или равна нулю") private Integer duration; + Set idUserLikes; } \ No newline at end of file diff --git a/src/main/java/ru/yandex/practicum/filmorate/model/LikeComparator.java b/src/main/java/ru/yandex/practicum/filmorate/model/LikeComparator.java new file mode 100644 index 0000000..20e6d87 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/model/LikeComparator.java @@ -0,0 +1,29 @@ +package ru.yandex.practicum.filmorate.model; + +import java.util.Comparator; + +public class LikeComparator implements Comparator { + @Override + public int compare(Film film1, Film film2) { + int size1; + int size2; + if (film1.getIdUserLikes() != null) { + size1 = film1.getIdUserLikes().size(); + } else { + size1 = 0; + } + if (film2.getIdUserLikes() != null) { + size2 = film2.getIdUserLikes().size(); + } else { + size2 = 0; + } + + int comparison = Integer.compare(size2, size1); + + if (comparison == 0) { + return Long.compare(film1.getId(), film2.getId()); + } + + return comparison; + } +} \ No newline at end of file diff --git a/src/main/java/ru/yandex/practicum/filmorate/model/User.java b/src/main/java/ru/yandex/practicum/filmorate/model/User.java index 04fcecb..b23a9fa 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/model/User.java +++ b/src/main/java/ru/yandex/practicum/filmorate/model/User.java @@ -4,6 +4,8 @@ import lombok.Data; import java.time.LocalDate; +import java.util.HashSet; +import java.util.Set; @Data public class User { @@ -33,4 +35,14 @@ public void setLogin(String login) { this.name = login; // Или любое другое значение по умолчанию } } + + private Set friends = new HashSet<>(); + + public Set getFriends() { + return friends; + } + + public void setFriends(Set friends) { + this.friends = friends; + } } \ No newline at end of file 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 0000000..f676f64 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java @@ -0,0 +1,89 @@ +package ru.yandex.practicum.filmorate.service; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import ru.yandex.practicum.filmorate.model.Film; +import ru.yandex.practicum.filmorate.model.LikeComparator; +import ru.yandex.practicum.filmorate.model.User; +import ru.yandex.practicum.filmorate.storage.FilmStorage; +import ru.yandex.practicum.filmorate.storage.UserStorage; + +import java.util.*; + +@Slf4j +@Service +@RequiredArgsConstructor +public class FilmService { + + private final FilmStorage filmStorage; + private final UserStorage userStorage; + + private final LikeComparator likeComparator = new LikeComparator(); + + public Collection getAllFilms() { + return filmStorage.getAllFilms(); + } + + public Film addFilm(Film postFilm) { + return filmStorage.addFilm(postFilm); + } + + public Film updateFilm(Film putFilm) { + return filmStorage.updateFilm(putFilm); + } + + public void addLike(Long userId, Long id) { + Map allFilmsMap = filmStorage.getAllFilmsMap(); + Film film = filmStorage.getFilm(id); + User user = userStorage.getUser(userId); + Set filmLikes = film.getIdUserLikes(); + if (filmLikes == null) { + filmLikes = new HashSet<>(); + } + if (filmLikes.contains(userId)) { + log.info("Пользователь с id: " + userId + "уже ставил лайк"); + return; + } + filmLikes.add(userId); + film.setIdUserLikes(filmLikes); + allFilmsMap.put(film.getId(), film); + filmStorage.setAllFilmsMap(allFilmsMap); + log.info("Пользователь c id: " + userId + " поставил лайк"); + } + + public void deleteLike(Long userId, Long id) { + Map allFilmsMap = filmStorage.getAllFilmsMap(); + Film film = filmStorage.getFilm(id); + User user = userStorage.getUser(userId); + Set filmLikes = film.getIdUserLikes(); + if (filmLikes == null) { + filmLikes = new HashSet<>(); + } + if (!filmLikes.contains(userId)) { + log.info("Пользователь с id: " + userId + " нет в списке тех кто ставил лайк"); + return; + } + filmLikes.remove(userId); + film.setIdUserLikes(filmLikes); + allFilmsMap.put(film.getId(), film); + filmStorage.setAllFilmsMap(allFilmsMap); + log.info("Пользователь c id: " + userId + " удалил лайк"); + } + + public Collection getPopularFilms(int count) { + Collection filmSet = filmStorage.getAllFilms(); + TreeSet filmTreeSet = new TreeSet<>(likeComparator); + filmTreeSet.addAll(filmSet); + List filmList = new ArrayList<>(filmTreeSet); + + if (count > filmList.size()) { + count = filmList.size(); + } + return filmList.subList(0, count); + } + + public Map getAllMapFilms() { + return filmStorage.getAllFilmsMap(); + } +} \ No newline at end of file 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 0000000..694c074 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java @@ -0,0 +1,112 @@ +package ru.yandex.practicum.filmorate.service; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import ru.yandex.practicum.filmorate.exceptions.ValidationException; +import ru.yandex.practicum.filmorate.model.User; +import ru.yandex.practicum.filmorate.storage.UserStorage; + +import java.util.*; + +@Slf4j +@Service +@RequiredArgsConstructor +public class UserService { + + private final UserStorage userStorage; + + public Collection getAllUsers() { + return userStorage.getAllUsers(); + } + + public User addUser(User postUser) { + return userStorage.addUser(postUser); + } + + public User updateUser(User putUser) { + return userStorage.updateUser(putUser); + } + + public void addFriend(Long id, Long friendId) { + if (id.equals(friendId)) { + log.info("Id пользователя и id друга совпадают"); + throw new ValidationException("Id пользователя и id друга совпадают"); + } + User user = userStorage.getUser(id); + User friend = userStorage.getUser(friendId); + Set userSet = userStorage.getUserFriends(id); + Set friendSet = userStorage.getUserFriends(friendId); + if (userSet == null) { + userSet = new HashSet<>(); + } + if (friendSet == null) { + friendSet = new HashSet<>(); + } + userSet.add(friend); + friendSet.add(user); + userStorage.updateUsersFriends(id, userSet); + userStorage.updateUsersFriends(friendId, friendSet); + log.info("Друг добавлен с id: " + friendId); + } + + public void deleteFriend(Long id, Long friendId) { + if (id.equals(friendId)) { + log.info("Id пользователя и id друга совпадают"); + throw new ValidationException("Id пользователя и id друга совпадают"); + } + User user = userStorage.getUser(id); + User friend = userStorage.getUser(friendId); + Set userSet = userStorage.getUserFriends(id); + Set friendSet = userStorage.getUserFriends(id); + if (userSet == null) { + userStorage.updateUsersFriends(user.getId(), null); + log.info("нет списка друзей"); + } + if (friendSet == null) { + log.info("нет списка друзей"); + userStorage.updateUsersFriends(friend.getId(), null); + return; + } + for (User user1 : userSet) { + if (user1.getId() == friendId) { + userSet.remove(friend); + friendSet.remove(user); + userStorage.updateUsersFriends(id, userSet); + userStorage.updateUsersFriends(friendId, friendSet); + log.info("Пользователь с id: " + friendId + "удален из списка"); + return; + } + } + log.info("Пользователь с id: " + friendId + "Нет в списке id"); + } + + public Collection allIdFriends(Long id) { + User user = userStorage.getUser(id); + Set friendsSet = userStorage.getUserFriends(id); + if (friendsSet == null) { + friendsSet = new HashSet<>(); + } + return friendsSet; + } + + public Collection generalFriends(Long id, Long otherId) { + Collection generalFriends = new ArrayList<>(); + Set users = userStorage.getUserFriends(id); + Set otherUsers = userStorage.getUserFriends(otherId); + for (User user : users) { + for (User otherUser : otherUsers) { + if (user.getId() == otherUser.getId()) { + generalFriends.add(otherUser); + break; + } + } + } + log.info("Возврат списка общих друзей"); + return generalFriends; + } + + public Map getAllUserMap() { + return userStorage.getCollectionAllUsers(); + } +} \ No newline at end of file diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/ValidationService.java b/src/main/java/ru/yandex/practicum/filmorate/service/ValidationService.java new file mode 100644 index 0000000..df7213b --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/service/ValidationService.java @@ -0,0 +1,138 @@ +package ru.yandex.practicum.filmorate.service; + +import lombok.extern.slf4j.Slf4j; +import ru.yandex.practicum.filmorate.exceptions.UserNotFoundException; +import ru.yandex.practicum.filmorate.exceptions.ValidationException; +import ru.yandex.practicum.filmorate.model.Film; +import ru.yandex.practicum.filmorate.model.User; + +import java.time.LocalDate; +import java.util.Set; + +@Slf4j +public class ValidationService { + + private final int maxLengthDescription = 200; + private final LocalDate minReleaseData = LocalDate.of(1895, 12, 28); + private final char checkSymbol = '@'; + + public Film checkValidationFilm(Film film) { + log.info("Проверка названия"); + checkNameFilm(film.getName()); + log.info("Проверка описания"); + maxLengthDescription(film.getDescription()); + log.debug("Проверка даты выхода"); + minDateReleaseDate(film.getReleaseDate()); + log.info("Проверка длительности"); + positiveDurationFilm(film.getDuration()); + return film; + } + + public Film checkValidationFilmOnPut(Set allId, Film film) { + if (allId.contains(film.getId())) { + checkValidationFilm(film); + return film; + } + throw new UserNotFoundException("Нет такого id в списке: " + film.getId()); + } + + public User checkValidationUser(User user) { + checkEmail(user.getEmail()); + checkLogin(user.getLogin()); + String nameUser = checkName(user.getLogin(), user.getName()); + user.setName(nameUser); + checkBirthday(user.getBirthday()); + return user; + } + + public User checkValidationUserOnPut(Set allId, User user) { + if (allId.contains(user.getId())) { + checkValidationUser(user); + return user; + } + throw new UserNotFoundException("Нет такого id в списке: " + user.getId()); + } + + public boolean checkNameFilm(String name) { + if (name == null || name.isBlank()) { + log.info("Название фильма не может быть пустым"); + throw new ValidationException("Название фильма не может быть пустым"); + } else { + return true; + } + } + + public boolean maxLengthDescription(String description) { + if (description == null) { + log.info("Нет описания фильма"); + return true; + } + if (description.length() > maxLengthDescription) { + log.info("Максимальная длина описания — 200 символов"); + throw new ValidationException("Максимальная длина описания — 200 символов"); + } else { + return true; + } + } + + public boolean minDateReleaseDate(LocalDate date) { + if (date == null) { + log.info("Не задано дата релиза"); + return true; + } + if (date.isBefore(minReleaseData)) { + log.info("Дата релиза — не раньше 28 декабря 1895 года"); + throw new ValidationException("Дата релиза — не раньше 28 декабря 1895 года"); + } else { + return true; + } + } + + public boolean positiveDurationFilm(int duration) { + if (duration > 0) { + return true; + } else { + log.info("Продолжительность фильма должна быть положительным числом"); + throw new ValidationException("Продолжительность фильма должна быть положительным числом"); + } + } + + public boolean checkEmail(String email) { + if (email == null || email.isBlank() || email.indexOf(checkSymbol) < 0) { + log.info("Электронная почта не может быть пустой и должна содержать символ @"); + throw new ValidationException("Электронная почта не может быть пустой и должна содержать символ @"); + } + return true; + } + + public String checkName(String login, String name) { + if (name == null || name.isBlank()) { + return login; + } else { + return name; + } + } + + public boolean checkBirthday(LocalDate localDate) { + if (localDate == null) { + log.info("Не указано дата рождения пользователя"); + return true; + } + LocalDate localDateNow = LocalDate.now(); + if (localDateNow.isBefore(localDate)) { + log.info("Год не может быть выше текущего года"); + throw new ValidationException("Дата рождения не может быть в будущем"); + } else { + return true; + } + } + + public String checkLogin(String login) { + if (login == null || login.isBlank()) { + log.info("Логин не может быть пустым и содержать пробелы"); + throw new ValidationException("Логин не может быть пустым и содержать пробелы"); + } else { + return login; + } + } +} \ No newline at end of file diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/FilmStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/FilmStorage.java new file mode 100644 index 0000000..933f9aa --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/FilmStorage.java @@ -0,0 +1,20 @@ +package ru.yandex.practicum.filmorate.storage; + +import ru.yandex.practicum.filmorate.model.Film; + +import java.util.Collection; +import java.util.Map; + +public interface FilmStorage { + Collection getAllFilms(); + + Film addFilm(Film postFilm); + + Film updateFilm(Film putFilm); + + Film getFilm(Long id); + + Map getAllFilmsMap(); + + void setAllFilmsMap(Map allFilmsMap); +} \ No newline at end of file diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryFilmStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryFilmStorage.java new file mode 100644 index 0000000..dc6e6ef --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryFilmStorage.java @@ -0,0 +1,65 @@ +package ru.yandex.practicum.filmorate.storage; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import ru.yandex.practicum.filmorate.exceptions.UserNotFoundException; +import ru.yandex.practicum.filmorate.model.Film; + +import java.util.*; + +@Slf4j +@Component +public class InMemoryFilmStorage implements FilmStorage { + + private Map allFilms = new HashMap<>(); + + @Override + public Collection getAllFilms() { + return allFilms.values(); + } + + @Override + public Film addFilm(Film postFilm) { + long id = getNextId(); + postFilm.setId(id); + allFilms.put(postFilm.getId(), postFilm); + log.info("Фильм добавлен в коллекцию: " + postFilm); + return postFilm; + } + + @Override + public Film updateFilm(Film putFilm) { + allFilms.put(putFilm.getId(), putFilm); + log.info("Фильм обновлен в коллекции: " + putFilm); + return putFilm; + } + + @Override + public void setAllFilmsMap(Map allFilmsMap) { + allFilms = allFilmsMap; + } + + private long getNextId() { + long currentMaxId = allFilms.keySet() + .stream() + .mapToLong(id -> id) + .max() + .orElse(0); + return ++currentMaxId; + } + + @Override + public Map getAllFilmsMap() { + return allFilms; + } + + @Override + public Film getFilm(Long id) { + Film film = allFilms.get(id); + if (film == null) { + log.info("Нет фильма с таким id: " + id); + throw new UserNotFoundException("Нет фильма с таким id: " + id); + } + return film; + } +} \ No newline at end of file diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorage.java new file mode 100644 index 0000000..08bcf2e --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorage.java @@ -0,0 +1,82 @@ +package ru.yandex.practicum.filmorate.storage; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import ru.yandex.practicum.filmorate.exceptions.UserNotFoundException; +import ru.yandex.practicum.filmorate.model.User; + +import java.util.*; + +@Slf4j +@Component +public class InMemoryUserStorage implements UserStorage { + + private Map allUsers = new HashMap<>(); + + private Map> friendsMap = new HashMap<>(); + + @Override + public void setFriendsMap(Map> friendsMap) { + this.friendsMap = friendsMap; + } + + @Override + public Map getCollectionAllUsers() { + return allUsers; + } + + @Override + public Map> getFriendsMap() { + return friendsMap; + } + + @Override + public void setCollectionAllUsers(Map allUsers1) { + allUsers = allUsers1; + } + + @Override + public Collection getAllUsers() { + return allUsers.values(); + } + + @Override + public User addUser(User postUser) { + long id = getNextId(); + postUser.setId(id); + allUsers.put(postUser.getId(), postUser); + log.info("Юзер добавлен в коллекцию: " + postUser); + return postUser; + } + + @Override + public User updateUser(User putUser) { + allUsers.put(putUser.getId(), putUser); + return putUser; + } + + @Override + public User getUser(long id) { + User user = allUsers.get(id); + if (user == null) { + log.info("Нет пользователя с таким id: " + user); + throw new UserNotFoundException("Нет пользователя с таким id: " + user); + } + return user; + } + + @Override + public Set getUserFriends(long id) { + return friendsMap.get(id); + } + + @Override + public void updateUsersFriends(long id, Set userSetFriends) { + friendsMap.put(id, userSetFriends); + } + + private long getNextId() { + long currentMaxId = allUsers.keySet().stream().mapToLong(id -> id).max().orElse(0); + return ++currentMaxId; + } +} \ No newline at end of file diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/UserStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/UserStorage.java new file mode 100644 index 0000000..0ddf8fb --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/UserStorage.java @@ -0,0 +1,30 @@ +package ru.yandex.practicum.filmorate.storage; + +import ru.yandex.practicum.filmorate.model.User; + +import java.util.Collection; +import java.util.Map; +import java.util.Set; + + +public interface UserStorage { + Collection getAllUsers(); + + User addUser(User postUser); + + User updateUser(User putUser); + + Map getCollectionAllUsers(); + + void setCollectionAllUsers(Map allUsers1); + + void setFriendsMap(Map> friendsMap); + + Map> getFriendsMap(); + + User getUser(long id); + + Set getUserFriends(long id); + + void updateUsersFriends(long id, Set userSetFriends); +} \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 8b13789..d5df4e3 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1 +1 @@ - +logging.level.org.zalando.logbook:TRACE \ No newline at end of file diff --git a/src/test/java/ru/yandex/practicum/filmorate/ValidationServiceTests.java b/src/test/java/ru/yandex/practicum/filmorate/ValidationServiceTests.java new file mode 100644 index 0000000..b5f3733 --- /dev/null +++ b/src/test/java/ru/yandex/practicum/filmorate/ValidationServiceTests.java @@ -0,0 +1,206 @@ +package ru.yandex.practicum.filmorate; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; +import ru.yandex.practicum.filmorate.model.Film; +import ru.yandex.practicum.filmorate.model.User; +import ru.yandex.practicum.filmorate.service.ValidationService; + +import java.time.LocalDate; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import static org.junit.jupiter.api.Assertions.*; + +@SpringBootTest +public class ValidationServiceTests { + + private ValidationService validationService; + private Film film; + private User user; + + @BeforeEach + public void setUp() { + validationService = new ValidationService(); + + film = new Film(); + film.setId(1L); + film.setName("Имя фильма"); + film.setDescription("Описание фильма"); + film.setReleaseDate(LocalDate.now()); + film.setDuration(80); + + user = new User(); + user.setId(1L); + user.setBirthday(LocalDate.of(1996, 9, 17)); + user.setEmail("volandesy@gmail.com"); + user.setLogin("Voland"); + user.setName("Volandesy"); + } + + @Nested // тесты фильма + class FilmValidationTests { + @Test + // тест на проверку имени фильма + void testCheckNameFilm() { + film.setName("CheckName"); + validationService.checkNameFilm(film.getName()); + assertEquals(film.getName(), "CheckName", "Имя не совпадает"); + } + + @Test + // тест на проверку длины описания + void testMaxLengthDescription() { + validationService.maxLengthDescription(film.getDescription()); + assertEquals(film.getDescription(), "Описание фильма", "Максимальная длина не совпадает"); + assertNotEquals(film.getDescription().length(), 210, "Длина больше 200 символов"); + } + + @Test + // тест на проверку даты релиза + void testMinDateReleaseDate() { + validationService.minDateReleaseDate(film.getReleaseDate()); + assertEquals(film.getReleaseDate(), LocalDate.now(), "Дата не совпадает"); + } + + @Test + // тест на проверку длительности + void testPositiveDurationFilm() { + validationService.positiveDurationFilm(film.getDuration()); + assertEquals(film.getDuration(), 80, "Не верная длительность"); + } + } + + @Nested // тесты пользователя + class UserValidationTests { + @Test + // тест на проверку email + void testCheckEmail() { + validationService.checkEmail(user.getEmail()); + assertEquals(user.getEmail(), "volandesy@gmail.com", "Не верный email"); + } + + @Test + // тест на проверку логина + void testCheckLogin() { + validationService.checkLogin(user.getLogin()); + assertEquals(user.getLogin(), "Voland", "Не верный логин"); + } + + @Test + // тест на проверку имени пользователя + void testCheckName() { + String result = validationService.checkName(user.getLogin(), user.getName()); + assertEquals(result, "Volandesy", "Не верное имя пользователя"); + } + + @Test + // тест на проверку даты рождения + void testCheckBirthday() { + validationService.checkBirthday(user.getBirthday()); + assertEquals(user.getBirthday(), LocalDate.of(1996, 9, 17), "Дата не прошла валидацию"); + } + } + + @Nested // тесты лайков + class FilmLikesTests { + @Test + // тест на добавление и удаление лайка + void testAddAndRemoveLike() { + Film testFilm = new Film(); + testFilm.setId(1L); + Set likes = new HashSet<>(); + testFilm.setIdUserLikes(likes); + + testFilm.getIdUserLikes().add(1L); + assertEquals(1, testFilm.getIdUserLikes().size()); + + testFilm.getIdUserLikes().remove(1L); + assertEquals(0, testFilm.getIdUserLikes().size()); + } + + @Test + // тест на получение популярных фильмов + void testGetPopularFilms() { + Film film1 = new Film(); + Film film2 = new Film(); + film1.setId(1L); + film2.setId(2L); + + film1.setIdUserLikes(new HashSet<>(Arrays.asList(1L, 2L))); + film2.setIdUserLikes(new HashSet<>(Arrays.asList(1L))); + + List films = Arrays.asList(film1, film2); + films.sort((f1, f2) -> f2.getIdUserLikes().size() - f1.getIdUserLikes().size()); + + assertEquals(film1, films.get(0)); + assertEquals(2, films.get(0).getIdUserLikes().size()); + } + } + + @Nested // тесты друзей + class UserFriendsTests { + @Test + // тест на добавление и удаление друзей + void testFriendshipOperations() { + User user1 = new User(); + User user2 = new User(); + user1.setId(1L); + user2.setId(2L); + + Set friends = new HashSet<>(); + friends.add(user2); + user1.setFriends(friends); + + assertTrue(user1.getFriends().contains(user2)); + assertEquals(1, user1.getFriends().size()); + + user1.getFriends().remove(user2); + assertEquals(0, user1.getFriends().size()); + } + + @Test + // тест на получение общих друзей + void testGeneralFriends() { + User user1 = new User(); + User user2 = new User(); + User user3 = new User(); + user1.setId(1L); + user2.setId(2L); + user3.setId(3L); + + user1.setFriends(new HashSet<>(Arrays.asList(user2, user3))); + user3.setFriends(new HashSet<>(Arrays.asList(user2))); + + Set commonFriends = new HashSet<>(user1.getFriends()); + commonFriends.retainAll(user3.getFriends()); + + assertEquals(1, commonFriends.size()); + assertTrue(commonFriends.contains(user2)); + } + } + + @Nested // тесты логирования + class LoggingTests { + @Test + void testLogbookLogging() { + // Создаем тестовый фильм + Film testFilm = new Film(); + testFilm.setId(1L); + testFilm.setName("Test Film"); + testFilm.setDescription("Test Description"); + testFilm.setReleaseDate(LocalDate.now()); + testFilm.setDuration(100); + + // Проверяем валидацию с логированием + Film validatedFilm = validationService.checkValidationFilm(testFilm); + + assertNotNull(validatedFilm); + assertEquals("Test Film", validatedFilm.getName()); + } + } +} From e8562bbb0df4d592a6c843987d0508e684a2b23e Mon Sep 17 00:00:00 2001 From: Viktor64 Date: Mon, 20 Jan 2025 20:00:09 +0400 Subject: [PATCH 02/11] =?UTF-8?q?1)=20=D0=92=D0=BD=D1=91=D1=81=20=D0=B8?= =?UTF-8?q?=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B4=D0=BB?= =?UTF-8?q?=D1=8F=20=D0=BF=D1=80=D0=BE=D1=85=D0=BE=D0=B6=D0=B4=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D1=8F=20Postman=20=D1=82=D0=B5=D1=81=D1=82=D0=B0.=202)?= =?UTF-8?q?=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D0=BB=20=D0=BF=D1=80?= =?UTF-8?q?=D0=BE=D0=B2=D0=B5=D1=80=D0=BA=D1=83=20=D0=BD=D0=B0=20=D0=BD?= =?UTF-8?q?=D1=83=D0=BB=D0=B5=D0=B2=D0=BE=D0=B5=20=D0=B7=D0=BD=D0=B0=D1=87?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BB=D0=B0=D0=B9=D0=BA=D0=BE=D0=B2?= =?UTF-8?q?=203)=20=D0=A3=D0=BF=D1=80=D0=BE=D1=81=D1=82=D0=B8=D0=BB=20?= =?UTF-8?q?=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20?= =?UTF-8?q?=D0=B8=20=D1=83=D0=B4=D0=B0=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20?= =?UTF-8?q?=D0=B2=20filmStorage=20=D0=B8=20InMemoryUserStorage?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../practicum/filmorate/model/Film.java | 3 +- .../filmorate/service/FilmService.java | 36 +++++-------------- .../storage/InMemoryUserStorage.java | 3 +- 3 files changed, 11 insertions(+), 31 deletions(-) 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 e54b48e..9b4b4b7 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/model/Film.java +++ b/src/main/java/ru/yandex/practicum/filmorate/model/Film.java @@ -5,6 +5,7 @@ import ru.yandex.practicum.filmorate.validation.ReleaseDateValidation; import java.time.LocalDate; +import java.util.HashSet; import java.util.Set; @Data @@ -25,5 +26,5 @@ public class Film { @NotNull(message = "Длительность не может быть пустой") @PositiveOrZero(message = "Длительность фильма должна быть больше или равна нулю") private Integer duration; - Set idUserLikes; + private Set idUserLikes = new HashSet<>(); } \ No newline at end of file diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java b/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java index f676f64..cb633ce 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java +++ b/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java @@ -34,41 +34,21 @@ public Film updateFilm(Film putFilm) { } public void addLike(Long userId, Long id) { - Map allFilmsMap = filmStorage.getAllFilmsMap(); Film film = filmStorage.getFilm(id); User user = userStorage.getUser(userId); - Set filmLikes = film.getIdUserLikes(); - if (filmLikes == null) { - filmLikes = new HashSet<>(); - } - if (filmLikes.contains(userId)) { - log.info("Пользователь с id: " + userId + "уже ставил лайк"); - return; - } - filmLikes.add(userId); - film.setIdUserLikes(filmLikes); - allFilmsMap.put(film.getId(), film); - filmStorage.setAllFilmsMap(allFilmsMap); - log.info("Пользователь c id: " + userId + " поставил лайк"); + + film.getIdUserLikes().add(userId); + filmStorage.updateFilm(film); + log.info("Пользователь c id: {} поставил лайк фильму id: {}", userId, id); } public void deleteLike(Long userId, Long id) { - Map allFilmsMap = filmStorage.getAllFilmsMap(); Film film = filmStorage.getFilm(id); User user = userStorage.getUser(userId); - Set filmLikes = film.getIdUserLikes(); - if (filmLikes == null) { - filmLikes = new HashSet<>(); - } - if (!filmLikes.contains(userId)) { - log.info("Пользователь с id: " + userId + " нет в списке тех кто ставил лайк"); - return; - } - filmLikes.remove(userId); - film.setIdUserLikes(filmLikes); - allFilmsMap.put(film.getId(), film); - filmStorage.setAllFilmsMap(allFilmsMap); - log.info("Пользователь c id: " + userId + " удалил лайк"); + + film.getIdUserLikes().remove(userId); + filmStorage.updateFilm(film); + log.info("Пользователь c id: {} удалил лайк у фильма id: {}", userId, id); } public Collection getPopularFilms(int count) { diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorage.java index 08bcf2e..cf16d88 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorage.java @@ -59,8 +59,7 @@ public User updateUser(User putUser) { public User getUser(long id) { User user = allUsers.get(id); if (user == null) { - log.info("Нет пользователя с таким id: " + user); - throw new UserNotFoundException("Нет пользователя с таким id: " + user); + throw new UserNotFoundException("Пользователь с id " + id + " не найден"); } return user; } From fd99aeeed43b6bd07ae42dc570c1aca5831e92d7 Mon Sep 17 00:00:00 2001 From: Viktor64 Date: Mon, 20 Jan 2025 20:31:36 +0400 Subject: [PATCH 03/11] =?UTF-8?q?1)=20=D0=92=D0=BD=D1=91=D1=81=20=D0=B8?= =?UTF-8?q?=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B4=D0=BB?= =?UTF-8?q?=D1=8F=20=D0=BF=D1=80=D0=BE=D1=85=D0=BE=D0=B6=D0=B4=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D1=8F=20Postman=20=D1=82=D0=B5=D1=81=D1=82=D0=B0.=202)?= =?UTF-8?q?=20=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=B8=D0=BB=20=D0=BF=D1=80?= =?UTF-8?q?=D0=BE=D0=B2=D0=B5=D1=80=D0=BA=D1=83=20=D0=BD=D0=B0=20=D0=BD?= =?UTF-8?q?=D1=83=D0=BB=D0=B5=D0=B2=D0=BE=D0=B5=20=D0=B7=D0=BD=D0=B0=D1=87?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BB=D0=B0=D0=B9=D0=BA=D0=BE=D0=B2?= =?UTF-8?q?=203)=20=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=B8=D0=BB=20=D0=B4?= =?UTF-8?q?=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B8?= =?UTF-8?q?=20=D1=83=D0=B4=D0=B0=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B2=20?= =?UTF-8?q?FilmService=20=D0=B8=20InMemoryUserStorage?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../practicum/filmorate/model/Film.java | 7 ++++++ .../filmorate/service/FilmService.java | 24 +++++++++---------- .../storage/InMemoryUserStorage.java | 5 +++- 3 files changed, 23 insertions(+), 13 deletions(-) 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 9b4b4b7..6d6b344 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/model/Film.java +++ b/src/main/java/ru/yandex/practicum/filmorate/model/Film.java @@ -27,4 +27,11 @@ public class Film { @PositiveOrZero(message = "Длительность фильма должна быть больше или равна нулю") private Integer duration; private Set idUserLikes = new HashSet<>(); + + public Set getIdUserLikes() { + if (idUserLikes == null) { + idUserLikes = new HashSet<>(); + } + return idUserLikes; + } } \ No newline at end of file diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java b/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java index cb633ce..4700c58 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java +++ b/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java @@ -3,6 +3,7 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import ru.yandex.practicum.filmorate.exceptions.UserNotFoundException; import ru.yandex.practicum.filmorate.model.Film; import ru.yandex.practicum.filmorate.model.LikeComparator; import ru.yandex.practicum.filmorate.model.User; @@ -34,12 +35,14 @@ public Film updateFilm(Film putFilm) { } public void addLike(Long userId, Long id) { - Film film = filmStorage.getFilm(id); - User user = userStorage.getUser(userId); + Film film = Optional.ofNullable(filmStorage.getFilm(id)) + .orElseThrow(() -> new UserNotFoundException("Фильм с id: " + id + " не найден")); + User user = Optional.ofNullable(userStorage.getUser(userId)) + .orElseThrow(() -> new UserNotFoundException("Фильм с id: " + userId + " не найден")); film.getIdUserLikes().add(userId); filmStorage.updateFilm(film); - log.info("Пользователь c id: {} поставил лайк фильму id: {}", userId, id); + log.info("Пользователь с id: {} добавил лайк фильму {}", userId, id); } public void deleteLike(Long userId, Long id) { @@ -52,15 +55,12 @@ public void deleteLike(Long userId, Long id) { } public Collection getPopularFilms(int count) { - Collection filmSet = filmStorage.getAllFilms(); - TreeSet filmTreeSet = new TreeSet<>(likeComparator); - filmTreeSet.addAll(filmSet); - List filmList = new ArrayList<>(filmTreeSet); - - if (count > filmList.size()) { - count = filmList.size(); - } - return filmList.subList(0, count); + List films = new ArrayList<>(filmStorage.getAllFilms()); + films.sort((f1, f2) -> Integer.compare( + f2.getIdUserLikes().size(), + f1.getIdUserLikes().size() + )); + return films.subList(0, Math.min(count, films.size())); } public Map getAllMapFilms() { diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorage.java index cf16d88..cd5179a 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorage.java @@ -66,11 +66,14 @@ public User getUser(long id) { @Override public Set getUserFriends(long id) { - return friendsMap.get(id); + return friendsMap.getOrDefault(id, new HashSet<>()); } @Override public void updateUsersFriends(long id, Set userSetFriends) { + if (!allUsers.containsKey(id)) { + throw new UserNotFoundException("Пользователь с id: " + id + " не найден"); + } friendsMap.put(id, userSetFriends); } From 89903075ff6699d925931fd58df5208d7e3f5a94 Mon Sep 17 00:00:00 2001 From: Viktor64 Date: Mon, 20 Jan 2025 22:05:38 +0400 Subject: [PATCH 04/11] =?UTF-8?q?1)=20=D0=92=D0=BD=D1=91=D1=81=20=D0=B8?= =?UTF-8?q?=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B4=D0=BB?= =?UTF-8?q?=D1=8F=20=D0=BF=D1=80=D0=BE=D1=85=D0=BE=D0=B6=D0=B4=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D1=8F=20Postman=20=D1=82=D0=B5=D1=81=D1=82=D0=B0.=202)?= =?UTF-8?q?=20=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=B8=D0=BB=20=D0=BF=D1=80?= =?UTF-8?q?=D0=BE=D0=B2=D0=B5=D1=80=D0=BA=D1=83=20=D0=BD=D0=B0=20=D0=BD?= =?UTF-8?q?=D1=83=D0=BB=D0=B5=D0=B2=D0=BE=D0=B5=20=D0=B7=D0=BD=D0=B0=D1=87?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BB=D0=B0=D0=B9=D0=BA=D0=BE=D0=B2?= =?UTF-8?q?=203)=20=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=B8=D0=BB=20=D0=B4?= =?UTF-8?q?=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B8?= =?UTF-8?q?=20=D1=83=D0=B4=D0=B0=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B2=20?= =?UTF-8?q?FilmService=20=D0=B8=20UserController?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../filmorate/controller/UserController.java | 15 ++++++----- .../filmorate/service/FilmService.java | 25 ++++++++++++++--- .../filmorate/service/UserService.java | 27 +++++++++++-------- 3 files changed, 46 insertions(+), 21 deletions(-) diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java b/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java index 4d16d5d..d4cec90 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java @@ -1,16 +1,16 @@ package ru.yandex.practicum.filmorate.controller; import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.server.ResponseStatusException; import ru.yandex.practicum.filmorate.exceptions.UserNotFoundException; import ru.yandex.practicum.filmorate.exceptions.ValidationException; import org.slf4j.LoggerFactory; import org.slf4j.Logger; -import org.springframework.web.bind.annotation.*; import ru.yandex.practicum.filmorate.model.User; - -import jakarta.validation.Valid; import ru.yandex.practicum.filmorate.service.UserService; +import jakarta.validation.Valid; import java.util.*; @RestController @@ -22,7 +22,6 @@ public class UserController { private static final Logger log = LoggerFactory.getLogger(UserController.class); private UserService userService; - private Long getNextId() { long currentMaxId = users.keySet() .stream() @@ -110,8 +109,12 @@ public void deleteFriend(@PathVariable long id, @PathVariable long friendId) { @GetMapping("/{id}/friends") public Collection allIdFriends(@PathVariable long id) { - log.info("Идет процесс получения друзей у пользователя с id: " + id); - return userService.allIdFriends(id); + try { + return userService.allIdFriends(id); + } catch (UserNotFoundException e) { + log.error("Пользователь с id {} не найден", id); + throw new ResponseStatusException(HttpStatus.NOT_FOUND, e.getMessage()); + } } @GetMapping("/{id}/friends/common/{otherId}") diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java b/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java index 4700c58..fa5a823 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java +++ b/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java @@ -35,19 +35,36 @@ public Film updateFilm(Film putFilm) { } public void addLike(Long userId, Long id) { - Film film = Optional.ofNullable(filmStorage.getFilm(id)) - .orElseThrow(() -> new UserNotFoundException("Фильм с id: " + id + " не найден")); - User user = Optional.ofNullable(userStorage.getUser(userId)) - .orElseThrow(() -> new UserNotFoundException("Фильм с id: " + userId + " не найден")); + Film film = filmStorage.getFilm(id); + if (film == null) { + log.error("Фильм с id: {} не найден", id); + throw new UserNotFoundException("Фильм с id: " + id + " не найден"); + } + + User user = userStorage.getUser(userId); + if (user == null) { + log.error("Пользователь с id: {} не найден", userId); + throw new UserNotFoundException("Пользователь с id: " + userId + " не найден"); + } film.getIdUserLikes().add(userId); filmStorage.updateFilm(film); log.info("Пользователь с id: {} добавил лайк фильму {}", userId, id); } + public void deleteLike(Long userId, Long id) { Film film = filmStorage.getFilm(id); + if (film == null) { + log.error("Фильм с id: {} не найден", id); + throw new UserNotFoundException("Фильм с id: " + id + " не найден"); + } + User user = userStorage.getUser(userId); + if (user == null) { + log.error("Пользователь с id: {} не найден", userId); + throw new UserNotFoundException("Пользователь с id: " + userId + " не найден"); + } film.getIdUserLikes().remove(userId); filmStorage.updateFilm(film); diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java b/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java index 694c074..2748737 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java +++ b/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java @@ -3,6 +3,7 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import ru.yandex.practicum.filmorate.exceptions.UserNotFoundException; import ru.yandex.practicum.filmorate.exceptions.ValidationException; import ru.yandex.practicum.filmorate.model.User; import ru.yandex.practicum.filmorate.storage.UserStorage; @@ -30,23 +31,26 @@ public User updateUser(User putUser) { public void addFriend(Long id, Long friendId) { if (id.equals(friendId)) { - log.info("Id пользователя и id друга совпадают"); throw new ValidationException("Id пользователя и id друга совпадают"); } User user = userStorage.getUser(id); + if (user == null) { + log.error("Пользователь с id {} не найден", id); + throw new UserNotFoundException("Пользователь с id " + id + " не найден"); + } + User friend = userStorage.getUser(friendId); + if (friend == null) { + log.error("Пользователь с id {} не найден", friendId); + throw new UserNotFoundException("Пользователь с id " + friendId + " не найден"); + } + Set userSet = userStorage.getUserFriends(id); - Set friendSet = userStorage.getUserFriends(friendId); if (userSet == null) { userSet = new HashSet<>(); } - if (friendSet == null) { - friendSet = new HashSet<>(); - } userSet.add(friend); - friendSet.add(user); userStorage.updateUsersFriends(id, userSet); - userStorage.updateUsersFriends(friendId, friendSet); log.info("Друг добавлен с id: " + friendId); } @@ -83,11 +87,12 @@ public void deleteFriend(Long id, Long friendId) { public Collection allIdFriends(Long id) { User user = userStorage.getUser(id); - Set friendsSet = userStorage.getUserFriends(id); - if (friendsSet == null) { - friendsSet = new HashSet<>(); + if (user == null) { + log.error("Пользователь с id {} не найден", id); + throw new UserNotFoundException("Пользователь с id " + id + " не найден"); } - return friendsSet; + Set friendsSet = userStorage.getUserFriends(id); + return friendsSet != null ? friendsSet : new HashSet<>(); } public Collection generalFriends(Long id, Long otherId) { From 7e5b9b7ad308c8d6aadac484eeb628bbdb47a755 Mon Sep 17 00:00:00 2001 From: Viktor64 Date: Mon, 20 Jan 2025 23:40:53 +0400 Subject: [PATCH 05/11] =?UTF-8?q?1)=20=D0=92=D0=BD=D1=91=D1=81=20=D0=B8?= =?UTF-8?q?=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B4=D0=BB?= =?UTF-8?q?=D1=8F=20=D0=BF=D1=80=D0=BE=D1=85=D0=BE=D0=B6=D0=B4=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D1=8F=20Postman=20=D1=82=D0=B5=D1=81=D1=82=D0=B0.=202)?= =?UTF-8?q?=20=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=B8=D0=BB=20=D0=BF=D1=80?= =?UTF-8?q?=D0=BE=D0=B2=D0=B5=D1=80=D0=BA=D1=83=20=D0=BD=D0=B0=20=D0=BD?= =?UTF-8?q?=D1=83=D0=BB=D0=B5=D0=B2=D0=BE=D0=B5=20=D0=B7=D0=BD=D0=B0=D1=87?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BB=D0=B0=D0=B9=D0=BA=D0=BE=D0=B2?= =?UTF-8?q?=203)=20=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=B8=D0=BB=20=D0=B4?= =?UTF-8?q?=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B8?= =?UTF-8?q?=20=D1=83=D0=B4=D0=B0=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B2=20?= =?UTF-8?q?User,=20UserService=20=D0=B8=20ValidationServiceTests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../practicum/filmorate/model/User.java | 8 +- .../filmorate/service/UserService.java | 87 +++++++++---------- .../filmorate/ValidationServiceTests.java | 17 ++-- 3 files changed, 55 insertions(+), 57 deletions(-) diff --git a/src/main/java/ru/yandex/practicum/filmorate/model/User.java b/src/main/java/ru/yandex/practicum/filmorate/model/User.java index b23a9fa..a9ee8db 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/model/User.java +++ b/src/main/java/ru/yandex/practicum/filmorate/model/User.java @@ -25,6 +25,8 @@ public class User { @PastOrPresent(message = "Дата рождения не может быть в будущем") private LocalDate birthday; + private Set friends = new HashSet<>(); + public User() { } @@ -36,13 +38,11 @@ public void setLogin(String login) { } } - private Set friends = new HashSet<>(); - - public Set getFriends() { + public Set getFriends() { return friends; } - public void setFriends(Set friends) { + public void setFriends(Set friends) { this.friends = friends; } } \ No newline at end of file diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java b/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java index 2748737..c76b35f 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java +++ b/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java @@ -31,6 +31,7 @@ public User updateUser(User putUser) { public void addFriend(Long id, Long friendId) { if (id.equals(friendId)) { + log.error("Id пользователя и id друга совпадают"); throw new ValidationException("Id пользователя и id друга совпадают"); } User user = userStorage.getUser(id); @@ -45,44 +46,28 @@ public void addFriend(Long id, Long friendId) { throw new UserNotFoundException("Пользователь с id " + friendId + " не найден"); } - Set userSet = userStorage.getUserFriends(id); - if (userSet == null) { - userSet = new HashSet<>(); - } - userSet.add(friend); - userStorage.updateUsersFriends(id, userSet); + user.getFriends().add(friendId); + friend.getFriends().add(id); + + userStorage.updateUser(user); + userStorage.updateUser(friend); log.info("Друг добавлен с id: " + friendId); } public void deleteFriend(Long id, Long friendId) { - if (id.equals(friendId)) { - log.info("Id пользователя и id друга совпадают"); - throw new ValidationException("Id пользователя и id друга совпадают"); - } User user = userStorage.getUser(id); User friend = userStorage.getUser(friendId); - Set userSet = userStorage.getUserFriends(id); - Set friendSet = userStorage.getUserFriends(id); - if (userSet == null) { - userStorage.updateUsersFriends(user.getId(), null); - log.info("нет списка друзей"); - } - if (friendSet == null) { - log.info("нет списка друзей"); - userStorage.updateUsersFriends(friend.getId(), null); - return; - } - for (User user1 : userSet) { - if (user1.getId() == friendId) { - userSet.remove(friend); - friendSet.remove(user); - userStorage.updateUsersFriends(id, userSet); - userStorage.updateUsersFriends(friendId, friendSet); - log.info("Пользователь с id: " + friendId + "удален из списка"); - return; - } + + if (user == null || friend == null) { + throw new UserNotFoundException("Пользователь не найден"); } - log.info("Пользователь с id: " + friendId + "Нет в списке id"); + + user.getFriends().remove(friendId); + friend.getFriends().remove(id); + + userStorage.updateUser(user); + userStorage.updateUser(friend); + log.info("Друг удален с id: " + friendId); } public Collection allIdFriends(Long id) { @@ -91,27 +76,39 @@ public Collection allIdFriends(Long id) { log.error("Пользователь с id {} не найден", id); throw new UserNotFoundException("Пользователь с id " + id + " не найден"); } - Set friendsSet = userStorage.getUserFriends(id); - return friendsSet != null ? friendsSet : new HashSet<>(); + + List friends = new ArrayList<>(); + for (Long friendId : user.getFriends()) { + User friend = userStorage.getUser(friendId); + if (friend != null) { + friends.add(friend); + } + } + return friends; } public Collection generalFriends(Long id, Long otherId) { - Collection generalFriends = new ArrayList<>(); - Set users = userStorage.getUserFriends(id); - Set otherUsers = userStorage.getUserFriends(otherId); - for (User user : users) { - for (User otherUser : otherUsers) { - if (user.getId() == otherUser.getId()) { - generalFriends.add(otherUser); - break; - } + User user = userStorage.getUser(id); + User otherUser = userStorage.getUser(otherId); + + if (user == null || otherUser == null) { + throw new UserNotFoundException("Пользователь не найден"); + } + + Set commonFriendIds = new HashSet<>(user.getFriends()); + commonFriendIds.retainAll(otherUser.getFriends()); + + List commonFriends = new ArrayList<>(); + for (Long friendId : commonFriendIds) { + User friend = userStorage.getUser(friendId); + if (friend != null) { + commonFriends.add(friend); } } - log.info("Возврат списка общих друзей"); - return generalFriends; + return commonFriends; } public Map getAllUserMap() { return userStorage.getCollectionAllUsers(); } -} \ No newline at end of file +} diff --git a/src/test/java/ru/yandex/practicum/filmorate/ValidationServiceTests.java b/src/test/java/ru/yandex/practicum/filmorate/ValidationServiceTests.java index b5f3733..513c52c 100644 --- a/src/test/java/ru/yandex/practicum/filmorate/ValidationServiceTests.java +++ b/src/test/java/ru/yandex/practicum/filmorate/ValidationServiceTests.java @@ -40,6 +40,7 @@ public void setUp() { user.setEmail("volandesy@gmail.com"); user.setLogin("Voland"); user.setName("Volandesy"); + user.setFriends(new HashSet<>()); } @Nested // тесты фильма @@ -152,14 +153,14 @@ void testFriendshipOperations() { user1.setId(1L); user2.setId(2L); - Set friends = new HashSet<>(); - friends.add(user2); + Set friends = new HashSet<>(); + friends.add(2L); user1.setFriends(friends); - assertTrue(user1.getFriends().contains(user2)); + assertTrue(user1.getFriends().contains(2L)); assertEquals(1, user1.getFriends().size()); - user1.getFriends().remove(user2); + user1.getFriends().remove(2L); assertEquals(0, user1.getFriends().size()); } @@ -173,14 +174,14 @@ void testGeneralFriends() { user2.setId(2L); user3.setId(3L); - user1.setFriends(new HashSet<>(Arrays.asList(user2, user3))); - user3.setFriends(new HashSet<>(Arrays.asList(user2))); + user1.setFriends(new HashSet<>(Arrays.asList(2L, 3L))); + user3.setFriends(new HashSet<>(Arrays.asList(2L))); - Set commonFriends = new HashSet<>(user1.getFriends()); + Set commonFriends = new HashSet<>(user1.getFriends()); commonFriends.retainAll(user3.getFriends()); assertEquals(1, commonFriends.size()); - assertTrue(commonFriends.contains(user2)); + assertTrue(commonFriends.contains(2L)); } } From 1b9ea9e178a46eb26c94c655b741ca2ad9efdc94 Mon Sep 17 00:00:00 2001 From: Viktor64 Date: Tue, 21 Jan 2025 00:07:22 +0400 Subject: [PATCH 06/11] =?UTF-8?q?1)=20=D0=92=D0=BD=D1=91=D1=81=20=D0=B8?= =?UTF-8?q?=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B4=D0=BB?= =?UTF-8?q?=D1=8F=20=D0=BF=D1=80=D0=BE=D1=85=D0=BE=D0=B6=D0=B4=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D1=8F=20Postman=20=D1=82=D0=B5=D1=81=D1=82=D0=B0.=202)?= =?UTF-8?q?=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D0=BB=20ErrorHandler=20?= =?UTF-8?q?3)=20=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=B8=D0=BB=20=20UserContro?= =?UTF-8?q?ller=20=D0=B8=20FilmController?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../filmorate/controller/FilmController.java | 60 ++++------- .../filmorate/controller/UserController.java | 101 ++++-------------- .../filmorate/exceptions/ErrorHandler.java | 23 ++++ 3 files changed, 66 insertions(+), 118 deletions(-) create mode 100644 src/main/java/ru/yandex/practicum/filmorate/exceptions/ErrorHandler.java 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 87f7d3a..118ccf8 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java @@ -1,5 +1,6 @@ package ru.yandex.practicum.filmorate.controller; +import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import ru.yandex.practicum.filmorate.exceptions.UserNotFoundException; import ru.yandex.practicum.filmorate.exceptions.ValidationException; @@ -22,73 +23,48 @@ @RestController @RequestMapping("/films") +@RequiredArgsConstructor public class FilmController { - private final Map films = new HashMap<>(); - private final LocalDate dayOfCreationCinema = LocalDate.of(1895, 12, 28); + private final FilmService filmService; private static final Logger log = LoggerFactory.getLogger(FilmController.class); - private FilmService filmService; - - private Long getNextId() { - long currentMaxId = films.keySet() - .stream() - .mapToLong(id -> id) - .max() - .orElse(0); - return ++currentMaxId; - } @GetMapping public List findAll() { - return new ArrayList<>(films.values()); + return new ArrayList<>(filmService.getAllFilms()); } @PostMapping @ResponseStatus(HttpStatus.CREATED) public Film createFilm(@Valid @RequestBody Film film) { log.debug("Получен фильм для добавления: {}", film); - film.setId(getNextId()); - - films.put(film.getId(), film); - log.info("Фильм {} успешно добавлен", film); - - return film; + return filmService.addFilm(film); } @PutMapping - @ResponseStatus(HttpStatus.OK) public Film updateFilm(@Valid @RequestBody Film film) { if (film.getId() == null) { log.error("Не введен Id фильма"); throw new ValidationException("id фильма не может быть пустым"); } - if (films.containsKey(film.getId())) { - Film oldFilm = films.get(film.getId()); - - oldFilm.setName(film.getName()); - log.info("Название фильма {} изменено", oldFilm); - oldFilm.setDescription(film.getDescription()); - log.info("Описание фильма {} изменено", oldFilm); - oldFilm.setReleaseDate(film.getReleaseDate()); - log.info("Дата выхода фильма {} изменена", oldFilm); - oldFilm.setDuration(film.getDuration()); - log.info("Длительность фильма {} изменена", oldFilm); - - return oldFilm; + if (!filmService.getAllMapFilms().containsKey(film.getId())) { + log.error("Фильм с id {} не найден", film.getId()); + throw new UserNotFoundException("Фильм с id = " + film.getId() + " не найден"); } - log.error("Фильм с id = {} не найден", film.getId()); - throw new UserNotFoundException("Фильм с id = " + film.getId() + " не найден"); + return filmService.updateFilm(film); } @PutMapping("/{id}/like/{userId}") - public void addLike(@PathVariable long userId, @PathVariable long id) { - log.info("Добавлен лайк пользователем с id: " + userId + ". К фильму с id: " + id); + @ResponseStatus(HttpStatus.NO_CONTENT) + public void addLike(@PathVariable Long id, @PathVariable Long userId) { filmService.addLike(userId, id); + log.info("Добавлен лайк пользователем с id: {} к фильму с id: {}", userId, id); } @DeleteMapping("/{id}/like/{userId}") - public void deleteLike(@PathVariable long userId, @PathVariable long id) { + @ResponseStatus(HttpStatus.NO_CONTENT) + public void deleteLike(@PathVariable Long id, @PathVariable Long userId) { filmService.deleteLike(userId, id); - log.info("Удален лайк пользователем с id: " + userId + ". К фильму с id: " + id); + log.info("Удален лайк пользователем с id: {} к фильму с id: {}", userId, id); } @GetMapping("/popular") @@ -96,4 +72,10 @@ public Collection getPopularFilms(@RequestParam(required = false, defaultV log.info("Получен список популярных фильмов"); return filmService.getPopularFilms(count); } + + @ExceptionHandler(UserNotFoundException.class) + @ResponseStatus(HttpStatus.NOT_FOUND) + public Map handleUserNotFound(final UserNotFoundException e) { + return Map.of("error", e.getMessage()); + } } diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java b/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java index d4cec90..d8147e1 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java @@ -1,5 +1,6 @@ package ru.yandex.practicum.filmorate.controller; +import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.*; import org.springframework.web.server.ResponseStatusException; @@ -11,115 +12,57 @@ import ru.yandex.practicum.filmorate.service.UserService; import jakarta.validation.Valid; + import java.util.*; @RestController @RequestMapping("/users") +@RequiredArgsConstructor public class UserController { - private final Map users = new HashMap<>(); - private final Set emails = new HashSet<>(); - private final Set logins = new HashSet<>(); + private final UserService userService; private static final Logger log = LoggerFactory.getLogger(UserController.class); - private UserService userService; - - private Long getNextId() { - long currentMaxId = users.keySet() - .stream() - .mapToLong(id -> id) - .max() - .orElse(0); - return ++currentMaxId; - } @GetMapping public List findAll() { - return new ArrayList<>(users.values()); + return new ArrayList<>(userService.getAllUsers()); } @PostMapping @ResponseStatus(HttpStatus.CREATED) public User addUser(@Valid @RequestBody User user) { - user.setId(getNextId()); - - if (logins.contains(user.getLogin())) { - log.error("Попытка добавить пользователя с существующим логином: {}", user.getLogin()); - throw new ValidationException("Ошибка. Попытка добавить логин, который уже существует"); - } - - if (emails.contains(user.getEmail())) { - log.error("Попытка добавить пользователя с существующим email: {}", user.getEmail()); - throw new ValidationException("Ошибка. Email уже существует"); - } - - users.put(user.getId(), user); - emails.add(user.getEmail()); - logins.add(user.getLogin()); - log.info("Пользователь добавлен"); - return user; + return userService.addUser(user); } @PutMapping - public User updateUser(@Valid @RequestBody User newUser) { - if (newUser.getId() == null) { - log.error("Не введен id пользователя при изменении"); - throw new ValidationException("id пользователя должен быть указан"); - } - - if (users.containsKey(newUser.getId())) { - User oldUser = users.get(newUser.getId()); - - // Удаляем старый адрес электронной почты и логин из наборов - emails.remove(oldUser.getEmail()); - logins.remove(oldUser.getLogin()); - - // Проверяем, не конфликтуют ли новые адрес электронной почты и логин - if (emails.contains(newUser.getEmail())) { - throw new ValidationException("Email уже существует"); - } - if (logins.contains(newUser.getLogin())) { - throw new ValidationException("Логин уже существует"); - } - - oldUser.setEmail(newUser.getEmail()); - oldUser.setLogin(newUser.getLogin()); - oldUser.setName(newUser.getName()); - oldUser.setBirthday(newUser.getBirthday()); - - // Добавляем новый Email и Логин - emails.add(newUser.getEmail()); - logins.add(newUser.getLogin()); - - return oldUser; - } - log.error("Пользователь с id {} не найден", newUser.getId()); - throw new UserNotFoundException("Пользователь с id =" + newUser.getId() + " не найден"); + public User updateUser(@Valid @RequestBody User user) { + return userService.updateUser(user); } @PutMapping("/{id}/friends/{friendId}") - public void addFriend(@PathVariable long id, @PathVariable long friendId) { - log.info("Пошел процесс добавления друга с id:" + friendId + ". Пользователем id:" + id); + @ResponseStatus(HttpStatus.NO_CONTENT) + public void addFriend(@PathVariable Long id, @PathVariable Long friendId) { userService.addFriend(id, friendId); } @DeleteMapping("/{id}/friends/{friendId}") - public void deleteFriend(@PathVariable long id, @PathVariable long friendId) { - log.info("Пошел процесс удаления друга с id:" + friendId + ". Пользователем id:" + id); + @ResponseStatus(HttpStatus.NO_CONTENT) + public void deleteFriend(@PathVariable Long id, @PathVariable Long friendId) { userService.deleteFriend(id, friendId); } @GetMapping("/{id}/friends") - public Collection allIdFriends(@PathVariable long id) { - try { - return userService.allIdFriends(id); - } catch (UserNotFoundException e) { - log.error("Пользователь с id {} не найден", id); - throw new ResponseStatusException(HttpStatus.NOT_FOUND, e.getMessage()); - } + public List getFriends(@PathVariable Long id) { + return new ArrayList<>(userService.allIdFriends(id)); } @GetMapping("/{id}/friends/common/{otherId}") - public Collection generalFriends(@PathVariable long id, @PathVariable long otherId) { - log.info("Идет процесс получения общих друзей у пользователя с id: " + id + ". C пользователя с id: " + otherId); - return userService.generalFriends(id, otherId); + public List getCommonFriends(@PathVariable Long id, @PathVariable Long otherId) { + return new ArrayList<>(userService.generalFriends(id, otherId)); + } + + @ExceptionHandler(UserNotFoundException.class) + @ResponseStatus(HttpStatus.NOT_FOUND) + public Map handleUserNotFound(final UserNotFoundException e) { + return Map.of("error", e.getMessage()); } } \ No newline at end of file diff --git a/src/main/java/ru/yandex/practicum/filmorate/exceptions/ErrorHandler.java b/src/main/java/ru/yandex/practicum/filmorate/exceptions/ErrorHandler.java new file mode 100644 index 0000000..8e15185 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/exceptions/ErrorHandler.java @@ -0,0 +1,23 @@ +package ru.yandex.practicum.filmorate.exceptions; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +import java.util.Map; + +@RestControllerAdvice +public class ErrorHandler { + @ExceptionHandler(UserNotFoundException.class) + @ResponseStatus(HttpStatus.NOT_FOUND) + public Map handleUserNotFound(UserNotFoundException e) { + return Map.of("error", e.getMessage()); + } + + @ExceptionHandler(ValidationException.class) + @ResponseStatus(HttpStatus.BAD_REQUEST) + public Map handleValidation(ValidationException e) { + return Map.of("error", e.getMessage()); + } +} From 2ba0149bcf74a397db38049db6765b1f097be900 Mon Sep 17 00:00:00 2001 From: Viktor64 Date: Tue, 21 Jan 2025 00:08:29 +0400 Subject: [PATCH 07/11] =?UTF-8?q?1)=20=D0=92=D0=BD=D1=91=D1=81=20=D0=B8?= =?UTF-8?q?=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B4=D0=BB?= =?UTF-8?q?=D1=8F=20=D0=BF=D1=80=D0=BE=D1=85=D0=BE=D0=B6=D0=B4=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D1=8F=20Postman=20=D1=82=D0=B5=D1=81=D1=82=D0=B0.=202)?= =?UTF-8?q?=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D0=BB=20ErrorHandler=20?= =?UTF-8?q?3)=20=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=B8=D0=BB=20=20UserContro?= =?UTF-8?q?ller=20=D0=B8=20FilmController?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yandex/practicum/filmorate/controller/UserController.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java b/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java index d8147e1..41c88a0 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java @@ -3,9 +3,7 @@ import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.*; -import org.springframework.web.server.ResponseStatusException; import ru.yandex.practicum.filmorate.exceptions.UserNotFoundException; -import ru.yandex.practicum.filmorate.exceptions.ValidationException; import org.slf4j.LoggerFactory; import org.slf4j.Logger; import ru.yandex.practicum.filmorate.model.User; From 2be3b6033c10f81a72f4ef6aea4ba78ad9173b0e Mon Sep 17 00:00:00 2001 From: Viktor64 Date: Tue, 21 Jan 2025 00:13:16 +0400 Subject: [PATCH 08/11] =?UTF-8?q?1)=20=D0=92=D0=BD=D1=91=D1=81=20=D0=B8?= =?UTF-8?q?=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B4=D0=BB?= =?UTF-8?q?=D1=8F=20=D0=BF=D1=80=D0=BE=D1=85=D0=BE=D0=B6=D0=B4=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D1=8F=20Postman=20=D1=82=D0=B5=D1=81=D1=82=D0=B0.=202)?= =?UTF-8?q?=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D0=BB=20ErrorHandler=20?= =?UTF-8?q?3)=20=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=B8=D0=BB=20=20UserContro?= =?UTF-8?q?ller=20=D0=B8=20FilmController?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yandex/practicum/filmorate/controller/FilmController.java | 2 -- 1 file changed, 2 deletions(-) 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 118ccf8..7f14cc5 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java @@ -17,9 +17,7 @@ import java.util.ArrayList; import java.util.List; -import java.util.HashMap; import java.util.Map; -import java.time.LocalDate; @RestController @RequestMapping("/films") From ec75ffefd5b90ea284daf082b1fae940665e4480 Mon Sep 17 00:00:00 2001 From: Viktor64 Date: Tue, 21 Jan 2025 00:22:09 +0400 Subject: [PATCH 09/11] =?UTF-8?q?1)=20=D0=92=D0=BD=D1=91=D1=81=20=D0=B8?= =?UTF-8?q?=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B4=D0=BB?= =?UTF-8?q?=D1=8F=20=D0=BF=D1=80=D0=BE=D1=85=D0=BE=D0=B6=D0=B4=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D1=8F=20Postman=20=D1=82=D0=B5=D1=81=D1=82=D0=B0.=202)?= =?UTF-8?q?=20=D0=98=D0=B7=D0=BC=D0=B5=D0=BD=D0=B8=D0=BB=20UserController?= =?UTF-8?q?=20=D0=B4=D0=BB=D1=8F=20=D0=B2=D0=BE=D0=B7=D0=B2=D1=80=D0=B0?= =?UTF-8?q?=D1=89=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=BA=D0=BE=D0=B4=D0=B0=20404?= =?UTF-8?q?=20=D0=BF=D1=80=D0=B8=20=D0=BF=D0=BE=D0=BF=D1=8B=D1=82=D0=BA?= =?UTF-8?q?=D0=B5=20=D0=BE=D0=B1=D0=BD=D0=BE=D0=B2=D0=B8=D1=82=D1=8C=20?= =?UTF-8?q?=D0=BD=D0=B5=D1=81=D1=83=D1=89=D0=B5=D1=81=D1=82=D0=B2=D1=83?= =?UTF-8?q?=D1=8E=D1=89=D0=B5=D0=B3=D0=BE=20=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7?= =?UTF-8?q?=D0=BE=D0=B2=D0=B0=D1=82=D0=B5=D0=BB=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../practicum/filmorate/controller/UserController.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java b/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java index 41c88a0..231bea4 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java @@ -6,6 +6,7 @@ import ru.yandex.practicum.filmorate.exceptions.UserNotFoundException; import org.slf4j.LoggerFactory; import org.slf4j.Logger; +import ru.yandex.practicum.filmorate.exceptions.ValidationException; import ru.yandex.practicum.filmorate.model.User; import ru.yandex.practicum.filmorate.service.UserService; @@ -33,6 +34,12 @@ public User addUser(@Valid @RequestBody User user) { @PutMapping public User updateUser(@Valid @RequestBody User user) { + if (user.getId() == null) { + throw new ValidationException("id пользователя должен быть указан"); + } + if (!userService.getAllUserMap().containsKey(user.getId())) { + throw new UserNotFoundException("Пользователь с id = " + user.getId() + " не найден"); + } return userService.updateUser(user); } From a10e8115a48e47be151fa62eca18d9fb5615513d Mon Sep 17 00:00:00 2001 From: Viktor64 Date: Wed, 22 Jan 2025 23:52:00 +0400 Subject: [PATCH 10/11] =?UTF-8?q?1)=20=D0=92=D1=8B=D0=BD=D0=B5=D1=81=20?= =?UTF-8?q?=D0=BD=D0=B0=20=D1=83=D1=80=D0=BE=D0=B2=D0=B5=D0=BD=D1=8C=20?= =?UTF-8?q?=D1=81=D0=B5=D1=80=D0=B2=D0=B8=D1=81=D0=B0=20=D0=B1=D0=B8=D0=B7?= =?UTF-8?q?=D0=BD=D0=B5=D1=81=20=D0=BB=D0=BE=D0=B3=D0=B8=D0=BA=D1=83=20?= =?UTF-8?q?=D0=B8=D0=B7=20FilmController.=202)=20=D0=A3=D0=B1=D1=80=D0=B0?= =?UTF-8?q?=D0=BB=20=D0=BB=D0=B8=D1=88=D0=BD=D0=B8=D0=B9=20=D0=BA=D0=BE?= =?UTF-8?q?=D0=B4=20(=D0=BF=D1=80=D0=B8=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B8=20=D0=B0=D0=BD=D0=BD=D0=BE=D1=82?= =?UTF-8?q?=D0=B0=D1=86=D0=B8=D0=B8=20=D0=B2=D0=B0=D0=BB=D0=B8=D0=B4=D0=B0?= =?UTF-8?q?=D1=86=D0=B8=D0=B8=20@NotNull=20=D0=B2=20=D0=BA=D0=BB=D0=B0?= =?UTF-8?q?=D1=81=D1=81=20Film=20=D1=81=D1=80=D0=B0=D0=B1=D0=B0=D1=82?= =?UTF-8?q?=D1=8B=D0=B2=D0=B0=D1=8E=D1=82=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BA?= =?UTF-8?q?=D0=B8=20=D0=B2=20=D0=BF=D1=80=D0=BE=D1=85=D0=BE=D0=B6=D0=B4?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B8=20POSTMAN=20=D1=82=D0=B5=D1=81=D1=82?= =?UTF-8?q?=D0=B0.=203)=20=D0=A3=D0=B1=D1=80=D0=B0=D0=BB=20=D0=BB=D0=B8?= =?UTF-8?q?=D1=88=D0=BD=D0=B8=D0=B9=20=D0=BA=D0=BE=D0=B4=20(=D0=BF=D1=80?= =?UTF-8?q?=D0=B8=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=B8=20=D0=B0=D0=BD=D0=BD=D0=BE=D1=82=D0=B0=D1=86=D0=B8=D0=B8?= =?UTF-8?q?=20=D0=B2=D0=B0=D0=BB=D0=B8=D0=B4=D0=B0=D1=86=D0=B8=D0=B8=20@No?= =?UTF-8?q?tNull=20=D0=B2=20=D0=BA=D0=BB=D0=B0=D1=81=D1=81=20User=20=D1=81?= =?UTF-8?q?=D1=80=D0=B0=D0=B1=D0=B0=D1=82=D1=8B=D0=B2=D0=B0=D1=8E=D1=82=20?= =?UTF-8?q?=D0=BE=D1=88=D0=B8=D0=B1=D0=BA=D0=B8=20=D0=B2=20=D0=BF=D1=80?= =?UTF-8?q?=D0=BE=D1=85=D0=BE=D0=B6=D0=B4=D0=B5=D0=BD=D0=B8=D0=B8=20POSTMA?= =?UTF-8?q?N=20=D1=82=D0=B5=D1=81=D1=82=D0=B0.=204)=20=D0=92=D1=8B=D0=BD?= =?UTF-8?q?=D0=B5=D1=81=20=D0=BD=D0=B0=20=D1=83=D1=80=D0=BE=D0=B2=D0=B5?= =?UTF-8?q?=D0=BD=D1=8C=20=D1=81=D0=B5=D1=80=D0=B2=D0=B8=D1=81=D0=B0=20?= =?UTF-8?q?=D0=B1=D0=B8=D0=B7=D0=BD=D0=B5=D1=81=20=D0=BB=D0=BE=D0=B3=D0=B8?= =?UTF-8?q?=D0=BA=D1=83=20=D0=B8=D0=B7=20UserController.=205)=20=D0=A0?= =?UTF-8?q?=D0=B0=D1=81=D1=88=D0=B8=D1=80=D0=B8=D0=BB=20=D0=BA=D0=BB=D0=B0?= =?UTF-8?q?=D1=81=D1=81=20GlobalExceptionHandler,=20=D0=B2=20=D0=BA=D0=BE?= =?UTF-8?q?=D1=82=D0=BE=D1=80=D0=BE=D0=BC=20=D0=BE=D1=82=D0=BB=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B8=D0=B2=D0=B0=D1=8E=D1=82=D1=81=D1=8F=20=D0=BE=D1=88?= =?UTF-8?q?=D0=B8=D0=B1=D0=BA=D0=B8=20=D0=BF=D1=80=D0=B8=D0=BB=D0=BE=D0=B6?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D1=8F,=20=D1=83=D0=B1=D1=80=D0=B0=D0=BB=20?= =?UTF-8?q?=D0=B4=D1=83=D0=B1=D0=BB=D1=8C=20=D0=B8=D0=B7=20UserController.?= =?UTF-8?q?=206)=20=D0=A3=D0=B4=D0=B0=D0=BB=D0=B8=D0=BB=20=D0=BB=D0=B8?= =?UTF-8?q?=D1=88=D0=BD=D0=B8=D0=B5=20=D0=BC=D0=B5=D1=82=D0=BE=D0=B4=D1=8B?= =?UTF-8?q?=20=D0=B8=D0=B7=20InMemoryUserStorage.=207)=20=D0=A3=D0=B4?= =?UTF-8?q?=D0=B0=D0=BB=D0=B8=D0=BB=20=D0=BD=D0=B5=20=D0=B8=D1=81=D0=BF?= =?UTF-8?q?=D0=BE=D0=BB=D1=8C=D0=B7=D1=83=D0=B5=D0=BC=D1=8B=D0=B9=20=D0=BA?= =?UTF-8?q?=D0=BB=D0=B0=D1=81=D1=81=20LikeComparator.=208)=20=D0=A3=D0=B4?= =?UTF-8?q?=D0=B0=D0=BB=D0=B8=D0=BB=20=D0=BB=D0=B8=D1=88=D0=BD=D0=B8=D0=B5?= =?UTF-8?q?=20getFriends=20=D0=B8=20setFriends=20=D0=B8=D0=B7=20User.=209)?= =?UTF-8?q?=20=D0=A3=D0=B1=D1=80=D0=B0=D0=BB=20wildcard=20=D0=B8=D0=B7=20?= =?UTF-8?q?=D0=B8=D0=BC=D0=BF=D0=BE=D1=80=D1=82=D0=BE=D0=B2=20=D0=BF=D1=80?= =?UTF-8?q?=D0=BE=D0=B5=D0=BA=D1=82=D0=B0.=2010)=20=D0=A3=D0=B4=D0=B0?= =?UTF-8?q?=D0=BB=D0=B8=D0=BB=20=D0=BD=D0=B5=20=D0=B8=D1=81=D0=BF=D0=BE?= =?UTF-8?q?=D0=BB=D1=8C=D0=B7=D1=83=D0=B5=D0=BC=D1=8B=D0=B9=20LikeComparat?= =?UTF-8?q?or=20=D0=B8=D0=B7=20FilmService.=2011)=20=D0=92=D1=8B=D0=B4?= =?UTF-8?q?=D0=B5=D0=BB=D0=B8=D0=BB=20=D0=B2=20=D0=BE=D1=82=D0=B4=D0=B5?= =?UTF-8?q?=D0=BB=D1=8C=D0=BD=D1=8B=D0=B9=20=D0=BC=D0=B5=D1=82=D0=BE=D0=B4?= =?UTF-8?q?=20=D0=B8=20=D0=BF=D0=B5=D1=80=D0=B5=D0=B8=D1=81=D0=BF=D0=BE?= =?UTF-8?q?=D0=BB=D1=8C=D0=B7=D0=BE=D0=B2=D0=B0=D0=BB=20=D0=BF=D0=BE=D0=B2?= =?UTF-8?q?=D1=82=D0=BE=D1=80=D1=8F=D1=8E=D1=89=D0=B8=D0=B5=D1=81=D1=8F=20?= =?UTF-8?q?=D1=81=D1=82=D1=80=D0=BE=D0=BA=D0=B8=20=D0=BA=D0=BE=D0=B4=D0=B0?= =?UTF-8?q?=20=D0=B2=20FilmService.=2012)=20=D0=98=D1=81=D0=BF=D0=BE=D0=BB?= =?UTF-8?q?=D1=8C=D0=B7=D0=BE=D0=B2=D0=B0=D0=BB=20film=20=D0=B8=20filmToCo?= =?UTF-8?q?mpare=20=D0=B2=D0=BC=D0=B5=D1=81=D1=82=D0=BE=20=D0=BE=D0=B4?= =?UTF-8?q?=D0=BD=D0=BE=D0=B1=D1=83=D0=BA=D0=B2=D0=B5=D0=BD=D0=BD=D1=8B?= =?UTF-8?q?=D1=85=20=D0=BF=D0=B5=D1=80=D0=B5=D0=BC=D0=B5=D0=BD=D0=BD=D1=8B?= =?UTF-8?q?=D1=85=20=D0=B2=20FilmService.=2013)=20=D0=9F=D0=B5=D1=80=D0=B5?= =?UTF-8?q?=D0=BF=D0=B8=D1=81=D0=B0=D0=BB=20=D1=86=D0=B8=D0=BA=D0=BB=D1=8B?= =?UTF-8?q?=20=D0=B2=20=D1=81=D1=82=D0=B8=D0=BB=D0=B5=20Stream=20API=20?= =?UTF-8?q?=D0=B2=20UserService.=2014)=20=D0=A3=D0=B4=D0=B0=D0=BB=D0=B8?= =?UTF-8?q?=D0=BB=20=D0=BD=D0=B5=20=D0=B8=D1=81=D0=BF=D0=BE=D0=BB=D1=8C?= =?UTF-8?q?=D0=B7=D1=83=D0=B5=D0=BC=D1=8B=D0=B9=20=D0=BA=D0=BB=D0=B0=D1=81?= =?UTF-8?q?=D1=81=20ValidationService.=2015)=20=D0=A3=D0=B4=D0=B0=D0=BB?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=BD=D0=B5=20=D0=B8=D1=81=D0=BF=D0=BE=D0=BB?= =?UTF-8?q?=D1=8C=D0=B7=D1=83=D0=B5=D0=BC=D1=8B=D0=B9=20=D0=BA=D0=BB=D0=B0?= =?UTF-8?q?=D1=81=D1=81=20ValidationServicetest.=2016)=20=D0=A1=D0=BE?= =?UTF-8?q?=D0=B7=D0=B4=D0=B0=D0=BB=20=D0=BA=D0=BB=D0=B0=D1=81=D1=81=20Val?= =?UTF-8?q?idationtest=20=D0=B4=D0=BB=D1=8F=20=D1=82=D0=B5=D1=81=D1=82?= =?UTF-8?q?=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F=20=D1=81=D0=BF?= =?UTF-8?q?=D1=80=D0=B8=D0=BD=D0=B3=D0=BE=D0=B2=D0=BE=D0=B9=20=D0=B2=D0=B0?= =?UTF-8?q?=D0=BB=D0=B8=D0=B4=D0=B0=D1=86=D0=B8=D0=B8.=2017)=20=D0=98?= =?UTF-8?q?=D1=81=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7=D0=BE=D0=B2=D0=B0=D0=BB=20?= =?UTF-8?q?List=20=D0=B2=D0=BC=D0=B5=D1=81=D1=82=D0=BE=20Collection=20?= =?UTF-8?q?=D0=B2=20FilmStorage.=2018)=20=D0=A1=D0=B4=D0=B5=D0=BB=D0=B0?= =?UTF-8?q?=D0=BB=20=D0=BA=D0=BB=D0=B0=D1=81=D1=81=20InMemoryFilmStorage?= =?UTF-8?q?=20final.=2019)=20=D0=A3=D0=B4=D0=B0=D0=BB=D0=B8=D0=BB=20=D0=BB?= =?UTF-8?q?=D0=B8=D1=88=D0=BD=D0=B8=D0=B9=20=D0=BC=D0=B5=D1=82=D0=BE=D0=B4?= =?UTF-8?q?,=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D0=B2=20=D0=B0=D0=BD?= =?UTF-8?q?=D0=BD=D0=BE=D1=82=D0=B0=D1=86=D0=B8=D1=8E=20=D0=B3=D0=B5=D0=BD?= =?UTF-8?q?=D0=B5=D1=80=D0=B8=D1=80=D1=83=D1=8E=D1=89=D1=83=D1=8E=20=D0=BA?= =?UTF-8?q?=D0=BE=D0=BD=D1=81=D1=82=D1=80=D1=83=D0=BA=D1=82=D0=BE=D1=80=20?= =?UTF-8?q?=D0=B4=D0=BB=D1=8F=20final=20=D0=BF=D0=BE=D0=BB=D0=B5=D0=B9=20?= =?UTF-8?q?=D0=BA=D0=BB=D0=B0=D1=81=D1=81=D0=B0=20=D0=B2=20InMemoryFilmSto?= =?UTF-8?q?rage.=2020)=20=D0=A3=D0=B4=D0=B0=D0=BB=D0=B8=D0=BB=20=D0=BB?= =?UTF-8?q?=D0=B8=D1=88=D0=BD=D0=B8=D0=B5=20=D0=BC=D0=B5=D1=82=D0=BE=D0=B4?= =?UTF-8?q?=D1=8B=20=D0=B8=D0=B7=20InMemoryFilmStorage.=2021)=20=D0=A1?= =?UTF-8?q?=D0=B4=D0=B5=D0=BB=D0=B0=D0=BB=20=D0=BA=D0=BB=D0=B0=D1=81=D1=81?= =?UTF-8?q?=20InMemoryUserStorage=20final.=2022)=20=D0=A3=D0=B4=D0=B0?= =?UTF-8?q?=D0=BB=D0=B8=D0=BB=20=D0=BB=D0=B8=D1=88=D0=BD=D1=8E=D1=8E=20?= =?UTF-8?q?=D0=BC=D0=B0=D0=BF=D1=83=20=D0=B8=D0=B7=20InMemoryUserStorage.?= =?UTF-8?q?=2023)=20=D0=A3=D0=B4=D0=B0=D0=BB=D0=B8=D0=BB=20=D0=BB=D0=B8?= =?UTF-8?q?=D1=88=D0=BD=D0=B8=D0=B9=20=D0=BC=D0=B5=D1=82=D0=BE=D0=B4,=20?= =?UTF-8?q?=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D0=B2=20=D0=B0=D0=BD=D0=BD?= =?UTF-8?q?=D0=BE=D1=82=D0=B0=D1=86=D0=B8=D1=8E=20=D0=B3=D0=B5=D0=BD=D0=B5?= =?UTF-8?q?=D1=80=D0=B8=D1=80=D1=83=D1=8E=D1=89=D1=83=D1=8E=20=D0=BA=D0=BE?= =?UTF-8?q?=D0=BD=D1=81=D1=82=D1=80=D1=83=D0=BA=D1=82=D0=BE=D1=80=20=D0=B4?= =?UTF-8?q?=D0=BB=D1=8F=20final=20=D0=BF=D0=BE=D0=BB=D0=B5=D0=B9=20=D0=BA?= =?UTF-8?q?=D0=BB=D0=B0=D1=81=D1=81=D0=B0=20=D0=B2=20InMemoryUserStorage.?= =?UTF-8?q?=2024)=20=D0=A3=D0=B4=D0=B0=D0=BB=D0=B8=D0=BB=20=D0=BB=D0=B8?= =?UTF-8?q?=D1=88=D0=BD=D0=B8=D0=B5=20=D0=BC=D0=B5=D1=82=D0=BE=D0=B4=D1=8B?= =?UTF-8?q?=20=D0=B8=D0=B7=20InMemoryUserStorage.=2025)=20=D0=98=D1=81?= =?UTF-8?q?=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7=D0=BE=D0=B2=D0=B0=D0=BB=20List?= =?UTF-8?q?=20=D0=B2=D0=BC=D0=B5=D1=81=D1=82=D0=BE=20Collection=20=D0=B2?= =?UTF-8?q?=20UserStorage.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../filmorate/controller/FilmController.java | 39 ++-- .../filmorate/controller/UserController.java | 34 ++- .../filmorate/exceptions/ErrorHandler.java | 23 -- .../exceptions/GlobalExceptionHandler.java | 14 +- .../practicum/filmorate/model/Film.java | 23 +- .../filmorate/model/LikeComparator.java | 29 --- .../practicum/filmorate/model/User.java | 37 ++-- .../filmorate/service/FilmService.java | 47 ++-- .../filmorate/service/UserService.java | 40 ++-- .../filmorate/service/ValidationService.java | 138 ------------ .../filmorate/storage/FilmStorage.java | 11 +- .../storage/InMemoryFilmStorage.java | 23 +- .../storage/InMemoryUserStorage.java | 48 +--- .../filmorate/storage/UserStorage.java | 19 +- .../validation/ReleaseDateValidation.java | 7 +- .../filmorate/ValidationServiceTests.java | 207 ------------------ .../practicum/filmorate/ValidationTests.java | 51 +++++ .../{ => controller}/FilmControllerTests.java | 8 +- .../{ => controller}/UserControllerTests.java | 6 +- .../filmorate/service/ServiceTests.java | 142 ++++++++++++ 20 files changed, 330 insertions(+), 616 deletions(-) delete mode 100644 src/main/java/ru/yandex/practicum/filmorate/exceptions/ErrorHandler.java delete mode 100644 src/main/java/ru/yandex/practicum/filmorate/model/LikeComparator.java delete mode 100644 src/main/java/ru/yandex/practicum/filmorate/service/ValidationService.java delete mode 100644 src/test/java/ru/yandex/practicum/filmorate/ValidationServiceTests.java create mode 100644 src/test/java/ru/yandex/practicum/filmorate/ValidationTests.java rename src/test/java/ru/yandex/practicum/filmorate/{ => controller}/FilmControllerTests.java (95%) rename src/test/java/ru/yandex/practicum/filmorate/{ => controller}/UserControllerTests.java (93%) create mode 100644 src/test/java/ru/yandex/practicum/filmorate/service/ServiceTests.java 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 7f14cc5..318e476 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java @@ -1,23 +1,26 @@ package ru.yandex.practicum.filmorate.controller; +import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.http.HttpStatus; -import ru.yandex.practicum.filmorate.exceptions.UserNotFoundException; -import ru.yandex.practicum.filmorate.exceptions.ValidationException; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; import ru.yandex.practicum.filmorate.model.Film; import ru.yandex.practicum.filmorate.service.FilmService; -import java.util.Collection; - -import org.slf4j.LoggerFactory; -import org.slf4j.Logger; - -import jakarta.validation.Valid; - import java.util.ArrayList; +import java.util.Collection; import java.util.List; -import java.util.Map; @RestController @RequestMapping("/films") @@ -40,14 +43,6 @@ public Film createFilm(@Valid @RequestBody Film film) { @PutMapping public Film updateFilm(@Valid @RequestBody Film film) { - if (film.getId() == null) { - log.error("Не введен Id фильма"); - throw new ValidationException("id фильма не может быть пустым"); - } - if (!filmService.getAllMapFilms().containsKey(film.getId())) { - log.error("Фильм с id {} не найден", film.getId()); - throw new UserNotFoundException("Фильм с id = " + film.getId() + " не найден"); - } return filmService.updateFilm(film); } @@ -70,10 +65,4 @@ public Collection getPopularFilms(@RequestParam(required = false, defaultV log.info("Получен список популярных фильмов"); return filmService.getPopularFilms(count); } - - @ExceptionHandler(UserNotFoundException.class) - @ResponseStatus(HttpStatus.NOT_FOUND) - public Map handleUserNotFound(final UserNotFoundException e) { - return Map.of("error", e.getMessage()); - } } diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java b/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java index 231bea4..2793ad9 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java @@ -1,18 +1,24 @@ package ru.yandex.practicum.filmorate.controller; +import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; -import org.springframework.http.HttpStatus; -import org.springframework.web.bind.annotation.*; -import ru.yandex.practicum.filmorate.exceptions.UserNotFoundException; -import org.slf4j.LoggerFactory; import org.slf4j.Logger; -import ru.yandex.practicum.filmorate.exceptions.ValidationException; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; import ru.yandex.practicum.filmorate.model.User; import ru.yandex.practicum.filmorate.service.UserService; -import jakarta.validation.Valid; - -import java.util.*; +import java.util.ArrayList; +import java.util.List; @RestController @RequestMapping("/users") @@ -34,12 +40,6 @@ public User addUser(@Valid @RequestBody User user) { @PutMapping public User updateUser(@Valid @RequestBody User user) { - if (user.getId() == null) { - throw new ValidationException("id пользователя должен быть указан"); - } - if (!userService.getAllUserMap().containsKey(user.getId())) { - throw new UserNotFoundException("Пользователь с id = " + user.getId() + " не найден"); - } return userService.updateUser(user); } @@ -64,10 +64,4 @@ public List getFriends(@PathVariable Long id) { public List getCommonFriends(@PathVariable Long id, @PathVariable Long otherId) { return new ArrayList<>(userService.generalFriends(id, otherId)); } - - @ExceptionHandler(UserNotFoundException.class) - @ResponseStatus(HttpStatus.NOT_FOUND) - public Map handleUserNotFound(final UserNotFoundException e) { - return Map.of("error", e.getMessage()); - } } \ No newline at end of file diff --git a/src/main/java/ru/yandex/practicum/filmorate/exceptions/ErrorHandler.java b/src/main/java/ru/yandex/practicum/filmorate/exceptions/ErrorHandler.java deleted file mode 100644 index 8e15185..0000000 --- a/src/main/java/ru/yandex/practicum/filmorate/exceptions/ErrorHandler.java +++ /dev/null @@ -1,23 +0,0 @@ -package ru.yandex.practicum.filmorate.exceptions; - -import org.springframework.http.HttpStatus; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.ResponseStatus; -import org.springframework.web.bind.annotation.RestControllerAdvice; - -import java.util.Map; - -@RestControllerAdvice -public class ErrorHandler { - @ExceptionHandler(UserNotFoundException.class) - @ResponseStatus(HttpStatus.NOT_FOUND) - public Map handleUserNotFound(UserNotFoundException e) { - return Map.of("error", e.getMessage()); - } - - @ExceptionHandler(ValidationException.class) - @ResponseStatus(HttpStatus.BAD_REQUEST) - public Map handleValidation(ValidationException e) { - return Map.of("error", e.getMessage()); - } -} diff --git a/src/main/java/ru/yandex/practicum/filmorate/exceptions/GlobalExceptionHandler.java b/src/main/java/ru/yandex/practicum/filmorate/exceptions/GlobalExceptionHandler.java index e7443ef..3ed0a47 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/exceptions/GlobalExceptionHandler.java +++ b/src/main/java/ru/yandex/practicum/filmorate/exceptions/GlobalExceptionHandler.java @@ -8,6 +8,12 @@ @RestControllerAdvice public class GlobalExceptionHandler { + public static class FilmNotFoundException extends RuntimeException { + public FilmNotFoundException(String message) { + super(message); + } + } + @ExceptionHandler(ValidationException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) public ErrorResponse handleValidationException(ValidationException exception) { @@ -19,4 +25,10 @@ public ErrorResponse handleValidationException(ValidationException exception) { public ErrorResponse handleUserNotFoundException(UserNotFoundException exception) { return new ErrorResponse(exception.getMessage()); } -} \ No newline at end of file + + @ExceptionHandler(FilmNotFoundException.class) + @ResponseStatus(HttpStatus.NOT_FOUND) + public ErrorResponse handleFilmNotFoundException(FilmNotFoundException exception) { + return new ErrorResponse(exception.getMessage()); + } +} 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 6d6b344..28969cd 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/model/Film.java +++ b/src/main/java/ru/yandex/practicum/filmorate/model/Film.java @@ -1,7 +1,10 @@ package ru.yandex.practicum.filmorate.model; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.PositiveOrZero; +import jakarta.validation.constraints.Size; import lombok.Data; -import jakarta.validation.constraints.*; import ru.yandex.practicum.filmorate.validation.ReleaseDateValidation; import java.time.LocalDate; @@ -12,26 +15,18 @@ public class Film { private Long id; - @NotBlank(message = "Название фильма не может быть пустым") + @NotBlank private String name; - @NotBlank(message = "Описание фильма не может быть пустым") - @Size(max = 200, message = "Максимальная длина описания — 200 символов") + @NotBlank + @Size(max = 200) private String description; - @NotNull(message = "Дата выхода не может быть пустой") - @ReleaseDateValidation // Кастомная аннотация валидации + @NotNull + @ReleaseDateValidation(message = "Release date cannot be earlier than December 28, 1895") private LocalDate releaseDate; - @NotNull(message = "Длительность не может быть пустой") @PositiveOrZero(message = "Длительность фильма должна быть больше или равна нулю") private Integer duration; private Set idUserLikes = new HashSet<>(); - - public Set getIdUserLikes() { - if (idUserLikes == null) { - idUserLikes = new HashSet<>(); - } - return idUserLikes; - } } \ No newline at end of file diff --git a/src/main/java/ru/yandex/practicum/filmorate/model/LikeComparator.java b/src/main/java/ru/yandex/practicum/filmorate/model/LikeComparator.java deleted file mode 100644 index 20e6d87..0000000 --- a/src/main/java/ru/yandex/practicum/filmorate/model/LikeComparator.java +++ /dev/null @@ -1,29 +0,0 @@ -package ru.yandex.practicum.filmorate.model; - -import java.util.Comparator; - -public class LikeComparator implements Comparator { - @Override - public int compare(Film film1, Film film2) { - int size1; - int size2; - if (film1.getIdUserLikes() != null) { - size1 = film1.getIdUserLikes().size(); - } else { - size1 = 0; - } - if (film2.getIdUserLikes() != null) { - size2 = film2.getIdUserLikes().size(); - } else { - size2 = 0; - } - - int comparison = Integer.compare(size2, size1); - - if (comparison == 0) { - return Long.compare(film1.getId(), film2.getId()); - } - - return comparison; - } -} \ No newline at end of file diff --git a/src/main/java/ru/yandex/practicum/filmorate/model/User.java b/src/main/java/ru/yandex/practicum/filmorate/model/User.java index a9ee8db..d9de9e2 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/model/User.java +++ b/src/main/java/ru/yandex/practicum/filmorate/model/User.java @@ -1,6 +1,10 @@ package ru.yandex.practicum.filmorate.model; -import jakarta.validation.constraints.*; +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.PastOrPresent; +import jakarta.validation.constraints.Pattern; import lombok.Data; import java.time.LocalDate; @@ -11,38 +15,23 @@ public class User { private Long id; - @NotBlank(message = "Email не может быть пустым") - @Email(message = "Email должен соответствовать формату") + @NotBlank + @Email private String email; - @NotBlank(message = "Login не может быть пустым") - @Pattern(regexp = "^[^\\s]+$", message = "Login не должен содержать пробелы") + @NotBlank + @Pattern(regexp = "^\\S+$") private String login; private String name; - @NotNull(message = "Дата рождения не может быть пустой") - @PastOrPresent(message = "Дата рождения не может быть в будущем") + @NotNull + @PastOrPresent private LocalDate birthday; private Set friends = new HashSet<>(); - public User() { - } - - public void setLogin(String login) { - this.login = login; - // Устанавливаем name, если он не задан - if (this.name == null || this.name.isBlank()) { - this.name = login; // Или любое другое значение по умолчанию - } - } - - public Set getFriends() { - return friends; - } - - public void setFriends(Set friends) { - this.friends = friends; + public void setName(String name) { + this.name = (name == null || name.isBlank()) ? this.login : name; } } \ No newline at end of file diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java b/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java index fa5a823..d0d5ff7 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java +++ b/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java @@ -5,12 +5,13 @@ import org.springframework.stereotype.Service; import ru.yandex.practicum.filmorate.exceptions.UserNotFoundException; import ru.yandex.practicum.filmorate.model.Film; -import ru.yandex.practicum.filmorate.model.LikeComparator; import ru.yandex.practicum.filmorate.model.User; import ru.yandex.practicum.filmorate.storage.FilmStorage; import ru.yandex.practicum.filmorate.storage.UserStorage; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; @Slf4j @Service @@ -20,8 +21,6 @@ public class FilmService { private final FilmStorage filmStorage; private final UserStorage userStorage; - private final LikeComparator likeComparator = new LikeComparator(); - public Collection getAllFilms() { return filmStorage.getAllFilms(); } @@ -30,15 +29,16 @@ public Film addFilm(Film postFilm) { return filmStorage.addFilm(postFilm); } - public Film updateFilm(Film putFilm) { - return filmStorage.updateFilm(putFilm); + public Film updateFilm(Film film) { + filmStorage.getFilm(film.getId()); // проверяем наличие фильма + return filmStorage.updateFilm(film); } - public void addLike(Long userId, Long id) { - Film film = filmStorage.getFilm(id); + private void validateFilmAndUser(Long filmId, Long userId) { + Film film = filmStorage.getFilm(filmId); if (film == null) { - log.error("Фильм с id: {} не найден", id); - throw new UserNotFoundException("Фильм с id: " + id + " не найден"); + log.error("Фильм с id: {} не найден", filmId); + throw new UserNotFoundException("Фильм с id: " + filmId + " не найден"); } User user = userStorage.getUser(userId); @@ -46,26 +46,19 @@ public void addLike(Long userId, Long id) { log.error("Пользователь с id: {} не найден", userId); throw new UserNotFoundException("Пользователь с id: " + userId + " не найден"); } + } + public void addLike(Long userId, Long id) { + validateFilmAndUser(id, userId); + Film film = filmStorage.getFilm(id); film.getIdUserLikes().add(userId); filmStorage.updateFilm(film); log.info("Пользователь с id: {} добавил лайк фильму {}", userId, id); } - public void deleteLike(Long userId, Long id) { + validateFilmAndUser(id, userId); Film film = filmStorage.getFilm(id); - if (film == null) { - log.error("Фильм с id: {} не найден", id); - throw new UserNotFoundException("Фильм с id: " + id + " не найден"); - } - - User user = userStorage.getUser(userId); - if (user == null) { - log.error("Пользователь с id: {} не найден", userId); - throw new UserNotFoundException("Пользователь с id: " + userId + " не найден"); - } - film.getIdUserLikes().remove(userId); filmStorage.updateFilm(film); log.info("Пользователь c id: {} удалил лайк у фильма id: {}", userId, id); @@ -73,14 +66,10 @@ public void deleteLike(Long userId, Long id) { public Collection getPopularFilms(int count) { List films = new ArrayList<>(filmStorage.getAllFilms()); - films.sort((f1, f2) -> Integer.compare( - f2.getIdUserLikes().size(), - f1.getIdUserLikes().size() + films.sort((film, filmToCompare) -> Integer.compare( + filmToCompare.getIdUserLikes().size(), + film.getIdUserLikes().size() )); return films.subList(0, Math.min(count, films.size())); } - - public Map getAllMapFilms() { - return filmStorage.getAllFilmsMap(); - } } \ No newline at end of file diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java b/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java index c76b35f..eb79bcf 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java +++ b/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java @@ -8,7 +8,11 @@ import ru.yandex.practicum.filmorate.model.User; import ru.yandex.practicum.filmorate.storage.UserStorage; -import java.util.*; +import java.util.Collection; +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; @Slf4j @Service @@ -25,8 +29,9 @@ public User addUser(User postUser) { return userStorage.addUser(postUser); } - public User updateUser(User putUser) { - return userStorage.updateUser(putUser); + public User updateUser(User user) { + userStorage.getUser(user.getId()); + return userStorage.updateUser(user); } public void addFriend(Long id, Long friendId) { @@ -77,16 +82,13 @@ public Collection allIdFriends(Long id) { throw new UserNotFoundException("Пользователь с id " + id + " не найден"); } - List friends = new ArrayList<>(); - for (Long friendId : user.getFriends()) { - User friend = userStorage.getUser(friendId); - if (friend != null) { - friends.add(friend); - } - } - return friends; + return user.getFriends().stream() + .map(userStorage::getUser) + .filter(Objects::nonNull) + .collect(Collectors.toList()); } + public Collection generalFriends(Long id, Long otherId) { User user = userStorage.getUser(id); User otherUser = userStorage.getUser(otherId); @@ -98,17 +100,9 @@ public Collection generalFriends(Long id, Long otherId) { Set commonFriendIds = new HashSet<>(user.getFriends()); commonFriendIds.retainAll(otherUser.getFriends()); - List commonFriends = new ArrayList<>(); - for (Long friendId : commonFriendIds) { - User friend = userStorage.getUser(friendId); - if (friend != null) { - commonFriends.add(friend); - } - } - return commonFriends; - } - - public Map getAllUserMap() { - return userStorage.getCollectionAllUsers(); + return commonFriendIds.stream() + .map(userStorage::getUser) + .filter(Objects::nonNull) + .collect(Collectors.toList()); } } diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/ValidationService.java b/src/main/java/ru/yandex/practicum/filmorate/service/ValidationService.java deleted file mode 100644 index df7213b..0000000 --- a/src/main/java/ru/yandex/practicum/filmorate/service/ValidationService.java +++ /dev/null @@ -1,138 +0,0 @@ -package ru.yandex.practicum.filmorate.service; - -import lombok.extern.slf4j.Slf4j; -import ru.yandex.practicum.filmorate.exceptions.UserNotFoundException; -import ru.yandex.practicum.filmorate.exceptions.ValidationException; -import ru.yandex.practicum.filmorate.model.Film; -import ru.yandex.practicum.filmorate.model.User; - -import java.time.LocalDate; -import java.util.Set; - -@Slf4j -public class ValidationService { - - private final int maxLengthDescription = 200; - private final LocalDate minReleaseData = LocalDate.of(1895, 12, 28); - private final char checkSymbol = '@'; - - public Film checkValidationFilm(Film film) { - log.info("Проверка названия"); - checkNameFilm(film.getName()); - log.info("Проверка описания"); - maxLengthDescription(film.getDescription()); - log.debug("Проверка даты выхода"); - minDateReleaseDate(film.getReleaseDate()); - log.info("Проверка длительности"); - positiveDurationFilm(film.getDuration()); - return film; - } - - public Film checkValidationFilmOnPut(Set allId, Film film) { - if (allId.contains(film.getId())) { - checkValidationFilm(film); - return film; - } - throw new UserNotFoundException("Нет такого id в списке: " + film.getId()); - } - - public User checkValidationUser(User user) { - checkEmail(user.getEmail()); - checkLogin(user.getLogin()); - String nameUser = checkName(user.getLogin(), user.getName()); - user.setName(nameUser); - checkBirthday(user.getBirthday()); - return user; - } - - public User checkValidationUserOnPut(Set allId, User user) { - if (allId.contains(user.getId())) { - checkValidationUser(user); - return user; - } - throw new UserNotFoundException("Нет такого id в списке: " + user.getId()); - } - - public boolean checkNameFilm(String name) { - if (name == null || name.isBlank()) { - log.info("Название фильма не может быть пустым"); - throw new ValidationException("Название фильма не может быть пустым"); - } else { - return true; - } - } - - public boolean maxLengthDescription(String description) { - if (description == null) { - log.info("Нет описания фильма"); - return true; - } - if (description.length() > maxLengthDescription) { - log.info("Максимальная длина описания — 200 символов"); - throw new ValidationException("Максимальная длина описания — 200 символов"); - } else { - return true; - } - } - - public boolean minDateReleaseDate(LocalDate date) { - if (date == null) { - log.info("Не задано дата релиза"); - return true; - } - if (date.isBefore(minReleaseData)) { - log.info("Дата релиза — не раньше 28 декабря 1895 года"); - throw new ValidationException("Дата релиза — не раньше 28 декабря 1895 года"); - } else { - return true; - } - } - - public boolean positiveDurationFilm(int duration) { - if (duration > 0) { - return true; - } else { - log.info("Продолжительность фильма должна быть положительным числом"); - throw new ValidationException("Продолжительность фильма должна быть положительным числом"); - } - } - - public boolean checkEmail(String email) { - if (email == null || email.isBlank() || email.indexOf(checkSymbol) < 0) { - log.info("Электронная почта не может быть пустой и должна содержать символ @"); - throw new ValidationException("Электронная почта не может быть пустой и должна содержать символ @"); - } - return true; - } - - public String checkName(String login, String name) { - if (name == null || name.isBlank()) { - return login; - } else { - return name; - } - } - - public boolean checkBirthday(LocalDate localDate) { - if (localDate == null) { - log.info("Не указано дата рождения пользователя"); - return true; - } - LocalDate localDateNow = LocalDate.now(); - if (localDateNow.isBefore(localDate)) { - log.info("Год не может быть выше текущего года"); - throw new ValidationException("Дата рождения не может быть в будущем"); - } else { - return true; - } - } - - public String checkLogin(String login) { - if (login == null || login.isBlank()) { - log.info("Логин не может быть пустым и содержать пробелы"); - throw new ValidationException("Логин не может быть пустым и содержать пробелы"); - } else { - return login; - } - } -} \ No newline at end of file diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/FilmStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/FilmStorage.java index 933f9aa..c2c122d 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/FilmStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/FilmStorage.java @@ -2,19 +2,14 @@ import ru.yandex.practicum.filmorate.model.Film; -import java.util.Collection; -import java.util.Map; +import java.util.List; public interface FilmStorage { - Collection getAllFilms(); + List getAllFilms(); Film addFilm(Film postFilm); Film updateFilm(Film putFilm); Film getFilm(Long id); - - Map getAllFilmsMap(); - - void setAllFilmsMap(Map allFilmsMap); -} \ No newline at end of file +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryFilmStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryFilmStorage.java index dc6e6ef..0a0beb6 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryFilmStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryFilmStorage.java @@ -1,21 +1,26 @@ package ru.yandex.practicum.filmorate.storage; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import ru.yandex.practicum.filmorate.exceptions.UserNotFoundException; import ru.yandex.practicum.filmorate.model.Film; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; @Slf4j @Component +@RequiredArgsConstructor public class InMemoryFilmStorage implements FilmStorage { - private Map allFilms = new HashMap<>(); + private final Map allFilms = new HashMap<>(); @Override - public Collection getAllFilms() { - return allFilms.values(); + public List getAllFilms() { + return new ArrayList<>(allFilms.values()); } @Override @@ -34,11 +39,6 @@ public Film updateFilm(Film putFilm) { return putFilm; } - @Override - public void setAllFilmsMap(Map allFilmsMap) { - allFilms = allFilmsMap; - } - private long getNextId() { long currentMaxId = allFilms.keySet() .stream() @@ -48,11 +48,6 @@ private long getNextId() { return ++currentMaxId; } - @Override - public Map getAllFilmsMap() { - return allFilms; - } - @Override public Film getFilm(Long id) { Film film = allFilms.get(id); diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorage.java index cd5179a..23a1dfb 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorage.java @@ -1,43 +1,26 @@ package ru.yandex.practicum.filmorate.storage; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import ru.yandex.practicum.filmorate.exceptions.UserNotFoundException; import ru.yandex.practicum.filmorate.model.User; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; @Slf4j @Component +@RequiredArgsConstructor public class InMemoryUserStorage implements UserStorage { - private Map allUsers = new HashMap<>(); - - private Map> friendsMap = new HashMap<>(); - - @Override - public void setFriendsMap(Map> friendsMap) { - this.friendsMap = friendsMap; - } - - @Override - public Map getCollectionAllUsers() { - return allUsers; - } - - @Override - public Map> getFriendsMap() { - return friendsMap; - } + private final Map allUsers = new HashMap<>(); @Override - public void setCollectionAllUsers(Map allUsers1) { - allUsers = allUsers1; - } - - @Override - public Collection getAllUsers() { - return allUsers.values(); + public List getAllUsers() { + return new ArrayList<>(allUsers.values()); } @Override @@ -64,19 +47,6 @@ public User getUser(long id) { return user; } - @Override - public Set getUserFriends(long id) { - return friendsMap.getOrDefault(id, new HashSet<>()); - } - - @Override - public void updateUsersFriends(long id, Set userSetFriends) { - if (!allUsers.containsKey(id)) { - throw new UserNotFoundException("Пользователь с id: " + id + " не найден"); - } - friendsMap.put(id, userSetFriends); - } - private long getNextId() { long currentMaxId = allUsers.keySet().stream().mapToLong(id -> id).max().orElse(0); return ++currentMaxId; diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/UserStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/UserStorage.java index 0ddf8fb..c05d240 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/UserStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/UserStorage.java @@ -2,29 +2,14 @@ import ru.yandex.practicum.filmorate.model.User; -import java.util.Collection; -import java.util.Map; -import java.util.Set; - +import java.util.List; public interface UserStorage { - Collection getAllUsers(); + List getAllUsers(); User addUser(User postUser); User updateUser(User putUser); - Map getCollectionAllUsers(); - - void setCollectionAllUsers(Map allUsers1); - - void setFriendsMap(Map> friendsMap); - - Map> getFriendsMap(); - User getUser(long id); - - Set getUserFriends(long id); - - void updateUsersFriends(long id, Set userSetFriends); } \ No newline at end of file diff --git a/src/main/java/ru/yandex/practicum/filmorate/validation/ReleaseDateValidation.java b/src/main/java/ru/yandex/practicum/filmorate/validation/ReleaseDateValidation.java index 16ed8b0..748e145 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/validation/ReleaseDateValidation.java +++ b/src/main/java/ru/yandex/practicum/filmorate/validation/ReleaseDateValidation.java @@ -2,7 +2,12 @@ import jakarta.validation.Constraint; import jakarta.validation.Payload; -import java.lang.annotation.*; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; @Target({ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) diff --git a/src/test/java/ru/yandex/practicum/filmorate/ValidationServiceTests.java b/src/test/java/ru/yandex/practicum/filmorate/ValidationServiceTests.java deleted file mode 100644 index 513c52c..0000000 --- a/src/test/java/ru/yandex/practicum/filmorate/ValidationServiceTests.java +++ /dev/null @@ -1,207 +0,0 @@ -package ru.yandex.practicum.filmorate; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; -import ru.yandex.practicum.filmorate.model.Film; -import ru.yandex.practicum.filmorate.model.User; -import ru.yandex.practicum.filmorate.service.ValidationService; - -import java.time.LocalDate; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import static org.junit.jupiter.api.Assertions.*; - -@SpringBootTest -public class ValidationServiceTests { - - private ValidationService validationService; - private Film film; - private User user; - - @BeforeEach - public void setUp() { - validationService = new ValidationService(); - - film = new Film(); - film.setId(1L); - film.setName("Имя фильма"); - film.setDescription("Описание фильма"); - film.setReleaseDate(LocalDate.now()); - film.setDuration(80); - - user = new User(); - user.setId(1L); - user.setBirthday(LocalDate.of(1996, 9, 17)); - user.setEmail("volandesy@gmail.com"); - user.setLogin("Voland"); - user.setName("Volandesy"); - user.setFriends(new HashSet<>()); - } - - @Nested // тесты фильма - class FilmValidationTests { - @Test - // тест на проверку имени фильма - void testCheckNameFilm() { - film.setName("CheckName"); - validationService.checkNameFilm(film.getName()); - assertEquals(film.getName(), "CheckName", "Имя не совпадает"); - } - - @Test - // тест на проверку длины описания - void testMaxLengthDescription() { - validationService.maxLengthDescription(film.getDescription()); - assertEquals(film.getDescription(), "Описание фильма", "Максимальная длина не совпадает"); - assertNotEquals(film.getDescription().length(), 210, "Длина больше 200 символов"); - } - - @Test - // тест на проверку даты релиза - void testMinDateReleaseDate() { - validationService.minDateReleaseDate(film.getReleaseDate()); - assertEquals(film.getReleaseDate(), LocalDate.now(), "Дата не совпадает"); - } - - @Test - // тест на проверку длительности - void testPositiveDurationFilm() { - validationService.positiveDurationFilm(film.getDuration()); - assertEquals(film.getDuration(), 80, "Не верная длительность"); - } - } - - @Nested // тесты пользователя - class UserValidationTests { - @Test - // тест на проверку email - void testCheckEmail() { - validationService.checkEmail(user.getEmail()); - assertEquals(user.getEmail(), "volandesy@gmail.com", "Не верный email"); - } - - @Test - // тест на проверку логина - void testCheckLogin() { - validationService.checkLogin(user.getLogin()); - assertEquals(user.getLogin(), "Voland", "Не верный логин"); - } - - @Test - // тест на проверку имени пользователя - void testCheckName() { - String result = validationService.checkName(user.getLogin(), user.getName()); - assertEquals(result, "Volandesy", "Не верное имя пользователя"); - } - - @Test - // тест на проверку даты рождения - void testCheckBirthday() { - validationService.checkBirthday(user.getBirthday()); - assertEquals(user.getBirthday(), LocalDate.of(1996, 9, 17), "Дата не прошла валидацию"); - } - } - - @Nested // тесты лайков - class FilmLikesTests { - @Test - // тест на добавление и удаление лайка - void testAddAndRemoveLike() { - Film testFilm = new Film(); - testFilm.setId(1L); - Set likes = new HashSet<>(); - testFilm.setIdUserLikes(likes); - - testFilm.getIdUserLikes().add(1L); - assertEquals(1, testFilm.getIdUserLikes().size()); - - testFilm.getIdUserLikes().remove(1L); - assertEquals(0, testFilm.getIdUserLikes().size()); - } - - @Test - // тест на получение популярных фильмов - void testGetPopularFilms() { - Film film1 = new Film(); - Film film2 = new Film(); - film1.setId(1L); - film2.setId(2L); - - film1.setIdUserLikes(new HashSet<>(Arrays.asList(1L, 2L))); - film2.setIdUserLikes(new HashSet<>(Arrays.asList(1L))); - - List films = Arrays.asList(film1, film2); - films.sort((f1, f2) -> f2.getIdUserLikes().size() - f1.getIdUserLikes().size()); - - assertEquals(film1, films.get(0)); - assertEquals(2, films.get(0).getIdUserLikes().size()); - } - } - - @Nested // тесты друзей - class UserFriendsTests { - @Test - // тест на добавление и удаление друзей - void testFriendshipOperations() { - User user1 = new User(); - User user2 = new User(); - user1.setId(1L); - user2.setId(2L); - - Set friends = new HashSet<>(); - friends.add(2L); - user1.setFriends(friends); - - assertTrue(user1.getFriends().contains(2L)); - assertEquals(1, user1.getFriends().size()); - - user1.getFriends().remove(2L); - assertEquals(0, user1.getFriends().size()); - } - - @Test - // тест на получение общих друзей - void testGeneralFriends() { - User user1 = new User(); - User user2 = new User(); - User user3 = new User(); - user1.setId(1L); - user2.setId(2L); - user3.setId(3L); - - user1.setFriends(new HashSet<>(Arrays.asList(2L, 3L))); - user3.setFriends(new HashSet<>(Arrays.asList(2L))); - - Set commonFriends = new HashSet<>(user1.getFriends()); - commonFriends.retainAll(user3.getFriends()); - - assertEquals(1, commonFriends.size()); - assertTrue(commonFriends.contains(2L)); - } - } - - @Nested // тесты логирования - class LoggingTests { - @Test - void testLogbookLogging() { - // Создаем тестовый фильм - Film testFilm = new Film(); - testFilm.setId(1L); - testFilm.setName("Test Film"); - testFilm.setDescription("Test Description"); - testFilm.setReleaseDate(LocalDate.now()); - testFilm.setDuration(100); - - // Проверяем валидацию с логированием - Film validatedFilm = validationService.checkValidationFilm(testFilm); - - assertNotNull(validatedFilm); - assertEquals("Test Film", validatedFilm.getName()); - } - } -} diff --git a/src/test/java/ru/yandex/practicum/filmorate/ValidationTests.java b/src/test/java/ru/yandex/practicum/filmorate/ValidationTests.java new file mode 100644 index 0000000..96c6d33 --- /dev/null +++ b/src/test/java/ru/yandex/practicum/filmorate/ValidationTests.java @@ -0,0 +1,51 @@ +package ru.yandex.practicum.filmorate; + +import jakarta.validation.ConstraintViolation; +import jakarta.validation.Validation; +import jakarta.validation.Validator; +import jakarta.validation.ValidatorFactory; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; +import ru.yandex.practicum.filmorate.model.Film; +import ru.yandex.practicum.filmorate.model.User; + +import java.time.LocalDate; +import java.util.Set; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +@SpringBootTest +public class ValidationTests { + + private Validator validator; + + @BeforeEach + public void setUp() { + ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); + validator = factory.getValidator(); + } + + @Test + void testFilmValidation() { + Film film = new Film(); + film.setName(""); + film.setDescription("Test description"); + film.setReleaseDate(LocalDate.now()); + film.setDuration(-1); + + Set> violations = validator.validate(film); + assertEquals(2, violations.size()); + } + + @Test + void testUserValidation() { + User user = new User(); + user.setEmail("invalid-email"); + user.setLogin(""); + user.setBirthday(LocalDate.now().plusDays(1)); + + Set> violations = validator.validate(user); + assertEquals(4, violations.size()); + } +} diff --git a/src/test/java/ru/yandex/practicum/filmorate/FilmControllerTests.java b/src/test/java/ru/yandex/practicum/filmorate/controller/FilmControllerTests.java similarity index 95% rename from src/test/java/ru/yandex/practicum/filmorate/FilmControllerTests.java rename to src/test/java/ru/yandex/practicum/filmorate/controller/FilmControllerTests.java index bb85000..96a1350 100644 --- a/src/test/java/ru/yandex/practicum/filmorate/FilmControllerTests.java +++ b/src/test/java/ru/yandex/practicum/filmorate/controller/FilmControllerTests.java @@ -1,4 +1,4 @@ -package ru.yandex.practicum.filmorate; +package ru.yandex.practicum.filmorate.controller; import jakarta.validation.ConstraintViolation; import jakarta.validation.Validator; @@ -18,7 +18,10 @@ import java.time.LocalDate; import java.util.Set; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) public class FilmControllerTests { @@ -40,6 +43,7 @@ public class FilmControllerTests { @BeforeEach void setUp() { film = new Film(); + film.setId(1L); // ID может быть любым film.setName("film"); film.setDescription(correctDescription); film.setReleaseDate(LocalDate.of(1985, 12, 28)); diff --git a/src/test/java/ru/yandex/practicum/filmorate/UserControllerTests.java b/src/test/java/ru/yandex/practicum/filmorate/controller/UserControllerTests.java similarity index 93% rename from src/test/java/ru/yandex/practicum/filmorate/UserControllerTests.java rename to src/test/java/ru/yandex/practicum/filmorate/controller/UserControllerTests.java index 845c748..cbbb174 100644 --- a/src/test/java/ru/yandex/practicum/filmorate/UserControllerTests.java +++ b/src/test/java/ru/yandex/practicum/filmorate/controller/UserControllerTests.java @@ -1,4 +1,4 @@ -package ru.yandex.practicum.filmorate; +package ru.yandex.practicum.filmorate.controller; import jakarta.validation.ConstraintViolation; import jakarta.validation.Validator; @@ -12,7 +12,8 @@ import java.time.LocalDate; import java.util.Set; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; @SpringBootTest public class UserControllerTests { @@ -25,6 +26,7 @@ public class UserControllerTests { @BeforeEach void setUp() { user = new User(); + user.setId(1L); // ID может быть любым user.setName("name"); user.setEmail("user@mail.ru"); user.setLogin("login"); diff --git a/src/test/java/ru/yandex/practicum/filmorate/service/ServiceTests.java b/src/test/java/ru/yandex/practicum/filmorate/service/ServiceTests.java new file mode 100644 index 0000000..afb2a75 --- /dev/null +++ b/src/test/java/ru/yandex/practicum/filmorate/service/ServiceTests.java @@ -0,0 +1,142 @@ +package ru.yandex.practicum.filmorate.service; + +import org.junit.jupiter.api.Nested; +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.model.Film; +import ru.yandex.practicum.filmorate.model.User; + +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@SpringBootTest +public class ServiceTests { + @Autowired + private UserService userService; + @Autowired + private FilmService filmService; + + @Nested + class FriendshipTests { + @Test // Тесты для работы с друзьями + void testFriendshipOperations() { + User user1 = new User(); + user1.setEmail("user1@mail.com"); + user1.setLogin("user1"); + user1.setName("User 1"); + user1.setBirthday(LocalDate.of(1990, 1, 1)); + + User user2 = new User(); + user2.setEmail("user2@mail.com"); + user2.setLogin("user2"); + user2.setName("User 2"); + user2.setBirthday(LocalDate.of(1990, 1, 2)); + + user1 = userService.addUser(user1); + user2 = userService.addUser(user2); + + userService.addFriend(user1.getId(), user2.getId()); + assertTrue(userService.allIdFriends(user1.getId()).contains(user2)); + + userService.deleteFriend(user1.getId(), user2.getId()); + assertFalse(userService.allIdFriends(user1.getId()).contains(user2)); + } + + @Test // Тесты для работы с общими друзьями + void testCommonFriends() { + User user1 = new User(); + user1.setEmail("user1@mail.com"); + user1.setLogin("user1"); + user1.setName("User 1"); + user1.setBirthday(LocalDate.of(1990, 1, 1)); + + User user2 = new User(); + user2.setEmail("user2@mail.com"); + user2.setLogin("user2"); + user2.setName("User 2"); + user2.setBirthday(LocalDate.of(1990, 1, 2)); + + User user3 = new User(); + user3.setEmail("user3@mail.com"); + user3.setLogin("user3"); + user3.setName("User 3"); + user3.setBirthday(LocalDate.of(1990, 1, 3)); + + user1 = userService.addUser(user1); + user2 = userService.addUser(user2); + user3 = userService.addUser(user3); + + userService.addFriend(user1.getId(), user3.getId()); + userService.addFriend(user2.getId(), user3.getId()); + + Collection commonFriends = userService.generalFriends(user1.getId(), user2.getId()); + assertTrue(commonFriends.contains(user3)); + } + } + + @Nested + class FilmLikesTests { + @Test // Тесты для работы с лайками + void testLikeOperations() { + Film film = new Film(); + film.setName("Test Film"); + film.setDescription("Test Description"); + film.setReleaseDate(LocalDate.of(2000, 1, 1)); + film.setDuration(120); + + User user = new User(); + user.setEmail("user@mail.com"); + user.setLogin("user"); + user.setName("User"); + user.setBirthday(LocalDate.of(1990, 1, 1)); + + film = filmService.addFilm(film); + user = userService.addUser(user); + + filmService.addLike(user.getId(), film.getId()); + assertTrue(film.getIdUserLikes().contains(user.getId())); + + filmService.deleteLike(user.getId(), film.getId()); + assertFalse(film.getIdUserLikes().contains(user.getId())); + } + + @Test // Тесты для работы с популярными фильмами + void testPopularFilms() { + Film film1 = new Film(); + film1.setName("Film 1"); + film1.setDescription("Description 1"); + film1.setReleaseDate(LocalDate.of(2000, 1, 1)); + film1.setDuration(120); + + Film film2 = new Film(); + film2.setName("Film 2"); + film2.setDescription("Description 2"); + film2.setReleaseDate(LocalDate.of(2000, 1, 2)); + film2.setDuration(120); + + User user = new User(); + user.setEmail("user@mail.com"); + user.setLogin("user"); + user.setName("User"); + user.setBirthday(LocalDate.of(1990, 1, 1)); + + film1 = filmService.addFilm(film1); + film2 = filmService.addFilm(film2); + user = userService.addUser(user); + + filmService.addLike(user.getId(), film1.getId()); + + List popularFilms = new ArrayList<>(filmService.getPopularFilms(10)); + assertEquals(film1.getId(), popularFilms.get(0).getId()); + } + } +} + + From 8c68892529e61796ef559a86d318b57c090ba82c Mon Sep 17 00:00:00 2001 From: Viktor64 Date: Thu, 23 Jan 2025 22:10:55 +0400 Subject: [PATCH 11/11] =?UTF-8?q?1)=20=D0=97=D0=B0=D0=BC=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=BB=20Collection=20=D0=BD=D0=B0=20List=20=D0=B2=20FilmServic?= =?UTF-8?q?e.=202)=20=D0=97=D0=B0=D0=BC=D0=B5=D0=BD=D0=B8=D0=BB=20Collecti?= =?UTF-8?q?on=20=D0=BD=D0=B0=20List=20=D0=B2=20UserService.=203)=20=D0=97?= =?UTF-8?q?=D0=B0=D0=BC=D0=B5=D0=BD=D0=B8=D0=BB=20=D0=B2=D0=BE=D0=B7=D0=B2?= =?UTF-8?q?=D1=80=D0=B0=D1=89=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BF=D0=BE=D0=BB?= =?UTF-8?q?=D1=8C=D0=B7=D0=BE=D0=B2=D0=B0=D1=82=D0=B5=D0=BB=D1=8E=20getPop?= =?UTF-8?q?ularFilms=20=D0=B8=D0=BD=D1=82=D0=B5=D1=80=D1=84=D0=B5=D0=B9?= =?UTF-8?q?=D1=81=20List=20=D0=B2=20FilmService.=204)=20=D0=A3=D0=B4=D0=B0?= =?UTF-8?q?=D0=BB=D0=B8=D0=BB=20=D0=BD=D0=B5=D0=B8=D1=81=D0=BF=D0=BE=D0=BB?= =?UTF-8?q?=D1=8C=D0=B7=D1=83=D0=B5=D0=BC=D1=8B=D0=B9=20=D0=BA=D0=BE=D0=B4?= =?UTF-8?q?=20=D0=B2=20GlobalExceptionHandler.=205)=20=D0=A1=D0=B4=D0=B5?= =?UTF-8?q?=D0=BB=D0=B0=D0=BB=20=D1=81=D1=82=D1=80=D0=B8=D0=BC=20=D0=B1?= =?UTF-8?q?=D0=BE=D0=BB=D0=B5=D0=B5=20=D1=87=D0=B8=D1=82=D0=B0=D0=B5=D0=BC?= =?UTF-8?q?=D1=8B=D0=BC.=206)=20=D0=A3=D0=B4=D0=B0=D0=BB=D0=B8=D0=BB=20?= =?UTF-8?q?=D0=B4=D1=83=D0=B1=D0=BB=D0=B8,=20=D0=B2=D1=8B=D0=BD=D0=B5?= =?UTF-8?q?=D1=81=D1=8F=20=D0=B8=D1=85=20=D0=B1=D0=BB=D0=BE=D0=BA=D0=BE?= =?UTF-8?q?=D0=BC=20@BeforeEach=20=D0=B2=20ServiceTests.java?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../filmorate/controller/FilmController.java | 6 +-- .../filmorate/controller/UserController.java | 7 ++- .../exceptions/GlobalExceptionHandler.java | 14 +----- .../filmorate/service/FilmService.java | 5 +-- .../filmorate/service/UserService.java | 8 ++-- .../storage/InMemoryUserStorage.java | 7 ++- .../filmorate/service/ServiceTests.java | 44 +++++++++---------- 7 files changed, 37 insertions(+), 54 deletions(-) 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 318e476..14b89ce 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java @@ -18,8 +18,6 @@ import ru.yandex.practicum.filmorate.model.Film; import ru.yandex.practicum.filmorate.service.FilmService; -import java.util.ArrayList; -import java.util.Collection; import java.util.List; @RestController @@ -31,7 +29,7 @@ public class FilmController { @GetMapping public List findAll() { - return new ArrayList<>(filmService.getAllFilms()); + return filmService.getAllFilms(); } @PostMapping @@ -61,7 +59,7 @@ public void deleteLike(@PathVariable Long id, @PathVariable Long userId) { } @GetMapping("/popular") - public Collection getPopularFilms(@RequestParam(required = false, defaultValue = "10") Integer count) { + public List getPopularFilms(@RequestParam(required = false, defaultValue = "10") Integer count) { log.info("Получен список популярных фильмов"); return filmService.getPopularFilms(count); } diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java b/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java index 2793ad9..df77734 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java @@ -17,7 +17,6 @@ import ru.yandex.practicum.filmorate.model.User; import ru.yandex.practicum.filmorate.service.UserService; -import java.util.ArrayList; import java.util.List; @RestController @@ -29,7 +28,7 @@ public class UserController { @GetMapping public List findAll() { - return new ArrayList<>(userService.getAllUsers()); + return userService.getAllUsers(); } @PostMapping @@ -57,11 +56,11 @@ public void deleteFriend(@PathVariable Long id, @PathVariable Long friendId) { @GetMapping("/{id}/friends") public List getFriends(@PathVariable Long id) { - return new ArrayList<>(userService.allIdFriends(id)); + return userService.allIdFriends(id); } @GetMapping("/{id}/friends/common/{otherId}") public List getCommonFriends(@PathVariable Long id, @PathVariable Long otherId) { - return new ArrayList<>(userService.generalFriends(id, otherId)); + return userService.generalFriends(id, otherId); } } \ No newline at end of file diff --git a/src/main/java/ru/yandex/practicum/filmorate/exceptions/GlobalExceptionHandler.java b/src/main/java/ru/yandex/practicum/filmorate/exceptions/GlobalExceptionHandler.java index 3ed0a47..e7443ef 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/exceptions/GlobalExceptionHandler.java +++ b/src/main/java/ru/yandex/practicum/filmorate/exceptions/GlobalExceptionHandler.java @@ -8,12 +8,6 @@ @RestControllerAdvice public class GlobalExceptionHandler { - public static class FilmNotFoundException extends RuntimeException { - public FilmNotFoundException(String message) { - super(message); - } - } - @ExceptionHandler(ValidationException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) public ErrorResponse handleValidationException(ValidationException exception) { @@ -25,10 +19,4 @@ public ErrorResponse handleValidationException(ValidationException exception) { public ErrorResponse handleUserNotFoundException(UserNotFoundException exception) { return new ErrorResponse(exception.getMessage()); } - - @ExceptionHandler(FilmNotFoundException.class) - @ResponseStatus(HttpStatus.NOT_FOUND) - public ErrorResponse handleFilmNotFoundException(FilmNotFoundException exception) { - return new ErrorResponse(exception.getMessage()); - } -} +} \ No newline at end of file diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java b/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java index d0d5ff7..cf8362f 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java +++ b/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java @@ -10,7 +10,6 @@ import ru.yandex.practicum.filmorate.storage.UserStorage; import java.util.ArrayList; -import java.util.Collection; import java.util.List; @Slf4j @@ -21,7 +20,7 @@ public class FilmService { private final FilmStorage filmStorage; private final UserStorage userStorage; - public Collection getAllFilms() { + public List getAllFilms() { return filmStorage.getAllFilms(); } @@ -64,7 +63,7 @@ public void deleteLike(Long userId, Long id) { log.info("Пользователь c id: {} удалил лайк у фильма id: {}", userId, id); } - public Collection getPopularFilms(int count) { + public List getPopularFilms(int count) { List films = new ArrayList<>(filmStorage.getAllFilms()); films.sort((film, filmToCompare) -> Integer.compare( filmToCompare.getIdUserLikes().size(), diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java b/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java index eb79bcf..07d9887 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java +++ b/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java @@ -8,8 +8,8 @@ import ru.yandex.practicum.filmorate.model.User; import ru.yandex.practicum.filmorate.storage.UserStorage; -import java.util.Collection; import java.util.HashSet; +import java.util.List; import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; @@ -21,7 +21,7 @@ public class UserService { private final UserStorage userStorage; - public Collection getAllUsers() { + public List getAllUsers() { return userStorage.getAllUsers(); } @@ -75,7 +75,7 @@ public void deleteFriend(Long id, Long friendId) { log.info("Друг удален с id: " + friendId); } - public Collection allIdFriends(Long id) { + public List allIdFriends(Long id) { User user = userStorage.getUser(id); if (user == null) { log.error("Пользователь с id {} не найден", id); @@ -89,7 +89,7 @@ public Collection allIdFriends(Long id) { } - public Collection generalFriends(Long id, Long otherId) { + public List generalFriends(Long id, Long otherId) { User user = userStorage.getUser(id); User otherUser = userStorage.getUser(otherId); diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorage.java index 23a1dfb..bb46e80 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorage.java @@ -48,7 +48,10 @@ public User getUser(long id) { } private long getNextId() { - long currentMaxId = allUsers.keySet().stream().mapToLong(id -> id).max().orElse(0); + long currentMaxId = allUsers.keySet().stream() + .mapToLong(id -> id) + .max() + .orElse(0); return ++currentMaxId; } -} \ No newline at end of file +} diff --git a/src/test/java/ru/yandex/practicum/filmorate/service/ServiceTests.java b/src/test/java/ru/yandex/practicum/filmorate/service/ServiceTests.java index afb2a75..f5a80ac 100644 --- a/src/test/java/ru/yandex/practicum/filmorate/service/ServiceTests.java +++ b/src/test/java/ru/yandex/practicum/filmorate/service/ServiceTests.java @@ -1,5 +1,6 @@ package ru.yandex.practicum.filmorate.service; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -25,7 +26,8 @@ public class ServiceTests { @Nested class FriendshipTests { - @Test // Тесты для работы с друзьями + @Test + // Тесты для работы с друзьями void testFriendshipOperations() { User user1 = new User(); user1.setEmail("user1@mail.com"); @@ -49,7 +51,8 @@ void testFriendshipOperations() { assertFalse(userService.allIdFriends(user1.getId()).contains(user2)); } - @Test // Тесты для работы с общими друзьями + @Test + // Тесты для работы с общими друзьями void testCommonFriends() { User user1 = new User(); user1.setEmail("user1@mail.com"); @@ -83,15 +86,18 @@ void testCommonFriends() { @Nested class FilmLikesTests { - @Test // Тесты для работы с лайками - void testLikeOperations() { - Film film = new Film(); + private Film film; + private User user; + + @BeforeEach + void setUp() { + film = new Film(); film.setName("Test Film"); film.setDescription("Test Description"); film.setReleaseDate(LocalDate.of(2000, 1, 1)); film.setDuration(120); - User user = new User(); + user = new User(); user.setEmail("user@mail.com"); user.setLogin("user"); user.setName("User"); @@ -99,7 +105,11 @@ void testLikeOperations() { film = filmService.addFilm(film); user = userService.addUser(user); + } + @Test + // Тесты для работы с лайками + void testLikeOperations() { filmService.addLike(user.getId(), film.getId()); assertTrue(film.getIdUserLikes().contains(user.getId())); @@ -107,34 +117,20 @@ void testLikeOperations() { assertFalse(film.getIdUserLikes().contains(user.getId())); } - @Test // Тесты для работы с популярными фильмами + @Test + // Тесты для работы с популярными фильмами void testPopularFilms() { - Film film1 = new Film(); - film1.setName("Film 1"); - film1.setDescription("Description 1"); - film1.setReleaseDate(LocalDate.of(2000, 1, 1)); - film1.setDuration(120); - Film film2 = new Film(); film2.setName("Film 2"); film2.setDescription("Description 2"); film2.setReleaseDate(LocalDate.of(2000, 1, 2)); film2.setDuration(120); - - User user = new User(); - user.setEmail("user@mail.com"); - user.setLogin("user"); - user.setName("User"); - user.setBirthday(LocalDate.of(1990, 1, 1)); - - film1 = filmService.addFilm(film1); film2 = filmService.addFilm(film2); - user = userService.addUser(user); - filmService.addLike(user.getId(), film1.getId()); + filmService.addLike(user.getId(), film.getId()); List popularFilms = new ArrayList<>(filmService.getPopularFilms(10)); - assertEquals(film1.getId(), popularFilms.get(0).getId()); + assertEquals(film.getId(), popularFilms.get(0).getId()); } } }