ReportApiController.java
package com.taxonomy.architecture.controller;
import com.taxonomy.dto.ArchitectureReport;
import com.taxonomy.architecture.service.ArchitectureReportService;
import com.taxonomy.versioning.service.RepositoryStateService;
import com.taxonomy.workspace.service.WorkspaceResolver;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
/**
* REST API for Architecture Report Export.
*
* <p>Endpoints:
* <ul>
* <li>{@code POST /api/report/markdown} — Export as Markdown (.md)</li>
* <li>{@code POST /api/report/html} — Export as standalone HTML</li>
* <li>{@code POST /api/report/docx} — Export as Word document (.docx)</li>
* <li>{@code POST /api/report/json} — Export as structured JSON</li>
* </ul>
*/
@RestController
@RequestMapping("/api/report")
@Tag(name = "Report Export")
public class ReportApiController {
private final ArchitectureReportService reportService;
private final RepositoryStateService repositoryStateService;
private final WorkspaceResolver workspaceResolver;
public ReportApiController(ArchitectureReportService reportService,
RepositoryStateService repositoryStateService,
WorkspaceResolver workspaceResolver) {
this.reportService = reportService;
this.repositoryStateService = repositoryStateService;
this.workspaceResolver = workspaceResolver;
}
/**
* Request body for report generation.
*/
public record ReportRequest(
Map<String, Integer> scores,
String businessText,
int minScore) {
}
@Operation(summary = "Export Markdown report",
description = "Generates a comprehensive architecture report as Markdown")
@ApiResponse(responseCode = "200", description = "Markdown report returned")
@ApiResponse(responseCode = "400", description = "Scores are missing")
@PostMapping("/markdown")
public ResponseEntity<byte[]> exportMarkdown(@RequestBody ReportRequest request) {
if (request.scores() == null || request.scores().isEmpty()) {
return ResponseEntity.badRequest().build();
}
ArchitectureReport report = reportService.generateReport(
request.scores(), request.businessText(), request.minScore());
String markdown = reportService.renderMarkdown(report);
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION,
"attachment; filename=\"architecture-report.md\"")
.header(HttpHeaders.CONTENT_TYPE, "text/markdown; charset=UTF-8")
.body(markdown.getBytes(java.nio.charset.StandardCharsets.UTF_8));
}
@Operation(summary = "Export HTML report",
description = "Generates a comprehensive architecture report as standalone HTML")
@ApiResponse(responseCode = "200", description = "HTML report returned")
@ApiResponse(responseCode = "400", description = "Scores are missing")
@PostMapping("/html")
public ResponseEntity<byte[]> exportHtml(@RequestBody ReportRequest request) {
if (request.scores() == null || request.scores().isEmpty()) {
return ResponseEntity.badRequest().build();
}
ArchitectureReport report = reportService.generateReport(
request.scores(), request.businessText(), request.minScore());
String html = reportService.renderHtml(report);
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION,
"attachment; filename=\"architecture-report.html\"")
.header(HttpHeaders.CONTENT_TYPE, "text/html; charset=UTF-8")
.body(html.getBytes(java.nio.charset.StandardCharsets.UTF_8));
}
@Operation(summary = "Export DOCX report",
description = "Generates a comprehensive architecture report as Word document")
@ApiResponse(responseCode = "200", description = "DOCX report returned as binary")
@ApiResponse(responseCode = "400", description = "Scores are missing")
@PostMapping("/docx")
public ResponseEntity<byte[]> exportDocx(@RequestBody ReportRequest request) {
if (request.scores() == null || request.scores().isEmpty()) {
return ResponseEntity.badRequest().build();
}
ArchitectureReport report = reportService.generateReport(
request.scores(), request.businessText(), request.minScore());
byte[] docx = reportService.renderDocx(report);
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION,
"attachment; filename=\"architecture-report.docx\"")
.contentType(MediaType.parseMediaType(
"application/vnd.openxmlformats-officedocument.wordprocessingml.document"))
.body(docx);
}
@Operation(summary = "Export JSON report",
description = "Returns the full architecture report as structured JSON")
@ApiResponse(responseCode = "200", description = "JSON report returned")
@ApiResponse(responseCode = "400", description = "Scores are missing")
@PostMapping("/json")
public ResponseEntity<ArchitectureReport> exportJson(@RequestBody ReportRequest request) {
if (request.scores() == null || request.scores().isEmpty()) {
return ResponseEntity.badRequest().build();
}
ArchitectureReport report = reportService.generateReport(
request.scores(), request.businessText(), request.minScore());
report.setViewContext(repositoryStateService.getViewContext(
workspaceResolver.resolveCurrentUsername(), "draft"));
return ResponseEntity.ok(report);
}
}