Skip to content

Commit ab4a320

Browse files
feat(rest): Api endpoint to retrieve package usage count
1 parent 9073eaa commit ab4a320

File tree

5 files changed

+137
-1
lines changed

5 files changed

+137
-1
lines changed

backend/common/src/main/java/org/eclipse/sw360/datahandler/db/ProjectRepository.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ public class ProjectRepository extends SummaryAwareRepository<Project> {
220220
"function(doc) {" +
221221
" if (doc.type == 'project' && doc.packageIds) {" +
222222
" for(var i in doc.packageIds) {" +
223-
" emit(doc.packageIds[i], doc._id);" +
223+
" emit(i, doc._id);" +
224224
" }" +
225225
" }" +
226226
"}";

rest/resource-server/src/docs/asciidoc/packages.adoc

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,3 +135,44 @@ include::{snippets}/should_document_delete_package/curl-request.adoc[]
135135

136136
===== Example response
137137
include::{snippets}/should_document_delete_package/http-response.adoc[]
138+
139+
140+
[[resources-package-usage]]
141+
==== Get Package Usage Information
142+
143+
A `GET` request to `/api/packages/{id}/usage` will get the usage information for a specific package, including whether the package is being used and the count of projects using it.
144+
145+
===== Path parameters
146+
[cols="2,1,2"]
147+
|===
148+
|Name |Type |Description
149+
150+
|id
151+
|String
152+
|The ID of the package to check usage for
153+
|===
154+
155+
===== Response structure
156+
[cols="2,1,2"]
157+
|===
158+
|Path |Type |Description
159+
160+
|count
161+
|Number
162+
|Number of projects using this package
163+
164+
|isUsed
165+
|Boolean
166+
|Flag indicating if the package is used in any project
167+
|===
168+
169+
===== Example request
170+
include::{snippets}/should_document_get_package_usage/curl-request.adoc[]
171+
172+
===== Example response
173+
include::{snippets}/should_document_get_package_usage/http-response.adoc[]
174+
175+
===== Error response
176+
When the package is not found:
177+
178+
include::{snippets}/should_document_get_package_usage_not_found/http-response.adoc[]

rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/packages/PackageController.java

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
import org.eclipse.sw360.rest.resourceserver.core.HalResource;
5353
import org.eclipse.sw360.rest.resourceserver.core.OpenAPIPaginationHelper;
5454
import org.eclipse.sw360.rest.resourceserver.core.RestControllerHelper;
55+
import org.eclipse.sw360.rest.resourceserver.project.Sw360ProjectService;
5556
import org.eclipse.sw360.rest.resourceserver.release.Sw360ReleaseService;
5657
import org.eclipse.sw360.rest.resourceserver.user.Sw360UserService;
5758
import org.jetbrains.annotations.NotNull;
@@ -87,6 +88,9 @@ public class PackageController implements RepresentationModelProcessor<Repositor
8788
@NonNull
8889
private final SW360PackageService packageService;
8990

91+
@NonNull
92+
private final Sw360ProjectService projectService;
93+
9094
@NonNull
9195
private Sw360ReleaseService releaseService;
9296

@@ -421,4 +425,41 @@ private ResponseEntity<CollectionModel<EntityModel<Package>>> getPackageResponse
421425
}
422426
return filterMap;
423427
}
428+
429+
@Operation(
430+
summary = "Check if a package is being used and get the count.",
431+
description = "Returns whether the package is being used and the total count of usages.",
432+
tags = {"Packages"},
433+
responses = {
434+
@ApiResponse(
435+
responseCode = "200", description = "Package usage information",
436+
content = {
437+
@Content(mediaType = "application/json",
438+
schema = @Schema(
439+
example = """
440+
{
441+
isUsed: true,
442+
count: 5
443+
}
444+
"""
445+
)
446+
)
447+
}
448+
)
449+
}
450+
)
451+
452+
@RequestMapping(value = PACKAGES_URL + "/{id}/usage", method = RequestMethod.GET)
453+
public ResponseEntity<Map<String, Object>> getPackageUsageInfo(
454+
@Parameter(description = "The id of the package to check usage for")
455+
@PathVariable("id") String id
456+
) throws TException {
457+
458+
Map<String, Object> response = new HashMap<>();
459+
int usageCount = projectService.getProjectCountByPackageId(id);
460+
response.put("isUsed", usageCount > 0);
461+
response.put("count", usageCount);
462+
463+
return new ResponseEntity<>(response, HttpStatus.OK);
464+
}
424465
}

rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/project/Sw360ProjectService.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1888,4 +1888,21 @@ private static PaginationData pageableToPaginationData(
18881888
return new PaginationData().setDisplayStart((int) pageable.getOffset())
18891889
.setRowsPerPage(pageable.getPageSize()).setSortColumnNumber(column.getValue()).setAscending(ascending);
18901890
}
1891+
1892+
public int getProjectCountByPackageId(String packageId) throws TException {
1893+
ThriftClients thriftClients = new ThriftClients();
1894+
ProjectService.Iface projectClient = thriftClients.makeProjectClient();
1895+
int count;
1896+
try {
1897+
count = projectClient.getProjectCountByPackageId(packageId);
1898+
} catch (SW360Exception sw360Exp) {
1899+
if (sw360Exp.getErrorCode() == 404) {
1900+
throw new ResourceNotFoundException("Requested Package Id Not Found");
1901+
}
1902+
else {
1903+
throw sw360Exp;
1904+
}
1905+
}
1906+
return count;
1907+
}
18911908
}

rest/resource-server/src/test/java/org/eclipse/sw360/rest/resourceserver/restdocs/PackageSpecTest.java

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
import org.eclipse.sw360.datahandler.thrift.users.UserGroup;
5252
import org.eclipse.sw360.rest.resourceserver.TestHelper;
5353
import org.eclipse.sw360.rest.resourceserver.packages.SW360PackageService;
54+
import org.eclipse.sw360.rest.resourceserver.project.Sw360ProjectService;
5455
import org.eclipse.sw360.rest.resourceserver.release.Sw360ReleaseService;
5556
import org.hamcrest.Matchers;
5657
import org.junit.Before;
@@ -60,6 +61,7 @@
6061
import org.springframework.hateoas.MediaTypes;
6162
import org.springframework.test.context.bean.override.mockito.MockitoBean;
6263
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
64+
import org.springframework.data.rest.webmvc.ResourceNotFoundException;
6365

6466
@RunWith(SpringJUnit4ClassRunner.class)
6567
public class PackageSpecTest extends TestRestDocsSpecBase {
@@ -76,6 +78,9 @@ public class PackageSpecTest extends TestRestDocsSpecBase {
7678
@MockitoBean
7779
private Sw360ReleaseService releaseServiceMock;
7880

81+
@MockitoBean
82+
private Sw360ProjectService projectServiceMock;
83+
7984
private Package package1;
8085
private Package package2;
8186
private Package package3;
@@ -465,4 +470,36 @@ public void should_document_delete_package() throws Exception {
465470
.accept(MediaTypes.HAL_JSON))
466471
.andExpect(status().isOk());
467472
}
473+
474+
@Test
475+
public void should_document_get_package_usage() throws Exception {
476+
String packageId = package1.getId();
477+
int projectCount = 5;
478+
479+
given(projectServiceMock.getProjectCountByPackageId(packageId)).willReturn(projectCount);
480+
481+
mockMvc.perform(get("/api/packages/" + packageId + "/usage")
482+
.header("Authorization", TestHelper.generateAuthHeader(testUserId, testUserPassword))
483+
.accept(MediaTypes.HAL_JSON))
484+
.andExpect(status().isOk())
485+
.andDo(this.documentationHandler.document(
486+
responseFields(
487+
fieldWithPath("count").description("Number of projects using this package"),
488+
fieldWithPath("isUsed").description("Flag indicating if the package is used in any project")
489+
)));
490+
}
491+
492+
@Test
493+
public void should_document_get_package_usage_not_found() throws Exception {
494+
String packageId = "non-existent-id";
495+
496+
given(projectServiceMock.getProjectCountByPackageId(packageId))
497+
.willThrow(new ResourceNotFoundException("Could not find package with id: " + packageId));
498+
499+
mockMvc.perform(get("/api/packages/" + packageId + "/usage")
500+
.header("Authorization", TestHelper.generateAuthHeader(testUserId, testUserPassword))
501+
.accept(MediaTypes.HAL_JSON))
502+
.andExpect(status().isNotFound());
503+
}
504+
468505
}

0 commit comments

Comments
 (0)