diff --git a/rest/resource-server/src/docs/asciidoc/projects.adoc b/rest/resource-server/src/docs/asciidoc/projects.adoc index fbb0356100..676ef16ca5 100644 --- a/rest/resource-server/src/docs/asciidoc/projects.adoc +++ b/rest/resource-server/src/docs/asciidoc/projects.adoc @@ -421,6 +421,20 @@ include::{snippets}/should_document_get_project_releases_ecc_information/http-re ===== Links include::{snippets}/should_document_get_project_releases_ecc_information/links.adoc[] +[[resources-project-get-license-obligation-information]] +==== Listing obligations from licenseDB + +A `GET` request will get all license obligations from licenseDB. + +===== Response structure +include::{snippets}/should_document_get_obligations_from_license_db/response-fields.adoc[] + +===== Example request +include::{snippets}/should_document_get_obligations_from_license_db/curl-request.adoc[] + +===== Example response +include::{snippets}/should_document_get_obligations_from_license_db/http-response.adoc[] + [[resources-project-get-license-clearing-information-information]] ==== Project's license clearing count diff --git a/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/core/JacksonCustomizations.java b/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/core/JacksonCustomizations.java index 87e994877a..e23f122844 100644 --- a/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/core/JacksonCustomizations.java +++ b/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/core/JacksonCustomizations.java @@ -37,6 +37,7 @@ import org.eclipse.sw360.datahandler.thrift.moderation.ModerationRequest; import org.eclipse.sw360.datahandler.thrift.packages.Package; import org.eclipse.sw360.datahandler.thrift.projects.ClearingRequest; +import org.eclipse.sw360.datahandler.thrift.projects.ObligationStatusInfo; import org.eclipse.sw360.datahandler.thrift.projects.Project; import org.eclipse.sw360.datahandler.thrift.projects.ProjectProjectRelationship; import org.eclipse.sw360.datahandler.thrift.projects.ProjectState; @@ -106,6 +107,7 @@ public Sw360Module() { setMixInAnnotation(ClearingRequest.class, Sw360Module.ClearingRequestMixin.class); setMixInAnnotation(Comment.class, Sw360Module.CommentMixin.class); setMixInAnnotation(ProjectReleaseRelationship.class, Sw360Module.ProjectReleaseRelationshipMixin.class); + setMixInAnnotation(ObligationStatusInfo.class, Sw360Module.ObligationStatusInfoMixin.class); setMixInAnnotation(ReleaseVulnerabilityRelation.class, Sw360Module.ReleaseVulnerabilityRelationMixin.class); setMixInAnnotation(VerificationStateInfo.class, Sw360Module.VerificationStateInfoMixin.class); setMixInAnnotation(ProjectProjectRelationship.class, Sw360Module.ProjectProjectRelationshipMixin.class); @@ -156,6 +158,7 @@ public Sw360Module() { .replaceWithClass(ClearingRequest.class, ClearingRequestMixin.class) .replaceWithClass(Comment.class, CommentMixin.class) .replaceWithClass(ProjectReleaseRelationship.class, ProjectReleaseRelationshipMixin.class) + .replaceWithClass(ObligationStatusInfo.class, ObligationStatusInfoMixin.class) .replaceWithClass(ReleaseVulnerabilityRelation.class, ReleaseVulnerabilityRelationMixin.class) .replaceWithClass(VerificationStateInfo.class, VerificationStateInfoMixin.class) .replaceWithClass(ProjectProjectRelationship.class, ProjectProjectRelationshipMixin.class) @@ -1810,6 +1813,29 @@ public static abstract class CommentMixin extends Comment { public static abstract class ProjectReleaseRelationshipMixin extends ProjectReleaseRelationship { } + @JsonInclude(JsonInclude.Include.NON_NULL) + @JsonIgnoreProperties({ + "setComment", + "setText", + "setObligationType", + "setObligationLevel", + "setModifiedBy", + "setModifiedOn", + "setId", + "setStatus", + "setAction", + "setLicenseIds", + "setReleaseIdToAcceptedCLI", + "releaseIdToAcceptedCLISize", + "releasesSize", + "releasesIterator", + "setReleases", + "licenseIdsSize", + "licenseIdsIterator" + }) + public static abstract class ObligationStatusInfoMixin extends ObligationStatusInfo { + } + @JsonInclude(JsonInclude.Include.NON_NULL) @JsonIgnoreProperties({ "setId", diff --git a/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/project/ProjectController.java b/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/project/ProjectController.java index bcca7e42f3..e181fe218e 100644 --- a/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/project/ProjectController.java +++ b/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/project/ProjectController.java @@ -19,6 +19,7 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Lists; +import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.google.gson.Gson; import com.google.gson.JsonObject; @@ -48,6 +49,7 @@ import org.eclipse.sw360.datahandler.resourcelists.PaginationResult; import org.eclipse.sw360.datahandler.resourcelists.ResourceClassNotFoundException; import org.eclipse.sw360.datahandler.thrift.MainlineState; +import org.eclipse.sw360.datahandler.thrift.ObligationStatus; import org.eclipse.sw360.datahandler.thrift.ProjectReleaseRelationship; import org.eclipse.sw360.datahandler.thrift.ReleaseRelationship; import org.eclipse.sw360.datahandler.thrift.RequestStatus; @@ -71,6 +73,8 @@ import org.eclipse.sw360.datahandler.thrift.licenseinfo.OutputFormatInfo; import org.eclipse.sw360.datahandler.thrift.licenseinfo.OutputFormatVariant; import org.eclipse.sw360.datahandler.thrift.licenses.License; +import org.eclipse.sw360.datahandler.thrift.projects.ObligationList; +import org.eclipse.sw360.datahandler.thrift.projects.ObligationStatusInfo; import org.eclipse.sw360.datahandler.thrift.projects.Project; import org.eclipse.sw360.datahandler.thrift.projects.ProjectClearingState; import org.eclipse.sw360.datahandler.thrift.projects.ProjectLink; @@ -1961,6 +1965,32 @@ public void getlicenseClearingCount(HttpServletResponse response , } } + @Operation( + description = "Get license obligations data from license database.", + tags = {"Project"} + ) + @RequestMapping(value = PROJECTS_URL + "/{id}/licenseDbObligations", method = RequestMethod.GET) + public ResponseEntity getLicObligations(Pageable pageable, + @Parameter(description = "Project ID.") @PathVariable("id") String id, HttpServletRequest request) + throws TException, URISyntaxException, PaginationParameterException, ResourceClassNotFoundException { + + final User sw360User = restControllerHelper.getSw360UserFromAuthentication(); + final Project sw360Project = projectService.getProjectForUserById(id, sw360User); + if (CommonUtils.isNullOrEmptyMap(sw360Project.getReleaseIdToUsage())) { + return new ResponseEntity("No release linked to the project", HttpStatus.CONFLICT); + } + Map licenseInfoAttachmentUsage = projectService.getLicenseInfoAttachmentUsage(id); + if(licenseInfoAttachmentUsage.size() == 0) { + return new ResponseEntity("No approved CLI or licenseInfo attachment usage present for the project", HttpStatus.CONFLICT); + } + Map> licensesFromAttachmentUsage = projectService.getLicensesFromAttachmentUsage( + licenseInfoAttachmentUsage, sw360Project.getReleaseIdToUsage(), sw360User); + Map licenseObligation = projectService.getLicenseObligationData(licensesFromAttachmentUsage, sw360User); + + HalResource> halObligation = new HalResource<>(licenseObligation); + return new ResponseEntity<>(halObligation, HttpStatus.OK); + } + @Operation( description = "Get summary and administration page of project tab.", tags = {"Projects"} diff --git a/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/project/Sw360ProjectService.java b/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/project/Sw360ProjectService.java index 78ad7207a7..967dcc2d40 100644 --- a/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/project/Sw360ProjectService.java +++ b/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/project/Sw360ProjectService.java @@ -20,6 +20,7 @@ import org.apache.thrift.transport.TTransportException; import org.eclipse.sw360.datahandler.common.CommonUtils; import org.eclipse.sw360.datahandler.common.SW360Utils; +import org.eclipse.sw360.datahandler.common.WrappedException.WrappedTException; import org.eclipse.sw360.datahandler.thrift.AddDocumentRequestStatus; import org.eclipse.sw360.datahandler.thrift.AddDocumentRequestSummary; import org.eclipse.sw360.datahandler.thrift.PaginationData; @@ -28,16 +29,27 @@ import org.eclipse.sw360.datahandler.thrift.RequestStatus; import org.eclipse.sw360.datahandler.thrift.RequestSummary; import org.eclipse.sw360.datahandler.thrift.SW360Exception; +import org.eclipse.sw360.datahandler.thrift.Source; import org.eclipse.sw360.datahandler.thrift.ThriftClients; -import org.eclipse.sw360.datahandler.thrift.attachments.Attachment; -import org.eclipse.sw360.datahandler.thrift.attachments.AttachmentType; +import org.eclipse.sw360.datahandler.thrift.attachments.*; +import org.eclipse.sw360.datahandler.thrift.components.ComponentService; import org.eclipse.sw360.datahandler.thrift.components.Release; import org.eclipse.sw360.datahandler.thrift.components.ReleaseClearingStatusData; import org.eclipse.sw360.datahandler.thrift.components.ReleaseLink; +import org.eclipse.sw360.datahandler.thrift.licenseinfo.LicenseInfoParsingResult; +import org.eclipse.sw360.datahandler.thrift.licenseinfo.LicenseInfoService; +import org.eclipse.sw360.datahandler.thrift.licenseinfo.LicenseObligationsStatusInfo; +import org.eclipse.sw360.datahandler.thrift.licenseinfo.ObligationParsingResult; +import org.eclipse.sw360.datahandler.thrift.licenses.LicenseService; +import org.eclipse.sw360.datahandler.thrift.licenses.License; +import org.eclipse.sw360.datahandler.thrift.licenses.ObligationType; +import org.eclipse.sw360.datahandler.thrift.projects.ObligationList; +import org.eclipse.sw360.datahandler.thrift.projects.ObligationStatusInfo; import org.eclipse.sw360.datahandler.thrift.projects.Project; import org.eclipse.sw360.datahandler.thrift.projects.ProjectClearingState; import org.eclipse.sw360.datahandler.thrift.projects.ProjectData; import org.eclipse.sw360.datahandler.thrift.projects.ProjectLink; +import org.eclipse.sw360.datahandler.common.ThriftEnumUtils; import org.eclipse.sw360.datahandler.thrift.projects.ProjectService; import org.eclipse.sw360.datahandler.thrift.projects.ProjectProjectRelationship; import org.eclipse.sw360.datahandler.thrift.users.User; @@ -57,14 +69,19 @@ import org.springframework.security.access.AccessDeniedException; import org.springframework.stereotype.Service; +import com.google.common.collect.Sets; + import javax.annotation.PreDestroy; + import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; +import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Map.Entry; import java.util.Optional; import java.util.Set; @@ -74,8 +91,10 @@ import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; +import java.util.function.BiFunction; import java.util.function.Function; import java.util.function.Predicate; +import java.util.stream.Collector; import java.util.stream.Collectors; import static com.google.common.base.Strings.nullToEmpty; @@ -128,6 +147,185 @@ public Project getProjectForUserById(String projectId, User sw360User) throws TE } } + public Map> getLicensesFromAttachmentUsage( + Map licenseInfoAttachmentUsage, + Map releaseIdToUsage, User user) { + ThriftClients thriftClients = new ThriftClients(); + LicenseInfoService.Iface licenseInfoClient = thriftClients.makeLicenseInfoClient(); + ComponentService.Iface componentClient = thriftClients.makeComponentClient(); + Map attachmentIdToReleaseMap = new HashMap(); + Map> licenseIdToReleasesMap = new HashMap<>(); + licenseInfoAttachmentUsage.entrySet().stream() + .filter(entry -> entry.getKey() != null && entry.getValue() != null).forEach(entry -> { + String releaseId = entry.getValue().getOwner().getReleaseId(); + Release releaseById = null; + try { + releaseById = componentClient.getReleaseById(releaseId, user); + } catch (TException exp) { + log.warn("Error fetching Release from backend! Release Id-" + releaseId, exp.getMessage()); + return; + } + if (CommonUtils.isNullOrEmptyCollection(releaseById.getAttachments())) + return; + + Set attachmentFiltered = releaseById.getAttachments().stream().filter(Objects::nonNull) + .filter(att -> entry.getKey().equals(att.getAttachmentContentId())) + .filter(att -> att.getCheckStatus() != null && att.getCheckStatus() == CheckStatus.ACCEPTED) + .collect(Collectors.toSet()); + + if (CommonUtils.isNullOrEmptyCollection(attachmentFiltered)) + return; + releaseById.setAttachments(attachmentFiltered); + + attachmentIdToReleaseMap.put(entry.getKey(), releaseById); + }); + + attachmentIdToReleaseMap.entrySet().stream().filter(entry -> entry.getKey() != null && entry.getValue() != null) + .forEach(entry -> wrapTException(() -> { + List licenseInfoForAttachment = licenseInfoClient + .getLicenseInfoForAttachment(entry.getValue(), entry.getKey(), false, user); + Set licenseIds = licenseInfoForAttachment.stream().filter(Objects::nonNull) + .filter(lia -> lia.getLicenseInfo() != null) + .filter(lia -> lia.getLicenseInfo().getLicenseNamesWithTexts() != null) + .flatMap(lia -> lia.getLicenseInfo().getLicenseNamesWithTexts().stream()) + .filter(Objects::nonNull) + .map(licenseNamesWithTexts -> CommonUtils.isNotNullEmptyOrWhitespace( + licenseNamesWithTexts.getLicenseSpdxId()) ? licenseNamesWithTexts.getLicenseSpdxId() + : licenseNamesWithTexts.getLicenseName()) + .filter(CommonUtils::isNotNullEmptyOrWhitespace).collect(Collectors.toSet()); + + licenseIds.stream().forEach(licenseId -> { + if (licenseIdToReleasesMap.containsKey(licenseId)) { + licenseIdToReleasesMap.get(licenseId).add(entry.getValue()); + } else { + Set listOfRelease = new HashSet<>(); + listOfRelease.add(entry.getValue()); + licenseIdToReleasesMap.put(licenseId, listOfRelease); + } + }); + })); + + return licenseIdToReleasesMap; + } + + public Map getLicenseInfoAttachmentUsage(String projectId) { + Map licenseInfoUsages = new HashMap<>(); + try { + ThriftClients thriftClients = new ThriftClients(); + AttachmentService.Iface attachmentClient = thriftClients.makeAttachmentClient(); + + List attachmentUsages = wrapTException( + () -> attachmentClient.getUsedAttachments(Source.projectId(projectId), null)); + Collector> attachmentUsageMapCollector = Collectors.toMap( + AttachmentUsage::getAttachmentContentId, Function.identity(), + Sw360ProjectService::mergeAttachmentUsages); + BiFunction, UsageData._Fields, Map> filterAttachmentUsages = ( + attUsages, type) -> attUsages.stream() + .filter(attUsage -> attUsage.getUsageData().getSetField().equals(type)) + .collect(attachmentUsageMapCollector); + + licenseInfoUsages = filterAttachmentUsages.apply(attachmentUsages, UsageData._Fields.LICENSE_INFO); + + } catch (WrappedTException e) { + log.error("Error fetching AttachmentUsage from backend!", e); + } + + return licenseInfoUsages; + } + + static AttachmentUsage mergeAttachmentUsages(AttachmentUsage u1, AttachmentUsage u2) { + if (u1.getUsageData() == null) { + if (u2.getUsageData() == null) { + return u1; + } else { + throw new IllegalArgumentException("Cannot merge attachment usages of different usage types"); + } + } else { + if (!u1.getUsageData().getSetField().equals(u2.getUsageData().getSetField())) { + throw new IllegalArgumentException("Cannot merge attachment usages of different usage types"); + } + } + AttachmentUsage mergedUsage = u1.deepCopy(); + switch (u1.getUsageData().getSetField()) { + case LICENSE_INFO: + mergedUsage.getUsageData().getLicenseInfo().setExcludedLicenseIds( + Sets.union(Optional.of(u1) + .map(AttachmentUsage::getUsageData) + .map(UsageData::getLicenseInfo) + .map(LicenseInfoUsage::getExcludedLicenseIds) + .orElse(Collections.emptySet()), + Optional.of(u2) + .map(AttachmentUsage::getUsageData) + .map(UsageData::getLicenseInfo) + .map(LicenseInfoUsage::getExcludedLicenseIds) + .orElse(Collections.emptySet()))); + break; + case SOURCE_PACKAGE: + case MANUALLY_SET: + // do nothing + // source package and manual usages do not have any information to be merged + break; + default: + throw new IllegalArgumentException("Unexpected UsageData type: " + u1.getUsageData().getSetField()); + } + + return mergedUsage; + } + + public Map getLicenseObligationData(Map> licensesFromAttachmentUsage, User user) { + ThriftClients thriftClients = new ThriftClients(); + LicenseService.Iface licenseClient = thriftClients.makeLicenseClient(); + Map obligationStatusMap = new HashMap(); + licensesFromAttachmentUsage.entrySet().stream().forEach(entry -> wrapTException(() -> { + License lic = null; + Set releaseList = new HashSet<>(); + Set releaseData = entry.getValue(); + for (Release originalRelease : releaseData) { + Release simplifiedRelease = new Release(); + simplifiedRelease.setName(originalRelease.getName()); + simplifiedRelease.setVersion(originalRelease.getVersion()); + releaseList.add(simplifiedRelease); + } + try { + lic = licenseClient.getByID(entry.getKey(), user.getDepartment()); + } catch (TException exp) { + log.warn("Error fetching license from backend! License Id-" + entry.getKey(), exp.getMessage()); + return; + } + if (lic == null || CommonUtils.isNullOrEmptyCollection(lic.getObligations())) + return; + + lic.getObligations().stream().filter(Objects::nonNull).forEach(obl -> { + String keyofObl = CommonUtils.isNotNullEmptyOrWhitespace(obl.getTitle()) ? obl.getTitle() + : obl.getText(); + ObligationStatusInfo osi = null; + if (obligationStatusMap.containsKey(keyofObl)) { + osi = obligationStatusMap.get(keyofObl); + } else { + osi = new ObligationStatusInfo(); + obligationStatusMap.put(keyofObl, osi); + } + osi.setText(obl.getText()); + osi.setId(obl.getId()); + osi.setObligationType(obl.getObligationType()); + Set licenseIds = osi.getLicenseIds(); + if (licenseIds == null) { + licenseIds = new HashSet<>(); + osi.setLicenseIds(licenseIds); + } + licenseIds.add(entry.getKey()); + Set releases = osi.getReleases(); + if (releases == null) { + releases = new HashSet<>(); + osi.setReleases(releases); + } + releases.addAll(releaseList); + }); + + })); + return obligationStatusMap; + } + public Set searchLinkingProjects(String projectId, User sw360User) throws TException { ProjectService.Iface sw360ProjectClient = getThriftProjectClient(); return sw360ProjectClient.searchLinkingProjects(projectId, sw360User); diff --git a/rest/resource-server/src/test/java/org/eclipse/sw360/rest/resourceserver/restdocs/ProjectSpecTest.java b/rest/resource-server/src/test/java/org/eclipse/sw360/rest/resourceserver/restdocs/ProjectSpecTest.java index dc22f69662..f2fc7fb03b 100644 --- a/rest/resource-server/src/test/java/org/eclipse/sw360/rest/resourceserver/restdocs/ProjectSpecTest.java +++ b/rest/resource-server/src/test/java/org/eclipse/sw360/rest/resourceserver/restdocs/ProjectSpecTest.java @@ -39,8 +39,13 @@ import org.eclipse.sw360.datahandler.thrift.licenseinfo.LicenseInfoFile; import org.eclipse.sw360.datahandler.thrift.licenseinfo.OutputFormatInfo; import org.eclipse.sw360.datahandler.thrift.licenseinfo.OutputFormatVariant; +import org.eclipse.sw360.datahandler.thrift.licenses.License; +import org.eclipse.sw360.datahandler.thrift.licenses.Obligation; +import org.eclipse.sw360.datahandler.thrift.licenses.ObligationLevel; +import org.eclipse.sw360.datahandler.thrift.licenses.ObligationType; import org.eclipse.sw360.datahandler.thrift.packages.Package; import org.eclipse.sw360.datahandler.thrift.packages.PackageManager; +import org.eclipse.sw360.datahandler.thrift.projects.ObligationStatusInfo; import org.eclipse.sw360.datahandler.thrift.projects.Project; import org.eclipse.sw360.datahandler.thrift.projects.ProjectClearingState; import org.eclipse.sw360.datahandler.thrift.projects.ProjectProjectRelationship; @@ -391,6 +396,69 @@ public void before() throws TException, IOException { project6.setClearingState(ProjectClearingState.OPEN); project6.setSecurityResponsibles(new HashSet<>(Arrays.asList("securityresponsible1@sw360.org", "securityresponsible2@sw360.org"))); + Map linkedReleases3 = new HashMap<>(); + Set attachmentSet = new HashSet(); + List obligationList = new ArrayList<>(); + Set licenseIds2 = new HashSet<>(); + licenseIds2.add("MIT"); + + License license = new License(); + license.setId("MIT"); + license.setFullname("The MIT License (MIT)"); + license.setShortname("MIT"); + + Obligation obligation = new Obligation(); + obligation.setId("0001"); + obligation.setTitle("Obligation_Title"); + obligation.setText("This is text of Obligation"); + obligation.setObligationType(ObligationType.PERMISSION); + obligation.setObligationLevel(ObligationLevel.LICENSE_OBLIGATION); + obligationList.add(obligation); + license.setObligations(obligationList); + + Attachment releaseAttachment = new Attachment("33312312533", "CLIXML_core-js.xml"); + releaseAttachment.setSha1("d32a6dcbf27c61230d909515e69ecd0d"); + releaseAttachment.setAttachmentType(AttachmentType.COMPONENT_LICENSE_INFO_XML); + releaseAttachment.setCheckStatus(CheckStatus.ACCEPTED); + attachmentSet.add(releaseAttachment); + + Release release7 = new Release(); + release7.setId("376527651233"); + release7.setName("Angular_Obl"); + release7.setVersion("2"); + + Project project7 = new Project(); + project7.setId("123456733"); + project7.setName("oblProject"); + project7.setVersion("3"); + linkedReleases3.put("376527651233", projectReleaseRelationship); + project7.setReleaseIdToUsage(linkedReleases3); + + Source ownerSrc3 = Source.releaseId("376527651233"); + Source usedBySrc3 = Source.projectId("123456733"); + LicenseInfoUsage licenseInfoUsage3 = new LicenseInfoUsage(new HashSet<>()); + licenseInfoUsage3.setProjectPath("123456733"); + licenseInfoUsage3.setExcludedLicenseIds(Sets.newHashSet()); + licenseInfoUsage3.setIncludeConcludedLicense(false); + UsageData usageData3 = new UsageData(); + usageData3.setLicenseInfo(licenseInfoUsage3); + usageData3.setFieldValue(UsageData._Fields.LICENSE_INFO, licenseInfoUsage3); + AttachmentUsage attachmentUsage3 = new AttachmentUsage(ownerSrc3, "aa1122334455bb33", usedBySrc3); + attachmentUsage3.setUsageData(usageData3); + attachmentUsage3.setId("11223344889933"); + + Set releaseSet = new HashSet<>(); + releaseSet.add(release7); + Map licenseInfoUsages = Map.of("aa1122334455bb33", attachmentUsage3); + Map> licensesFromAttachmentUsage = Map.of(license.getId(), releaseSet); + ObligationStatusInfo osi = new ObligationStatusInfo(); + osi.setText(obligation.getText()); + osi.setLicenseIds(licenseIds2); + osi.setReleases(releaseSet); + osi.setId(obligation.getId()); + osi.setObligationType(obligation.getObligationType()); + Map obligationStatusMap = Map.of(obligation.getTitle(), osi); + Release release5 = new Release(); release5.setId("37652765121"); release5.setName("Angular 2.3.1"); @@ -455,6 +523,10 @@ public void before() throws TException, IOException { given(this.projectServiceMock.getProjectForUserById(eq(project4.getId()), any())).willReturn(project4); given(this.projectServiceMock.getProjectForUserById(eq(project5.getId()), any())).willReturn(project5); given(this.projectServiceMock.getProjectForUserById(eq(project6.getId()), any())).willReturn(project6); + given(this.projectServiceMock.getProjectForUserById(eq(project7.getId()), any())).willReturn(project7); + given(this.projectServiceMock.getLicenseInfoAttachmentUsage(eq(project7.getId()))).willReturn(licenseInfoUsages); + given(this.projectServiceMock.getLicensesFromAttachmentUsage(eq(licenseInfoUsages), any(), any())).willReturn(licensesFromAttachmentUsage); + given(this.projectServiceMock.getLicenseObligationData(eq(licensesFromAttachmentUsage), any())).willReturn(obligationStatusMap); given(this.projectServiceMock.getProjectForUserById(eq(projectForAtt.getId()), any())).willReturn(projectForAtt); given(this.projectServiceMock.getProjectForUserById(eq(SPDXProject.getId()), any())).willReturn(SPDXProject); given(this.projectServiceMock.getProjectForUserById(eq(cycloneDXProject.getId()), any())).willReturn(cycloneDXProject); @@ -745,6 +817,21 @@ public void should_document_get_usedbyresource_for_project() throws Exception { ))); } + @Test + public void should_document_get_obligations_from_license_db() throws Exception { + String accessToken = TestHelper.getAccessToken(mockMvc, testUserId, testUserPassword); + mockMvc.perform(get("/api/projects/" + "123456733" + "/licenseDbObligations") + .header("Authorization", "Bearer " + accessToken).accept(MediaTypes.HAL_JSON)) + .andExpect(status().isOk()) + .andDo(this.documentationHandler.document(responseFields( + subsectionWithPath("Obligation_Title").description("Title of license obligation"), + subsectionWithPath("Obligation_Title.text").description("Text of license obligation"), + subsectionWithPath("Obligation_Title.releases[]").description("Release array in which license obligation are present"), + subsectionWithPath("Obligation_Title.licenseIds[]").description("List of licenseIds"), + subsectionWithPath("Obligation_Title.id").description("Id of the obligation"), + subsectionWithPath("Obligation_Title.obligationType").description("Type of the obligation")))); + } + @Test public void should_document_get_attachment_usage_for_project() throws Exception { String accessToken = TestHelper.getAccessToken(mockMvc, testUserId, testUserPassword);