Meilenstein 1 vor Implementierung der Spezifikation

This commit is contained in:
2026-03-26 01:03:55 +01:00
parent fc4386ac99
commit 1b4b22b073
27 changed files with 873 additions and 374 deletions

View File

@@ -9,8 +9,7 @@
<properties> <properties>
<!-- Java Version --> <!-- Java Version -->
<maven.compiler.source>21</maven.compiler.source> <maven.compiler.release>21</maven.compiler.release>
<maven.compiler.target>21</maven.compiler.target>
<!-- Encoding --> <!-- Encoding -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
@@ -19,7 +18,7 @@
<!-- Dependency Versions --> <!-- Dependency Versions -->
<log4j.version>2.20.0</log4j.version> <log4j.version>2.20.0</log4j.version>
<junit.version>5.9.2</junit.version> <junit.version>5.9.2</junit.version>
<mockito.version>4.11.0</mockito.version> <mockito.version>5.23.0</mockito.version>
<!-- Plugin Versions --> <!-- Plugin Versions -->
<maven-compiler-plugin.version>3.11.0</maven-compiler-plugin.version> <maven-compiler-plugin.version>3.11.0</maven-compiler-plugin.version>
@@ -65,8 +64,7 @@
<artifactId>maven-compiler-plugin</artifactId> <artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version> <version>${maven-compiler-plugin.version}</version>
<configuration> <configuration>
<source>21</source> <release>21</release>
<target>21</target>
</configuration> </configuration>
</plugin> </plugin>

View File

@@ -0,0 +1,163 @@
package de.gecheckt.asv.cli;
import de.gecheckt.asv.domain.model.InputFile;
import de.gecheckt.asv.parser.DefaultInputFileParser;
import de.gecheckt.asv.parser.DefaultSegmentLineTokenizer;
import de.gecheckt.asv.parser.InputFileParseException;
import de.gecheckt.asv.parser.InputFileParser;
import de.gecheckt.asv.parser.SegmentLineTokenizer;
import de.gecheckt.asv.validation.DefaultInputFileValidator;
import de.gecheckt.asv.validation.InputFileValidator;
import de.gecheckt.asv.validation.field.DefaultFieldValidator;
import de.gecheckt.asv.validation.field.FieldValidator;
import de.gecheckt.asv.validation.model.ValidationResult;
import de.gecheckt.asv.validation.structure.DefaultStructureValidator;
import de.gecheckt.asv.validation.structure.StructureValidator;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
/**
* Haupteinstiegspunkt für die ASV Format Validator CLI-Anwendung.
*
* Diese Anwendung validiert Dateien gegen ein segmentorientiertes Dateiformat.
* Sie nimmt einen Dateipfad als Kommandozeilenargument entgegen, parst die Datei,
* validiert sie und gibt die Ergebnisse auf der Konsole aus.
*/
public class AsvValidatorApplication {
private static final int EXIT_CODE_SUCCESS = 0;
private static final int EXIT_CODE_INVALID_ARGUMENTS = 1;
private static final int EXIT_CODE_FILE_ERROR = 2;
private static final int EXIT_CODE_VALIDATION_ERRORS = 3;
private static final Logger logger = LogManager.getLogger(AsvValidatorApplication.class);
private final InputFileParser parser;
private final InputFileValidator validator;
private final ValidationResultPrinter printer;
/**
* Konstruktor für einen AsvValidatorApplication mit Standardkomponenten.
*/
public AsvValidatorApplication() {
// Initialize all required components
SegmentLineTokenizer tokenizer = new DefaultSegmentLineTokenizer();
this.parser = new DefaultInputFileParser(tokenizer);
StructureValidator structureValidator = new DefaultStructureValidator();
FieldValidator fieldValidator = new DefaultFieldValidator();
this.validator = new DefaultInputFileValidator(structureValidator, fieldValidator);
this.printer = new ValidationResultPrinter();
}
/**
* Konstruktor für einen AsvValidatorApplication mit den bereitgestellten Komponenten.
* Dieser Konstruktor unterstützt Dependency Injection für bessere Testbarkeit.
*
* @param parser der Parser zum Parsen von Eingabedateien
* @param validator der Validator zum Validieren geparster Dateien
* @param printer der Printer zum Anzeigen von Validierungsergebnissen
*/
public AsvValidatorApplication(InputFileParser parser, InputFileValidator validator, ValidationResultPrinter printer) {
this.parser = parser;
this.validator = validator;
this.printer = printer;
}
/**
* Haupteinstiegspunkt für die Anwendung.
*
* @param args Kommandozeilenargumente - erwartet genau ein Argument: den Dateipfad
*/
public static void main(String[] args) {
AsvValidatorApplication app = new AsvValidatorApplication();
int exitCode = app.run(args);
System.exit(exitCode);
}
/**
* Führt die Anwendung mit den bereitgestellten Argumenten aus.
*
* @param args Kommandozeilenargumente
* @return Exit-Code (0 für Erfolg, ungleich 0 für Fehler)
*/
public int run(String[] args) {
// Validate command line arguments
if (args.length != 1) {
printUsage();
return EXIT_CODE_INVALID_ARGUMENTS;
}
String filePath = args[0];
try {
// Parse the file
InputFile inputFile = parseFile(filePath);
// Validate the parsed file
ValidationResult result = validator.validate(inputFile);
// Output results
printer.printToConsole(result);
// Return appropriate exit code based on validation results
return result.hasErrors() ? EXIT_CODE_VALIDATION_ERRORS : EXIT_CODE_SUCCESS;
} catch (IOException e) {
logger.error("Fehler beim Lesen der Datei: {}", e.getMessage(), e);
System.err.println("Fehler beim Lesen der Datei: " + e.getMessage());
return EXIT_CODE_FILE_ERROR;
} catch (InputFileParseException e) {
logger.error("Fehler beim Parsen der Datei: {}", e.getMessage(), e);
System.err.println("Fehler beim Parsen der Datei: " + e.getMessage());
return EXIT_CODE_FILE_ERROR;
} catch (Exception e) {
logger.error("Unerwarteter Fehler während der Validierung: {}", e.getMessage(), e);
System.err.println("Unerwarteter Fehler während der Validierung: " + e.getMessage());
return EXIT_CODE_FILE_ERROR;
}
}
/**
* Parst eine Datei unter dem gegebenen Pfad.
*
* @param filePath Pfad zur zu parsenden Datei
* @return geparstes InputFile-Objekt
* @throws IOException wenn die Datei nicht gelesen werden kann
* @throws InputFileParseException wenn die Datei nicht geparst werden kann
*/
private InputFile parseFile(String filePath) throws IOException, InputFileParseException {
Path path = Paths.get(filePath);
if (!Files.exists(path)) {
throw new IOException("File does not exist: " + filePath);
}
if (!Files.isRegularFile(path)) {
throw new IOException("Path is not a regular file: " + filePath);
}
if (!Files.isReadable(path)) {
throw new IOException("File is not readable: " + filePath);
}
String fileContent = Files.readString(path, StandardCharsets.UTF_8);
return parser.parse(path.getFileName().toString(), fileContent);
}
/**
* Gibt Nutzungsinformationen auf der Konsole aus.
*/
private void printUsage() {
System.out.println("ASV Format Validator");
System.out.println("Verwendung: java -jar asv-format-validator.jar <datei-pfad>");
System.out.println(" <datei-pfad> Pfad zur zu validierenden Datei");
}
}

View File

@@ -0,0 +1,67 @@
package de.gecheckt.asv.cli;
import de.gecheckt.asv.validation.model.ValidationError;
import de.gecheckt.asv.validation.model.ValidationResult;
/**
* Printer-Klasse zum Ausgeben von ValidationResult-Objekten auf der Konsole.
* Diese Klasse trennt die Darstellungslogik vom Datenmodell.
*/
public class ValidationResultPrinter {
/**
* Gibt ein ValidationResult formatiert auf der Konsole aus.
*
* @param result das auszugebende ValidationResult (darf nicht null sein)
*/
public void printToConsole(ValidationResult result) {
if (result == null) {
throw new IllegalArgumentException("ValidationResult must not be null");
}
System.out.println("=== Validierungsergebnis ===");
if (result.hasErrors()) {
System.out.println("Fehler (" + result.getErrors().size() + "):");
result.getErrors().forEach(error -> System.out.println(" [ERROR] " + formatError(error)));
}
if (result.hasWarnings()) {
System.out.println("Warnungen (" + result.getWarnings().size() + "):");
result.getWarnings().forEach(error -> System.out.println(" [WARNING] " + formatError(error)));
}
if (result.hasInfos()) {
System.out.println("Informationen (" + result.getInfos().size() + "):");
result.getInfos().forEach(error -> System.out.println(" [INFO] " + formatError(error)));
}
if (!result.hasErrors() && !result.hasWarnings() && !result.hasInfos()) {
System.out.println("Keine Probleme gefunden.");
}
System.out.println("============================");
}
/**
* Formatiert einen ValidationError für die Konsolenausgabe.
*
* @param error der zu formatierende Fehler
* @return formatierte Zeichenkettendarstellung des Fehlers
*/
private String formatError(ValidationError error) {
var sb = new StringBuilder();
sb.append(error.description());
sb.append(" (Code: ").append(error.errorCode()).append(")");
sb.append(" im Segment '").append(error.segmentName()).append("' Position ").append(error.segmentPosition());
sb.append(", Feld '").append(error.fieldName()).append("' Position ").append(error.fieldPosition());
error.getActualValue().ifPresent(value ->
sb.append(", Ist-Wert: '").append(value).append("'"));
error.getExpectedRule().ifPresent(rule ->
sb.append(", Erwartet: '").append(rule).append("'"));
return sb.toString();
}
}

