Fix foundry overwrite option

Resolves #14

Change-Id: Iaaeaf499ec3dad1b8c5b33a28ff60e8703217486
diff --git a/app/src/main/kotlin/de/ids_mannheim/korapxmltools/KorapXmlTool.kt b/app/src/main/kotlin/de/ids_mannheim/korapxmltools/KorapXmlTool.kt
index 646980c..9a789a7 100644
--- a/app/src/main/kotlin/de/ids_mannheim/korapxmltools/KorapXmlTool.kt
+++ b/app/src/main/kotlin/de/ids_mannheim/korapxmltools/KorapXmlTool.kt
@@ -1227,7 +1227,7 @@
 
         if (annotateWith.isNotEmpty()) {
             // Detect external foundry label once from annotateWith command
-            externalFoundry = detectFoundryFromAnnotateCmd(annotateWith)
+            externalFoundry = foundryOverride ?: detectFoundryFromAnnotateCmd(annotateWith)
             // Initialize ZIP output stream BEFORE creating worker pool, if needed
             if (outputFormat == OutputFormat.KORAP_XML) {
                 // Determine output filename - respect outputDir consistently
@@ -1943,15 +1943,17 @@
             dbFactory = DocumentBuilderFactory.newInstance()
             dBuilder = dbFactory!!.newDocumentBuilder()
 
-            // Respect outputDir option consistently
+            // Determine output filename - respect outputDir consistently
             val baseZipName = File(zipFilePath).name.replace(Regex("\\.zip$"), "")
-            val outputMorphoZipFileName = File(outputDir, "$baseZipName.$targetFoundry.zip").absolutePath
-            targetZipFileName = outputMorphoZipFileName
-            LOGGER.info("Output ZIP file: $outputMorphoZipFileName")
+            val autoOutputFileName = File(outputDir, "$baseZipName.$targetFoundry.zip").absolutePath
+            val finalOutputFileName = outputFile ?: autoOutputFileName
+            targetZipFileName = finalOutputFileName
+            val outputMorphoZipFileName = finalOutputFileName
+            LOGGER.info("Output ZIP file: $targetZipFileName")
 
             // Check for existing output file BEFORE redirecting logging, so user sees the message
-            if (File(outputMorphoZipFileName).exists() && !overwrite) {
-                val errorMsg = "Output file $outputMorphoZipFileName already exists. Use --force to overwrite."
+            if (File(targetZipFileName).exists() && !overwrite) {
+                val errorMsg = "Output file $targetZipFileName already exists. Use --force to overwrite."
                 System.err.println("ERROR: $errorMsg")
                 LOGGER.severe(errorMsg)
                 exitProcess(1)
@@ -3949,7 +3951,9 @@
         }
 
         // Use extracted foundry from CoNLL-U output if available
-        val actualFoundry = if (extractedFoundry != null) {
+        val actualFoundry = if (foundryOverride != null) {
+            foundryOverride!!
+        } else if (extractedFoundry != null) {
             LOGGER.info("Using foundry from CoNLL-U output: $extractedFoundry (was: $foundry)")
             // Update the global externalFoundry variable for consistent naming
             externalFoundry = extractedFoundry
diff --git a/app/src/test/kotlin/de/ids_mannheim/korapxmltools/FoundryOverrideTest.kt b/app/src/test/kotlin/de/ids_mannheim/korapxmltools/FoundryOverrideTest.kt
new file mode 100644
index 0000000..8e1f1d9
--- /dev/null
+++ b/app/src/test/kotlin/de/ids_mannheim/korapxmltools/FoundryOverrideTest.kt
@@ -0,0 +1,116 @@
+package de.ids_mannheim.korapxmltools
+
+import org.junit.After
+import org.junit.Before
+import java.io.ByteArrayOutputStream
+import java.io.File
+import java.io.PrintStream
+import java.net.URL
+import kotlin.test.Ignore
+import kotlin.test.Test
+import kotlin.test.assertEquals
+import kotlin.test.assertTrue
+import kotlin.test.assertFalse
+
+class FoundryOverrideTest {
+    private val outContent = ByteArrayOutputStream(10000000)
+    private val errContent = ByteArrayOutputStream()
+    private val originalOut: PrintStream = System.out
+    private val originalErr: PrintStream = System.err
+
+    @Before
+    fun setUpStreams() {
+        System.setOut(PrintStream(outContent))
+        System.setErr(PrintStream(errContent))
+    }
+
+    @After
+    fun restoreStreams() {
+        System.setOut(originalOut)
+        System.setErr(originalErr)
+    }
+
+    private fun loadResource(path: String): URL {
+        val resource = Thread.currentThread().contextClassLoader.getResource(path)
+        requireNotNull(resource) { "Resource $path not found" }
+        return resource
+    }
+
+    @Test
+    fun testFoundryOverrideWithTagger() {
+        val outputDir = File.createTempFile("foundry_override_test", "").apply {
+            delete()
+            mkdirs()
+        }
+        try {
+            val baseZip = loadResource("wud24_sample.zip").path
+            val args = arrayOf(
+                "-f",
+                "-T", "spacy",
+                "-q",
+                "-D", outputDir.path,
+                "-F", "xyz",
+                "-t", "zip",
+                baseZip
+            )
+
+            // Using debug() which calls KorapXmlTool().call()
+            val exitCode = debug(args)
+            assertEquals(0, exitCode, "Tool execution should succeed")
+
+            // Check if the correct file exists
+            val expectedFile = File(outputDir, "wud24_sample.xyz.zip")
+            assertTrue(expectedFile.exists(), "Output file should be named wud24_sample.xyz.zip")
+
+            // Check if the wrong file does NOT exist
+            val wrongFile = File(outputDir, "wud24_sample.spacy.zip")
+            assertFalse(wrongFile.exists(), "Output file wud24_sample.spacy.zip should NOT exist")
+
+            // Check content of the zip
+            val zipEntries = org.apache.commons.compress.archivers.zip.ZipFile.builder()
+                .setFile(expectedFile)
+                .get()
+                .use { zip ->
+                    zip.entries.asSequence().map { it.name }.toList()
+                }
+
+            assertTrue(zipEntries.any { it.contains("/xyz/morpho.xml") }, "Zip should contain entries with 'xyz' foundry")
+            assertFalse(zipEntries.any { it.contains("/spacy/morpho.xml") }, "Zip should NOT contain entries with 'spacy' foundry")
+
+        } finally {
+            outputDir.deleteRecursively()
+        }
+    }
+
+    @Ignore("This test is ignored until -o is fixed")
+    fun testOutputOptionHasPriority() {
+        val outputDir = File.createTempFile("output_option_test", "").apply {
+            delete()
+            mkdirs()
+        }
+        try {
+            val baseZip = loadResource("wud24_sample.zip").path
+            val explicitOutputFile = File(outputDir, "my_custom_output.zip")
+            val args = arrayOf(
+                "-f",
+                "-q",
+                "-T", "spacy",
+                "-o", explicitOutputFile.path,
+                "-t", "zip",
+                baseZip
+            )
+
+            val exitCode = debug(args)
+            assertEquals(0, exitCode, "Tool execution should succeed")
+
+            assertTrue(explicitOutputFile.exists(), "Explicit output file should exist: ${explicitOutputFile.path}")
+            
+            // Ensure the default-named file does NOT exist
+            val defaultFile = File(outputDir, "wud24_sample.spacy.zip")
+            assertFalse(defaultFile.exists(), "Default output file should NOT exist when -o is used")
+
+        } finally {
+            outputDir.deleteRecursively()
+        }
+    }
+}