diff --git a/HELP.md b/HELP.md
index 0ca1809..ac035f8 100644
--- a/HELP.md
+++ b/HELP.md
@@ -1,17 +1,12 @@
-# Read Me First
-The following was discovered as part of building this project:
-
-* The JVM level was changed from '11' to '17', review the [JDK Version Range](https://github.com/spring-projects/spring-framework/wiki/Spring-Framework-Versions#jdk-version-range) on the wiki for more details.
-
# Getting Started
### Reference Documentation
For further reference, please consider the following sections:
* [Official Apache Maven documentation](https://maven.apache.org/guides/index.html)
-* [Spring Boot Maven Plugin Reference Guide](https://docs.spring.io/spring-boot/docs/3.1.3/maven-plugin/reference/html/)
-* [Create an OCI image](https://docs.spring.io/spring-boot/docs/3.1.3/maven-plugin/reference/html/#build-image)
-* [Spring Web](https://docs.spring.io/spring-boot/docs/3.1.3/reference/htmlsingle/index.html#web)
+* [Spring Boot Maven Plugin Reference Guide](https://docs.spring.io/spring-boot/docs/2.7.13/maven-plugin/reference/html/)
+* [Create an OCI image](https://docs.spring.io/spring-boot/docs/2.7.13/maven-plugin/reference/html/#build-image)
+* [Spring Web](https://docs.spring.io/spring-boot/docs/2.7.13/reference/htmlsingle/#web)
### Guides
The following guides illustrate how to use some features concretely:
diff --git a/README.md b/README.md
index 2cf454a..43c373b 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,53 @@
# java-filmorate
Template repository for Filmorate project.
+
+
+
+В таблице User храняться все пльзователи приложения
+В таблице Friends храняться все дружественные связи со статусом их подтвреждения
+
+В таблице Film храняться все фильмы
+В талице MPA храняться все рейтинги фильмов, а в Film добавляется только индекс нужного рейтинга
+сделано так что бы убрать избыточность
+В таблице genre храняться все жанры и так как связь к фильма многие ко многим выделена таблица для связи genre_film
+В таблице likes храняться все id пользователе которым понравился фильма
+
+Запросы
+
+1.Для получения таблицы всей информации обо всех пользователях
+SLECT *
+FROM user;
+
+2.Для получения таблицы всех пользователей и их друзей
+SELECT u.name,
+f.isApproved,
+u2.name
+FROM user u
+JOIN friend f ON f.id_user1 = u.id;
+JOIN user u2 ON u2.id = f.id_user2
+
+2.Для получения таблицы конкретного пользователя и его друзей
+SELECT u.name,
+f.isApproved,
+u2.name
+FROM user u
+JOIN friend f ON f.id_user1 = u.id;
+JOIN user u2 ON u2.id = f.id_user2
+WHERE u.id = {id}
+
+3.Для полученя таблицы всех фильмов и информации о них
+SELECT *
+FROM film
+
+4.Для получения таблицы всех пользователе кому понравился конкретный фильма
+SELECT likes.id_user
+FROM film f
+JOIN likes_film likes ON likes.id_film = f.id
+WHERE f.id = {id}
+
+5.Для получения таблицы всех жанров конкретного фильма
+SELECT g.name
+FROM film f
+JOIN genre_film gf ON gf.id_film = film.id
+JOIN genre g ON g.id = gf.id_genre
+WHERE f.id = {id}
\ No newline at end of file
diff --git a/db_filmorate.jpg b/db_filmorate.jpg
new file mode 100644
index 0000000..2913656
Binary files /dev/null and b/db_filmorate.jpg differ
diff --git a/pom.xml b/pom.xml
index b576ebc..0da5ac4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,40 +5,58 @@
org.springframework.boot
spring-boot-starter-parent
- 2.7.15
+ 2.7.13
- ru.yandex.practicum.com.example
+ ru.yandex.practicum
filmorate
0.0.1-SNAPSHOT
+ jar
filmorate
Demo project for Spring Boot
11
+
+ org.projectlombok
+ lombok
+ 1.18.28
+ provided
+
+
org.springframework.boot
- spring-boot-starter-web
+ spring-boot-starter-data-jdbc
org.springframework.boot
- spring-boot-starter-test
- test
+ spring-boot-starter-data-jpa
+
- org.projectlombok
- lombok
- 1.18.20
- compile
+ com.h2database
+ h2
+ runtime
+
- junit
- junit
- test
-
-
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
diff --git a/src/main/java/ru/yandex/practicum/filmorate/FilmorateApplication.java b/src/main/java/ru/yandex/practicum/filmorate/FilmorateApplication.java
index 3c12a84..0625195 100644
--- a/src/main/java/ru/yandex/practicum/filmorate/FilmorateApplication.java
+++ b/src/main/java/ru/yandex/practicum/filmorate/FilmorateApplication.java
@@ -1,9 +1,11 @@
package ru.yandex.practicum.filmorate;
import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
+@AutoConfiguration
public class FilmorateApplication {
public static void main(String[] args) {
diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/Controller.java b/src/main/java/ru/yandex/practicum/filmorate/controller/Controller.java
new file mode 100644
index 0000000..d80f457
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/filmorate/controller/Controller.java
@@ -0,0 +1,39 @@
+package ru.yandex.practicum.filmorate.controller;
+
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.GetMapping;
+import ru.yandex.practicum.filmorate.exception.NotFoundException;
+import ru.yandex.practicum.filmorate.exception.ValidateException;
+import ru.yandex.practicum.filmorate.model.Model;
+import ru.yandex.practicum.filmorate.service.Service;
+
+import java.util.List;
+
+@RequiredArgsConstructor
+public abstract class Controller {
+
+ protected final Service service;
+
+
+ public T add(T model) throws ValidateException {
+
+ return service.addModel(model);
+ }
+
+
+ public T update(T model) throws NotFoundException {
+ service.updateModel(model);
+ return model;
+ }
+
+ @GetMapping
+ public List getModelList() {
+ return service.getModelList();
+ }
+
+ public T get(int id) throws NotFoundException {
+ T model = service.getModelById(id);
+
+ return model;
+ }
+}
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 294b2fc..1169ed7 100644
--- a/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java
+++ b/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java
@@ -1,31 +1,36 @@
package ru.yandex.practicum.filmorate.controller;
-
+import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
-import ru.yandex.practicum.filmorate.manager.FilmManager;
+import ru.yandex.practicum.filmorate.exception.NotFoundException;
+import ru.yandex.practicum.filmorate.exception.ValidateException;
import ru.yandex.practicum.filmorate.model.Film;
+import ru.yandex.practicum.filmorate.service.Service;
+import javax.validation.Valid;
-import java.util.List;
+@Slf4j
+@RequestMapping("/films")
+public class FilmController extends Controller {
-@RestController
-@RequestMapping ("/films")
-public class FilmController {
- FilmManager filmManager = new FilmManager();
- @GetMapping
- private List getFilm() {
- return filmManager.getFilmsList();
+ public FilmController(Service service) {
+ super(service);
+ }
+
+ @PostMapping
+ public Film add(@RequestBody @Valid Film model) throws ValidateException {
+ return super.add(model);
}
@PutMapping
- private Film update(@RequestBody Film film) {
- return filmManager.updateFilm(film);
+ public Film update(@RequestBody @Valid Film model) throws NotFoundException {
+ return super.update(model);
}
- @PostMapping
- private Film add(@RequestBody Film film) {
- return filmManager.addFilm(film);
+ @GetMapping("/{id}")
+ public Film get(@PathVariable int id) throws NotFoundException {
+ return super.get(id);
}
}
diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/FilmLikeController.java b/src/main/java/ru/yandex/practicum/filmorate/controller/FilmLikeController.java
new file mode 100644
index 0000000..fe782fe
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/filmorate/controller/FilmLikeController.java
@@ -0,0 +1,38 @@
+package ru.yandex.practicum.filmorate.controller;
+
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.web.bind.annotation.*;
+import ru.yandex.practicum.filmorate.exception.NotFoundException;
+import ru.yandex.practicum.filmorate.model.Film;
+import ru.yandex.practicum.filmorate.model.FilmLikes;
+import ru.yandex.practicum.filmorate.service.ManageLikeFilmService;
+import ru.yandex.practicum.filmorate.service.ServiceFilm;
+
+import java.util.List;
+
+@RestController
+public class FilmLikeController extends FilmController {
+ protected static final String USE_SERVICE = "ManageLikeFilmService";
+ private final ManageLikeFilmService manageLikeFilmService;
+
+ public FilmLikeController(@Qualifier(USE_SERVICE) ServiceFilm filmService) {
+ super(filmService);
+ manageLikeFilmService = (ManageLikeFilmService) filmService;
+ }
+
+ @PutMapping("/{id}/like/{userId}")
+ public void setLike(@PathVariable int id, @PathVariable int userId) {
+ manageLikeFilmService.addLike(new FilmLikes(id, userId));
+ }
+
+ @DeleteMapping("/{id}/like/{userId}")
+ public void deleteLike(@PathVariable int id, @PathVariable int userId) throws NotFoundException {
+ manageLikeFilmService.deleteLike(new FilmLikes(id, userId));
+ }
+
+ @GetMapping("/popular")
+ public List getFilmsPopular(@RequestParam(defaultValue = "10") int count) {
+
+ return manageLikeFilmService.getFilmsPopular(count);
+ }
+}
diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/GenresController.java b/src/main/java/ru/yandex/practicum/filmorate/controller/GenresController.java
new file mode 100644
index 0000000..878dfc3
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/filmorate/controller/GenresController.java
@@ -0,0 +1,30 @@
+package ru.yandex.practicum.filmorate.controller;
+
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import ru.yandex.practicum.filmorate.exception.NotFoundException;
+import ru.yandex.practicum.filmorate.model.Genre;
+import ru.yandex.practicum.filmorate.service.ServiceFilm;
+
+import java.util.List;
+
+@RestController
+@RequestMapping("/genres")
+@RequiredArgsConstructor
+public class GenresController {
+ private final ServiceFilm filmService;
+
+ @GetMapping("/{id}")
+ public Genre getGenreByID(@PathVariable int id) throws NotFoundException {
+ return filmService.getGenre(id);
+ }
+
+ @GetMapping
+ public List getGenreList() {
+ return filmService.getGenreList();
+ }
+
+}
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..ba96ad6
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/filmorate/controller/MpaController.java
@@ -0,0 +1,30 @@
+package ru.yandex.practicum.filmorate.controller;
+
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import ru.yandex.practicum.filmorate.exception.NotFoundException;
+import ru.yandex.practicum.filmorate.model.Mpa;
+import ru.yandex.practicum.filmorate.service.ServiceFilm;
+
+import java.util.List;
+
+@RestController
+@RequestMapping("/mpa")
+@RequiredArgsConstructor
+public class MpaController {
+ private final ServiceFilm filmService;
+
+ @GetMapping
+ public List getMpaList() {
+ return filmService.getMpaList();
+ }
+
+ @GetMapping("/{id}")
+ public Mpa getMpaById(@PathVariable int id) throws NotFoundException {
+ return filmService.getMpa(id);
+ }
+
+}
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 57f1346..39ee5fb 100644
--- a/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java
+++ b/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java
@@ -1,30 +1,38 @@
package ru.yandex.practicum.filmorate.controller;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.*;
-import ru.yandex.practicum.filmorate.manager.UserManager;
+import ru.yandex.practicum.filmorate.exception.NotFoundException;
+import ru.yandex.practicum.filmorate.exception.ValidateException;
import ru.yandex.practicum.filmorate.model.User;
+import ru.yandex.practicum.filmorate.service.UserService;
+import javax.validation.Valid;
-import java.util.List;
-
-@RestController
+@Slf4j
@RequestMapping("/users")
-public class UserController {
- UserManager userManager = new UserManager();
+public class UserController extends Controller {
+
+ private static final String SERVICE = "UserService";
+
+ public UserController(@Qualifier(SERVICE) UserService service) {
+ super(service);
+ }
- @GetMapping
- private List getUser() {
- return userManager.getUserList();
+ @PostMapping
+ public User add(@RequestBody @Valid User model) throws ValidateException {
+ return super.add(model);
}
@PutMapping
- private User update(@RequestBody User user) {
- return userManager.updateUser(user);
+ public User update(@RequestBody @Valid User model) throws NotFoundException {
+ return super.update(model);
}
- @PostMapping
- private User add(@RequestBody User user) {
- return userManager.addUser(user);
+ @GetMapping("/{id}")
+ public User get(@PathVariable int id) throws NotFoundException {
+ return super.get(id);
}
}
diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/UserLikeController.java b/src/main/java/ru/yandex/practicum/filmorate/controller/UserLikeController.java
new file mode 100644
index 0000000..adec0f5
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/filmorate/controller/UserLikeController.java
@@ -0,0 +1,44 @@
+package ru.yandex.practicum.filmorate.controller;
+
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.web.bind.annotation.*;
+import ru.yandex.practicum.filmorate.exception.NotFoundException;
+import ru.yandex.practicum.filmorate.model.FriendsTo;
+import ru.yandex.practicum.filmorate.model.User;
+import ru.yandex.practicum.filmorate.service.ManageFriendsUserService;
+import ru.yandex.practicum.filmorate.service.UserService;
+
+import java.util.List;
+
+@RestController
+public class UserLikeController extends UserController {
+
+ private static final String SERVICE = "ManageFriendsUserService";
+ private final ManageFriendsUserService manageFriendsUserService;
+
+ public UserLikeController(@Qualifier(SERVICE) UserService filmService) {
+ super(filmService);
+ manageFriendsUserService = (ManageFriendsUserService) filmService;
+ }
+
+ @PutMapping("/{idUser}/friends/{idFriend}")
+ public void addToFriends(@PathVariable int idUser, @PathVariable int idFriend) throws NotFoundException {
+ manageFriendsUserService.addToFriends(new FriendsTo(idUser, idFriend));
+ }
+
+ @DeleteMapping("/{idUser}/friends/{idFriend}")
+ public void deleteFromFriends(@PathVariable int idUser, @PathVariable int idFriend) {
+ manageFriendsUserService.removeFriends(new FriendsTo(idUser, idFriend));
+ }
+
+ @GetMapping("/{idUser}/friends")
+ public List getFriend(@PathVariable Integer idUser) throws NotFoundException {
+ return manageFriendsUserService.getFriends(idUser);
+ }
+
+ @GetMapping("/{idUser}/friends/common/{idFriend}")
+ public List getCommonFriend(@PathVariable int idUser, @PathVariable int idFriend) throws NotFoundException {
+ return manageFriendsUserService.getCommonFriends(new FriendsTo(idUser, idFriend));
+ }
+
+}
diff --git a/src/main/java/ru/yandex/practicum/filmorate/exception/ControllerException.java b/src/main/java/ru/yandex/practicum/filmorate/exception/ControllerException.java
new file mode 100644
index 0000000..14de323
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/filmorate/exception/ControllerException.java
@@ -0,0 +1,28 @@
+package ru.yandex.practicum.filmorate.exception;
+
+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.model.ExceptionEntity;
+
+@RestControllerAdvice
+public class ControllerException {
+ @ExceptionHandler
+ @ResponseStatus(HttpStatus.BAD_REQUEST)
+ public ExceptionEntity handlerValidateException(final ValidateException validateException) {
+ return new ExceptionEntity("validateException", validateException.getMessage());
+ }
+
+ @ExceptionHandler
+ @ResponseStatus(HttpStatus.NOT_FOUND)
+ public ExceptionEntity handlerNotFoundException(final NotFoundException notFoundException) {
+ return new ExceptionEntity("not found exception", notFoundException.getMessage());
+ }
+
+ @ExceptionHandler
+ @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
+ public ExceptionEntity handlerException(final Exception exception) {
+ return new ExceptionEntity("exception", exception.getMessage());
+ }
+}
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..df92130
--- /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 Exception {
+ public NotFoundException(String message) {
+ super(message);
+ }
+}
diff --git a/src/main/java/ru/yandex/practicum/filmorate/exception/ValidateException.java b/src/main/java/ru/yandex/practicum/filmorate/exception/ValidateException.java
new file mode 100644
index 0000000..4d0b7f3
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/filmorate/exception/ValidateException.java
@@ -0,0 +1,7 @@
+package ru.yandex.practicum.filmorate.exception;
+
+public class ValidateException extends Exception {
+ public ValidateException(String message) {
+ super(message);
+ }
+}
diff --git a/src/main/java/ru/yandex/practicum/filmorate/exception/ValidationException.java b/src/main/java/ru/yandex/practicum/filmorate/exception/ValidationException.java
deleted file mode 100644
index 52dc49c..0000000
--- a/src/main/java/ru/yandex/practicum/filmorate/exception/ValidationException.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package ru.yandex.practicum.filmorate.exception;
-
-public class ValidationException extends RuntimeException {
- public ValidationException(String message) {
- super(message);
- }
-}
diff --git a/src/main/java/ru/yandex/practicum/filmorate/manager/FilmManager.java b/src/main/java/ru/yandex/practicum/filmorate/manager/FilmManager.java
deleted file mode 100644
index 8875ba2..0000000
--- a/src/main/java/ru/yandex/practicum/filmorate/manager/FilmManager.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package ru.yandex.practicum.filmorate.manager;
-
-import lombok.Data;
-import lombok.extern.slf4j.Slf4j;
-
-
-import ru.yandex.practicum.filmorate.exception.ValidationException;
-import ru.yandex.practicum.filmorate.model.Film;
-
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-
-
-@Slf4j
-@Data
-public class FilmManager {
- private HashMap allFilms = new HashMap<>();
- private int filmId;
-
-
- public Film addFilm(Film film) {
- ValidationManager.allFilmExceptions(film.getName(), film.getDescription(), film.getReleaseDate(), film.getDuration());
- createId(film);
- allFilms.put(filmId, film);
- log.info("Фильм создан", film.getName(), film.getId());
- return film;
- }
-
- public void createId(Film film) {
- film.setId(++filmId);
- }
-
- public Film updateFilm(Film film) throws ValidationException {
- if (allFilms.containsKey(film.getId())) {
- ValidationManager.allFilmExceptions(film.getName(), film.getDescription(), film.getReleaseDate(), film.getDuration());
- allFilms.put(film.getId(), film);
- return film;
- } else {
- throw new ValidationException("Фильма с таким айди нет");
- }
- }
-
- public List getFilmsList() {
- List list = new ArrayList<>(allFilms.values());
- return list;
- }
-
-}
diff --git a/src/main/java/ru/yandex/practicum/filmorate/manager/UserManager.java b/src/main/java/ru/yandex/practicum/filmorate/manager/UserManager.java
deleted file mode 100644
index f5ee8fb..0000000
--- a/src/main/java/ru/yandex/practicum/filmorate/manager/UserManager.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package ru.yandex.practicum.filmorate.manager;
-
-import lombok.Data;
-import lombok.extern.slf4j.Slf4j;
-
-
-import ru.yandex.practicum.filmorate.exception.ValidationException;
-import ru.yandex.practicum.filmorate.model.User;
-
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-
-@Slf4j
-@Data
-public class UserManager {
- private HashMap allUsers = new HashMap<>();
- private int userId;
-
-
- public User addUser(User user) {
- if (user.getName() == null || user.getName().isEmpty()) {
- user.setName(user.getLogin());
- }
- ValidationManager.allUserExceptions(user.getEmail(), user.getLogin(), user.getName(), user);
- createId(user);
- allUsers.put(userId, user);
- log.info("Пользователь создан", user.getName(), user.getId());
- return user;
- }
-
- public void createId(User user) {
- user.setId(++userId);
- }
-
- public User updateUser(User user) throws ValidationException {
- if (allUsers.containsKey(user.getId())) {
- ValidationManager.allUserExceptions(user.getEmail(), user.getLogin(), user.getName(), user);
- allUsers.put(user.getId(), user);
- return user;
- } else {
- throw new ValidationException("Пользователя с таким айди нет");
- }
- }
-
- public List getUserList() {
- List list = new ArrayList<>(allUsers.values());
- return list;
- }
-}
diff --git a/src/main/java/ru/yandex/practicum/filmorate/manager/ValidationManager.java b/src/main/java/ru/yandex/practicum/filmorate/manager/ValidationManager.java
deleted file mode 100644
index 0bae36e..0000000
--- a/src/main/java/ru/yandex/practicum/filmorate/manager/ValidationManager.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package ru.yandex.practicum.filmorate.manager;
-
-import ru.yandex.practicum.filmorate.exception.ValidationException;
-import ru.yandex.practicum.filmorate.model.User;
-
-import java.time.LocalDate;
-
-public class ValidationManager {
-
- public static void allFilmExceptions(String name, String description, LocalDate date, double time) throws ValidationException {
- if (name == null || name.isBlank()) {
- throw new ValidationException("Поле name не должно быть пустым");
- }
-
- if (description.length() > 200 || description.length() == 0) {
- throw new ValidationException("Максимальная длина должна быть не больше 200 символов");
- }
-
- if (date == null || date.isBefore(LocalDate.of(1895, 12, 28))) {
- throw new ValidationException("Некорректная дата");
- }
-
- if (time <= 0) {
- throw new ValidationException("Неверная длительность фильма");
- }
- }
-
- public static void allUserExceptions(String email, String login, String name, User user) throws ValidationException {
- if (email == null || email.isBlank() || !email.contains("@")) {
- throw new ValidationException("Email не должен быть пустым и должен содержать @");
- }
-
- if (login.isBlank() || login.isEmpty()) {
- throw new ValidationException("Логин не может быть пустым и содержать пробелы");
- }
-
- if (name == null || name.isEmpty()) {
- throw new ValidationException("Вместо имени будет использован логин");
- }
-
- if (user.getBirthday().isAfter(LocalDate.now()) || user.getBirthday() == null) {
- throw new ValidationException("Некорректная дата рождения" + user.getId() + "'");
- }
- }
-}
diff --git a/src/main/java/ru/yandex/practicum/filmorate/model/ExceptionEntity.java b/src/main/java/ru/yandex/practicum/filmorate/model/ExceptionEntity.java
new file mode 100644
index 0000000..65da990
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/filmorate/model/ExceptionEntity.java
@@ -0,0 +1,14 @@
+package ru.yandex.practicum.filmorate.model;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+
+
+@Data
+@AllArgsConstructor
+public class ExceptionEntity {
+ private String error;
+ private String message;
+
+
+}
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 10c2bd7..515c284 100644
--- a/src/main/java/ru/yandex/practicum/filmorate/model/Film.java
+++ b/src/main/java/ru/yandex/practicum/filmorate/model/Film.java
@@ -1,19 +1,22 @@
package ru.yandex.practicum.filmorate.model;
-
-import lombok.AllArgsConstructor;
+import lombok.Builder;
import lombok.Data;
+import javax.validation.constraints.Positive;
import java.time.LocalDate;
+import java.util.TreeSet;
@Data
-@AllArgsConstructor
-public class Film {
+@Builder
+public class Film extends Model {
private int id;
private String name;
private String description;
private LocalDate releaseDate;
- private double duration;
-
-
+ @Positive
+ private int duration;
+ private Mpa mpa;
+ private TreeSet genres = new TreeSet<>();
+ private TreeSet likes = new TreeSet<>();
}
diff --git a/src/main/java/ru/yandex/practicum/filmorate/model/FilmLikes.java b/src/main/java/ru/yandex/practicum/filmorate/model/FilmLikes.java
new file mode 100644
index 0000000..9a46b72
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/filmorate/model/FilmLikes.java
@@ -0,0 +1,9 @@
+package ru.yandex.practicum.filmorate.model;
+
+
+public class FilmLikes extends FromTo {
+
+ public FilmLikes(Integer filmId, Integer userId) {
+ super(filmId, userId);
+ }
+}
diff --git a/src/main/java/ru/yandex/practicum/filmorate/model/FriendsTo.java b/src/main/java/ru/yandex/practicum/filmorate/model/FriendsTo.java
new file mode 100644
index 0000000..5d560c4
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/filmorate/model/FriendsTo.java
@@ -0,0 +1,7 @@
+package ru.yandex.practicum.filmorate.model;
+
+public class FriendsTo extends FromTo {
+ public FriendsTo(int idUser, int idFriend) {
+ super(idUser, idFriend);
+ }
+}
diff --git a/src/main/java/ru/yandex/practicum/filmorate/model/FromTo.java b/src/main/java/ru/yandex/practicum/filmorate/model/FromTo.java
new file mode 100644
index 0000000..204282f
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/filmorate/model/FromTo.java
@@ -0,0 +1,12 @@
+package ru.yandex.practicum.filmorate.model;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+
+@Data
+@AllArgsConstructor
+public abstract class FromTo {
+ protected Integer from;
+ protected Integer to;
+
+}
diff --git a/src/main/java/ru/yandex/practicum/filmorate/model/Genre.java b/src/main/java/ru/yandex/practicum/filmorate/model/Genre.java
new file mode 100644
index 0000000..78d8e62
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/filmorate/model/Genre.java
@@ -0,0 +1,14 @@
+package ru.yandex.practicum.filmorate.model;
+
+
+public class Genre extends Model implements Comparable {
+ public Genre(int id, String name) {
+ this.setId(id);
+ this.setName(name);
+ }
+
+ @Override
+ public int compareTo(Genre o) {
+ return this.getId() - o.id;
+ }
+}
diff --git a/src/main/java/ru/yandex/practicum/filmorate/model/Model.java b/src/main/java/ru/yandex/practicum/filmorate/model/Model.java
new file mode 100644
index 0000000..53a595c
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/filmorate/model/Model.java
@@ -0,0 +1,9 @@
+package ru.yandex.practicum.filmorate.model;
+
+import lombok.Data;
+
+@Data
+public abstract class Model {
+ protected int id;
+ protected String name;
+}
diff --git a/src/main/java/ru/yandex/practicum/filmorate/model/Mpa.java b/src/main/java/ru/yandex/practicum/filmorate/model/Mpa.java
new file mode 100644
index 0000000..d294de2
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/filmorate/model/Mpa.java
@@ -0,0 +1,12 @@
+package ru.yandex.practicum.filmorate.model;
+
+public class Mpa extends Model {
+ public Mpa(int id, String name) {
+ setId(id);
+ setName(name);
+ }
+
+ public Mpa(int id) {
+ setId(id);
+ }
+}
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 c73ccdc..8c7a324 100644
--- a/src/main/java/ru/yandex/practicum/filmorate/model/User.java
+++ b/src/main/java/ru/yandex/practicum/filmorate/model/User.java
@@ -1,17 +1,32 @@
package ru.yandex.practicum.filmorate.model;
-
import lombok.AllArgsConstructor;
+import lombok.Builder;
import lombok.Data;
+import javax.validation.constraints.Email;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
import java.time.LocalDate;
+import java.util.List;
@Data
+@Builder
@AllArgsConstructor
-public class User {
+public class User extends Model {
private int id;
+ private String name;
+ @Email
+ @NotBlank
+ @NotNull
+ @NotEmpty
private String email;
+ @NotNull
+ @NotBlank
+ @NotEmpty
private String login;
- private String name;
private LocalDate birthday;
+ private List friends;
+
}
diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java b/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java
new file mode 100644
index 0000000..694ca68
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java
@@ -0,0 +1,54 @@
+package ru.yandex.practicum.filmorate.service;
+
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Service;
+import ru.yandex.practicum.filmorate.exception.ValidateException;
+import ru.yandex.practicum.filmorate.model.Film;
+import ru.yandex.practicum.filmorate.storage.StorageFilm;
+
+import java.time.LocalDate;
+import java.util.Objects;
+import java.util.TreeSet;
+
+@Service
+public class FilmService extends ServiceFilm {
+
+ // protected static final String FILM_STORAGE = "inMemoryFilmStorage";
+ protected static final String FILM_STORAGE = "FilmDBStorage";
+ protected static final String FILM_NAME_BLANK_EXCEPTION = "Не заполнено название фильма";
+ protected static final String FILM_DESCRIPTION_EXCEPTION = "Длинна описания привышает 200 символов";
+ protected static final String FILM_DATE_PRODUCE_EXCEPTION = "Дата выпуска не может быть раньше появления самого кино";
+ protected static final String FILM_DURATION_EXCEPTION = "Продолжительность не может быть меньше или ровна 0";
+
+
+ public FilmService(@Qualifier(FILM_STORAGE) StorageFilm storage) {
+ super(storage);
+ }
+
+ protected void validate(Film film) throws ValidateException {
+ if (Objects.isNull(film.getGenres())) {
+ film.setGenres(new TreeSet<>());
+ }
+
+ if (Objects.isNull(film.getLikes())) {
+ film.setLikes(new TreeSet<>());
+ }
+
+ if (Objects.isNull(film.getName()) || film.getName().isBlank() || film.getName().isEmpty()) {
+ throw new ValidateException(FILM_NAME_BLANK_EXCEPTION);
+ }
+
+ if (film.getDescription().length() > 200) {
+ throw new ValidateException(FILM_DESCRIPTION_EXCEPTION);
+ }
+ final String dateStartFilmEpoch = "1895-12-28";
+ if (film.getReleaseDate().isBefore(LocalDate.parse(dateStartFilmEpoch))) {
+ throw new ValidateException(FILM_DATE_PRODUCE_EXCEPTION);
+ }
+
+ if (film.getDuration() <= 0) {
+ throw new ValidateException(FILM_DURATION_EXCEPTION);
+ }
+ }
+
+}
diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/ManageFriendsUserService.java b/src/main/java/ru/yandex/practicum/filmorate/service/ManageFriendsUserService.java
new file mode 100644
index 0000000..6e5fe77
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/filmorate/service/ManageFriendsUserService.java
@@ -0,0 +1,65 @@
+package ru.yandex.practicum.filmorate.service;
+
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Service;
+import ru.yandex.practicum.filmorate.exception.NotFoundException;
+import ru.yandex.practicum.filmorate.model.FriendsTo;
+import ru.yandex.practicum.filmorate.model.Model;
+import ru.yandex.practicum.filmorate.model.User;
+import ru.yandex.practicum.filmorate.storage.StorageUser;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+
+@Service("ManageFriendsUserService")
+public class ManageFriendsUserService extends UserService {
+ protected static final String NEGATIVE_ID_EXCEPTION = "Id пользователя не может быть меньше нуля";
+
+ public ManageFriendsUserService(@Qualifier(UserService.USER_STORAGE) StorageUser storage) {
+ super(storage);
+ }
+
+ public void addToFriends(FriendsTo users) throws NotFoundException {
+ if (users.getFrom() < 1 || users.getTo() < 1) {
+ throw new NotFoundException(NEGATIVE_ID_EXCEPTION);
+ }
+ storage.addToSet(users);
+ }
+
+ public void removeFriends(FriendsTo user) {
+ storage.removeIdFromIdSet(user);
+ }
+
+ public List getCommonFriends(FriendsTo user) throws NotFoundException {
+ User user1 = super.getModelById(user.getFrom());
+ User user2 = super.getModelById(user.getTo());
+ List idFriends = user1.getFriends().stream().filter(e -> user2.getFriends().stream()
+ .anyMatch(e1 -> Objects.equals(e, e1))).collect(Collectors.toList());
+
+ return idFriends.stream().map(e -> {
+ Model model;
+ try {
+ model = getModelById(e);
+ } catch (NotFoundException exception) {
+ return null;
+ }
+ return model;
+ })
+ .collect(Collectors.toList()).stream().map(e -> (User) e)
+ .collect(Collectors.toList());
+ }
+
+ public List getFriends(int id) throws NotFoundException {
+ User user = super.getModelById(id);
+ List userList = new ArrayList<>();
+
+ for (int idUser : user.getFriends()) {
+ userList.add(super.getModelById(idUser));
+ }
+
+ return userList;
+ }
+}
diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/ManageLikeFilmService.java b/src/main/java/ru/yandex/practicum/filmorate/service/ManageLikeFilmService.java
new file mode 100644
index 0000000..6490d93
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/filmorate/service/ManageLikeFilmService.java
@@ -0,0 +1,62 @@
+package ru.yandex.practicum.filmorate.service;
+
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.dao.EmptyResultDataAccessException;
+import org.springframework.stereotype.Service;
+import ru.yandex.practicum.filmorate.exception.NotFoundException;
+import ru.yandex.practicum.filmorate.model.Film;
+import ru.yandex.practicum.filmorate.model.FilmLikes;
+import ru.yandex.practicum.filmorate.storage.StorageFilm;
+import ru.yandex.practicum.filmorate.storage.StorageUser;
+
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+@Service("ManageLikeFilmService")
+public class ManageLikeFilmService extends FilmService {
+ private final StorageUser storageUser;
+
+ public ManageLikeFilmService(@Qualifier(FilmService.FILM_STORAGE) StorageFilm storage,
+ @Qualifier(UserService.USER_STORAGE) StorageUser storageUser) {
+ super(storage);
+ this.storageUser = storageUser;
+ }
+
+ public Film addLike(FilmLikes filmLikes) {
+ return storage.addToSet(filmLikes);
+ }
+
+ public Film deleteLike(FilmLikes filmLikes) throws NotFoundException {
+ validateExistUser(filmLikes.getTo());
+
+ storage.removeIdFromIdSet(filmLikes);
+
+ Film film = (Film) getModelById(filmLikes.getFrom());
+
+ return film;
+ }
+
+ public Set getLikes(Integer idFilm) throws NotFoundException {
+ Film film = (Film) getModelById(idFilm);
+ Set likes = film.getLikes();
+
+ return likes;
+ }
+
+ public List getFilmsPopular(int count) {
+ List filmList = super.getModelList();
+
+ return filmList.stream().sorted((e1, e2) -> e2.getLikes().size() - e1.getLikes().size())
+ .limit(count).collect(Collectors.toList());
+ }
+
+ private boolean validateExistUser(int userId) throws NotFoundException {
+ try {
+ storageUser.isExist(userId);
+ } catch (EmptyResultDataAccessException e) {
+ throw new NotFoundException(String.format(UserService.NOT_FOUND_ID_EXCEPTION, userId));
+ }
+ return true;
+ }
+}
diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/Service.java b/src/main/java/ru/yandex/practicum/filmorate/service/Service.java
new file mode 100644
index 0000000..f81be5f
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/filmorate/service/Service.java
@@ -0,0 +1,73 @@
+package ru.yandex.practicum.filmorate.service;
+
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.dao.EmptyResultDataAccessException;
+import ru.yandex.practicum.filmorate.exception.NotFoundException;
+import ru.yandex.practicum.filmorate.exception.ValidateException;
+import ru.yandex.practicum.filmorate.model.Film;
+import ru.yandex.practicum.filmorate.model.Model;
+import ru.yandex.practicum.filmorate.storage.Storage;
+
+import java.util.*;
+
+@Slf4j
+@RequiredArgsConstructor
+public abstract class Service {
+ public static String NOT_FOUND_ID_EXCEPTION = "модель с требуемым id = %d не найдена";
+
+ protected final Storage storage;
+
+ public T addModel(T model) throws ValidateException {
+ try {
+ validate(model);
+ if (model instanceof Film) {
+ Film film = (Film) model;
+ if (Objects.isNull(film.getGenres())) {
+ film.setGenres(new TreeSet<>());
+ }
+
+ if (Objects.isNull(film.getLikes())) {
+ film.setLikes(new TreeSet<>());
+ }
+ }
+ return (T) storage.save(model);
+ } catch (ValidateException ex) {
+ log.warn(ex.getMessage());
+ throw new ValidateException(ex.getMessage());
+ }
+ }
+
+ public T updateModel(T model) throws NotFoundException {
+ try {
+ if (storage.isExist(model.getId())) {
+ validate(model);
+ storage.update(model);
+
+ }
+ } catch (EmptyResultDataAccessException exception) {
+ log.warn(String.format(NOT_FOUND_ID_EXCEPTION, model.getId()));
+ throw new NotFoundException(String.format(NOT_FOUND_ID_EXCEPTION, model.getId()));
+ } catch (ValidateException e) {
+ throw new RuntimeException(e);
+ }
+
+ return model;
+ }
+
+ public List getModelList() {
+ return new ArrayList((Collection extends T>) storage.getModelMap().values());
+ }
+
+ protected abstract void validate(T model) throws ValidateException;
+
+ public T getModelById(int id) throws NotFoundException {
+ try {
+ return storage.get(id);
+ } catch (EmptyResultDataAccessException exception) {
+ throw new NotFoundException(String.format(NOT_FOUND_ID_EXCEPTION, id));
+ }
+ }
+
+
+}
diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/ServiceFilm.java b/src/main/java/ru/yandex/practicum/filmorate/service/ServiceFilm.java
new file mode 100644
index 0000000..1782142
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/filmorate/service/ServiceFilm.java
@@ -0,0 +1,44 @@
+package ru.yandex.practicum.filmorate.service;
+
+import org.springframework.dao.EmptyResultDataAccessException;
+import ru.yandex.practicum.filmorate.exception.NotFoundException;
+import ru.yandex.practicum.filmorate.model.Film;
+import ru.yandex.practicum.filmorate.model.Genre;
+import ru.yandex.practicum.filmorate.model.Model;
+import ru.yandex.practicum.filmorate.model.Mpa;
+import ru.yandex.practicum.filmorate.storage.StorageFilm;
+
+import java.util.List;
+
+public abstract class ServiceFilm extends Service {
+ private static StorageFilm storageFilm;
+
+ public ServiceFilm(StorageFilm storage) {
+ super(storage);
+ storageFilm = storage;
+ }
+
+ public T getGenre(int id) throws NotFoundException {
+ try {
+ return storageFilm.getGenreById(id);
+ } catch (EmptyResultDataAccessException e) {
+ throw new NotFoundException("Genre не найден");
+ }
+ }
+
+ public List getGenreList() {
+ return (List) storageFilm.getGenreList();
+ }
+
+ public T getMpa(int id) throws NotFoundException {
+ try {
+ return storageFilm.getMpa(id);
+ } catch (EmptyResultDataAccessException e) {
+ throw new NotFoundException("mpa не айден");
+ }
+ }
+
+ public List getMpaList() {
+ return (List) storageFilm.getMpaList();
+ }
+}
diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/ServiceUser.java b/src/main/java/ru/yandex/practicum/filmorate/service/ServiceUser.java
new file mode 100644
index 0000000..c8949c2
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/filmorate/service/ServiceUser.java
@@ -0,0 +1,16 @@
+package ru.yandex.practicum.filmorate.service;
+
+import lombok.extern.slf4j.Slf4j;
+import ru.yandex.practicum.filmorate.model.User;
+import ru.yandex.practicum.filmorate.storage.StorageUser;
+
+@Slf4j
+public abstract class ServiceUser extends Service {
+
+ protected ServiceUser(StorageUser storage) {
+ super(storage);
+ NOT_FOUND_ID_EXCEPTION = "Пользователь с требуемым id не найден";
+ }
+
+
+}
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..7ae6bf0
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java
@@ -0,0 +1,39 @@
+package ru.yandex.practicum.filmorate.service;
+
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Service;
+import ru.yandex.practicum.filmorate.exception.ValidateException;
+import ru.yandex.practicum.filmorate.model.User;
+import ru.yandex.practicum.filmorate.storage.StorageUser;
+
+import java.time.LocalDate;
+import java.util.Objects;
+
+@Service("UserService")
+public class UserService extends ServiceUser {
+ protected static final String USER_STORAGE = "userDBStorage";
+ protected static final String USER_LOGIN_EXCEPTION = "Логин пользователя не может содержать пробелы";
+ protected static final String USER_BIRTH_DATE_EXCEPTION = "Дата рождения не может быть в будущем";
+
+ public UserService(@Qualifier(USER_STORAGE) StorageUser storage) {
+ super(storage);
+ }
+
+ @Override
+ protected void validate(User user) throws ValidateException {
+
+
+ if (user.getLogin().contains(" ")) {
+ throw new ValidateException(USER_LOGIN_EXCEPTION);
+ }
+
+ if (Objects.isNull(user.getName()) || user.getName().isEmpty() || user.getName().isBlank()) {
+ user.setName(user.getLogin());
+ }
+
+ if (user.getBirthday().isAfter(LocalDate.now())) {
+ throw new ValidateException(USER_BIRTH_DATE_EXCEPTION);
+ }
+
+ }
+}
diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/FilmDBStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/FilmDBStorage.java
new file mode 100644
index 0000000..b460d97
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/filmorate/storage/FilmDBStorage.java
@@ -0,0 +1,234 @@
+package ru.yandex.practicum.filmorate.storage;
+
+import lombok.AllArgsConstructor;
+import org.springframework.jdbc.core.BatchPreparedStatementSetter;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.support.GeneratedKeyHolder;
+import org.springframework.jdbc.support.KeyHolder;
+import org.springframework.stereotype.Repository;
+import ru.yandex.practicum.filmorate.model.*;
+
+import java.sql.Date;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.*;
+
+@Repository("FilmDBStorage")
+@AllArgsConstructor
+public class FilmDBStorage implements StorageFilm {
+ private JdbcTemplate jdbcTemplate;
+
+ @Override
+ public boolean isExist(int id) {
+ return get(id) != null;
+ }
+
+ @Override
+ public void update(Model model) {
+ Film film = (Film) model;
+ String sql = "UPDATE film SET title = ?, description = ?, release_date = ?, duration = ?, mpa_id = ? WHERE film_id = ?";
+
+ jdbcTemplate.update(sql, film.getName(), film.getDescription(), film.getReleaseDate(), film.getDuration(),
+ film.getMpa().getId(), film.getId());
+ updateGenres(film);
+ updateLikes(film);
+ }
+
+ @Override
+ public Model save(Model model) {
+ Film film = (Film) model;
+ String sql = "INSERT INTO film (title, description, release_date, duration, mpa_id) VALUES (?,?,?,?,?)";
+ KeyHolder keyHolder = new GeneratedKeyHolder();
+
+
+ jdbcTemplate.update(connection -> {
+ PreparedStatement stm = connection.prepareStatement(sql, new String[]{"film_id"});
+ stm.setString(1, film.getName());
+ stm.setString(2, film.getDescription());
+ stm.setDate(3, Date.valueOf(film.getReleaseDate()));
+ stm.setInt(4, film.getDuration());
+ stm.setInt(5, film.getMpa().getId());
+
+ return stm;
+ }, keyHolder);
+ film.setId(keyHolder.getKey().intValue());
+ saveGenres(film);
+ updateLikes(film);
+
+
+ return model;
+ }
+
+ private void saveGenres(Film film) {
+
+ String sqlGenre = "INSERT INTO genre_film (genre_id, film_id) VALUES (?,?)";
+ Iterator iterator = film.getGenres().iterator();
+
+ jdbcTemplate.batchUpdate(sqlGenre, new BatchPreparedStatementSetter() {
+ @Override
+ public void setValues(PreparedStatement ps, int i) throws SQLException {
+ ps.setInt(2, film.getId());
+ ps.setInt(1, iterator.next().getId());
+ }
+
+ @Override
+ public int getBatchSize() {
+ return film.getGenres().size();
+ }
+ });
+ }
+
+ private void updateLikes(Film film) {
+ String sqlDelGenre = "DELETE FROM likes_film WHERE film_id = ?";
+
+ jdbcTemplate.update(sqlDelGenre, film.getId());
+
+ String sqlGenre = "INSERT INTO likes_film (user_id, film_id) VALUES (?,?)";
+ Iterator iterator = film.getLikes().iterator();
+ jdbcTemplate.batchUpdate(sqlGenre, new BatchPreparedStatementSetter() {
+ @Override
+ public void setValues(PreparedStatement ps, int i) throws SQLException {
+ ps.setInt(2, film.getId());
+ ps.setInt(1, iterator.next());
+ }
+
+ @Override
+ public int getBatchSize() {
+ return film.getLikes().size();
+ }
+ });
+ }
+
+ private void updateGenres(Film film) {
+ String sqlDelGenre = "DELETE FROM genre_film WHERE film_id = ?";
+
+ jdbcTemplate.update(sqlDelGenre, film.getId());
+
+ String sqlGenre = "INSERT INTO genre_film (genre_id, film_id) VALUES (?,?)";
+ Iterator iterator = film.getGenres().iterator();
+
+ jdbcTemplate.batchUpdate(sqlGenre, new BatchPreparedStatementSetter() {
+ @Override
+ public void setValues(PreparedStatement ps, int i) throws SQLException {
+ ps.setInt(2, film.getId());
+ ps.setInt(1, iterator.next().getId());
+ }
+
+ @Override
+ public int getBatchSize() {
+ return film.getGenres().size();
+ }
+ });
+ }
+
+ @Override
+ public Film get(int id) {
+ String sqlNew = "SELECT f.film_id, f.title, f.description, f.release_date, f.duration, f.mpa_id, g.genre_id, g.name, lf.user_id\n" +
+ "FROM genre as g \n" +
+ "left JOIN genre_film as gf on gf.genre_id = g.genre_id \n" +
+ "right JOIN film AS f ON f.film_id = gf.film_id \n" +
+ "left JOIN likes_film AS lf ON lf.film_id = f.film_id \n" +
+ "WHERE f.film_id = ?";
+ Film film = jdbcTemplate.queryForObject(sqlNew, this::mapRowToFilm, id);
+
+ return film;
+ }
+
+ private Film mapRowToFilm(ResultSet rs, int rowNum) throws SQLException {
+ TreeSet filmGenre = new TreeSet<>();
+ TreeSet likes = new TreeSet<>();
+
+ Film film = Film.builder().id(rs.getInt("film_id"))
+ .name(rs.getString("title"))
+ .description(rs.getString("description"))
+ .genres(filmGenre)
+ .duration(rs.getInt("duration"))
+ .releaseDate(rs.getDate("release_date").toLocalDate())
+ .mpa(getMpa(rs.getInt("mpa_id")))
+ .likes(likes).build();
+
+ do {
+ if (rs.getInt("genre_id") != 0) {
+ filmGenre.add(new Genre(rs.getInt("genre_id"), rs.getString("name")));
+ }
+
+ if (rs.getInt("user_id") != 0) {
+ likes.add(rs.getInt("user_id"));
+ }
+
+ } while (rs.next());
+
+ return film;
+ }
+
+
+ @Override
+ public void delete(int id) {
+ String sql = "DELETE FROM film WHERE film_id = ?";
+
+ jdbcTemplate.update(sql, id);
+ }
+
+ @Override
+ public Map getModelMap() {
+ String sql1 = "SELECT film_id FROM FILM";
+ Map filmMap = new HashMap<>();
+ List idsList = jdbcTemplate.query(sql1, (rs, nm) -> rs.getInt("film_id"));
+
+ for (int id : idsList) {
+ filmMap.put(id, get(id));
+ }
+
+ return filmMap;
+ }
+
+ @Override
+ public void removeIdFromIdSet(FromTo user) {
+ String sql = "DELETE FROM likes_film WHERE film_id = ? AND user_id = ?";
+
+ jdbcTemplate.update(sql, user.getFrom(), user.getTo());
+
+ }
+
+ @Override
+ public T addToSet(FromTo filmLikes) {
+ String sql = "INSERT INTO likes_film (film_id, user_id) VALUES (?,?)";
+
+ jdbcTemplate.update(sql, filmLikes.getFrom(), filmLikes.getTo());
+
+ return null;
+ }
+
+ @Override
+ public Genre getGenreById(int id) {
+ String sql = "SELECT * FROM genre WHERE genre_id = ?";
+
+ return jdbcTemplate.queryForObject(sql,
+ (rs, rowNum) -> new Genre(rs.getInt("genre_id"), rs.getString("name")), id);
+ }
+
+ @Override
+ public List getGenreList() {
+ String sql = "SELECT * FROM genre ";
+
+ return jdbcTemplate.query(sql,
+ ((rs, rowNum) -> new Genre(rs.getInt("genre_id"), rs.getString("name"))));
+ }
+
+ @Override
+ public Mpa getMpa(int id) {
+ String sql = "SELECT * FROM MPA WHERE mpa_id = ?";
+
+ return jdbcTemplate.queryForObject(sql,
+ (rs, rowNum) -> new Mpa(rs.getInt("mpa_id"), rs.getString("name")), id);
+ }
+
+ @Override
+ public List extends Model> getMpaList() {
+ String sql = "SELECT * FROM MPA";
+
+ return jdbcTemplate.query(sql, (rs, rowNum) -> new Mpa(rs.getInt("mpa_id"),
+ rs.getString("name")));
+ }
+}
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..224f587
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryFilmStorage.java
@@ -0,0 +1,78 @@
+package ru.yandex.practicum.filmorate.storage;
+
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Component;
+import ru.yandex.practicum.filmorate.model.Film;
+import ru.yandex.practicum.filmorate.model.FromTo;
+import ru.yandex.practicum.filmorate.model.Model;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+@Component("inMemoryFilmStorage")
+@RequiredArgsConstructor
+public class InMemoryFilmStorage implements StorageFilm {
+ protected final Map filmMap;
+ private Integer id = 0;
+
+ public boolean isExist(int id) {
+ return filmMap.containsKey(id);
+ }
+
+ public void update(Model model) {
+ filmMap.put(model.getId(), (Film) model);
+ }
+
+ public Model save(Model model) {
+ id++;
+ model.setId(id);
+ filmMap.put(id, (Film) model);
+ return model;
+ }
+
+ public Film get(int id) {
+ return filmMap.get(id);
+ }
+
+ public void delete(int id) {
+ filmMap.remove(id);
+ }
+
+ public Map getModelMap() {
+ return filmMap;
+ }
+
+ public void removeIdFromIdSet(FromTo films) {
+ }
+
+ @Override
+ public T getGenreById(int id) {
+ return null;
+ }
+
+ @Override
+ public List extends Model> getGenreList() {
+ return null;
+ }
+
+ @Override
+ public T getMpa(int id) {
+ return null;
+ }
+
+ @Override
+ public List extends Model> getMpaList() {
+ return null;
+ }
+
+ @Override
+ public Film addToSet(FromTo filmLikes) {
+ Film film = filmMap.get(filmLikes.getFrom());
+ Set likes = film.getLikes();
+
+ likes.add(filmLikes.getTo());
+ return film;
+ }
+
+}
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..93ba3e0
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorage.java
@@ -0,0 +1,70 @@
+package ru.yandex.practicum.filmorate.storage;
+
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Component;
+import ru.yandex.practicum.filmorate.model.FromTo;
+import ru.yandex.practicum.filmorate.model.Model;
+import ru.yandex.practicum.filmorate.model.User;
+
+import java.util.List;
+import java.util.Map;
+
+@Component("inMemoryUserStorage")
+@RequiredArgsConstructor
+public class InMemoryUserStorage implements StorageUser {
+ private final Map userMap;
+ private Integer id = 0;
+
+ public boolean isExist(int id) {
+ return userMap.containsKey(id);
+ }
+
+ public void update(Model model) {
+ userMap.put(model.getId(), (User) model);
+ }
+
+ public Model save(Model model) {
+ id++;
+ model.setId(id);
+ userMap.put(id, (User) model);
+
+ return model;
+ }
+
+ public User get(int id) {
+ return userMap.get(id);
+ }
+
+ public void delete(int id) {
+ userMap.remove(id);
+ }
+
+ @Override
+ public Map getModelMap() {
+ return userMap;
+ }
+
+ public void removeIdFromIdSet(FromTo user) {
+ User user1 = userMap.get(user.getFrom());
+ User user2 = userMap.get(user.getTo());
+ List userFr1 = user1.getFriends();
+ List userFr2 = user2.getFriends();
+
+ userFr1.remove(user2.getId());
+ userFr2.remove(user1.getId());
+
+ }
+
+ public User addToSet(FromTo user) {
+ User user1 = userMap.get(user.getFrom());
+ User user2 = userMap.get(user.getTo());
+ List userFr1 = user1.getFriends();
+ List userFr2 = user2.getFriends();
+
+ userFr1.add(user2.getId());
+ userFr2.add(user1.getId());
+
+ return user1;
+ }
+
+}
diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/Storage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/Storage.java
new file mode 100644
index 0000000..b3c576d
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/filmorate/storage/Storage.java
@@ -0,0 +1,27 @@
+package ru.yandex.practicum.filmorate.storage;
+
+import ru.yandex.practicum.filmorate.model.FromTo;
+import ru.yandex.practicum.filmorate.model.Model;
+
+import java.util.Map;
+
+public interface Storage {
+
+ boolean isExist(int id);
+
+ void update(Model model);
+
+ Model save(Model model);
+
+ T get(int id);
+
+ void delete(int id);
+
+ Map getModelMap();
+
+ void removeIdFromIdSet(FromTo user);
+
+ T addToSet(FromTo filmLikes);
+
+
+}
diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/StorageFilm.java b/src/main/java/ru/yandex/practicum/filmorate/storage/StorageFilm.java
new file mode 100644
index 0000000..151d09d
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/filmorate/storage/StorageFilm.java
@@ -0,0 +1,15 @@
+package ru.yandex.practicum.filmorate.storage;
+
+import ru.yandex.practicum.filmorate.model.Model;
+
+import java.util.List;
+
+public interface StorageFilm extends Storage {
+ T getGenreById(int id);
+
+ List extends Model> getGenreList();
+
+ T getMpa(int id);
+
+ List extends Model> getMpaList();
+}
diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/StorageUser.java b/src/main/java/ru/yandex/practicum/filmorate/storage/StorageUser.java
new file mode 100644
index 0000000..0173ece
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/filmorate/storage/StorageUser.java
@@ -0,0 +1,6 @@
+package ru.yandex.practicum.filmorate.storage;
+
+
+public interface StorageUser extends Storage {
+
+}
diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/UserDBStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/UserDBStorage.java
new file mode 100644
index 0000000..7ddc69a
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/filmorate/storage/UserDBStorage.java
@@ -0,0 +1,122 @@
+package ru.yandex.practicum.filmorate.storage;
+
+import lombok.AllArgsConstructor;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.support.GeneratedKeyHolder;
+import org.springframework.jdbc.support.KeyHolder;
+import org.springframework.stereotype.Repository;
+import ru.yandex.practicum.filmorate.model.FromTo;
+import ru.yandex.practicum.filmorate.model.Model;
+import ru.yandex.practicum.filmorate.model.User;
+
+import java.sql.Date;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Repository("userDBStorage")
+@AllArgsConstructor
+public class UserDBStorage implements StorageUser {
+ private JdbcTemplate jdbcTemplate;
+
+ @Override
+ public boolean isExist(int id) {
+ return get(id) != null;
+ }
+
+ @Override
+ public void update(Model model) {
+ User user = (User) model;
+ String sql = "UPDATE users SET name = ?, birth_date = ?, email = ?, login = ? WHERE user_id = ?";
+ jdbcTemplate.update(sql, user.getName(), user.getBirthday(), user.getEmail(), user.getLogin(), user.getId());
+ }
+
+ @Override
+ public User save(Model model) {
+ User user = (User) model;
+ String sql = ("INSERT INTO users (name, birth_date, email, login) VALUES (?,?,?,?)");
+ KeyHolder keyHolder = new GeneratedKeyHolder();
+
+ jdbcTemplate.update(con -> {
+ PreparedStatement stmt = con.prepareStatement(sql, new String[]{"user_id"});
+ stmt.setString(1, user.getName());
+ stmt.setDate(2, Date.valueOf(user.getBirthday()));
+ stmt.setString(3, user.getEmail());
+ stmt.setString(4, user.getLogin());
+ return stmt;
+ }, keyHolder);
+ user.setId(keyHolder.getKey().intValue());
+ return user;
+ }
+
+ @Override
+ public User get(int id) {
+ String sqlUserLikes = "SELECT u.user_id, u.name, u.email, u.login, u.birth_date, fr.friend_id\n" +
+ "FROM users as u\n" +
+ "LEFT JOIN friend as fr ON fr.user_id = u.user_id\n" +
+ "WHERE u.user_id = ?\n";
+ ;
+ User user = jdbcTemplate.queryForObject(sqlUserLikes, this::rowMapperUser, id);
+
+ return user;
+
+ }
+
+ private Integer mapRowToInteger(ResultSet rs, int rowNum) throws SQLException {
+ return rs.getInt("friend_id");
+ }
+
+ private User rowMapperUser(ResultSet rs, int idRow) throws SQLException {
+ List likes = new ArrayList<>();
+ User user = User.builder().id(rs.getInt("user_id"))
+ .name(rs.getString("name"))
+ .email(rs.getString("email"))
+ .login(rs.getString("login"))
+ .birthday(rs.getDate("birth_date").toLocalDate())
+ .friends(likes).build();
+ do {
+ if (rs.getInt("friend_id") != 0) {
+ likes.add(rs.getInt("friend_id"));
+ }
+ } while (rs.next());
+ return user;
+ }
+
+ @Override
+ public void delete(int id) {
+ String sql = "DELETE FROM users WHERE user_id = ?";
+ jdbcTemplate.update(sql, id);
+
+ }
+
+ @Override
+ public Map getModelMap() {
+ String sql = "SELECT user_id FROM users";
+ Map mapUsers = new HashMap<>();
+ List usersIdList = jdbcTemplate.query(sql, (rs, r) -> rs.getInt("user_id"));
+
+ for (int id : usersIdList) {
+ mapUsers.put(id, get(id));
+ }
+
+ return mapUsers;
+ }
+
+ @Override
+ public void removeIdFromIdSet(FromTo user) {
+ String sql = "DELETE FROM friend WHERE user_id = ? AND friend_id = ?";
+ jdbcTemplate.update(sql, user.getFrom(), user.getTo());
+ }
+
+ @Override
+ public Model addToSet(FromTo userFriend) {
+ String sql = "INSERT INTO friend (user_id, friend_id, IS_APPROVED) VALUES (?,?,?);";
+ jdbcTemplate.update(sql, userFriend.getFrom(), userFriend.getTo(), true);
+ return null;
+ }
+
+}
diff --git a/src/main/java/sprint.json b/src/main/java/sprint.json
deleted file mode 100644
index 541e79a..0000000
--- a/src/main/java/sprint.json
+++ /dev/null
@@ -1,1047 +0,0 @@
-{
- "info": {
- "_postman_id": "e337606f-5df6-47d0-9784-7fa89c1b51fe",
- "name": "sprint09/controllers-films-users",
- "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
- "_exporter_id": "2036415"
- },
- "item": [
- {
- "name": "users",
- "item": [
- {
- "name": "User create",
- "event": [
- {
- "listen": "test",
- "script": {
- "exec": [
- "pm.test(\"Status code is 200 or 201\", function () {\r",
- " pm.expect(pm.response.code).to.be.oneOf([200,201]);\r",
- "});\r",
- "pm.test(\"Has user create response\", function () {\r",
- " pm.response.to.be.withBody;\r",
- " pm.response.to.be.json;\r",
- "});\r",
- "pm.test(\"Test user 'id' field\", function () {\r",
- " var jsonData = pm.response.json();\r",
- " pm.expect(jsonData).to.have.property('id');\r",
- " pm.expect(jsonData.id, '\"id\" must be 1').to.eql(1);\r",
- "});\r",
- "pm.test(\"Test user 'email' field\", function () {\r",
- " var jsonData = pm.response.json();\r",
- " pm.expect(jsonData).to.have.property('email');\r",
- " pm.expect(jsonData.email, '\"email\" must be \"mail@mail.ru\"').to.eql('mail@mail.ru');\r",
- "});\r",
- "pm.test(\"Test user 'name' field\", function () {\r",
- " var jsonData = pm.response.json();\r",
- " pm.expect(jsonData).to.have.property('name');\r",
- " pm.expect(jsonData.name, '\"name\" must be \"Nick Name\"').to.eql('Nick Name');\r",
- "});\r",
- "pm.test(\"Test user 'login' field\", function () {\r",
- " var jsonData = pm.response.json();\r",
- " pm.expect(jsonData).to.have.property('login');\r",
- " pm.expect(jsonData.login, '\"login\" field must be \"dolore\"').to.eql('dolore'); \r",
- "});\r",
- "pm.test(\"Test user 'birthday' field\", function () {\r",
- " var jsonData = pm.response.json();\r",
- " pm.expect(jsonData).to.have.property('birthday');\r",
- " pm.expect(jsonData.birthday, '\"birthday\" field must be \"1946-08-20\"').to.eql('1946-08-20');\r",
- "});"
- ],
- "type": "text/javascript"
- }
- }
- ],
- "request": {
- "method": "POST",
- "header": [
- {
- "key": "Content-Type",
- "value": "application/json"
- },
- {
- "key": "Accept",
- "value": "*/*"
- }
- ],
- "body": {
- "mode": "raw",
- "raw": "{\n \"login\": \"dolore\",\n \"name\": \"Nick Name\",\n \"email\": \"mail@mail.ru\",\n \"birthday\": \"1946-08-20\"\n}",
- "options": {
- "raw": {
- "language": "json"
- }
- }
- },
- "url": {
- "raw": "{{baseUrl}}/users",
- "host": [
- "{{baseUrl}}"
- ],
- "path": [
- "users"
- ]
- }
- },
- "response": []
- },
- {
- "name": "User create Fail login",
- "event": [
- {
- "listen": "test",
- "script": {
- "exec": [
- "pm.test(\"Status code is 500 or 400\", function () {\r",
- " pm.expect(pm.response.code).to.be.oneOf([500,400]);\r",
- "});\r",
- "pm.test(\"Has error response\", function () {\r",
- " pm.response.to.be.withBody;\r",
- " pm.response.to.be.json;\r",
- "});\r",
- ""
- ],
- "type": "text/javascript"
- }
- }
- ],
- "request": {
- "method": "POST",
- "header": [
- {
- "key": "Content-Type",
- "value": "application/json"
- },
- {
- "key": "Accept",
- "value": "*/*"
- }
- ],
- "body": {
- "mode": "raw",
- "raw": "{\n \"login\": \"dolore ullamco\",\n \"email\": \"yandex@mail.ru\",\n \"birthday\": \"2446-08-20\"\n}",
- "options": {
- "raw": {
- "language": "json"
- }
- }
- },
- "url": {
- "raw": "{{baseUrl}}/users",
- "host": [
- "{{baseUrl}}"
- ],
- "path": [
- "users"
- ]
- }
- },
- "response": []
- },
- {
- "name": "User create Fail email",
- "event": [
- {
- "listen": "test",
- "script": {
- "exec": [
- "pm.test(\"Status code is 500 or 400\", function () {\r",
- " pm.expect(pm.response.code).to.be.oneOf([500,400]);\r",
- "});\r",
- "pm.test(\"Has error response\", function () {\r",
- " pm.response.to.be.withBody;\r",
- " pm.response.to.be.json;\r",
- "});"
- ],
- "type": "text/javascript"
- }
- }
- ],
- "request": {
- "method": "POST",
- "header": [
- {
- "key": "Content-Type",
- "value": "application/json"
- },
- {
- "key": "Accept",
- "value": "*/*"
- }
- ],
- "body": {
- "mode": "raw",
- "raw": "{\n \"login\": \"dolore ullamco\",\n \"name\": \"\",\n \"email\": \"mail.ru\",\n \"birthday\": \"1980-08-20\"\n}",
- "options": {
- "raw": {
- "language": "json"
- }
- }
- },
- "url": {
- "raw": "{{baseUrl}}/users",
- "host": [
- "{{baseUrl}}"
- ],
- "path": [
- "users"
- ]
- }
- },
- "response": []
- },
- {
- "name": "User create Fail birthday",
- "event": [
- {
- "listen": "test",
- "script": {
- "exec": [
- "pm.test(\"Status code is 500 or 400\", function () {\r",
- " pm.expect(pm.response.code).to.be.oneOf([500,400]);\r",
- "});\r",
- "pm.test(\"Has error response\", function () {\r",
- " pm.response.to.be.withBody;\r",
- " pm.response.to.be.json;\r",
- "});"
- ],
- "type": "text/javascript"
- }
- }
- ],
- "request": {
- "method": "POST",
- "header": [
- {
- "key": "Content-Type",
- "value": "application/json"
- },
- {
- "key": "Accept",
- "value": "*/*"
- }
- ],
- "body": {
- "mode": "raw",
- "raw": "{\n \"login\": \"dolore\",\n \"name\": \"\",\n \"email\": \"test@mail.ru\",\n \"birthday\": \"2446-08-20\"\n}",
- "options": {
- "raw": {
- "language": "json"
- }
- }
- },
- "url": {
- "raw": "{{baseUrl}}/users",
- "host": [
- "{{baseUrl}}"
- ],
- "path": [
- "users"
- ]
- }
- },
- "response": []
- },
- {
- "name": "User update",
- "event": [
- {
- "listen": "test",
- "script": {
- "exec": [
- "pm.test(\"Status code is 200\", function () {\r",
- " pm.response.to.be.ok;\r",
- "});\r",
- "pm.test(\"Has user update response\", function () {\r",
- " pm.response.to.be.withBody;\r",
- " pm.response.to.be.json;\r",
- "});\r",
- "pm.test(\"Test user 'id' field\", function () {\r",
- " var jsonData = pm.response.json();\r",
- " pm.expect(jsonData).to.have.property('id');\r",
- " pm.expect(jsonData.id, '\"id\" must be 1').to.eql(1);\r",
- "});\r",
- "pm.test(\"Test user 'email' field\", function () {\r",
- " var jsonData = pm.response.json();\r",
- " pm.expect(jsonData).to.have.property('email');\r",
- " pm.expect(jsonData.email, '\"email\" must be \"mail@yandex.ru\"').to.eql('mail@yandex.ru');\r",
- "});\r",
- "pm.test(\"Test user 'name' field\", function () {\r",
- " var jsonData = pm.response.json();\r",
- " pm.expect(jsonData).to.have.property('name');\r",
- " pm.expect(jsonData.name, '\"name\" must be \"est adipisicing\"').to.eql('est adipisicing');\r",
- "});\r",
- "pm.test(\"Test user 'login' field\", function () {\r",
- " var jsonData = pm.response.json();\r",
- " pm.expect(jsonData).to.have.property('login');\r",
- " pm.expect(jsonData.login, '\"login\" field must be \"doloreUpdate\"').to.eql('doloreUpdate'); \r",
- "});\r",
- "pm.test(\"Test user 'birthday' field\", function () {\r",
- " var jsonData = pm.response.json();\r",
- " pm.expect(jsonData).to.have.property('birthday');\r",
- " pm.expect(jsonData.birthday, '\"birthday\" field must be \"1976-09-20\"').to.eql('1976-09-20');\r",
- "});"
- ],
- "type": "text/javascript"
- }
- }
- ],
- "request": {
- "method": "PUT",
- "header": [
- {
- "key": "Content-Type",
- "value": "application/json"
- },
- {
- "key": "Accept",
- "value": "*/*"
- }
- ],
- "body": {
- "mode": "raw",
- "raw": "{\n \"login\": \"doloreUpdate\",\n \"name\": \"est adipisicing\",\n \"id\": 1,\n \"email\": \"mail@yandex.ru\",\n \"birthday\": \"1976-09-20\"\n}",
- "options": {
- "raw": {
- "language": "json"
- }
- }
- },
- "url": {
- "raw": "{{baseUrl}}/users",
- "host": [
- "{{baseUrl}}"
- ],
- "path": [
- "users"
- ]
- }
- },
- "response": []
- },
- {
- "name": "User update unknown",
- "event": [
- {
- "listen": "test",
- "script": {
- "exec": [
- "pm.test(\"Status code is 500\", function () {\r",
- " pm.expect(pm.response.code).to.be.oneOf([500, 404]);\r",
- "});\r",
- "pm.test(\"Has error response\", function () {\r",
- " pm.response.to.be.withBody;\r",
- " pm.response.to.be.json;\r",
- "});"
- ],
- "type": "text/javascript"
- }
- }
- ],
- "request": {
- "method": "PUT",
- "header": [
- {
- "key": "Content-Type",
- "value": "application/json"
- },
- {
- "key": "Accept",
- "value": "*/*"
- }
- ],
- "body": {
- "mode": "raw",
- "raw": "{\n \"login\": \"doloreUpdate\",\n \"name\": \"est adipisicing\",\n \"id\": 9999,\n \"email\": \"mail@yandex.ru\",\n \"birthday\": \"1976-09-20\"\n}",
- "options": {
- "raw": {
- "language": "json"
- }
- }
- },
- "url": {
- "raw": "{{baseUrl}}/users",
- "host": [
- "{{baseUrl}}"
- ],
- "path": [
- "users"
- ]
- }
- },
- "response": []
- },
- {
- "name": "User get All",
- "event": [
- {
- "listen": "test",
- "script": {
- "exec": [
- "pm.test(\"Status code is 200\", function () {\r",
- " pm.response.to.be.ok;\r",
- "});\r",
- "pm.test(\"Test list user response\", function () {\r",
- " pm.response.to.be.withBody;\r",
- " pm.response.to.be.json;\r",
- " var jsonData = pm.response.json();\r",
- " pm.expect(jsonData.length, 'List length must be 1').to.eql(1);\r",
- "});\r",
- "pm.test(\"Test user[0] 'id' field\", function () {\r",
- " var jsonData = pm.response.json();\r",
- " pm.expect(jsonData[0]).to.have.property('id');\r",
- " pm.expect(jsonData[0].id, '\"id\" must be 1').to.eql(1);\r",
- "});\r",
- "pm.test(\"Test user[0] 'email' field\", function () {\r",
- " var jsonData = pm.response.json();\r",
- " pm.expect(jsonData[0]).to.have.property('email');\r",
- " pm.expect(jsonData[0].email, '\"email\" must be \"mail@yandex.ru\"').to.eql('mail@yandex.ru');\r",
- "});\r",
- "pm.test(\"Test user[0] 'name' field\", function () {\r",
- " var jsonData = pm.response.json();\r",
- " pm.expect(jsonData[0]).to.have.property('name');\r",
- " pm.expect(jsonData[0].name, '\"name\" must be \"est adipisicing\"').to.eql('est adipisicing');\r",
- "});\r",
- "pm.test(\"Test user[0] 'login' field\", function () {\r",
- " var jsonData = pm.response.json();\r",
- " pm.expect(jsonData[0]).to.have.property('login');\r",
- " pm.expect(jsonData[0].login, '\"login\" field must be \"doloreUpdate\"').to.eql('doloreUpdate'); \r",
- "});\r",
- "pm.test(\"Test user[0] 'birthday' field\", function () {\r",
- " var jsonData = pm.response.json();\r",
- " pm.expect(jsonData[0]).to.have.property('birthday');\r",
- " pm.expect(jsonData[0].birthday, '\"birthday\" field must be \"1976-09-20\"').to.eql('1976-09-20');\r",
- "});\r",
- "\r",
- ""
- ],
- "type": "text/javascript"
- }
- }
- ],
- "request": {
- "method": "GET",
- "header": [
- {
- "key": "Accept",
- "value": "*/*"
- }
- ],
- "url": {
- "raw": "{{baseUrl}}/users",
- "host": [
- "{{baseUrl}}"
- ],
- "path": [
- "users"
- ]
- }
- },
- "response": []
- },
- {
- "name": "Create user with empty name",
- "event": [
- {
- "listen": "test",
- "script": {
- "exec": [
- "pm.test(\"Status code is 200 or 201\", function () {\r",
- " pm.expect(pm.response.code).to.be.oneOf([200,201]);\r",
- "});\r",
- "pm.test(\"Has user create response\", function () {\r",
- " pm.response.to.be.withBody;\r",
- " pm.response.to.be.json;\r",
- "});\r",
- "pm.test(\"Test user 'id' field\", function () {\r",
- " var jsonData = pm.response.json();\r",
- " pm.expect(jsonData).to.have.property('id');\r",
- " pm.expect(jsonData.id, '\"id\" must be 2').to.eql(2);\r",
- "});\r",
- "pm.test(\"Test user 'email' field\", function () {\r",
- " var jsonData = pm.response.json();\r",
- " pm.expect(jsonData).to.have.property('email');\r",
- " pm.expect(jsonData.email, '\"email\" must be \"friend@common.ru\"').to.eql('friend@common.ru');\r",
- "});\r",
- "pm.test(\"Test user 'name' field\", function () {\r",
- " var jsonData = pm.response.json();\r",
- " pm.expect(jsonData).to.have.property('name');\r",
- " pm.expect(jsonData.name, '\"name\" must be \"common\"').to.eql('common');\r",
- "});\r",
- "pm.test(\"Test user 'login' field\", function () {\r",
- " var jsonData = pm.response.json();\r",
- " pm.expect(jsonData).to.have.property('login');\r",
- " pm.expect(jsonData.login, '\"login\" field must be \"common\"').to.eql('common'); \r",
- "});\r",
- "pm.test(\"Test user 'birthday' field\", function () {\r",
- " var jsonData = pm.response.json();\r",
- " pm.expect(jsonData).to.have.property('birthday');\r",
- " pm.expect(jsonData.birthday, '\"birthday\" field must be \"2000-08-20\"').to.eql('2000-08-20');\r",
- "});\r",
- ""
- ],
- "type": "text/javascript"
- }
- }
- ],
- "request": {
- "method": "POST",
- "header": [
- {
- "key": "Content-Type",
- "value": "application/json"
- },
- {
- "key": "Accept",
- "value": "*/*"
- }
- ],
- "body": {
- "mode": "raw",
- "raw": "{\n \"login\": \"common\",\n \"email\": \"friend@common.ru\",\n \"birthday\": \"2000-08-20\"\n}",
- "options": {
- "raw": {
- "language": "json"
- }
- }
- },
- "url": {
- "raw": "{{baseUrl}}/users",
- "host": [
- "{{baseUrl}}"
- ],
- "path": [
- "users"
- ]
- }
- },
- "response": []
- }
- ]
- },
- {
- "name": "films",
- "item": [
- {
- "name": "Film create",
- "event": [
- {
- "listen": "test",
- "script": {
- "exec": [
- "pm.test(\"Status code is 200 or 201\", function () {\r",
- " pm.expect(pm.response.code).to.be.oneOf([200,201]);\r",
- "});\r",
- "pm.test(\"Has film create response\", function () {\r",
- " pm.response.to.be.withBody;\r",
- " pm.response.to.be.json;\r",
- "});\r",
- "pm.test(\"Test film 'id' field\", function () {\r",
- " var jsonData = pm.response.json();\r",
- " pm.expect(jsonData).to.have.property('id');\r",
- " pm.expect(jsonData.id, '\"id\" must be 1').to.eql(1);\r",
- "});\r",
- "pm.test(\"Test film 'name' field\", function () {\r",
- " var jsonData = pm.response.json();\r",
- " pm.expect(jsonData).to.have.property('name');\r",
- " pm.expect(jsonData.name, '\"name\" must be \"nisi eiusmod\"').to.eql('nisi eiusmod');\r",
- "});\r",
- "pm.test(\"Test film 'description' field\", function () {\r",
- " var jsonData = pm.response.json();\r",
- " pm.expect(jsonData).to.have.property('description');\r",
- " pm.expect(jsonData.description, '\"description\" must be \"adipisicing\"').to.eql('adipisicing');\r",
- "});\r",
- "pm.test(\"Test film 'releaseDate' field\", function () {\r",
- " var jsonData = pm.response.json();\r",
- " pm.expect(jsonData).to.have.property('releaseDate');\r",
- " pm.expect(jsonData.releaseDate, '\"releaseDate\" field must be \"1967-03-25\"').to.eql('1967-03-25');\r",
- "});\r",
- "pm.test(\"Test film 'duration' field\", function () {\r",
- " var jsonData = pm.response.json();\r",
- " pm.expect(jsonData).to.have.property('duration');\r",
- " pm.expect(jsonData.duration, '\"duration\" field must be 100').to.eql(100); \r",
- "});\r",
- "\r",
- ""
- ],
- "type": "text/javascript"
- }
- }
- ],
- "request": {
- "method": "POST",
- "header": [
- {
- "key": "Content-Type",
- "value": "application/json"
- },
- {
- "key": "Accept",
- "value": "*/*"
- }
- ],
- "body": {
- "mode": "raw",
- "raw": "{\n \"name\": \"nisi eiusmod\",\n \"description\": \"adipisicing\",\n \"releaseDate\": \"1967-03-25\",\n \"duration\": 100\n}",
- "options": {
- "raw": {
- "language": "json"
- }
- }
- },
- "url": {
- "raw": "{{baseUrl}}/films",
- "host": [
- "{{baseUrl}}"
- ],
- "path": [
- "films"
- ]
- }
- },
- "response": []
- },
- {
- "name": "Film create Fail name",
- "event": [
- {
- "listen": "test",
- "script": {
- "exec": [
- "pm.test(\"Status code is 500 or 400\", function () {\r",
- " pm.expect(pm.response.code).to.be.oneOf([500,400]);\r",
- "});\r",
- "pm.test(\"Has error response\", function () {\r",
- " pm.response.to.be.withBody;\r",
- " pm.response.to.be.json;\r",
- "});\r",
- ""
- ],
- "type": "text/javascript"
- }
- }
- ],
- "request": {
- "method": "POST",
- "header": [
- {
- "key": "Content-Type",
- "value": "application/json"
- },
- {
- "key": "Accept",
- "value": "*/*"
- }
- ],
- "body": {
- "mode": "raw",
- "raw": "{\n \"name\": \"\",\n \"description\": \"Description\",\n \"releaseDate\": \"1900-03-25\",\n \"duration\": 200\n}",
- "options": {
- "raw": {
- "language": "json"
- }
- }
- },
- "url": {
- "raw": "{{baseUrl}}/films",
- "host": [
- "{{baseUrl}}"
- ],
- "path": [
- "films"
- ]
- }
- },
- "response": []
- },
- {
- "name": "Film create Fail description",
- "event": [
- {
- "listen": "test",
- "script": {
- "exec": [
- "pm.test(\"Status code is 500 or 400\", function () {\r",
- " pm.expect(pm.response.code).to.be.oneOf([500,400]);\r",
- "});\r",
- "pm.test(\"Has error response\", function () {\r",
- " pm.response.to.be.withBody;\r",
- " pm.response.to.be.json;\r",
- "});\r",
- ""
- ],
- "type": "text/javascript"
- }
- }
- ],
- "request": {
- "method": "POST",
- "header": [
- {
- "key": "Content-Type",
- "value": "application/json"
- },
- {
- "key": "Accept",
- "value": "*/*"
- }
- ],
- "body": {
- "mode": "raw",
- "raw": "{\n \"name\": \"Film name\",\n \"description\": \"Пятеро друзей ( комик-группа «Шарло»), приезжают в город Бризуль. Здесь они хотят разыскать господина Огюста Куглова, который задолжал им деньги, а именно 20 миллионов. о Куглов, который за время «своего отсутствия», стал кандидатом Коломбани.\",\n \"releaseDate\": \"1900-03-25\",\n \"duration\": 200\n}",
- "options": {
- "raw": {
- "language": "json"
- }
- }
- },
- "url": {
- "raw": "{{baseUrl}}/films",
- "host": [
- "{{baseUrl}}"
- ],
- "path": [
- "films"
- ]
- }
- },
- "response": []
- },
- {
- "name": "Film create Fail releaseDate",
- "event": [
- {
- "listen": "test",
- "script": {
- "exec": [
- "pm.test(\"Status code is 500 or 400\", function () {\r",
- " pm.expect(pm.response.code).to.be.oneOf([500,400]);\r",
- "});\r",
- "pm.test(\"Has error response\", function () {\r",
- " pm.response.to.be.withBody;\r",
- " pm.response.to.be.json;\r",
- "});\r",
- ""
- ],
- "type": "text/javascript"
- }
- }
- ],
- "request": {
- "method": "POST",
- "header": [
- {
- "key": "Content-Type",
- "value": "application/json"
- },
- {
- "key": "Accept",
- "value": "*/*"
- }
- ],
- "body": {
- "mode": "raw",
- "raw": "{\n \"name\": \"Name\",\n \"description\": \"Description\",\n \"releaseDate\": \"1890-03-25\",\n \"duration\": 200\n}",
- "options": {
- "raw": {
- "language": "json"
- }
- }
- },
- "url": {
- "raw": "{{baseUrl}}/films",
- "host": [
- "{{baseUrl}}"
- ],
- "path": [
- "films"
- ]
- }
- },
- "response": []
- },
- {
- "name": "Film create Fail duration",
- "event": [
- {
- "listen": "test",
- "script": {
- "exec": [
- "pm.test(\"Status code is 500 or 400\", function () {\r",
- " pm.expect(pm.response.code).to.be.oneOf([500,400]);\r",
- "});\r",
- "pm.test(\"Has error response\", function () {\r",
- " pm.response.to.be.withBody;\r",
- " pm.response.to.be.json;\r",
- "});\r",
- ""
- ],
- "type": "text/javascript"
- }
- }
- ],
- "request": {
- "method": "POST",
- "header": [
- {
- "key": "Content-Type",
- "value": "application/json"
- },
- {
- "key": "Accept",
- "value": "*/*"
- }
- ],
- "body": {
- "mode": "raw",
- "raw": "{\n \"name\": \"Name\",\n \"description\": \"Descrition\",\n \"releaseDate\": \"1980-03-25\",\n \"duration\": -200\n}",
- "options": {
- "raw": {
- "language": "json"
- }
- }
- },
- "url": {
- "raw": "{{baseUrl}}/films",
- "host": [
- "{{baseUrl}}"
- ],
- "path": [
- "films"
- ]
- }
- },
- "response": []
- },
- {
- "name": "Film update",
- "event": [
- {
- "listen": "test",
- "script": {
- "exec": [
- "pm.test(\"Status code is 200\", function () {\r",
- " pm.response.to.be.ok;\r",
- "});\r",
- "pm.test(\"Has film update response\", function () {\r",
- " pm.response.to.be.withBody;\r",
- " pm.response.to.be.json;\r",
- "});\r",
- "\r",
- "pm.test(\"Test film 'id' field\", function () {\r",
- " var jsonData = pm.response.json();\r",
- " pm.expect(jsonData).to.have.property('id');\r",
- " pm.expect(jsonData.id, '\"id\" must be 1').to.eql(1);\r",
- "});\r",
- "pm.test(\"Test film 'name' field\", function () {\r",
- " var jsonData = pm.response.json();\r",
- " pm.expect(jsonData).to.have.property('name');\r",
- " pm.expect(jsonData.name, '\"name\" must be \"Film Updated\"').to.eql('Film Updated');\r",
- "});\r",
- "pm.test(\"Test film 'description' field\", function () {\r",
- " var jsonData = pm.response.json();\r",
- " pm.expect(jsonData).to.have.property('description');\r",
- " pm.expect(jsonData.description, '\"description\" must be \"New film update decription\"').to.eql('New film update decription');\r",
- "});\r",
- "pm.test(\"Test film 'releaseDate' field\", function () {\r",
- " var jsonData = pm.response.json();\r",
- " pm.expect(jsonData).to.have.property('releaseDate');\r",
- " pm.expect(jsonData.releaseDate, '\"releaseDate\" field must be \"1989-04-17\"').to.eql('1989-04-17');\r",
- "});\r",
- "pm.test(\"Test film 'duration' field\", function () {\r",
- " var jsonData = pm.response.json();\r",
- " pm.expect(jsonData).to.have.property('duration');\r",
- " pm.expect(jsonData.duration, '\"duration\" field must be 190').to.eql(190); \r",
- "});\r",
- "\r",
- ""
- ],
- "type": "text/javascript"
- }
- }
- ],
- "request": {
- "method": "PUT",
- "header": [
- {
- "key": "Content-Type",
- "value": "application/json"
- },
- {
- "key": "Accept",
- "value": "*/*"
- }
- ],
- "body": {
- "mode": "raw",
- "raw": "{\n \"id\": 1,\n \"name\": \"Film Updated\",\n \"releaseDate\": \"1989-04-17\",\n \"description\": \"New film update decription\",\n \"duration\": 190,\n \"rate\": 4\n}",
- "options": {
- "raw": {
- "language": "json"
- }
- }
- },
- "url": {
- "raw": "{{baseUrl}}/films",
- "host": [
- "{{baseUrl}}"
- ],
- "path": [
- "films"
- ]
- }
- },
- "response": []
- },
- {
- "name": "Film update unknown",
- "event": [
- {
- "listen": "test",
- "script": {
- "exec": [
- "pm.test(\"Status code is 500\", function () {\r",
- " pm.expect(pm.response.code).to.be.oneOf([500, 404]);\r",
- "});\r",
- "pm.test(\"Has error response\", function () {\r",
- " pm.response.to.be.withBody;\r",
- " pm.response.to.be.json;\r",
- "});\r",
- ""
- ],
- "type": "text/javascript"
- }
- }
- ],
- "request": {
- "method": "PUT",
- "header": [
- {
- "key": "Content-Type",
- "value": "application/json"
- },
- {
- "key": "Accept",
- "value": "*/*"
- }
- ],
- "body": {
- "mode": "raw",
- "raw": "{\n \"id\": 9999,\n \"name\": \"Film Updated\",\n \"releaseDate\": \"1989-04-17\",\n \"description\": \"New film update decription\",\n \"duration\": 190,\n \"rate\": 4\n}",
- "options": {
- "raw": {
- "language": "json"
- }
- }
- },
- "url": {
- "raw": "{{baseUrl}}/films",
- "host": [
- "{{baseUrl}}"
- ],
- "path": [
- "films"
- ]
- }
- },
- "response": []
- },
- {
- "name": "Film get All",
- "event": [
- {
- "listen": "test",
- "script": {
- "exec": [
- "pm.test(\"Status code is 200\", function () {\r",
- " pm.response.to.be.ok;\r",
- "});\r",
- "pm.test(\"Test list film response\", function () {\r",
- " pm.response.to.be.withBody;\r",
- " pm.response.to.be.json;\r",
- " var jsonData = pm.response.json();\r",
- " pm.expect(jsonData.length, 'List length must be 1').to.eql(1);\r",
- "});\r",
- "pm.test(\"Test film[0] 'id' field\", function () {\r",
- " var jsonData = pm.response.json();\r",
- " pm.expect(jsonData[0]).to.have.property('id');\r",
- " pm.expect(jsonData[0].id, '\"id\" must be 1').to.eql(1);\r",
- "});\r",
- "pm.test(\"Test film[0] 'name' field\", function () {\r",
- " var jsonData = pm.response.json();\r",
- " pm.expect(jsonData[0]).to.have.property('name');\r",
- " pm.expect(jsonData[0].name, '\"name\" must be \"Film Updated\"').to.eql('Film Updated');\r",
- "});\r",
- "pm.test(\"Test film[0] 'description' field\", function () {\r",
- " var jsonData = pm.response.json();\r",
- " pm.expect(jsonData[0]).to.have.property('description');\r",
- " pm.expect(jsonData[0].description, '\"description\" must be \"New film update decription\"').to.eql('New film update decription');\r",
- "});\r",
- "pm.test(\"Test film[0] 'releaseDate' field\", function () {\r",
- " var jsonData = pm.response.json();\r",
- " pm.expect(jsonData[0]).to.have.property('releaseDate');\r",
- " pm.expect(jsonData[0].releaseDate, '\"releaseDate\" field must be \"1989-04-17\"').to.eql('1989-04-17');\r",
- "});\r",
- "pm.test(\"Test film[0] 'duration' field\", function () {\r",
- " var jsonData = pm.response.json();\r",
- " pm.expect(jsonData[0]).to.have.property('duration');\r",
- " pm.expect(jsonData[0].duration, '\"duration\" field must be 190').to.eql(190); \r",
- "});\r",
- ""
- ],
- "type": "text/javascript"
- }
- }
- ],
- "request": {
- "method": "GET",
- "header": [
- {
- "key": "Accept",
- "value": "*/*"
- }
- ],
- "url": {
- "raw": "{{baseUrl}}/films",
- "host": [
- "{{baseUrl}}"
- ],
- "path": [
- "films"
- ]
- }
- },
- "response": []
- }
- ]
- }
- ],
- "event": [
- {
- "listen": "prerequest",
- "script": {
- "type": "text/javascript",
- "exec": [
- ""
- ]
- }
- },
- {
- "listen": "test",
- "script": {
- "type": "text/javascript",
- "exec": [
- ""
- ]
- }
- }
- ],
- "variable": [
- {
- "key": "baseUrl",
- "value": "http://localhost:8080",
- "type": "string"
- }
- ]
-}
\ No newline at end of file
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index 8b13789..939a8c1 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -1 +1,7 @@
-
+spring.h2.console.enabled=true
+spring.sql.init.mode=always
+# ? jdbc-url ???????, ??? ?????? ????? ????????? ? ????
+spring.datasource.url=jdbc:h2:file:./db/filmorate
+spring.datasource.driverClassName=org.h2.Driver
+spring.datasource.username=sa
+spring.datasource.password=password
\ No newline at end of file
diff --git a/src/main/resources/data.sql b/src/main/resources/data.sql
new file mode 100644
index 0000000..2634c74
--- /dev/null
+++ b/src/main/resources/data.sql
@@ -0,0 +1,12 @@
+INSERT INTO genre (name) VALUES ('Комедия');
+INSERT INTO genre (name) VALUES ('Драма');
+INSERT INTO genre (name) VALUES ('Мультфильм');
+INSERT INTO genre (name) VALUES ('Триллер');
+INSERT INTO genre (name) VALUES ('Документальный');
+INSERT INTO genre (name) VALUES ('Боевик');
+
+INSERT INTO MPA (NAME) VALUES ('G');
+INSERT INTO MPA (NAME) VALUES ('PG');
+INSERT INTO MPA (NAME) VALUES ('PG-13');
+INSERT INTO MPA (NAME) VALUES ('R');
+INSERT INTO MPA (NAME) VALUES ('NC-17');
\ No newline at end of file
diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql
new file mode 100644
index 0000000..8bf0ed5
--- /dev/null
+++ b/src/main/resources/schema.sql
@@ -0,0 +1,43 @@
+create TABLE IF NOT EXISTS users (
+ user_id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
+ name VARCHAR(20),
+ birth_date DATE,
+ email VARCHAR(40),
+ login VARCHAR(20)
+);
+
+create TABLE IF NOT EXISTS MPA (
+ mpa_id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
+ name varchar
+);
+
+create TABLE IF NOT EXISTS film (
+ film_id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
+ title varchar(100),
+ description varchar(255),
+ release_date date,
+ duration integer,
+ mpa_id integer REFERENCES MPA (mpa_id) ON delete CASCADE
+);
+
+create TABLE IF NOT EXISTS friend (
+ user_id INTEGER REFERENCES USERS (user_id) ON delete CASCADE,
+ is_approved BIT,
+ friend_id INTEGER REFERENCES USERS (user_id) ON delete CASCADE
+);
+
+create TABLE IF NOT EXISTS genre (
+ genre_id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
+ name VARCHAR(100)
+);
+
+create TABLE IF NOT EXISTS genre_film (
+ genre_id INTEGER REFERENCES genre (genre_id) ON delete CASCADE,
+ film_id INTEGER REFERENCES film (film_id) ON delete CASCADE
+);
+
+create TABLE IF NOT EXISTS likes_film(
+ film_id INTEGER REFERENCES film(film_id) ON delete CASCADE,
+ user_id INTEGER REFERENCES users(user_id) ON delete CASCADE
+);
+
diff --git a/src/test/java/ru/yandex/practicum/filmorate/FilmorateApplicationTests.java b/src/test/java/ru/yandex/practicum/filmorate/FilmorateApplicationTests.java
index 660412e..9035f0a 100644
--- a/src/test/java/ru/yandex/practicum/filmorate/FilmorateApplicationTests.java
+++ b/src/test/java/ru/yandex/practicum/filmorate/FilmorateApplicationTests.java
@@ -1,13 +1,20 @@
package ru.yandex.practicum.filmorate;
+import lombok.RequiredArgsConstructor;
import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.boot.test.context.SpringBootTest;
+
@SpringBootTest
+@AutoConfigureTestDatabase
+@RequiredArgsConstructor(onConstructor_ = @Autowired)
class FilmorateApplicationTests {
+
@Test
- void contextLoads() {
- }
+ public void test() {
+ }
}
diff --git a/src/test/java/ru/yandex/practicum/filmorate/controller/FilmControllerTest.java b/src/test/java/ru/yandex/practicum/filmorate/controller/FilmControllerTest.java
new file mode 100644
index 0000000..4b9c88c
--- /dev/null
+++ b/src/test/java/ru/yandex/practicum/filmorate/controller/FilmControllerTest.java
@@ -0,0 +1,42 @@
+package ru.yandex.practicum.filmorate.controller;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import ru.yandex.practicum.filmorate.exception.NotFoundException;
+import ru.yandex.practicum.filmorate.exception.ValidateException;
+import ru.yandex.practicum.filmorate.model.Film;
+import ru.yandex.practicum.filmorate.service.ManageLikeFilmService;
+import ru.yandex.practicum.filmorate.storage.InMemoryFilmStorage;
+import ru.yandex.practicum.filmorate.storage.InMemoryUserStorage;
+
+import java.time.LocalDate;
+import java.util.HashMap;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+class FilmControllerTest {
+ private FilmController filmController;
+
+ @BeforeEach
+ void setUp() {
+ filmController = new FilmController(new ManageLikeFilmService(new InMemoryFilmStorage(new HashMap<>()),
+ new InMemoryUserStorage(new HashMap<>())));
+ }
+
+ @Test
+ void add() throws ValidateException, NotFoundException {
+ Film film = Film.builder()
+ .description("description")
+ .duration(60)
+ .releaseDate(LocalDate.of(2022, 02, 23)).build();
+
+ assertThrows(ValidateException.class, () -> filmController.add(film));
+ film.setName("film1");
+ Film film1 = filmController.add(film);
+ assertEquals(1, filmController.getModelList().size());
+ film1.setName("FilmVasya");
+ filmController.update(film1);
+ assertEquals("FilmVasya", ((Film) filmController.getModelList().get(0)).getName());
+ }
+}
\ 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/UserControllerTest.java
new file mode 100644
index 0000000..1ae22ee
--- /dev/null
+++ b/src/test/java/ru/yandex/practicum/filmorate/controller/UserControllerTest.java
@@ -0,0 +1,37 @@
+package ru.yandex.practicum.filmorate.controller;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import ru.yandex.practicum.filmorate.exception.NotFoundException;
+import ru.yandex.practicum.filmorate.exception.ValidateException;
+import ru.yandex.practicum.filmorate.model.User;
+import ru.yandex.practicum.filmorate.service.ManageFriendsUserService;
+import ru.yandex.practicum.filmorate.storage.InMemoryUserStorage;
+
+import java.time.LocalDate;
+import java.util.HashMap;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class UserControllerTest {
+ private UserController userController;
+
+ @BeforeEach
+ void setUp() {
+ userController = new UserController(new ManageFriendsUserService(new InMemoryUserStorage(new HashMap<>())));
+ }
+
+ @Test
+ void add() throws ValidateException, NotFoundException {
+ User user = User.builder()
+ .email("my@email.ru")
+ .login("login1")
+ .birthday(LocalDate.of(1994, 6, 12)).build();
+
+ User user1 = userController.add(user);
+ assertEquals(1, userController.getModelList().size());
+ user1.setName("Vasya");
+ userController.update(user1);
+ assertEquals("Vasya", ((User) userController.getModelList().get(0)).getName());
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/ru/yandex/practicum/filmorate/managerTest/FilmManagerTest.java b/src/test/java/ru/yandex/practicum/filmorate/managerTest/FilmManagerTest.java
deleted file mode 100644
index b6e8fd6..0000000
--- a/src/test/java/ru/yandex/practicum/filmorate/managerTest/FilmManagerTest.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package ru.yandex.practicum.filmorate.managerTest;
-
-import org.junit.Test;
-import org.junit.jupiter.api.Assertions;
-
-
-import ru.yandex.practicum.filmorate.manager.FilmManager;
-import ru.yandex.practicum.filmorate.model.Film;
-
-import java.time.LocalDate;
-import java.util.ArrayList;
-import java.util.List;
-
-
-public class FilmManagerTest {
- FilmManager manager = new FilmManager();
- private final Film film = new Film(1, "Film", "Описание фильма",
- LocalDate.of(1995, 2, 2), 120);
- private final Film updatedFilm = new Film(2, "Drill",
- "Drill этого фильма",
- LocalDate.of(2000, 3, 1), 180);
-
- @Test
- public void addFilmTest() {
- manager.addFilm(film);
-
- Assertions.assertEquals(1, manager.getAllFilms().size());
- }
-
- @Test
- public void updateFilmTest() {
- manager.addFilm(film);
- manager.updateFilm(updatedFilm);
-
- Assertions.assertEquals("Drill этого фильма", updatedFilm.getDescription());
- Assertions.assertEquals(2, manager.getAllFilms().size());
- }
-
- @Test
- public void testGetFilmsList() {
- manager.addFilm(film);
- manager.addFilm(updatedFilm);
- List expectedList = new ArrayList<>(manager.getAllFilms().values());
- List actualList = new ArrayList<>();
- actualList.add(film);
- actualList.add(updatedFilm);
-
- Assertions.assertEquals(expectedList, actualList);
- }
-}
-
-
-
diff --git a/src/test/java/ru/yandex/practicum/filmorate/managerTest/UserManagerTest.java b/src/test/java/ru/yandex/practicum/filmorate/managerTest/UserManagerTest.java
deleted file mode 100644
index f98355a..0000000
--- a/src/test/java/ru/yandex/practicum/filmorate/managerTest/UserManagerTest.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package ru.yandex.practicum.filmorate.managerTest;
-
-import org.junit.Test;
-import org.junit.jupiter.api.Assertions;
-import ru.yandex.practicum.filmorate.manager.UserManager;
-import ru.yandex.practicum.filmorate.model.User;
-
-import java.time.LocalDate;
-import java.util.ArrayList;
-import java.util.List;
-
-public class UserManagerTest {
- UserManager manager = new UserManager();
- private final User user = new User(1, "di@mail.ru", "balda", "aa", LocalDate.of(1995, 1, 1));
- private final User updatedUser = new User(1, "xi@mail.ru", "nefritoviy", "sterzen", LocalDate.of(2000, 1, 1));
-
- @Test
- public void addUserTest() {
- manager.addUser(user);
-
- Assertions.assertEquals(1, manager.getAllUsers().size());
- }
-
- @Test
- public void updateFilmTest() {
- manager.addUser(user);
- manager.updateUser(updatedUser);
-
- Assertions.assertEquals("xi@mail.ru", updatedUser.getEmail());
- Assertions.assertEquals(user.getId(), updatedUser.getId());
- Assertions.assertEquals(1, manager.getAllUsers().size());
- }
-
- @Test
- public void testGetFilmsList() {
- manager.addUser(user);
- manager.addUser(updatedUser);
- List expectedList = new ArrayList<>(manager.getAllUsers().values());
- List actualList = new ArrayList<>();
- actualList.add(user);
- actualList.add(updatedUser);
-
- Assertions.assertEquals(expectedList, actualList);
- }
-}
diff --git a/src/test/java/ru/yandex/practicum/filmorate/service/FilmServiceTest.java b/src/test/java/ru/yandex/practicum/filmorate/service/FilmServiceTest.java
new file mode 100644
index 0000000..0f15249
--- /dev/null
+++ b/src/test/java/ru/yandex/practicum/filmorate/service/FilmServiceTest.java
@@ -0,0 +1,42 @@
+package ru.yandex.practicum.filmorate.service;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import ru.yandex.practicum.filmorate.exception.ValidateException;
+import ru.yandex.practicum.filmorate.model.Film;
+import ru.yandex.practicum.filmorate.storage.InMemoryFilmStorage;
+
+import java.time.LocalDate;
+import java.util.HashMap;
+
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+class FilmServiceTest {
+ private FilmService filmService;
+
+ @BeforeEach
+ void setUp() {
+ filmService = new FilmService(new InMemoryFilmStorage(new HashMap<>()));
+ }
+
+ @Test
+ void addFilm() {
+ Film film = Film.builder().description("description")
+ .duration(60)
+ .releaseDate(LocalDate.of(2022, 02, 23))
+ .build();
+
+ assertThrows(ValidateException.class, () -> filmService.addModel(film));
+ film.setName(" ");
+ assertThrows(ValidateException.class, () -> filmService.addModel(film));
+ film.setDescription(" wqeqwrwefsdgsdevygfghdfgsdrthdfhdfgsgsdgdsgdgfdfgdfggggggfdffhljhjlhkjlhiuhiulhjlknjhkjdsafjdfasofuawejflkasjfls;jfiasojfeiajs;fe;kasjdfksjfdiosjfisjfsidhgdfgskdjfksdjfjsif fjs kfj sdkfjas;lfd ;sjfkas");
+ film.setName("film1");
+ assertThrows(ValidateException.class, () -> filmService.addModel(film));
+ film.setDescription("description");
+ film.setReleaseDate(LocalDate.of(1895, 12, 25));
+ assertThrows(ValidateException.class, () -> filmService.addModel(film));
+ film.setReleaseDate(LocalDate.of(2022, 02, 23));
+ film.setDuration(-1);
+ assertThrows(ValidateException.class, () -> filmService.addModel(film));
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/ru/yandex/practicum/filmorate/service/ManageFriendsToServiceTest.java b/src/test/java/ru/yandex/practicum/filmorate/service/ManageFriendsToServiceTest.java
new file mode 100644
index 0000000..9bc06c2
--- /dev/null
+++ b/src/test/java/ru/yandex/practicum/filmorate/service/ManageFriendsToServiceTest.java
@@ -0,0 +1,51 @@
+package ru.yandex.practicum.filmorate.service;
+
+import org.junit.jupiter.api.Test;
+import ru.yandex.practicum.filmorate.exception.NotFoundException;
+import ru.yandex.practicum.filmorate.exception.ValidateException;
+import ru.yandex.practicum.filmorate.model.FriendsTo;
+import ru.yandex.practicum.filmorate.model.User;
+import ru.yandex.practicum.filmorate.storage.InMemoryUserStorage;
+import ru.yandex.practicum.filmorate.storage.StorageUser;
+
+import java.time.LocalDate;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+public class ManageFriendsToServiceTest {
+ private final StorageUser userStorage = new InMemoryUserStorage(new HashMap<>());
+ private final UserService userService = new UserService(userStorage);
+ private final ManageFriendsUserService manageFriendsUserService = new ManageFriendsUserService(userStorage);
+
+ @Test
+ public void addFriend() throws ValidateException, NotFoundException {
+ User user = User.builder()
+ .birthday(LocalDate.of(1994, 6, 12))
+ .email("my@email.ru")
+ .login("vasyaPupkin")
+ .friends(new ArrayList<>())
+ .build();
+
+ User user1 = User.builder()
+ .birthday(LocalDate.of(1994, 6, 12))
+ .email("123my@email.ru")
+ .login("vasislisaPupkina")
+ .friends(new ArrayList<>())
+ .build();
+
+ User user3 = User.builder()
+ .birthday(LocalDate.of(1994, 6, 12))
+ .email("123@email.ru")
+ .login("vasisPupkin")
+ .friends(new ArrayList<>())
+ .build();
+
+ manageFriendsUserService.addToFriends(new FriendsTo(userService.addModel(user3).getId(), userService.addModel(user).getId()));
+ manageFriendsUserService.addToFriends(new FriendsTo(userService.addModel(user1).getId(), user3.getId()));
+
+
+ manageFriendsUserService.addToFriends(new FriendsTo(userService.addModel(user1).getId(), userService.addModel(user).getId()));
+ System.out.println(user1.getFriends());
+ System.out.println(manageFriendsUserService.getCommonFriends(new FriendsTo(user.getId(), user1.getId())));
+ }
+}
diff --git a/src/test/java/ru/yandex/practicum/filmorate/storage/FilmDBStorageTest.java b/src/test/java/ru/yandex/practicum/filmorate/storage/FilmDBStorageTest.java
new file mode 100644
index 0000000..ffa3eb6
--- /dev/null
+++ b/src/test/java/ru/yandex/practicum/filmorate/storage/FilmDBStorageTest.java
@@ -0,0 +1,85 @@
+package ru.yandex.practicum.filmorate.storage;
+
+import lombok.RequiredArgsConstructor;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.dao.EmptyResultDataAccessException;
+import ru.yandex.practicum.filmorate.model.*;
+
+import java.time.LocalDate;
+import java.util.Collections;
+import java.util.Objects;
+import java.util.TreeSet;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+@SpringBootTest
+@AutoConfigureTestDatabase
+@RequiredArgsConstructor(onConstructor_ = @Autowired)
+class FilmDBStorageTest {
+
+ private final FilmDBStorage storageFilm;
+ private final UserDBStorage userDBStorage;
+ TreeSet genreTreeSet = new TreeSet<>();
+ TreeSet likes = new TreeSet<>();
+
+ User user = User.builder().name("user").email("user@mail.ru").login("userLogin").birthday(LocalDate.of(1993, 2, 12)).build();
+ Film film = Film.builder().name("name").genres(genreTreeSet).description("description")
+ .releaseDate(LocalDate.of(2021, 3, 23)).duration(45).mpa(new Mpa(1))
+ .likes(likes).build();
+ Film film2 = Film.builder().name("name2").genres(genreTreeSet).description("description2")
+ .releaseDate(LocalDate.of(2021, 3, 23)).duration(45).mpa(new Mpa(1))
+ .likes(likes).build();
+
+
+ @Test
+ public void save() {
+ Collections.addAll(genreTreeSet, new Genre(1, null), new Genre(3, null));
+ Collections.addAll(likes, 1);
+ userDBStorage.save(user);
+ storageFilm.save(film);
+ storageFilm.save(film2);
+
+ Film filmGet = storageFilm.get(1);
+
+ assertEquals(1, filmGet.getId());
+ assertEquals(2, storageFilm.get(2).getId());
+ storageFilm.delete(1);
+ assertThrows(EmptyResultDataAccessException.class, () -> storageFilm.get(1));
+ assertTrue(storageFilm.get(2).getLikes().stream().anyMatch(e -> Objects.equals(e, 1)));
+ storageFilm.removeIdFromIdSet(new FilmLikes(2, 1));
+ assertEquals(0, storageFilm.get(2).getLikes().size());
+
+ }
+
+ @Test
+ public void update() {
+ storageFilm.save(film);
+
+ Film updateWithName = Film.builder().name("nameUpdate").genres(genreTreeSet).description("descriptionUpdate")
+ .releaseDate(LocalDate.of(2021, 3, 23)).duration(45).mpa(new Mpa(1))
+ .likes(likes).id(1).build();
+
+ storageFilm.update(updateWithName);
+
+ Film updateGet = storageFilm.get(1);
+
+ assertEquals(updateGet.getName(), "nameUpdate");
+
+ Collections.addAll(genreTreeSet, new Genre(2, null));
+
+ storageFilm.update(updateWithName);
+ assertTrue(storageFilm.get(1).getGenres().stream().anyMatch(e -> Objects.equals(e.getId(), 2)));
+ }
+
+ @Test
+ void getMpaGenres() {
+ assertEquals(1, storageFilm.getMpa(1).getId());
+ assertEquals(5, storageFilm.getMpaList().size());
+ assertEquals(1, storageFilm.getGenreById(1).getId());
+ assertEquals(6, storageFilm.getGenreList().size());
+
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/ru/yandex/practicum/filmorate/storage/UserDBStorageTest.java b/src/test/java/ru/yandex/practicum/filmorate/storage/UserDBStorageTest.java
new file mode 100644
index 0000000..b084625
--- /dev/null
+++ b/src/test/java/ru/yandex/practicum/filmorate/storage/UserDBStorageTest.java
@@ -0,0 +1,55 @@
+package ru.yandex.practicum.filmorate.storage;
+
+import lombok.RequiredArgsConstructor;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.dao.EmptyResultDataAccessException;
+import ru.yandex.practicum.filmorate.model.User;
+
+import java.time.LocalDate;
+import java.util.Optional;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+@SpringBootTest
+@AutoConfigureTestDatabase
+@RequiredArgsConstructor(onConstructor_ = @Autowired)
+class UserDBStorageTest {
+
+ private final UserDBStorage userStorage;
+
+ @Test
+ public void save() {
+ User user1 = User.builder()
+ .name("test")
+ .email("testEmail")
+ .login("testlogin")
+ .birthday(LocalDate.of(1994, 2, 1))
+ .build();
+
+ userStorage.save(user1);
+ Optional userOptional = Optional.of(userStorage.get(1));
+
+ assertThat(userOptional)
+ .isPresent()
+ .hasValueSatisfying(user ->
+ assertThat(user).hasFieldOrPropertyWithValue("id", 1)
+ );
+
+ user1.setId(1);
+ user1.setName("Update");
+ userStorage.update(user1);
+
+ User userUp = userStorage.get(1);
+ assertEquals("Update", userUp.getName());
+
+ userStorage.delete(1);
+ assertThrows(EmptyResultDataAccessException.class, () -> userStorage.get(1));
+
+ }
+
+}
\ No newline at end of file