diff --git a/pom.xml b/pom.xml
index 2db888c..c890aeb 100644
--- a/pom.xml
+++ b/pom.xml
@@ -17,6 +17,7 @@
21
+ 3.3.1
@@ -82,6 +83,27 @@
+
+ org.apache.maven.plugins
+ maven-checkstyle-plugin
+ ${maven-checkstyle-plugin.version}
+
+
+ true
+ true
+ true
+ checkstyle.xml
+
+
+
+
+
+ check
+
+ compile
+
+
+
diff --git a/src/main/java/ru/practicum/shareit/item/ItemController.java b/src/main/java/ru/practicum/shareit/item/ItemController.java
index bb17668..4cdcdc7 100644
--- a/src/main/java/ru/practicum/shareit/item/ItemController.java
+++ b/src/main/java/ru/practicum/shareit/item/ItemController.java
@@ -1,12 +1,55 @@
package ru.practicum.shareit.item;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import jakarta.validation.constraints.Positive;
+import lombok.RequiredArgsConstructor;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+import ru.practicum.shareit.item.dto.ItemDto;
+import ru.practicum.shareit.item.service.ItemService;
+import ru.practicum.shareit.validation.OnCreate;
+import ru.practicum.shareit.validation.OnUpdate;
+
+import java.util.Collection;
/**
* TODO Sprint add-controllers.
*/
@RestController
@RequestMapping("/items")
+@RequiredArgsConstructor
public class ItemController {
+
+ private static final String USER_ID_HEADER = "X-Sharer-User-Id";
+ private final ItemService itemService;
+
+ @GetMapping("/{itemId}")
+ public ItemDto getItem(@PathVariable @Positive Long itemId) {
+ return itemService.getItem(itemId);
+ }
+
+ @GetMapping("/search")
+ public Collection searchItems(@RequestParam String text) {
+ return itemService.searchItems(text);
+ }
+
+ @GetMapping
+ public Collection getItems(@RequestHeader(USER_ID_HEADER) @Positive Long userId) {
+ return itemService.getItems(userId);
+ }
+
+ @PostMapping
+ public ItemDto addItem(
+ @RequestHeader(USER_ID_HEADER) @Positive Long userId,
+ @RequestBody @Validated(OnCreate.class) ItemDto itemDto) {
+ return itemService.addItem(userId, itemDto);
+ }
+
+ @PatchMapping("/{itemId}")
+ public ItemDto updateItem(
+ @RequestHeader(USER_ID_HEADER) @Positive Long userId,
+ @PathVariable @Positive Long itemId,
+ @RequestBody @Validated(OnUpdate.class) ItemDto itemDto) {
+ return itemService.updateItem(userId, itemId, itemDto);
+ }
+
}
diff --git a/src/main/java/ru/practicum/shareit/item/ItemMapper.java b/src/main/java/ru/practicum/shareit/item/ItemMapper.java
new file mode 100644
index 0000000..05c0b4d
--- /dev/null
+++ b/src/main/java/ru/practicum/shareit/item/ItemMapper.java
@@ -0,0 +1,24 @@
+package ru.practicum.shareit.item;
+
+import ru.practicum.shareit.item.dto.ItemDto;
+import ru.practicum.shareit.item.model.Item;
+
+public class ItemMapper {
+ public static Item toItem(ItemDto itemDto) {
+ Item item = new Item();
+ item.setId(itemDto.getId());
+ item.setName(itemDto.getName());
+ item.setDescription(itemDto.getDescription());
+ item.setIsAvailable(itemDto.getAvailable());
+ return item;
+ }
+
+ public static ItemDto toItemDto(Item item) {
+ ItemDto itemDto = new ItemDto();
+ itemDto.setId(item.getId());
+ itemDto.setName(item.getName());
+ itemDto.setDescription(item.getDescription());
+ itemDto.setAvailable(item.getIsAvailable());
+ return itemDto;
+ }
+}
diff --git a/src/main/java/ru/practicum/shareit/item/dao/ItemRepository.java b/src/main/java/ru/practicum/shareit/item/dao/ItemRepository.java
new file mode 100644
index 0000000..d785762
--- /dev/null
+++ b/src/main/java/ru/practicum/shareit/item/dao/ItemRepository.java
@@ -0,0 +1,18 @@
+package ru.practicum.shareit.item.dao;
+
+import ru.practicum.shareit.item.model.Item;
+
+import java.util.Collection;
+import java.util.Optional;
+
+public interface ItemRepository {
+ Optional- getItem(Long itemId);
+
+ Collection
- searchItems(String text);
+
+ Collection
- getItems(Long userId);
+
+ Item addItem(Item item);
+
+ Optional
- updateItem(Item item);
+}
diff --git a/src/main/java/ru/practicum/shareit/item/dao/ItemRepositoryInMemory.java b/src/main/java/ru/practicum/shareit/item/dao/ItemRepositoryInMemory.java
new file mode 100644
index 0000000..e899f9b
--- /dev/null
+++ b/src/main/java/ru/practicum/shareit/item/dao/ItemRepositoryInMemory.java
@@ -0,0 +1,78 @@
+package ru.practicum.shareit.item.dao;
+
+import org.springframework.stereotype.Repository;
+import ru.practicum.shareit.item.model.Item;
+
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicLong;
+
+@Repository
+public class ItemRepositoryInMemory implements ItemRepository {
+
+ private final Map storage = new ConcurrentHashMap<>();
+ private final AtomicLong idCounter = new AtomicLong(1L);
+
+ @Override
+ public Optional
- getItem(Long itemId) {
+ return Optional.ofNullable(storage.get(itemId));
+ }
+
+ @Override
+ public Collection
- searchItems(String text) {
+ return storage.values()
+ .stream()
+ .filter(Item::getIsAvailable)
+ .filter(item ->
+ item.getName().toLowerCase(Locale.ROOT).contains(text) ||
+ item.getDescription().toLowerCase(Locale.ROOT).contains(text))
+ .toList();
+ }
+
+ @Override
+ public Collection
- getItems(Long userId) {
+ return storage.values()
+ .stream()
+ .filter(item -> Objects.equals(item.getOwnerId(), userId))
+ .toList();
+ }
+
+ @Override
+ public Item addItem(Item item) {
+ Long id = idCounter.getAndIncrement();
+ item.setId(id);
+ storage.put(id, item);
+
+ return item;
+ }
+
+ @Override
+ public Optional
- updateItem(Item newItem) {
+ if (!storage.containsKey(newItem.getId())) {
+ return Optional.empty();
+ }
+
+ Item oldItem = storage.get(newItem.getId());
+ patchItem(oldItem, newItem);
+
+ return Optional.of(oldItem);
+ }
+
+ private void patchItem(Item oldItem, Item newItem) {
+ String name = newItem.getName();
+ String description = newItem.getDescription();
+ Boolean isAvailable = newItem.getIsAvailable();
+
+ if (name != null) {
+ oldItem.setName(name);
+ }
+
+ if (description != null) {
+ oldItem.setDescription(description);
+ }
+
+ if (isAvailable != null) {
+ oldItem.setIsAvailable(isAvailable);
+ }
+ }
+}
diff --git a/src/main/java/ru/practicum/shareit/item/dto/ItemDto.java b/src/main/java/ru/practicum/shareit/item/dto/ItemDto.java
index 9319d7d..c26a3ca 100644
--- a/src/main/java/ru/practicum/shareit/item/dto/ItemDto.java
+++ b/src/main/java/ru/practicum/shareit/item/dto/ItemDto.java
@@ -1,7 +1,28 @@
package ru.practicum.shareit.item.dto;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Size;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import ru.practicum.shareit.validation.OnCreate;
+import ru.practicum.shareit.validation.OnUpdate;
+
/**
* TODO Sprint add-controllers.
*/
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
public class ItemDto {
+ private Long id;
+ @Size(groups = OnUpdate.class, min = 1, message = "Название предмета должно быть заполнено")
+ @NotBlank(groups = OnCreate.class, message = "Название предмета должно быть заполнено")
+ private String name;
+ @Size(groups = OnUpdate.class, min = 1, message = "Описание предмета должно быть заполнено")
+ @NotBlank(groups = OnCreate.class, message = "Описание предмета должно быть заполнено")
+ private String description;
+ @NotNull(groups = OnCreate.class, message = "Статус должен быть заполнен")
+ private Boolean available;
}
diff --git a/src/main/java/ru/practicum/shareit/item/model/Item.java b/src/main/java/ru/practicum/shareit/item/model/Item.java
index 44eb73d..93f135d 100644
--- a/src/main/java/ru/practicum/shareit/item/model/Item.java
+++ b/src/main/java/ru/practicum/shareit/item/model/Item.java
@@ -1,7 +1,19 @@
package ru.practicum.shareit.item.model;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
/**
* TODO Sprint add-controllers.
*/
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
public class Item {
+ private Long id;
+ private String name;
+ private String description;
+ private Boolean isAvailable;
+ private Long ownerId;
}
diff --git a/src/main/java/ru/practicum/shareit/item/service/ItemService.java b/src/main/java/ru/practicum/shareit/item/service/ItemService.java
new file mode 100644
index 0000000..d5ac715
--- /dev/null
+++ b/src/main/java/ru/practicum/shareit/item/service/ItemService.java
@@ -0,0 +1,17 @@
+package ru.practicum.shareit.item.service;
+
+import ru.practicum.shareit.item.dto.ItemDto;
+
+import java.util.Collection;
+
+public interface ItemService {
+ ItemDto getItem(Long itemId);
+
+ Collection searchItems(String text);
+
+ Collection getItems(Long userId);
+
+ ItemDto addItem(Long userId, ItemDto itemDto);
+
+ ItemDto updateItem(Long userId, Long itemId, ItemDto itemDto);
+}
\ No newline at end of file
diff --git a/src/main/java/ru/practicum/shareit/item/service/ItemServiceImpl.java b/src/main/java/ru/practicum/shareit/item/service/ItemServiceImpl.java
new file mode 100644
index 0000000..4b633b8
--- /dev/null
+++ b/src/main/java/ru/practicum/shareit/item/service/ItemServiceImpl.java
@@ -0,0 +1,92 @@
+package ru.practicum.shareit.item.service;
+
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import ru.practicum.shareit.item.ItemMapper;
+import ru.practicum.shareit.item.dao.ItemRepository;
+import ru.practicum.shareit.item.dto.ItemDto;
+import ru.practicum.shareit.item.model.Item;
+import ru.practicum.shareit.user.dao.UserRepository;
+import ru.practicum.shareit.validation.NotFoundException;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Locale;
+import java.util.Optional;
+
+@Service
+@RequiredArgsConstructor
+public class ItemServiceImpl implements ItemService {
+
+ private final ItemRepository itemRepository;
+ private final UserRepository userRepository;
+
+ @Override
+ public ItemDto getItem(Long itemId) {
+ Optional
- maybeItem = itemRepository.getItem(itemId);
+
+ if (maybeItem.isPresent()) {
+ return ItemMapper.toItemDto(maybeItem.get());
+ }
+
+ throw new NotFoundException("Предмет с id " + itemId + " не найден");
+ }
+
+ @Override
+ public Collection searchItems(String text) {
+ if (text == null || text.isBlank()) {
+ return Collections.emptyList();
+ }
+
+ text = text.toLowerCase(Locale.ROOT);
+
+ return itemRepository.searchItems(text)
+ .stream()
+ .map(ItemMapper::toItemDto)
+ .toList();
+ }
+
+ @Override
+ public Collection getItems(Long userId) {
+ throwIfUserNotFound(userId);
+
+ Collection
- items = itemRepository.getItems(userId);
+
+ return items.stream()
+ .map(ItemMapper::toItemDto)
+ .toList();
+ }
+
+ @Override
+ public ItemDto addItem(Long userId, ItemDto itemDto) {
+ throwIfUserNotFound(userId);
+
+ Item item = ItemMapper.toItem(itemDto);
+ item.setOwnerId(userId);
+
+ return ItemMapper.toItemDto(itemRepository.addItem(item));
+ }
+
+ @Override
+ public ItemDto updateItem(Long userId, Long itemId, ItemDto itemDto) {
+ throwIfUserNotFound(userId);
+
+ Item item = ItemMapper.toItem(itemDto);
+ item.setOwnerId(userId);
+ item.setId(itemId);
+
+ Optional
- maybeItem = itemRepository.updateItem(item);
+
+ if (maybeItem.isPresent()) {
+ return ItemMapper.toItemDto(maybeItem.get());
+ }
+
+ throw new NotFoundException("Предмет с id " + itemId + " не найден");
+ }
+
+ private void throwIfUserNotFound(Long userId) {
+ if (!userRepository.contains(userId)) {
+ throw new NotFoundException("Пользователь с id " + userId + " не найден");
+ }
+ }
+}
diff --git a/src/main/java/ru/practicum/shareit/user/User.java b/src/main/java/ru/practicum/shareit/user/User.java
deleted file mode 100644
index ae6e7f3..0000000
--- a/src/main/java/ru/practicum/shareit/user/User.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package ru.practicum.shareit.user;
-
-/**
- * TODO Sprint add-controllers.
- */
-public class User {
-}
diff --git a/src/main/java/ru/practicum/shareit/user/UserController.java b/src/main/java/ru/practicum/shareit/user/UserController.java
index 03039b9..4da9340 100644
--- a/src/main/java/ru/practicum/shareit/user/UserController.java
+++ b/src/main/java/ru/practicum/shareit/user/UserController.java
@@ -1,12 +1,44 @@
package ru.practicum.shareit.user;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import jakarta.validation.constraints.Positive;
+import lombok.RequiredArgsConstructor;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+import ru.practicum.shareit.user.dto.UserDto;
+import ru.practicum.shareit.user.model.User;
+import ru.practicum.shareit.user.service.UserService;
+import ru.practicum.shareit.validation.OnCreate;
+import ru.practicum.shareit.validation.OnUpdate;
/**
* TODO Sprint add-controllers.
*/
@RestController
@RequestMapping(path = "/users")
+@RequiredArgsConstructor
public class UserController {
+
+ private final UserService userService;
+
+ @GetMapping("/{userId}")
+ public User getUser(@PathVariable @Positive Long userId) {
+ return userService.getUser(userId);
+ }
+
+ @PostMapping
+ public User addUser(@RequestBody @Validated(OnCreate.class) UserDto user) {
+ return userService.addUser(user);
+ }
+
+ @PatchMapping("/{userId}")
+ public User updateUser(
+ @PathVariable @Positive Long userId,
+ @RequestBody @Validated(OnUpdate.class) UserDto user) {
+ return userService.updateUser(userId, user);
+ }
+
+ @DeleteMapping("/{userId}")
+ public void deleteUser(@PathVariable @Positive Long userId) {
+ userService.deleteUser(userId);
+ }
}
diff --git a/src/main/java/ru/practicum/shareit/user/UserMapper.java b/src/main/java/ru/practicum/shareit/user/UserMapper.java
new file mode 100644
index 0000000..7adf898
--- /dev/null
+++ b/src/main/java/ru/practicum/shareit/user/UserMapper.java
@@ -0,0 +1,13 @@
+package ru.practicum.shareit.user;
+
+import ru.practicum.shareit.user.dto.UserDto;
+import ru.practicum.shareit.user.model.User;
+
+public class UserMapper {
+ public static User toUser(UserDto userDto) {
+ User user = new User();
+ user.setName(userDto.getName());
+ user.setEmail(userDto.getEmail());
+ return user;
+ }
+}
diff --git a/src/main/java/ru/practicum/shareit/user/dao/UserRepository.java b/src/main/java/ru/practicum/shareit/user/dao/UserRepository.java
new file mode 100644
index 0000000..2f185ef
--- /dev/null
+++ b/src/main/java/ru/practicum/shareit/user/dao/UserRepository.java
@@ -0,0 +1,17 @@
+package ru.practicum.shareit.user.dao;
+
+import ru.practicum.shareit.user.model.User;
+
+import java.util.Optional;
+
+public interface UserRepository {
+ Optional getUser(Long userId);
+
+ User addUser(User user);
+
+ Optional updateUser(User user);
+
+ boolean deleteUser(Long userId);
+
+ boolean contains(Long userId);
+}
diff --git a/src/main/java/ru/practicum/shareit/user/dao/UserRepositoryInMemory.java b/src/main/java/ru/practicum/shareit/user/dao/UserRepositoryInMemory.java
new file mode 100644
index 0000000..aadb2c1
--- /dev/null
+++ b/src/main/java/ru/practicum/shareit/user/dao/UserRepositoryInMemory.java
@@ -0,0 +1,82 @@
+package ru.practicum.shareit.user.dao;
+
+import org.springframework.stereotype.Repository;
+import ru.practicum.shareit.user.model.User;
+import ru.practicum.shareit.validation.NotUniqueException;
+
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicLong;
+
+@Repository
+public class UserRepositoryInMemory implements UserRepository {
+
+ private final Map storage = new ConcurrentHashMap<>();
+ private final AtomicLong idCounter = new AtomicLong(1L);
+
+ @Override
+ public Optional getUser(Long userId) {
+ return Optional.ofNullable(storage.get(userId));
+ }
+
+ @Override
+ public User addUser(User user) {
+ if (isEmailTaken(user.getEmail())) {
+ throw new NotUniqueException("Email " + user.getEmail() + " уже занят");
+ }
+
+ Long id = idCounter.getAndIncrement();
+ user.setId(id);
+ storage.put(id, user);
+
+ return user;
+ }
+
+ @Override
+ public Optional updateUser(User newUser) {
+ if (!storage.containsKey(newUser.getId())) {
+ return Optional.empty();
+ }
+
+ User oldUser = storage.get(newUser.getId());
+ patchUser(oldUser, newUser);
+
+ return Optional.of(oldUser);
+
+ }
+
+ @Override
+ public boolean deleteUser(Long userId) {
+ User user = storage.remove(userId);
+
+ return user != null;
+ }
+
+ @Override
+ public boolean contains(Long userId) {
+ return storage.containsKey(userId);
+ }
+
+ private boolean isEmailTaken(String email) {
+ return storage.values()
+ .stream()
+ .anyMatch(user -> user.getEmail().equals(email));
+ }
+
+ private void patchUser(User oldUser, User newUser) {
+ String name = newUser.getName();
+ String email = newUser.getEmail();
+
+ if (name != null) {
+ oldUser.setName(name);
+ }
+
+ if (email != null) {
+ if (isEmailTaken(email)) {
+ throw new NotUniqueException("Email " + email + " уже занят");
+ }
+ oldUser.setEmail(email);
+ }
+ }
+}
diff --git a/src/main/java/ru/practicum/shareit/user/dto/UserDto.java b/src/main/java/ru/practicum/shareit/user/dto/UserDto.java
new file mode 100644
index 0000000..bf5f27c
--- /dev/null
+++ b/src/main/java/ru/practicum/shareit/user/dto/UserDto.java
@@ -0,0 +1,19 @@
+package ru.practicum.shareit.user.dto;
+
+import jakarta.validation.constraints.Email;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Size;
+import lombok.Data;
+import ru.practicum.shareit.validation.OnCreate;
+import ru.practicum.shareit.validation.OnUpdate;
+
+@Data
+public class UserDto {
+ @Size(groups = OnUpdate.class, min = 1, message = "Имя пользователя должно быть заполнено")
+ @NotBlank(groups = OnCreate.class, message = "Имя пользователя должно быть заполнено")
+ private String name;
+ @NotNull(groups = OnCreate.class, message = "Почта должна быть заполнена")
+ @Email(groups = {OnCreate.class, OnUpdate.class}, message = "Почта должна соответствовать формату")
+ private String email;
+}
diff --git a/src/main/java/ru/practicum/shareit/user/model/User.java b/src/main/java/ru/practicum/shareit/user/model/User.java
new file mode 100644
index 0000000..0a07207
--- /dev/null
+++ b/src/main/java/ru/practicum/shareit/user/model/User.java
@@ -0,0 +1,17 @@
+package ru.practicum.shareit.user.model;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * TODO Sprint add-controllers.
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class User {
+ private Long id;
+ private String name;
+ private String email;
+}
diff --git a/src/main/java/ru/practicum/shareit/user/service/UserService.java b/src/main/java/ru/practicum/shareit/user/service/UserService.java
new file mode 100644
index 0000000..ba3e769
--- /dev/null
+++ b/src/main/java/ru/practicum/shareit/user/service/UserService.java
@@ -0,0 +1,14 @@
+package ru.practicum.shareit.user.service;
+
+import ru.practicum.shareit.user.dto.UserDto;
+import ru.practicum.shareit.user.model.User;
+
+public interface UserService {
+ User getUser(Long userId);
+
+ User addUser(UserDto userDto);
+
+ User updateUser(Long userId, UserDto userDto);
+
+ void deleteUser(Long userId);
+}
diff --git a/src/main/java/ru/practicum/shareit/user/service/UserServiceImpl.java b/src/main/java/ru/practicum/shareit/user/service/UserServiceImpl.java
new file mode 100644
index 0000000..82250d9
--- /dev/null
+++ b/src/main/java/ru/practicum/shareit/user/service/UserServiceImpl.java
@@ -0,0 +1,49 @@
+package ru.practicum.shareit.user.service;
+
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import ru.practicum.shareit.user.UserMapper;
+import ru.practicum.shareit.user.dao.UserRepository;
+import ru.practicum.shareit.user.dto.UserDto;
+import ru.practicum.shareit.user.model.User;
+import ru.practicum.shareit.validation.NotFoundException;
+
+import java.util.Optional;
+
+@Service
+@RequiredArgsConstructor
+public class UserServiceImpl implements UserService {
+
+ private final UserRepository userRepository;
+
+ @Override
+ public User getUser(Long userId) {
+ Optional maybeUser = userRepository.getUser(userId);
+
+ return maybeUser.orElseThrow(() -> new NotFoundException("Пользователь с id " + userId + " не найден"));
+ }
+
+ @Override
+ public User addUser(UserDto userDto) {
+ return userRepository.addUser(UserMapper.toUser(userDto));
+ }
+
+ @Override
+ public User updateUser(Long userId, UserDto userDto) {
+ User user = UserMapper.toUser(userDto);
+ user.setId(userId);
+
+ Optional maybeUser = userRepository.updateUser(user);
+
+ return maybeUser.orElseThrow(() -> new NotFoundException("Пользователь с id " + userId + " не найден"));
+ }
+
+ @Override
+ public void deleteUser(Long userId) {
+ boolean isDeleted = userRepository.deleteUser(userId);
+
+ if (!isDeleted) {
+ throw new NotFoundException("Пользователь с id " + userId + " не найден");
+ }
+ }
+}
diff --git a/src/main/java/ru/practicum/shareit/validation/GlobalExceptionHandler.java b/src/main/java/ru/practicum/shareit/validation/GlobalExceptionHandler.java
new file mode 100644
index 0000000..64b34f4
--- /dev/null
+++ b/src/main/java/ru/practicum/shareit/validation/GlobalExceptionHandler.java
@@ -0,0 +1,40 @@
+package ru.practicum.shareit.validation;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+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 java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+@ControllerAdvice
+public class GlobalExceptionHandler {
+
+ @ExceptionHandler(MethodArgumentNotValidException.class)
+ public ResponseEntity