Skip to content
Closed
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
13 changes: 13 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,24 @@
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>

<dependency>
<groupId>org.zalando</groupId>
<artifactId>logbook-spring-boot-starter</artifactId>
<version>3.7.2</version>
</dependency>

</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@

@SpringBootApplication
public class FilmorateApplication {
public static void main(String[] args) {
SpringApplication.run(FilmorateApplication.class, args);
}

public static void main(String[] args) {
SpringApplication.run(FilmorateApplication.class, args);
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,91 @@
package ru.yandex.practicum.filmorate.controller;

import org.springframework.web.bind.annotation.RestController;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import jakarta.validation.Valid;
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.List;

@RestController
@RequestMapping("/films")
@Slf4j
public class FilmController {
private final FilmService filmService;

public FilmController(FilmService filmService) {
this.filmService = filmService;
}

@GetMapping
public List<Film> getAllFilms() {
log.info("Fetching all films");
return filmService.getAllFilms();
}

@GetMapping("/{id}")
public Film getFilm(@PathVariable Long id) {
log.info("Fetching film with id {}", id);
return filmService.getFilmById(id);
}

@PostMapping
public Film addFilm(@Valid @RequestBody Film film) {
log.info("Adding film: {}", film);
validateFilm(film);
return filmService.addFilm(film);
}

@PutMapping
public Film updateFilm(@Valid @RequestBody Film film) {
log.info("Updating film: {}", film);
validateFilm(film);
return filmService.updateFilm(film);
}

@DeleteMapping("/{id}")
public void deleteFilm(@PathVariable Long id) {
log.info("Deleting film with id {}", id);
filmService.removeFilm(id);
}

@PutMapping("/{id}/like/{userId}")
public void addLike(@PathVariable Long id, @PathVariable Long userId) {
log.info("User {} likes film {}", userId, id);
filmService.addLike(id, userId);
}

@DeleteMapping("/{id}/like/{userId}")
public void removeLike(@PathVariable Long id, @PathVariable Long userId) {
log.info("User {} removes like from film {}", userId, id);
filmService.removeLike(id, userId);
}

@GetMapping("/popular")
public List<Film> getPopularFilms(@RequestParam(defaultValue = "10") int count) {
log.info("Fetching top {} popular films", count);
return filmService.getPopularFilms(count);
}

private void validateFilm(Film film) {
if (film.getName() == null || film.getName().isBlank()) {
log.warn("Film name is invalid");
throw new ValidationException("Film name is invalid");
}
if (film.getDescription() != null && film.getDescription().length() > 200) {
log.warn("Film description is too long");
throw new ValidationException("Description length exceeds 200 characters");
}
if (film.getReleaseDate() == null || film.getReleaseDate().isBefore(LocalDate.of(1895, 12, 28))) {
log.warn("Film release date is invalid");
throw new ValidationException("Release date is invalid");
}
if (film.getDuration() <= 0) {
log.warn("Film duration is invalid");
throw new ValidationException("Duration must be positive");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package ru.yandex.practicum.filmorate.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import jakarta.validation.Valid;
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.List;

@RestController
@RequestMapping("/users")
@Slf4j
public class UserController {
private final UserService userService;

public UserController(UserService userService) {
this.userService = userService;
}

@GetMapping
public List<User> getAllUsers() {
log.info("Fetching all users");
return userService.getAllUsers();
}

@GetMapping("/{id}")
public User getUser(@PathVariable Long id) {
log.info("Fetching user with id {}", id);
return userService.getUserById(id);
}

@PostMapping
public User createUser(@Valid @RequestBody User user) {
log.info("Creating user: {}", user);
validateUser(user);
return userService.createUser(user);
}

@PutMapping
public User updateUser(@Valid @RequestBody User user) {
log.info("Updating user: {}", user);
validateUser(user);
return userService.updateUser(user);
}

@PutMapping("/{id}/friends/{friendId}")
public void addFriend(@PathVariable Long id, @PathVariable Long friendId) {
log.info("User {} adds friend {}", id, friendId);
userService.addFriend(id, friendId);
}

@DeleteMapping("/{id}/friends/{friendId}")
public void removeFriend(@PathVariable Long id, @PathVariable Long friendId) {
log.info("User {} removes friend {}", id, friendId);
userService.removeFriend(id, friendId);
}

@GetMapping("/{id}/friends")
public List<User> getFriends(@PathVariable Long id) {
log.info("Fetching friends of user {}", id);
return userService.getFriends(id);
}

@GetMapping("/{id}/friends/common/{otherId}")
public List<User> getCommonFriends(@PathVariable Long id, @PathVariable Long otherId) {
log.info("Fetching common friends of users {} and {}", id, otherId);
return userService.getCommonFriends(id, otherId);
}

private void validateUser(User user) {
if (user.getEmail() == null || user.getEmail().isBlank() || !user.getEmail().contains("@")) {
log.warn("Email is invalid");
throw new ValidationException("Email is invalid");
}
if (user.getLogin() == null || user.getLogin().isBlank() || user.getLogin().contains(" ")) {
log.warn("Login is invalid");
throw new ValidationException("Login is invalid");
}
if (user.getName() == null || user.getName().isBlank()) {
user.setName(user.getLogin());
log.info("Name set to login for user {}", user.getLogin());
}
if (user.getBirthday() == null || user.getBirthday().isAfter(LocalDate.now())) {
log.warn("Birthday is in the future");
throw new ValidationException("Birthday is invalid");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package ru.yandex.practicum.filmorate.exception;


public class NotFoundException extends RuntimeException {
public NotFoundException() {
super();
}

public NotFoundException(String message) {
super(message);
}

public NotFoundException(String message, Throwable cause) {
super(message, cause);
}

public NotFoundException(Throwable cause) {
super(cause);
}
}
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);
}
}
32 changes: 24 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,28 @@
package ru.yandex.practicum.filmorate.model;

import lombok.Getter;
import lombok.Setter;

/**
* Film.
*/
@Getter
@Setter
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Data;

import java.time.LocalDate;


@Data
public class Film {
private Long id;

@NotBlank
private String name;

@NotBlank
@Size(min = 1, max = 200)
private String description;

@NotNull
private LocalDate releaseDate;

@Min(1)
private int duration;
}
21 changes: 21 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,21 @@
package ru.yandex.practicum.filmorate.model;

import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;

import java.time.LocalDate;

@Data
public class User {
private Long id;

@NotBlank
@Email
private String email;

@NotBlank
private String login;
private String name;
private LocalDate birthday;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package ru.yandex.practicum.filmorate.service;

import org.springframework.stereotype.Service;
import ru.yandex.practicum.filmorate.model.Film;
import ru.yandex.practicum.filmorate.storage.FilmStorage;

import java.util.List;

@Service
public class FilmService {
private final FilmStorage filmStorage;

public FilmService(FilmStorage filmStorage) {
this.filmStorage = filmStorage;
}

public Film addFilm(Film film) {
return filmStorage.addFilm(film);
}

public Film updateFilm(Film film) {
return filmStorage.updateFilm(film);
}

public Film getFilmById(Long id) {
return filmStorage.getFilmById(id);
}

public List<Film> getAllFilms() {
return filmStorage.getAllFilms();
}

public void removeFilm(Long id) {
filmStorage.removeFilm(id);
}

public void addLike(Long filmId, Long userId) {
filmStorage.addLike(filmId, userId);
}

public void removeLike(Long filmId, Long userId) {
filmStorage.removeLike(filmId, userId);
}

public List<Film> getPopularFilms(int count) {
return filmStorage.getPopularFilms(count);
}
}
Loading
Loading