ArchiMateImportController.java
package com.taxonomy.catalog.controller;
import com.taxonomy.catalog.service.ArchiMateImportException;
import com.taxonomy.catalog.service.ArchiMateXmlImporter;
import com.taxonomy.dto.ArchiMateImportResult;
import com.taxonomy.workspace.service.WorkspaceContext;
import com.taxonomy.workspace.service.WorkspaceContextResolver;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.util.Map;
/** REST API for previewing and importing ArchiMate 3.x XML models. */
@RestController
@RequestMapping("/api/import")
@Tag(name = "ArchiMate Import")
public class ArchiMateImportController {
private static final Logger log = LoggerFactory.getLogger(ArchiMateImportController.class);
private final ArchiMateXmlImporter importer;
private final WorkspaceContextResolver contextResolver;
public ArchiMateImportController(ArchiMateXmlImporter importer,
WorkspaceContextResolver contextResolver) {
this.importer = importer;
this.contextResolver = contextResolver;
}
@Operation(summary = "Preview ArchiMate XML import",
description = "Parses, matches, and checks duplicates for the active workspace without writing relations")
@PostMapping(value = "/preview/archimate", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<?> previewArchiMate(@RequestParam("file") MultipartFile file) {
return process(file, true);
}
@Operation(summary = "Import ArchiMate XML",
description = "Atomically creates matched taxonomy relations in the active workspace")
@PostMapping(value = "/archimate", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<?> importArchiMate(@RequestParam("file") MultipartFile file) {
return process(file, false);
}
private ResponseEntity<?> process(MultipartFile file, boolean preview) {
if (file.isEmpty()) {
return ResponseEntity.badRequest().body(Map.of(
"error", "EMPTY_FILE",
"message", "The uploaded ArchiMate XML file is empty"));
}
WorkspaceContext context = contextResolver.resolveCurrentContext();
try {
ArchiMateImportResult result = preview
? importer.previewXml(file.getInputStream(), context)
: importer.importXml(file.getInputStream(), context);
return ResponseEntity.ok(result);
} catch (ArchiMateImportException error) {
log.warn("ArchiMate {} rejected for file '{}' in workspace '{}': {}",
preview ? "preview" : "import", file.getOriginalFilename(),
context.workspaceId(), error.getMessage());
return ResponseEntity.status(422).body(Map.of(
"error", "INVALID_ARCHIMATE_XML",
"message", error.getMessage()));
} catch (Exception error) {
log.error("ArchiMate {} failed for file '{}' in workspace '{}'",
preview ? "preview" : "import", file.getOriginalFilename(),
context.workspaceId(), error);
return ResponseEntity.internalServerError().body(Map.of(
"error", "ARCHIMATE_IMPORT_FAILED",
"message", "The ArchiMate model could not be processed"));
}
}
}