Files

425 lines
27 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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.45.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 111 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 1516). |
| `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<ValidationError>` | 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.15.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)