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 a0648184e4..9050770317 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 @@ -2736,13 +2736,16 @@ public ResponseEntity removeOrphanObligation( tags = {"Projects"} ) @RequestMapping(value = PROJECTS_URL + "/{id}/licenseObligations", method = RequestMethod.GET) - public ResponseEntity getLicenseObligations(Pageable pageable, - @Parameter(description = "Project ID.") @PathVariable("id") String id) + public ResponseEntity getLicenseObligations(Pageable pageable, + @Parameter(description = "Project ID.") @PathVariable("id") String id, + @Parameter(description = "If true, returns the license obligation data in release view. " + + "Otherwise, returns it in project view.") + @RequestParam(value = "view", defaultValue = "false") boolean releaseView) throws TException { final User sw360User = restControllerHelper.getSw360UserFromAuthentication(); final Project sw360Project = projectService.getProjectForUserById(id, sw360User); final Map releaseIdToAcceptedCLI = Maps.newHashMap(); - List releases = new ArrayList<>();; + List releases = new ArrayList<>(); ObligationList obligation = new ObligationList(); Map obligationStatusMap = Maps.newHashMap(); List releaseIds = new ArrayList<>(sw360Project.getReleaseIdToUsage().keySet()); @@ -2757,17 +2760,36 @@ public ResponseEntity getLicenseObligations(Pageable pageable, obligationStatusMap = CommonUtils.nullToEmptyMap(obligation.getLinkedObligationStatus()); releaseIdToAcceptedCLI.putAll(SW360Utils.getReleaseIdtoAcceptedCLIMappings(obligationStatusMap)); } + if (releaseView) { + final List licenseInfoWithObligations = new ArrayList<>(); + List processedLicenses = projectService.processLicenseInfoWithObligations( + licenseInfoWithObligations, releaseIdToAcceptedCLI, releases, sw360User); + for (Map.Entry entry : obligationStatusMap.entrySet()) { + ObligationStatusInfo statusInfo = entry.getValue(); + Set limitedSet = releaseService + .getReleasesForUserByIds(statusInfo.getReleaseIdToAcceptedCLI().keySet()); + statusInfo.setReleases(limitedSet); + } - obligationStatusMap = projectService.setLicenseInfoWithObligations(obligationStatusMap, releaseIdToAcceptedCLI, releases, sw360User); - for (Map.Entry entry : obligationStatusMap.entrySet()) { - ObligationStatusInfo statusInfo = entry.getValue(); - Set limitedSet = releaseService.getReleasesForUserByIds(statusInfo.getReleaseIdToAcceptedCLI().keySet()); - statusInfo.setReleases(limitedSet); - } + // Include obligation status in the response + Map responseBody = new HashMap<>(); + responseBody.put("processedLicenses", processedLicenses); + responseBody.put("obligationStatusMap", obligationStatusMap); + return new ResponseEntity<>(responseBody, HttpStatus.OK); + } else { + obligationStatusMap = projectService.setLicenseInfoWithObligations(obligationStatusMap, + releaseIdToAcceptedCLI, releases, sw360User); + for (Map.Entry entry : obligationStatusMap.entrySet()) { + ObligationStatusInfo statusInfo = entry.getValue(); + Set limitedSet = releaseService + .getReleasesForUserByIds(statusInfo.getReleaseIdToAcceptedCLI().keySet()); + statusInfo.setReleases(limitedSet); + } - Map responseBody = createPaginationMetadata(pageable, obligationStatusMap); - HalResource> halObligation = new HalResource<>(responseBody); - return new ResponseEntity<>(halObligation, HttpStatus.OK); + Map responseBody = createPaginationMetadata(pageable, obligationStatusMap); + HalResource> halObligation = new HalResource<>(responseBody); + return new ResponseEntity<>(halObligation, HttpStatus.OK); + } } @Operation( 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 dc577c1ccb..d5dfee3ad7 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 @@ -45,6 +45,7 @@ import org.eclipse.sw360.datahandler.thrift.components.ReleaseNode; import org.eclipse.sw360.datahandler.thrift.licenseinfo.LicenseInfoParsingResult; import org.eclipse.sw360.datahandler.thrift.licenseinfo.LicenseInfoService; +import org.eclipse.sw360.datahandler.thrift.licenseinfo.LicenseNameWithText; import org.eclipse.sw360.datahandler.thrift.licenses.LicenseService; import org.eclipse.sw360.datahandler.thrift.licenses.License; import org.eclipse.sw360.datahandler.thrift.licenseinfo.LicenseObligationsStatusInfo; @@ -93,6 +94,7 @@ import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Objects; @@ -440,22 +442,26 @@ static AttachmentUsage mergeAttachmentUsages(AttachmentUsage u1, AttachmentUsage } AttachmentUsage mergedUsage = u1.deepCopy(); switch (u1.getUsageData().getSetField()) { - case LICENSE_INFO: - Set mergedExcludedLicenseIds = new HashSet<>( - Optional.of(u1).map(AttachmentUsage::getUsageData).map(UsageData::getLicenseInfo) - .map(LicenseInfoUsage::getExcludedLicenseIds).orElse(Collections.emptySet())); - mergedExcludedLicenseIds - .addAll(Optional.of(u2).map(AttachmentUsage::getUsageData).map(UsageData::getLicenseInfo) - .map(LicenseInfoUsage::getExcludedLicenseIds).orElse(Collections.emptySet())); - mergedUsage.getUsageData().getLicenseInfo().setExcludedLicenseIds(mergedExcludedLicenseIds); - 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()); + 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 mergedSw360ProjectService.java + break; + default: + throw new IllegalArgumentException("Unexpected UsageData type: " + u1.getUsageData().getSetField()); } return mergedUsage; @@ -699,7 +705,7 @@ public Map setLicenseInfoWithObligations( .createLicenseToObligationMapping(licenseResults.get(0), obligationResults.get(0))); } } catch (TException exception) { - log.error(String.format("Error fetchinig license Information for attachment: %s in release: %s", + log.error(String.format("Error fetchinig Sw360ProjectService.javalicense Information for attachment: %s in release: %s", filteredAttachment.getFilename(), releaseId), exception); } } @@ -1434,8 +1440,73 @@ private Set filteredProjectIds(List filteredProjectLinks) { return filteredProjectLinks.stream().map(ProjectLink::getId).collect(Collectors.toSet()); } - public List> serveDependencyNetworkListView(String projectId, User sw360User) - throws TException { + public List processLicenseInfoWithObligations( + List licenseInfoWithObligations, Map releaseIdToAcceptedCLI, + List releases, User user) throws TException { + ThriftClients thriftClients = new ThriftClients(); + LicenseInfoService.Iface licenseClient = thriftClients.makeLicenseInfoClient(); + + for (Release release : releases) { + List approvedCliAttachments = SW360Utils.getApprovedClxAttachmentForRelease(release); + if (approvedCliAttachments.isEmpty()) { + log.info("No approved CLX attachments found for release: {}. Proceeding with attached CLX.", + release.getId()); + approvedCliAttachments = SW360Utils.getClxAttachmentForRelease(release); + } + final String releaseId = release.getId(); + + for (Attachment filteredAttachment : approvedCliAttachments) { + final String attachmentContentId = filteredAttachment.getAttachmentContentId(); + + if (releaseIdToAcceptedCLI.containsKey(releaseId) + && releaseIdToAcceptedCLI.get(releaseId).equals(attachmentContentId)) { + releaseIdToAcceptedCLI.remove(releaseId); + } + + try { + List licenseResults = licenseClient.getLicenseInfoForAttachment(release, + attachmentContentId, false, user); + List obligationResults = licenseClient.getObligationsForAttachment(release, + attachmentContentId, user); + + if (CommonUtils.allAreNotEmpty(licenseResults, obligationResults) + && obligationResults.get(0).getObligationsAtProjectSize() > 0) { + licenseInfoWithObligations.add(licenseClient + .createLicenseToObligationMapping(licenseResults.get(0), obligationResults.get(0))); + } + } catch (TException exception) { + log.error(String.format("Error fetching license Information for attachment: %s in release: %s", + filteredAttachment.getFilename(), releaseId), exception); + } + } + } + + Predicate filterLicense = license -> (license.isSetObligationsAtProject() + && !(SW360Constants.LICENSE_NAME_UNKNOWN.equals(license.getLicenseName()) + || SW360Constants.NA.equalsIgnoreCase(license.getLicenseName()))); + + licenseInfoWithObligations.stream() + .sorted(Comparator.comparing(LicenseInfoParsingResult::getName, String.CASE_INSENSITIVE_ORDER)) + .forEach(e -> { + Set updatedLicenses = e.getLicenseInfo().getLicenseNamesWithTexts().stream() + .filter(filterLicense).map(license -> { + if (SW360Constants.LICENSE_TYPE_GLOBAL.equalsIgnoreCase(license.getType())) { + license.setType(SW360Constants.LICENSE_TYPE_GLOBAL); + } else { + license.setType(SW360Constants.LICENSE_TYPE_OTHERS); + } + return license; + }) + .sorted(Comparator.comparing(LicenseNameWithText::getType, String.CASE_INSENSITIVE_ORDER) + .thenComparing(LicenseNameWithText::getLicenseName, String.CASE_INSENSITIVE_ORDER)) + .collect(Collectors.toCollection(LinkedHashSet::new)); + e.getLicenseInfo().setLicenseNamesWithTexts(updatedLicenses); + }); + + return licenseInfoWithObligations; + } + + public List> serveDependencyNetworkListView(String projectId, User sw360User) throws TException { try { ProjectService.Iface sw360ProjectClient = getThriftProjectClient(); return sw360ProjectClient.getAccessibleDependencyNetworkForListView(projectId, sw360User); @@ -1451,7 +1522,7 @@ public List> serveDependencyNetworkListView(String projectId } } - public ProjectLink serveLinkedResourcesOfProjectInDependencyNetwork(String projectId, boolean transitive, User sw360User) throws TException { + public ProjectLink serveLinkedResourcesOfProjectInDependencyNetwork(String projectId, boolean transitive, User sw360User) throws TException{ Project project = getProjectForUserById(projectId, sw360User); final Collection linkedProjects = (!transitive) ? SW360Utils.getLinkedProjectsAsFlatList(project, false, new ThriftClients(), log, sw360User)