diff --git a/pom.xml b/pom.xml
index 8439ff4..7cd7b4c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -43,6 +43,12 @@
org.slf4j
slf4j-api
+
+
+ org.zalando
+ logbook-spring-boot-starter
+ 3.7.2
+
diff --git a/src/main/java/ru/yandex/practicum/filmorate/FilmorateApplication.java b/src/main/java/ru/yandex/practicum/filmorate/FilmorateApplication.java
index e55e710..8f860a2 100644
--- a/src/main/java/ru/yandex/practicum/filmorate/FilmorateApplication.java
+++ b/src/main/java/ru/yandex/practicum/filmorate/FilmorateApplication.java
@@ -8,4 +8,4 @@ public class FilmorateApplication {
public static void main(String[] args) {
SpringApplication.run(FilmorateApplication.class, args);
}
-}
+}
\ No newline at end of file
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..aaf6f71
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/filmorate/controller/ErrorHandler.java
@@ -0,0 +1,31 @@
+package ru.yandex.practicum.filmorate.controller;
+
+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 ru.yandex.practicum.filmorate.exception.NotFoundException;
+import ru.yandex.practicum.filmorate.exception.ValidationException;
+import ru.yandex.practicum.filmorate.model.ErrorResponse;
+
+@RestControllerAdvice
+public class ErrorHandler {
+
+ @ExceptionHandler
+ @ResponseStatus(HttpStatus.BAD_REQUEST)
+ public ErrorResponse handleValidationException(final ValidationException e) {
+ return new ErrorResponse(e.getMessage());
+ }
+
+ @ExceptionHandler
+ @ResponseStatus(HttpStatus.NOT_FOUND)
+ public ErrorResponse handleNotFoundException(final NotFoundException e) {
+ return new ErrorResponse(e.getMessage());
+ }
+
+ @ExceptionHandler
+ @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
+ public ErrorResponse handleAllOtherExceptions(Throwable e) {
+ return new ErrorResponse(e.getMessage());
+ }
+}
\ No newline at end of file
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 4116f66..6f50e3c 100644
--- a/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java
+++ b/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java
@@ -1,85 +1,67 @@
package ru.yandex.practicum.filmorate.controller;
-import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import ru.yandex.practicum.filmorate.model.Film;
-import jakarta.validation.ValidationException;
+import ru.yandex.practicum.filmorate.service.FilmService;
+import ru.yandex.practicum.filmorate.storage.FilmStorage;
-import java.time.LocalDate;
import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
@Slf4j
@RestController
@RequestMapping("/films")
public class FilmController {
- private final Map films = new HashMap<>();
+ private final FilmStorage inMemoryFilmStorage;
+ private final FilmService filmService;
+
+ @Autowired
+ public FilmController(FilmStorage inMemoryFilmStorage, FilmService filmService) {
+ this.inMemoryFilmStorage = inMemoryFilmStorage;
+ this.filmService = filmService;
+ }
@GetMapping
public Collection findAll() {
log.info("Список фильмов выведен");
- return films.values();
+ return inMemoryFilmStorage.findAll();
+ }
+
+ @GetMapping("/{id}")
+ public Film findById(@PathVariable("id") int filmId) {
+ log.info("Фильм с id: {} выведен", filmId);
+ return inMemoryFilmStorage.findFilmById(filmId);
}
- private int getNextId() {
- int currentMaxId = films.keySet()
- .stream()
- .mapToInt(id -> id)
- .max()
- .orElse(0);
- return ++currentMaxId;
+ @GetMapping("/popular")
+ public Collection getPopular(@RequestParam(defaultValue = "10") int count) {
+ log.info("Список популярных фильмов выведен");
+ return filmService.getPopular(count);
}
@PostMapping
- public Film create(@Valid @RequestBody Film film) {
- validateFilm(film);
- film.setId(getNextId());
- films.put(film.getId(), film);
+ public Film create(@RequestBody Film film) {
log.info("Фильм: {} добавлен в базу", film);
- return film;
+ return inMemoryFilmStorage.create(film);
}
@PutMapping
- public Film update(@Valid @RequestBody Film newFilm) {
- if (newFilm.getId() == null) {
- log.warn("Не указан id");
- throw new ValidationException("Id должен быть указан");
- }
- if (!films.containsKey(newFilm.getId())) {
- log.warn("Фильм с указанным id не найден");
- throw new ValidationException("Фильм с id = " + newFilm.getId() + " не найден");
- }
- validateFilm(newFilm);
- Film oldFilm = films.get(newFilm.getId());
- oldFilm.setDescription(newFilm.getDescription());
- oldFilm.setDuration(newFilm.getDuration());
- oldFilm.setName(newFilm.getName());
- oldFilm.setReleaseDate(newFilm.getReleaseDate());
- log.info("Данные о фильме: {} обновлены", oldFilm);
- return oldFilm;
+ public Film update(@RequestBody Film newFilm) {
+ log.info("Данные о фильме: {} обновлены", newFilm);
+ return inMemoryFilmStorage.update(newFilm);
}
- private void validateFilm(Film film) {
- if (film.getDescription().length() > 200) {
- log.warn("Ошибка лимита");
- throw new ValidationException("Описание превышает 200 символов");
- }
- if (film.getReleaseDate().isBefore(LocalDate.of(1895, 12, 28))) {
- log.warn("Ошибка даты");
- throw new ValidationException("Неверная дата релиза");
- }
-
- if (film.getName() == null || film.getName().isBlank()) {
- log.warn("Пустое название фильма");
- throw new ValidationException("Название не может быть пустым");
- }
+ @PutMapping("/{id}/like/{userId}")
+ public void addLike(@PathVariable int id, @PathVariable int userId) {
+ log.info("Фильму с id: {} поставил лайк пользователь с id: {}", id, userId);
+ filmService.addLike(id, userId);
+ }
- if (film.getDuration() < 1) {
- log.warn("Ошибка длительности");
- throw new ValidationException("Длительность не может быть меньше 1");
- }
+ @DeleteMapping("/{id}/like/{userId}")
+ public void deleteLike(@PathVariable int id, @PathVariable int userId) {
+ log.info("У фильма с id: {} убрал лайк пользователь с id: {}", id, userId);
+ filmService.deleteLike(id, userId);
}
}
\ 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 915a2df..c134492 100644
--- a/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java
+++ b/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java
@@ -2,81 +2,70 @@
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
-import ru.yandex.practicum.filmorate.exception.ValidationException;
import ru.yandex.practicum.filmorate.model.User;
+import ru.yandex.practicum.filmorate.service.UserService;
+import ru.yandex.practicum.filmorate.storage.InMemoryUserStorage;
-import java.time.LocalDate;
import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
@Slf4j
@RestController
@RequestMapping("/users")
public class UserController {
- private final Map users = new HashMap<>();
+ private final InMemoryUserStorage inMemoryUserStorage;
+ private final UserService userService;
+
+ public UserController(InMemoryUserStorage inMemoryUserStorage, UserService userService) {
+ this.inMemoryUserStorage = inMemoryUserStorage;
+ this.userService = userService;
+ }
@GetMapping
public Collection findAll() {
- log.info("Список фильмов выведен");
- return users.values();
+ log.info("Список пользователей выведен");
+ return inMemoryUserStorage.findAll();
+ }
+
+ @GetMapping("/{id}")
+ public User findUserById(@PathVariable("id") int userId) {
+ log.info("Пользователь с id: {} выведен", userId);
+ return inMemoryUserStorage.findUserById(userId);
}
- private int getNextId() {
- int currentMaxId = users.keySet()
- .stream()
- .mapToInt(id -> id)
- .max()
- .orElse(0);
- return ++currentMaxId;
+ @GetMapping("/{id}/friends")
+ public Collection findAllFriends(@PathVariable("id") int userId) {
+ log.info("Список друзей пользователя с id: {} выведен", userId);
+ return userService.getFriendList(userId);
+ }
+
+ @GetMapping("/{id}/friends/common/{otherId}")
+ public Collection findAllCommonFriends(@PathVariable int id, @PathVariable int otherId) {
+ log.info("Список общих друзей пользователей с id: {} и {} выведен", id, otherId);
+ return userService.getCommonFriendList(id, otherId);
}
@PostMapping
public User create(@RequestBody User user) {
- validateUser(user);
- user.setId(getNextId());
- users.put(user.getId(), user);
- log.info("Пользователь: {} добавлен в базу", user);
- return user;
+ log.info("Пользоввтель: {} создан и добавлен", user);
+ return inMemoryUserStorage.create(user);
}
@PutMapping
public User update(@RequestBody User newUser) {
- if (newUser.getId() == null) {
- log.warn("Не указан id");
- throw new ValidationException("Id должен быть указан");
- }
- if (!users.containsKey(newUser.getId())) {
- log.warn("Пользователь с указанным id не найден");
- throw new ValidationException("Пользователь с id = " + newUser.getId() + " не найден");
- }
- validateUser(newUser);
- User oldUser = users.get(newUser.getId());
- oldUser.setEmail(newUser.getEmail());
- oldUser.setName(newUser.getName());
- oldUser.setLogin(newUser.getLogin());
- oldUser.setBirthday(newUser.getBirthday());
- log.info("Данные о пользователе: {} обновлены", oldUser);
- return oldUser;
+ log.info("Данные о пользователе: {} обновлены", newUser);
+ return inMemoryUserStorage.update(newUser);
+ }
+
+ @PutMapping("/{id}/friends/{friendId}")
+ public void addFriend(@PathVariable("id") int userId, @PathVariable int friendId) {
+ log.info("Пользователь с id: {} добавил пользователя с id: {} в друзья", userId, friendId);
+ userService.addFriend(userId, friendId);
}
- private void validateUser(User user) {
- if (!user.getEmail().contains("@")) {
- log.warn("Ошибка в формате почты");
- throw new ValidationException("Неверная почта");
- }
- if (user.getBirthday().isAfter(LocalDate.now())) {
- log.warn("Ошибка в дате рождения");
- throw new ValidationException("Неверная дата рождения");
- }
- if (user.getLogin().contains(" ")) {
- log.warn("Ошибка в формате логина");
- throw new ValidationException("Неправильный формат логина");
- }
- if (user.getName() == null || user.getName().trim().isEmpty()) {
- log.info("Пустое имя пользователя заменено на логин");
- user.setName(user.getLogin());
- }
+ @DeleteMapping("/{id}/friends/{friendId}")
+ public void deleteFriend(@PathVariable("id") int userId, @PathVariable int friendId) {
+ log.info("Пользователь с id: {} удалил пользователя с id: {} из друзей", userId, friendId);
+ userService.deleteFriend(userId, friendId);
}
}
\ No newline at end of file
diff --git a/src/main/java/ru/yandex/practicum/filmorate/exception/NotFoundException.java b/src/main/java/ru/yandex/practicum/filmorate/exception/NotFoundException.java
new file mode 100644
index 0000000..82e3f72
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/filmorate/exception/NotFoundException.java
@@ -0,0 +1,7 @@
+package ru.yandex.practicum.filmorate.exception;
+
+public class NotFoundException extends RuntimeException {
+ public NotFoundException(String message) {
+ super(message);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/ru/yandex/practicum/filmorate/exception/ValidationException.java b/src/main/java/ru/yandex/practicum/filmorate/exception/ValidationException.java
index 52dc49c..532f9bd 100644
--- a/src/main/java/ru/yandex/practicum/filmorate/exception/ValidationException.java
+++ b/src/main/java/ru/yandex/practicum/filmorate/exception/ValidationException.java
@@ -4,4 +4,4 @@ public class ValidationException extends RuntimeException {
public ValidationException(String message) {
super(message);
}
-}
+}
\ No newline at end of file
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..6a9e1f5
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/filmorate/model/ErrorResponse.java
@@ -0,0 +1,13 @@
+package ru.yandex.practicum.filmorate.model;
+
+public class ErrorResponse {
+ String error;
+
+ public ErrorResponse(String error) {
+ this.error = error;
+ }
+
+ public String getError() {
+ return error;
+ }
+}
\ 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 b9e156e..6fbe6f5 100644
--- a/src/main/java/ru/yandex/practicum/filmorate/model/Film.java
+++ b/src/main/java/ru/yandex/practicum/filmorate/model/Film.java
@@ -1,11 +1,10 @@
package ru.yandex.practicum.filmorate.model;
-import jakarta.validation.constraints.Min;
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.time.LocalDate;
+import java.util.HashSet;
+import java.util.Set;
/**
* Film.
@@ -13,11 +12,13 @@
@Data
public class Film {
private Integer id;
- @NotBlank
private String name;
private String description;
- @NotNull
private LocalDate releaseDate;
- @Min(1)
private int duration;
-}
+ private Set likes = new HashSet<>();
+
+ public int getRating() {
+ return likes.size();
+ }
+}
\ 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 0060c62..e06c2d7 100644
--- a/src/main/java/ru/yandex/practicum/filmorate/model/User.java
+++ b/src/main/java/ru/yandex/practicum/filmorate/model/User.java
@@ -3,6 +3,8 @@
import lombok.Data;
import java.time.LocalDate;
+import java.util.HashSet;
+import java.util.Set;
@Data
public class User {
@@ -11,4 +13,5 @@ public class User {
private String login;
private String name;
private LocalDate birthday;
+ private Set friends = 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
new file mode 100644
index 0000000..4ea7853
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java
@@ -0,0 +1,58 @@
+package ru.yandex.practicum.filmorate.service;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Service;
+import ru.yandex.practicum.filmorate.exception.ValidationException;
+import ru.yandex.practicum.filmorate.model.Film;
+import ru.yandex.practicum.filmorate.storage.FilmStorage;
+import ru.yandex.practicum.filmorate.storage.UserStorage;
+
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.stream.Collectors;
+
+@Slf4j
+@Service
+public class FilmService {
+
+ private final FilmStorage filmStorage;
+ private final UserStorage userStorage;
+
+ @Autowired
+ public FilmService(@Qualifier("inMemoryFilmStorage") FilmStorage filmStorage,
+ @Qualifier("inMemoryUserStorage") UserStorage userStorage) {
+ this.filmStorage = filmStorage;
+ this.userStorage = userStorage;
+ }
+
+ public void addLike(int id, int userId) {
+ Film film = filmStorage.findFilmById(id);
+ userStorage.findUserById(userId);
+ if (film.getLikes().contains(userId)) {
+ log.warn("Ошибка добавления лайка");
+ throw new ValidationException("Лайк от этого пользователя уже стоит");
+ }
+ film.getLikes().add(userId);
+ }
+
+ public void deleteLike(int id, int userId) {
+ Film film = filmStorage.findFilmById(id);
+ userStorage.findUserById(userId);
+ if (!film.getLikes().contains(userId)) {
+ log.warn("Ошибка удаления лайка");
+ throw new ValidationException("У фильма нет лайка от этого пользователя");
+ }
+ film.getLikes().remove(userId);
+ }
+
+ public Collection getPopular(int count) {
+ return filmStorage.findAll().stream()
+ .sorted(comparator)
+ .limit(count)
+ .collect(Collectors.toList());
+ }
+
+ public static final Comparator comparator = Comparator.comparingInt(Film::getRating).reversed();
+}
\ 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..e03525e
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java
@@ -0,0 +1,70 @@
+package ru.yandex.practicum.filmorate.service;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Service;
+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;
+
+@Slf4j
+@Service
+public class UserService {
+
+ private final UserStorage userStorage;
+
+ public UserService(@Qualifier("inMemoryUserStorage") UserStorage userStorage) {
+ this.userStorage = userStorage;
+ }
+
+ public void addFriend(int userId, int friendId) {
+ if (userId == friendId) {
+ log.warn("Ошибка добавления в друзья");
+ throw new ValidationException("Пользователь не может добавить сам себя в друзья");
+ }
+ User user = userStorage.findUserById(userId);
+ User usersFriend = userStorage.findUserById(friendId);
+ if (user.getFriends().contains(friendId)) {
+ log.warn("Ошибка добавления в друзья");
+ throw new ValidationException("Пользователь уже добавлен в друзья");
+ }
+ user.getFriends().add(friendId);
+ usersFriend.getFriends().add(userId);
+ }
+
+ public void deleteFriend(int userId, int friendId) {
+ if (userId == friendId) {
+ log.warn("Ошибка удаления из друзей");
+ throw new ValidationException("Пользователь не может удалить сам себя");
+ }
+ User user = userStorage.findUserById(userId);
+ User usersFriend = userStorage.findUserById(friendId);
+ user.getFriends().remove(friendId);
+ usersFriend.getFriends().remove(userId);
+ }
+
+ public Collection getFriendList(int userId) {
+ User user = userStorage.findUserById(userId);
+ List list = new ArrayList<>();
+ for (Integer id : user.getFriends()) {
+ list.add(userStorage.findUserById(id));
+ }
+ return list;
+ }
+
+ public Collection getCommonFriendList(int id, int otherId) {
+ User user1 = userStorage.findUserById(id);
+ User user2 = userStorage.findUserById(otherId);
+ List list = new ArrayList<>();
+ for (Integer userid : user1.getFriends()) {
+ if (user2.getFriends().contains(userid)) {
+ list.add(userStorage.findUserById(userid));
+ }
+ }
+ return list;
+ }
+}
\ 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..0b380f8
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/filmorate/storage/FilmStorage.java
@@ -0,0 +1,16 @@
+package ru.yandex.practicum.filmorate.storage;
+
+import ru.yandex.practicum.filmorate.model.Film;
+
+import java.util.Collection;
+
+public interface FilmStorage {
+
+ Collection findAll();
+
+ Film create(Film film);
+
+ Film update(Film newFilm);
+
+ Film findFilmById(int id);
+}
\ 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..b6b340a
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryFilmStorage.java
@@ -0,0 +1,87 @@
+package ru.yandex.practicum.filmorate.storage;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+import ru.yandex.practicum.filmorate.exception.ValidationException;
+import ru.yandex.practicum.filmorate.exception.NotFoundException;
+import ru.yandex.practicum.filmorate.model.Film;
+
+import java.time.LocalDate;
+import java.util.*;
+
+@Slf4j
+@Component("inMemoryFilmStorage")
+public class InMemoryFilmStorage implements FilmStorage {
+
+ private final Map films = new HashMap<>();
+
+ @Override
+ public Collection findAll() {
+ return films.values();
+ }
+
+ @Override
+ public Film create(Film film) {
+ validateFilm(film);
+ film.setId(getNextId());
+ films.put(film.getId(), film);
+ return film;
+ }
+
+ @Override
+ public Film update(Film newFilm) {
+ if (newFilm.getId() == null) {
+ log.warn("Не указан id");
+ throw new ValidationException("Id должен быть указан");
+ }
+ if (!films.containsKey(newFilm.getId())) {
+ log.warn("Фильм с указанным id не найден");
+ throw new NotFoundException("Фильм с id = " + newFilm.getId() + " не найден");
+ }
+ validateFilm(newFilm);
+ Film oldFilm = films.get(newFilm.getId());
+ oldFilm.setDescription(newFilm.getDescription());
+ oldFilm.setDuration(newFilm.getDuration());
+ oldFilm.setName(newFilm.getName());
+ oldFilm.setReleaseDate(newFilm.getReleaseDate());
+ return oldFilm;
+ }
+
+ @Override
+ public Film findFilmById(int id) {
+ if (!films.containsKey(id)) {
+ throw new NotFoundException("Фильма с таким id не найдено");
+ }
+ return films.get(id);
+ }
+
+ private int getNextId() {
+ int currentMaxId = films.keySet()
+ .stream()
+ .mapToInt(id -> id)
+ .max()
+ .orElse(0);
+ return ++currentMaxId;
+ }
+
+ private void validateFilm(Film film) {
+ if (film.getDescription() != null && film.getDescription().length() > 200) {
+ log.warn("Ошибка лимита");
+ throw new ValidationException("Описание превышает 200 символов");
+ }
+ if (film.getReleaseDate().isBefore(LocalDate.of(1895, 12, 28))) {
+ log.warn("Ошибка даты");
+ throw new ValidationException("Неверная дата релиза");
+ }
+
+ if (film.getName() == null || film.getName().isBlank()) {
+ log.warn("Пустое название фильма");
+ throw new ValidationException("Название не может быть пустым");
+ }
+
+ if (film.getDuration() < 1) {
+ log.warn("Ошибка длительности");
+ throw new ValidationException("Длительность не может быть меньше 1");
+ }
+ }
+}
\ 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..d9468af
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorage.java
@@ -0,0 +1,87 @@
+package ru.yandex.practicum.filmorate.storage;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+import ru.yandex.practicum.filmorate.exception.NotFoundException;
+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.HashMap;
+import java.util.Map;
+
+@Slf4j
+@Component("inMemoryUserStorage")
+public class InMemoryUserStorage implements UserStorage {
+
+ private final Map users = new HashMap<>();
+
+ @Override
+ public Collection findAll() {
+ return users.values();
+ }
+
+ @Override
+ public User create(User user) {
+ validateUser(user);
+ user.setId(getNextId());
+ users.put(user.getId(), user);
+ return user;
+ }
+
+ @Override
+ public User update(User newUser) {
+ if (newUser.getId() == null) {
+ log.warn("Не указан id");
+ throw new ValidationException("Id должен быть указан");
+ }
+ if (!users.containsKey(newUser.getId())) {
+ log.warn("Пользователь с указанным id не найден");
+ throw new NotFoundException("Пользователь с id = " + newUser.getId() + " не найден");
+ }
+ validateUser(newUser);
+ User oldUser = users.get(newUser.getId());
+ oldUser.setEmail(newUser.getEmail());
+ oldUser.setName(newUser.getName());
+ oldUser.setLogin(newUser.getLogin());
+ oldUser.setBirthday(newUser.getBirthday());
+ return oldUser;
+ }
+
+ private int getNextId() {
+ int currentMaxId = users.keySet()
+ .stream()
+ .mapToInt(id -> id)
+ .max()
+ .orElse(0);
+ return ++currentMaxId;
+ }
+
+ public User findUserById(int userId) {
+ if (!users.containsKey(userId)) {
+ log.warn("Пользователь не найден");
+ throw new NotFoundException("Пользователя с таким id не найдено");
+ }
+ return users.get(userId);
+ }
+
+ private void validateUser(User user) {
+ if (!user.getEmail().contains("@")) {
+ log.warn("Ошибка в формате почты");
+ throw new ValidationException("Неверная почта");
+ }
+ if (user.getBirthday().isAfter(LocalDate.now())) {
+ log.warn("Ошибка в дате рождения");
+ throw new ValidationException("Неверная дата рождения");
+ }
+ if (user.getLogin().contains(" ")) {
+ log.warn("Ошибка в формате логина");
+ throw new ValidationException("Неправильный формат логина");
+ }
+ if (user.getName() == null || user.getName().trim().isEmpty()) {
+ log.info("Пустое имя пользователя заменено на логин");
+ user.setName(user.getLogin());
+ }
+ }
+}
\ 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..04935d0
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/filmorate/storage/UserStorage.java
@@ -0,0 +1,16 @@
+package ru.yandex.practicum.filmorate.storage;
+
+import ru.yandex.practicum.filmorate.model.User;
+
+import java.util.Collection;
+
+public interface UserStorage {
+
+ Collection findAll();
+
+ User create(User user);
+
+ User update(User newUser);
+
+ User findUserById(int id);
+}
\ No newline at end of file
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index 4c00e40..4a23bbc 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -1 +1,2 @@
server.port=8080
+logging.level.org.zalando.logbook=TRACE
\ No newline at end of file
diff --git a/src/test/java/ru/yandex/practicum/filmorate/controller/FilmControllerTest.java b/src/test/java/ru/yandex/practicum/filmorate/controller/InMemoryFilmStorageTest.java
similarity index 54%
rename from src/test/java/ru/yandex/practicum/filmorate/controller/FilmControllerTest.java
rename to src/test/java/ru/yandex/practicum/filmorate/controller/InMemoryFilmStorageTest.java
index 7bb1ead..875d090 100644
--- a/src/test/java/ru/yandex/practicum/filmorate/controller/FilmControllerTest.java
+++ b/src/test/java/ru/yandex/practicum/filmorate/controller/InMemoryFilmStorageTest.java
@@ -1,15 +1,16 @@
package ru.yandex.practicum.filmorate.controller;
-import jakarta.validation.ValidationException;
import org.junit.jupiter.api.Test;
+import ru.yandex.practicum.filmorate.exception.ValidationException;
import ru.yandex.practicum.filmorate.model.Film;
+import ru.yandex.practicum.filmorate.storage.InMemoryFilmStorage;
+
import static org.junit.jupiter.api.Assertions.*;
import java.time.LocalDate;
-public class FilmControllerTest {
-
- FilmController filmController = new FilmController();
+public class InMemoryFilmStorageTest {
+ InMemoryFilmStorage inMemoryFilmStorage = new InMemoryFilmStorage();
@Test
void getFilmTest() {
@@ -18,18 +19,18 @@ void getFilmTest() {
film.setDuration(100);
film.setName("test");
film.setDescription("t");
- filmController.create(film);
+ inMemoryFilmStorage.create(film);
film.setName(" ");
- assertThrows(ValidationException.class, () -> filmController.update(film));
+ assertThrows(ValidationException.class, () -> inMemoryFilmStorage.update(film));
film.setName("test");
String description200 = "A".repeat(200);
film.setDescription(film.getDescription() + description200);
- assertThrows(ValidationException.class, () -> filmController.update(film));
+ assertThrows(ValidationException.class, () -> inMemoryFilmStorage.update(film));
film.setDescription("t");
film.setReleaseDate(LocalDate.of(1895, 12, 27));
- assertThrows(ValidationException.class, () -> filmController.update(film));
+ assertThrows(ValidationException.class, () -> inMemoryFilmStorage.update(film));
film.setReleaseDate(LocalDate.now());
film.setDuration(0);
- assertThrows(ValidationException.class, () -> filmController.update(film));
+ assertThrows(ValidationException.class, () -> inMemoryFilmStorage.update(film));
}
}
\ No newline at end of file
diff --git a/src/test/java/ru/yandex/practicum/filmorate/controller/UserControllerTest.java b/src/test/java/ru/yandex/practicum/filmorate/controller/InMemoryUserStorageTest.java
similarity index 62%
rename from src/test/java/ru/yandex/practicum/filmorate/controller/UserControllerTest.java
rename to src/test/java/ru/yandex/practicum/filmorate/controller/InMemoryUserStorageTest.java
index f2af4a7..3174a9a 100644
--- a/src/test/java/ru/yandex/practicum/filmorate/controller/UserControllerTest.java
+++ b/src/test/java/ru/yandex/practicum/filmorate/controller/InMemoryUserStorageTest.java
@@ -3,14 +3,15 @@
import org.junit.jupiter.api.Test;
import ru.yandex.practicum.filmorate.exception.ValidationException;
import ru.yandex.practicum.filmorate.model.User;
+import ru.yandex.practicum.filmorate.storage.InMemoryUserStorage;
import java.time.LocalDate;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
-public class UserControllerTest {
- UserController userController = new UserController();
+public class InMemoryUserStorageTest {
+ InMemoryUserStorage inMemoryUserStorage = new InMemoryUserStorage();
@Test
void getFilmTest() {
@@ -19,17 +20,17 @@ void getFilmTest() {
user.setLogin("test2");
user.setBirthday(LocalDate.of(2000, 12, 27));
user.setEmail("test@");
- userController.create(user);
+ inMemoryUserStorage.create(user);
user.setEmail(" ");
- assertThrows(ValidationException.class, () -> userController.update(user));
+ assertThrows(ValidationException.class, () -> inMemoryUserStorage.update(user));
user.setEmail("test2@");
user.setLogin("TEST ETS");
- assertThrows(ValidationException.class, () -> userController.update(user));
+ assertThrows(ValidationException.class, () -> inMemoryUserStorage.update(user));
user.setLogin("test2");
user.setName(" ");
- userController.update(user);
+ inMemoryUserStorage.update(user);
assertEquals(user.getLogin(), user.getName(), "Имя совпадает с логином");
user.setBirthday(LocalDate.of(2200, 12, 27));
- assertThrows(ValidationException.class, () -> userController.update(user));
+ assertThrows(ValidationException.class, () -> inMemoryUserStorage.update(user));
}
}
\ No newline at end of file