|
78 | 78 | import org.eclipse.sw360.datahandler.thrift.licenseinfo.OutputFormatInfo; |
79 | 79 | import org.eclipse.sw360.datahandler.thrift.licenseinfo.OutputFormatVariant; |
80 | 80 | import org.eclipse.sw360.datahandler.thrift.licenses.License; |
| 81 | +import org.eclipse.sw360.datahandler.thrift.licenses.ObligationLevel; |
81 | 82 | import org.eclipse.sw360.datahandler.thrift.projects.*; |
82 | 83 | import org.eclipse.sw360.datahandler.thrift.packages.Package; |
83 | 84 | import org.eclipse.sw360.datahandler.thrift.projects.ObligationList; |
|
138 | 139 | import org.springframework.web.bind.annotation.RequestMethod; |
139 | 140 | import org.springframework.web.bind.annotation.RequestParam; |
140 | 141 | import org.springframework.web.bind.annotation.RestController; |
141 | | -import org.springframework.web.client.HttpClientErrorException; |
142 | 142 | import org.springframework.web.multipart.MultipartFile; |
143 | 143 | import org.springframework.web.servlet.support.ServletUriComponentsBuilder; |
144 | 144 | import org.eclipse.sw360.datahandler.thrift.users.RequestedAction; |
@@ -3044,7 +3044,7 @@ public ResponseEntity<Object> getLicenseObligations( |
3044 | 3044 | } |
3045 | 3045 | if (CommonUtils.isNotNullEmptyOrWhitespace(sw360Project.getLinkedObligationId())) { |
3046 | 3046 | obligation = projectService.getObligationData(sw360Project.getLinkedObligationId(), sw360User); |
3047 | | - obligationStatusMap = CommonUtils.nullToEmptyMap(obligation.getLinkedObligationStatus()); |
| 3047 | + obligationStatusMap = filterObligationsByLevel(CommonUtils.nullToEmptyMap(obligation.getLinkedObligationStatus()), null); |
3048 | 3048 | releaseIdToAcceptedCLI.putAll(SW360Utils.getReleaseIdtoAcceptedCLIMappings(obligationStatusMap)); |
3049 | 3049 | } |
3050 | 3050 |
|
@@ -3120,27 +3120,49 @@ public ResponseEntity<HalResource> getObligations( |
3120 | 3120 | } |
3121 | 3121 |
|
3122 | 3122 | if (oblLevel.equalsIgnoreCase("License")) { |
3123 | | - for (Map.Entry<String, ObligationStatusInfo> entry : obligationStatusMap.entrySet()) { |
3124 | | - String key = entry.getKey(); |
3125 | | - if (!key.equals("compObl") && !key.equals("projectObl") && !key.equals("orgObl")) { |
3126 | | - filterData.put(key, entry.getValue()); |
3127 | | - } |
3128 | | - } |
| 3123 | + filterData = filterObligationsByLevel(obligationStatusMap, null); |
3129 | 3124 | releaseIdToAcceptedCLI.putAll(SW360Utils.getReleaseIdtoAcceptedCLIMappings(filterData)); |
3130 | 3125 | oblData = projectService.setLicenseInfoWithObligations(filterData, releaseIdToAcceptedCLI, releases, sw360User); |
| 3126 | + |
3131 | 3127 | for (Map.Entry<String, ObligationStatusInfo> entry : oblData.entrySet()) { |
3132 | 3128 | ObligationStatusInfo statusInfo = entry.getValue(); |
3133 | 3129 | Set<Release> limitedSet = releaseService.getReleasesForUserByIds(statusInfo.getReleaseIdToAcceptedCLI().keySet()); |
3134 | 3130 | statusInfo.setReleases(limitedSet); |
3135 | 3131 | statusInfo.setId(entry.getKey()); |
3136 | 3132 | } |
| 3133 | + } else { |
| 3134 | + ObligationLevel targetLevel; |
| 3135 | + switch (oblLevel.toLowerCase()) { |
| 3136 | + case "project": |
| 3137 | + targetLevel = ObligationLevel.PROJECT_OBLIGATION; |
| 3138 | + break; |
| 3139 | + case "organization": |
| 3140 | + targetLevel = ObligationLevel.ORGANISATION_OBLIGATION; |
| 3141 | + break; |
| 3142 | + case "component": |
| 3143 | + targetLevel = ObligationLevel.COMPONENT_OBLIGATION; |
| 3144 | + break; |
| 3145 | + default: |
| 3146 | + throw new BadRequestClientException("Invalid Obligation Level"); |
| 3147 | + } |
| 3148 | + oblData = filterObligationsByLevel(oblData, targetLevel); |
3137 | 3149 | } |
3138 | 3150 |
|
| 3151 | + |
3139 | 3152 | Map<String, Object> responseBody = createPaginationMetadata(pageable, oblData); |
3140 | 3153 | HalResource<Map<String, Object>> halObligation = new HalResource<>(responseBody); |
3141 | 3154 | return new ResponseEntity<>(halObligation, HttpStatus.OK); |
3142 | 3155 | } |
3143 | 3156 |
|
| 3157 | + private Map<String, ObligationStatusInfo> filterObligationsByLevel( |
| 3158 | + Map<String, ObligationStatusInfo> obligationStatusMap, ObligationLevel targetLevel) { |
| 3159 | + return obligationStatusMap.entrySet().stream() |
| 3160 | + .filter(entry -> { |
| 3161 | + ObligationLevel obligationLevel = entry.getValue().getObligationLevel(); |
| 3162 | + return obligationLevel == null || obligationLevel == targetLevel; |
| 3163 | + }) |
| 3164 | + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); |
| 3165 | + } |
3144 | 3166 | @PreAuthorize("hasAuthority('WRITE')") |
3145 | 3167 | @Operation( |
3146 | 3168 | summary = "Add licenseObligations from license DB", |
@@ -3209,38 +3231,240 @@ public ResponseEntity<?> addLicenseObligations( |
3209 | 3231 | ) |
3210 | 3232 | @RequestMapping(value = PROJECTS_URL + "/{id}/updateLicenseObligation", method = RequestMethod.PATCH) |
3211 | 3233 | public ResponseEntity<?> patchLicenseObligations( |
3212 | | - @Parameter(description = "Project ID.") |
3213 | | - @PathVariable("id") String id, |
3214 | | - @Parameter(description = "Map of obligation status info.") |
| 3234 | + @Parameter(description = "Project ID") @PathVariable("id") String id, |
| 3235 | + @Parameter(description = "Map of obligation status info") |
3215 | 3236 | @RequestBody Map<String, ObligationStatusInfo> requestBodyObligationStatusInfo |
3216 | 3237 | ) throws TException { |
3217 | 3238 | final User sw360User = restControllerHelper.getSw360UserFromAuthentication(); |
3218 | | - final Project sw360Project = projectService.getProjectForUserById(id, sw360User); |
3219 | | - ObligationList obligation = new ObligationList(); |
3220 | | - Map<String, ObligationStatusInfo> obligationStatusMap = Maps.newHashMap(); |
3221 | | - if (CommonUtils.isNotNullEmptyOrWhitespace(sw360Project.getLinkedObligationId())) { |
3222 | | - obligation = projectService.getObligationData(sw360Project.getLinkedObligationId(), sw360User); |
3223 | | - obligationStatusMap = CommonUtils.nullToEmptyMap(obligation.getLinkedObligationStatus()); |
| 3239 | + restControllerHelper.throwIfSecurityUser(sw360User); |
| 3240 | + Map<String, ObligationStatusInfo> obligationStatusMap = new HashMap<>(); |
| 3241 | + try { |
| 3242 | + obligationStatusMap = processLicenseObligations(id, sw360User, requestBodyObligationStatusInfo); |
| 3243 | + Map<String, ObligationStatusInfo> updatedObligationStatusMap = projectService |
| 3244 | + .compareObligationStatusMap(sw360User, obligationStatusMap, requestBodyObligationStatusInfo); |
| 3245 | + Project sw360Project = projectService.getProjectForUserById(id, sw360User); |
| 3246 | + ObligationList obligationList = projectService.getObligationData(sw360Project.getLinkedObligationId(), sw360User); |
| 3247 | + RequestStatus updateStatus = projectService |
| 3248 | + .patchLinkedObligations(sw360User, updatedObligationStatusMap, obligationList); |
| 3249 | + if (updateStatus == RequestStatus.SUCCESS) { |
| 3250 | + return ResponseEntity |
| 3251 | + .status(HttpStatus.CREATED) |
| 3252 | + .body("License Obligation Updated Successfully"); |
| 3253 | + } |
| 3254 | + |
| 3255 | + throw new DataIntegrityViolationException("Cannot update License Obligation"); |
| 3256 | + } catch (Exception e) { |
| 3257 | + log.error("Error updating license obligations: ", e); |
| 3258 | + throw new DataIntegrityViolationException("Failed to update License Obligation: " + e.getMessage()); |
3224 | 3259 | } |
| 3260 | + } |
3225 | 3261 |
|
3226 | | - // Accept STATUS and COMMENT in the request body |
3227 | | - for (Map.Entry<String, ObligationStatusInfo> entry : requestBodyObligationStatusInfo.entrySet()) { |
3228 | | - ObligationStatusInfo updatedInfo = entry.getValue(); |
3229 | | - if (updatedInfo.getStatus() != null) { |
3230 | | - obligationStatusMap.get(entry.getKey()).setStatus(updatedInfo.getStatus()); |
3231 | | - } |
3232 | | - if (updatedInfo.getComment() != null) { |
3233 | | - obligationStatusMap.get(entry.getKey()).setComment(updatedInfo.getComment()); |
3234 | | - } |
| 3262 | + /** |
| 3263 | + * Processes the obligations for a project based on whether it has linked obligations or not. |
| 3264 | + * If linked obligations exist, it processes them; otherwise, it updates the project obligations. |
| 3265 | + * |
| 3266 | + * @param sw360Project The SW360 project to process obligations for. |
| 3267 | + * @param sw360User The user performing the operation. |
| 3268 | + * @param requestBodyObligationStatusInfo The obligation status information from the request body. |
| 3269 | + * @param obligationList The obligation list to be processed. |
| 3270 | + * @return A map of obligation status information after processing. |
| 3271 | + * @throws TException If there is an error during the Thrift operation. |
| 3272 | + */ |
| 3273 | + private Map<String, ObligationStatusInfo> processLicenseObligations( |
| 3274 | + String projectId, |
| 3275 | + User sw360User, |
| 3276 | + Map<String, ObligationStatusInfo> requestBodyObligationStatusInfo |
| 3277 | + |
| 3278 | + ) throws TException { |
| 3279 | + Project sw360Project = projectService.getProjectForUserById(projectId, sw360User); |
| 3280 | + if (hasLinkedObligations(sw360Project)) { |
| 3281 | + return processExistingLicenseObligations(sw360Project, sw360User, requestBodyObligationStatusInfo); |
3235 | 3282 | } |
| 3283 | + return updateProjectLicenseObligations(sw360Project, sw360User, new HashMap<>()); |
| 3284 | + } |
| 3285 | + |
| 3286 | + private boolean hasLinkedObligations(Project project) { |
| 3287 | + return CommonUtils.isNotNullEmptyOrWhitespace(project.getLinkedObligationId()); |
| 3288 | + } |
3236 | 3289 |
|
3237 | | - Map<String, ObligationStatusInfo> updatedObligationStatusMap = projectService |
3238 | | - .compareObligationStatusMap(sw360User, obligationStatusMap, requestBodyObligationStatusInfo); |
3239 | | - RequestStatus updateObligationStatus = projectService.patchLinkedObligations(sw360User, updatedObligationStatusMap, obligation); |
3240 | | - if (updateObligationStatus == RequestStatus.SUCCESS) { |
3241 | | - return new ResponseEntity<>("License Obligation Updated Successfully", HttpStatus.CREATED); |
| 3290 | + /** |
| 3291 | + * Processes existing obligations for a project. |
| 3292 | + * If the project has linked obligations, it retrieves them and checks if all obligations from the request body are present. |
| 3293 | + * If not all obligations are present, it updates the project obligations with the existing ones. |
| 3294 | + * If all obligations are present, it returns the existing obligation status map. |
| 3295 | + * |
| 3296 | + * @param sw360Project The SW360 project to process obligations for. |
| 3297 | + * @param sw360User The user performing the operation. |
| 3298 | + * @param requestBodyObligationStatusInfo The obligation status information from the request body. |
| 3299 | + * @param obligationList The obligation list to be processed. |
| 3300 | + * @return A map of obligation status information after processing. |
| 3301 | + * @throws TException If there is an error during the Thrift operation. |
| 3302 | + */ |
| 3303 | + private Map<String, ObligationStatusInfo> processExistingLicenseObligations( |
| 3304 | + Project sw360Project, |
| 3305 | + User sw360User, |
| 3306 | + Map<String, ObligationStatusInfo> requestBodyObligationStatusInfo |
| 3307 | + ) throws TException { |
| 3308 | + ObligationList obligationList = projectService.getObligationData(sw360Project.getLinkedObligationId(), sw360User); |
| 3309 | + Map<String, ObligationStatusInfo> obligationStatusMap = CommonUtils.nullToEmptyMap(obligationList.getLinkedObligationStatus()); |
| 3310 | + |
| 3311 | + boolean allObligationsPresent = requestBodyObligationStatusInfo.keySet() |
| 3312 | + .stream() |
| 3313 | + .allMatch(obligationStatusMap::containsKey); |
| 3314 | + |
| 3315 | + if (!allObligationsPresent) { |
| 3316 | + return updateProjectLicenseObligations(sw360Project, sw360User, obligationStatusMap); |
3242 | 3317 | } |
3243 | | - throw new DataIntegrityViolationException("Cannot update License Obligation"); |
| 3318 | + |
| 3319 | + return obligationStatusMap; |
| 3320 | + } |
| 3321 | + |
| 3322 | + /** |
| 3323 | + * Updates the project obligations by retrieving the releases and setting the license information with obligations. |
| 3324 | + * It also adds linked obligations to the project. |
| 3325 | + * This method is called when the project has no linked obligations or when the existing obligations need to be updated. |
| 3326 | + * |
| 3327 | + * @param sw360Project The SW360 project to update obligations for. |
| 3328 | + * @param sw360User The user performing the operation. |
| 3329 | + * @param existingObligationStatusMap The existing obligation status map to be updated. |
| 3330 | + * @return A map of updated obligation status information. |
| 3331 | + * @throws TException If there is an error during the Thrift operation. |
| 3332 | + */ |
| 3333 | + private Map<String, ObligationStatusInfo> updateProjectLicenseObligations( |
| 3334 | + Project sw360Project, |
| 3335 | + User sw360User, |
| 3336 | + Map<String, ObligationStatusInfo> existingObligationStatusMap |
| 3337 | + ) throws TException { |
| 3338 | + Map<String, String> releaseIdToAcceptedCLI = new HashMap<>(); |
| 3339 | + List<Release> releases = getReleasesWithAttachments(sw360Project, sw360User); |
| 3340 | + |
| 3341 | + Map<String, ObligationStatusInfo> updatedObligationStatusMap = projectService.setLicenseInfoWithObligations( |
| 3342 | + existingObligationStatusMap, |
| 3343 | + releaseIdToAcceptedCLI, |
| 3344 | + releases, |
| 3345 | + sw360User |
| 3346 | + ); |
| 3347 | + |
| 3348 | + |
| 3349 | + projectService.addLinkedObligations(sw360Project, sw360User, updatedObligationStatusMap); |
| 3350 | + return updatedObligationStatusMap; |
| 3351 | + } |
| 3352 | + |
| 3353 | + /** |
| 3354 | + * Retrieves releases with attachments for a given project and user. |
| 3355 | + * It filters out releases that do not have any attachments. |
| 3356 | + * This method is used to ensure that only relevant releases are processed, especially when dealing with license obligations. |
| 3357 | + * |
| 3358 | + * |
| 3359 | + * @param project The project to retrieve releases from. |
| 3360 | + * @param user The user for whom the releases are being retrieved. |
| 3361 | + * @return A list of releases that have attachments. |
| 3362 | + * @throws TException If there is an error during the Thrift operation. |
| 3363 | + */ |
| 3364 | + private List<Release> getReleasesWithAttachments(Project project, User user) throws TException { |
| 3365 | + return project.getReleaseIdToUsage().keySet().stream() |
| 3366 | + .map(releaseId -> { |
| 3367 | + try { |
| 3368 | + Release release = releaseService.getReleaseForUserById(releaseId, user); |
| 3369 | + return release.getAttachmentsSize() > 0 ? release : null; |
| 3370 | + } catch (TException e) { |
| 3371 | + log.error("Error fetching release: " + releaseId, e); |
| 3372 | + return null; |
| 3373 | + } |
| 3374 | + }) |
| 3375 | + .filter(Objects::nonNull) |
| 3376 | + .collect(Collectors.toList()); |
| 3377 | + } |
| 3378 | + @PreAuthorize("hasAuthority('WRITE')") |
| 3379 | + @Operation( |
| 3380 | + summary = "Update project Obligations other than License Obligations", |
| 3381 | + description = "Pass a map of obligations in request body.", |
| 3382 | + tags = {"Projects"} |
| 3383 | + ) |
| 3384 | + @RequestMapping(value = PROJECTS_URL + "/{id}/updateObligation", method = RequestMethod.PATCH) |
| 3385 | + public ResponseEntity<?> patchObligations( |
| 3386 | + @Parameter(description = "Project ID") @PathVariable("id") String id, |
| 3387 | + @Parameter(description = "Map of obligation status info") |
| 3388 | + @RequestBody Map<String, ObligationStatusInfo> requestBodyObligationStatusInfo , |
| 3389 | + @Parameter(description = "Obligation Level", |
| 3390 | + schema = @Schema(allowableValues = {"project", "organization", "component"})) |
| 3391 | + @RequestParam(value = "obligationLevel", required = true) String oblLevel |
| 3392 | + ) throws TException { |
| 3393 | + |
| 3394 | + Map<String, ObligationStatusInfo> obligationStatusMap = new HashMap<>(); |
| 3395 | + try { |
| 3396 | + final User sw360User = restControllerHelper.getSw360UserFromAuthentication(); |
| 3397 | + restControllerHelper.throwIfSecurityUser(sw360User); |
| 3398 | + |
| 3399 | + obligationStatusMap = processObligations(id, sw360User, requestBodyObligationStatusInfo, oblLevel); |
| 3400 | + Map<String, ObligationStatusInfo> updatedObligationStatusMap = projectService |
| 3401 | + .compareObligationStatusMap(sw360User, obligationStatusMap, requestBodyObligationStatusInfo); |
| 3402 | + Project sw360Project = projectService.getProjectForUserById(id, sw360User); |
| 3403 | + ObligationList obligationList = projectService.getObligationData(sw360Project.getLinkedObligationId(), sw360User); |
| 3404 | + RequestStatus updateStatus = projectService |
| 3405 | + .patchLinkedObligations(sw360User, updatedObligationStatusMap, obligationList); |
| 3406 | + if (updateStatus == RequestStatus.SUCCESS) { |
| 3407 | + return ResponseEntity |
| 3408 | + .status(HttpStatus.CREATED) |
| 3409 | + .body(oblLevel + " Obligation Updated Successfully"); |
| 3410 | + } |
| 3411 | + |
| 3412 | + throw new DataIntegrityViolationException("Cannot update "+oblLevel+" Obligation"); |
| 3413 | + } catch (Exception e) { |
| 3414 | + log.error("Error updating {0} obligations: ", oblLevel ,e); |
| 3415 | + throw new DataIntegrityViolationException("Failed to update "+oblLevel+" Obligation: " + e.getMessage()); |
| 3416 | + } |
| 3417 | + } |
| 3418 | + |
| 3419 | + private Map<String, ObligationStatusInfo> processObligations( |
| 3420 | + String projectId, |
| 3421 | + User sw360User, |
| 3422 | + Map<String, ObligationStatusInfo> requestBodyObligationStatusInfo, |
| 3423 | + String oblLevel) throws TException { |
| 3424 | + Project sw360Project = projectService.getProjectForUserById(projectId, sw360User); |
| 3425 | + if (hasLinkedObligations(sw360Project)) { |
| 3426 | + return processExistingObligations(sw360Project, sw360User, requestBodyObligationStatusInfo ,oblLevel); |
| 3427 | + } |
| 3428 | + return updateProjectObligations(sw360Project, sw360User, new HashMap<>(), oblLevel); |
| 3429 | + } |
| 3430 | + |
| 3431 | + private Map<String, ObligationStatusInfo> processExistingObligations( |
| 3432 | + Project sw360Project, |
| 3433 | + User sw360User, |
| 3434 | + Map<String, ObligationStatusInfo> requestBodyObligationStatusInfo, |
| 3435 | + String oblLevel) throws TException { |
| 3436 | + ObligationList obligationList = projectService.getObligationData(sw360Project.getLinkedObligationId(), sw360User); |
| 3437 | + Map<String, ObligationStatusInfo> obligationStatusMap = CommonUtils.nullToEmptyMap(obligationList.getLinkedObligationStatus()); |
| 3438 | + |
| 3439 | + boolean allObligationsPresent = requestBodyObligationStatusInfo.keySet() |
| 3440 | + .stream() |
| 3441 | + .filter(entry -> { |
| 3442 | + ObligationStatusInfo statusInfo = requestBodyObligationStatusInfo.get(entry); |
| 3443 | + return statusInfo.getObligationLevel() == null || statusInfo.getObligationLevel().toString().equalsIgnoreCase(oblLevel); |
| 3444 | + }) |
| 3445 | + .distinct() |
| 3446 | + .collect(Collectors.toSet()) |
| 3447 | + .stream() |
| 3448 | + .allMatch(obligationStatusMap::containsKey); |
| 3449 | + |
| 3450 | + if (!allObligationsPresent) { |
| 3451 | + return updateProjectObligations(sw360Project, sw360User, obligationStatusMap , oblLevel); |
| 3452 | + } |
| 3453 | + |
| 3454 | + return obligationStatusMap; |
| 3455 | + } |
| 3456 | + |
| 3457 | + private Map<String, ObligationStatusInfo> updateProjectObligations( |
| 3458 | + Project sw360Project, |
| 3459 | + User sw360User, |
| 3460 | + Map<String, ObligationStatusInfo> existingObligationStatusMap, |
| 3461 | + String oblLevel) throws TException { |
| 3462 | + |
| 3463 | + Map<String, ObligationStatusInfo> updatedObligationStatusMap = projectService.setObligationsFromAdminSection( |
| 3464 | + sw360User, existingObligationStatusMap, sw360Project, oblLevel); |
| 3465 | + |
| 3466 | + projectService.addLinkedObligations(sw360Project, sw360User, updatedObligationStatusMap); |
| 3467 | + return updatedObligationStatusMap; |
3244 | 3468 | } |
3245 | 3469 |
|
3246 | 3470 | @Operation( |
|
0 commit comments