Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -137,11 +137,12 @@ public static void putRemediationMetricFields(ObjectNode result, RemediationMetr
int total = metric == null ? 0 : metric.totalRemediations();
int applied = metric == null ? 0 : metric.appliedRemediations();
int skipped = metric == null ? 0 : metric.skippedRemediations();
String appliedFieldName = metric instanceof RemediationMetric.Preview ? "availableRemediation" : "appliedRemediation";
Map<String, Integer> skippedByReason = metric == null ? Map.of() : metric.skippedByReason();
Set<String> modifiedFiles = metric == null ? Set.of() : metric.modifiedFiles();

result.put("totalRemediation", total);
result.put("appliedRemediation", applied);
result.put(appliedFieldName, applied);
result.put("skippedRemediation", skipped);
result.put("skippedReasons", formatSkippedReasons(skippedByReason));
result.set("skippedByReason", toObjectNode(skippedByReason));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,7 @@ private static final class ProcessingState {
private final boolean previewMode;
private final Map<String, Map<String, FileMetadata>> changesByIssue = new LinkedHashMap<>();
private final Map<String, String> skipReasonsByIssue = new LinkedHashMap<>();
private final Map<String, String> descriptionsByIssue = new LinkedHashMap<>();
private int xmlEntryCount;
private int appliedRemediations;

Expand Down Expand Up @@ -441,6 +442,12 @@ private void addChangeDetails(String instanceId, String filename, String encodin
}
}

private void recordDescription(String instanceId, String description) {
if (previewMode && instanceId != null && !instanceId.isBlank() && description != null) {
descriptionsByIssue.put(instanceId, description);
}
}

private List<PreviewDetail> buildPreviewDetails() {
List<PreviewDetail> details = new ArrayList<>();

Expand All @@ -461,7 +468,8 @@ private List<PreviewDetail> buildPreviewDetails() {
FilePreview filePreview = new FilePreview(metadata.path, metadata.encoding, fileChanges);
fileMap.put(filename, filePreview);
}
details.add(PreviewDetail.available(issueId, fileMap));
String description = descriptionsByIssue.get(issueId);
details.add(PreviewDetail.available(issueId, description, fileMap));
}

// Add skipped remediations
Expand All @@ -470,7 +478,8 @@ private List<PreviewDetail> buildPreviewDetails() {
String skipReason = entry.getValue();
// Only add if not already in successful list
if (!changesByIssue.containsKey(issueId)) {
details.add(PreviewDetail.skipped(issueId, skipReason));
String description = descriptionsByIssue.get(issueId);
details.add(PreviewDetail.skipped(issueId, description, skipReason));
}
}

Expand Down Expand Up @@ -517,6 +526,13 @@ private void validateRequestedIssueIds() {
private boolean processRemediation(
Element remediation, Path sourceBasePath, FvdlMetadataResult fvdlMetadataResult, ProcessingState state) {
String instanceId = remediation.getAttribute("instanceId");

if (previewMode) {
NodeList nodes = remediation.getElementsByTagNameNS(NAMESPACE_URI, "AuditComment");
String description = nodes.getLength() > 0 ? ((Element) nodes.item(0)).getTextContent() : null;
state.recordDescription(instanceId, description);
}

try {
Map<Path, PendingFileWrite> pendingWrites = prepareFileChanges(remediation, sourceBasePath, fvdlMetadataResult);
if (pendingWrites.isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,16 @@
*
* @param issueId The issue/remediation ID from the remediations.xml file
* @param status Either "available" (successfully processed) or "skipped" (processing failed)
* @param description A detailed explanation of the issue and the suggested remediation
* @param files Map of filename to FilePreview objects containing change details
* @param skipReason Human-readable reason why remediation was skipped (null if status is "available")
*/
@Reflectable
@JsonPropertyOrder({"issueId", "status", "files", "available", "skipped", "skipReason"})
@JsonPropertyOrder({"issueId", "status", "description", "files", "available", "skipped", "skipReason"})
public record PreviewDetail(
String issueId,
String status,
String description,
Map<String, FilePreview> files,
String skipReason) {

Expand All @@ -47,12 +49,12 @@ public record PreviewDetail(
files = files == null ? Map.of() : Collections.unmodifiableMap(new LinkedHashMap<>(files));
}

public static PreviewDetail available(String issueId, Map<String, FilePreview> files) {
return new PreviewDetail(issueId, "available", files, null);
public static PreviewDetail available(String issueId, String description, Map<String, FilePreview> files) {
return new PreviewDetail(issueId, "available", description, files, null);
}

public static PreviewDetail skipped(String issueId, String skipReason) {
return new PreviewDetail(issueId, "skipped", Map.of(), skipReason);
public static PreviewDetail skipped(String issueId, String description, String skipReason) {
return new PreviewDetail(issueId, "skipped", description, Map.of(), skipReason);
}

public boolean isAvailable() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ void remainingIssueIdsDropsAlreadyApplied() {
void aggregatingAnyPreviewMetricYieldsPreviewResultWithMergedDetails() {
RemediationMetric applied = RemediationMetric.unfiltered(1, 1, Set.of("A.java"));
RemediationMetric preview = RemediationMetric.previewUnfiltered(1, 0, Set.of(), Map.of(),
List.of(com.fortify.cli.aviator.fpr.processor.preview.PreviewDetail.skipped("ISSUE-2", "Source file missing")));
List.of(com.fortify.cli.aviator.fpr.processor.preview.PreviewDetail.skipped("ISSUE-2", null, "Source file missing")));

RemediationMetric aggregated = AviatorRemediationMetricsHelper.aggregateMetrics(
null, List.of(applied, preview));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,19 +32,20 @@ class PreviewDetailTest {
void availablePreviewDetailCreatedCorrectly() {
Map<String, FilePreview> files = Map.of("Example.java",
new FilePreview("/path/to/Example.java", "UTF-8", java.util.List.of()));
PreviewDetail detail = PreviewDetail.available("ISSUE-123", files);
PreviewDetail detail = PreviewDetail.available("ISSUE-123", "Remediation rationale", files);

assertNotNull(detail);
assertEquals("ISSUE-123", detail.issueId());
assertEquals("available", detail.status());
assertEquals("Remediation rationale", detail.description());
assertEquals(1, detail.files().size());
assertEquals(null, detail.skipReason());
assertTrue(detail.isAvailable());
}

@Test
void skippedPreviewDetailCreatedCorrectly() {
PreviewDetail detail = PreviewDetail.skipped("ISSUE-456", "Source file missing");
PreviewDetail detail = PreviewDetail.skipped("ISSUE-456", null, "Source file missing");

assertNotNull(detail);
assertEquals("ISSUE-456", detail.issueId());
Expand All @@ -57,30 +58,30 @@ void skippedPreviewDetailCreatedCorrectly() {
@Test
void nullIssueIdThrowsException() {
assertThrows(AviatorBugException.class,
() -> new PreviewDetail(null, "available", Map.of(), null));
() -> new PreviewDetail(null, "available", null, Map.of(), null));
}

@Test
void blankIssueIdThrowsException() {
assertThrows(AviatorBugException.class,
() -> new PreviewDetail("", "available", Map.of(), null));
() -> new PreviewDetail("", "available", null, Map.of(), null));
}

@Test
void nullStatusThrowsException() {
assertThrows(AviatorBugException.class,
() -> new PreviewDetail("ISSUE-1", null, Map.of(), null));
() -> new PreviewDetail("ISSUE-1", null, null, Map.of(), null));
}

@Test
void blankStatusThrowsException() {
assertThrows(AviatorBugException.class,
() -> new PreviewDetail("ISSUE-1", " ", Map.of(), null));
() -> new PreviewDetail("ISSUE-1", " ", null, Map.of(), null));
}

@Test
void nullFilesMapIsConvertedToEmptyMap() {
PreviewDetail detail = new PreviewDetail("ISSUE-1", "available", null, null);
PreviewDetail detail = new PreviewDetail("ISSUE-1", "available", null, null, null);
assertNotNull(detail.files());
assertEquals(0, detail.files().size());
}
Expand All @@ -89,7 +90,7 @@ void nullFilesMapIsConvertedToEmptyMap() {
void filesMapIsUnmodifiable() {
Map<String, FilePreview> files = new java.util.LinkedHashMap<>();
files.put("Test.java", new FilePreview("/path", "UTF-8", java.util.List.of()));
PreviewDetail detail = new PreviewDetail("ISSUE-1", "available", files, null);
PreviewDetail detail = new PreviewDetail("ISSUE-1", "available", null, files, null);

assertThrows(UnsupportedOperationException.class,
() -> detail.files().put("Another.java", new FilePreview("/path2", "UTF-8", java.util.List.of())));
Expand Down
Loading