View File

@@ -4,7 +4,6 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.stream.Collectors;
/** /**
* Represents a message in an input file. * Represents a message in an input file.
@@ -92,7 +91,7 @@ public record Message(int messagePosition, List<Segment> segments) {
return segments.stream() return segments.stream()
.filter(segment -> segmentName.equals(segment.segmentName())) .filter(segment -> segmentName.equals(segment.segmentName()))
.collect(Collectors.toList()); .toList();
} }
/** /**

View File

@@ -5,29 +5,28 @@ import de.gecheckt.asv.domain.model.InputFile;
import de.gecheckt.asv.domain.model.Message; import de.gecheckt.asv.domain.model.Message;
import de.gecheckt.asv.domain.model.Segment; import de.gecheckt.asv.domain.model.Segment;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader; import java.io.StringReader;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
/** /**
* Default implementation of InputFileParser. * Standardimplementierung von InputFileParser.
*/ */
public class DefaultInputFileParser implements InputFileParser { public class DefaultInputFileParser implements InputFileParser {
private final SegmentLineTokenizer tokenizer; private final SegmentLineTokenizer tokenizer;
/** /**
* Constructs a DefaultInputFileParser with the specified tokenizer. * Konstruktor für einen DefaultInputFileParser mit dem angegebenen Tokenizer.
* *
* @param tokenizer the tokenizer to use for parsing segment lines * @param tokenizer der für das Parsen von Segmentzeilen zu verwendende Tokenizer
*/ */
public DefaultInputFileParser(SegmentLineTokenizer tokenizer) { public DefaultInputFileParser(SegmentLineTokenizer tokenizer) {
this.tokenizer = tokenizer; this.tokenizer = tokenizer;
} }
@Override @Override
public InputFile parse(String fileName, String fileContent) throws IOException { public InputFile parse(String fileName, String fileContent) throws InputFileParseException {
if (fileName == null || fileName.isEmpty()) { if (fileName == null || fileName.isEmpty()) {
throw new IllegalArgumentException("File name must not be null or empty"); throw new IllegalArgumentException("File name must not be null or empty");
} }
@@ -58,7 +57,8 @@ public class DefaultInputFileParser implements InputFileParser {
return new InputFile(fileName, messages); return new InputFile(fileName, messages);
} catch (Exception e) { } catch (Exception e) {
throw new IOException("Error parsing file: " + fileName, e); // Wrap all exceptions as parsing exceptions
throw new InputFileParseException("Error parsing file: " + fileName, e);
} }
} }
} }

View File

