Skip to content
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

commit 1.0 #1

Merged
merged 14 commits into from
Nov 7, 2023
Merged
Show file tree
Hide file tree
Changes from 12 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
54 changes: 54 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>ru.yandex.practicum</groupId>
<artifactId>filmorate</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>filmorate</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>

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

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

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
<scope>provided</scope>
</dependency>

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

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package ru.yandex.practicum.filmorate;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class FilmorateApplication {

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

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

import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import ru.yandex.practicum.filmorate.model.Film;

import javax.validation.Valid;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Validated
sergeev-alexander marked this conversation as resolved.
Show resolved Hide resolved
@RestController
public class FilmController {


private static final Map<Integer, Film> filmMap = new HashMap<>();
sergeev-alexander marked this conversation as resolved.
Show resolved Hide resolved
private Integer filmIdCounter = 1;

@GetMapping("/films")
public List<Film> getAllFilms() {
return new ArrayList<>(filmMap.values());
}

@PostMapping("/films")
public Film postFilm(@Valid @RequestBody Film film) {
film.setId(filmIdCounter++);
filmMap.put(film.getId(), film);
log.info("Added new film: " + film);
sergeev-alexander marked this conversation as resolved.
Show resolved Hide resolved
return film;
}

@PutMapping("/films")
public Film putFilm(@Valid @RequestBody Film film) {
filmMap.put(film.getId(), film);
log.info("Updated film: " + film);
sergeev-alexander marked this conversation as resolved.
Show resolved Hide resolved
return film;
}

public static boolean isFilmPresent(Integer id) {
return filmMap.containsKey(id);
}

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

import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import ru.yandex.practicum.filmorate.model.User;

import javax.validation.Valid;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Validated
sergeev-alexander marked this conversation as resolved.
Show resolved Hide resolved
@RestController
public class UserController {

private static final Map<Integer, User> userMap = new HashMap<>();
sergeev-alexander marked this conversation as resolved.
Show resolved Hide resolved
private Integer idCounter = 1;

@GetMapping("/users")
public List<User> getAllUsers() {
return new ArrayList<>(userMap.values());
}

@PostMapping("/users")
public User postUser(@Valid @RequestBody User user) {
user.setId(idCounter++);
if (null == user.getName()) {
sergeev-alexander marked this conversation as resolved.
Show resolved Hide resolved
user.setName(user.getLogin());
}
userMap.put(user.getId(), user);
log.info("Added new user: " + user);
return user;
}

@PutMapping("/users")
public User putUser(@Valid @RequestBody User user) {
if (null == user.getName()) {
user.setName(user.getLogin());
}
userMap.put(user.getId(), user);
log.info("Updated user: " + user);
return user;
}

public static boolean isUserPresent(Integer id) {
return userMap.containsKey(id);
}

}

Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package ru.yandex.practicum.filmorate.exception;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import ru.yandex.practicum.filmorate.FilmorateApplication;
import ru.yandex.practicum.filmorate.controller.FilmController;
import ru.yandex.practicum.filmorate.controller.UserController;

import java.util.HashMap;
import java.util.Map;

@ControllerAdvice
public class ErrorHandlingController {

@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody
sergeev-alexander marked this conversation as resolved.
Show resolved Hide resolved
public Map<String, String> autoValidationHendle(MethodArgumentNotValidException e) {
Map<String, String> response = new HashMap<>();
for (FieldError error : e.getBindingResult().getFieldErrors()) {
response.put(error.getField(), error.getDefaultMessage());
}
Class<?> loggerPath = FilmorateApplication.class;
if ("user".equals(e.getObjectName())) {
loggerPath = UserController.class;
} else if ("film".equals(e.getObjectName())) {
loggerPath = FilmController.class;
}
Logger logger = LoggerFactory.getLogger(loggerPath);
logger.error(loggerPath.getSimpleName() + " validation error: " + response.entrySet());
sergeev-alexander marked this conversation as resolved.
Show resolved Hide resolved
return response;
}

}
33 changes: 33 additions & 0 deletions src/main/java/ru/yandex/practicum/filmorate/model/Film.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package ru.yandex.practicum.filmorate.model;

import lombok.Data;
import org.springframework.validation.annotation.Validated;
import ru.yandex.practicum.filmorate.validation.IdBelonging;
import ru.yandex.practicum.filmorate.validation.PresetIdValidation;
import ru.yandex.practicum.filmorate.validation.ReleaseDateValidation;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Positive;
import javax.validation.constraints.Size;
import java.time.LocalDate;

@Validated
sergeev-alexander marked this conversation as resolved.
Show resolved Hide resolved
@Data
public class Film {

@PresetIdValidation(message = "There's no film with such id!", value = IdBelonging.FILM_ID)
private Integer id;

@NotBlank(message = "Name field is empty!")
private String name;

@Size(max = 200, message = "Description field must be less 200 characters!")
sergeev-alexander marked this conversation as resolved.
Show resolved Hide resolved
private String description;

@ReleaseDateValidation(message = "Release date is before 28.12.1895!")
private LocalDate releaseDate;

@Positive(message = "Duration field must be positive!")
private Long duration;
sergeev-alexander marked this conversation as resolved.
Show resolved Hide resolved

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

import lombok.Data;
import ru.yandex.practicum.filmorate.validation.IdBelonging;
import ru.yandex.practicum.filmorate.validation.PresetIdValidation;

import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Past;
import javax.validation.constraints.Pattern;
import java.time.LocalDate;

@Data
public class User {

@PresetIdValidation(message = "There's no user with such id!", value = IdBelonging.USER_ID)
private Integer id;

@NotBlank(message = "Email field is empty!")
@Email(message = "Wrong email format!")
private String email;

@NotBlank(message = "Login field is empty!")
@Pattern(regexp = "^\\S+$", message = "Login field should be without whitespaces!")
private String login;

private String name;

@Past(message = "Birthday field must contain a past date!")
sergeev-alexander marked this conversation as resolved.
Show resolved Hide resolved
private LocalDate birthday;

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

public enum IdBelonging {

USER_ID, FILM_ID

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

import ru.yandex.practicum.filmorate.controller.FilmController;
import ru.yandex.practicum.filmorate.controller.UserController;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

public class PresentIdValidator implements ConstraintValidator<PresetIdValidation, Integer> {
sergeev-alexander marked this conversation as resolved.
Show resolved Hide resolved

private IdBelonging idBelonging;

@Override
public void initialize(PresetIdValidation constraintAnnotation) {
this.idBelonging = constraintAnnotation.value();
}

@Override
public boolean isValid(Integer id, ConstraintValidatorContext constraintValidatorContext) {
if (id == null) {
return true;
}
if (idBelonging == IdBelonging.FILM_ID) {
return FilmController.isFilmPresent(id);
} else {
return UserController.isUserPresent(id);
}
}

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

import javax.validation.Constraint;
import javax.validation.Payload;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

@Target(FIELD)
@Retention(RUNTIME)
@Constraint(validatedBy = PresentIdValidator.class)
@Documented
public @interface PresetIdValidation {

String message() default "Default PresentValidation message";

Class<?>[] groups() default {};

Class<? extends Payload>[] payload() default {};

IdBelonging value();

@Target(FIELD)
@Retention(RUNTIME)
@Documented
@interface List {
PresetIdValidation[] value();
}

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

import javax.validation.Constraint;
import javax.validation.Payload;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

@Target(FIELD)
@Retention(RUNTIME)
@Constraint(validatedBy = ReleaseDateValidator.class)
@Documented
public @interface ReleaseDateValidation {

String message() default "Default ReleaseDateValidation message";

Class<?>[] groups() default {};

Class<? extends Payload>[] payload() default {};

}

Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package ru.yandex.practicum.filmorate.validation;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

import java.time.LocalDate;

public class ReleaseDateValidator implements ConstraintValidator<ReleaseDateValidation, LocalDate> {

public static final LocalDate FIRST_FILM_RELEASE_DATE = LocalDate.of(1895, 12, 28);

@Override
public boolean isValid(LocalDate releaseDate, ConstraintValidatorContext constraintValidatorContext) {
return !releaseDate.isBefore(FIRST_FILM_RELEASE_DATE);
sergeev-alexander marked this conversation as resolved.
Show resolved Hide resolved
}

}

Empty file.
Loading
Loading