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
7 changes: 6 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.4</version>
<version>3.5.8</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>ru.yandex.practicum</groupId>
Expand All @@ -25,13 +25,18 @@
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.38</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
Comment thread
milayadasha marked this conversation as resolved.
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,124 @@
package ru.yandex.practicum.filmorate.controller;

import org.springframework.web.bind.annotation.RestController;
import jakarta.validation.Valid;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import ru.yandex.practicum.filmorate.exception.ValidationException;
import ru.yandex.practicum.filmorate.model.Film;

import java.time.LocalDate;
import java.time.Month;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

@RestController
@RequestMapping("/films")
public class FilmController {
}
private static final int FILM_DESCRIPTION_LENGTH = 200;
private static final LocalDate EARLIEST_RELEASE_DATE = LocalDate.of(1895, Month.DECEMBER, 28);
private static final Logger log = LoggerFactory.getLogger(FilmController.class);
private final HashMap<Integer, Film> films = new HashMap<>();

/**
* Возвращает все фильмы в виде списка
*/
@GetMapping
public ResponseEntity<List<Film>> getFilms() {
return ResponseEntity.ok(new ArrayList<>(films.values()));
}

/**
* Добавляет новый фильм.
* Проверяет поля фильма на соответствие.
* Если всё хорошо, то создаёт копию переданного фильма, присваивает уникальный ID и сохраняет в контроллер.
*
* @param newFilm объект фильма, который нужно добавить
* @return копия созданного фильма с присвоенным ID
*/
@PostMapping
public ResponseEntity<Film> addFilm(@Valid @RequestBody Film newFilm) {
try {
checkIsValidFilm(newFilm);
} catch (ValidationException exception) {
log.error("Ошибка валидации данных фильма {} при добавлении: {}", newFilm.getId(), exception.getMessage());
throw exception;
}
log.trace("Данные фильма {} прошли валидацию при добавлении", newFilm.getId());

newFilm.setId(getNextId());
films.put(newFilm.getId(), newFilm);
log.info("Фильм {} добавлен", newFilm.getId());

return ResponseEntity.status(HttpStatus.CREATED).body(newFilm);
}

/**
* Обновляет фильм.
* Проверяет поля переданного фильма на соответствие.
* Если всё хорошо и переданный фильм существует в контроллере, то создаёт копию и сохраняет в контроллер.
*
* @param updatedFilm объект фильма, который нужно обновить
* @return копия обновлённого фильма
*/
@PutMapping
public ResponseEntity<Film> updateFilm(@Valid @RequestBody Film updatedFilm) {
try {
checkIsValidFilm(updatedFilm);
} catch (ValidationException exception) {
log.error("Ошибка валидации данных фильма {} при обновлении: {}", updatedFilm.getId(),
exception.getMessage());
throw exception;
}

log.trace("Фильм {} прошёл валидацию для обновления", updatedFilm.getId());
if (!films.containsKey(updatedFilm.getId())) {
String filmNotFound = "Фильм " + updatedFilm.getId() + " для обновления не найден";
log.error(filmNotFound);
throw new ValidationException(filmNotFound);
}

films.put(updatedFilm.getId(), updatedFilm);
log.info("Фильм {} обновлён", updatedFilm.getId());

return ResponseEntity.ok(updatedFilm);
}

/**
* Генерирует следующий Id.
* Находит максимальный текущй Id и увеличивает его.
*/
private int getNextId() {
int currentMaxId = films.keySet()
.stream()
.mapToInt(id -> id)
.max()
.orElse(0);
return ++currentMaxId;
}

