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
4 changes: 4 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<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,74 @@
package ru.yandex.practicum.filmorate.controller;

import org.springframework.web.bind.annotation.RestController;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
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.util.Collection;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@RestController
@RequestMapping(value = "/films")
public class FilmController {

private final Map<Long, Film> films = new HashMap<>();

@GetMapping
public Collection<Film> findAll() {

Choose a reason for hiding this comment

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

залоггируй вызов метода

log.info("Запрос всех фильмов");
return films.values();
}

@PostMapping
public Film create(@Valid @RequestBody Film film) {
checkDate(film);

film.setId(getNextId());

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

@PutMapping
public Film update(@Valid @RequestBody Film newFilm) {
if (newFilm.getId() == null) {
log.debug("Не указан Id при обновлении фильма");
throw new ValidationException("Не указан Id при обновлении фильма");
}
checkDate(newFilm);
if (films.containsKey(newFilm.getId())) {
Film oldFilm = films.get(newFilm.getId());
oldFilm.setName(newFilm.getName());
oldFilm.setDescription(newFilm.getDescription());
oldFilm.setReleaseDate(newFilm.getReleaseDate());
oldFilm.setDuration(newFilm.getDuration());
log.info("Фильм с id " + newFilm.getId() + " обновлен");
return oldFilm;
}
log.debug("Фильм с id = " + newFilm.getId() + " не найден");
throw new ValidationException("Фильм с id = " + newFilm.getId() + " не найден");
}

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

private void checkDate(Film film) {
if (film.getReleaseDate().isBefore(LocalDate.of(1895, 12, 28))) {
log.debug("Дата рождения не может быть в будущем");
throw new ValidationException("Дата рождения не может быть в будущем");
}
}

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

import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
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.Collection;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@RestController
@RequestMapping(value = "/users")
public class UserController {

private final Map<Long, User> users = new HashMap<>();

@GetMapping
public Collection<User> findAll() {
log.info("Запрос всех пользователей");
return users.values();
}

@PostMapping
public User create(@Valid @RequestBody User user) {

checkEmail(user.getEmail());
checkLogin(user.getLogin());
checkBirthday(user.getBirthday());

user.setId(getNextId());
user.setNameWithCheck(user);

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

@PutMapping
public User update(@Valid @RequestBody User newUser) {
if (newUser.getId() == null) {
log.debug("Не указан Id при обновлении пользователя");
throw new ValidationException("Не указан Id при обновлении пользователя");
}
checkEmail(newUser.getEmail());
checkLogin(newUser.getLogin());
checkBirthday(newUser.getBirthday());

if (users.containsKey(newUser.getId())) {
User oldUser = users.get(newUser.getId());
oldUser.setEmail(newUser.getEmail());
oldUser.setNameWithCheck(newUser);
oldUser.setLogin(newUser.getLogin());
oldUser.setBirthday(newUser.getBirthday());
log.info("Пользователь с id " + newUser.getId() + " обновлен");
return oldUser;
}
log.debug("Пользователь с id = " + newUser.getId() + " не найден");
throw new ValidationException("Пользователь с id = " + newUser.getId() + " не найден");
}

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

private void checkEmail(String email) {
boolean existEmail = users.values().stream()
.map(User::getEmail)
.anyMatch(email::equals);
if (existEmail) {
log.debug("Пользователь с почтой " + email + " уже существует");
throw new ValidationException("Пользователь с почтой " + email + " уже существует");
}
}

private void checkLogin(String login) {
if (login.contains(" ")) {
log.debug("Логин должен быть без пробелов");
throw new ValidationException("Логин должен быть без пробелов");
}
boolean existEmail = users.values().stream()
.map(User::getLogin)
.anyMatch(login::equals);
if (existEmail) {
log.debug("Пользователь с логином " + login + " уже существует");
throw new ValidationException("Пользователь с логином " + login + " уже существует");
}
}

private void checkBirthday(LocalDate birthday) {
if (birthday.isAfter(LocalDate.now())) {
log.debug("Дата рождения не может быть в будущем");
throw new ValidationException("Дата рождения не может быть в будущем");
}
}
}
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);
}
}
39 changes: 31 additions & 8 deletions src/main/java/ru/yandex/practicum/filmorate/model/Film.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,35 @@
package ru.yandex.practicum.filmorate.model;

