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
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package ru.yandex.practicum.filmorate.controller;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import ru.yandex.practicum.filmorate.exception.DataNotFoundException;
import ru.yandex.practicum.filmorate.model.ErrorResponse;
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.ValidationException;

@RestControllerAdvice
public class ErrorHandler {

private static final Logger log = LoggerFactory.getLogger(ErrorHandler.class);

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

}

@ExceptionHandler
@ResponseStatus(HttpStatus.NOT_FOUND)
public ErrorResponse handleNotFoundException(final DataNotFoundException e) {
log.info("404 {}", e.getMessage());
return new ErrorResponse(e.getMessage());

}

}

Original file line number Diff line number Diff line change
@@ -1,65 +1,61 @@
package ru.yandex.practicum.filmorate.controller;

import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.*;
import ru.yandex.practicum.filmorate.exception.DataNotFoundException;
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.time.Month;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.List;


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

@GetMapping
private static final Logger log = LoggerFactory.getLogger(FilmController.class);
private final FilmService filmService;

@GetMapping(path = "/films")
public Collection<Film> getFilms() {
return films.values();
return filmService.getFilms();
}


@PostMapping
@PostMapping(path = "/films")
public Film createFilm(@Valid @RequestBody Film film) throws ValidationException {
LocalDate date = LocalDate.of(1895, Month.DECEMBER, 28);
if (film.getName() == null || film.getName().isEmpty()) {
throw new ValidationException("Название фильма не может быть пустым");
}
if (film.getDescription() == null || film.getDescription().length() > 200) {
throw new ValidationException("Максимальная длина описания — 200 символов");
}
if (film.getReleaseDate().isBefore(date)) {
throw new ValidationException("Дата релиза — не раньше 28 декабря 1895 года");
}
if (film.getDuration() <= 0) {
throw new ValidationException("Продолжительность фильма должна быть положительным числом");
}
film.setId(getNextId());
films.put(film.getId(), film);
log.debug("Фильм успешно добавлен");
return film;
return filmService.createFilm(film);

}