/**
* Проверяет переданный фильм на соответствие условиям.
* Если не удовлетворяет какой-то проверке, то выбрасывается ошибка
*/
private void checkIsValidFilm(Film film) throws ValidationException {
if (film == null) {
throw new ValidationException("Фильм не найден");
}

if (film.getDescription().length() > FILM_DESCRIPTION_LENGTH) {
throw new ValidationException("Описание фильма не может быть больше 200 символов");
}

if (film.getReleaseDate().isBefore(EARLIEST_RELEASE_DATE)) {
throw new ValidationException("Дата релиза фильма не может быть раньше 28 декабря 1895 года");
}

if (film.getDuration() <= 0) {
throw new ValidationException("Продолжительность фильма должна быть положительным числом");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
package ru.yandex.practicum.filmorate.controller;

import jakarta.validation.Valid;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import ru.yandex.practicum.filmorate.exception.ValidationException;
import ru.yandex.practicum.filmorate.model.User;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

@RestController
@RequestMapping("/users")
public class UserController {
private static final Logger log = LoggerFactory.getLogger(UserController.class);
private final HashMap<Integer, User> users = new HashMap<>();

/**
* Возвращает всех пользователей в виде списка
*/
@GetMapping
public ResponseEntity<List<User>> getUsers() {
return ResponseEntity.ok(new ArrayList<>(users.values()));
}

/**
* Добавляет нового пользователя.
* Проверяет поля пользователя на соответствие.
* Если всё хорошо, то создаёт копию переданного пользователя, присваивает уникальный ID и сохраняет в контроллер.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

за javadoc плюсую

*
* @param newUser объект пользователя, который нужно добавить
* @return копия созданного пользователя с присвоенным ID
*/
@PostMapping
public ResponseEntity<User> addUser(@Valid @RequestBody User newUser) {
try {
checkIsValidUser(newUser);
} catch (ValidationException exception) {
log.error("Ошибка валидации данных пользователя при добавлении: {}",
exception.getMessage());
throw exception;
}
log.info("Данные пользователя прошли валидацию при добавлении");

newUser.setId(getNextId());
users.put(newUser.getId(), newUser);
log.info("Пользователь {} добавлен", newUser.getId());

return ResponseEntity.status(HttpStatus.CREATED).body(newUser);
}

/**
* Обновляет пользователя.
* Проверяет поля переданного пользователя на соответствие.
* Если всё хорошо и переданный пользователь существует в контроллере, то создаёт копию и сохраняет в контроллер.
*
* @param updatedUser объект пользователя, который нужно обновить
* @return копия обновлённого пользователя
*/
@PutMapping
public ResponseEntity<User> updateUser(@Valid @RequestBody User updatedUser) {
try {
checkIsValidUser(updatedUser);
} catch (ValidationException exception) {
log.error("Ошибка валидации данных пользователя {} при обновлении: {}", updatedUser.getId(),
exception.getMessage());
throw exception;
}
log.info("Данные пользователя {} прошли валидацию при обновлении", updatedUser.getId());

if (!users.containsKey(updatedUser.getId())) {
String userNotFound = "Пользователь " + updatedUser.getId() + " для обновления не найден";
log.error(userNotFound);
throw new ValidationException(userNotFound);
}

users.put(updatedUser.getId(), updatedUser);
log.info("Пользователь {} обновлён", updatedUser.getId());

return ResponseEntity.ok(updatedUser);
}

/**
* Генерирует следующий Id.
* Находит максимальный текущй Id и увеличивает его.
*/
private int getNextId() {
int currentMaxId = users.keySet()
.stream()
.mapToInt(id -> id)
.max()
.orElse(0);
return ++currentMaxId;
}

/**
* Проверяет переданного пользователя на соответствие условиям.
* Если не удовлетворяет какой-то проверке, то выбрасывается ошибка
*/
private void checkIsValidUser(User user) throws ValidationException {
if (user == null) {
throw new ValidationException("Пользователь не найден");
}

if (user.getLogin().contains(" ")) {
throw new ValidationException("Логин пользователя не может содержать пробел");
}

if (user.getBirthday() != null && user.getBirthday().isAfter(LocalDate.now())) {
throw new ValidationException("Дата рождения не может быть в будущем");
}

if (user.getName() == null || user.getName().isEmpty()) {
user.setName(user.getLogin());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package ru.yandex.practicum.filmorate.exception;

public class ValidationException extends RuntimeException {
public ValidationException(String message) {
super(message);
}
}
27 changes: 22 additions & 5 deletions src/main/java/ru/yandex/practicum/filmorate/model/Film.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,29 @@
package ru.yandex.practicum.filmorate.model;

import lombok.Getter;
import lombok.Setter;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.*;

import java.time.LocalDate;

/**
* Film.
*/
@Getter
@Setter
@Data
@Builder(toBuilder = true)
@EqualsAndHashCode(of = { "id" })
@AllArgsConstructor
public class Film {
}
private int id;

@NotBlank
private String name;

private String description;

@NotNull
private LocalDate releaseDate;

@NotNull
private Integer duration;
}
28 changes: 28 additions & 0 deletions src/main/java/ru/yandex/practicum/filmorate/model/User.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package ru.yandex.practicum.filmorate.model;

import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;

import java.time.LocalDate;

@Data
@Builder(toBuilder = true)
@EqualsAndHashCode(of = { "id" })
@AllArgsConstructor
public class User {
private int id;
private String name;

@Email
@NotBlank
private String email;

@NotBlank
private String login;

private LocalDate birthday;
}
Loading
Loading