import lombok.Getter;
import lombok.Setter;

/**
* Film.
*/
@Getter
@Setter
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Positive;
import jakarta.validation.constraints.Size;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.LocalDate;

@Data
@Builder(toBuilder = true)
@NoArgsConstructor
@AllArgsConstructor
public class Film {

private Long id;

@NotNull

Choose a reason for hiding this comment

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

лишняя аннотация, @notblank покроет и null, и пустую строку

@NotBlank
private String name;

@Size(max = 200)
private String description;

@NotNull
private LocalDate releaseDate;

Choose a reason for hiding this comment

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

для этого поля нужна аннотация @NotNull


@Positive
@NotNull
private Integer duration;

Choose a reason for hiding this comment

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

и для этого тоже

}
38 changes: 38 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,38 @@
package ru.yandex.practicum.filmorate.model;

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

import java.time.LocalDate;

@Data
@Builder(toBuilder = true)
@NoArgsConstructor
@AllArgsConstructor
public class User {

private Long id;

@Email
@NotNull
private String email;

Choose a reason for hiding this comment

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

для этого поля нужна аннотация @NotNull


@NotBlank
private String login;

private String name;

@NotNull
private LocalDate birthday;

Choose a reason for hiding this comment

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

для этого поля нужна аннотация @NotNull


public void setNameWithCheck(User user) {
if (user.getName() == null || user.getName().isBlank())
this.setName(user.getLogin());
else this.setName(user.getName());
}
}
61 changes: 61 additions & 0 deletions src/test/java/ru/yandex/practicum/filmorate/FilmTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package ru.yandex.practicum.filmorate;

import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import ru.yandex.practicum.filmorate.model.Film;

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

public class FilmTest {

private final Film film = Film.builder()
.name("nisi eiusmod")
.description("adipisicing")
.releaseDate(LocalDate.parse("1895-12-28").plusDays(1))
.duration(100)
.build();
private final ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
private final Validator validator = validatorFactory.getValidator();

@Test
void shouldCreateFilm() {
Set<ConstraintViolation<Film>> violations = validator.validate(film);

Assertions.assertTrue(violations.isEmpty());
}

@Test
void shouldNotCreateFilmIfNameIsEmpty() {
String[] names = {"", " ", " ", null};

Arrays.stream(names).forEach(name -> {
Film filmWithIncorrectName = film
.toBuilder()
.name(name)
.build();

Set<ConstraintViolation<Film>> violations = validator.validate(filmWithIncorrectName);

Assertions.assertFalse(violations.isEmpty());
});
}

@Test
void shouldNotCreateFilmIfDurationIsWrong() {
Film filmWithIncorrectDuration = film
.toBuilder()
.duration(-100)
.build();

Set<ConstraintViolation<Film>> violations = validator.validate(filmWithIncorrectDuration);

Assertions.assertFalse(violations.isEmpty());
Assertions.assertEquals(1, violations.size());
}
}
33 changes: 33 additions & 0 deletions src/test/java/ru/yandex/practicum/filmorate/UserTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package ru.yandex.practicum.filmorate;

import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import ru.yandex.practicum.filmorate.model.User;

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

public class UserTest {

private final User user = User
.builder()
.login("a_b")
.name("Nick Name")
.email("[email protected]")
.birthday(LocalDate.now())
.build();
private final ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
private final Validator validator = validatorFactory.getValidator();

@Test
void shouldCreateUser() {
Set<ConstraintViolation<User>> violations = validator.validate(user);

Assertions.assertTrue(violations.isEmpty());
}

}