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
41 changes: 41 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

<properties>
<java.version>21</java.version>
<org.mapstruct.version>1.6.3</org.mapstruct.version>
<lombok-mapstruct-binding.version>0.2.0</lombok-mapstruct-binding.version>
</properties>

<dependencies>
Expand Down Expand Up @@ -60,6 +62,19 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>

<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${org.mapstruct.version}</version>
</dependency>

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-mapstruct-binding</artifactId>
<version>${lombok-mapstruct-binding.version}</version>
</dependency>

</dependencies>

<build>
Expand Down Expand Up @@ -120,6 +135,32 @@
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
</path>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-mapstruct-binding</artifactId>
<version>${lombok-mapstruct-binding.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<plugin>
<groupId>com.github.spotbugs</groupId>
<artifactId>spotbugs-maven-plugin</artifactId>
Expand Down
9 changes: 9 additions & 0 deletions src/main/java/ru/practicum/shareit/booking/Booking.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
package ru.practicum.shareit.booking;

import java.time.LocalDate;

/**
* TODO Sprint add-bookings.
*/
public class Booking {

private Long bookingId;
private LocalDate start;
private LocalDate end;
private Long itemId;
private Long bookerId;
BookingStatus status;
}
8 changes: 8 additions & 0 deletions src/main/java/ru/practicum/shareit/booking/BookingStatus.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package ru.practicum.shareit.booking;

public enum BookingStatus {
WAITING,
APPROVED,
REJECTED,
CANCELED
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package ru.practicum.shareit.exception;

public class AnotherUserException extends RuntimeException {

public AnotherUserException(String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package ru.practicum.shareit.exception;

public class DuplicatedDataException extends RuntimeException {

public DuplicatedDataException(String message) {
super(message);
}
}
33 changes: 33 additions & 0 deletions src/main/java/ru/practicum/shareit/exception/ErrorHandler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package ru.practicum.shareit.exception;

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

@RestControllerAdvice
@Slf4j
public class ErrorHandler {

@ExceptionHandler(DuplicatedDataException.class)
@ResponseStatus(HttpStatus.CONFLICT)
public ErrorResponse handleDuplicatedDataException(final DuplicatedDataException e) {
log.error("Duplicated: {}", e.getMessage());
return new ErrorResponse(e.getMessage(), HttpStatus.CONFLICT);
}

@ExceptionHandler(NotFoundException.class)
@ResponseStatus(HttpStatus.NOT_FOUND)
public ErrorResponse handleNotFoundException(final NotFoundException e) {
log.error("Not found: {}", e.getMessage());
return new ErrorResponse(e.getMessage(), HttpStatus.NOT_FOUND);
}

@ExceptionHandler
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public ErrorResponse handleException(final RuntimeException e) {
log.error("ServerError: {}", e.getMessage());
return new ErrorResponse(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
}
}
16 changes: 16 additions & 0 deletions src/main/java/ru/practicum/shareit/exception/ErrorResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package ru.practicum.shareit.exception;

import lombok.Getter;
import org.springframework.http.HttpStatus;

@Getter
public class ErrorResponse {
String error;
HttpStatus status;

public ErrorResponse(String error, HttpStatus status) {
this.error = error;
this.status = status;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package ru.practicum.shareit.exception;

public class NotFoundException extends RuntimeException {

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

}

Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package ru.practicum.shareit.exception;

public class ValidationException extends RuntimeException {

public ValidationException(String message) {
super(message);
}
}
51 changes: 46 additions & 5 deletions src/main/java/ru/practicum/shareit/item/ItemController.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,53 @@
package ru.practicum.shareit.item;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
* TODO Sprint add-controllers.
*/
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import ru.practicum.shareit.item.dto.ItemRequestDto;
import ru.practicum.shareit.item.dto.ItemResponseDto;

import java.util.Collection;

@RestController
@RequestMapping("/items")
@RequiredArgsConstructor
@Slf4j
@Validated
public class ItemController {

public static final String OWNER_ID = "X-Sharer-User-Id";
private final ItemService itemService;

@PostMapping
public ItemResponseDto create(@RequestHeader(OWNER_ID) Long ownerId,
@Valid @RequestBody ItemRequestDto item) {
return itemService.createItem(item, ownerId);
}

@PatchMapping("/{itemId}")
public ItemResponseDto update(@RequestBody ItemRequestDto item,
@PathVariable Long itemId,
@RequestHeader(OWNER_ID) Long ownerId) {
return itemService.updateItem(itemId, item, ownerId);
}

@GetMapping("/{itemId}")
public ItemResponseDto getItemById(@PathVariable Long itemId) {
return itemService.getItemById(itemId);
}

@GetMapping
public Collection<ItemResponseDto> getAllItemsForOwner(
@RequestHeader(OWNER_ID) Long ownerId) {
return itemService.getAllItemsForOwner(ownerId);
}

@GetMapping("/search")
public Collection<ItemResponseDto> searchItems(@RequestParam String text) {
return itemService.searchByText(text);
}

}
77 changes: 77 additions & 0 deletions src/main/java/ru/practicum/shareit/item/ItemService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package ru.practicum.shareit.item;

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import ru.practicum.shareit.exception.AnotherUserException;
import ru.practicum.shareit.exception.NotFoundException;
import ru.practicum.shareit.exception.ValidationException;
import ru.practicum.shareit.item.dto.ItemRequestDto;
import ru.practicum.shareit.item.dto.ItemResponseDto;
import ru.practicum.shareit.item.interfaces.ItemServiceInterface;
import ru.practicum.shareit.item.mapper.ItemMapper;
import ru.practicum.shareit.item.model.Item;
import ru.practicum.shareit.user.UserStorage;

import java.util.ArrayList;
import java.util.Collection;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class ItemService implements ItemServiceInterface {

private final ItemStorage itemStorage;
private final UserStorage userStorage;
private final ItemMapper itemMapper;

public ItemResponseDto createItem(ItemRequestDto item, Long ownerId) {
if (ownerId == null) {
throw new ValidationException("Owner id cannot be null");
}
userStorage.getUserById(ownerId)
.orElseThrow(() -> new NotFoundException("User with id " + ownerId + " not found"));
Item itemSaved = itemMapper.toItem(item);
itemSaved.setOwnerId(ownerId);
return itemMapper.toItemResponseDto(itemStorage.createItem(itemSaved));
}

public ItemResponseDto getItemById(Long id) {
return itemMapper.toItemResponseDto(itemStorage.getItemById(id)
.orElseThrow(() -> new NotFoundException("Item with id " + id + " not found")));
}

public ItemResponseDto updateItem(Long itemId,
ItemRequestDto item, Long ownerId) {
findUserById(ownerId);
Item foundItem = itemStorage.getItemById(itemId)
.orElseThrow(() -> new NotFoundException("Item with id " + itemId + " not found"));
if (foundItem.getOwnerId().equals(ownerId)) {
item.setItemId(itemId);
foundItem = itemMapper.toItem(item);
} else {
throw new AnotherUserException("User with id " + ownerId + " is not owner of this Item");
}
return itemMapper.toItemResponseDto(itemStorage.updateItem(foundItem));
}

public Collection<ItemResponseDto> getAllItemsForOwner(Long ownerId) {
return itemStorage.getAllItemsForOwner(ownerId).stream()
.map(itemMapper::toItemResponseDto)
.collect(Collectors.toList());
}

public Collection<ItemResponseDto> searchByText(String text) {
if (text == null || text.isEmpty()) {
return new ArrayList<>();
}
return itemStorage.searchByText(text).stream()
.filter(Item::getIsAvailable)
.map(itemMapper::toItemResponseDto)
.collect(Collectors.toList());
}

private void findUserById(Long userId) {
userStorage.getUserById(userId)
.orElseThrow(() -> new NotFoundException("User with id = " + userId + " not found"));
}
}
67 changes: 67 additions & 0 deletions src/main/java/ru/practicum/shareit/item/ItemStorage.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package ru.practicum.shareit.item;

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;
import ru.practicum.shareit.item.interfaces.ItemStorageInterface;
import ru.practicum.shareit.item.model.Item;

import java.util.*;
import java.util.stream.Collectors;

@Repository
@RequiredArgsConstructor
public class ItemStorage implements ItemStorageInterface {

private Long nextItemId = 1L;
private final Map<Long, Item> items = new HashMap<>();

public Item createItem(Item item) {
item.setItemId(nextItemId++);
items.put(item.getItemId(), item);
return item;
}

public Optional<Item> getItemById(Long id) {
return Optional.ofNullable(items.get(id));
}

public Item updateItem(Item item) {
Item oldItem = items.get(item.getItemId());

if (oldItem != null) {

if (item.getItemName() != null) {
oldItem.setItemName(item.getItemName());
}

if (item.getItemDescription() != null) {
oldItem.setItemDescription(item.getItemDescription());
}

if (item.getIsAvailable() != null) {
oldItem.setIsAvailable(item.getIsAvailable());
}

}
return oldItem;
}

public Collection<Item> getAllItemsForOwner(Long ownerId) {
return items.values()
.stream()
.filter(item -> Objects.equals(item.getOwnerId(), ownerId))
.collect(Collectors.toList());
}

public Collection<Item> searchByText(String text) {
Collection<Item> itemCollection = new ArrayList<>();
for (Item item : items.values()) {
if (item.getItemName().toLowerCase().contains(text.toLowerCase())) {
itemCollection.add(item);
} else if (item.getItemDescription().toLowerCase().contains(text.toLowerCase())) {
itemCollection.add(item);
}
}
return itemCollection;
}
}
7 changes: 0 additions & 7 deletions src/main/java/ru/practicum/shareit/item/dto/ItemDto.java

This file was deleted.

Loading