Skip to content

Commit 738b856

Browse files
author
LINESKL
committed
Merge branch 'development_l'
2 parents 6a155e7 + 84cbdd9 commit 738b856

24 files changed

Lines changed: 1609 additions & 115 deletions
Lines changed: 105 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -1,155 +1,150 @@
11
package com.stackscout.controller;
22

3-
import com.stackscout.dto.ErrorResponse;
4-
import com.stackscout.model.Library;
3+
import com.stackscout.dto.CreateLibraryRequest;
4+
import com.stackscout.dto.LibraryDto;
5+
import com.stackscout.dto.UpdateLibraryRequest;
6+
import com.stackscout.service.LibraryService;
7+
import io.swagger.v3.oas.annotations.Operation;
8+
import io.swagger.v3.oas.annotations.tags.Tag;
9+
import jakarta.validation.Valid;
10+
import lombok.RequiredArgsConstructor;
11+
import org.springframework.data.domain.Page;
12+
import org.springframework.data.domain.PageRequest;
13+
import org.springframework.data.domain.Pageable;
14+
import org.springframework.data.domain.Sort;
515
import org.springframework.http.HttpStatus;
616
import org.springframework.http.ResponseEntity;
717
import org.springframework.web.bind.annotation.*;
818

9-
import java.time.LocalDateTime;
10-
import java.util.ArrayList;
1119
import java.util.HashMap;
1220
import java.util.List;
1321
import java.util.Map;
1422

