From d26a28f87fd45ddceb5f113472d5e682a800a682 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D0=BB=D0=B0=D0=B2=D0=B0?= Date: Fri, 28 Mar 2025 07:03:33 +0400 Subject: [PATCH 1/2] =?UTF-8?q?=D0=9F=D0=B5=D1=80=D0=B2=D0=B0=20=D1=80?= =?UTF-8?q?=D0=B5=D0=B0=D0=BB=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D1=8F=20=D1=82?= =?UTF-8?q?=D0=B7=2011=D0=BE=D0=B3=D0=BE=20=D1=81=D0=BF=D1=80=D0=B8=D0=BD?= =?UTF-8?q?=D1=82=D0=B0.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../filmorate/controller/ErrorHandler.java | 36 +++++++ .../filmorate/controller/FilmController.java | 75 +++++++-------- .../filmorate/controller/UserController.java | 69 +++++++------ .../exception/DataNotFoundException.java | 7 ++ .../filmorate/model/ErrorResponse.java | 20 ++++ .../practicum/filmorate/model/Film.java | 8 +- .../practicum/filmorate/model/User.java | 3 + .../filmorate/service/FilmService.java | 73 ++++++++++++++ .../filmorate/service/UserService.java | 96 +++++++++++++++++++ .../filmorate/storage/FilmStorage.java | 19 ++++ .../storage/InMemoryFilmStorage.java | 69 +++++++++++++ .../storage/InMemoryUserStorage.java | 67 +++++++++++++ .../filmorate/storage/UserStorage.java | 17 ++++ .../filmorate/FilmorateApplicationTests.java | 6 +- .../controller/FilmControllerTest.java | 3 +- .../controller/UserControllerTest.java | 5 +- 16 files changed, 491 insertions(+), 82 deletions(-) create mode 100644 src/main/java/ru/yandex/practicum/filmorate/controller/ErrorHandler.java create mode 100644 src/main/java/ru/yandex/practicum/filmorate/exception/DataNotFoundException.java create mode 100644 src/main/java/ru/yandex/practicum/filmorate/model/ErrorResponse.java create mode 100644 src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java create mode 100644 src/main/java/ru/yandex/practicum/filmorate/service/UserService.java create mode 100644 src/main/java/ru/yandex/practicum/filmorate/storage/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 diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/ErrorHandler.java b/src/main/java/ru/yandex/practicum/filmorate/controller/ErrorHandler.java new file mode 100644 index 0000000..0b04798 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/ErrorHandler.java @@ -0,0 +1,36 @@ +package ru.yandex.practicum.filmorate.controller; + + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpStatus; +import ru.yandex.practicum.filmorate.exception.DataNotFoundException; +import ru.yandex.practicum.filmorate.model.ErrorResponse; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestControllerAdvice; +import ru.yandex.practicum.filmorate.exception.ValidationException; + +@RestControllerAdvice +public class ErrorHandler { + + private static final Logger log = LoggerFactory.getLogger(ErrorHandler.class); + + @ExceptionHandler + @ResponseStatus(HttpStatus.BAD_REQUEST) + public ErrorResponse handleValidationException(final ValidationException e) { + log.info("400 {}", e.getMessage()); + return new ErrorResponse(e.getMessage()); + + } + + @ExceptionHandler + @ResponseStatus(HttpStatus.NOT_FOUND) + public ErrorResponse handleNotFoundException(final DataNotFoundException e) { + log.info("404 {}", e.getMessage()); + return new ErrorResponse(e.getMessage()); + + } + +} + 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 752734a..4b1feae 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java @@ -1,65 +1,62 @@ package ru.yandex.practicum.filmorate.controller; import jakarta.validation.Valid; -import lombok.extern.slf4j.Slf4j; +import lombok.RequiredArgsConstructor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.*; +import ru.yandex.practicum.filmorate.exception.DataNotFoundException; import ru.yandex.practicum.filmorate.exception.ValidationException; import ru.yandex.practicum.filmorate.model.Film; +import ru.yandex.practicum.filmorate.service.FilmService; + -import java.time.LocalDate; -import java.time.Month; import java.util.Collection; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; +import java.util.List; + @RestController -@RequestMapping("/films") -@Slf4j +@RequestMapping +@RequiredArgsConstructor public class FilmController { - private final Map films = new ConcurrentHashMap<>(); - private int nextId = 1; - @GetMapping + private static final Logger log = LoggerFactory.getLogger(FilmController.class); + private final FilmService filmService; + + @GetMapping(path = "/films") public Collection getFilms() { - return films.values(); + return filmService.getFilms(); } - @PostMapping + @PostMapping(path = "/films") public Film createFilm(@Valid @RequestBody Film film) throws ValidationException { - LocalDate date = LocalDate.of(1895, Month.DECEMBER, 28); - if (film.getName() == null || film.getName().isEmpty()) { - throw new ValidationException("Название фильма не может быть пустым"); - } - if (film.getDescription() == null || film.getDescription().length() > 200) { - throw new ValidationException("Максимальная длина описания — 200 символов"); - } - if (film.getReleaseDate().isBefore(date)) { - throw new ValidationException("Дата релиза — не раньше 28 декабря 1895 года"); - } - if (film.getDuration() <= 0) { - throw new ValidationException("Продолжительность фильма должна быть положительным числом"); - } - film.setId(getNextId()); - films.put(film.getId(), film); - log.debug("Фильм успешно добавлен"); - return film; + return filmService.createFilm(film); } - @PutMapping - public Film updateFilm(@RequestBody Film newFilm) throws ValidationException { + @PutMapping(path = "/films") + public Film updateFilm(@RequestBody Film newFilm) throws DataNotFoundException { - if (newFilm.getId() != null && films.containsKey(newFilm.getId())) { - films.put(newFilm.getId(), newFilm); - log.debug("Фильм успешно изменён"); - return newFilm; - } - throw new ValidationException("Некорректный Id"); + return filmService.updateFilm(newFilm); } - private int getNextId() { - return nextId++; + @PutMapping(path = "/films/{id}/like/{userId}") + public void addLike(@PathVariable("id") int id, @PathVariable("userId") int userId) { + + filmService.addLike(id, userId); + } + @DeleteMapping(path = "/films/{id}/like/{userId}") + public void deleteLike(@PathVariable("id") int id, @PathVariable("userId") int userId) { + log.info("delete like: {}", id); + filmService.deleteLike(id, userId); } + + @GetMapping(path = "/films/popular") + public List getPopularFilms(@RequestParam(defaultValue = "10") int count) { + 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 3d67a63..1615b08 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java @@ -1,63 +1,62 @@ package ru.yandex.practicum.filmorate.controller; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.*; +import ru.yandex.practicum.filmorate.exception.DataNotFoundException; import ru.yandex.practicum.filmorate.exception.ValidationException; import ru.yandex.practicum.filmorate.model.User; +import ru.yandex.practicum.filmorate.service.UserService; + -import java.time.LocalDate; import java.util.Collection; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; +import java.util.List; + @RestController -@RequestMapping("/users") +@RequestMapping @Slf4j +@RequiredArgsConstructor public class UserController { - private final Map users = new ConcurrentHashMap<>(); - private int nextId = 1; - @GetMapping + private final UserService userService; + + + @GetMapping(path = "/users") public Collection getUsers() { - return users.values(); + return userService.getUsers(); } - @PostMapping + @PostMapping(path = "/users") public User createUser(@RequestBody User user) throws ValidationException { - if (user.getEmail().isEmpty() || !user.getEmail().contains("@")) { - throw new ValidationException("Электронная почта не может быть пустой и должна содержать символ @"); - } - if (user.getLogin() == null || user.getLogin().isEmpty() || user.getLogin().contains(" ")) { - throw new ValidationException("Логин не может быть пустым и содержать пробелы"); - } - if (user.getName() == null) { - user.setName(user.getLogin()); - } - if (user.getBirthday().isAfter(LocalDate.now())) { - throw new ValidationException("Дата рождения не может быть в будущем"); - } - user.setId(getNextId()); - users.put(user.getId(), user); - log.debug("Пользователь успешно добавлен"); - return user; + + return userService.createUser(user); } - @PutMapping - public User updateUser(@RequestBody User newUser) throws ValidationException { + @PutMapping(path = "/users") + public User updateUser(@RequestBody User newUser) throws DataNotFoundException { + return userService.updateUser(newUser); - if (newUser.getId() != null && users.containsKey(newUser.getId())) { - users.put(newUser.getId(), newUser); - log.debug("Пользователь успешно изменён"); - return newUser; - } + } - throw new ValidationException("Некорректный Id"); + @PutMapping(path = "/users/{id}/friends/{friendId}") + public void addFriend(@PathVariable("id") int id, @PathVariable("friendId") int friendId) throws DataNotFoundException { + userService.addFriend(id, friendId); } + @DeleteMapping(path = "/users/{id}/friends/{friendId}") + public void deleteFriend(@PathVariable("id") int id, @PathVariable("friendId") int friendId) throws DataNotFoundException { + userService.deleteFriend(id, friendId); + } - private int getNextId() { - return nextId++; + @GetMapping(path = "/users/{id}/friends") + public List getUserFriends(@PathVariable("id") int id) throws DataNotFoundException { + return userService.getUserFriends(id); + } + @GetMapping(path = "/users/{id}/friends/common/{otherId}") + public List getCommonFriends(@PathVariable("id") int id, @PathVariable("otherId") int otherId) { + return userService.getCommonFriends(id, otherId); } } diff --git a/src/main/java/ru/yandex/practicum/filmorate/exception/DataNotFoundException.java b/src/main/java/ru/yandex/practicum/filmorate/exception/DataNotFoundException.java new file mode 100644 index 0000000..96be3ce --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/exception/DataNotFoundException.java @@ -0,0 +1,7 @@ +package ru.yandex.practicum.filmorate.exception; + +public class DataNotFoundException extends NullPointerException { + public DataNotFoundException(String message) { + super(message); + } +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/model/ErrorResponse.java b/src/main/java/ru/yandex/practicum/filmorate/model/ErrorResponse.java new file mode 100644 index 0000000..aea38a7 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/model/ErrorResponse.java @@ -0,0 +1,20 @@ +package ru.yandex.practicum.filmorate.model; + +public class ErrorResponse { + private final String error; + + public ErrorResponse(String error) { + this.error = error; + } + + public String getError() { + return error; + } + + + @Override + public String toString() { + return + "error= " + error; + } +} 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 8063357..ab003db 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/model/Film.java +++ b/src/main/java/ru/yandex/practicum/filmorate/model/Film.java @@ -1,22 +1,26 @@ package ru.yandex.practicum.filmorate.model; import lombok.Getter; -import lombok.NoArgsConstructor; +import lombok.RequiredArgsConstructor; import lombok.Setter; import java.time.LocalDate; +import java.util.HashSet; +import java.util.Set; /** * Film. */ @Getter @Setter -@NoArgsConstructor +@RequiredArgsConstructor public class Film { private Integer id; private String name; private String description; private LocalDate releaseDate; private Long duration; + private Set likes = new HashSet<>(); + } 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 a489737..75662c3 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/model/User.java +++ b/src/main/java/ru/yandex/practicum/filmorate/model/User.java @@ -5,11 +5,14 @@ import lombok.Setter; import java.time.LocalDate; +import java.util.HashSet; +import java.util.Set; @Getter @Setter @NoArgsConstructor public class User { + private Set friendsList = new HashSet<>(); private Integer id; private String email; private String login; 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..c909ce8 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java @@ -0,0 +1,73 @@ +package ru.yandex.practicum.filmorate.service; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import ru.yandex.practicum.filmorate.exception.DataNotFoundException; +import ru.yandex.practicum.filmorate.exception.ValidationException; +import ru.yandex.practicum.filmorate.model.Film; +import ru.yandex.practicum.filmorate.model.User; +import ru.yandex.practicum.filmorate.storage.FilmStorage; +import ru.yandex.practicum.filmorate.storage.UserStorage; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Comparator; +import java.util.List; +import java.util.stream.Collectors; + +@Service +@RequiredArgsConstructor +@Slf4j +public class FilmService { + + private final FilmStorage filmStorage; + private final UserStorage userStorage; + + public Collection getFilms() { + return filmStorage.getFilms(); + } + + public Film createFilm(Film film) throws ValidationException { + return filmStorage.createFilm(film); + } + + public Film updateFilm(Film newFilm) throws DataNotFoundException { + + return filmStorage.updateFilm(newFilm); + } + + public void addLike(int id, int userId) { + Film film = filmStorage.get(id); + User user = userStorage.get(userId); + if (film == null || user == null) { + throw new DataNotFoundException("Некорректный айди фильма или пользователя"); + } + film.getLikes().add(userId); + log.info("add like: {}", film); + } + + public void deleteLike(int id, int userId) { + Film film = filmStorage.get(id); + User user = userStorage.get(userId); + if (film == null || user == null) { + throw new DataNotFoundException("Некорректный айди фильма или пользователя"); + } + film.getLikes().remove(userId); + log.info("delete like: {}", film); + } + + public List getPopularFilms(int count) { + List popularFilms = new ArrayList<>(filmStorage.getFilms()); + popularFilms.sort(FILM_COMPARATOR.reversed()); + return popularFilms.stream().limit(count).collect(Collectors.toList()); + + } + + public static final Comparator FILM_COMPARATOR = new Comparator() { + @Override + public int compare(Film o1, Film o2) { + return o1.getLikes().size() - o2.getLikes().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 new file mode 100644 index 0000000..e9e9b2d --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java @@ -0,0 +1,96 @@ +package ru.yandex.practicum.filmorate.service; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import ru.yandex.practicum.filmorate.exception.DataNotFoundException; +import ru.yandex.practicum.filmorate.exception.ValidationException; +import ru.yandex.practicum.filmorate.model.User; +import ru.yandex.practicum.filmorate.storage.UserStorage; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + + +@Service +@RequiredArgsConstructor +public class UserService { + private final UserStorage userStorage; + + public Collection getUsers() { + return userStorage.getUsers(); + } + + public User createUser(User user) throws ValidationException { + + return userStorage.createUser(user); + } + + public User updateUser(User newUser) throws DataNotFoundException { + return userStorage.updateUser(newUser); + + } + + public void addFriend(int id, int friendId) throws DataNotFoundException { + + User user = userStorage.get(id); + User friend = userStorage.get(friendId); + if (user == null) { + throw new DataNotFoundException("Искомый пользователь не найден"); + + } + if (friend == null) { + throw new DataNotFoundException("Искомый друг не найден"); + + } + user.getFriendsList().add(friendId); + friend.getFriendsList().add(id); + } + + public void deleteFriend(Integer id, int friendId) throws DataNotFoundException { + + User user = userStorage.get(id); + User friend = userStorage.get(friendId); + if (user == null) { + throw new DataNotFoundException("Искомый пользователь не найден"); + + } + if (friend == null) { + throw new DataNotFoundException("Искомый друг не найден"); + + } + user.getFriendsList().remove(friendId); + friend.getFriendsList().remove(id); + } + + public List getUserFriends(int id) throws DataNotFoundException { + + User user = userStorage.get(id); + if (user == null) { + throw new DataNotFoundException("Искомый пользователь не найден"); + + } + List friends = new ArrayList<>(); + for (Integer friend : user.getFriendsList()) { + friends.add(userStorage.get(friend)); + } + return friends; + + } + + public List getCommonFriends(int id, int otherId) { + List userList = getUserFriends(id); + List otherUserList = getUserFriends(otherId); + List commonFriends = new ArrayList<>(); + for (User user : userList) { + if (otherUserList.contains(user)) { + commonFriends.add(user); + } + } + return commonFriends; + + + } + + +} 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..3634ad0 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/FilmStorage.java @@ -0,0 +1,19 @@ +package ru.yandex.practicum.filmorate.storage; + +import ru.yandex.practicum.filmorate.exception.DataNotFoundException; +import ru.yandex.practicum.filmorate.exception.ValidationException; +import ru.yandex.practicum.filmorate.model.Film; + +import java.util.Collection; + +public interface FilmStorage { + + Collection getFilms(); + + Film createFilm(Film film) throws ValidationException; + + + Film updateFilm(Film newFilm) throws DataNotFoundException; + + Film get(int filmId); +} 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..b8b0a7d --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryFilmStorage.java @@ -0,0 +1,69 @@ +package ru.yandex.practicum.filmorate.storage; + + +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import ru.yandex.practicum.filmorate.exception.DataNotFoundException; +import ru.yandex.practicum.filmorate.exception.ValidationException; +import ru.yandex.practicum.filmorate.model.Film; + +import java.time.LocalDate; +import java.time.Month; +import java.util.Collection; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + + +@Component +@Slf4j +public class InMemoryFilmStorage implements FilmStorage { + + private final Map films = new ConcurrentHashMap<>(); + private int nextId = 1; + + @Override + public Collection getFilms() { + return films.values(); + } + + @Override + public Film createFilm(Film film) throws ValidationException { + LocalDate date = LocalDate.of(1895, Month.DECEMBER, 28); + if (film.getName() == null || film.getName().isEmpty()) { + throw new ValidationException("Название фильма не может быть пустым"); + } + if (film.getDescription() == null || film.getDescription().length() > 200) { + throw new ValidationException("Максимальная длина описания — 200 символов"); + } + if (film.getReleaseDate().isBefore(date)) { + throw new ValidationException("Дата релиза — не раньше 28 декабря 1895 года"); + } + if (film.getDuration() <= 0) { + throw new ValidationException("Продолжительность фильма должна быть положительным числом"); + } + film.setId(getNextId()); + films.put(film.getId(), film); + log.debug("Фильм успешно добавлен"); + return film; + } + + @Override + public Film updateFilm(Film newFilm) throws DataNotFoundException { + if (newFilm.getId() != null && films.containsKey(newFilm.getId())) { + films.put(newFilm.getId(), newFilm); + log.debug("Фильм успешно изменён"); + return newFilm; + } + throw new DataNotFoundException("Некорректный Id"); + } + + @Override + public Film get(int id) { + return films.get(id); + } + + private int getNextId() { + return nextId++; + + } +} 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..23bdbee --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorage.java @@ -0,0 +1,67 @@ +package ru.yandex.practicum.filmorate.storage; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import ru.yandex.practicum.filmorate.exception.DataNotFoundException; +import ru.yandex.practicum.filmorate.exception.ValidationException; +import ru.yandex.practicum.filmorate.model.User; + +import java.time.LocalDate; +import java.util.Collection; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +@Component +@Slf4j +public class InMemoryUserStorage implements UserStorage { + + private final Map users = new ConcurrentHashMap<>(); + private int nextId = 1; + + @Override + public Collection getUsers() { + return users.values(); + } + + @Override + public User createUser(User user) throws ValidationException { + if (user.getEmail().isEmpty() || !user.getEmail().contains("@")) { + throw new ValidationException("Электронная почта не может быть пустой и должна содержать символ @"); + } + if (user.getLogin() == null || user.getLogin().isEmpty() || user.getLogin().contains(" ")) { + throw new ValidationException("Логин не может быть пустым и содержать пробелы"); + } + if (user.getName() == null) { + user.setName(user.getLogin()); + } + if (user.getBirthday().isAfter(LocalDate.now())) { + throw new ValidationException("Дата рождения не может быть в будущем"); + } + user.setId(getNextId()); + users.put(user.getId(), user); + log.debug("Пользователь успешно добавлен"); + return user; + } + + @Override + public User updateUser(User newUser) throws DataNotFoundException { + if (newUser.getId() != null && users.containsKey(newUser.getId())) { + users.put(newUser.getId(), newUser); + log.debug("Пользователь успешно изменён"); + return newUser; + } + + throw new DataNotFoundException("Некорректный Id"); + + } + + @Override + public User get(int id) { + return users.get(id); + } + + private int getNextId() { + return nextId++; + + } +} 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..296d8a9 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/UserStorage.java @@ -0,0 +1,17 @@ +package ru.yandex.practicum.filmorate.storage; + +import ru.yandex.practicum.filmorate.exception.DataNotFoundException; +import ru.yandex.practicum.filmorate.exception.ValidationException; +import ru.yandex.practicum.filmorate.model.User; + +import java.util.Collection; + +public interface UserStorage { + Collection getUsers(); + + User createUser(User user) throws ValidationException; + + User updateUser(User newUser) throws DataNotFoundException; + + User get(int id); +} diff --git a/src/test/java/ru/yandex/practicum/filmorate/FilmorateApplicationTests.java b/src/test/java/ru/yandex/practicum/filmorate/FilmorateApplicationTests.java index 660412e..dc5cfdf 100644 --- a/src/test/java/ru/yandex/practicum/filmorate/FilmorateApplicationTests.java +++ b/src/test/java/ru/yandex/practicum/filmorate/FilmorateApplicationTests.java @@ -6,8 +6,8 @@ @SpringBootTest class FilmorateApplicationTests { - @Test - void contextLoads() { - } + @Test + void contextLoads() { + } } diff --git a/src/test/java/ru/yandex/practicum/filmorate/controller/FilmControllerTest.java b/src/test/java/ru/yandex/practicum/filmorate/controller/FilmControllerTest.java index af87af4..a8e13d9 100644 --- a/src/test/java/ru/yandex/practicum/filmorate/controller/FilmControllerTest.java +++ b/src/test/java/ru/yandex/practicum/filmorate/controller/FilmControllerTest.java @@ -3,6 +3,7 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; +import ru.yandex.practicum.filmorate.exception.DataNotFoundException; import ru.yandex.practicum.filmorate.exception.ValidationException; import ru.yandex.practicum.filmorate.model.Film; @@ -84,6 +85,6 @@ void updateFilmTest() throws ValidationException { Film filmUpdate = new Film(); filmUpdate.setId(8); - assertThrows(ValidationException.class, () -> filmController.updateFilm(filmUpdate)); + assertThrows(DataNotFoundException.class, () -> filmController.updateFilm(filmUpdate)); } } diff --git a/src/test/java/ru/yandex/practicum/filmorate/controller/UserControllerTest.java b/src/test/java/ru/yandex/practicum/filmorate/controller/UserControllerTest.java index 8f40a1a..dbf950f 100644 --- a/src/test/java/ru/yandex/practicum/filmorate/controller/UserControllerTest.java +++ b/src/test/java/ru/yandex/practicum/filmorate/controller/UserControllerTest.java @@ -3,6 +3,7 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; +import ru.yandex.practicum.filmorate.exception.DataNotFoundException; import ru.yandex.practicum.filmorate.exception.ValidationException; import ru.yandex.practicum.filmorate.model.User; @@ -17,7 +18,7 @@ public class UserControllerTest { @Autowired - private UserController userController = new UserController(); + private UserController userController; @Test public void returnsUsersTest() throws ValidationException { @@ -94,6 +95,6 @@ void updateUserTest() throws ValidationException { userUpdate.setName(null); userUpdate.setBirthday(LocalDate.of(1999, 8, 6)); userUpdate.setId(8); - assertThrows(ValidationException.class, () -> userController.updateUser(userUpdate)); + assertThrows(DataNotFoundException.class, () -> userController.updateUser(userUpdate)); } } From 8e1315ea17369f39d7a5988289990160a79bffcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D0=BB=D0=B0=D0=B2=D0=B0?= Date: Sat, 29 Mar 2025 04:12:53 +0400 Subject: [PATCH 2/2] =?UTF-8?q?=D0=92=D1=82=D0=BE=D1=80=D0=B0=D1=8F=20?= =?UTF-8?q?=D1=80=D0=B5=D0=B0=D0=BB=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D1=8F=20?= =?UTF-8?q?=D1=82=D0=B7=2011=D0=BE=D0=B3=D0=BE=20=D1=81=D0=BF=D1=80=D0=B8?= =?UTF-8?q?=D0=BD=D1=82=D0=B0.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../filmorate/controller/FilmController.java | 5 ++- .../filmorate/controller/UserController.java | 2 +- .../exception/DataNotFoundException.java | 2 +- .../filmorate/service/FilmService.java | 28 +++++++-------- .../filmorate/service/UserService.java | 35 ++++++------------- .../filmorate/storage/FilmStorage.java | 2 +- .../storage/InMemoryFilmStorage.java | 7 ++-- .../storage/InMemoryUserStorage.java | 5 ++- .../filmorate/storage/UserStorage.java | 2 +- 9 files changed, 40 insertions(+), 48 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 4b1feae..0f35e51 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java @@ -42,14 +42,13 @@ public Film updateFilm(@RequestBody Film newFilm) throws DataNotFoundException { } @PutMapping(path = "/films/{id}/like/{userId}") - public void addLike(@PathVariable("id") int id, @PathVariable("userId") int userId) { + public void addLike(@PathVariable("id") int id, @PathVariable("userId") int userId) throws DataNotFoundException { filmService.addLike(id, userId); } @DeleteMapping(path = "/films/{id}/like/{userId}") - public void deleteLike(@PathVariable("id") int id, @PathVariable("userId") int userId) { - log.info("delete like: {}", id); + public void deleteLike(@PathVariable("id") int id, @PathVariable("userId") int userId) throws DataNotFoundException { filmService.deleteLike(id, userId); } 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 1615b08..7b3d42d 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java @@ -56,7 +56,7 @@ public List getUserFriends(@PathVariable("id") int id) throws DataNotFound } @GetMapping(path = "/users/{id}/friends/common/{otherId}") - public List getCommonFriends(@PathVariable("id") int id, @PathVariable("otherId") int otherId) { + public List getCommonFriends(@PathVariable("id") int id, @PathVariable("otherId") int otherId) throws DataNotFoundException { return userService.getCommonFriends(id, otherId); } } diff --git a/src/main/java/ru/yandex/practicum/filmorate/exception/DataNotFoundException.java b/src/main/java/ru/yandex/practicum/filmorate/exception/DataNotFoundException.java index 96be3ce..589a8d6 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/exception/DataNotFoundException.java +++ b/src/main/java/ru/yandex/practicum/filmorate/exception/DataNotFoundException.java @@ -1,6 +1,6 @@ package ru.yandex.practicum.filmorate.exception; -public class DataNotFoundException extends NullPointerException { +public class DataNotFoundException extends Exception { public DataNotFoundException(String message) { super(message); } 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 c909ce8..0731a2a 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java +++ b/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java @@ -8,7 +8,6 @@ import ru.yandex.practicum.filmorate.model.Film; import ru.yandex.practicum.filmorate.model.User; import ru.yandex.practicum.filmorate.storage.FilmStorage; -import ru.yandex.practicum.filmorate.storage.UserStorage; import java.util.ArrayList; import java.util.Collection; @@ -22,7 +21,7 @@ public class FilmService { private final FilmStorage filmStorage; - private final UserStorage userStorage; + private final UserService userService; public Collection getFilms() { return filmStorage.getFilms(); @@ -37,22 +36,18 @@ public Film updateFilm(Film newFilm) throws DataNotFoundException { return filmStorage.updateFilm(newFilm); } - public void addLike(int id, int userId) { - Film film = filmStorage.get(id); - User user = userStorage.get(userId); - if (film == null || user == null) { - throw new DataNotFoundException("Некорректный айди фильма или пользователя"); - } + public void addLike(int id, int userId) throws DataNotFoundException { + Film film = get(id); + User user = userService.get(userId); + film.getLikes().add(userId); log.info("add like: {}", film); } - public void deleteLike(int id, int userId) { - Film film = filmStorage.get(id); - User user = userStorage.get(userId); - if (film == null || user == null) { - throw new DataNotFoundException("Некорректный айди фильма или пользователя"); - } + public void deleteLike(int id, int userId) throws DataNotFoundException { + Film film = get(id); + User user = userService.get(userId); + film.getLikes().remove(userId); log.info("delete like: {}", film); } @@ -69,5 +64,10 @@ public List getPopularFilms(int count) { public int compare(Film o1, Film o2) { return o1.getLikes().size() - o2.getLikes().size(); } + }; + + public Film get(int filmId) throws DataNotFoundException { + return filmStorage.get(filmId); + } } 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 e9e9b2d..de588ba 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java +++ b/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java @@ -33,52 +33,35 @@ public User updateUser(User newUser) throws DataNotFoundException { public void addFriend(int id, int friendId) throws DataNotFoundException { - User user = userStorage.get(id); - User friend = userStorage.get(friendId); - if (user == null) { - throw new DataNotFoundException("Искомый пользователь не найден"); + User user = get(id); + User friend = get(friendId); - } - if (friend == null) { - throw new DataNotFoundException("Искомый друг не найден"); - - } user.getFriendsList().add(friendId); friend.getFriendsList().add(id); } public void deleteFriend(Integer id, int friendId) throws DataNotFoundException { - User user = userStorage.get(id); - User friend = userStorage.get(friendId); - if (user == null) { - throw new DataNotFoundException("Искомый пользователь не найден"); - - } - if (friend == null) { - throw new DataNotFoundException("Искомый друг не найден"); + User user = get(id); + User friend = get(friendId); - } user.getFriendsList().remove(friendId); friend.getFriendsList().remove(id); } public List getUserFriends(int id) throws DataNotFoundException { - User user = userStorage.get(id); - if (user == null) { - throw new DataNotFoundException("Искомый пользователь не найден"); + User user = get(id); - } List friends = new ArrayList<>(); for (Integer friend : user.getFriendsList()) { - friends.add(userStorage.get(friend)); + friends.add(get(friend)); } return friends; } - public List getCommonFriends(int id, int otherId) { + public List getCommonFriends(int id, int otherId) throws DataNotFoundException { List userList = getUserFriends(id); List otherUserList = getUserFriends(otherId); List commonFriends = new ArrayList<>(); @@ -93,4 +76,8 @@ public List getCommonFriends(int id, int otherId) { } + public User get(int userId) throws DataNotFoundException { + + return userStorage.get(userId); + } } 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 3634ad0..4d0311d 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/FilmStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/FilmStorage.java @@ -15,5 +15,5 @@ public interface FilmStorage { Film updateFilm(Film newFilm) throws DataNotFoundException; - Film get(int filmId); + Film get(int filmId) throws DataNotFoundException; } 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 b8b0a7d..b44b130 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryFilmStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryFilmStorage.java @@ -54,11 +54,14 @@ public Film updateFilm(Film newFilm) throws DataNotFoundException { log.debug("Фильм успешно изменён"); return newFilm; } - throw new DataNotFoundException("Некорректный Id"); + throw new DataNotFoundException("Фильм не найден"); } @Override - public Film get(int id) { + public Film get(int id) throws DataNotFoundException { + if (films.get(id) == null) { + throw new DataNotFoundException("Фильм не найден"); + } return films.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 23bdbee..11bbd05 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorage.java @@ -56,7 +56,10 @@ public User updateUser(User newUser) throws DataNotFoundException { } @Override - public User get(int id) { + public User get(int id) throws DataNotFoundException { + if (users.get(id) == null) { + throw new DataNotFoundException("Искомый пользователь не найден"); + } return users.get(id); } 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 296d8a9..860a424 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/UserStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/UserStorage.java @@ -13,5 +13,5 @@ public interface UserStorage { User updateUser(User newUser) throws DataNotFoundException; - User get(int id); + User get(int id) throws DataNotFoundException; }