@PutMapping
public Film updateFilm(@RequestBody Film newFilm) throws ValidationException {
@PutMapping(path = "/films")
public Film updateFilm(@RequestBody Film newFilm) throws DataNotFoundException {

if (newFilm.getId() != null && films.containsKey(newFilm.getId())) {
films.put(newFilm.getId(), newFilm);
log.debug("Фильм успешно изменён");
return newFilm;
}
throw new ValidationException("Некорректный Id");
return filmService.updateFilm(newFilm);
}

private int getNextId() {
return nextId++;
@PutMapping(path = "/films/{id}/like/{userId}")
public void addLike(@PathVariable("id") int id, @PathVariable("userId") int userId) throws DataNotFoundException {

filmService.addLike(id, userId);
}

@DeleteMapping(path = "/films/{id}/like/{userId}")
public void deleteLike(@PathVariable("id") int id, @PathVariable("userId") int userId) throws DataNotFoundException {
filmService.deleteLike(id, userId);
}

@GetMapping(path = "/films/popular")
public List<Film> getPopularFilms(@RequestParam(defaultValue = "10") int count) {
return filmService.getPopularFilms(count);

}

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

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


import java.time.LocalDate;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.List;


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

@GetMapping
private final UserService userService;


@GetMapping(path = "/users")
public Collection<User> getUsers() {
return users.values();
return userService.getUsers();
}

@PostMapping
@PostMapping(path = "/users")
public User createUser(@RequestBody User user) throws ValidationException {
if (user.getEmail().isEmpty() || !user.getEmail().contains("@")) {
throw new ValidationException("Электронная почта не может быть пустой и должна содержать символ @");
}
if (user.getLogin() == null || user.getLogin().isEmpty() || user.getLogin().contains(" ")) {
throw new ValidationException("Логин не может быть пустым и содержать пробелы");
}
if (user.getName() == null) {
user.setName(user.getLogin());
}
if (user.getBirthday().isAfter(LocalDate.now())) {
throw new ValidationException("Дата рождения не может быть в будущем");
}
user.setId(getNextId());
users.put(user.getId(), user);
log.debug("Пользователь успешно добавлен");
return user;

return userService.createUser(user);
}

@PutMapping
public User updateUser(@RequestBody User newUser) throws ValidationException {
@PutMapping(path = "/users")
public User updateUser(@RequestBody User newUser) throws DataNotFoundException {
return userService.updateUser(newUser);

if (newUser.getId() != null && users.containsKey(newUser.getId())) {
users.put(newUser.getId(), newUser);
log.debug("Пользователь успешно изменён");
return newUser;
}
}

throw new ValidationException("Некорректный Id");

@PutMapping(path = "/users/{id}/friends/{friendId}")
public void addFriend(@PathVariable("id") int id, @PathVariable("friendId") int friendId) throws DataNotFoundException {
userService.addFriend(id, friendId);
}

@DeleteMapping(path = "/users/{id}/friends/{friendId}")
public void deleteFriend(@PathVariable("id") int id, @PathVariable("friendId") int friendId) throws DataNotFoundException {
userService.deleteFriend(id, friendId);
}

private int getNextId() {
return nextId++;
@GetMapping(path = "/users/{id}/friends")
public List<User> getUserFriends(@PathVariable("id") int id) throws DataNotFoundException {
return userService.getUserFriends(id);
}

@GetMapping(path = "/users/{id}/friends/common/{otherId}")
public List<User> getCommonFriends(@PathVariable("id") int id, @PathVariable("otherId") int otherId) throws DataNotFoundException {
return userService.getCommonFriends(id, otherId);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package ru.yandex.practicum.filmorate.exception;

public class DataNotFoundException extends Exception {
public DataNotFoundException(String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package ru.yandex.practicum.filmorate.model;

public class ErrorResponse {
private final String error;

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

public String getError() {
return error;
}


@Override
public String toString() {
return
"error= " + error;
}
}
8 changes: 6 additions & 2 deletions src/main/java/ru/yandex/practicum/filmorate/model/Film.java
Original file line number Diff line number Diff line change
@@ -1,22 +1,26 @@
package ru.yandex.practicum.filmorate.model;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
import lombok.Setter;

import java.time.LocalDate;
import java.util.HashSet;
import java.util.Set;

/**
* Film.
*/
@Getter
@Setter
@NoArgsConstructor
@RequiredArgsConstructor
public class Film {
private Integer id;
private String name;
private String description;
private LocalDate releaseDate;
private Long duration;
private Set<Integer> likes = new HashSet<>();


}
3 changes: 3 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 @@ -5,11 +5,14 @@
import lombok.Setter;

import java.time.LocalDate;
import java.util.HashSet;
import java.util.Set;

@Getter
@Setter
@NoArgsConstructor
public class User {
private Set<Integer> friendsList = new HashSet<>();
private Integer id;
private String email;
private String login;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package ru.yandex.practicum.filmorate.service;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import ru.yandex.practicum.filmorate.exception.DataNotFoundException;
import ru.yandex.practicum.filmorate.exception.ValidationException;
import ru.yandex.practicum.filmorate.model.Film;
import ru.yandex.practicum.filmorate.model.User;
import ru.yandex.practicum.filmorate.storage.FilmStorage;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
@Slf4j
public class FilmService {

private final FilmStorage filmStorage;
private final UserService userService;

public Collection<Film> getFilms() {
return filmStorage.getFilms();
}

public Film createFilm(Film film) throws ValidationException {
return filmStorage.createFilm(film);
}

public Film updateFilm(Film newFilm) throws DataNotFoundException {

return filmStorage.updateFilm(newFilm);
}

public void addLike(int id, int userId) throws DataNotFoundException {
Film film = get(id);
User user = userService.get(userId);

film.getLikes().add(userId);
log.info("add like: {}", film);
}

public void deleteLike(int id, int userId) throws DataNotFoundException {
Film film = get(id);
User user = userService.get(userId);

film.getLikes().remove(userId);
log.info("delete like: {}", film);
}

public List<Film> getPopularFilms(int count) {
List<Film> popularFilms = new ArrayList<>(filmStorage.getFilms());
popularFilms.sort(FILM_COMPARATOR.reversed());
return popularFilms.stream().limit(count).collect(Collectors.toList());

}

public static final Comparator<Film> FILM_COMPARATOR = new Comparator<Film>() {
@Override
public int compare(Film o1, Film o2) {
return o1.getLikes().size() - o2.getLikes().size();
}

};

public Film get(int filmId) throws DataNotFoundException {
return filmStorage.get(filmId);
}
}
Loading