@@ -5,8 +5,8 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
/** /**
* Default implementation of SegmentLineTokenizer that uses '+' as field separator * Standardimplementierung von SegmentLineTokenizer, die '+' als Feldtrennzeichen verwendet
* and assumes the first token is the segment name. * und annimmt, dass das erste Token der Segmentname ist.
*/ */
public class DefaultSegmentLineTokenizer implements SegmentLineTokenizer { public class DefaultSegmentLineTokenizer implements SegmentLineTokenizer {

View File

@@ -0,0 +1,30 @@
package de.gecheckt.asv.parser;
/**
* Exception thrown when an input file cannot be parsed due to format or content issues.
* This exception is used specifically for parsing-related problems, as opposed to
* I/O issues which would be represented by IOException.
*/
public class InputFileParseException extends Exception {
private static final long serialVersionUID = 1L;
/**
* Constructs a new InputFileParseException with the specified detail message.
*
* @param message the detail message
*/
public InputFileParseException(String message) {
super(message);
}
/**
* Constructs a new InputFileParseException with the specified detail message and cause.
*
* @param message the detail message
* @param cause the cause of this exception
*/
public InputFileParseException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@@ -1,20 +1,19 @@
package de.gecheckt.asv.parser; package de.gecheckt.asv.parser;
import de.gecheckt.asv.domain.model.InputFile; import de.gecheckt.asv.domain.model.InputFile;
import java.io.IOException;
/** /**
* Interface for parsing input files into the domain model. * Interface für das Parsen von Eingabedateien in das Domänenmodell.
*/ */
public interface InputFileParser { public interface InputFileParser {
/** /**
* Parses the content of a file into an InputFile domain object. * Parst den Inhalt einer Datei in ein InputFile-Domänenobjekt.
* *
* @param fileName the name of the file to parse * @param fileName der Name der zu parsenden Datei
* @param fileContent the content of the file to parse * @param fileContent der Inhalt der zu parsenden Datei
* @return the parsed InputFile domain object * @return das geparste InputFile-Domänenobjekt
* @throws IOException if there is an error reading or parsing the file * @throws InputFileParseException wenn beim Parsen des Dateiinhalts ein Fehler auftritt
*/ */
InputFile parse(String fileName, String fileContent) throws IOException; InputFile parse(String fileName, String fileContent) throws InputFileParseException;
} }

View File

@@ -4,23 +4,23 @@ import de.gecheckt.asv.domain.model.Field;
import java.util.List; import java.util.List;
/** /**
* Interface for splitting a segment line into its components. * Interface für das Aufteilen einer Segmentzeile in ihre Bestandteile.
*/ */
public interface SegmentLineTokenizer { public interface SegmentLineTokenizer {
/** /**
* Extracts the segment name from a segment line. * Extrahiert den Segmentnamen aus einer Segmentzeile.
* *
* @param segmentLine the line to extract the segment name from * @param segmentLine die Zeile, aus der der Segmentname extrahiert werden soll
* @return the segment name * @return der Segmentname
*/ */
String extractSegmentName(String segmentLine); String extractSegmentName(String segmentLine);
/** /**
* Splits a segment line into fields. * Teilt eine Segmentzeile in Felder auf.
* *
* @param segmentLine the line to split into fields * @param segmentLine die in Felder aufzuteilende Zeile
* @return the list of fields * @return die Liste der Felder
*/ */
List<Field> tokenizeFields(String segmentLine); List<Field> tokenizeFields(String segmentLine);
} }

View File

@@ -10,13 +10,14 @@ import de.gecheckt.asv.validation.model.ValidationResult;
import de.gecheckt.asv.validation.structure.StructureValidator; import de.gecheckt.asv.validation.structure.StructureValidator;
/** /**
* Default implementation of InputFileValidator that orchestrates multiple specialized validators. * Standardimplementierung von InputFileValidator, die mehrere spezialisierte Validatoren orchestriert.
* *
* This orchestrator executes validators in a predefined order: * Dieser Orchestrator führt Validatoren in einer vordefinierten Reihenfolge aus:
* 1. StructureValidator - validates structural integrity * 1. StructureValidator - validiert die strukturelle Integrität
* 2. FieldValidator - validates field-specific rules * 2. FieldValidator - validiert feldspezifische Regeln
* *
* Additional validators can be added in the future by extending this class or modifying the validation sequence. * Zusätzliche Validatoren können in Zukunft hinzugefügt werden, indem diese Klasse erweitert
* oder die Validierungssequenz modifiziert wird.
*/ */
public class DefaultInputFileValidator implements InputFileValidator { public class DefaultInputFileValidator implements InputFileValidator {
@@ -24,10 +25,10 @@ public class DefaultInputFileValidator implements InputFileValidator {
private final FieldValidator fieldValidator; private final FieldValidator fieldValidator;
/** /**
* Constructs a DefaultInputFileValidator with the required validators. * Konstruktor für einen DefaultInputFileValidator mit den erforderlichen Validatoren.
* *
* @param structureValidator the structure validator to use (must not be null) * @param structureValidator der zu verwendende Strukturvalidator (darf nicht null sein)
* @param fieldValidator the field validator to use (must not be null) * @param fieldValidator der zu verwendende Feldvalidator (darf nicht null sein)
*/ */
public DefaultInputFileValidator(StructureValidator structureValidator, FieldValidator fieldValidator) { public DefaultInputFileValidator(StructureValidator structureValidator, FieldValidator fieldValidator) {
this.structureValidator = Objects.requireNonNull(structureValidator, "structureValidator must not be null"); this.structureValidator = Objects.requireNonNull(structureValidator, "structureValidator must not be null");

View File

@@ -4,17 +4,17 @@ import de.gecheckt.asv.domain.model.InputFile;
import de.gecheckt.asv.validation.model.ValidationResult; import de.gecheckt.asv.validation.model.ValidationResult;
/** /**
* Interface for orchestrating the validation of an ASV input file. * Interface für die Orchestrierung der Validierung einer ASV-Eingabedatei.
* This validator coordinates multiple specialized validators to perform a complete validation. * Dieser Validator koordiniert mehrere spezialisierte Validatoren, um eine vollständige Validierung durchzuführen.
*/ */
public interface InputFileValidator { public interface InputFileValidator {
/** /**
* Validates the given input file using all configured validators. * Validiert die gegebene Eingabedatei unter Verwendung aller konfigurierten Validatoren.
* *
* @param inputFile the input file to validate (must not be null) * @param inputFile die zu validierende Eingabedatei (darf nicht null sein)
* @return a validation result containing all errors found by all validators * @return ein Validierungsergebnis, das alle von allen Validatoren gefundenen Fehler enthält
* @throws IllegalArgumentException if inputFile is null * @throws IllegalArgumentException wenn inputFile null ist
*/ */
ValidationResult validate(InputFile inputFile); ValidationResult validate(InputFile inputFile);
} }

View File

@@ -1,60 +0,0 @@
package de.gecheckt.asv.validation.example;
import de.gecheckt.asv.validation.model.ValidationError;
import de.gecheckt.asv.validation.model.ValidationResult;
import de.gecheckt.asv.validation.model.ValidationSeverity;
import java.util.Arrays;
import java.util.List;
/**
* Beispielanwendung zur Demonstration der Verwendung der Validierungsmodelle.
*/
public class ValidationExample {
public static void main(String[] args) {
// Erstelle einige Beispielvalidierungsfehler
ValidationError error1 = new ValidationError(
"FORMAT001",
"Ungültiges Datumsformat",
ValidationSeverity.ERROR,
"KOPF",
1,
"ERSTELLUNGSDATUM",
3,
"2023-99-99",
"YYYY-MM-DD"
);
ValidationError warning1 = new ValidationError(
"LENGTH001",
"Feldlänge überschritten",
ValidationSeverity.WARNING,
"POSITION",
5,
"ARTIKELBEZEICHNUNG",
2,
"Extrem langer Artikelname, der die maximale Feldlänge überschreitet",
"Max. 30 Zeichen"
);
ValidationError info1 = new ValidationError(
"OPTIONAL001",
"Optionales Feld ist leer",
ValidationSeverity.INFO,
"FUSS",
100,
"BEMERKUNG",
1,
null,
"Freitextfeld für zusätzliche Informationen"
);
// Erstelle ein ValidationResult-Objekt
List<ValidationError> validationErrors = Arrays.asList(error1, warning1, info1);
ValidationResult result = new ValidationResult(validationErrors);
// Gib das Ergebnis auf der Konsole aus
result.printToConsole();
}
}

View File

@@ -13,12 +13,10 @@ import de.gecheckt.asv.validation.model.ValidationSeverity;
* Default implementation of FieldValidator that checks general field rules. * Default implementation of FieldValidator that checks general field rules.
* *
* Rules checked: * Rules checked:
* 1. Field.rawValue must not be null * 1. Field.rawValue must not be empty
* 2. Field.rawValue must not be empty * 2. Field.rawValue must not consist only of whitespaces
* 3. Field.rawValue must not consist only of whitespaces * 3. Field positions within a segment should be consecutive without gaps, starting at 1
* 4. fieldPosition must be positive * 4. If fieldName is set, it must not be empty or only whitespace
* 5. Field positions within a segment should be consecutive without gaps, starting at 1
* 6. If fieldName is set, it must not be empty or only whitespace
*/ */
public class DefaultFieldValidator implements FieldValidator { public class DefaultFieldValidator implements FieldValidator {
@@ -73,65 +71,33 @@ public class DefaultFieldValidator implements FieldValidator {
var fieldPosition = field.fieldPosition(); var fieldPosition = field.fieldPosition();
var fieldName = field.getFieldName().orElse(""); var fieldName = field.getFieldName().orElse("");
// Rule 1: Field.rawValue must not be null // Rule 2: Field.rawValue must not be empty
// (This is already enforced by the domain model, but we check for completeness) if (rawValue.isEmpty()) {
if (rawValue == null) {
errors.add(createError( errors.add(createError(
"FIELD_001", "FIELD_002",
"Field raw value must not be null", "Field raw value must not be empty",
ValidationSeverity.ERROR, ValidationSeverity.ERROR,
segmentName, segmentName,
segmentPosition, segmentPosition,
fieldName, fieldName,
fieldPosition, fieldPosition,
"null", rawValue,
"Non-null raw value required" "Non-empty raw value required"
)); ));
} else {
// Rule 2: Field.rawValue must not be empty
if (rawValue.isEmpty()) {
errors.add(createError(
"FIELD_002",
"Field raw value must not be empty",
ValidationSeverity.ERROR,
segmentName,
segmentPosition,
fieldName,
fieldPosition,
rawValue,
"Non-empty raw value required"
));
}
// Rule 3: Field.rawValue must not consist only of whitespaces
if (rawValue.trim().isEmpty() && !rawValue.isEmpty()) {
errors.add(createError(
"FIELD_003",
"Field raw value must not consist only of whitespaces",
ValidationSeverity.ERROR,
segmentName,
segmentPosition,
fieldName,
fieldPosition,
rawValue,
"Non-whitespace-only raw value required"
));
}
} }
// Rule 4: fieldPosition must be positive // Rule 3: Field.rawValue must not consist only of whitespaces
// (This is already enforced by the domain model, but we check for completeness) if (rawValue.trim().isEmpty() && !rawValue.isEmpty()) {
if (fieldPosition <= 0) {
errors.add(createError( errors.add(createError(
"FIELD_004", "FIELD_003",
"Field position must be positive", "Field raw value must not consist only of whitespaces",
ValidationSeverity.ERROR, ValidationSeverity.ERROR,
segmentName, segmentName,
segmentPosition, segmentPosition,
fieldName, fieldName,
fieldPosition, fieldPosition,
String.valueOf(fieldPosition), rawValue,
"Positive field position required" "Non-whitespace-only raw value required"
)); ));
} }

View File

@@ -4,17 +4,17 @@ import de.gecheckt.asv.domain.model.InputFile;
import de.gecheckt.asv.validation.model.ValidationResult; import de.gecheckt.asv.validation.model.ValidationResult;
/** /**
* Interface for validating fields in an ASV input file. * Interface für die Validierung von Feldern in einer ASV-Eingabedatei.
* This validator checks general field rules without requiring specification details. * Dieser Validator prüft allgemeine Feldregeln ohne Angabe von Spezifikationsdetails.
*/ */
public interface FieldValidator { public interface FieldValidator {
/** /**
* Validates the fields in the given input file. * Validiert die Felder in der gegebenen Eingabedatei.
* *
* @param inputFile the input file to validate (must not be null) * @param inputFile die zu validierende Eingabedatei (darf nicht null sein)
* @return a validation result containing any field errors found * @return ein Validierungsergebnis, das alle gefundenen Feldfehler enthält
* @throws IllegalArgumentException if inputFile is null * @throws IllegalArgumentException wenn inputFile null ist
*/ */
ValidationResult validate(InputFile inputFile); ValidationResult validate(InputFile inputFile);
} }

View File

@@ -109,56 +109,6 @@ public final class ValidationResult {
return errors; return errors;
} }
/**
* Gibt eine textbasierte Darstellung des Validierungsergebnisses auf der Konsole aus.
*/
public void printToConsole() {
System.out.println("=== Validierungsergebnis ===");
if (hasErrors()) {
System.out.println("Fehler (" + getErrors().size() + "):");
getErrors().forEach(error -> System.out.println(" [ERROR] " + formatError(error)));
}
if (hasWarnings()) {
System.out.println("Warnungen (" + getWarnings().size() + "):");
getWarnings().forEach(error -> System.out.println(" [WARNING] " + formatError(error)));
}
if (hasInfos()) {
System.out.println("Informationen (" + getInfos().size() + "):");
getInfos().forEach(error -> System.out.println(" [INFO] " + formatError(error)));
}
if (!hasErrors() && !hasWarnings() && !hasInfos()) {
System.out.println("Keine Probleme gefunden.");
}
System.out.println("============================");
}
/**
* Formatiert einen ValidationError für die Konsolenausgabe.
*
* @param error der zu formatierende Fehler
* @return formatierte Zeichenkette
*/
private String formatError(ValidationError error) {
var sb = new StringBuilder();
sb.append(error.description());
sb.append(" (Code: ").append(error.errorCode()).append(")");
sb.append(" im Segment '").append(error.segmentName()).append("' Position ").append(error.segmentPosition());
sb.append(", Feld '").append(error.fieldName()).append("' Position ").append(error.fieldPosition());
error.getActualValue().ifPresent(value ->
sb.append(", Ist-Wert: '").append(value).append("'"));
error.getExpectedRule().ifPresent(rule ->
sb.append(", Erwartet: '").append(rule).append("'"));
return sb.toString();
}
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (this == o) return true; if (this == o) return true;

View File

@@ -4,17 +4,17 @@ import de.gecheckt.asv.domain.model.InputFile;
import de.gecheckt.asv.validation.model.ValidationResult; import de.gecheckt.asv.validation.model.ValidationResult;
/** /**
* Interface for validating the structural integrity of an ASV input file. * Interface für die Validierung der strukturellen Integrität einer ASV-Eingabedatei.
* This validator checks general structural rules without requiring specification details. * Dieser Validator prüft allgemeine Strukturregeln ohne Angabe von Spezifikationsdetails.
*/ */
public interface StructureValidator { public interface StructureValidator {
/** /**
* Validates the structural integrity of the given input file. * Validiert die strukturelle Integrität der gegebenen Eingabedatei.
* *
* @param inputFile the input file to validate (must not be null) * @param inputFile die zu validierende Eingabedatei (darf nicht null sein)
* @return a validation result containing any structural errors found * @return ein Validierungsergebnis, das alle gefundenen Strukturfehler enthält
* @throws IllegalArgumentException if inputFile is null * @throws IllegalArgumentException wenn inputFile null ist
*/ */
ValidationResult validate(InputFile inputFile); ValidationResult validate(InputFile inputFile);
} }

View File

@@ -0,0 +1,218 @@
package de.gecheckt.asv.cli;
import de.gecheckt.asv.domain.model.Field;
import de.gecheckt.asv.domain.model.InputFile;
import de.gecheckt.asv.domain.model.Message;
import de.gecheckt.asv.domain.model.Segment;
import de.gecheckt.asv.parser.InputFileParseException;
import de.gecheckt.asv.parser.InputFileParser;
import de.gecheckt.asv.validation.InputFileValidator;
import de.gecheckt.asv.validation.model.ValidationError;
import de.gecheckt.asv.validation.model.ValidationResult;
import de.gecheckt.asv.validation.model.ValidationSeverity;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.*;
/**
* Zusätzliche Unittests für AsvValidatorApplication.
*/
class AsvValidatorApplicationAdditionalTest {
@TempDir
Path tempDir;
@Test
void testRunWithValidFileShouldReturnSuccessExitCode() throws InputFileParseException, IOException {
// Given
InputFileParser parser = mock(InputFileParser.class);
InputFileValidator validator = mock(InputFileValidator.class);
ValidationResultPrinter printer = mock(ValidationResultPrinter.class);
AsvValidatorApplication app = new AsvValidatorApplication(parser, validator, printer);
// Create a test file
Path testFile = tempDir.resolve("valid-file.txt");
String validContent = "HDR|TestHeader\n" +
"DTL|TestData|MoreData\n" +
"TRL|3";
Files.writeString(testFile, validContent);
String[] args = {testFile.toString()};
// Create real objects instead of mocks for final classes
Field hdrField1 = new Field(1, "HDR");
Field hdrField2 = new Field(2, "TestHeader");
Segment hdrSegment = new Segment("HDR", 1, List.of(hdrField1, hdrField2));
Field dtlField1 = new Field(1, "DTL");
Field dtlField2 = new Field(2, "TestData");
Field dtlField3 = new Field(3, "MoreData");
Segment dtlSegment = new Segment("DTL", 2, List.of(dtlField1, dtlField2, dtlField3));
Field trlField1 = new Field(1, "TRL");
Field trlField2 = new Field(2, "3");
Segment trlSegment = new Segment("TRL", 3, List.of(trlField1, trlField2));
Message message = new Message(1, List.of(hdrSegment, dtlSegment, trlSegment));
InputFile inputFile = new InputFile("valid-file.txt", List.of(message));
// Mock the parser and validator behavior
when(parser.parse(anyString(), anyString())).thenReturn(inputFile);
// Create a real ValidationResult with no errors
ValidationResult validationResult = new ValidationResult(List.of());
when(validator.validate(inputFile)).thenReturn(validationResult);
// Capture System.out
ByteArrayOutputStream outContent = new ByteArrayOutputStream();
PrintStream originalOut = System.out;
System.setOut(new PrintStream(outContent));
try {
// When
int exitCode = app.run(args);
// Then
assertEquals(0, exitCode);
// Verify that the printer was called
verify(printer).printToConsole(validationResult);
} finally {
// Restore System.out
System.setOut(originalOut);
}
}
@Test
void testRunWithInvalidFileShouldReturnValidationErrorsExitCode() throws InputFileParseException, IOException {
// Given
InputFileParser parser = mock(InputFileParser.class);
InputFileValidator validator = mock(InputFileValidator.class);
ValidationResultPrinter printer = mock(ValidationResultPrinter.class);
AsvValidatorApplication app = new AsvValidatorApplication(parser, validator, printer);
// Create an invalid test file (missing required segments)
Path testFile = tempDir.resolve("invalid-file.txt");
String invalidContent = "DTL|TestData|MoreData\n" + // Missing HDR
"DTL|MoreData|EvenMoreData\n"; // Missing TRL
Files.writeString(testFile, invalidContent);
String[] args = {testFile.toString()};
// Create real objects instead of mocks for final classes
Field dtlField1 = new Field(1, "DTL");
Field dtlField2 = new Field(2, "TestData");
Field dtlField3 = new Field(3, "MoreData");
Segment dtlSegment1 = new Segment("DTL", 1, List.of(dtlField1, dtlField2, dtlField3));
Field dtlField4 = new Field(1, "DTL");
Field dtlField5 = new Field(2, "MoreData");
Field dtlField6 = new Field(3, "EvenMoreData");
Segment dtlSegment2 = new Segment("DTL", 2, List.of(dtlField4, dtlField5, dtlField6));
Message message = new Message(1, List.of(dtlSegment1, dtlSegment2));
InputFile inputFile = new InputFile("invalid-file.txt", List.of(message));
// Mock the parser and validator behavior
when(parser.parse(anyString(), anyString())).thenReturn(inputFile);
// Create a real ValidationResult with errors
ValidationError error = new ValidationError(
"MISSING_SEGMENT",
"Required segment HDR is missing",
ValidationSeverity.ERROR,
"HDR",
1,
"HDR",
1,
null,
"HDR segment is required"
);
ValidationResult validationResult = new ValidationResult(List.of(error));
when(validator.validate(inputFile)).thenReturn(validationResult);
// Capture System.out
ByteArrayOutputStream outContent = new ByteArrayOutputStream();
PrintStream originalOut = System.out;
System.setOut(new PrintStream(outContent));
try {
// When
int exitCode = app.run(args);
// Then
assertEquals(3, exitCode); // Validation errors exit code
// Verify that the printer was called
verify(printer).printToConsole(validationResult);
} finally {
// Restore System.out
System.setOut(originalOut);
}
}
/**
* Spezialisierter Test für den Fall, dass ein technisch lesbares/parstabares Dokument
* Validierungsfehler enthält und der CLI Exit-Code 3 zurückgibt.
*
* Dieser Test konzentriert sich explizit auf:
* 1. Parser liefert ein InputFile
* 2. Validator liefert ein ValidationResult mit mindestens einem ERROR
* 3. CLI gibt daraufhin Exit-Code 3 zurück
*/
@Test
void testParserReturnsInputFileAndValidatorReturnsErrorsShouldReturnExitCodeThree() throws InputFileParseException, IOException {
// Given
InputFileParser parser = mock(InputFileParser.class);
InputFileValidator validator = mock(InputFileValidator.class);
ValidationResultPrinter printer = mock(ValidationResultPrinter.class);
AsvValidatorApplication app = new AsvValidatorApplication(parser, validator, printer);
// Create a dummy test file (content doesn't matter since we're mocking the parser)
Path testFile = tempDir.resolve("dummy-file.txt");
Files.writeString(testFile, "dummy content");
String[] args = {testFile.toString()};
// Mock: Parser liefert ein gültiges InputFile
InputFile inputFile = mock(InputFile.class);
when(parser.parse(anyString(), anyString())).thenReturn(inputFile);
// Mock: Validator liefert ein ValidationResult mit mindestens einem ERROR
ValidationError validationError = new ValidationError(
"TEST_ERROR_CODE",
"Test error message",
ValidationSeverity.ERROR, // Wichtig: ValidationSeverity.ERROR
"TEST_SEGMENT",
1,
"TEST_FIELD",
1,
null,
"Test error description"
);
ValidationResult validationResultWithErrors = new ValidationResult(List.of(validationError));
when(validator.validate(inputFile)).thenReturn(validationResultWithErrors);
// When
int exitCode = app.run(args);
// Then
// Prüfe explizit, dass der Exit-Code 3 ist
assertEquals(3, exitCode, "CLI should return exit code 3 when validation errors occur");
// Verify that the printer was called with the validation result
verify(printer).printToConsole(validationResultWithErrors);
}
}

View File

@@ -0,0 +1,103 @@
package de.gecheckt.asv.cli;
import de.gecheckt.asv.parser.InputFileParser;
import de.gecheckt.asv.validation.InputFileValidator;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.nio.file.Path;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.*;
/**
* Unittests für AsvValidatorApplication.
*/
class AsvValidatorApplicationTest {
@TempDir
Path tempDir;
@Test
void testRunWithNoArgumentsShouldPrintUsageAndReturnInvalidArgumentsExitCode() {
// Given
InputFileParser parser = mock(InputFileParser.class);
InputFileValidator validator = mock(InputFileValidator.class);
ValidationResultPrinter printer = mock(ValidationResultPrinter.class);
AsvValidatorApplication app = new AsvValidatorApplication(parser, validator, printer);
String[] args = {};
// Capture System.out
ByteArrayOutputStream outContent = new ByteArrayOutputStream();
PrintStream originalOut = System.out;
System.setOut(new PrintStream(outContent));
try {
// When
int exitCode = app.run(args);
// Then
assertEquals(1, exitCode);
assertEquals(true, outContent.toString().contains("Verwendung:"), "Output should contain usage information");
} finally {
// Restore System.out
System.setOut(originalOut);
}
}
@Test
void testRunWithTooManyArgumentsShouldPrintUsageAndReturnInvalidArgumentsExitCode() {
// Given
InputFileParser parser = mock(InputFileParser.class);
InputFileValidator validator = mock(InputFileValidator.class);
ValidationResultPrinter printer = mock(ValidationResultPrinter.class);
AsvValidatorApplication app = new AsvValidatorApplication(parser, validator, printer);
String[] args = {"file1.txt", "file2.txt"};
// Capture System.out
ByteArrayOutputStream outContent = new ByteArrayOutputStream();
PrintStream originalOut = System.out;
System.setOut(new PrintStream(outContent));
try {
// When
int exitCode = app.run(args);
// Then
assertEquals(1, exitCode);
assertEquals(true, outContent.toString().contains("Verwendung:"), "Output should contain usage information");
} finally {
// Restore System.out
System.setOut(originalOut);
}
}
@Test
void testRunWithNonExistentFileShouldReturnFileErrorExitCode() {
// Given
InputFileParser parser = mock(InputFileParser.class);
InputFileValidator validator = mock(InputFileValidator.class);
ValidationResultPrinter printer = mock(ValidationResultPrinter.class);
AsvValidatorApplication app = new AsvValidatorApplication(parser, validator, printer);
String[] args = {"/non/existent/file.txt"};
// Capture System.err
ByteArrayOutputStream errContent = new ByteArrayOutputStream();
PrintStream originalErr = System.err;
System.setErr(new PrintStream(errContent));
try {
// When
int exitCode = app.run(args);
// Then
assertEquals(2, exitCode);
assertEquals(true, errContent.toString().contains("File does not exist"), "Error output should contain file not found message");
} finally {
// Restore System.err
System.setErr(originalErr);
}
}
}

View File

@@ -0,0 +1,69 @@
package de.gecheckt.asv.cli;
import de.gecheckt.asv.validation.model.ValidationError;
import de.gecheckt.asv.validation.model.ValidationResult;
import de.gecheckt.asv.validation.model.ValidationSeverity;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
class ValidationResultPrinterTest {
private final ByteArrayOutputStream outContent = new ByteArrayOutputStream();
private final PrintStream originalOut = System.out;
@BeforeEach
void setUp() {
System.setOut(new PrintStream(outContent));
}
@AfterEach
void tearDown() {
System.setOut(originalOut);
}
@Test
void testPrintToConsoleWithNullResult() {
ValidationResultPrinter printer = new ValidationResultPrinter();
assertThrows(IllegalArgumentException.class, () -> printer.printToConsole(null));
}
@Test
void testPrintToConsoleWithEmptyResult() {
ValidationResultPrinter printer = new ValidationResultPrinter();
ValidationResult result = new ValidationResult(List.of());
printer.printToConsole(result);
String output = outContent.toString();
assertTrue(output.contains("=== Validierungsergebnis ==="));
assertTrue(output.contains("Keine Probleme gefunden."));
assertTrue(output.contains("============================"));
}
@Test
void testPrintToConsoleWithError() {
ValidationError error = new ValidationError(
"TEST001", "Test error", ValidationSeverity.ERROR,
"SEGMENT", 1, "FIELD", 1, "actual", "expected"
);
ValidationResult result = new ValidationResult(List.of(error));
ValidationResultPrinter printer = new ValidationResultPrinter();
printer.printToConsole(result);
String output = outContent.toString();
assertTrue(output.contains("=== Validierungsergebnis ==="));
assertTrue(output.contains("Fehler (1):"));
assertTrue(output.contains("[ERROR] Test error (Code: TEST001)"));
assertTrue(output.contains("im Segment 'SEGMENT' Position 1, Feld 'FIELD' Position 1"));
assertTrue(output.contains("Ist-Wert: 'actual'"));
assertTrue(output.contains("Erwartet: 'expected'"));
assertTrue(output.contains("============================"));
}
}

View File

@@ -2,6 +2,7 @@ package de.gecheckt.asv.domain.model;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
import java.util.List;
/** /**
* Unit tests for the InputFile class. * Unit tests for the InputFile class.
@@ -20,7 +21,7 @@ class InputFileTest {
@Test @Test
void constructorWithFileNameAndMessagesShouldCreateInputFile() { void constructorWithFileNameAndMessagesShouldCreateInputFile() {
Message message = new Message(1); Message message = new Message(1);
InputFile inputFile = new InputFile("test.txt", java.util.Arrays.asList(message)); InputFile inputFile = new InputFile("test.txt", List.of(message));
assertEquals("test.txt", inputFile.sourceFileName()); assertEquals("test.txt", inputFile.sourceFileName());
assertEquals(1, inputFile.messages().size()); assertEquals(1, inputFile.messages().size());
@@ -45,7 +46,7 @@ class InputFileTest {
@Test @Test
void getMessagesShouldReturnUnmodifiableList() { void getMessagesShouldReturnUnmodifiableList() {
Message message = new Message(1); Message message = new Message(1);
InputFile inputFile = new InputFile("test.txt", java.util.Arrays.asList(message)); InputFile inputFile = new InputFile("test.txt", List.of(message));
assertThrows(UnsupportedOperationException.class, () -> { assertThrows(UnsupportedOperationException.class, () -> {
inputFile.getMessages().add(message); inputFile.getMessages().add(message);
@@ -62,7 +63,7 @@ class InputFileTest {
void getMessageCountShouldReturnCorrectCount() { void getMessageCountShouldReturnCorrectCount() {
Message message1 = new Message(1); Message message1 = new Message(1);
Message message2 = new Message(2); Message message2 = new Message(2);
InputFile inputFile = new InputFile("test.txt", java.util.Arrays.asList(message1, message2)); InputFile inputFile = new InputFile("test.txt", List.of(message1, message2));
assertEquals(2, inputFile.getMessageCount()); assertEquals(2, inputFile.getMessageCount());
} }
@@ -70,9 +71,9 @@ class InputFileTest {
@Test @Test
void equalsAndHashCodeShouldWorkCorrectly() { void equalsAndHashCodeShouldWorkCorrectly() {
Message message = new Message(1); Message message = new Message(1);
InputFile inputFile1 = new InputFile("test.txt", java.util.Arrays.asList(message)); InputFile inputFile1 = new InputFile("test.txt", List.of(message));
InputFile inputFile2 = new InputFile("test.txt", java.util.Arrays.asList(message)); InputFile inputFile2 = new InputFile("test.txt", List.of(message));
InputFile inputFile3 = new InputFile("other.txt", java.util.Arrays.asList(message)); InputFile inputFile3 = new InputFile("other.txt", List.of(message));
assertEquals(inputFile1, inputFile2); assertEquals(inputFile1, inputFile2);
assertNotEquals(inputFile1, inputFile3); assertNotEquals(inputFile1, inputFile3);
@@ -82,7 +83,7 @@ class InputFileTest {
@Test @Test
void toStringShouldReturnValidString() { void toStringShouldReturnValidString() {
Message message = new Message(1); Message message = new Message(1);
InputFile inputFile = new InputFile("test.txt", java.util.Arrays.asList(message)); InputFile inputFile = new InputFile("test.txt", List.of(message));
String result = inputFile.toString(); String result = inputFile.toString();
assertTrue(result.contains("sourceFileName=test.txt")); assertTrue(result.contains("sourceFileName=test.txt"));

View File

@@ -2,6 +2,7 @@ package de.gecheckt.asv.domain.model;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
import java.util.List;
/** /**
* Unit tests for the Message class. * Unit tests for the Message class.
@@ -20,7 +21,7 @@ class MessageTest {
@Test @Test
void constructorWithPositionAndSegmentsShouldCreateMessage() { void constructorWithPositionAndSegmentsShouldCreateMessage() {
Segment segment = new Segment("TEST", 1); Segment segment = new Segment("TEST", 1);
Message message = new Message(1, java.util.Arrays.asList(segment)); Message message = new Message(1, List.of(segment));
assertEquals(1, message.messagePosition()); assertEquals(1, message.messagePosition());
assertEquals(1, message.segments().size()); assertEquals(1, message.segments().size());
@@ -41,7 +42,7 @@ class MessageTest {
@Test @Test
void getSegmentsShouldReturnUnmodifiableList() { void getSegmentsShouldReturnUnmodifiableList() {
Segment segment = new Segment("TEST", 1); Segment segment = new Segment("TEST", 1);
Message message = new Message(1, java.util.Arrays.asList(segment)); Message message = new Message(1, List.of(segment));
assertThrows(UnsupportedOperationException.class, () -> { assertThrows(UnsupportedOperationException.class, () -> {
message.getSegments().add(segment); message.getSegments().add(segment);
@@ -58,7 +59,7 @@ class MessageTest {
void hasSegmentShouldWorkCorrectly() { void hasSegmentShouldWorkCorrectly() {
Segment segment1 = new Segment("TEST1", 1); Segment segment1 = new Segment("TEST1", 1);
Segment segment2 = new Segment("TEST2", 2); Segment segment2 = new Segment("TEST2", 2);
Message message = new Message(1, java.util.Arrays.asList(segment1, segment2)); Message message = new Message(1, List.of(segment1, segment2));
assertTrue(message.hasSegment("TEST1")); assertTrue(message.hasSegment("TEST1"));
assertTrue(message.hasSegment("TEST2")); assertTrue(message.hasSegment("TEST2"));
@@ -71,7 +72,7 @@ class MessageTest {
void getSegmentCountShouldReturnCorrectCount() { void getSegmentCountShouldReturnCorrectCount() {
Segment segment1 = new Segment("TEST1", 1); Segment segment1 = new Segment("TEST1", 1);
Segment segment2 = new Segment("TEST2", 2); Segment segment2 = new Segment("TEST2", 2);
Message message = new Message(1, java.util.Arrays.asList(segment1, segment2)); Message message = new Message(1, List.of(segment1, segment2));
assertEquals(2, message.getSegmentCount()); assertEquals(2, message.getSegmentCount());
} }
@@ -81,7 +82,7 @@ class MessageTest {
Segment segment1 = new Segment("TEST", 1); Segment segment1 = new Segment("TEST", 1);
Segment segment2 = new Segment("TEST", 2); Segment segment2 = new Segment("TEST", 2);
Segment segment3 = new Segment("OTHER", 3); Segment segment3 = new Segment("OTHER", 3);
Message message = new Message(1, java.util.Arrays.asList(segment1, segment2, segment3)); Message message = new Message(1, List.of(segment1, segment2, segment3));
var segments = message.getSegments("TEST"); var segments = message.getSegments("TEST");
assertEquals(2, segments.size()); assertEquals(2, segments.size());
@@ -95,7 +96,7 @@ class MessageTest {
void getFirstSegmentShouldReturnCorrectSegment() { void getFirstSegmentShouldReturnCorrectSegment() {
Segment segment1 = new Segment("TEST1", 1); Segment segment1 = new Segment("TEST1", 1);
Segment segment2 = new Segment("TEST2", 2); Segment segment2 = new Segment("TEST2", 2);
Message message = new Message(1, java.util.Arrays.asList(segment1, segment2)); Message message = new Message(1, List.of(segment1, segment2));
assertTrue(message.getFirstSegment("TEST1").isPresent()); assertTrue(message.getFirstSegment("TEST1").isPresent());
assertEquals(segment1, message.getFirstSegment("TEST1").get()); assertEquals(segment1, message.getFirstSegment("TEST1").get());
@@ -109,9 +110,9 @@ class MessageTest {
@Test @Test
void equalsAndHashCodeShouldWorkCorrectly() { void equalsAndHashCodeShouldWorkCorrectly() {
Segment segment = new Segment("TEST", 1); Segment segment = new Segment("TEST", 1);
Message message1 = new Message(1, java.util.Arrays.asList(segment)); Message message1 = new Message(1, List.of(segment));
Message message2 = new Message(1, java.util.Arrays.asList(segment)); Message message2 = new Message(1, List.of(segment));
Message message3 = new Message(2, java.util.Arrays.asList(segment)); Message message3 = new Message(2, List.of(segment));
assertEquals(message1, message2); assertEquals(message1, message2);
assertNotEquals(message1, message3); assertNotEquals(message1, message3);
@@ -121,7 +122,7 @@ class MessageTest {
@Test @Test
void toStringShouldReturnValidString() { void toStringShouldReturnValidString() {
Segment segment = new Segment("TEST", 1); Segment segment = new Segment("TEST", 1);
Message message = new Message(1, java.util.Arrays.asList(segment)); Message message = new Message(1, List.of(segment));
String result = message.toString(); String result = message.toString();
assertTrue(result.contains("messagePosition=1")); assertTrue(result.contains("messagePosition=1"));

View File

@@ -2,6 +2,7 @@ package de.gecheckt.asv.domain.model;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
import java.util.List;
/** /**
* Unit tests for the Segment class. * Unit tests for the Segment class.
@@ -21,7 +22,7 @@ class SegmentTest {
@Test @Test
void constructorWithNamePositionAndFieldsShouldCreateSegment() { void constructorWithNamePositionAndFieldsShouldCreateSegment() {
Field field = new Field(1, "value"); Field field = new Field(1, "value");
Segment segment = new Segment("TEST", 1, java.util.Arrays.asList(field)); Segment segment = new Segment("TEST", 1, List.of(field));
assertEquals("TEST", segment.segmentName()); assertEquals("TEST", segment.segmentName());
assertEquals(1, segment.segmentPosition()); assertEquals(1, segment.segmentPosition());
@@ -53,7 +54,7 @@ class SegmentTest {
@Test @Test
void getFieldsShouldReturnUnmodifiableList() { void getFieldsShouldReturnUnmodifiableList() {
Field field = new Field(1, "value"); Field field = new Field(1, "value");
Segment segment = new Segment("TEST", 1, java.util.Arrays.asList(field)); Segment segment = new Segment("TEST", 1, List.of(field));
assertThrows(UnsupportedOperationException.class, () -> { assertThrows(UnsupportedOperationException.class, () -> {
segment.getFields().add(field); segment.getFields().add(field);
@@ -70,7 +71,7 @@ class SegmentTest {
void hasFieldAtShouldWorkCorrectly() { void hasFieldAtShouldWorkCorrectly() {
Field field1 = new Field(1, "value1"); Field field1 = new Field(1, "value1");
Field field2 = new Field(3, "value3"); Field field2 = new Field(3, "value3");
Segment segment = new Segment("TEST", 1, java.util.Arrays.asList(field1, field2)); Segment segment = new Segment("TEST", 1, List.of(field1, field2));
assertTrue(segment.hasFieldAt(1)); assertTrue(segment.hasFieldAt(1));
assertFalse(segment.hasFieldAt(2)); assertFalse(segment.hasFieldAt(2));
@@ -82,7 +83,7 @@ class SegmentTest {
void getFieldCountShouldReturnCorrectCount() { void getFieldCountShouldReturnCorrectCount() {
Field field1 = new Field(1, "value1"); Field field1 = new Field(1, "value1");
Field field2 = new Field(2, "value2"); Field field2 = new Field(2, "value2");
Segment segment = new Segment("TEST", 1, java.util.Arrays.asList(field1, field2)); Segment segment = new Segment("TEST", 1, List.of(field1, field2));
assertEquals(2, segment.getFieldCount()); assertEquals(2, segment.getFieldCount());
} }
@@ -91,7 +92,7 @@ class SegmentTest {
void getFieldShouldReturnCorrectField() { void getFieldShouldReturnCorrectField() {
Field field1 = new Field(1, "value1"); Field field1 = new Field(1, "value1");
Field field2 = new Field(2, "value2"); Field field2 = new Field(2, "value2");
Segment segment = new Segment("TEST", 1, java.util.Arrays.asList(field1, field2)); Segment segment = new Segment("TEST", 1, List.of(field1, field2));
assertTrue(segment.getField(1).isPresent()); assertTrue(segment.getField(1).isPresent());
assertEquals(field1, segment.getField(1).get()); assertEquals(field1, segment.getField(1).get());
@@ -103,9 +104,9 @@ class SegmentTest {
@Test @Test
void equalsAndHashCodeShouldWorkCorrectly() { void equalsAndHashCodeShouldWorkCorrectly() {
Field field = new Field(1, "value"); Field field = new Field(1, "value");
Segment segment1 = new Segment("TEST", 1, java.util.Arrays.asList(field)); Segment segment1 = new Segment("TEST", 1, List.of(field));
Segment segment2 = new Segment("TEST", 1, java.util.Arrays.asList(field)); Segment segment2 = new Segment("TEST", 1, List.of(field));
Segment segment3 = new Segment("OTHER", 1, java.util.Arrays.asList(field)); Segment segment3 = new Segment("OTHER", 1, List.of(field));
assertEquals(segment1, segment2); assertEquals(segment1, segment2);
assertNotEquals(segment1, segment3); assertNotEquals(segment1, segment3);
@@ -115,7 +116,7 @@ class SegmentTest {
@Test @Test
void toStringShouldReturnValidString() { void toStringShouldReturnValidString() {
Field field = new Field(1, "value"); Field field = new Field(1, "value");
Segment segment = new Segment("TEST", 1, java.util.Arrays.asList(field)); Segment segment = new Segment("TEST", 1, List.of(field));
String result = segment.toString(); String result = segment.toString();
assertTrue(result.contains("segmentName=TEST")); assertTrue(result.contains("segmentName=TEST"));

View File

@@ -6,13 +6,12 @@ import de.gecheckt.asv.domain.model.InputFile;
import de.gecheckt.asv.domain.model.Message; import de.gecheckt.asv.domain.model.Message;
import de.gecheckt.asv.domain.model.Segment; import de.gecheckt.asv.domain.model.Segment;
import de.gecheckt.asv.domain.model.Field; import de.gecheckt.asv.domain.model.Field;
import java.io.IOException;
import java.util.List; import java.util.List;
class DefaultInputFileParserTest { class DefaultInputFileParserTest {
@Test @Test
void testParseSimpleFile() throws IOException { void testParseSimpleFile() throws InputFileParseException {
// Given // Given
SegmentLineTokenizer tokenizer = new DefaultSegmentLineTokenizer(); SegmentLineTokenizer tokenizer = new DefaultSegmentLineTokenizer();
InputFileParser parser = new DefaultInputFileParser(tokenizer); InputFileParser parser = new DefaultInputFileParser(tokenizer);
@@ -80,7 +79,7 @@ class DefaultInputFileParserTest {
} }
@Test @Test
void testParseWithEmptyLines() throws IOException { void testParseWithEmptyLines() throws InputFileParseException {
// Given // Given
SegmentLineTokenizer tokenizer = new DefaultSegmentLineTokenizer(); SegmentLineTokenizer tokenizer = new DefaultSegmentLineTokenizer();
InputFileParser parser = new DefaultInputFileParser(tokenizer); InputFileParser parser = new DefaultInputFileParser(tokenizer);
@@ -115,7 +114,7 @@ class DefaultInputFileParserTest {
} }
@Test @Test
void testParseWithNoFields() throws IOException { void testParseWithNoFields() throws InputFileParseException {
// Given // Given
SegmentLineTokenizer tokenizer = new DefaultSegmentLineTokenizer(); SegmentLineTokenizer tokenizer = new DefaultSegmentLineTokenizer();
InputFileParser parser = new DefaultInputFileParser(tokenizer); InputFileParser parser = new DefaultInputFileParser(tokenizer);
@@ -184,4 +183,89 @@ class DefaultInputFileParserTest {
parser.parse(fileName, null); parser.parse(fileName, null);
}); });
} }
@Test
void testParseInvalidContent() {
// Given
SegmentLineTokenizer tokenizer = new DefaultSegmentLineTokenizer();
InputFileParser parser = new DefaultInputFileParser(tokenizer);
String fileName = "test.asv";
String fileContent = "HDR+20260325+12345\n" +
"DAT+field1+field2+field3\n" +
"TRL"; // Missing field that might cause issues in downstream processing
// When / Then
// This should not throw an exception as our simple parser handles this case
assertDoesNotThrow(() -> {
parser.parse(fileName, fileContent);
});
}
@Test
void testParseWithWindowsLineEndings() throws InputFileParseException {
// Given
SegmentLineTokenizer tokenizer = new DefaultSegmentLineTokenizer();
InputFileParser parser = new DefaultInputFileParser(tokenizer);
String fileName = "test-windows.asv";
String fileContent = "HDR+20260325+12345\r\n" +
"DAT+field1+field2+field3\r\n" +
"TRL+5";
// When
InputFile inputFile = parser.parse(fileName, fileContent);
// Then
assertNotNull(inputFile);
assertEquals(fileName, inputFile.sourceFileName());
assertEquals(1, inputFile.messages().size());
List<Message> messages = inputFile.messages();
assertEquals(1, messages.size());
Message message = messages.get(0);
assertEquals(1, message.messagePosition());
assertEquals(3, message.segments().size());
// Check HDR segment
Segment hdrSegment = message.segments().get(0);
assertEquals("HDR", hdrSegment.segmentName());
assertEquals(1, hdrSegment.segmentPosition());
assertEquals(2, hdrSegment.fields().size());
Field hdrField1 = hdrSegment.fields().get(0);
assertEquals(1, hdrField1.fieldPosition());
assertEquals("20260325", hdrField1.rawValue());
Field hdrField2 = hdrSegment.fields().get(1);
assertEquals(2, hdrField2.fieldPosition());
assertEquals("12345", hdrField2.rawValue());
// Check DAT segment
Segment datSegment = message.segments().get(1);
assertEquals("DAT", datSegment.segmentName());
assertEquals(2, datSegment.segmentPosition());
assertEquals(3, datSegment.fields().size());
Field datField1 = datSegment.fields().get(0);
assertEquals(1, datField1.fieldPosition());
assertEquals("field1", datField1.rawValue());
Field datField2 = datSegment.fields().get(1);
assertEquals(2, datField2.fieldPosition());
assertEquals("field2", datField2.rawValue());
Field datField3 = datSegment.fields().get(2);
assertEquals(3, datField3.fieldPosition());
assertEquals("field3", datField3.rawValue());
// Check TRL segment
Segment trlSegment = message.segments().get(2);
assertEquals("TRL", trlSegment.segmentName());
assertEquals(3, trlSegment.segmentPosition());
assertEquals(1, trlSegment.fields().size());
Field trlField1 = trlSegment.fields().get(0);
assertEquals(1, trlField1.fieldPosition());
assertEquals("5", trlField1.rawValue());
}
} }

View File

@@ -1,54 +0,0 @@
package de.gecheckt.asv.parser;
import de.gecheckt.asv.domain.model.InputFile;
import de.gecheckt.asv.domain.model.Message;
import de.gecheckt.asv.domain.model.Segment;
import de.gecheckt.asv.domain.model.Field;
import java.io.IOException;
/**
* Example usage of the parser.
*/
public class ParserExample {
public static void main(String[] args) {
try {
// Create the parser
SegmentLineTokenizer tokenizer = new DefaultSegmentLineTokenizer();
InputFileParser parser = new DefaultInputFileParser(tokenizer);
// Sample file content
String fileName = "sample.asv";
String fileContent = "HDR+20260325+12345\n" +
"DAT+John+Doe+30\n" +
"DAT+Jane+Smith+25\n" +
"TRL+2";
// Parse the file
InputFile inputFile = parser.parse(fileName, fileContent);
// Print the results
System.out.println("Parsed file: " + inputFile.sourceFileName());
System.out.println("Number of messages: " + inputFile.messages().size());
for (Message message : inputFile.messages()) {
System.out.println(" Message " + message.messagePosition() +
" has " + message.segments().size() + " segments:");
for (Segment segment : message.segments()) {
System.out.println(" Segment " + segment.segmentPosition() +
" (" + segment.segmentName() + ") has " +
segment.fields().size() + " fields:");
for (Field field : segment.fields()) {
System.out.println(" Field " + field.fieldPosition() +
": '" + field.rawValue() + "'");
}
}
}
} catch (IOException e) {
System.err.println("Error parsing file: " + e.getMessage());
e.printStackTrace();
}
}
}

View File

@@ -2,8 +2,8 @@ package de.gecheckt.asv.validation.field;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@@ -29,9 +29,9 @@ class DefaultFieldValidatorTest {
// Arrange // Arrange
Field field1 = new Field(1, "value1", "Field1"); Field field1 = new Field(1, "value1", "Field1");
Field field2 = new Field(2, "value2", "Field2"); Field field2 = new Field(2, "value2", "Field2");
Segment segment = new Segment("SEG1", 1, Arrays.asList(field1, field2)); Segment segment = new Segment("SEG1", 1, List.of(field1, field2));
Message message = new Message(1, Arrays.asList(segment)); Message message = new Message(1, List.of(segment));
InputFile inputFile = new InputFile("test.asv", Arrays.asList(message)); InputFile inputFile = new InputFile("test.asv", List.of(message));
// Act // Act
ValidationResult result = validator.validate(inputFile); ValidationResult result = validator.validate(inputFile);
@@ -47,9 +47,9 @@ class DefaultFieldValidatorTest {
void testValidate_withEmptyRawValue_returnsError() { void testValidate_withEmptyRawValue_returnsError() {
// Arrange // Arrange
Field field = new Field(1, "", "Field1"); Field field = new Field(1, "", "Field1");
Segment segment = new Segment("SEG1", 1, Arrays.asList(field)); Segment segment = new Segment("SEG1", 1, List.of(field));
Message message = new Message(1, Arrays.asList(segment)); Message message = new Message(1, List.of(segment));
InputFile inputFile = new InputFile("test.asv", Arrays.asList(message)); InputFile inputFile = new InputFile("test.asv", List.of(message));
// Act // Act
ValidationResult result = validator.validate(inputFile); ValidationResult result = validator.validate(inputFile);
@@ -74,9 +74,9 @@ class DefaultFieldValidatorTest {
void testValidate_withWhitespaceOnlyRawValue_returnsError() { void testValidate_withWhitespaceOnlyRawValue_returnsError() {
// Arrange // Arrange
Field field = new Field(1, " ", "Field1"); Field field = new Field(1, " ", "Field1");
Segment segment = new Segment("SEG1", 1, Arrays.asList(field)); Segment segment = new Segment("SEG1", 1, List.of(field));
Message message = new Message(1, Arrays.asList(segment)); Message message = new Message(1, List.of(segment));
InputFile inputFile = new InputFile("test.asv", Arrays.asList(message)); InputFile inputFile = new InputFile("test.asv", List.of(message));
// Act // Act
ValidationResult result = validator.validate(inputFile); ValidationResult result = validator.validate(inputFile);
@@ -97,30 +97,14 @@ class DefaultFieldValidatorTest {
assertEquals("Non-whitespace-only raw value required", error.getExpectedRule().orElse(null)); assertEquals("Non-whitespace-only raw value required", error.getExpectedRule().orElse(null));
} }
@Test
void testValidate_withZeroFieldPosition_returnsError() {
// Note: This test creates a field with an invalid position that would normally be rejected by the domain model.
// We're testing the validator's ability to handle such cases if they were to occur.
// In practice, the domain model prevents this, but we include the check for completeness.
// For this test, we'll simulate the scenario by directly creating the objects
// Since the domain model prevents zero/negative positions, we'll skip this test for now
// as it would require changing the domain model which is outside our scope.
}
@Test
void testValidate_withNegativeFieldPosition_returnsError() {
// Note: Similar to the zero position test, this would require bypassing the domain model restrictions.
// We'll skip this test for the same reasons.
}
@Test @Test
void testValidate_withEmptyFieldName_returnsError() { void testValidate_withEmptyFieldName_returnsError() {
// Arrange // Arrange
Field field = new Field(1, "value1", ""); Field field = new Field(1, "value1", "");
Segment segment = new Segment("SEG1", 1, Arrays.asList(field)); Segment segment = new Segment("SEG1", 1, List.of(field));
Message message = new Message(1, Arrays.asList(segment)); Message message = new Message(1, List.of(segment));
InputFile inputFile = new InputFile("test.asv", Arrays.asList(message)); InputFile inputFile = new InputFile("test.asv", List.of(message));
// Act // Act
ValidationResult result = validator.validate(inputFile); ValidationResult result = validator.validate(inputFile);
@@ -145,9 +129,9 @@ class DefaultFieldValidatorTest {
void testValidate_withWhitespaceOnlyFieldName_returnsError() { void testValidate_withWhitespaceOnlyFieldName_returnsError() {
// Arrange // Arrange
Field field = new Field(1, "value1", " "); Field field = new Field(1, "value1", " ");
Segment segment = new Segment("SEG1", 1, Arrays.asList(field)); Segment segment = new Segment("SEG1", 1, List.of(field));
Message message = new Message(1, Arrays.asList(segment)); Message message = new Message(1, List.of(segment));
InputFile inputFile = new InputFile("test.asv", Arrays.asList(message)); InputFile inputFile = new InputFile("test.asv", List.of(message));
// Act // Act
ValidationResult result = validator.validate(inputFile); ValidationResult result = validator.validate(inputFile);
@@ -173,9 +157,9 @@ class DefaultFieldValidatorTest {
// Arrange // Arrange
Field field1 = new Field(1, "value1", "Field1"); Field field1 = new Field(1, "value1", "Field1");
Field field3 = new Field(3, "value3", "Field3"); // Missing field at position 2 Field field3 = new Field(3, "value3", "Field3"); // Missing field at position 2
Segment segment = new Segment("SEG1", 1, Arrays.asList(field1, field3)); Segment segment = new Segment("SEG1", 1, List.of(field1, field3));
Message message = new Message(1, Arrays.asList(segment)); Message message = new Message(1, List.of(segment));
InputFile inputFile = new InputFile("test.asv", Arrays.asList(message)); InputFile inputFile = new InputFile("test.asv", List.of(message));
// Act // Act
ValidationResult result = validator.validate(inputFile); ValidationResult result = validator.validate(inputFile);
@@ -202,9 +186,9 @@ class DefaultFieldValidatorTest {
// Arrange // Arrange
Field field1 = new Field(1, "", "Field1"); // Empty value Field field1 = new Field(1, "", "Field1"); // Empty value
Field field2 = new Field(2, " ", " "); // Whitespace only value and name Field field2 = new Field(2, " ", " "); // Whitespace only value and name
Segment segment = new Segment("SEG1", 1, Arrays.asList(field1, field2)); Segment segment = new Segment("SEG1", 1, List.of(field1, field2));
Message message = new Message(1, Arrays.asList(segment)); Message message = new Message(1, List.of(segment));
InputFile inputFile = new InputFile("test.asv", Arrays.asList(message)); InputFile inputFile = new InputFile("test.asv", List.of(message));
// Act // Act
ValidationResult result = validator.validate(inputFile); ValidationResult result = validator.validate(inputFile);
@@ -235,8 +219,8 @@ class DefaultFieldValidatorTest {
void testValidate_withNoFields_returnsNoErrors() { void testValidate_withNoFields_returnsNoErrors() {
// Arrange // Arrange
Segment segment = new Segment("SEG1", 1, Collections.emptyList()); Segment segment = new Segment("SEG1", 1, Collections.emptyList());
Message message = new Message(1, Arrays.asList(segment)); Message message = new Message(1, List.of(segment));
InputFile inputFile = new InputFile("test.asv", Arrays.asList(message)); InputFile inputFile = new InputFile("test.asv", List.of(message));
// Act // Act
ValidationResult result = validator.validate(inputFile); ValidationResult result = validator.validate(inputFile);

View File

@@ -2,6 +2,7 @@ package de.gecheckt.asv.validation.model;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
import java.util.List;
class ValidationResultTest { class ValidationResultTest {
@@ -12,7 +13,7 @@ class ValidationResultTest {
"TEST001", "Test error", ValidationSeverity.ERROR, "TEST001", "Test error", ValidationSeverity.ERROR,
"SEGMENT", 1, "FIELD", 1, "actual", "expected" "SEGMENT", 1, "FIELD", 1, "actual", "expected"
); );
ValidationResult result = new ValidationResult(java.util.Arrays.asList(error)); ValidationResult result = new ValidationResult(List.of(error));
// When & Then // When & Then
assertTrue(result.hasErrors()); assertTrue(result.hasErrors());
@@ -27,33 +28,11 @@ class ValidationResultTest {
"TEST001", "Test error", ValidationSeverity.ERROR, "TEST001", "Test error", ValidationSeverity.ERROR,
"SEGMENT", 1, "FIELD", 1, "actual", "expected" "SEGMENT", 1, "FIELD", 1, "actual", "expected"
); );
ValidationResult result = new ValidationResult(java.util.Arrays.asList(error)); ValidationResult result = new ValidationResult(List.of(error));
// When & Then // When & Then
assertThrows(UnsupportedOperationException.class, () -> { assertThrows(UnsupportedOperationException.class, () -> {
result.getErrors().add(error); result.getErrors().add(error);
}); });
} }
@Test
void testValidationErrorCreationAndAccess() {
// Given
ValidationError error = new ValidationError(
"TEST001", "Test error", ValidationSeverity.ERROR,
"SEGMENT", 1, "FIELD", 2, "actualValue", "expectedRule"
);
// When & Then
assertEquals("TEST001", error.errorCode());
assertEquals("Test error", error.description());
assertEquals(ValidationSeverity.ERROR, error.severity());
assertEquals("SEGMENT", error.segmentName());
assertEquals(1, error.segmentPosition());
assertEquals("FIELD", error.fieldName());
assertEquals(2, error.fieldPosition());
assertTrue(error.getActualValue().isPresent());
assertEquals("actualValue", error.getActualValue().get());
assertTrue(error.getExpectedRule().isPresent());
assertEquals("expectedRule", error.getExpectedRule().get());
}
} }

View File

@@ -2,8 +2,8 @@ package de.gecheckt.asv.validation.structure;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@@ -50,7 +50,7 @@ class DefaultStructureValidatorTest {
@Test @Test
void validate_shouldReportErrorWhenMessageHasNoSegments() { void validate_shouldReportErrorWhenMessageHasNoSegments() {
Message message = new Message(1, Collections.emptyList()); Message message = new Message(1, Collections.emptyList());
InputFile inputFile = new InputFile("test.txt", Arrays.asList(message)); InputFile inputFile = new InputFile("test.txt", List.of(message));
ValidationResult result = validator.validate(inputFile); ValidationResult result = validator.validate(inputFile);
@@ -68,8 +68,8 @@ class DefaultStructureValidatorTest {
void validate_shouldReportErrorWhenSegmentHasDuplicatePositions() { void validate_shouldReportErrorWhenSegmentHasDuplicatePositions() {
Segment segment1 = new Segment("SEG1", 1); Segment segment1 = new Segment("SEG1", 1);
Segment segment2 = new Segment("SEG2", 1); // Duplicate position Segment segment2 = new Segment("SEG2", 1); // Duplicate position
Message message = new Message(1, Arrays.asList(segment1, segment2)); Message message = new Message(1, List.of(segment1, segment2));
InputFile inputFile = new InputFile("test.txt", Arrays.asList(message)); InputFile inputFile = new InputFile("test.txt", List.of(message));
ValidationResult result = validator.validate(inputFile); ValidationResult result = validator.validate(inputFile);
@@ -87,9 +87,9 @@ class DefaultStructureValidatorTest {
void validate_shouldReportErrorWhenFieldHasDuplicatePositions() { void validate_shouldReportErrorWhenFieldHasDuplicatePositions() {
Field field1 = new Field(1, "value1"); Field field1 = new Field(1, "value1");
Field field2 = new Field(1, "value2"); // Duplicate position Field field2 = new Field(1, "value2"); // Duplicate position
Segment segment = new Segment("SEG1", 1, Arrays.asList(field1, field2)); Segment segment = new Segment("SEG1", 1, List.of(field1, field2));
Message message = new Message(1, Arrays.asList(segment)); Message message = new Message(1, List.of(segment));
InputFile inputFile = new InputFile("test.txt", Arrays.asList(message)); InputFile inputFile = new InputFile("test.txt", List.of(message));
ValidationResult result = validator.validate(inputFile); ValidationResult result = validator.validate(inputFile);
@@ -108,9 +108,9 @@ class DefaultStructureValidatorTest {
void validate_shouldReturnNoErrorsForValidStructure() { void validate_shouldReturnNoErrorsForValidStructure() {
Field field1 = new Field(1, "value1"); Field field1 = new Field(1, "value1");
Field field2 = new Field(2, "value2"); Field field2 = new Field(2, "value2");
Segment segment = new Segment("SEG1", 1, Arrays.asList(field1, field2)); Segment segment = new Segment("SEG1", 1, List.of(field1, field2));
Message message = new Message(1, Arrays.asList(segment)); Message message = new Message(1, List.of(segment));
InputFile inputFile = new InputFile("test.txt", Arrays.asList(message)); InputFile inputFile = new InputFile("test.txt", List.of(message));
ValidationResult result = validator.validate(inputFile); ValidationResult result = validator.validate(inputFile);