diff --git a/README.md b/README.md index 2cf454a..5d153e4 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,4 @@ # java-filmorate Template repository for Filmorate project. + +![](img.png) \ No newline at end of file diff --git a/img.png b/img.png new file mode 100644 index 0000000..9f7fdec Binary files /dev/null and b/img.png differ diff --git a/pom.xml b/pom.xml index 439601a..a17849b 100644 --- a/pom.xml +++ b/pom.xml @@ -45,6 +45,15 @@ junit test + + org.springframework.boot + spring-boot-starter-data-jdbc + + + com.h2database + h2 + runtime + 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 8fc3d90..dd94f86 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java @@ -3,14 +3,13 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; +import ru.yandex.practicum.filmorate.exception.ValidationException; import ru.yandex.practicum.filmorate.model.Film; import ru.yandex.practicum.filmorate.service.FilmService; import ru.yandex.practicum.filmorate.service.UserService; -import ru.yandex.practicum.filmorate.sortage.FilmStorage; -import ru.yandex.practicum.filmorate.exception.ValidationException; import javax.validation.Valid; -import java.util.Collection; +import java.util.List; @Slf4j @RestController @@ -26,7 +25,7 @@ public FilmController(FilmService filmService, UserService userService) { } @GetMapping - public Collection findAll() { + public List findAll() { return filmService.findAll(); } @@ -42,8 +41,8 @@ public Collection findAll() { @PutMapping("{id}/like/{userId}") public void addLike(@PathVariable Integer id, - @PathVariable Integer userId) throws ValidationException { - filmService.addLike(filmService.findById(id), userService.findById(userId)); + @PathVariable Integer userId) { + filmService.addLike(id, userId); } @DeleteMapping("{id}/like/{userId}") @@ -53,10 +52,10 @@ public void deleteLike(@PathVariable Integer id, } @GetMapping("/popular") - public Collection getPopularFilms( + public List getPopularFilms( @RequestParam(defaultValue = "10",required = false) Integer count ) { - return filmService.getPopularFilms(filmService.findAll(), count); + return filmService.getPopularFilms(count); } @GetMapping("{id}") diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/GenreController.java b/src/main/java/ru/yandex/practicum/filmorate/controller/GenreController.java new file mode 100644 index 0000000..6bda364 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/GenreController.java @@ -0,0 +1,32 @@ +package ru.yandex.practicum.filmorate.controller; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +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.model.Genre; +import ru.yandex.practicum.filmorate.service.GenreService; + +import javax.validation.constraints.NotNull; +import java.util.List; + +@Slf4j +@RestController +@RequestMapping("/genres") +public class GenreController { + + @Autowired + GenreService genreService; + + @GetMapping("{id}") + public Genre findById(@NotNull @PathVariable Integer id){ + return genreService.findById(id); + } + + @GetMapping + public List findAll() { + return genreService.findAll(); + } +} 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..7a9cff5 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/MpaController.java @@ -0,0 +1,33 @@ +package ru.yandex.practicum.filmorate.controller; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +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.model.MpaRating; +import ru.yandex.practicum.filmorate.service.MpaService; + +import javax.validation.constraints.NotNull; +import java.util.List; + +@Slf4j +@RestController +@RequestMapping("/mpa") +public class MpaController { + + @Autowired + MpaService mpaService; + + @GetMapping("{id}") + public MpaRating findById(@NotNull @PathVariable Integer id) { + return mpaService.findById(id); + } + + @GetMapping() + public List findAll() { + return mpaService.findAll(); + } + +} 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 59ba687..dbb886a 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java @@ -4,9 +4,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import ru.yandex.practicum.filmorate.model.User; -import ru.yandex.practicum.filmorate.service.UserService; import ru.yandex.practicum.filmorate.exception.ValidationException; -import ru.yandex.practicum.filmorate.sortage.UserStorage; +import ru.yandex.practicum.filmorate.service.UserService; import javax.validation.Valid; import java.util.Collection; @@ -75,7 +74,7 @@ public List commonFriends(@PathVariable Integer id, @DeleteMapping public @Valid void delete(@Valid @RequestBody User user) throws ValidationException { - userService.deleteUser(user); + userService.deleteUser(user.getUserId()); } } 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 12a9553..f302192 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/model/Film.java +++ b/src/main/java/ru/yandex/practicum/filmorate/model/Film.java @@ -1,18 +1,23 @@ package ru.yandex.practicum.filmorate.model; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; import lombok.Data; -import org.springframework.validation.annotation.Validated; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; -import java.time.Duration; import java.time.LocalDate; -import java.util.HashSet; -import java.util.Set; +import java.util.List; import javax.validation.constraints.*; @Data +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode public class Film { - private int id; + @JsonProperty("id") + private int filmId; @NotBlank(message = "Имя не может быть пустым!") private String name; @NotBlank(message = "Описание не может быть пустым!") @@ -21,14 +26,30 @@ public class Film { @Past(message = "Некорректная дата релиза") private LocalDate releaseDate; private long duration; - private Set likes; + //private Set likes; + private int rate; + private long likes; + @JsonProperty("genres") + private List genre; + @NotNull + @JsonProperty("mpa") + private MpaRating mpa; - public Film(int id, String name, String description, LocalDate releaseDate, long duration) { - this.id = id; + public Film(int filmId, String name, String description, LocalDate releaseDate, long duration, int rate, MpaRating mpa) { + this.filmId = filmId; + this.name = name; + this.description = description; + this.releaseDate = releaseDate; + this.duration = duration; + this.rate = rate; + this.mpa = mpa; + } + + public Film(int filmId, String name, String description, LocalDate releaseDate, long duration, int rate) { + this.filmId = filmId; this.name = name; this.description = description; this.releaseDate = releaseDate; this.duration = duration; - this.likes = new HashSet<>(); } } diff --git a/src/main/java/ru/yandex/practicum/filmorate/model/FriendshipStatus.java b/src/main/java/ru/yandex/practicum/filmorate/model/FriendshipStatus.java new file mode 100644 index 0000000..c1ed4ab --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/model/FriendshipStatus.java @@ -0,0 +1,6 @@ +package ru.yandex.practicum.filmorate.model; + +public enum FriendshipStatus { + CONFIRMED, + UNCONFIRMED +} 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..4211d7b --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/model/Genre.java @@ -0,0 +1,13 @@ +package ru.yandex.practicum.filmorate.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +@Data +public class Genre { + @JsonProperty("id") + private Integer id; + + @JsonProperty("name") + private String name; +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/model/GenreEnum.java b/src/main/java/ru/yandex/practicum/filmorate/model/GenreEnum.java new file mode 100644 index 0000000..8f53192 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/model/GenreEnum.java @@ -0,0 +1,30 @@ +package ru.yandex.practicum.filmorate.model; + +public enum GenreEnum { + COMEDY(1, "Комедия"), + DRAMA(2,"Драма"), + CARTOON(3,"Мультфильм"), + THRILLER(4,"Триллер"), + DOCUMENTARY(5,"Документальный"), + ACTION(6,"Экшн"); + + private int id; + + private String name; + + GenreEnum(int aId, String aName) { + id = aId; + name = aName; + } + + public static String getNameById(int id) { + for (GenreEnum o : GenreEnum.values()) { + if (o.id == id) { + return o.name; + } + } + return ""; + } +} + + diff --git a/src/main/java/ru/yandex/practicum/filmorate/model/LikeFilms.java b/src/main/java/ru/yandex/practicum/filmorate/model/LikeFilms.java new file mode 100644 index 0000000..93f4580 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/model/LikeFilms.java @@ -0,0 +1,15 @@ +package ru.yandex.practicum.filmorate.model; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode +public class LikeFilms { + + private Integer filmId; +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/model/MpaRating.java b/src/main/java/ru/yandex/practicum/filmorate/model/MpaRating.java new file mode 100644 index 0000000..8830575 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/model/MpaRating.java @@ -0,0 +1,16 @@ +package ru.yandex.practicum.filmorate.model; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +@Data +public class MpaRating { + @JsonProperty("id") + private int id; + + @JsonProperty("name") + @JsonIgnore + private String name; + +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/model/MpaRatingEnum.java b/src/main/java/ru/yandex/practicum/filmorate/model/MpaRatingEnum.java new file mode 100644 index 0000000..845a480 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/model/MpaRatingEnum.java @@ -0,0 +1,27 @@ +package ru.yandex.practicum.filmorate.model; + +public enum MpaRatingEnum { + G(1, "G"), + PG(2, "PG"), + PG13(3, "PG-13"), + R(4, "R"), + NC17(5, "NC-17"); + + private int id; + + private String name; + + MpaRatingEnum(int id, String name) { + this.id = id; + this.name = name; + } + + public static String getNameById(int id) { + for (MpaRatingEnum e : MpaRatingEnum.values()) { + if (e.id == id) { + return e.name; + } + } + return null; + } +} 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 44938df..a0a6a5d 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/model/User.java +++ b/src/main/java/ru/yandex/practicum/filmorate/model/User.java @@ -1,8 +1,12 @@ package ru.yandex.practicum.filmorate.model; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonRootName; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import lombok.AllArgsConstructor; import lombok.Data; import lombok.EqualsAndHashCode; -import org.springframework.validation.annotation.Validated; +import lombok.NoArgsConstructor; import javax.validation.constraints.*; import java.time.LocalDate; @@ -11,8 +15,11 @@ @Data @EqualsAndHashCode +@AllArgsConstructor +@NoArgsConstructor public class User { - private int id; + @JsonProperty("id") + private int userId; @NotBlank @Email(message = "Некоррктный email!") private String email; @@ -23,14 +30,23 @@ public class User { @Past(message = "Дата рождения не может быть в будущем!") private LocalDate birthday; private Set friends; + private FriendshipStatus friendshipStatus; - public User(int id, String email, String login, String name, LocalDate birthday) { - this.id = id; + public User(int userId, String email, String login, String name, LocalDate birthday, FriendshipStatus friendshipStatus) { + this.userId = userId; this.email = email; this.login = login; this.name = name; this.birthday = birthday; this.friends = new HashSet<>(); + this.friendshipStatus = friendshipStatus; } + public User(int userId, String email, String login, String name, LocalDate birthday) { + this.userId = userId; + this.email = email; + this.login = login; + this.name = name; + this.birthday = birthday; + } } diff --git a/src/main/java/ru/yandex/practicum/filmorate/model/mapper/FilmRowMapper.java b/src/main/java/ru/yandex/practicum/filmorate/model/mapper/FilmRowMapper.java new file mode 100644 index 0000000..227971e --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/model/mapper/FilmRowMapper.java @@ -0,0 +1,22 @@ +package ru.yandex.practicum.filmorate.model.mapper; + +import org.springframework.jdbc.core.RowMapper; +import ru.yandex.practicum.filmorate.model.Film; +import ru.yandex.practicum.filmorate.model.User; + +import java.sql.ResultSet; +import java.sql.SQLException; + +public class FilmRowMapper implements RowMapper { + + @Override + public Film mapRow(ResultSet rs, int rowNum) throws SQLException { + Film film = new Film(rs.getInt("FILM_ID"), + rs.getString("NAME"), + rs.getString("DESCRIPTION"), + rs.getDate("RELEASE_DATE").toLocalDate(), + rs.getLong("DURATION"), + rs.getInt("RATE")); + return film; + } +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/model/mapper/LikeFilmsRowMapper.java b/src/main/java/ru/yandex/practicum/filmorate/model/mapper/LikeFilmsRowMapper.java new file mode 100644 index 0000000..2a0cfa7 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/model/mapper/LikeFilmsRowMapper.java @@ -0,0 +1,16 @@ +package ru.yandex.practicum.filmorate.model.mapper; + +import org.springframework.jdbc.core.RowMapper; +import ru.yandex.practicum.filmorate.model.LikeFilms; + +import java.sql.ResultSet; +import java.sql.SQLException; + +public class LikeFilmsRowMapper implements RowMapper { + + @Override + public LikeFilms mapRow(ResultSet rs, int rowNum) throws SQLException { + LikeFilms likeFilms = new LikeFilms(rs.getInt("FILM_ID")); + return likeFilms; + } +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/model/mapper/UserRowMapper.java b/src/main/java/ru/yandex/practicum/filmorate/model/mapper/UserRowMapper.java new file mode 100644 index 0000000..08129be --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/model/mapper/UserRowMapper.java @@ -0,0 +1,22 @@ +package ru.yandex.practicum.filmorate.model.mapper; + +import org.springframework.jdbc.core.RowMapper; +import ru.yandex.practicum.filmorate.model.User; + + +import javax.swing.tree.TreePath; +import java.sql.ResultSet; +import java.sql.SQLException; + +public class UserRowMapper implements RowMapper { + + @Override + public User mapRow(ResultSet rs, int rowNum) throws SQLException { + User user = new User(rs.getInt("USER_ID"), + rs.getString("EMAIL"), + rs.getString("LOGIN"), + rs.getString("NAME"), + rs.getDate("BIRTHDAY").toLocalDate()); + return user; + } +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java b/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java index 27b410d..c7d8a77 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java +++ b/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java @@ -4,27 +4,31 @@ import org.springframework.stereotype.Service; import ru.yandex.practicum.filmorate.exception.FilmIdNotValidation; import ru.yandex.practicum.filmorate.exception.FilmNotExistsException; +import ru.yandex.practicum.filmorate.exception.UserIdNotValidation; import ru.yandex.practicum.filmorate.model.Film; import ru.yandex.practicum.filmorate.model.User; import ru.yandex.practicum.filmorate.sortage.FilmStorage; import ru.yandex.practicum.filmorate.exception.ValidationException; +import ru.yandex.practicum.filmorate.sortage.LikeFilmDbStorage; import java.time.LocalDate; -import java.util.Collection; -import java.util.Set; -import java.util.stream.Collectors; + +import java.util.List; + @Service public class FilmService { FilmStorage filmStorage; + LikeFilmDbStorage likeFilmDbStorage; LocalDate minReleaseDate = LocalDate.of(1895, 12, 28); @Autowired - public FilmService (FilmStorage filmStorage) { + public FilmService (FilmStorage filmStorage, LikeFilmDbStorage likeFilmDbStorage) { this.filmStorage = filmStorage; + this.likeFilmDbStorage = likeFilmDbStorage; } - public Collection findAll() { + public List findAll() { return filmStorage.findAll(); } @@ -32,7 +36,7 @@ public Film create(Film film) throws ValidationException { if (film.getReleaseDate().isBefore(minReleaseDate) || film.getDuration() < 0) { throw new FilmNotExistsException("Некорректные данные! Дата релиза должна быть позднее 28.12.1985 года!"); } - if (film.getId() < 0) { + if (film.getFilmId() < 0) { throw new FilmIdNotValidation("Id не может быть отрицательный!"); } return filmStorage.create(film); @@ -42,39 +46,46 @@ public Film put(Film film) throws ValidationException { if (film.getReleaseDate().isBefore(minReleaseDate) || film.getDuration() < 0) { throw new FilmNotExistsException("" + "Некорректные данные!"); } - if (film.getId() < 0) { + if (film.getFilmId() < 0) { throw new FilmIdNotValidation("Id не может быть отрицательный!"); } return filmStorage.put(film); } - public Film findById(Integer id) throws ValidationException { - if (!filmStorage.findAllId().contains(id)) { - throw new FilmIdNotValidation("Некорректные данные! Проверьте логин или email"); + public Film findById(Integer id) { + if (id < 0) { + throw new FilmIdNotValidation("Id не может быть отрицательный!"); } return filmStorage.findFilm(id); } - public void addLike(Film film, User user) { - Set filmLikes = film.getLikes(); - filmLikes.add(user.getId()); - film.setLikes(filmLikes); + public void addLike(int filmId, int userId) { + if(userId < 0) { + throw new UserIdNotValidation("Id не может быть отрицательный!"); + } + if(filmId < 0) { + throw new FilmIdNotValidation("Id не может быть отрицательный!"); + } + + likeFilmDbStorage.addLike(userId, filmId); } public void deleteLike(Film film, User user) { - Set filmLikes = film.getLikes(); - filmLikes.remove(user.getId()); - film.setLikes(filmLikes); + if(user.getUserId() < 0) { + throw new UserIdNotValidation("Id не может быть отрицательный!"); + } + if(film.getFilmId() < 0) { + throw new FilmIdNotValidation("Id не может быть отрицательный!"); + } + likeFilmDbStorage.deleteLike(user.getUserId(), film.getFilmId()); } - public Collection getPopularFilms(Collection listFilms, Integer count) { - return listFilms.stream() - .sorted((o1, o2) -> o2.getLikes().size() - o1.getLikes().size()) - .limit(count).collect(Collectors.toList()); + public List getPopularFilms(Integer count) { + return likeFilmDbStorage.getPopularFilms(count); } public void DeleteFilm(Film film) { - filmStorage.deleteFilm(film); + filmStorage.deleteFilm(film.getFilmId()); } diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/GenreService.java b/src/main/java/ru/yandex/practicum/filmorate/service/GenreService.java new file mode 100644 index 0000000..14f2517 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/service/GenreService.java @@ -0,0 +1,27 @@ +package ru.yandex.practicum.filmorate.service; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import ru.yandex.practicum.filmorate.exception.FilmIdNotValidation; +import ru.yandex.practicum.filmorate.model.Genre; +import ru.yandex.practicum.filmorate.sortage.GenreDbStorage; + +import java.util.List; + +@Service +public class GenreService { + + @Autowired + GenreDbStorage genreDbStorage; + + public Genre findById(Integer id) { + if (id < 0) { + throw new FilmIdNotValidation("Id не может быть отрицательный!"); + } + return genreDbStorage.findById(id); + } + + public List findAll() { + return genreDbStorage.findAll(); + } +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/MpaService.java b/src/main/java/ru/yandex/practicum/filmorate/service/MpaService.java new file mode 100644 index 0000000..82ec953 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/service/MpaService.java @@ -0,0 +1,29 @@ +package ru.yandex.practicum.filmorate.service; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import ru.yandex.practicum.filmorate.exception.FilmIdNotValidation; +import ru.yandex.practicum.filmorate.model.MpaRating; +import ru.yandex.practicum.filmorate.sortage.MpaDbStorage; + +import java.util.List; + +@Service +public class MpaService { + + @Autowired + MpaDbStorage mpaDbStorage; + + public MpaRating findById(Integer id) { + if (id < 0) { + throw new FilmIdNotValidation("Id не может быть отрицательный!"); + } + return mpaDbStorage.findById(id); + } + + public List findAll() { + List mpaRatingList = mpaDbStorage.findAll(); + return mpaRatingList; + } + +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java b/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java index b87793e..da75679 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java +++ b/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java @@ -4,23 +4,25 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import ru.yandex.practicum.filmorate.exception.UserIdNotValidation; +import ru.yandex.practicum.filmorate.exception.ValidationException; import ru.yandex.practicum.filmorate.model.User; +import ru.yandex.practicum.filmorate.sortage.UserFriendDbStorage; import ru.yandex.practicum.filmorate.sortage.UserStorage; -import ru.yandex.practicum.filmorate.exception.ValidationException; -import java.util.ArrayList; import java.util.Collection; import java.util.List; -import java.util.Set; @Slf4j @Service public class UserService { UserStorage userStorage; + UserFriendDbStorage userFriendDbStorage; + @Autowired - public UserService (UserStorage userStorage) { + public UserService(UserStorage userStorage, UserFriendDbStorage userFriendDbStorage) { this.userStorage = userStorage; + this.userFriendDbStorage = userFriendDbStorage; } public Collection findAll() { @@ -31,7 +33,7 @@ public User put(User user) throws ValidationException { if(user.getLogin().contains(" ")) { throw new ValidationException("Некорректные данные! Логин содержит пробелы"); } - if(user.getId() <= 0) { + if(user.getUserId() <= 0) { throw new UserIdNotValidation("Id не может быть отрицательный!"); } if (user.getName().isEmpty() || user.getName() == null) { @@ -44,7 +46,7 @@ public User create(User user) throws ValidationException { if (user.getLogin().contains(" ") ) { throw new ValidationException("Некорректные данные! Проверьте логин или email"); } - if(user.getId() < 0) { + if(user.getUserId() < 0) { throw new UserIdNotValidation("Id не может быть отрицательный!"); } if (user.getName().isEmpty() || user.getName() == null) { @@ -54,61 +56,40 @@ public User create(User user) throws ValidationException { } public User findById(Integer id) throws UserIdNotValidation { - if (!userStorage.findAllId().contains(id)) { - throw new UserIdNotValidation("Некорректные данные! Такого id не существует"); - } return userStorage.findUser(id); } - public void addFriends(User user, User friends) { - - Set userList = user.getFriends(); - userList.add(friends.getId()); - user.setFriends(userList); - - Set friendsList = friends.getFriends(); - friendsList.add(user.getId()); - friends.setFriends(friendsList); + public void addFriends(User user, User friends) throws ValidationException { + if(!(findAll().contains(user) && findAll().contains(friends))) { + throw new ValidationException("Такого пользователя не существует"); + } + userFriendDbStorage.addFriend(user.getUserId(), friends.getUserId()); } public void deleteFriends(User user, User friends) { - - Set userList = user.getFriends(); - userList.remove(friends.getId()); - user.setFriends(userList); - - Set friendsList = friends.getFriends(); - friendsList.remove(user.getId()); - friends.setFriends(friendsList); + userFriendDbStorage.deleteFriends(user.getUserId(), friends.getUserId()); } public List findAllFriends(User user) { - List friends = new ArrayList<>(); - List friendsId = new ArrayList<>(user.getFriends()); - for (Integer integer : friendsId) { - friends.add(userStorage.findUser(integer)); + if (user == null) { + throw new UserIdNotValidation("Такого пользователя не существует"); } - return friends; + return userFriendDbStorage.findAllFriends(user.getUserId()); + } public List commonFriendsList(User user1, User user2) { - Set setFriendsUser1 = user1.getFriends(); - Set setFriendsUser2 = user2.getFriends(); - - List commonFriends = new ArrayList<>(); - - for (Integer l : setFriendsUser1) { - for (Integer s : setFriendsUser2) { - if (l.equals(s)) { - commonFriends.add(userStorage.findUser(l)); - } - } + if(user1.getUserId() < 0) { + throw new UserIdNotValidation("Id не может быть отрицательный!"); + } + if(user2.getUserId() < 0) { + throw new UserIdNotValidation("Id не может быть отрицательный!"); } - return commonFriends; + return userFriendDbStorage.commonFriends(user1.getUserId(), user2.getUserId()); } - public void deleteUser(User user) { - userStorage.deleteUser(user); + public void deleteUser(Integer id) { + userStorage.deleteUser(id); } } diff --git a/src/main/java/ru/yandex/practicum/filmorate/sortage/FilmDbStorage.java b/src/main/java/ru/yandex/practicum/filmorate/sortage/FilmDbStorage.java new file mode 100644 index 0000000..1407cfc --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/sortage/FilmDbStorage.java @@ -0,0 +1,164 @@ +package ru.yandex.practicum.filmorate.sortage; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.jdbc.support.GeneratedKeyHolder; +import org.springframework.jdbc.support.KeyHolder; +import org.springframework.stereotype.Service; +import ru.yandex.practicum.filmorate.model.*; +import ru.yandex.practicum.filmorate.model.mapper.FilmRowMapper; + +import java.sql.*; +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.stream.Collectors; + + +@Slf4j +@Service +public class FilmDbStorage implements FilmStorage{ + + private final JdbcTemplate jdbcTemplate; + + @Autowired + public FilmDbStorage(JdbcTemplate jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + } + + + @Override + public List findAll() { + String sqlQuery = "select * from FILMS"; + return jdbcTemplate.query(sqlQuery, new FilmRowMapper()); + } + + @Override + public Film create(Film film) { + String sqlQuery = "insert into FILMS (NAME, DESCRIPTION, RELEASE_DATE, DURATION) values (?,?,?,?)"; + + KeyHolder keyHolder = new GeneratedKeyHolder(); + jdbcTemplate.update(connection -> { + PreparedStatement stmt = connection.prepareStatement(sqlQuery, new String[]{"FILM_ID"}); + stmt.setString(1, film.getName()); + stmt.setString(2, film.getDescription()); + stmt.setLong(4, film.getDuration()); + final LocalDate releaseDate = film.getReleaseDate(); + if (releaseDate == null) { + stmt.setNull(3, Types.DATE); + } else { + stmt.setDate(3, Date.valueOf(releaseDate)); + } + return stmt; + }, keyHolder); + film.setFilmId(keyHolder.getKey().intValue()); + List genre = film.getGenre(); + if (genre != null) { + genre.forEach(g -> jdbcTemplate.update("INSERT INTO GENRE_FILM values (?,?)", film.getFilmId(), g.getId())); + } + MpaRating mpa = film.getMpa(); + if (mpa != null) { + jdbcTemplate.update("INSERT INTO MPA_FILMS values (?,?)",mpa.getId(), film.getFilmId()); + } + + return film; + } + + @Override + public Film put(Film film) { + String sqlQuery = "update FILMS set " + + "NAME = ?, DESCRIPTION = ?, RELEASE_DATE = ?, DURATION = ? " + + "where FILM_ID = ?"; + jdbcTemplate.update(sqlQuery + , film.getName() + , film.getDescription() + , film.getReleaseDate() + , film.getDuration() + , film.getFilmId()); + if (film.getMpa() != null) { + jdbcTemplate.update("update mpa_films set mpa_id = ? where film_id = ?", + film.getMpa().getId(), film.getFilmId()); + } + + if (film.getGenre() != null && !film.getGenre().isEmpty()) { + film.getGenre().forEach(g -> { + List integers = jdbcTemplate.query("select film_id from genre_film where film_id = ? and genre_id = ?", new RowMapper() { + @Override + public Integer mapRow(ResultSet rs, int rowNum) throws SQLException { + return rs.getInt("FILM_ID"); + } + }, film.getFilmId(), g.getId()); + if (integers.isEmpty()) { +// jdbcTemplate.update("delete from genre_film where film_id = ?", film.getFilmId()); + jdbcTemplate.update("insert into genre_film values(?,?)",film.getFilmId(), g.getId()); + } else { + jdbcTemplate.update("update genre_film set genre_id = ? where film_id = ? and genre_id = ?", + g.getId(), film.getFilmId(), g.getId()); + }}); + List genreIds = film.getGenre().stream().map(Genre::getId).collect(Collectors.toList()); + List forDelInts = getGenre(genreIds); + forDelInts.forEach(i -> { + jdbcTemplate.update("delete from genre_film where film_id = ? and genre_id = ?", film.getFilmId(), i); + }); + + + } else if (film.getGenre() != null && film.getGenre().isEmpty()) { + jdbcTemplate.update("delete from genre_film where film_id = ?", film.getFilmId()); + } + + return findFilm(film.getFilmId()); + } + + private List getGenre(List genreIds) { + List genres = new ArrayList<>(List.of(1, 2, 3, 4, 5, 6)); + genres.removeAll(genreIds); + return genres; + } + + @Override + public Film findFilm(Integer id) { + final String sqlQuery = "select * from FILMS where FILM_ID = ?"; + final List findFilms = jdbcTemplate.query(sqlQuery, new FilmRowMapper(), id); + if (findFilms.isEmpty()) { + throw new NoSuchElementException(); + } + Film film = findFilms.get(0); + List query = jdbcTemplate.query("select MPA_ID from MPA_FILMS WHERE FILM_ID = ?", + (rs, rowNum) -> rs.getInt("MPA_ID"), film.getFilmId()); + + MpaRating mpa = new MpaRating(); + film.setMpa(mpa); + + if (query.isEmpty()) { + return film; + } + + int mpaId = query.get(0); + mpa.setId(mpaId); + mpa.setName(MpaRatingEnum.getNameById(mpaId)); + + List genreList = new ArrayList<>(); + film.setGenre(genreList); + List genreId = jdbcTemplate.query("select genre_id from genre_film where film_id = ?", + (rs, rowNum) -> rs.getInt("GENRE_ID"), + film.getFilmId()); + genreId.forEach(g -> { + Genre genre = new Genre(); + genre.setId(g); + genre.setName(GenreEnum.getNameById(g)); + genreList.add(genre); + }); + return film; + } + + @Override + public void deleteFilm(Integer id) { + String sqlQuery = "DELETE FROM FILMS WHERE film_id = ?"; + jdbcTemplate.update(sqlQuery, id); + } + + +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/sortage/FilmStorage.java b/src/main/java/ru/yandex/practicum/filmorate/sortage/FilmStorage.java index 885ba1d..7974386 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/sortage/FilmStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/sortage/FilmStorage.java @@ -1,23 +1,30 @@ package ru.yandex.practicum.filmorate.sortage; +import org.springframework.data.relational.core.sql.In; import ru.yandex.practicum.filmorate.model.Film; import ru.yandex.practicum.filmorate.exception.ValidationException; +import ru.yandex.practicum.filmorate.model.User; +import javax.naming.InsufficientResourcesException; import java.util.Collection; import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; public interface FilmStorage { - Collection findAll(); + List findAll(); Film create(Film film) throws ValidationException; Film put(Film film) throws ValidationException; - List findAllId(); + //List findAllId(); Film findFilm(Integer id); - void deleteFilm(Film film); + void deleteFilm(Integer id); + + } diff --git a/src/main/java/ru/yandex/practicum/filmorate/sortage/GenreDbStorage.java b/src/main/java/ru/yandex/practicum/filmorate/sortage/GenreDbStorage.java new file mode 100644 index 0000000..1585a78 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/sortage/GenreDbStorage.java @@ -0,0 +1,38 @@ +package ru.yandex.practicum.filmorate.sortage; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.stereotype.Service; +import ru.yandex.practicum.filmorate.model.Genre; +import ru.yandex.practicum.filmorate.model.GenreEnum; + +import java.util.List; + +@Slf4j +@Service +public class GenreDbStorage { + @Autowired + JdbcTemplate jdbcTemplate; + + public Genre findById(int id) { + List genres = jdbcTemplate.query("select * from genre where genre_id = ?", (rs, rowNum) -> { + Genre genre = new Genre(); + genre.setId(rs.getInt("GENRE_ID")); + genre.setName(GenreEnum.getNameById(genre.getId())); + return genre; + }, id); + return genres.size() != 1 ? new Genre() : genres.get(0); + } + + public List findAll() { + List genres = jdbcTemplate.query("select genre_id from genre", + (rs, rowNum) -> { + Genre genre = new Genre(); + genre.setId(rs.getInt("GENRE_ID")); + genre.setName(GenreEnum.getNameById(genre.getId())); + return genre; + }); + return genres; + } +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/sortage/InMemoryFilmStorage.java b/src/main/java/ru/yandex/practicum/filmorate/sortage/InMemoryFilmStorage.java deleted file mode 100644 index 4d9d8b4..0000000 --- a/src/main/java/ru/yandex/practicum/filmorate/sortage/InMemoryFilmStorage.java +++ /dev/null @@ -1,55 +0,0 @@ -package ru.yandex.practicum.filmorate.sortage; - -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; -import ru.yandex.practicum.filmorate.model.Film; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; - - -@Slf4j -@Component -public class InMemoryFilmStorage implements FilmStorage{ - private final HashMap films = new HashMap<>(); - - - @Override - public Collection findAll() { - log.debug("Текущее количество фильмов: {}", films.size()); - return films.values(); - } - - @Override - public Film create(Film film) { - log.debug("Добавлен фильм: {}", film.getName()); - if (film.getId() == 0) { - film.setId(films.size() + 1); - films.put(film.getId(), film); - } else { - films.put(film.getId(), film); - } - return film; - } - - @Override - public Film put(Film film) { - films.put(film.getId(),film); - log.debug("Изменен фильм: {}", film.getName()); - return film; - } - - @Override - public List findAllId() { - return new ArrayList<>(films.keySet()); - } - - @Override - public Film findFilm(Integer id) { - return films.get(id); - } - - -} diff --git a/src/main/java/ru/yandex/practicum/filmorate/sortage/InMemoryUserStorage.java b/src/main/java/ru/yandex/practicum/filmorate/sortage/InMemoryUserStorage.java deleted file mode 100644 index 966bf35..0000000 --- a/src/main/java/ru/yandex/practicum/filmorate/sortage/InMemoryUserStorage.java +++ /dev/null @@ -1,44 +0,0 @@ -package ru.yandex.practicum.filmorate.sortage; - -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; -import ru.yandex.practicum.filmorate.model.User; -import ru.yandex.practicum.filmorate.exception.ValidationException; - -import java.util.*; - -@Slf4j -@Component -public class InMemoryUserStorage implements UserStorage{ - private final HashMap users = new HashMap<>(); - - public Collection findAll() { - log.debug("Текущее количество юзеров: {}", users.size()); - return users.values(); - } - - public User put(User user) { - log.debug("Изменен пользователь с логином: {}", user.getLogin()); - users.put(user.getId(),user); - return user; - } - - public User create(User user) throws ValidationException { - log.debug("Добавлен пользователь с логином: {}", user.getLogin()); - if(user.getId() == 0) { - user.setId(users.size()+1); - } - users.put(user.getId(), user); - return user; - } - - public List findAllId() { - return new ArrayList<>(users.keySet()); - } - - public User findUser(Integer id) { - return users.get(id); - } - - -} diff --git a/src/main/java/ru/yandex/practicum/filmorate/sortage/LikeFilmDbStorage.java b/src/main/java/ru/yandex/practicum/filmorate/sortage/LikeFilmDbStorage.java new file mode 100644 index 0000000..66bed68 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/sortage/LikeFilmDbStorage.java @@ -0,0 +1,51 @@ +package ru.yandex.practicum.filmorate.sortage; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.stereotype.Component; +import ru.yandex.practicum.filmorate.model.Film; +import ru.yandex.practicum.filmorate.model.MpaRating; +import ru.yandex.practicum.filmorate.model.MpaRatingEnum; +import ru.yandex.practicum.filmorate.model.mapper.FilmRowMapper; + +import java.util.Collection; +import java.util.List; + +@Component +public class LikeFilmDbStorage { + @Autowired + private JdbcTemplate jdbcTemplate; + + + + public boolean addLike(Integer userId, Integer filmId) { + int updatedRows = jdbcTemplate.update("INSERT INTO LIKE_FILMS values(?, ?)", userId, filmId); + return updatedRows > 0; + } + + + public void deleteLike(Integer userId, Integer filmId) { + final String sqlQuery = "DELETE FROM LIKE_FILMS where USER_ID = ? AND FILM_ID = ?"; + jdbcTemplate.update(sqlQuery, + userId, filmId); + } + + + public List getPopularFilms(Integer count) { + List films = jdbcTemplate.query("SELECT * FROM FILMS AS f " + + "LEFT JOIN LIKE_FILMS AS fl ON f.film_id = fl.film_id GROUP BY f.name ORDER BY COUNT(user_id) DESC LIMIT ?", + new FilmRowMapper(), count); + films.forEach(f -> { + List query = jdbcTemplate.query("select MPA_ID from MPA_FILMS WHERE FILM_ID = ?", + (rs, rowNum) -> rs.getInt("MPA_ID"), f.getFilmId()); + + MpaRating mpa = new MpaRating(); + f.setMpa(mpa); + + int mpaId = query.get(0); + mpa.setId(mpaId); + mpa.setName(MpaRatingEnum.getNameById(mpaId)); + }); + return films; + } +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/sortage/MpaDbStorage.java b/src/main/java/ru/yandex/practicum/filmorate/sortage/MpaDbStorage.java new file mode 100644 index 0000000..6d25d15 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/sortage/MpaDbStorage.java @@ -0,0 +1,39 @@ +package ru.yandex.practicum.filmorate.sortage; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.stereotype.Service; +import ru.yandex.practicum.filmorate.model.MpaRating; + +import java.util.List; + +@Slf4j +@Service +public class MpaDbStorage { + + @Autowired + JdbcTemplate jdbcTemplate; + + public MpaRating findById(int id) { + List mpaList = jdbcTemplate.query("select mpa_id, mpa_rating from mpa_rating where mpa_id = ?", + (rs, rowNum) -> { + MpaRating mpa = new MpaRating(); + mpa.setId(rs.getInt("MPA_ID")); + mpa.setName(rs.getString("MPA_RATING")); + return mpa; + }, id); + return mpaList.size() != 1 ? new MpaRating() : mpaList.get(0); + } + + public List findAll() { + List mpaRatingList = jdbcTemplate.query("select mpa_id, mpa_rating from mpa_rating", + (rs, rowNum) -> { + MpaRating mpa = new MpaRating(); + mpa.setId(rs.getInt("MPA_ID")); + mpa.setName(rs.getString("MPA_RATING")); + return mpa; + }); + return mpaRatingList; + } +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/sortage/UserDbStorage.java b/src/main/java/ru/yandex/practicum/filmorate/sortage/UserDbStorage.java new file mode 100644 index 0000000..31a39d2 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/sortage/UserDbStorage.java @@ -0,0 +1,88 @@ +package ru.yandex.practicum.filmorate.sortage; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.support.GeneratedKeyHolder; +import org.springframework.jdbc.support.KeyHolder; +import org.springframework.stereotype.Component; +import ru.yandex.practicum.filmorate.exception.UserIdNotValidation; +import ru.yandex.practicum.filmorate.model.User; +import ru.yandex.practicum.filmorate.model.mapper.UserRowMapper; + +import java.sql.Date; +import java.sql.PreparedStatement; +import java.sql.Types; +import java.time.LocalDate; +import java.util.Collection; +import java.util.List; + +@Slf4j +@Component +public class UserDbStorage implements UserStorage { + + private final JdbcTemplate jdbcTemplate; + + @Autowired + public UserDbStorage(JdbcTemplate jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + } + + public Collection findAll() { + //log.debug("Текущее количество юзеров: {}", users.size()); + String sqlQuery = "select * from USERS"; + return jdbcTemplate.query(sqlQuery, new UserRowMapper()); + } + + + public User put(User user) { + log.debug("Изменен пользователь с логином: {}", user.getLogin()); + String sqlQuery = "update USERS set " + + "EMAIL = ?, LOGIN = ?, NAME = ?, BIRTHDAY = ? " + + "where USER_ID = ?"; + jdbcTemplate.update(sqlQuery + , user.getEmail() + , user.getLogin() + , user.getName() + , user.getBirthday() + , user.getUserId()); + return user; + } + + public User findUser(Integer id) { + final String sqlQuery = "select * from USERS where USER_ID = ?"; + final List findUsers = jdbcTemplate.query(sqlQuery, new UserRowMapper(), id); + if(findUsers.isEmpty()){ + throw new UserIdNotValidation("Некорректный ID"); + } + return findUsers.get(0); + } + @Override + public void deleteUser(Integer id) { + String sqlQuery = ("DELETE FROM USERS WHERE user_id = ?"); + jdbcTemplate.update(sqlQuery, id); + } + + @Override + public User create(User user) { + String sqlQuery = "insert into USERS (EMAIL, LOGIN, NAME, BIRTHDAY) values (?,?,?,?)"; + + KeyHolder keyHolder = new GeneratedKeyHolder(); + jdbcTemplate.update(connection -> { + PreparedStatement stmt = connection.prepareStatement(sqlQuery, new String[]{"USER_ID"}); + stmt.setString(1, user.getEmail()); + stmt.setString(2, user.getLogin()); + stmt.setString(3, user.getName()); + final LocalDate birthday = user.getBirthday(); + if (birthday == null) { + stmt.setNull(4, Types.DATE); + } else { + stmt.setDate(4, Date.valueOf(birthday)); + } + return stmt; + }, keyHolder); + user.setUserId(keyHolder.getKey().intValue()); + return user; + } + +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/sortage/UserFriendDbStorage.java b/src/main/java/ru/yandex/practicum/filmorate/sortage/UserFriendDbStorage.java new file mode 100644 index 0000000..4723214 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/sortage/UserFriendDbStorage.java @@ -0,0 +1,76 @@ +package ru.yandex.practicum.filmorate.sortage; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.support.rowset.SqlRowSet; +import org.springframework.stereotype.Component; +import ru.yandex.practicum.filmorate.model.User; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +@Component +public class UserFriendDbStorage { + private final JdbcTemplate jdbcTemplate; + private UserDbStorage userDbStorage; + + @Autowired + public UserFriendDbStorage(JdbcTemplate jdbcTemplate, UserDbStorage userDbStorage) { + this.jdbcTemplate = jdbcTemplate; + this.userDbStorage = userDbStorage; + } + + public void addFriend(Integer userId, Integer friendId) { + String sqlQuery = "INSERT INTO USER_FRIEND (user_id, friend_id)" + + "VALUES (?, ?)"; + jdbcTemplate.update(sqlQuery, + userId, + friendId); + } + + public void deleteFriends(Integer userId, Integer friendId) { + String sqlQuery = "DELETE FROM USER_FRIEND WHERE USER_ID = ? AND FRIEND_ID = ?"; + jdbcTemplate.update(sqlQuery, + userId, + friendId); + } + + + public List findAllFriends(Integer userId) { + SqlRowSet sqlRowSet = jdbcTemplate.queryForRowSet("SELECT friend_id FROM USER_FRIEND " + + "WHERE USER_ID = ?", userId); + List friends = new ArrayList<>(); + while (sqlRowSet.next()) { + User friend = userDbStorage.findUser(sqlRowSet.getInt("friend_id")); + friends.add(friend); + } + return friends; + } + + + public List commonFriends(Integer userId, Integer secondUserId) { + SqlRowSet sqlRowSetUser = jdbcTemplate.queryForRowSet("SELECT friend_id FROM USER_FRIEND " + + "WHERE USER_ID = ?", userId); + + SqlRowSet sqlRowSetSecondUser = jdbcTemplate.queryForRowSet("SELECT friend_id FROM USER_FRIEND " + + "WHERE USER_ID = ?", secondUserId); + + List friendsUser = new ArrayList<>(); + List friendsSecondUser = new ArrayList<>(); + + while (sqlRowSetUser.next()) { + friendsUser.add(sqlRowSetUser.getInt("friend_id")); + } + + while (sqlRowSetSecondUser.next()) { + friendsSecondUser.add(sqlRowSetSecondUser.getInt("friend_id")); + } + + friendsUser.retainAll(friendsSecondUser); + + return friendsUser.stream().map(s -> userDbStorage.findUser(s)).collect(Collectors.toList()); + } + + +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/sortage/UserStorage.java b/src/main/java/ru/yandex/practicum/filmorate/sortage/UserStorage.java index c3af870..0c3fcc6 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/sortage/UserStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/sortage/UserStorage.java @@ -1,5 +1,6 @@ package ru.yandex.practicum.filmorate.sortage; +import org.springframework.data.relational.core.sql.In; import ru.yandex.practicum.filmorate.model.Film; import ru.yandex.practicum.filmorate.model.User; import ru.yandex.practicum.filmorate.exception.ValidationException; @@ -10,14 +11,9 @@ public interface UserStorage { Collection findAll(); - User put(User user) throws ValidationException; - User create(User user) throws ValidationException; - - List findAllId(); - + //List findAllId(); User findUser(Integer friendsId); - - void deleteUser(User user); + void deleteUser(Integer id); } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index c4df02b..5ec9f04 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1 +1,6 @@ server.port=8088 +spring.sql.init.mode=always +spring.datasource.url=jdbc:h2:file:./db/filmorate +spring.datasource.driverClassName=org.h2.Driver +spring.datasource.username=sa +spring.datasource.password=password diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql new file mode 100644 index 0000000..79cc135 --- /dev/null +++ b/src/main/resources/schema.sql @@ -0,0 +1,104 @@ +DROP TABLE IF EXISTS USERS; +DROP TABLE IF EXISTS USER_FRIEND; +DROP TABLE IF EXISTS FILMS; +DROP TABLE IF EXISTS LIKE_FILMS; +DROP TABLE IF EXISTS GENRE_FILM; + + +-- Creating tables +CREATE TABLE if not exists USERS +( + user_id int auto_increment unique, + email varchar, + login varchar, + name varchar, + birthday date, + primary key (user_id) +); + +CREATE TABLE if not exists FRIENDSHIP_STATUS +( + friendship_status_id int, + status varchar, + primary key (friendship_status_id) +); + +CREATE TABLE if not exists USER_FRIEND +( + user_id int references users (user_id), + friend_id int references users (user_id), + friendship_status_id int references FRIENDSHIP_STATUS (friendship_status_id) +); + + + +CREATE TABLE if not exists MPA_RATING +( + mpa_id int auto_increment unique, + mpa_rating varchar, + description varchar, + primary key (mpa_id) +); + + +CREATE TABLE if not exists FILMS +( + film_id int auto_increment unique, + name varchar, + description varchar, + release_date date, + duration int, + rate int, + mpa_id int references mpa_rating (mpa_id), + primary key (film_id) +); + +CREATE TABLE if not exists LIKE_FILMS +( + user_id int references users (user_id), + film_id int references films (film_id) +); + +CREATE TABLE if not exists MPA_FILMS +( + mpa_id int references MPA_RATING (mpa_id), + film_id int references films (film_id) +); + +CREATE TABLE if not exists GENRE +( + genre_id int auto_increment unique, + genre_name varchar, + primary key (genre_id) +); + +CREATE TABLE if not exists GENRE_FILM +( + film_id int references films (film_id), + genre_id int references genre (genre_id) +); + +MERGE INTO MPA_RATING (MPA_ID, MPA_RATING, DESCRIPTION) + values (1, 'G', 'У фильма нет возрастных ограничений'); +MERGE INTO MPA_RATING (MPA_ID, MPA_RATING, DESCRIPTION) + values (2, 'PG', 'Детям рекомендуется смотреть фильм с родителями'); +MERGE INTO MPA_RATING (MPA_ID, MPA_RATING, DESCRIPTION) + values (3, 'PG-13', 'Детям до 13 лет просмотр не желателен'); +MERGE INTO MPA_RATING (MPA_ID, MPA_RATING, DESCRIPTION) + values (4, 'R', 'Лицам до 17 лет просматривать фильм можно только в присутствии взрослого'); +MERGE INTO MPA_RATING (MPA_ID, MPA_RATING, DESCRIPTION) + values (5, 'NC-17', 'Лицам до 18 лет просмотр запрещён'); + +MERGE INTO GENRE + values (1, 'COMEDY'); +MERGE INTO GENRE + values (2, 'DRAMA'); +MERGE INTO GENRE + values (3, 'CARTOON'); +MERGE INTO GENRE + values (4, 'THRILLER'); +MERGE INTO GENRE + values (5, 'DOCUMENTARY'); +MERGE INTO GENRE + values (6, 'ACTION'); + diff --git a/src/test/java/resources/application.properties b/src/test/java/resources/application.properties new file mode 100644 index 0000000..5ec9f04 --- /dev/null +++ b/src/test/java/resources/application.properties @@ -0,0 +1,6 @@ +server.port=8088 +spring.sql.init.mode=always +spring.datasource.url=jdbc:h2:file:./db/filmorate +spring.datasource.driverClassName=org.h2.Driver +spring.datasource.username=sa +spring.datasource.password=password diff --git a/src/test/java/resources/schema.sql b/src/test/java/resources/schema.sql new file mode 100644 index 0000000..2a54d18 --- /dev/null +++ b/src/test/java/resources/schema.sql @@ -0,0 +1,103 @@ +DROP TABLE IF EXISTS LIKE_FILMS; +DROP TABLE IF EXISTS GENRE_FILM; +DROP TABLE IF EXISTS USER_FRIEND; +DROP TABLE IF EXISTS USERS; +DROP TABLE IF EXISTS FILMS; + + + +-- Creating tables +CREATE TABLE if not exists USERS +( + user_id int auto_increment unique, + email varchar, + login varchar, + name varchar, + birthday date, + primary key (user_id) +); + +CREATE TABLE if not exists FRIENDSHIP_STATUS +( + friendship_status_id int, + status varchar, + primary key (friendship_status_id) +); + +CREATE TABLE if not exists USER_FRIEND +( + user_id int references users (user_id), + friend_id int references users (user_id), + friendship_status_id int references FRIENDSHIP_STATUS (friendship_status_id) +); + + + +CREATE TABLE if not exists MPA_RATING +( + mpa_id int auto_increment unique, + mpa_rating varchar, + description varchar, + primary key (mpa_id) +); + + +CREATE TABLE if not exists FILMS +( + film_id int auto_increment unique, + name varchar, + description varchar, + release_date date, + duration int, + rate int, + mpa_id int references mpa_rating (mpa_id), + primary key (film_id) +); + +CREATE TABLE if not exists LIKE_FILMS +( + user_id int references users (user_id), + film_id int references films (film_id) +); + +CREATE TABLE if not exists GENRE +( + genre_id int auto_increment unique, + genre_name varchar, + primary key (genre_id) +); + +CREATE TABLE if not exists GENRE_FILM +( + film_id int references films (film_id), + genre_id int references genre (genre_id) +); + +MERGE INTO MPA_RATING (MPA_ID, MPA_RATING, DESCRIPTION) + values (1, 'G', 'У фильма нет возрастных ограничений'); +MERGE INTO MPA_RATING (MPA_ID, MPA_RATING, DESCRIPTION) + values (2, 'PG', 'Детям рекомендуется смотреть фильм с родителями'); +MERGE INTO MPA_RATING (MPA_ID, MPA_RATING, DESCRIPTION) + values (3, 'PG-13', 'Детям до 13 лет просмотр не желателен'); +MERGE INTO MPA_RATING (MPA_ID, MPA_RATING, DESCRIPTION) + values (4, 'R', 'Лицам до 17 лет просматривать фильм можно только в присутствии взрослого'); +MERGE INTO MPA_RATING (MPA_ID, MPA_RATING, DESCRIPTION) + values (5, 'NC-17', 'Лицам до 18 лет просмотр запрещён'); + + + + +INSERT INTO FILMS (NAME, DESCRIPTION, RELEASE_DATE, DURATION, RATE, MPA_ID) +VALUES ('Film', 'Description', '2000-01-01', 100, 4, 1); + +INSERT INTO USERS (EMAIL, LOGIN, NAME, BIRTHDAY) +VALUES ('test@test.ru', 'test', 'test', '2000-01-01'); + +INSERT INTO USERS (EMAIL, LOGIN, NAME, BIRTHDAY) +VALUES ('test1@test.ru', 'test1', 'test1', '1999-01-01'); + +INSERT INTO LIKE_FILMS (USER_ID, FILM_ID) +VALUES (2, 1); + + + diff --git a/src/test/java/ru/yandex/practicum/filmorate/controllerTest/FilmControllerTest.java b/src/test/java/ru/yandex/practicum/filmorate/controllerTest/FilmControllerTest.java index b083245..4a37e88 100644 --- a/src/test/java/ru/yandex/practicum/filmorate/controllerTest/FilmControllerTest.java +++ b/src/test/java/ru/yandex/practicum/filmorate/controllerTest/FilmControllerTest.java @@ -28,7 +28,7 @@ public class FilmControllerTest { void beforeEach() { duration1 = 100; releaseDate = LocalDate.of(1900, 1, 1); - film1 = new Film(1,"name", "logi n sdad", releaseDate, duration1); + film1 = new Film(1,"name", "logi n sdad", releaseDate, duration1, 4); } @Test diff --git a/src/test/java/ru/yandex/practicum/filmorate/sortage/FilmDbStorageTest.java b/src/test/java/ru/yandex/practicum/filmorate/sortage/FilmDbStorageTest.java new file mode 100644 index 0000000..de66d6b --- /dev/null +++ b/src/test/java/ru/yandex/practicum/filmorate/sortage/FilmDbStorageTest.java @@ -0,0 +1,84 @@ +package ru.yandex.practicum.filmorate.sortage; + +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 ru.yandex.practicum.filmorate.model.Film; + +import java.time.LocalDate; +import java.util.List; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +@SpringBootTest +@AutoConfigureTestDatabase +@RequiredArgsConstructor(onConstructor_ = @Autowired) +class FilmDbStorageTest { + + private final FilmDbStorage filmDbStorage; + @Test + void findAll() { + List films = filmDbStorage.findAll(); + + assertFalse(films.isEmpty()); + } + + @Test + void create() { + Film film = new Film(); + + film.setName("Фильм1"); + film.setDescription("Описание фильма 1"); + film.setReleaseDate(LocalDate.of(2000, 01, 01)); + film.setDuration(100); + film.setRate(10); + + MpaRating mpaRating = new MpaRating(); + mpaRating.setId(1); + + film.setMpa(mpaRating); + + filmDbStorage.create(film); + + assertThat(film).hasFieldOrPropertyWithValue("filmId", 2); + } + + @Test + void put() { + Film film = new Film(); + + film.setFilmId(2); + film.setName("Фильм измененный 1"); + film.setDescription("Описание фильма измененного 1"); + film.setReleaseDate(LocalDate.of(2000, 01, 01)); + film.setDuration(100); + film.setRate(10); + + MpaRating mpaRating = new MpaRating(); + mpaRating.setId(2); + + film.setMpa(mpaRating); + + filmDbStorage.put(film); + + assertThat(film).hasFieldOrPropertyWithValue("description", "Описание фильма измененного 1"); + } + + @Test + void findFilm() { + Film film = filmDbStorage.findFilm(1); + + assertThat(film).hasFieldOrPropertyWithValue("filmId", 1); + } + + @Test + void deleteFilm() { + filmDbStorage.deleteFilm(2); + + List films = filmDbStorage.findAll(); + + assertThat(films.size()).isEqualTo(1); + } +} \ No newline at end of file diff --git a/src/test/java/ru/yandex/practicum/filmorate/sortage/LikeFilmDbStorageTest.java b/src/test/java/ru/yandex/practicum/filmorate/sortage/LikeFilmDbStorageTest.java new file mode 100644 index 0000000..c7db6c2 --- /dev/null +++ b/src/test/java/ru/yandex/practicum/filmorate/sortage/LikeFilmDbStorageTest.java @@ -0,0 +1,45 @@ +package ru.yandex.practicum.filmorate.sortage; + +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 ru.yandex.practicum.filmorate.model.Film; +import ru.yandex.practicum.filmorate.model.LikeFilms; + +import java.util.List; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.junit.jupiter.api.Assertions.*; + + +@SpringBootTest +@AutoConfigureTestDatabase +@RequiredArgsConstructor(onConstructor_ = @Autowired) +class LikeFilmDbStorageTest { + + private final LikeFilmDbStorage likeFilmDbStorage; + private final FilmDbStorage filmDbStorage; + + @Test + void addLike() { + assertTrue(likeFilmDbStorage.addLike(1,1)); + } + + @Test + void deleteLike() { + likeFilmDbStorage.deleteLike(2, 1); + + Film film = filmDbStorage.findFilm(1); + + assertThat(film.getLikes()).isEqualTo(0); + } + + @Test + void getPopularFilms() { + List popularFilms = likeFilmDbStorage.getPopularFilms(1); + + assertFalse(popularFilms.isEmpty()); + } +} \ No newline at end of file diff --git a/src/test/java/ru/yandex/practicum/filmorate/sortage/UserDbStorageTest.java b/src/test/java/ru/yandex/practicum/filmorate/sortage/UserDbStorageTest.java new file mode 100644 index 0000000..790b030 --- /dev/null +++ b/src/test/java/ru/yandex/practicum/filmorate/sortage/UserDbStorageTest.java @@ -0,0 +1,74 @@ +package ru.yandex.practicum.filmorate.sortage; + +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 ru.yandex.practicum.filmorate.exception.UserIdNotValidation; +import ru.yandex.practicum.filmorate.model.User; + +import java.time.LocalDate; +import java.util.List; +import java.util.Optional; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.junit.jupiter.api.Assertions.*; + +@SpringBootTest +@AutoConfigureTestDatabase +@RequiredArgsConstructor(onConstructor_ = @Autowired) +class UserDbStorageTest { + + private final UserDbStorage userStorage; + + @Test + void findAll() { + Optional> optionalUsers = Optional.of(List.copyOf(userStorage.findAll())); + + assertThat(optionalUsers.get().size()).isEqualTo(3); + + } + + @Test + void create() { + User user = new User(); + user.setUserId(3); + user.setName("test1"); + user.setEmail("test1@test1.ru"); + user.setLogin("test1"); + user.setBirthday(LocalDate.of(1999, 01, 01)); + + userStorage.create(user); + + assertThat(user).hasFieldOrPropertyWithValue("userId",3); + } + + @Test + void put() { + User user = new User(); + user.setUserId(2); + user.setName("test1Changed"); + user.setEmail("test1Changed@test1.ru"); + user.setLogin("test1Changed"); + user.setBirthday(LocalDate.of(1998, 01, 01)); + userStorage.put(user); + + + assertThat(user).hasFieldOrPropertyWithValue("name", "test1Changed"); + } + + @Test + void findUser() { + User user = userStorage.findUser(1); + + assertThat(user).hasFieldOrPropertyWithValue("userId", 1); + + } + + @Test + void deleteUser() { + userStorage.deleteUser(3); + assertThrows(UserIdNotValidation.class ,() -> userStorage.findUser(3)); + } +} \ No newline at end of file diff --git a/src/test/java/ru/yandex/practicum/filmorate/sortage/UserFriendDbStorageTest.java b/src/test/java/ru/yandex/practicum/filmorate/sortage/UserFriendDbStorageTest.java new file mode 100644 index 0000000..d50d05f --- /dev/null +++ b/src/test/java/ru/yandex/practicum/filmorate/sortage/UserFriendDbStorageTest.java @@ -0,0 +1,42 @@ +package ru.yandex.practicum.filmorate.sortage; + +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 ru.yandex.practicum.filmorate.model.User; + +import java.util.List; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.junit.jupiter.api.Assertions.*; + +@SpringBootTest +@AutoConfigureTestDatabase +@RequiredArgsConstructor(onConstructor_ = @Autowired) +class UserFriendDbStorageTest { + + private final UserFriendDbStorage userFriendDbStorage; + + @Test + public void addFriend() { + userFriendDbStorage.addFriend(1, 2); + Integer fiendsId = userFriendDbStorage.findAllFriends(1).get(0).getUserId(); + assertThat(fiendsId).isEqualTo(2); + } + + @Test + public void findAllFriends() { + userFriendDbStorage.addFriend(1, 2); + List allFriends = userFriendDbStorage.findAllFriends(1); + assertFalse(allFriends.isEmpty()); + } + + @Test + public void deleteFriends() { + userFriendDbStorage.deleteFriends(1, 2); + Integer friend = userFriendDbStorage.findAllFriends(1).size(); + assertThat(friend).isEqualTo(0); + } +} \ No newline at end of file