Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.zalando</groupId>
<artifactId>logbook-spring-boot-starter</artifactId>
<version>3.7.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package ru.yandex.practicum.filmorate.controller;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import ru.yandex.practicum.filmorate.exception.ErrorResponse;
import ru.yandex.practicum.filmorate.exception.InternalServerErrorException;
import ru.yandex.practicum.filmorate.exception.NotFoundException;
import ru.yandex.practicum.filmorate.exception.ValidationException;

@RestControllerAdvice
public class ErrorHandler {

@ExceptionHandler
@ResponseStatus(HttpStatus.NOT_FOUND)
public ErrorResponse handleNotFoundException(final NotFoundException e) {
return new ErrorResponse("Error", e.getMessage());
}

@ExceptionHandler
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ErrorResponse handleValidationException(final ValidationException e) {
return new ErrorResponse("Error", e.getMessage());
}

@ExceptionHandler
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public ErrorResponse handleInternalServerErrorException(final InternalServerErrorException e) {
return new ErrorResponse("Error", e.getMessage());
}

}
Original file line number Diff line number Diff line change
@@ -1,95 +1,53 @@
package ru.yandex.practicum.filmorate.controller;

import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import ru.yandex.practicum.filmorate.exception.NotFoundException;
import ru.yandex.practicum.filmorate.exception.ValidationException;
import ru.yandex.practicum.filmorate.model.Film;
import ru.yandex.practicum.filmorate.service.FilmService;

