Skip to content

Commit 13e3fda

Browse files
authored
Merge pull request #2 from CrodiYa/add-controllers
Add controllers
2 parents ae48deb + 83cf880 commit 13e3fda

23 files changed

Lines changed: 636 additions & 11 deletions

pom.xml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
<properties>
1919
<java.version>21</java.version>
20+
<maven-checkstyle-plugin.version>3.3.1</maven-checkstyle-plugin.version>
2021
</properties>
2122

2223
<dependencies>
@@ -82,6 +83,27 @@
8283
</excludes>
8384
</configuration>
8485
</plugin>
86+
<plugin>
87+
<groupId>org.apache.maven.plugins</groupId>
88+
<artifactId>maven-checkstyle-plugin</artifactId>
89+
<version>${maven-checkstyle-plugin.version}</version>
90+
91+
<configuration>
92+
<failOnViolation>true</failOnViolation>
93+
<logViolationsToConsole>true</logViolationsToConsole>
94+
<includeTestSourceDirectory>true</includeTestSourceDirectory>
95+
<configLocation>checkstyle.xml</configLocation>
96+
</configuration>
97+
98+
<executions>
99+
<execution>
100+
<goals>
101+
<goal>check</goal>
102+
</goals>
103+
<phase>compile</phase>
104+
</execution>
105+
</executions>
106+
</plugin>
85107
</plugins>
86108
<pluginManagement>
87109
<plugins>
Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,55 @@
11
package ru.practicum.shareit.item;
22

3-
import org.springframework.web.bind.annotation.RequestMapping;
4-
import org.springframework.web.bind.annotation.RestController;
3+
import jakarta.validation.constraints.Positive;
4+
import lombok.RequiredArgsConstructor;
5+
import org.springframework.validation.annotation.Validated;
6+
import org.springframework.web.bind.annotation.*;
7+
import ru.practicum.shareit.item.dto.ItemDto;
8+
import ru.practicum.shareit.item.service.ItemService;
9+
import ru.practicum.shareit.validation.OnCreate;
10+
import ru.practicum.shareit.validation.OnUpdate;
11+
12+
import java.util.Collection;
513