23+
/**
24+
* REST контроллер для управления библиотеками
25+
*/
1526
@RestController
1627
@RequestMapping("/api/v1/libraries")
1728
@CrossOrigin(origins = "*")
29+
@RequiredArgsConstructor
30+
@Tag(name = "Libraries", description = "API для управления библиотеками")
1831
public class LibraryController {
1932

20-
private final List<Library> libraries = new ArrayList<>();
21-
private Long nextId = 1L;
22-
23-
public LibraryController() {
24-
libraries.add(new Library(
25-
nextId++, "requests", "2.31.0", "pypi",
26-
"Apache-2.0", 95, "2023-05-22",
27-
"https://github.com/psf/requests",
28-
"HTTP библиотека для Python"
29-
));
30-
31-
libraries.add(new Library(
32-
nextId++, "django", "5.0.0", "pypi",
33-
"BSD-3-Clause", 98, "2023-12-04",
34-
"https://github.com/django/django",
35-
"Веб-фреймворк для Python"
36-
));
37-
38-
libraries.add(new Library(
39-
nextId++, "react", "18.2.0", "npm",
40-
"MIT", 99, "2023-06-14",
41-
"https://github.com/facebook/react",
42-
"JavaScript библиотека для UI"
43-
));
44-
}
33+
private final LibraryService libraryService;
4534

35+
@Operation(summary = "Получить все библиотеки", description = "Возвращает список всех библиотек с пагинацией")
4636
@GetMapping
4737
public ResponseEntity<Map<String, Object>> getAllLibraries(
4838
@RequestParam(defaultValue = "0") int page,
49-
@RequestParam(defaultValue = "10") int size
39+
@RequestParam(defaultValue = "10") int size,
40+
@RequestParam(defaultValue = "id") String sortBy,
41+
@RequestParam(defaultValue = "ASC") String sortDirection
5042
) {
51-
int start = Math.min(page * size, libraries.size());
52-
int end = Math.min(start + size, libraries.size());
53-
List<Library> paginatedLibraries = libraries.subList(start, end);
43+
Sort.Direction direction = Sort.Direction.fromString(sortDirection);
44+
Pageable pageable = PageRequest.of(page, size, Sort.by(direction, sortBy));
45+
46+
Page<LibraryDto> librariesPage = libraryService.getAllLibraries(pageable);
5447

5548
Map<String, Object> response = new HashMap<>();
56-
response.put("libraries", paginatedLibraries);
57-
response.put("totalElements", libraries.size());
58-
response.put("currentPage", page);
59-
response.put("pageSize", size);
60-
response.put("totalPages", (int) Math.ceil((double) libraries.size() / size));
49+
response.put("libraries", librariesPage.getContent());
50+
response.put("totalElements", librariesPage.getTotalElements());
51+
response.put("currentPage", librariesPage.getNumber());
52+
response.put("pageSize", librariesPage.getSize());
53+
response.put("totalPages", librariesPage.getTotalPages());
6154

6255
return ResponseEntity.ok(response);
6356
}
6457

58+
@Operation(summary = "Получить библиотеку по ID", description = "Возвращает детали конкретной библиотеки")
6559
@GetMapping("/{id}")
66-
public ResponseEntity<Library> getLibraryById(@PathVariable Long id) {
67-
return libraries.stream()
68-
.filter(lib -> lib.getId().equals(id))
69-
.findFirst()
70-
.map(ResponseEntity::ok)
71-
.orElse(ResponseEntity.notFound().build());
60+
public ResponseEntity<LibraryDto> getLibraryById(@PathVariable Long id) {
61+
LibraryDto library = libraryService.getLibraryById(id);
62+
return ResponseEntity.ok(library);
7263
}
7364

65+
@Operation(summary = "Поиск библиотек", description = "Поиск библиотек по названию и/или источнику")
7466
@GetMapping("/search")
75-
public ResponseEntity<List<Library>> searchLibraries(
67+
public ResponseEntity<Map<String, Object>> searchLibraries(
7668
@RequestParam(required = false) String query,
77-
@RequestParam(required = false) String source
69+
@RequestParam(required = false) String source,
70+
@RequestParam(defaultValue = "0") int page,
71+
@RequestParam(defaultValue = "10") int size
7872
) {
79-
List<Library> result = libraries.stream()
80-
.filter(lib -> {
81-
boolean matchQuery = query == null ||
82-
lib.getName().toLowerCase().contains(query.toLowerCase());
83-
boolean matchSource = source == null ||
84-
lib.getSource().equalsIgnoreCase(source);
85-
return matchQuery && matchSource;
86-
})
87-
.toList();
88-
return ResponseEntity.ok(result);
73+
Pageable pageable = PageRequest.of(page, size);
74+
Page<LibraryDto> result;
75+
76+
if (query != null && !query.trim().isEmpty() && source != null && !source.trim().isEmpty()) {
77+
result = libraryService.searchLibrariesBySource(query, source, pageable);
78+
} else if (query != null && !query.trim().isEmpty()) {
79+
result = libraryService.searchLibraries(query, pageable);
80+
} else if (source != null && !source.trim().isEmpty()) {
81+
result = libraryService.getLibrariesBySource(source, pageable);
82+
} else {
83+
result = libraryService.getAllLibraries(pageable);
84+
}
85+
86+
Map<String, Object> response = new HashMap<>();
87+
response.put("libraries", result.getContent());
88+
response.put("totalElements", result.getTotalElements());
89+
response.put("currentPage", result.getNumber());
90+
response.put("totalPages", result.getTotalPages());
91+
92+
return ResponseEntity.ok(response);
8993
}
9094

95+
@Operation(summary = "Создать новую библиотеку", description = "Добавляет новую библиотеку в систему")
9196
@PostMapping
92-
public ResponseEntity<?> createLibrary(@RequestBody Library library) {
93-
try {
94-
if (library.getName() == null || library.getName().trim().isEmpty()) {
95-
return ResponseEntity.badRequest()
96-
.body(new ErrorResponse("Имя библиотеки обязательно", LocalDateTime.now()));
97-
}
98-
99-
library.setId(nextId++);
100-
libraries.add(library);
101-
102-
Map<String, Object> response = new HashMap<>();
103-
response.put("message", "Библиотека успешно создана");
104-
response.put("library", library);
105-
106-
return ResponseEntity.status(HttpStatus.CREATED).body(response);
107-
} catch (Exception e) {
108-
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
109-
.body(new ErrorResponse("Ошибка при создании библиотеки: " + e.getMessage(), LocalDateTime.now()));
110-
}
97+
public ResponseEntity<Map<String, Object>> createLibrary(@Valid @RequestBody CreateLibraryRequest request) {
98+
LibraryDto createdLibrary = libraryService.createLibrary(request);
99+
100+
Map<String, Object> response = new HashMap<>();
101+
response.put("message", "Библиотека успешно создана");
102+
response.put("library", createdLibrary);
103+
104+
return ResponseEntity.status(HttpStatus.CREATED).body(response);
111105
}
112106

107+
@Operation(summary = "Обновить библиотеку", description = "Обновляет существующую библиотеку")
113108
@PutMapping("/{id}")
114-
public ResponseEntity<?> updateLibrary(@PathVariable Long id, @RequestBody Library updatedLibrary) {
115-
return libraries.stream()
116-
.filter(lib -> lib.getId().equals(id))
117-
.findFirst()
118-
.<ResponseEntity<?>>map(library -> {
119-
if (updatedLibrary.getName() != null) library.setName(updatedLibrary.getName());
120-
if (updatedLibrary.getVersion() != null) library.setVersion(updatedLibrary.getVersion());
121-
if (updatedLibrary.getSource() != null) library.setSource(updatedLibrary.getSource());
122-
if (updatedLibrary.getLicense() != null) library.setLicense(updatedLibrary.getLicense());
123-
if (updatedLibrary.getHealthScore() != null) library.setHealthScore(updatedLibrary.getHealthScore());
124-
if (updatedLibrary.getLastRelease() != null) library.setLastRelease(updatedLibrary.getLastRelease());
125-
if (updatedLibrary.getRepository() != null) library.setRepository(updatedLibrary.getRepository());
126-
if (updatedLibrary.getDescription() != null) library.setDescription(updatedLibrary.getDescription());
127-
128-
Map<String, Object> response = new HashMap<>();
129-
response.put("message", "Библиотека успешно обновлена");
130-
response.put("library", library);
131-
return ResponseEntity.ok(response);
132-
})
133-
.orElseGet(() -> ResponseEntity.status(HttpStatus.NOT_FOUND)
134-
.body(new ErrorResponse("Библиотека с ID " + id + " не найдена", LocalDateTime.now())));
109+
public ResponseEntity<Map<String, Object>> updateLibrary(
110+
@PathVariable Long id,
111+
@Valid @RequestBody UpdateLibraryRequest request) {
112+
113+
LibraryDto updatedLibrary = libraryService.updateLibrary(id, request);
114+
115+
Map<String, Object> response = new HashMap<>();
116+
response.put("message", "Библиотека успешно обновлена");
117+
response.put("library", updatedLibrary);
118+
119+
return ResponseEntity.ok(response);
135120
}
136121

122+
@Operation(summary = "Удалить библиотеку", description = "Удаляет библиотеку из системы")
137123
@DeleteMapping("/{id}")
138-
public ResponseEntity<?> deleteLibrary(@PathVariable Long id) {
139-
boolean removed = libraries.removeIf(lib -> lib.getId().equals(id));
140-
if (removed) {
141-
Map<String, String> response = new HashMap<>();
142-
response.put("message", "Библиотека успешно удалена");
143-
response.put("id", id.toString());
144-
return ResponseEntity.ok(response);
145-
} else {
146-
return ResponseEntity.status(HttpStatus.NOT_FOUND)
147-
.body(new ErrorResponse("Библиотека с ID " + id + " не найдена", LocalDateTime.now()));
148-
}
124+
public ResponseEntity<Map<String, String>> deleteLibrary(@PathVariable Long id) {
125+
libraryService.deleteLibrary(id);
126+
127+
Map<String, String> response = new HashMap<>();
128+
response.put("message", "Библиотека успешно удалена");
129+
response.put("id", id.toString());
130+
131+
return ResponseEntity.ok(response);
149132
}
150133

134+
@Operation(summary = "Получить здоровые библиотеки", description = "Возвращает библиотеки с оценкой здоровья выше заданного порога")
135+
@GetMapping("/healthy")
136+
public ResponseEntity<List<LibraryDto>> getHealthyLibraries(
137+
@RequestParam(defaultValue = "80") Integer minScore) {
138+
List<LibraryDto> healthyLibraries = libraryService.getHealthyLibraries(minScore);
139+
return ResponseEntity.ok(healthyLibraries);
140+
}
141+
142+
@Operation(summary = "Статистика библиотек", description = "Возвращает общую статистику по библиотекам")
151143
@GetMapping("/stats")
152144
public ResponseEntity<Map<String, Object>> getStats() {
145+
Page<LibraryDto> allLibraries = libraryService.getAllLibraries(Pageable.unpaged());
146+
List<LibraryDto> libraries = allLibraries.getContent();
147+
153148
Map<String, Object> stats = new HashMap<>();
154149
stats.put("totalLibraries", libraries.size());
155150
stats.put("sources", Map.of(
@@ -159,10 +154,12 @@ public ResponseEntity<Map<String, Object>> getStats() {
159154
));
160155
stats.put("averageHealthScore",
161156
libraries.stream()
162-
.mapToInt(l -> l.getHealthScore() != null ? l.getHealthScore() : 0)
157+
.filter(l -> l.getHealthScore() != null)
158+
.mapToInt(LibraryDto::getHealthScore)
163159
.average()
164160
.orElse(0.0)
165161
);
162+
166163
return ResponseEntity.ok(stats);
167164
}
168165
}
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
package com.stackscout.controller;
2+
3+
import com.stackscout.dto.CreateLicenseRequest;
4+
import com.stackscout.dto.LicenseDto;
5+
import com.stackscout.model.License;
6+
import com.stackscout.service.LicenseService;
7+
import io.swagger.v3.oas.annotations.Operation;
8+
import io.swagger.v3.oas.annotations.tags.Tag;
9+
import jakarta.validation.Valid;
10+
import lombok.RequiredArgsConstructor;
11+
import org.springframework.data.domain.Page;
12+
import org.springframework.data.domain.PageRequest;
13+
import org.springframework.data.domain.Pageable;
14+
import org.springframework.data.domain.Sort;
15+
import org.springframework.http.HttpStatus;
16+
import org.springframework.http.ResponseEntity;
17+
import org.springframework.web.bind.annotation.*;
18+
19+
import java.util.HashMap;
20+
import java.util.List;
21+
import java.util.Map;
22+
23+
/**
24+
* REST контроллер для управления лицензиями
25+
*/
26+
@RestController
27+
@RequestMapping("/api/v1/licenses")
28+
@CrossOrigin(origins = "*")
29+
@RequiredArgsConstructor
30+
@Tag(name = "Licenses", description = "API для управления лицензиями")
31+
public class LicenseController {
32+
33+
private final LicenseService licenseService;
34+
35+
@Operation(summary = "Получить все лицензии", description = "Возвращает список всех лицензий с пагинацией")
36+
@GetMapping
37+
public ResponseEntity<Map<String, Object>> getAllLicenses(
38+
@RequestParam(defaultValue = "0") int page,
39+
@RequestParam(defaultValue = "10") int size,
40+
@RequestParam(defaultValue = "name") String sortBy,
41+
@RequestParam(defaultValue = "ASC") String sortDirection
42+
) {
43+
Sort.Direction direction = Sort.Direction.fromString(sortDirection);
44+
Pageable pageable = PageRequest.of(page, size, Sort.by(direction, sortBy));
45+
46+
Page<LicenseDto> licensesPage = licenseService.getAllLicenses(pageable);
47+
48+
Map<String, Object> response = new HashMap<>();
49+
response.put("licenses", licensesPage.getContent());
50+
response.put("totalElements", licensesPage.getTotalElements());
51+
response.put("currentPage", licensesPage.getNumber());
52+
response.put("pageSize", licensesPage.getSize());
53+
response.put("totalPages", licensesPage.getTotalPages());
54+
55+
return ResponseEntity.ok(response);
56+
}
57+
58+
@Operation(summary = "Получить лицензию по ID", description = "Возвращает детали конкретной лицензии")
59+
@GetMapping("/{id}")
60+
public ResponseEntity<LicenseDto> getLicenseById(@PathVariable Long id) {
61+
LicenseDto license = licenseService.getLicenseById(id);
62+
return ResponseEntity.ok(license);
63+
}
64+
65+
@Operation(summary = "Создать новую лицензию", description = "Добавляет новую лицензию в систему")
66+
@PostMapping
67+
public ResponseEntity<Map<String, Object>> createLicense(@Valid @RequestBody CreateLicenseRequest request) {
68+
LicenseDto createdLicense = licenseService.createLicense(request);
69+
70+
Map<String, Object> response = new HashMap<>();
71+
response.put("message", "Лицензия успешно создана");
72+
response.put("license", createdLicense);
73+
74+
return ResponseEntity.status(HttpStatus.CREATED).body(response);
75+
}
76+
77+
@Operation(summary = "Обновить лицензию", description = "Обновляет существующую лицензию")
78+
@PutMapping("/{id}")
79+
public ResponseEntity<Map<String, Object>> updateLicense(
80+
@PathVariable Long id,
81+
@Valid @RequestBody CreateLicenseRequest request) {
82+
83+
LicenseDto updatedLicense = licenseService.updateLicense(id, request);
84+
85+
Map<String, Object> response = new HashMap<>();
86+
response.put("message", "Лицензия успешно обновлена");
87+
response.put("license", updatedLicense);
88+
89+
return ResponseEntity.ok(response);
90+
}
91+
92+
@Operation(summary = "Удалить лицензию", description = "Удаляет лицензию из системы")
93+
@DeleteMapping("/{id}")
94+
public ResponseEntity<Map<String, String>> deleteLicense(@PathVariable Long id) {
95+
licenseService.deleteLicense(id);
96+
97+
Map<String, String> response = new HashMap<>();
98+
response.put("message", "Лицензия успешно удалена");
99+
response.put("id", id.toString());
100+
101+
return ResponseEntity.ok(response);
102+
}
103+
104+
@Operation(summary = "Найти лицензию по имени", description = "Возвращает лицензию с указанным именем")
105+
@GetMapping("/search")
106+
public ResponseEntity<LicenseDto> findByName(@RequestParam String name) {
107+
LicenseDto license = licenseService.findByName(name);
108+
return ResponseEntity.ok(license);
109+
}
110+
111+
@Operation(summary = "Получить лицензии по типу", description = "Возвращает все лицензии указанного типа")
112+
@GetMapping("/type/{type}")
113+
public ResponseEntity<List<LicenseDto>> getLicensesByType(@PathVariable License.LicenseType type) {
114+
List<LicenseDto> licenses = licenseService.getLicensesByType(type);
115+
return ResponseEntity.ok(licenses);
116+
}
117+
118+
@Operation(summary = "Получить OSI-одобренные лицензии", description = "Возвращает все OSI-одобренные лицензии")
119+
@GetMapping("/osi-approved")
120+
public ResponseEntity<List<LicenseDto>> getOsiApprovedLicenses() {
121+
List<LicenseDto> licenses = licenseService.getOsiApprovedLicenses();
122+
return ResponseEntity.ok(licenses);
123+
}
124+
}

0 commit comments

Comments
 (0)