From 8b5ec8d5677cbf925711d45ffd13b1c4003a0fee Mon Sep 17 00:00:00 2001 From: afsahsyeda Date: Tue, 4 Jun 2024 14:37:30 +0530 Subject: [PATCH] feat(rest): includeAllAttachments parameter in licenseInfo endpoint Signed-off-by: afsahsyeda --- .../licenseinfo/parsers/SPDXParserTools.java | 2 +- .../licenseinfo/parsers/SPDXParserTest.java | 6 ++-- .../datahandler/common/SW360Constants.java | 5 ++- .../sw360/datahandler/common/SW360Utils.java | 6 ++-- .../src/docs/asciidoc/projects.adoc | 14 +++++++++ .../project/ProjectController.java | 31 +++++++++++++------ .../project/Sw360ProjectService.java | 26 ++++++++++++++++ .../restdocs/ProjectSpecTest.java | 23 ++++++++++++-- 8 files changed, 94 insertions(+), 19 deletions(-) diff --git a/backend/src/src-licenseinfo/src/main/java/org/eclipse/sw360/licenseinfo/parsers/SPDXParserTools.java b/backend/src/src-licenseinfo/src/main/java/org/eclipse/sw360/licenseinfo/parsers/SPDXParserTools.java index 63051547bb..a38e5e34bd 100644 --- a/backend/src/src-licenseinfo/src/main/java/org/eclipse/sw360/licenseinfo/parsers/SPDXParserTools.java +++ b/backend/src/src-licenseinfo/src/main/java/org/eclipse/sw360/licenseinfo/parsers/SPDXParserTools.java @@ -241,7 +241,7 @@ private static String findFirstSpdxChildContent(Node parent, String localName) { * Get license name of spdx:ExtractedLicensingInfo and spdx:ListedLicense. */ private static String getExtractedLicenseName(Node extractedLicenseInfo) { - String[] tagNames = { SPDX_NAME, SPDX_LICENSE_NAME_VERSION_1, SPDX_LICENSE_ID }; + String[] tagNames = {SPDX_LICENSE_ID, SPDX_NAME, SPDX_LICENSE_NAME_VERSION_1}; for (String tagName : tagNames) { String name = findFirstSpdxNodeContent(extractedLicenseInfo, tagName); if (!isNullEmptyOrWhitespace(name)) { diff --git a/backend/src/src-licenseinfo/src/test/java/org/eclipse/sw360/licenseinfo/parsers/SPDXParserTest.java b/backend/src/src-licenseinfo/src/test/java/org/eclipse/sw360/licenseinfo/parsers/SPDXParserTest.java index 56cdb17aab..ad37cf6b39 100644 --- a/backend/src/src-licenseinfo/src/test/java/org/eclipse/sw360/licenseinfo/parsers/SPDXParserTest.java +++ b/backend/src/src-licenseinfo/src/test/java/org/eclipse/sw360/licenseinfo/parsers/SPDXParserTest.java @@ -70,17 +70,17 @@ public static Object[][] dataProviderAdd() { // @formatter:off return new Object[][] { { spdxExampleFile, - Arrays.asList("Apache-2.0", "LGPL-2.0", "1", "GPL-2.0", "CyberNeko License", "2"), + Arrays.asList("Apache-2.0", "LGPL-2.0", "1", "GPL-2.0", "3", "2"), 4, "Copyright 2008-2010 John Smith", Sets.newHashSet("3", "LGPL-2.0") }, { spdx11ExampleFile, - Arrays.asList("4", "1", "Apache-2.0", "2", "Apache-1.0", "MPL-1.1", "CyberNeko License"), + Arrays.asList("4", "1", "Apache-2.0", "2", "Apache-1.0", "MPL-1.1", "3"), 2, "Hewlett-Packard Development Company, LP", Sets.newHashSet("1", "2", "3", "4", "Apache-1.0", "Apache-2.0", "MPL-1.1") }, { spdx12ExampleFile, - Arrays.asList("4", "1", "Apache-2.0", "2", "Apache-1.0", "MPL-1.1", "CyberNeko License"), + Arrays.asList("4", "1", "Apache-2.0", "2", "Apache-1.0", "MPL-1.1", "3"), 3, "Hewlett-Packard Development Company, LP", Sets.newHashSet("1", "2", "3", "4", "Apache-1.0", "Apache-2.0", "MPL-1.1") }, diff --git a/libraries/datahandler/src/main/java/org/eclipse/sw360/datahandler/common/SW360Constants.java b/libraries/datahandler/src/main/java/org/eclipse/sw360/datahandler/common/SW360Constants.java index d70cd967a3..957e1fde27 100644 --- a/libraries/datahandler/src/main/java/org/eclipse/sw360/datahandler/common/SW360Constants.java +++ b/libraries/datahandler/src/main/java/org/eclipse/sw360/datahandler/common/SW360Constants.java @@ -144,7 +144,10 @@ public class SW360Constants { .put(TYPE_PACKAGE, "name version") .build(); - public static final Collection LICENSE_INFO_ATTACHMENT_TYPES = Arrays.asList(AttachmentType.COMPONENT_LICENSE_INFO_XML, AttachmentType.COMPONENT_LICENSE_INFO_COMBINED); + public static final Collection LICENSE_INFO_ATTACHMENT_TYPES = Arrays.asList(AttachmentType.COMPONENT_LICENSE_INFO_XML, + AttachmentType.COMPONENT_LICENSE_INFO_COMBINED); + public static final Collection INITIAL_LICENSE_INFO_ATTACHMENT_TYPES = Arrays.asList(AttachmentType.COMPONENT_LICENSE_INFO_XML, + AttachmentType.COMPONENT_LICENSE_INFO_COMBINED, AttachmentType.INITIAL_SCAN_REPORT); public static final Collection SOURCE_CODE_ATTACHMENT_TYPES = Arrays.asList(AttachmentType.SOURCE, AttachmentType.SOURCE_SELF); public static final String CONTENT_TYPE_OPENXML_SPREADSHEET = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; diff --git a/libraries/datahandler/src/main/java/org/eclipse/sw360/datahandler/common/SW360Utils.java b/libraries/datahandler/src/main/java/org/eclipse/sw360/datahandler/common/SW360Utils.java index 239853e88d..1c11d7bcff 100644 --- a/libraries/datahandler/src/main/java/org/eclipse/sw360/datahandler/common/SW360Utils.java +++ b/libraries/datahandler/src/main/java/org/eclipse/sw360/datahandler/common/SW360Utils.java @@ -512,7 +512,7 @@ public static List getLinkedReleasesWithAccessibility(Project proje } return Collections.emptyList(); } - + public static List getLinkedReleaseRelations(Release release, ThriftClients thriftClients, Logger log) { if (release != null && release.getReleaseIdToRelationship() != null) { try { @@ -536,7 +536,7 @@ public static List getLinkedReleaseRelationsWithAccessibility(Relea } return Collections.emptyList(); } - + public static Predicate startsWith(final String prefix) { return new Predicate() { @Override @@ -684,7 +684,7 @@ public static Map putAccessibleReleaseNamesInMap(Map m } return releaseNamesMap; } - + public static Map putProjectNamesInMap(Map map, List projects) { if(map == null || projects == null) { return Collections.emptyMap(); diff --git a/rest/resource-server/src/docs/asciidoc/projects.adoc b/rest/resource-server/src/docs/asciidoc/projects.adoc index c87e9c2337..007becec8c 100644 --- a/rest/resource-server/src/docs/asciidoc/projects.adoc +++ b/rest/resource-server/src/docs/asciidoc/projects.adoc @@ -698,6 +698,20 @@ include::{snippets}/should_document_get_download_license_info/curl-request.adoc[ ===== Example response include::{snippets}/should_document_get_download_license_info/http-response.adoc[] +[[resources-project-get-download-licenseinfo-with-all-attachments]] +==== Download License Info with all attachments + +A `GET` request is used to download the project's license information. The resulting file will include findings from either the CLX or ISR attachment of a linked release. + +===== Request parameter +include::{snippets}/should_document_get_download_license_info_with_all_attachemnts/request-parameters.adoc[] + +===== Example request +include::{snippets}/should_document_get_download_license_info_with_all_attachemnts/curl-request.adoc[] + +===== Example response +include::{snippets}/should_document_get_download_license_info_with_all_attachemnts/http-response.adoc[] + [[resources-project-usedby-list]] ==== Resources using the project 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 ca704ab1b2..2340d449c5 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 @@ -1368,13 +1368,21 @@ public void downloadLicenseInfo( @Parameter(description = "The external Ids of the project", example = "376577") @RequestParam(value = "externalIds", required = false) String externalIds, @RequestParam(value = "template", required = false) String template, + @Parameter(description = "Generate license info including all attachments of the linked releases") + @RequestParam(value = "includeAllAttachments", required = false ) boolean includeAllAttachments, HttpServletResponse response ) throws TException, IOException { final User sw360User = restControllerHelper.getSw360UserFromAuthentication(); final Project sw360Project = projectService.getProjectForUserById(id, sw360User); + List mappedProjectLinks = new ArrayList<>(); - List mappedProjectLinks = projectService.createLinkedProjects(sw360Project, + if (includeAllAttachments) { + mappedProjectLinks = projectService.createLinkedProjects(sw360Project, + projectService.filterAndSortAllAttachments(SW360Constants.INITIAL_LICENSE_INFO_ATTACHMENT_TYPES), true, sw360User); + } else { + mappedProjectLinks = projectService.createLinkedProjects(sw360Project, projectService.filterAndSortAttachments(SW360Constants.LICENSE_INFO_ATTACHMENT_TYPES), true, sw360User); + } List attchmntUsg = attachmentService.getAttachemntUsages(id); @@ -1407,14 +1415,17 @@ public void downloadLicenseInfo( Release release = componentService.getReleaseById(releaseLinkId, sw360User); for (final Attachment attachment : attachments) { String attachemntContentId = attachment.getAttachmentContentId(); - if (usedAttachmentContentIds.containsKey(attachemntContentId)) { - boolean includeConcludedLicense = usedAttachmentContentIds.get(attachemntContentId); - List licenseInfoParsingResult = licenseInfoService - .getLicenseInfoForAttachment(release, sw360User, attachemntContentId, includeConcludedLicense); - excludedLicensesPerAttachments.put(attachemntContentId, - getExcludedLicenses(excludedLicenseIds, licenseInfoParsingResult)); + if (includeAllAttachments) { selectedReleaseAndAttachmentIds.get(releaseLinkId).put(attachemntContentId, - includeConcludedLicense); + false); + } else { + if (usedAttachmentContentIds.containsKey(attachemntContentId)) { + boolean includeConcludedLicense = usedAttachmentContentIds.get(attachemntContentId); + List licenseInfoParsingResult = licenseInfoService + .getLicenseInfoForAttachment(release, sw360User, attachemntContentId, includeConcludedLicense); + excludedLicensesPerAttachments.put(attachemntContentId, getExcludedLicenses(excludedLicenseIds, licenseInfoParsingResult)); + selectedReleaseAndAttachmentIds.get(releaseLinkId).put(attachemntContentId, includeConcludedLicense); + } } } }))); @@ -1435,7 +1446,9 @@ public void downloadLicenseInfo( fileName = orgToTemplate.get(template); } - final LicenseInfoFile licenseInfoFile = licenseInfoService.getLicenseInfoFile(sw360Project, sw360User, outputGeneratorClassNameWithVariant, selectedReleaseAndAttachmentIds, excludedLicensesPerAttachments, externalIds, fileName); + final LicenseInfoFile licenseInfoFile = licenseInfoService.getLicenseInfoFile(sw360Project, sw360User, + outputGeneratorClassNameWithVariant, selectedReleaseAndAttachmentIds, excludedLicensesPerAttachments, + externalIds, fileName); byte[] byteContent = licenseInfoFile.bufferForGeneratedOutput().array(); response.setContentType(outputFormatInfo.getMimeType()); response.setHeader("Content-Disposition", String.format("attachment; filename=\"%s\"", filename)); 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 a15ba7b963..8e5f863adc 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 @@ -713,6 +713,32 @@ public Function filterAndSortAttachments(Collection filterAndSortAllAttachments(Collection attachmentTypes) { + Predicate filter = att -> attachmentTypes.contains(att.getAttachmentType()); + return createProjectLinkMapper(rl -> { + List attachments = nullToEmptyList(rl.getAttachments()).stream() + .filter(filter) + .collect(Collectors.toList()); + + if (attachments.size() > 1) { + Optional acceptedAttachment = attachments.stream() + .filter(att -> att.getCheckStatus() == CheckStatus.ACCEPTED).findFirst(); + + if (acceptedAttachment.isPresent()) { + attachments = List.of(acceptedAttachment.get()); + } else { + attachments = attachments.stream() + .filter(att -> SW360Constants.LICENSE_INFO_ATTACHMENT_TYPES.contains(att.getAttachmentType())) + .limit(1) + .collect(Collectors.toList()); + } + } + + rl.setAttachments(attachments); + return rl; + }); + } + public Function createProjectLinkMapper(Function releaseLinkMapper){ return (projectLink) -> { List mappedReleaseLinks = nullToEmptyList(projectLink 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 79cfc9e9a7..bdb201824c 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 @@ -478,7 +478,7 @@ public void before() throws TException, IOException { osi.setStatus(ObligationStatus.OPEN); osi.setObligationType(obligation.getObligationType()); Map obligationStatusMap = Map.of(obligation.getTitle(), osi); - + ObligationList obligationLists = new ObligationList(); obligationLists.setProjectId(project8.getId()); obligationLists.setId("009"); @@ -538,7 +538,7 @@ public void before() throws TException, IOException { RequestSummary requestSummaryForCycloneDX = new RequestSummary(); requestSummaryForCycloneDX.setMessage("{\"projectId\":\"" + cycloneDXProject.getId() + "\"}"); - + String projectName="project_name_version_createdOn.xlsx"; AddDocumentRequestSummary requestSummaryForCR = new AddDocumentRequestSummary(); @@ -2073,6 +2073,25 @@ public void should_document_get_download_license_info() throws Exception { ))); } + @Test + public void should_document_get_download_license_info_with_all_attachemnts() throws Exception { + String accessToken = TestHelper.getAccessToken(mockMvc, testUserId, testUserPassword); + this.mockMvc.perform(get("/api/projects/" + project.getId()+ "/licenseinfo?generatorClassName=XhtmlGenerator&variant=DISCLOSURE&includeAllAttachments=true") + .header("Authorization", "Bearer " + accessToken) + .accept("application/xhtml+xml")) + .andExpect(status().isOk()) + .andDo(this.documentationHandler + .document(requestParameters( + parameterWithName("generatorClassName") + .description("All possible values for output generator class names are " + + Arrays.asList("DocxGenerator", "XhtmlGenerator", "TextGenerator")), + parameterWithName("variant").description("All the possible values for variants are " + + Arrays.asList(OutputFormatVariant.values())), + parameterWithName("includeAllAttachments").description("Set this option to `true` to include all attachments from linked releases. " + + "Note that only one attachment per release will be parsed for " + + "license information, and if available, a CLX file will be preferred over an ISR file.")))); + } + @Test public void should_document_get_projects_releases() throws Exception { this.mockMvc.perform(get("/api/projects/releases")