From 50815d97e55e46a93268aba02786c4425135a1ff Mon Sep 17 00:00:00 2001 From: Marcus van Elst Date: Thu, 9 Apr 2026 06:57:15 +0200 Subject: [PATCH] M1-AP01: Ist-Stand-Inventar und Delta-Analyse --- .../arbeitspakete/m1/berichte/AP01-bericht.md | 424 ++++++++++++++++++ 1 file changed, 424 insertions(+) create mode 100644 docs/arbeitspakete/m1/berichte/AP01-bericht.md diff --git a/docs/arbeitspakete/m1/berichte/AP01-bericht.md b/docs/arbeitspakete/m1/berichte/AP01-bericht.md new file mode 100644 index 0000000..b5adac9 --- /dev/null +++ b/docs/arbeitspakete/m1/berichte/AP01-bericht.md @@ -0,0 +1,424 @@ +# Abschlussbericht AP01 – Ist-Stand-Inventar und Delta-Analyse + +> **Bezug:** `docs/arbeitspakete/m1/AP01-ist-stand-inventar.md` +> **Bearbeiter:** Claude Code (claude-sonnet-4-6) +> **Datum:** 2026-04-09 +> **Commit(s):** — (kein Commit in AP01; der Mensch committet nach Prüfung) +> **Status:** ✅ abgeschlossen + +--- + +## 1. Zusammenfassung + +AP01 hat den vollständigen Ist-Stand der bestehenden Code-Basis inventarisiert und ein Delta zum M1-Soll dokumentiert. Der Build ist grün (147 Tests, 0 Fehler). Die wichtigsten Befunde: Die Paketstruktur ist schichtenbasiert statt hexagonal, es existiert ein vierter Exit-Code (3), der Soll-Stand kennt nur drei (0/1/2), das Eingabe-Encoding ist hartkodiert UTF-8 statt ISO 8859-15, und mehrere M1-Kernanforderungen (Befundmodell mit Spec-/Diagnose-Trennung, Logging-Adapter, Ausgabeartefakte, Suffix-Logik) fehlen vollständig. Der bestehende Code — insbesondere Parser, Domänenmodell und Fachvalidierung — ist qualitativ gut und kann in späteren APs erhalten und migriert werden. + +--- + +## 2. Umgesetzte Änderungen + +Keine Code-Änderungen. Keine `pom.xml`-Änderungen. Keine Datei-Verschiebungen. + +Einzige neue Datei: `docs/arbeitspakete/m1/berichte/AP01-bericht.md` (dieser Bericht). + +--- + +## 3. Scope-Treue + +| Scope-Punkt aus dem Arbeitspaket | Erfüllt? | Bemerkung | +|---|---|---| +| Vollständige Dateiliste `src/main/java` mit Kurzbeschreibung | ✅ | 20 Klassen, alle beschrieben (Abschnitt 5.1) | +| Vollständige Dateiliste `src/test/java` mit Kurzbeschreibung | ✅ | 21 Testklassen, alle beschrieben (Abschnitt 5.2) | +| Dependency-Liste aus `pom.xml` | ✅ | Abschnitt 5.3 | +| Grep: `org.apache.logging.log4j` | ✅ | Abschnitt 5.4 | +| Grep: `StandardCharsets`, `Charset.forName` | ✅ | Abschnitt 5.5 | +| Grep: `System.exit`, `EXIT_CODE` | ✅ | Abschnitt 5.6 | +| Ist-Paketstruktur als Baum | ✅ | Abschnitt 5.7 | +| Delta-Tabelle Paketstruktur | ✅ | Abschnitt 5.8.1 | +| Delta-Tabelle Exit-Codes | ✅ | Abschnitt 5.8.2 | +| Delta-Tabelle fehlende M1-Elemente | ✅ | Abschnitt 5.8.3 | +| Klassifikation pro Paket | ✅ | Abschnitt 5.9 | +| Keine Code-Änderungen | ✅ | keine `.java`-Datei angefasst | +| Keine `pom.xml`-Änderungen | ✅ | — | +| Keine Datei-Verschiebungen | ✅ | — | +| Neue Dateien nur: AP01-bericht.md | ✅ | einzige neue Datei | + +**Wurde der Scope eingehalten?** Ja, vollständig. + +**Wurden Dinge außerhalb des Scopes gemacht?** Nein. + +--- + +## 4. Abnahmekriterien + +| Abnahmekriterium | Erfüllt? | Nachweis | +|---|---|---| +| `berichte/AP01-bericht.md` existiert | ✅ | dieser Bericht | +| Vollständige Dateiliste (main + test) mit Kurzbeschreibung | ✅ | Abschnitte 5.1 und 5.2 | +| Dependency-Liste | ✅ | Abschnitt 5.3 | +| Alle Grep-Fundstellen | ✅ | Abschnitte 5.4–5.6 | +| Ist-vs-Soll-Paketstrukturbaum | ✅ | Abschnitte 5.7 und 5.8.1 | +| Delta-Tabelle Exit-Codes | ✅ | Abschnitt 5.8.2 | +| Delta-Tabelle fehlender M1-Elemente | ✅ | Abschnitt 5.8.3 | +| Klassifikationstabelle pro Paket | ✅ | Abschnitt 5.9 | +| `mvn clean verify` vor und nach AP01 identisch | ✅ | BUILD SUCCESS, 147 Tests; keine Änderungen vorgenommen | +| Keine neuen Dateien außer AP01-bericht.md | ✅ | `git status` zeigt nur diese Datei | + +--- + +## 5. Build- und Teststatus + +### 5.0 Schritt 1: `mvn clean verify` + +- **Ergebnis:** ✅ BUILD SUCCESS +- **Anzahl Tests:** 147 (0 neu; AP01 ändert keinen Code) +- **Fehler / Skipped:** 0 / 0 +- **Dauer:** 11,930 Sekunden +- **Coverage:** noch nicht messbar (kein JaCoCo) + +**Warnungen beim Build (nicht blockierend):** + +| Warnung | Quelle | Bewertung | +|---|---|---| +| Annotation-Processing aktiv, obwohl kein expliziter Prozessor angegeben | javac (2×, für main und test) | kosmetisch; kann mit `-proc:none` oder `-Xlint:-options` unterdrückt werden | +| Mockito self-attaching via ByteBuddy, wird in künftigen JDK-Releases nicht mehr funktionieren | Mockito / JVM | relevant für AP02: Mockito sollte als Java-Agent konfiguriert werden | +| Dynamic loading of agents will be disallowed in future release | JVM (ByteBuddy-Agent) | hängt mit dem Mockito-Problem zusammen; AP02-relevant | +| JVM Sharing only for boot loader classes | HotSpot | unerheblich für den Build | + +--- + +### 5.1 Dateiliste `src/main/java` (Schritt 2) + +**Paket `de.gecheckt.asv.cli`** (2 Klassen) + +| Datei | Kurzbeschreibung | +|---|---| +| `AsvValidatorApplication.java` | Haupteinstiegspunkt (`main`), CLI-Bootstrap und Verdrahtung aller Komponenten per Default-Konstruktor; enthält Exit-Code-Konstanten, `System.exit`-Aufruf, Log4j2-Direktimport und liest die Eingabedatei mit `StandardCharsets.UTF_8`. | +| `ValidationResultPrinter.java` | Gibt ein `ValidationResult` formatiert auf der Konsole aus (Fehler, Warnungen, Infos); enthält die Darstellungslogik, kein Logging. | + +**Paket `de.gecheckt.asv.domain.model`** (4 Klassen) + +| Datei | Kurzbeschreibung | +|---|---| +| `Field.java` | Java Record: ein einzelnes Feld in einem Segment mit Position (positiv), Rohwert (nicht null) und optionalem Feldnamen; unveränderlich. | +| `Segment.java` | Java Record: ein Segment mit Name (nicht leer), Position (positiv) und unveränderlicher Feldliste; bietet Zugriffsmethoden (`getField`, `hasFieldAt`, `getFieldCount`). | +| `Message.java` | Java Record: eine Nachricht mit Position (positiv) und unveränderlicher Segmentliste; bietet Zugriffsmethoden (`hasSegment`, `getSegments(name)`, `getFirstSegment`). | +| `InputFile.java` | Java Record: eine geparste Eingabedatei mit Dateiname (nicht leer) und unveränderlicher Nachrichtenliste; bietet `getMessageCount`. | + +**Paket `de.gecheckt.asv.parser`** (5 Klassen) + +| Datei | Kurzbeschreibung | +|---|---| +| `InputFileParser.java` | Interface: Kontrakt für das Parsen eines Dateiinhalts (String) in ein `InputFile`-Domänenobjekt. | +| `DefaultInputFileParser.java` | Standardimplementierung: liest zeilenweise via `BufferedReader`, ignoriert Leerzeilen, delegiert Tokenisierung an `SegmentLineTokenizer`; erzeugt vereinfachend **genau eine** `Message` pro Datei. | +| `SegmentLineTokenizer.java` | Interface: Kontrakt für das Tokenisieren einer Segmentzeile in Segmentname und Feldliste. | +| `DefaultSegmentLineTokenizer.java` | Standardimplementierung: trennt am `+`-Zeichen (hartkodiert), extrahiert Segmentname als ersten Token. | +| `InputFileParseException.java` | Checked Exception für Parsing-Fehler; wraps beliebige Ursachen. | + +**Paket `de.gecheckt.asv.validation`** (2 Klassen) + +| Datei | Kurzbeschreibung | +|---|---| +| `InputFileValidator.java` | Interface: Kontrakt für die Gesamtvalidierung einer `InputFile`; gibt ein `ValidationResult` zurück. | +| `DefaultInputFileValidator.java` | Orchestrator: führt `StructureValidator` und `FieldValidator` sequenziell aus und mergt die Teil-`ValidationResult`s zu einem Gesamt-Ergebnis. | + +**Paket `de.gecheckt.asv.validation.field`** (2 Klassen) + +| Datei | Kurzbeschreibung | +|---|---| +| `FieldValidator.java` | Interface: Kontrakt für die Feldvalidierung einer `InputFile`. | +| `DefaultFieldValidator.java` | Implementierung: prüft Feldrohwerte auf Leerheit, Whitespace-only; prüft Feldnamen auf Leerheit; keine ASV-fachliche Logik. | + +**Paket `de.gecheckt.asv.validation.model`** (3 Klassen) + +| Datei | Kurzbeschreibung | +|---|---| +| `ValidationSeverity.java` | Enum mit drei Stufen: `INFO`, `WARNING`, `ERROR`. | +| `ValidationError.java` | Java Record: ein einzelner Validierungsbefund mit `errorCode`, `description`, `severity`, `segmentName`, `segmentPosition`, `fieldName`, `fieldPosition`, optionalem `actualValue` und optionalem `expectedRule`. | +| `ValidationResult.java` | Klasse: Sammlung von `ValidationError`-Instanzen mit Hilfsmethoden (`hasErrors`, `hasWarnings`, `hasInfos`, `getErrors`, `getWarnings`, `getInfos`, `merge`). | + +**Paket `de.gecheckt.asv.validation.structure`** (2 Klassen) + +| Datei | Kurzbeschreibung | +|---|---| +| `StructureValidator.java` | Interface: Kontrakt für die Strukturvalidierung einer `InputFile`. | +| `DefaultStructureValidator.java` | Implementierung mit 19 Prüfregeln: strukturelle Vollständigkeit (Nachrichten, Segmente, Feldpositionen), UNH/UNT-Referenzgleichheit, Segmentanzahl-Prüfung, Nachrichtentyp (ASVREC/ASVFEH), Pflicht-Segmente und Reihenfolge in ASVREC, Rechnungskennzeichen, Rechnungsbetrag bei Storno, DGN/LEA-Prüfung, FHL für ASVFEH. | + +**Gesamtzahl Produktionsklassen: 20** + +--- + +### 5.2 Dateiliste `src/test/java` (Schritt 3) + +| Testklasse | Tests (laut Build) | Kurzbeschreibung | +|---|---|---| +| `cli/AsvValidatorApplicationTest` | 3 | Testet `run()` mit fehlenden Argumenten, nicht-existenter Datei und (via Mock) korrekter Verarbeitung. | +| `cli/AsvValidatorApplicationAdditionalTest` | 3 | Weitere `run()`-Szenarien: `InputFileParseException`, Validierungsfehler (Exit-Code 3), allgemeine Exception. | +| `cli/ValidationResultPrinterTest` | 3 | Testet Konsolenausgabe bei Fehlern/Warnungen/Infos und leerem Ergebnis (Null-Guard). | +| `domain/model/FieldTest` | 6 | Konstruktorvalidierung für `Field`: illegale Positionen, null-Rohwert, optionaler Feldname. | +| `domain/model/InputFileTest` | 9 | Konstruktorvalidierung und Methoden für `InputFile`. | +| `domain/model/MessageTest` | 11 | Konstruktorvalidierung und Methoden für `Message`. | +| `domain/model/SegmentTest` | 12 | Konstruktorvalidierung und Methoden für `Segment`. | +| `parser/DefaultInputFileParserTest` | 8 | Parsing verschiedener Dateiformate (Leerzeilen, mehrzeilig, Segmentnamen). | +| `parser/DefaultSegmentLineTokenizerTest` | 3 | Tokenisierung: Segmentname-Extraktion, Feldaufteilung. | +| `validation/DefaultInputFileValidatorTest` | 5 | Orchestrierung: null-Guard, Struktur- und Feldvalidator werden aufgerufen, Merge. | +| `validation/field/DefaultFieldValidatorTest` | 9 | Feldvalidierungsregeln: Leerheit, Whitespace, Feldname. | +| `validation/model/ValidationErrorTest` | 3 | Record-Konstruktor, Optional-Getter für `actualValue` und `expectedRule`. | +| `validation/model/ValidationResultTest` | 2 | `hasErrors`, `merge`. | +| `validation/structure/DefaultStructureValidatorTest` | 22 | Allgemeine Strukturregeln (Regeln 1–11 aus `DefaultStructureValidator`). | +| `validation/structure/DefaultStructureValidatorTestAdditional` | 0 | Datei vorhanden, keine `@Test`-Methoden; vermutlich Hilfsmethoden oder Vorbereitung. | +| `validation/structure/DefaultStructureValidatorAsvfehFhlSegmentTest` | 8 | FHL-Segment-Pflicht für ASVFEH (Regel 19). | +| `validation/structure/DefaultStructureValidatorAsvrecRechnungsbetragTest` | 7 | Rechnungsbetrag `0,00` bei Storno-Rechnungskennzeichen (Regel 17). | +| `validation/structure/DefaultStructureValidatorAsvrecRechnungskennzeichenTest` | 12 | Rechnungskennzeichen-Prüfungen (Regeln 15–16). | +| `validation/structure/DefaultStructureValidatorAsvrecSegmentCardinalityTest` | 9 | Segment-Kardinalität IFA/REA/IVA (Regel 18). | +| `validation/structure/DefaultStructureValidatorAsvrecSegmentOrderTest` | 5 | Segment-Reihenfolge IFA → REA → IVA (Regel 14). | +| `validation/structure/DefaultStructureValidatorAsvrecSegmentsTest` | 7 | Pflicht-Segmente IFA, REA, IVA (Regel 13). | +| **Gesamt** | **147** | | + +**Gesamtzahl Testklassen: 21** (davon 1 ohne `@Test`-Methoden) + +--- + +### 5.3 Dependencies aus `pom.xml` (Schritt 3 Ergänzung) + +| Dependency | Version | Scope | Zweck | +|---|---|---|---| +| `org.apache.logging.log4j:log4j-api` | 2.20.0 | compile | Log4j2 API | +| `org.apache.logging.log4j:log4j-core` | 2.20.0 | compile | Log4j2 Implementierung | +| `org.junit.jupiter:junit-jupiter` | 5.9.2 | test | JUnit 5 | +| `org.mockito:mockito-core` | 5.23.0 | test | Mockito | + +**Plugins:** + +| Plugin | Version | Zweck | +|---|---|---| +| `maven-compiler-plugin` | 3.11.0 | Compiler-Konfiguration (Java 21) | +| `maven-surefire-plugin` | 3.0.0 | Test-Runner | + +**Fehlend laut M1-Soll:** `slf4j-api`, `log4j-slf4j2-impl`, `maven-jar-plugin` (Main-Class), `jacoco-maven-plugin`, PIT/Pitest-Plugin. + +--- + +### 5.4 Grep: Log4j2-Direktimporte (Schritt 4) + +``` +src/main/java/de/gecheckt/asv/cli/AsvValidatorApplication.java:23: import org.apache.logging.log4j.LogManager; +src/main/java/de/gecheckt/asv/cli/AsvValidatorApplication.java:24: import org.apache.logging.log4j.Logger; +``` + +**Befund:** Log4j2-Typen werden ausschließlich in `AsvValidatorApplication` direkt importiert. Kein Test-Code importiert Log4j2. Laut Soll-Architektur dürfen Log4j2-Typen nur in `bootstrap` und `adapter.out.logging` sichtbar sein. + +--- + +### 5.5 Grep: Zeichensatz-Setzen (Schritt 5) + +``` +src/main/java/de/gecheckt/asv/cli/AsvValidatorApplication.java:18: import java.nio.charset.StandardCharsets; +src/main/java/de/gecheckt/asv/cli/AsvValidatorApplication.java:151: String fileContent = Files.readString(path, StandardCharsets.UTF_8); +``` + +**Befund:** Die Eingabedatei wird mit `StandardCharsets.UTF_8` gelesen. Laut Soll-Architektur (`technik-und-architektur.md`) und fachlicher Anforderung (`R-GLOBAL-ZEICHENSATZ-001`) ist **ISO 8859-15** verpflichtend. `Charset.forName` wird nicht verwendet. Kein weiterer Zeichensatz-Code im gesamten Projekt. + +--- + +### 5.6 Grep: `System.exit` und Exit-Code-Konstanten (Schritt 6) + +``` +src/main/java/de/gecheckt/asv/cli/AsvValidatorApplication.java:35: private static final int EXIT_CODE_SUCCESS = 0; +src/main/java/de/gecheckt/asv/cli/AsvValidatorApplication.java:36: private static final int EXIT_CODE_INVALID_ARGUMENTS = 1; +src/main/java/de/gecheckt/asv/cli/AsvValidatorApplication.java:37: private static final int EXIT_CODE_FILE_ERROR = 2; +src/main/java/de/gecheckt/asv/cli/AsvValidatorApplication.java:38: private static final int EXIT_CODE_VALIDATION_ERRORS = 3; +src/main/java/de/gecheckt/asv/cli/AsvValidatorApplication.java:83: System.exit(exitCode); +src/main/java/de/gecheckt/asv/cli/AsvValidatorApplication.java:96: return EXIT_CODE_INVALID_ARGUMENTS; +src/main/java/de/gecheckt/asv/cli/AsvValidatorApplication.java:112: return result.hasErrors() ? EXIT_CODE_VALIDATION_ERRORS : EXIT_CODE_SUCCESS; +src/main/java/de/gecheckt/asv/cli/AsvValidatorApplication.java:117: return EXIT_CODE_FILE_ERROR; +src/main/java/de/gecheckt/asv/cli/AsvValidatorApplication.java:121: return EXIT_CODE_FILE_ERROR; +src/main/java/de/gecheckt/asv/cli/AsvValidatorApplication.java:125: return EXIT_CODE_FILE_ERROR; +``` + +**Befund:** `System.exit` wird genau einmal aufgerufen (Zeile 83, in `main`). Die Methode `run()` gibt einen `int`-Exit-Code zurück und ist damit testbar — das ist ein positives Muster. Es existieren vier Exit-Code-Konstanten statt drei. + +--- + +### 5.7 Ist-Paketstruktur (Schritt 7) + +``` +src/main/java/de/gecheckt/asv/ +├── cli/ +│ ├── AsvValidatorApplication.java +│ └── ValidationResultPrinter.java +├── domain/ +│ └── model/ +│ ├── Field.java +│ ├── InputFile.java +│ ├── Message.java +│ └── Segment.java +├── parser/ +│ ├── DefaultInputFileParser.java +│ ├── DefaultSegmentLineTokenizer.java +│ ├── InputFileParseException.java +│ ├── InputFileParser.java +│ └── SegmentLineTokenizer.java +└── validation/ + ├── DefaultInputFileValidator.java + ├── InputFileValidator.java + ├── field/ + │ ├── DefaultFieldValidator.java + │ └── FieldValidator.java + ├── model/ + │ ├── ValidationError.java + │ ├── ValidationResult.java + │ └── ValidationSeverity.java + └── structure/ + ├── DefaultStructureValidator.java + └── StructureValidator.java + +src/test/java/de/gecheckt/asv/ +├── cli/ +│ ├── AsvValidatorApplicationAdditionalTest.java +│ ├── AsvValidatorApplicationTest.java +│ └── ValidationResultPrinterTest.java +├── domain/ +│ └── model/ +│ ├── FieldTest.java +│ ├── InputFileTest.java +│ ├── MessageTest.java +│ └── SegmentTest.java +├── parser/ +│ ├── DefaultInputFileParserTest.java +│ └── DefaultSegmentLineTokenizerTest.java +└── validation/ + ├── DefaultInputFileValidatorTest.java + ├── field/ + │ └── DefaultFieldValidatorTest.java + ├── model/ + │ ├── ValidationErrorTest.java + │ └── ValidationResultTest.java + └── structure/ + ├── DefaultStructureValidatorAsvfehFhlSegmentTest.java + ├── DefaultStructureValidatorAsvrecRechnungsbetragTest.java + ├── DefaultStructureValidatorAsvrecRechnungskennzeichenTest.java + ├── DefaultStructureValidatorAsvrecSegmentCardinalityTest.java + ├── DefaultStructureValidatorAsvrecSegmentOrderTest.java + ├── DefaultStructureValidatorAsvrecSegmentsTest.java + ├── DefaultStructureValidatorTest.java + └── DefaultStructureValidatorTestAdditional.java +``` + +**Soll-Paketstruktur** laut `technik-und-architektur.md`: +``` +de.gecheckt.asv. +├── domain +├── application +├── adapter.in.cli +├── adapter.out.filesystem +├── adapter.out.parsing +├── adapter.out.crypto +├── adapter.out.reporting +├── adapter.out.logging +└── bootstrap +``` + +--- + +### 5.8 Delta-Tabellen (Schritt 8) + +#### 5.8.1 Paketstruktur Ist vs. Soll + +| Soll-Paket | Entsprechung im Ist | Status | Bemerkung | +|---|---|---|---| +| `domain` | `domain.model` | ⚠️ teilweise | Nur Dateimodell vorhanden; Befundmodell fehlt; Paketname ist `domain.model`, nicht `domain` | +| `application` | — | ❌ fehlt | Orchestrierungslogik liegt in `validation` (DefaultInputFileValidator) | +| `adapter.in.cli` | `cli` | ⚠️ teilweise | CLI-Code vorhanden, aber falscher Paketname; enthält auch Bootstrap-Logik | +| `adapter.out.filesystem` | — | ❌ fehlt | Dateisystemzugriff (`Files.readString`) liegt direkt in `AsvValidatorApplication` | +| `adapter.out.parsing` | `parser` | ⚠️ teilweise | Parser vorhanden und gut, aber falscher Paketname | +| `adapter.out.crypto` | — | ❌ fehlt | In M1 noch nicht benötigt (PKCS#7 erst in M8) | +| `adapter.out.reporting` | `cli` (ValidationResultPrinter) | ⚠️ teilweise | Klasse existiert, liegt im falschen Paket | +| `adapter.out.logging` | — | ❌ fehlt | Log4j2 direkt in `cli.AsvValidatorApplication` | +| `bootstrap` | — | ❌ fehlt | Bootstrap-Logik in `AsvValidatorApplication.main()` und Default-Konstruktor | +| — | `validation` | ⚠️ kein Soll-Äquivalent | Application-Logik im falschen Paket | +| — | `validation.model` | ⚠️ kein Soll-Äquivalent | Gehört fachlich näher zu `domain` | +| — | `validation.structure` | ⚠️ kein Soll-Äquivalent | Teils `domain`-Logik, teils `application`-Logik | +| — | `validation.field` | ⚠️ kein Soll-Äquivalent | Teils `domain`-Logik, teils `application`-Logik | + +#### 5.8.2 Exit-Codes Ist vs. Soll + +| Konstante (Ist) | Ist-Wert | Soll-Wert | Soll-Semantik | Bewertung | +|---|---|---|---|---| +| `EXIT_CODE_SUCCESS` | `0` | `0` | gültig | ✅ übereinstimmend | +| `EXIT_CODE_INVALID_ARGUMENTS` | `1` | `2` | Bedienfehler | ❌ Diskrepanz: Ist=1, Soll=2 | +| `EXIT_CODE_FILE_ERROR` | `2` | `2` | Bedienfehler | ⚠️ zufällig gleicher Wert, aber semantisch überlappt mit `EXIT_CODE_INVALID_ARGUMENTS`; laut Soll ist `2` der einzige Bedienfehler-Code | +| `EXIT_CODE_VALIDATION_ERRORS` | `3` | `1` | ungültig | ❌ Diskrepanz: Ist=3, Soll=1; dieser Code existiert im Soll nicht | + +**Kernproblem:** Der Ist-Stand hat **vier** Exit-Codes; der Soll-Stand hat **drei**. `EXIT_CODE_INVALID_ARGUMENTS=1` und `EXIT_CODE_VALIDATION_ERRORS=3` sind gegenüber dem Soll vertauscht/falsch. `EXIT_CODE_INVALID_ARGUMENTS` und `EXIT_CODE_FILE_ERROR` sollen im Soll zusammengeführt werden zu einem einzigen Bedienfehler-Code `2`. + +#### 5.8.3 Fehlende M1-Elemente + +| M1-Element | Status | Ist-Befund | Soll-Anforderung | +|---|---|---|---| +| Befundmodell mit Spec-/Diagnose-Trennung | ❌ fehlt | `ValidationError`/`ValidationResult` kennen keine Trennung zwischen Spec-Urteil und diagnostischer Weiteranalyse; alles in einem `List` | Strukturell trennen: verbindliches Prüfurteil (Spec) ≠ diagnostische Weiteranalyse; Diagnose darf Spec-Urteil nicht verändern (AP05) | +| SLF4J als Logging-Fassade | ❌ fehlt | Log4j2 direkt importiert in `AsvValidatorApplication`; kein SLF4J in `pom.xml` | SLF4J als Fassade, Log4j2 als Bindung; Bindung nur in `adapter.out.logging` und `bootstrap` (AP04) | +| Berichtdatei im Eingabeverzeichnis (`.txt`) | ❌ fehlt | Kein File-Output implementiert; nur Konsolenausgabe via `ValidationResultPrinter` | `.txt`-Datei im Verzeichnis der Eingabedatei, UTF-8 (AP07) | +| Log-Datei im Eingabeverzeichnis (`.log`) | ❌ fehlt | Kein File-Logging konfiguriert | `.log`-Datei im Verzeichnis der Eingabedatei, UTF-8 (AP07) | +| Suffix-Logik `_v1`/`_v2` | ❌ fehlt | Kein Mehrfachlauf-Mechanismus vorhanden | Laufendes Suffix bei bereits existierenden Ausgabedateien (AP07) | +| Minimalbericht bei Exit-Code 2 | ❌ fehlt | Bei Fehlern nur `System.err.println`, kein strukturierter Bericht; kein Bericht bei Bedienfehler | Auch bei Exit-Code 2 muss ein nachvollziehbarer Minimalbericht entstehen (AP08) | +| ISO 8859-15 als Eingabe-Encoding | ❌ fehlt | `Files.readString(path, StandardCharsets.UTF_8)` — hartkodiert UTF-8 | `StandardCharsets.ISO_8859_1` reicht nicht; muss `ISO-8859-15` (Level C) sein; Level-C-Charset nicht in Standard-Java-API (AP02/AP03) | +| Hexagonale Paketstruktur | ❌ fehlt | Schichtenbasierte Struktur: `cli`, `domain`, `parser`, `validation` | Hexagonale Trennung: `domain`, `application`, `adapter.*`, `bootstrap` (AP03) | +| Manueller Bootstrap per Constructor Injection | ⚠️ teilweise | Default-Konstruktor in `AsvValidatorApplication` verdrahtet Komponenten per `new`; aber im falschen Paket und vermischt mit CLI-Logik | Separates `bootstrap`-Paket mit dünner Bootstrap-Klasse; vollständig entkoppelt (AP06) | +| JaCoCo im Build | ❌ fehlt | Kein `jacoco-maven-plugin` in `pom.xml` | Coverage-Messung als Quality-Gate (AP02) | +| PIT / Mutation-Testing im Build | ❌ fehlt | Kein `pitest-maven`-Plugin in `pom.xml` | Mutation-Testing-Profil (AP02) | + +--- + +### 5.9 Klassifikation pro Ist-Paket (Schritt 9) + +| Ist-Paket | enthält | Klassifikation | Begründung | +|---|---|---|---| +| `cli` | `AsvValidatorApplication`, `ValidationResultPrinter` | **behalten und anpassen** | `AsvValidatorApplication` enthält Bootstrap-Logik, CLI-Logik, Dateisystemzugriff und Logging vermischt; muss in AP03/AP06 aufgeteilt werden. `ValidationResultPrinter` ist strukturell sauber und kann nach `adapter.out.reporting` migriert werden. | +| `domain.model` | `Field`, `Segment`, `Message`, `InputFile` | **behalten und migrieren** | Records sind technisch gut und korrekt; das Domänenmodell der Dateistruktur wird erhalten. Paket muss zu `domain` (ohne Sub-Paket `model`) migriert oder dort integriert werden. Das Befundmodell fehlt vollständig und wird in AP05 neu gebaut. | +| `parser` | `InputFileParser`, `DefaultInputFileParser`, `SegmentLineTokenizer`, `DefaultSegmentLineTokenizer`, `InputFileParseException` | **behalten und migrieren** | Gut strukturierter, wertvoller Parser-Code mit sauberem Interface-Kontrakt; muss nach `adapter.out.parsing` migriert werden. Der hartkodierte `+`-Trenner ist ein Rest-Risiko (UNA-Segment fehlt). | +| `validation` | `InputFileValidator`, `DefaultInputFileValidator` | **behalten und anpassen** | Orchestrator-Pattern ist gut (Interface + Implementierung, Constructor Injection, Merge-Logik); muss nach `application` migriert und ggf. an das neue Befundmodell angepasst werden. | +| `validation.model` | `ValidationSeverity`, `ValidationError`, `ValidationResult` | **behalten und anpassen** | Strukturell solide; `ValidationError` als Record ist gut. Das Befundmodell kennt keine Spec-/Diagnose-Trennung und wird in AP05 erweitert. Paketziel: Aufgehen in `domain` (Befundmodell) oder umbenannt als `domain.finding`. | +| `validation.structure` | `StructureValidator`, `DefaultStructureValidator` | **später verwenden (M3+)** | Enthält substantielle ASVREC/ASVFEH-Fachvalidierung mit 19 Regeln — wertvoll, aber M1-fremd. In AP09 einfrieren (als Vorbau für M3+ erhalten, nicht aktiv in den M1-Lauf verdrahtet). | +| `validation.field` | `FieldValidator`, `DefaultFieldValidator` | **später verwenden (M3+)** | Ähnlich wie `validation.structure`: wertvolle Feldlogik, die in M1 nicht weiterentwickelt wird; in AP09 einfrieren. | + +--- + +## 6. Rest-Risiken und offene Punkte + +1. **Trennzeichen hartkodiert (`+`):** `DefaultSegmentLineTokenizer` trennt immer am `+`-Zeichen, ohne das UNA-Segment auszuwerten. ASV erlaubt (gemäß Spezifikation) ein optionales UNA-Segment, das die tatsächlich verwendeten Trennzeichen definiert. Dies ist ein bekanntes technisches Risiko für den Parser (relevant ab M3). + +2. **Mockito-Agent-Warnung:** Mockito 5.23.0 nutzt ByteBuddy-Self-Attach, das in künftigen JDK-Versionen nicht mehr erlaubt sein wird. In AP02 sollte Mockito als expliziter Java-Agent konfiguriert werden (`argLine` in `maven-surefire-plugin`). + +3. **ISO 8859-15 nicht in Standard-Java-API:** `java.nio.charset.StandardCharsets` kennt nur `ISO_8859_1` (Latin-1), nicht ISO 8859-15 (Latin-9). Für ISO 8859-15 muss `Charset.forName("ISO-8859-15")` verwendet werden. Dies muss in AP02 oder AP03 sorgfältig behandelt werden (Charset-Verfügbarkeit im JDK prüfen). + +4. **`DefaultStructureValidatorTestAdditional` ohne Tests:** Die Datei existiert, enthält aber keine `@Test`-Methoden. Dies ist unkritisch, sollte aber in AP10 aufgeräumt werden (entweder Tests hinzufügen oder Datei entfernen). + +5. **`DefaultInputFileParser` erzeugt immer genau eine Message:** Der Parser erzeugt per Design „vereinfachend" genau eine Nachricht pro Datei (`// For this simplified version, we assume exactly one message per file`). Dies ist für M1 akzeptabel, muss aber spätestens in M3 überarbeitet werden. + +6. **Klassifikation als Arbeitsgrundlage:** Die Einschätzungen in Abschnitt 5.9 sind konservativ; die tatsächliche Entscheidung über Verbleib oder Neubau kann in späteren APs revidiert werden. + +7. **Keine Main-Class im JAR-Manifest:** Das aktuelle `pom.xml` konfiguriert kein `maven-jar-plugin` mit `Main-Class`-Manifest-Eintrag. Das JAR ist nach `mvn package` nicht direkt mit `java -jar` startbar. + +--- + +## 7. Empfehlungen für Folge-Arbeitspakete + +- **AP02 (Build-Infrastruktur):** SLF4J- und Log4j2-SLF4J-Bridge-Dependency hinzufügen, JaCoCo und PIT konfigurieren, `maven-jar-plugin` mit `Main-Class` einrichten, Mockito als Java-Agent in `maven-surefire-plugin` konfigurieren (Warnung beheben). + +- **AP03 (Paketstruktur):** Die Klassifikationstabelle (Abschnitt 5.9) kann direkt als Migrationsleitfaden verwendet werden. `validation.structure` und `validation.field` sind bewusst für `später verwenden (M3+)` markiert — AP09 soll sie einfrieren. + +- **AP05 (Befundmodell):** Das bestehende `ValidationError`/`ValidationResult`-Modell kann als Ausgangspunkt dienen, muss aber um die Spec-/Diagnose-Trennung erweitert werden. `ValidationSeverity` könnte erhalten bleiben. + +- **AP06 (Bootstrap/CLI):** Exit-Code-Konstanten komplett ersetzen: `0` = gültig, `1` = ungültig, `2` = Bedienfehler. Den hartkodiert-UTF-8-Lesezugriff auf ISO 8859-15 umstellen. + +--- + +## 8. Reviewer-Checkliste + +- [x] Alle im Arbeitspaket genannten Scope-IN-Punkte sind nachweislich umgesetzt (Abschnitte 5.1–5.9) +- [x] Keine Scope-OUT-Punkte wurden angefasst (keine Code-, `pom.xml`- oder Datei-Änderungen) +- [x] Abnahmekriterien sind mit konkreten Nachweisen belegt (Abschnitt 4) +- [x] `mvn clean verify` ist grün (147 Tests, BUILD SUCCESS — Abschnitt 5.0) +- [ ] Der Commit für dieses AP hat eine sprechende Message (`M1-AP01: Ist-Stand-Inventar und Delta-Analyse`) — _Commit liegt beim Menschen_ +- [x] Keine Regeln der Grunddokumente (Spec, Fachliche, Technik) wurden verletzt +- [x] Rest-Risiken sind ehrlich dokumentiert (Abschnitt 6)