diff --git a/pom.xml b/pom.xml
index a973f82..b68f756 100644
--- a/pom.xml
+++ b/pom.xml
@@ -61,6 +61,27 @@
4.0.0
test
+
+
+
+ com.h2database
+ h2
+ runtime
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-jdbc
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
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 ef0a166..b0a6080 100644
--- a/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java
+++ b/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java
@@ -1,73 +1,118 @@
package ru.yandex.practicum.filmorate.controller;
+import com.fasterxml.jackson.databind.node.ObjectNode;
import jakarta.validation.Valid;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
-import org.springframework.beans.factory.annotation.Autowired;
-import ru.yandex.practicum.filmorate.exception.NotFoundException;
+import ru.yandex.practicum.filmorate.model.Buffer;
import ru.yandex.practicum.filmorate.model.Film;
-import ru.yandex.practicum.filmorate.service.FilmService;
+import ru.yandex.practicum.filmorate.model.FilmResponse;
+import ru.yandex.practicum.filmorate.service.FilmInterface;
+import ru.yandex.practicum.filmorate.storage.film.FilmStorage;
+import ru.yandex.practicum.filmorate.storage.user.UserStorage;
-import java.util.Collection;
-import java.util.Map;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.util.*;
@RestController
@RequestMapping("/films")
public class FilmController {
- private final FilmService filmService;
+ private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+ private static final String DEFAULT_GENRE = "нет жанра";
+
+ private final FilmStorage filmStorage;
+ private final UserStorage userStorage;
+ private final FilmInterface filmInterface;
@Autowired
- public FilmController(FilmService filmService) {
- this.filmService = filmService;
+ public FilmController(
+ FilmStorage filmStorage,
+ UserStorage userStorage,
+ FilmInterface filmInterface
+ ) {
+ this.filmStorage = filmStorage;
+ this.userStorage = userStorage;
+ this.filmInterface = filmInterface;
}
- //создание фильма
- @PostMapping
- public Film createFilm(@Valid @RequestBody Film film) {
- return filmService.createFilm(film);
+ @GetMapping
+ public List findAll() {
+ return filmStorage.findAll();
}
- //обновление фильма
- @PutMapping
- public Film update(@Valid @RequestBody Film film) {
- return filmService.update(film);
+ @GetMapping("/{id}")
+ public FilmResponse findById(@PathVariable("id") Long id) {
+ return filmStorage.findById(id);
}
- //получение всех фильмов
- @GetMapping
- public Collection getFilms() {
- return filmService.getFilms();
+ @PostMapping
+ @ResponseStatus(HttpStatus.CREATED)
+ public FilmResponse create(@Valid @RequestBody ObjectNode objectNode) {
+ Buffer buffer = parseObjectNodeToBuffer(objectNode);
+ return filmStorage.create(buffer);
}
- //получение фильма по ID
- @GetMapping("/{id}")
- public Film getFilmById(@PathVariable Long id) {
- return filmService.getFilmById(id);
+ @PutMapping
+ public FilmResponse update(@Valid @RequestBody ObjectNode objectNode) {
+ Buffer buffer = parseObjectNodeToBuffer(objectNode);
+ return filmStorage.update(buffer);
}
@PutMapping("/{id}/like/{userId}")
- public ResponseEntity> addLike(@PathVariable Long id, @PathVariable Long userId) {
- try {
- filmService.addLike(id, userId);
- return ResponseEntity.ok().build(); // Возвращаем 200 OK, если лайк добавлен
- } catch (NotFoundException e) {
- return ResponseEntity.status(HttpStatus.NOT_FOUND)
- .body(Map.of("error", e.getMessage())); // Возвращаем 404 и JSON с ошибкой
- }
+ public FilmResponse addLike(@Valid @PathVariable("id") Long id, @PathVariable("userId") Long userId) {
+ return filmInterface.addLike(userId, id);
}
- //удаление лайка из фильма
@DeleteMapping("/{id}/like/{userId}")
- public ResponseEntity removeLike(@PathVariable Long id, @PathVariable Long userId) {
- filmService.removeLike(id, userId);
- return ResponseEntity.ok().build();
+ public FilmResponse delLike(@Valid @PathVariable("id") Long id, @PathVariable("userId") Long userId) {
+ return filmInterface.delLike(userId, id);
}
- //получение популярных фильмов
@GetMapping("/popular")
- public Collection getTopFilms(@RequestParam(defaultValue = "10") int count) {
- return filmService.getTopFilms(count);
+ public LinkedHashSet viewRating(@RequestParam(defaultValue = "10") Long count) {
+ return filmInterface.viewRating(count);
+ }
+
+ /**
+ * преобразует json объект в объект Buffer
+ *
+ * @param objectNode json объект
+ * @return объект Buffer
+ */
+ private Buffer parseObjectNodeToBuffer(ObjectNode objectNode) {
+ Long id = objectNode.has("id") ? objectNode.get("id").asLong() : 0L;
+ String name = objectNode.get("name").asText();
+ String description = objectNode.get("description").asText();
+ String releaseDate = objectNode.get("releaseDate").asText();
+ Integer duration = objectNode.get("duration").asInt();
+ List mpa = objectNode.get("mpa").findValuesAsText("id");
+ List genres = extractGenresFromObjectNode(objectNode);
+
+ return Buffer.of(
+ id,
+ name,
+ description,
+ LocalDate.parse(releaseDate, DATE_FORMATTER),
+ duration,
+ genres,
+ Long.valueOf(mpa.get(0))
+ );
+ }
+
+ /**
+ * извлекает список жанров из json объекта
+ *
+ * @param objectNode json объект
+ * @return список жанров
+ */
+ private List extractGenresFromObjectNode(ObjectNode objectNode) {
+ try {
+ return objectNode.get("genres").findValuesAsText("id");
+ } catch (NullPointerException e) {
+ return List.of(DEFAULT_GENRE);
+ }
}
}
\ No newline at end of file
diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/GenreController.java b/src/main/java/ru/yandex/practicum/filmorate/controller/GenreController.java
new file mode 100644
index 0000000..5d1ed35
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/filmorate/controller/GenreController.java
@@ -0,0 +1,37 @@
+package ru.yandex.practicum.filmorate.controller;
+
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+import ru.yandex.practicum.filmorate.model.Genre;
+import ru.yandex.practicum.filmorate.service.GenreService;
+
+import java.util.List;
+
+@RestController
+@RequestMapping("/genres")
+@RequiredArgsConstructor
+public class GenreController {
+
+ private final GenreService genreService;
+
+ /**
+ * получить жанр по его идентификатору
+ *
+ * @param id идентификатор жанра
+ * @return объект жанра
+ */
+ @GetMapping("/{id}")
+ public Genre getGenreById(@PathVariable Long id) {
+ return genreService.getGenreById(id);
+ }
+
+ /**
+ * получить список всех жанров
+ *
+ * @return список всех жанров
+ */
+ @GetMapping
+ public List getAllGenres() {
+ return genreService.getAllGenres();
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/MpaController.java b/src/main/java/ru/yandex/practicum/filmorate/controller/MpaController.java
new file mode 100644
index 0000000..6561c16
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/filmorate/controller/MpaController.java
@@ -0,0 +1,37 @@
+package ru.yandex.practicum.filmorate.controller;
+
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+import ru.yandex.practicum.filmorate.model.Mpa;
+import ru.yandex.practicum.filmorate.service.MpaService;
+
+import java.util.List;
+
+@RestController
+@RequestMapping("/mpa")
+@RequiredArgsConstructor
+public class MpaController {
+
+ private final MpaService mpaService;
+
+ /**
+ * получить рейтинг mpa по его идентификатору
+ *
+ * @param id идентификатор рейтинга mpa
+ * @return объект рейтинга mpa
+ */
+ @GetMapping("/{id}")
+ public Mpa getMpaById(@PathVariable Long id) {
+ return mpaService.getMpaById(id);
+ }
+
+ /**
+ * получить список всех рейтингов mpa
+ *
+ * @return список всех рейтингов mpa
+ */
+ @GetMapping
+ public List getAllMpa() {
+ return mpaService.getAllMpa();
+ }
+}
\ No newline at end of file
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 7cdbea6..707d71a 100644
--- a/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java
+++ b/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java
@@ -1,68 +1,117 @@
package ru.yandex.practicum.filmorate.controller;
import jakarta.validation.Valid;
-import org.springframework.beans.factory.annotation.Autowired;
+import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
-import ru.yandex.practicum.filmorate.exception.DuplicatedDataException;
-import ru.yandex.practicum.filmorate.exception.NotFoundException;
-import ru.yandex.practicum.filmorate.exception.ValidationException;
import ru.yandex.practicum.filmorate.model.User;
-import ru.yandex.practicum.filmorate.service.UserService;
+import ru.yandex.practicum.filmorate.service.UserInterface;
+import ru.yandex.practicum.filmorate.storage.user.UserStorage;
import java.util.Collection;
+import java.util.Set;
@RestController
@RequestMapping("/users")
+@RequiredArgsConstructor
public class UserController {
- private final UserService userService;
+ private static final String USER_ID_PATH = "/{id}";
+ private static final String FRIENDS_PATH = USER_ID_PATH + "/friends";
+ private static final String FRIEND_ID_PATH = FRIENDS_PATH + "/{friendId}";
+ private static final String COMMON_FRIENDS_PATH = USER_ID_PATH + "/friends/common/{otherId}";
- @Autowired
- public UserController(UserService userService) {
- this.userService = userService;
- }
+ private final UserStorage userStorage;
+ private final UserInterface userInterface;
+ /**
+ * получить список всех пользователей
+ *
+ * @return список всех пользователей
+ */
@GetMapping
public Collection findAll() {
- return userService.findAll();
+ return userStorage.findAll();
+ }
+
+ /**
+ * получить пользователя по его ид
+ *
+ * @param id идентификатор пользователя
+ * @return объект пользователя
+ */
+ @GetMapping(USER_ID_PATH)
+ public User findById(@PathVariable("id") Long id) {
+ return userStorage.findById(id);
}
+ /**
+ * создать нового пользователя
+ *
+ * @param user объект пользователя
+ * @return созданный пользователь
+ */
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
- public User create(@Valid @RequestBody User user) throws ValidationException, DuplicatedDataException {
- return userService.create(user);
+ public User create(@Valid @RequestBody User user) {
+ return userStorage.create(user);
}
+ /**
+ * обновить данные пользователя
+ *
+ * @param newUser объект пользователя с новыми данными
+ * @return обновленный пользователь
+ */
@PutMapping
- public User update(@Valid @RequestBody User user) throws NotFoundException, ValidationException {
- return userService.update(user);
- }
-
- @GetMapping("/{id}")
- public User getUserById(@PathVariable Long id) throws NotFoundException, ValidationException {
- return userService.findById(id);
+ public User update(@Valid @RequestBody User newUser) {
+ return userStorage.update(newUser);
}
- @PutMapping("/{id}/friends/{friendId}")
- @ResponseStatus(HttpStatus.NO_CONTENT)
- public void addFriend(@PathVariable Long id, @PathVariable Long friendId) throws NotFoundException {
- userService.addFriend(id, friendId);
+ /**
+ * добавить друга пользователю
+ *
+ * @param id идентификатор пользователя
+ * @param friendId идентификатор друга
+ * @return пользователь с обновленным списком друзей
+ */
+ @PutMapping(FRIEND_ID_PATH)
+ public User addFriend(@Valid @PathVariable("id") Long id, @PathVariable("friendId") Long friendId) {
+ return userInterface.addFriend(id, friendId);
}
- @DeleteMapping("/{id}/friends/{friendId}")
- @ResponseStatus(HttpStatus.NO_CONTENT)
- public void removeFriend(@PathVariable Long id, @PathVariable Long friendId) throws NotFoundException {
- userService.removeFriend(id, friendId);
+ /**
+ * удалить друга у пользователя
+ *
+ * @param id идентификатор пользователя
+ * @param friendId идентификатор друга
+ * @return пользователь с обновленным списком друзей
+ */
+ @DeleteMapping(FRIEND_ID_PATH)
+ public User delFriend(@Valid @PathVariable("id") Long id, @PathVariable("friendId") Long friendId) {
+ return userInterface.delFriend(id, friendId);
}
- @GetMapping("/{id}/friends")
- public Collection getFriends(@PathVariable Long id) throws NotFoundException {
- return userService.getFriends(id);
+ /**
+ * получить список общих друзей двух пользователей
+ *
+ * @param id идентификатор первого пользователя
+ * @param otherId идентификатор второго пользователя
+ * @return список общих друзей
+ */
+ @GetMapping(COMMON_FRIENDS_PATH)
+ public Set findJointFriends(@Valid @PathVariable("id") Long id, @PathVariable("otherId") Long otherId) {
+ return userInterface.findJointFriends(id, otherId);
}
- @GetMapping("/{id}/friends/common/{otherId}")
- public Collection getCommonFriends(@PathVariable Long id, @PathVariable Long otherId) throws NotFoundException {
- return userService.getCommonFriends(id, otherId);
+ /**
+ * получить список друзей пользователя
+ *
+ * @param id идентификатор пользователя
+ * @return список друзей
+ */
+ @GetMapping(FRIENDS_PATH)
+ public Set findAllFriends(@Valid @PathVariable("id") Long id) {
+ return userInterface.findAllFriends(id);
}
}
\ No newline at end of file
diff --git a/src/main/java/ru/yandex/practicum/filmorate/exception/ConditionsNotMetException.java b/src/main/java/ru/yandex/practicum/filmorate/exception/ConditionsNotMetException.java
new file mode 100644
index 0000000..d84fada
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/filmorate/exception/ConditionsNotMetException.java
@@ -0,0 +1,9 @@
+package ru.yandex.practicum.filmorate.exception;
+
+import java.util.Objects;
+
+public class ConditionsNotMetException extends RuntimeException {
+ public ConditionsNotMetException(String message) {
+ super(Objects.requireNonNull(message, "Сообщение об ошибке не может быть null"));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/ru/yandex/practicum/filmorate/exception/ErrorHandler.java b/src/main/java/ru/yandex/practicum/filmorate/exception/ErrorHandler.java
index e03903a..8afe7ff 100644
--- a/src/main/java/ru/yandex/practicum/filmorate/exception/ErrorHandler.java
+++ b/src/main/java/ru/yandex/practicum/filmorate/exception/ErrorHandler.java
@@ -46,4 +46,10 @@ public ResponseEntity