-
Notifications
You must be signed in to change notification settings - Fork 0
controllers-films-users. Создать модели данных и котроллеры. #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| 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() { | ||
| 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); | ||
| } | ||
| } |
| 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 | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. для этого поля нужна аннотация @NotNull |
||
|
|
||
| @Positive | ||
| @NotNull | ||
| private Integer duration; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. и для этого тоже |
||
| } | ||
| 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; | ||
|
|
||
| @NotNull | ||
| private String email; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. для этого поля нужна аннотация @NotNull |
||
|
|
||
| @NotBlank | ||
| private String login; | ||
|
|
||
| private String name; | ||
|
|
||
| @NotNull | ||
| private LocalDate birthday; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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()); | ||
| } | ||
| } | ||
| 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()); | ||
| } | ||
| } |
| 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()); | ||
| } | ||
|
|
||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
залоггируй вызов метода