614
/**
715
* TODO Sprint add-controllers.
816
*/
917
@RestController
1018
@RequestMapping("/items")
19+
@RequiredArgsConstructor
1120
public class ItemController {
21+
22+
private static final String USER_ID_HEADER = "X-Sharer-User-Id";
23+
private final ItemService itemService;
24+
25+
@GetMapping("/{itemId}")
26+
public ItemDto getItem(@PathVariable @Positive Long itemId) {
27+
return itemService.getItem(itemId);
28+
}
29+
30+
@GetMapping("/search")
31+
public Collection<ItemDto> searchItems(@RequestParam String text) {
32+
return itemService.searchItems(text);
33+
}
34+
35+
@GetMapping
36+
public Collection<ItemDto> getItems(@RequestHeader(USER_ID_HEADER) @Positive Long userId) {
37+
return itemService.getItems(userId);
38+
}
39+
40+
@PostMapping
41+
public ItemDto addItem(
42+
@RequestHeader(USER_ID_HEADER) @Positive Long userId,
43+
@RequestBody @Validated(OnCreate.class) ItemDto itemDto) {
44+
return itemService.addItem(userId, itemDto);
45+
}
46+
47+
@PatchMapping("/{itemId}")
48+
public ItemDto updateItem(
49+
@RequestHeader(USER_ID_HEADER) @Positive Long userId,
50+
@PathVariable @Positive Long itemId,
51+
@RequestBody @Validated(OnUpdate.class) ItemDto itemDto) {
52+
return itemService.updateItem(userId, itemId, itemDto);
53+
}
54+
1255
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package ru.practicum.shareit.item;
2+
3+
import ru.practicum.shareit.item.dto.ItemDto;
4+
import ru.practicum.shareit.item.model.Item;
5+
6+
public class ItemMapper {
7+
public static Item toItem(ItemDto itemDto) {
8+
Item item = new Item();
9+
item.setId(itemDto.getId());
10+
item.setName(itemDto.getName());
11+
item.setDescription(itemDto.getDescription());
12+
item.setIsAvailable(itemDto.getAvailable());
13+
return item;
14+
}
15+
16+
public static ItemDto toItemDto(Item item) {
17+
ItemDto itemDto = new ItemDto();
18+
itemDto.setId(item.getId());
19+
itemDto.setName(item.getName());
20+
itemDto.setDescription(item.getDescription());
21+
itemDto.setAvailable(item.getIsAvailable());
22+
return itemDto;
23+
}
24+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package ru.practicum.shareit.item.dao;
2+
3+
import ru.practicum.shareit.item.model.Item;
4+
5+
import java.util.Collection;
6+
import java.util.Optional;
7+
8+
public interface ItemRepository {
9+
Optional<Item> getItem(Long itemId);
10+
11+
Collection<Item> searchItems(String text);
12+
13+
Collection<Item> getItems(Long userId);
14+
15+
Item addItem(Item item);
16+
17+
Optional<Item> updateItem(Item item);
18+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package ru.practicum.shareit.item.dao;
2+
3+
import org.springframework.stereotype.Repository;
4+
import ru.practicum.shareit.item.model.Item;
5+
6+
import java.util.*;
7+
import java.util.concurrent.ConcurrentHashMap;
8+
import java.util.concurrent.atomic.AtomicLong;
9+
10+
@Repository
11+
public class ItemRepositoryInMemory implements ItemRepository {
12+
13+
private final Map<Long, Item> storage = new ConcurrentHashMap<>();
14+
private final AtomicLong idCounter = new AtomicLong(1L);
15+
16+
@Override
17+
public Optional<Item> getItem(Long itemId) {
18+
return Optional.ofNullable(storage.get(itemId));
19+
}
20+
21+
@Override
22+
public Collection<Item> searchItems(String text) {
23+
return storage.values()
24+
.stream()
25+
.filter(Item::getIsAvailable)
26+
.filter(item ->
27+
item.getName().toLowerCase(Locale.ROOT).contains(text) ||
28+
item.getDescription().toLowerCase(Locale.ROOT).contains(text))
29+
.toList();
30+
}
31+
32+
@Override
33+
public Collection<Item> getItems(Long userId) {
34+
return storage.values()
35+
.stream()
36+
.filter(item -> Objects.equals(item.getOwnerId(), userId))
37+
.toList();
38+
}
39+
40+
@Override
41+
public Item addItem(Item item) {
42+
Long id = idCounter.getAndIncrement();
43+
item.setId(id);
44+
storage.put(id, item);
45+
46+
return item;
47+
}
48+
49+
@Override
50+
public Optional<Item> updateItem(Item newItem) {
51+
if (!storage.containsKey(newItem.getId())) {
52+
return Optional.empty();
53+
}
54+
55+
Item oldItem = storage.get(newItem.getId());
56+
patchItem(oldItem, newItem);
57+
58+
return Optional.of(oldItem);
59+
}
60+
61+
private void patchItem(Item oldItem, Item newItem) {
62+
String name = newItem.getName();
63+
String description = newItem.getDescription();
64+
Boolean isAvailable = newItem.getIsAvailable();
65+
66+
if (name != null) {
67+
oldItem.setName(name);
68+
}
69+
70+
if (description != null) {
71+
oldItem.setDescription(description);
72+
}
73+
74+
if (isAvailable != null) {
75+
oldItem.setIsAvailable(isAvailable);
76+
}
77+
}
78+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,28 @@
11
package ru.practicum.shareit.item.dto;
22

3+
import jakarta.validation.constraints.NotBlank;
4+
import jakarta.validation.constraints.NotNull;
5+
import jakarta.validation.constraints.Size;
6+
import lombok.AllArgsConstructor;
7+
import lombok.Data;
8+
import lombok.NoArgsConstructor;
9+
import ru.practicum.shareit.validation.OnCreate;
10+
import ru.practicum.shareit.validation.OnUpdate;
11+
312
/**
413
* TODO Sprint add-controllers.
514
*/
15+
@Data
16+
@AllArgsConstructor
17+
@NoArgsConstructor
618
public class ItemDto {
19+
private Long id;
20+
@Size(groups = OnUpdate.class, min = 1, message = "Название предмета должно быть заполнено")
21+
@NotBlank(groups = OnCreate.class, message = "Название предмета должно быть заполнено")
22+
private String name;
23+
@Size(groups = OnUpdate.class, min = 1, message = "Описание предмета должно быть заполнено")
24+
@NotBlank(groups = OnCreate.class, message = "Описание предмета должно быть заполнено")
25+
private String description;
26+
@NotNull(groups = OnCreate.class, message = "Статус должен быть заполнен")
27+
private Boolean available;
728
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,19 @@
11
package ru.practicum.shareit.item.model;
22

3+
import lombok.AllArgsConstructor;
4+
import lombok.Data;
5+
import lombok.NoArgsConstructor;
6+
37
/**
48
* TODO Sprint add-controllers.
59
*/
10+
@Data
11+
@AllArgsConstructor
12+
@NoArgsConstructor
613
public class Item {
14+
private Long id;
15+
private String name;
16+
private String description;
17+
private Boolean isAvailable;
18+
private Long ownerId;
719
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package ru.practicum.shareit.item.service;
2+
3+
import ru.practicum.shareit.item.dto.ItemDto;
4+
5+
import java.util.Collection;
6+
7+
public interface ItemService {
8+
ItemDto getItem(Long itemId);
9+
10+
Collection<ItemDto> searchItems(String text);
11+
12+
Collection<ItemDto> getItems(Long userId);
13+
14+
ItemDto addItem(Long userId, ItemDto itemDto);
15+
16+
ItemDto updateItem(Long userId, Long itemId, ItemDto itemDto);
17+
}
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
package ru.practicum.shareit.item.service;
2+
3+
import lombok.RequiredArgsConstructor;
4+
import org.springframework.stereotype.Service;
5+
import ru.practicum.shareit.item.ItemMapper;
6+
import ru.practicum.shareit.item.dao.ItemRepository;
7+
import ru.practicum.shareit.item.dto.ItemDto;
8+
import ru.practicum.shareit.item.model.Item;
9+
import ru.practicum.shareit.user.dao.UserRepository;
10+
import ru.practicum.shareit.validation.NotFoundException;
11+
12+
import java.util.Collection;
13+
import java.util.Collections;
14+
import java.util.Locale;
15+
import java.util.Optional;
16+
17+
@Service
18+
@RequiredArgsConstructor
19+
public class ItemServiceImpl implements ItemService {
20+
21+
private final ItemRepository itemRepository;
22+
private final UserRepository userRepository;
23+
24+
@Override
25+
public ItemDto getItem(Long itemId) {
26+
Optional<Item> maybeItem = itemRepository.getItem(itemId);
27+
28+
if (maybeItem.isPresent()) {
29+
return ItemMapper.toItemDto(maybeItem.get());
30+
}
31+
32+
throw new NotFoundException("Предмет с id " + itemId + " не найден");
33+
}
34+
35+
@Override
36+
public Collection<ItemDto> searchItems(String text) {
37+
if (text == null || text.isBlank()) {
38+
return Collections.emptyList();
39+
}
40+
41+
text = text.toLowerCase(Locale.ROOT);
42+
43+
return itemRepository.searchItems(text)
44+
.stream()
45+
.map(ItemMapper::toItemDto)
46+
.toList();
47+
}
48+
49+
@Override
50+
public Collection<ItemDto> getItems(Long userId) {
51+
throwIfUserNotFound(userId);
52+
53+
Collection<Item> items = itemRepository.getItems(userId);
54+
55+
return items.stream()
56+
.map(ItemMapper::toItemDto)
57+
.toList();
58+
}
59+
60+
@Override
61+
public ItemDto addItem(Long userId, ItemDto itemDto) {
62+
throwIfUserNotFound(userId);
63+
64+
Item item = ItemMapper.toItem(itemDto);
65+
item.setOwnerId(userId);
66+
67+
return ItemMapper.toItemDto(itemRepository.addItem(item));
68+
}
69+
70+
@Override
71+
public ItemDto updateItem(Long userId, Long itemId, ItemDto itemDto) {
72+
throwIfUserNotFound(userId);
73+
74+
Item item = ItemMapper.toItem(itemDto);
75+
item.setOwnerId(userId);
76+
item.setId(itemId);
77+
78+
Optional<Item> maybeItem = itemRepository.updateItem(item);
79+
80+
if (maybeItem.isPresent()) {
81+
return ItemMapper.toItemDto(maybeItem.get());
82+
}
83+
84+
throw new NotFoundException("Предмет с id " + itemId + " не найден");
85+
}
86+
87+
private void throwIfUserNotFound(Long userId) {
88+
if (!userRepository.contains(userId)) {
89+
throw new NotFoundException("Пользователь с id " + userId + " не найден");
90+
}
91+
}
92+
}

src/main/java/ru/practicum/shareit/user/User.java

Lines changed: 0 additions & 7 deletions
This file was deleted.

0 commit comments

Comments
 (0)