import java.time.LocalDate;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/films")
public class FilmController {
private final Map<Integer, Film> films = new HashMap<>();

private final FilmService filmService;

@GetMapping
public Collection<Film> getAll() {
log.debug("GET, all films");
return films.values();
return filmService.getAll();
}

@GetMapping("/popular")
public Collection<Film> getFilmsByLike(@RequestParam(defaultValue = "10") int sizeFilms) {
return filmService.getFilmsByLike(sizeFilms);
}

@PostMapping
public Film create(@Valid @RequestBody Film film) {
log.debug("POST, create film {}", film);
validateReleaseDate(film);
film.setId(getNextId());
films.put(film.getId(), film);
return film;
return filmService.create(film);
}


@PutMapping
public Film update(@Valid @RequestBody Film filmUpdate) {
log.debug("PUT, update film {}", filmUpdate);
Integer id = validateUpdate(filmUpdate);
Film oldFilm = films.get(id);
String newName = filmUpdate.getName();
if (!newName.equals(oldFilm.getName())) oldFilm.setName(newName);
if (filmUpdate.getDescription() != null) {
String newDescription = filmUpdate.getDescription();
if (!newDescription.equals(oldFilm.getDescription())) oldFilm.setDescription(newDescription);
}
LocalDate newReleaseDate = filmUpdate.getReleaseDate();
if (!newReleaseDate.equals(oldFilm.getReleaseDate())) oldFilm.setReleaseDate(newReleaseDate);

if (filmUpdate.getDuration() != null) {
Integer newDuration = filmUpdate.getDuration();
if (!newDuration.equals(oldFilm.getDuration())) oldFilm.setDuration(newDuration);
}
return oldFilm;
return filmService.update(filmUpdate);
}


private void validateReleaseDate(Film film) {
log.debug("validateReleaseDate start for {}", film);
LocalDate birthdayFilm = LocalDate.of(1895, 12, 28);
if (film.getReleaseDate().isBefore(birthdayFilm)) {
String msg = "дата релиза — не раньше 28 декабря 1895 года";
log.error(msg);
throw new ValidationException(msg);
}
@PutMapping("/{filmId}/like/{userId}")
public Map<Film, Set<Integer>> addLike(@PathVariable int filmId, @PathVariable int userId) {
return filmService.addLike(filmId, userId);
}

private Integer validateUpdate(Film film) {
log.debug("validateUpdate start for {}", film);
String newName = film.getName();
if (film.getId() == null) {
String msg = "Id должен быть указан";
log.error(msg);
throw new ValidationException(msg);
}
Integer id = film.getId();
if (!films.containsKey(id)) {
String msg = "Фильм с id = " + id + " не найден";
log.error(msg);
throw new NotFoundException(msg);
}
validateReleaseDate(film);
return id;
@DeleteMapping("/{filmId}/like/{userId}")
public void removeLike(@PathVariable int filmId, @PathVariable int userId) {
filmService.removeLike(filmId, userId);
}

private int getNextId() {
int currentMaxId = films.keySet()
.stream()
.mapToInt(id -> id)
.max()
.orElse(0);
return ++currentMaxId;
}

}
Original file line number Diff line number Diff line change
@@ -1,100 +1,58 @@
package ru.yandex.practicum.filmorate.controller;

import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import ru.yandex.practicum.filmorate.exception.NotFoundException;
import ru.yandex.practicum.filmorate.exception.ValidationException;
import ru.yandex.practicum.filmorate.model.User;
import ru.yandex.practicum.filmorate.service.UserService;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

@Slf4j
@RestController
@RequestMapping("/users")
@RequiredArgsConstructor
public class UserController {
private final Map<Integer, User> users = new HashMap<>();

private final UserService userService;

@GetMapping
public Collection<User> getAll() {
log.debug("GET, all users");
return users.values();
return userService.getAll();
}

@GetMapping("/{userId}/friends")
public Collection<User> getFriendsUser(@PathVariable int userId) {
return userService.getFriendsUser(userId);
}

@GetMapping("/{userId}/friends/common/{friendsId}")
public Collection<User> getMutualFriends(@PathVariable int userId, @PathVariable int friendsId) {
return userService.getMutualFriends(userId, friendsId);
}

@PostMapping
public User create(@Valid @RequestBody User user) {
log.debug("POST, create user {}", user);
cloneSearchEmail(user);
user.setId(getNextId());
checkUserName(user);
users.put(user.getId(), user);
return user;
return userService.create(user);
}


@PutMapping
public User update(@Valid @RequestBody User newUser) {
log.debug("PUT, update User {}", newUser);
Integer id = validateUpdate(newUser);
User oldUser = users.get(id);
String newEmail = newUser.getEmail();
String newLogin = newUser.getLogin();
oldUser.setName(newUser.getName());
if (newUser.getBirthday() != null) oldUser.setBirthday(newUser.getBirthday());
if (!oldUser.getEmail().equals(newEmail)) oldUser.setEmail(newEmail);
if (!oldUser.getLogin().equals(newLogin)) oldUser.setLogin(newLogin);
return oldUser;
}

private void cloneSearchEmail(User user) {
log.debug("cloneSearchEmail start for {}", user);
String newEmail = user.getEmail();
for (User userMap : users.values()) {
if (userMap.getEmail().equals(newEmail)) {
String msg = "Этот Email уже используется";
log.error(msg);
throw new ValidationException(msg);
}
}
return userService.update(newUser);
}

private void checkUserName(User user) {
if (user.getName() == null) {
user.setName(user.getLogin());
}
@PutMapping("/{userId}/friends/{friendsId}")
public Map<User, Set<Integer>> addToFriend(@PathVariable int userId, @PathVariable int friendsId) {
return userService.addToFriend(userId, friendsId);
}

private Integer validateUpdate(User newUser) {
log.debug("validateUpdate start for {}", newUser);
checkUserName(newUser);
String newEmail = newUser.getEmail();
if (newUser.getId() == null) {
String msg = "Id должен быть указан";
log.error(msg);
throw new ValidationException(msg);
}
Integer id = newUser.getId();
if (!users.containsKey(id)) {
String msg = "Пользователь с id = " + newUser.getId() + " не найден";
log.error(msg);
throw new NotFoundException(msg);
}
if (!newEmail.equals(users.get(id).getEmail())) {
cloneSearchEmail(newUser);
}
return id;
@DeleteMapping("/{userId}/friends/{friendsId}")
public void removeFriend(@PathVariable int userId, @PathVariable int friendsId) {
userService.removeFriend(userId, friendsId);
}


private int getNextId() {
int currentMaxId = users.keySet()
.stream()
.mapToInt(id -> id)
.max()
.orElse(0);
return ++currentMaxId;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package ru.yandex.practicum.filmorate.exception;

public class ErrorResponse {
private final String error;
private final String description;

public ErrorResponse(String error, String description) {
this.error = error;
this.description = description;
}

public String getError() {
return error;
}

public String getDescription() {
return description;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package ru.yandex.practicum.filmorate.exception;

public class InternalServerErrorException extends RuntimeException {
public InternalServerErrorException(String message) {
super(message);
}
}
2 changes: 2 additions & 0 deletions src/main/java/ru/yandex/practicum/filmorate/model/Film.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,6 @@ public class Film {
@Positive
@NotNull
private Integer duration;
private int likes;

}
2 changes: 2 additions & 0 deletions src/main/java/ru/yandex/practicum/filmorate/model/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
@Builder
@Data
public class User {

private Integer id;
@NotNull
@NotBlank
Expand All @@ -24,4 +25,5 @@ public class User {
@Past
@NotNull
private LocalDate birthday;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package ru.yandex.practicum.filmorate.service;

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import ru.yandex.practicum.filmorate.model.Film;
import ru.yandex.practicum.filmorate.storage.film.InMemoryFilmStorage;

import java.util.Collection;
import java.util.Map;
import java.util.Set;

@RequiredArgsConstructor
@Service
public class FilmService {

private final InMemoryFilmStorage inMemoryFilmStorage;

public Collection<Film> getAll() {
return inMemoryFilmStorage.getAll();
}

public Film create(Film film) {
return inMemoryFilmStorage.create(film);
}

public Film update(Film filmUpdate) {
return inMemoryFilmStorage.update(filmUpdate);
}

public Map<Film, Set<Integer>> addLike(int filmId, int userId) {
return inMemoryFilmStorage.addLike(filmId, userId);
}

public void removeLike(int filmId, int userId) {
inMemoryFilmStorage.removeLike(filmId, userId);
}

public Collection<Film> getFilmsByLike(Integer sizeFilms) {
return inMemoryFilmStorage.getFilmsByLike(sizeFilms);
}

}
Loading
Loading