Skip to content

Commit dc53626

Browse files
committed
Extend functionality
1 parent bf3cf91 commit dc53626

File tree

6 files changed

+105
-33
lines changed

6 files changed

+105
-33
lines changed

dsl/pom.xml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,6 @@
3535
<groupId>be.sddevelopment.validation</groupId>
3636
<artifactId>core</artifactId>
3737
</dependency>
38-
<dependency>
39-
<groupId>be.sddevelopment.commons</groupId>
40-
<artifactId>commons-kernel</artifactId>
41-
</dependency>
4238
<dependency>
4339
<groupId>be.sddevelopment.commons</groupId>
4440
<artifactId>commons</artifactId>

dsl/src/main/java/be/sddevelopment/validation/dsl/CsvFile.java

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
11
package be.sddevelopment.validation.dsl;
22

3+
import be.sddevelopment.commons.exceptions.ExceptionSuppressor;
4+
import com.opencsv.CSVParser;
5+
import com.opencsv.CSVParserBuilder;
6+
7+
import java.io.IOException;
38
import java.nio.file.Path;
49
import java.util.List;
510
import java.util.Vector;
6-
import java.util.stream.Collectors;
711
import java.util.stream.Stream;
812

9-
public record CsvFile (
10-
String fileIdentifier,
11-
Vector<String> headerFields,
12-
Vector<Vector<String>> lines
13+
public record CsvFile(
14+
String fileIdentifier,
15+
Vector<String> headerFields,
16+
Vector<Vector<String>> lines
1317
) {
1418
private static final String DEFAULT = ".*\\.csv";
1519

@@ -23,22 +27,34 @@ public Vector<String> line(int lineNumber) {
2327
return lines.get(lineNumber);
2428
}
2529

26-
public static CsvFile fromLines(List<String> lines) {
27-
if(lines.isEmpty()) {
30+
public static CsvFile fromLines(List<String> lines) throws IOException {
31+
if (lines.isEmpty()) {
2832
throw new IllegalArgumentException("No lines provided. A data file requires at least one line");
2933
}
3034

3135
var header = parseHeader(lines.getFirst());
32-
var dataLines = lines.stream().skip(1).map(CsvFile::parseLine).toList();
36+
37+
var dataLines = lines.stream().skip(1).map(ExceptionSuppressor.uncheck(CsvFile::parseLine)).toList();
3338
return new CsvFile(DEFAULT, header, new Vector<>(dataLines));
3439
}
3540

36-
private static Vector<String> parseHeader(String s) {
37-
return null;
41+
private static Vector<String> parseHeader(String lineToParse) throws IOException {
42+
List<String> parsedFields = Stream.of(createParser().parseLine(lineToParse))
43+
.map(String::trim)
44+
.toList();
45+
return new Vector<>(parsedFields);
3846
}
3947

40-
private static Vector<String> parseLine(String s) {
41-
return null;
48+
private static Vector<String> parseLine(String lineToParse) throws IOException {
49+
return new Vector<>(Stream.of(createParser().parseLine(lineToParse)).map(String::trim).toList());
50+
}
51+
52+
private static CSVParser createParser() {
53+
return new CSVParserBuilder()
54+
.withSeparator(',')
55+
.withEscapeChar('\\')
56+
.withQuoteChar('"')
57+
.build();
4258
}
4359

4460
public static CsvFile fromFile(Path dataFile) {

dsl/src/main/java/be/sddevelopment/validation/dsl/FileValidatorParser.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import java.nio.file.Files;
1010
import java.nio.file.Path;
1111
import java.util.List;
12+
import java.util.Map;
1213
import java.util.function.Function;
1314

1415
import static be.sddevelopment.commons.access.AccessProtectionUtils.utilityClassConstructor;
@@ -46,7 +47,16 @@ static boolean isRuleSpecification(String specificationLine) {
4647
return KNOWN_RULESPECS.stream().anyMatch(specificationLine::contains);
4748
}
4849

49-
static <T> Function<ModularValidatorBuilder<T>, ModularValidatorBuilder<T>> toRuleAdder(String line) {
50+
static Function<ModularValidatorBuilder<CsvFile>, ModularValidatorBuilder<CsvFile>> toRuleAdder(String line) {
51+
if(line.trim().startsWith("FieldExists")) {
52+
var field = line.substring(line.indexOf('(') + 1, line.indexOf(')'))
53+
.trim()
54+
.replace("'", "");
55+
return ruleset -> ruleset.must(
56+
file -> file.headerFields().contains(field),
57+
"Field '%s' must exist in the data file".formatted(field)
58+
);
59+
}
5060
return ruleset -> ruleset;
5161
}
5262
}

dsl/src/test/java/be/sddevelopment/validation/dsl/CsvFileTest.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import org.junit.jupiter.api.Nested;
88
import org.junit.jupiter.api.Test;
99

10+
import java.io.IOException;
1011
import java.util.List;
1112

1213
@DisplayName("Comma Separated Values File")
@@ -17,7 +18,7 @@ class CsvFileTest implements WithAssertions {
1718
class LineBasedParsing {
1819

1920
@Test
20-
void dataIsAccessibleAfterParsing() {
21+
void dataIsAccessibleAfterParsing() throws IOException {
2122
var dataWithHeader = """
2223
NAME,HEIGHT,SPECIES
2324
Luke Skywalker,172,Human
@@ -44,7 +45,7 @@ void parsingRequiresAtLeastAHeaderLine() {
4445
}
4546

4647
@Test
47-
void canHandleEmptyDataSets() {
48+
void canHandleEmptyDataSets() throws IOException {
4849
var headerOnly = List.of("NAME,HEIGHT,SPECIES");
4950

5051
var csvFile = CsvFile.fromLines(headerOnly);

dsl/src/test/java/be/sddevelopment/validation/dsl/FileValidatorParserTest.java

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
import be.sddevelopment.commons.testing.naming.ReplaceUnderscoredCamelCasing;
44
import be.sddevelopment.validation.core.ModularRuleset;
55
import be.sddevelopment.validation.core.Rationale;
6-
import com.opencsv.CSVParser;
7-
import com.opencsv.bean.util.OpencsvUtils;
86
import org.assertj.core.api.WithAssertions;
97
import org.junit.jupiter.api.DisplayName;
108
import org.junit.jupiter.api.DisplayNameGeneration;
@@ -16,12 +14,14 @@
1614
import java.io.IOException;
1715
import java.nio.file.Paths;
1816

17+
import static be.sddevelopment.validation.dsl.FileValidatorParser.toRuleAdder;
18+
1919
@DisplayName("Parsing of validation rules")
2020
@DisplayNameGeneration(ReplaceUnderscoredCamelCasing.class)
2121
class FileValidatorParserTest implements WithAssertions {
2222

2323
@Test
24-
void createsAValidatorBasedOnSpecifications() throws IOException, SpecificationParserException {
24+
void createsAValidatorBasedOnSpecifications() throws SpecificationParserException {
2525
var validationSpec = Paths.get("src/test/resources/parsing/star_wars/STARWARS_VALIDATOR.puml");
2626
var dataFile = Paths.get("src/test/resources/parsing/star_wars/STARWARS_INPUT_DATA.csv");
2727
assertThat(validationSpec).exists();
@@ -54,25 +54,53 @@ void recognizesSimpleRule(String ruleToParse) {
5454
}
5555

5656
@Test
57-
void canCheckFieldExistence() {
57+
void fieldExistenceCheckFailsIfHeaderIsNotPresent() throws IOException {
5858
var dataFile = CsvFile.fromLines(
5959
"""
60-
NAME,HEIGHT,SPECIES
61-
Luke Skywalker,172,Human
62-
C-3PO,167,Droid
63-
R2-D2,96,Droid
64-
Boba Fett,183, Human
65-
""".lines().toList()
60+
NAME,HEIGHT,SPECIES
61+
Luke Skywalker,172,Human
62+
C-3PO,167,Droid
63+
R2-D2,96,Droid
64+
Boba Fett,183, Human
65+
""".lines().toList()
6666
);
6767
var rule = "FieldExists('HOMEWORLD')";
68-
var ruleAdder = FileValidatorParser.<CsvFile>toRuleAdder(rule);
68+
var ruleAdder = toRuleAdder(rule);
69+
70+
var ruleset = ModularRuleset.aValid(CsvFile.class);
71+
ruleAdder.apply(ruleset);
72+
73+
var result = ruleset.iHaveSpoken().check(dataFile);
74+
75+
assertThat(result)
76+
.isNotNull()
77+
.matches(Rationale::isFailing, "fails because the field does not exist");
78+
assertThat(result.details().getFirst().rationale())
79+
.contains("Field 'HOMEWORLD' must exist in the data file");
80+
}
81+
82+
@Test
83+
void fieldExistenceCheckPassesIfHeaderIsPresent() throws IOException {
84+
var dataFile = CsvFile.fromLines(
85+
"""
86+
NAME,HEIGHT,SPECIES
87+
Luke Skywalker,172,Human
88+
C-3PO,167,Droid
89+
R2-D2,96,Droid
90+
Boba Fett,183, Human
91+
""".lines().toList()
92+
);
93+
var rule = "FieldExists('SPECIES')";
94+
var ruleAdder = toRuleAdder(rule);
6995

7096
var ruleset = ModularRuleset.aValid(CsvFile.class);
7197
ruleAdder.apply(ruleset);
7298

7399
var result = ruleset.iHaveSpoken().check(dataFile);
74100

75-
assertThat(result).isNotNull().matches(Rationale::isFailing, "fails because the field does not exist");
101+
assertThat(result).isNotNull().matches(Rationale::isPassing);
102+
assertThat(result.details().getFirst().rationale())
103+
.contains("Field 'SPECIES' must exist in the data file");
76104
}
77105
}
78106
}

pom.xml

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@
6060
<sonar.projectKey>sddevelopment_modular-validators</sonar.projectKey>
6161
<sonar.coverage.jacoco.xmlReportPaths>${jacoco.build.dir}/jacoco.xml</sonar.coverage.jacoco.xmlReportPaths>
6262

63-
<code.utils.version>1.0.0</code.utils.version>
63+
<code.utils.version>1.0.1-SNAPSHOT</code.utils.version>
6464
<rewrite.version>5.36.0</rewrite.version>
6565
</properties>
6666
<dependencyManagement>
@@ -92,7 +92,7 @@
9292
<groupId>be.sddevelopment.commons</groupId>
9393
<artifactId>commons-testing</artifactId>
9494
<scope>test</scope>
95-
<version>1.0.0-SNAPSHOT</version>
95+
<version>${code.utils.version}</version>
9696
</dependency>
9797
<dependency>
9898
<groupId>org.junit.jupiter</groupId>
@@ -357,4 +357,25 @@
357357
</plugin>
358358
</plugins>
359359
</reporting>
360+
361+
<repositories>
362+
<repository>
363+
<id>central</id>
364+
<url>https://repo1.maven.org/maven2</url>
365+
</repository>
366+
<repository>
367+
<id>github-utils</id>
368+
<url>https://maven.pkg.github.com/sddevelopment-be/coding-utils</url>
369+
<snapshots>
370+
<enabled>true</enabled>
371+
</snapshots>
372+
</repository>
373+
<repository>
374+
<id>github-validators</id>
375+
<url>https://maven.pkg.github.com/sddevelopment-be/modular-validators</url>
376+
<snapshots>
377+
<enabled>true</enabled>
378+
</snapshots>
379+
</repository>
380+
</repositories>
360381
</project>

0 commit comments

Comments
 (0)