-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refinement and implementation of DSL ruleset specifications
- Loading branch information
1 parent
1f1e1fb
commit 5531835
Showing
11 changed files
with
231 additions
and
59 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
29 changes: 29 additions & 0 deletions
29
dsl/src/main/java/be/sddevelopment/validation/dsl/CsvFile.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package be.sddevelopment.validation.dsl; | ||
|
||
import java.nio.file.Path; | ||
import java.util.Vector; | ||
import java.util.stream.Stream; | ||
|
||
public record CsvFile ( | ||
String fileIdentifier, | ||
Vector<String> headerFields, | ||
Vector<Vector<String>> lines | ||
) { | ||
public CsvFile { | ||
if (headerFields == null || lines == null) { | ||
throw new IllegalArgumentException("Header fields and lines must not be null"); | ||
} | ||
} | ||
|
||
public Vector<String> line(int lineNumber) { | ||
return lines.get(lineNumber); | ||
} | ||
|
||
public static CsvFile fromLines(Stream<String> lines) { | ||
return null; | ||
} | ||
|
||
public static CsvFile fromFile(Path dataFile) { | ||
return null; | ||
} | ||
} |
52 changes: 52 additions & 0 deletions
52
dsl/src/main/java/be/sddevelopment/validation/dsl/FileValidatorParser.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package be.sddevelopment.validation.dsl; | ||
|
||
import be.sddevelopment.commons.annotations.Utility; | ||
import be.sddevelopment.validation.core.ModularRuleset; | ||
import be.sddevelopment.validation.core.ModularRuleset.ModularValidatorBuilder; | ||
import org.apache.commons.lang3.StringUtils; | ||
|
||
import java.io.IOException; | ||
import java.nio.file.Files; | ||
import java.nio.file.Path; | ||
import java.util.List; | ||
import java.util.function.Function; | ||
|
||
import static be.sddevelopment.commons.access.AccessProtectionUtils.utilityClassConstructor; | ||
|
||
@Utility | ||
public final class FileValidatorParser { | ||
|
||
private FileValidatorParser() { | ||
utilityClassConstructor(); | ||
} | ||
|
||
public static ModularRuleset<CsvFile> fromSpecification(Path validationSpec) throws SpecificationParserException { | ||
try { | ||
var lines = Files.readAllLines(validationSpec); | ||
var ruleSet = ModularRuleset.aValid(CsvFile.class); | ||
lines.stream() | ||
.filter(StringUtils::isNotBlank) | ||
.filter(FileValidatorParser::isRuleSpecification) | ||
.map(FileValidatorParser::<CsvFile>toRuleAdder) | ||
.forEach(ruleAdder -> ruleAdder.apply(ruleSet)); | ||
return ruleSet.iHaveSpoken(); | ||
} catch (IOException e) { | ||
throw new SpecificationParserException("Error processing validation specification file", e); | ||
} | ||
} | ||
|
||
private static final List<String> KNOWN_RULESPECS = List.of( | ||
"RecordIdentifier", | ||
"FieldExists", | ||
"FieldPopulated", | ||
"RecordExists" | ||
); | ||
|
||
static boolean isRuleSpecification(String specificationLine) { | ||
return KNOWN_RULESPECS.stream().anyMatch(specificationLine::contains); | ||
} | ||
|
||
static <T> Function<ModularValidatorBuilder<T>, ModularValidatorBuilder<T>> toRuleAdder(String line) { | ||
return ruleset -> ruleset; | ||
} | ||
} |
18 changes: 18 additions & 0 deletions
18
dsl/src/main/java/be/sddevelopment/validation/dsl/SpecificationParserException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package be.sddevelopment.validation.dsl; | ||
|
||
/** | ||
* Exception thrown when an error occurs while parsing a validation specification. | ||
* To be used by the {@link FileValidatorParser} or related specification file to {@link be.sddevelopment.validation.core.ModularRuleset} parsers. | ||
* | ||
* @since 1.1.0 | ||
*/ | ||
public class SpecificationParserException extends Exception { | ||
|
||
public SpecificationParserException(String message) { | ||
super(message); | ||
} | ||
|
||
public SpecificationParserException(String message, Throwable cause) { | ||
super(message, cause); | ||
} | ||
} |
21 changes: 0 additions & 21 deletions
21
dsl/src/main/java/be/sddevelopment/validation/dsl/ValidatorParser.java
This file was deleted.
Oops, something went wrong.
2 changes: 1 addition & 1 deletion
2
dsl/src/main/java/be/sddevelopment/validation/dsl/package-info.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
34 changes: 34 additions & 0 deletions
34
dsl/src/test/java/be/sddevelopment/validation/dsl/CsvFileTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package be.sddevelopment.validation.dsl; | ||
|
||
import be.sddevelopment.commons.testing.naming.ReplaceUnderscoredCamelCasing; | ||
import org.assertj.core.api.InstanceOfAssertFactories; | ||
import org.assertj.core.api.WithAssertions; | ||
import org.junit.jupiter.api.DisplayName; | ||
import org.junit.jupiter.api.DisplayNameGeneration; | ||
import org.junit.jupiter.api.Test; | ||
|
||
import static org.assertj.core.api.InstanceOfAssertFactories.*; | ||
|
||
@DisplayName("Comma Separated Values File") | ||
@DisplayNameGeneration(ReplaceUnderscoredCamelCasing.class) | ||
class CsvFileTest implements WithAssertions { | ||
|
||
@Test | ||
void canBeCreatedFromLines() { | ||
var dataWithHeader = """ | ||
NAME,HEIGHT,SPECIES | ||
Luke Skywalker,172,Human | ||
C-3PO,167,Droid | ||
R2-D2,96,Droid | ||
Boba Fett,183, Human | ||
"""; | ||
|
||
var csvFile = CsvFile.fromLines(dataWithHeader.lines()); | ||
|
||
assertThat(csvFile).isNotNull() | ||
.extracting(CsvFile::headerFields) | ||
.asInstanceOf(LIST) | ||
.containsExactly("NAME", "HEIGHT", "SPECIES"); | ||
assertThat(csvFile.line(0)).containsExactly("Luke Skywalker", "172", "Human"); | ||
} | ||
} |
78 changes: 78 additions & 0 deletions
78
dsl/src/test/java/be/sddevelopment/validation/dsl/FileValidatorParserTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
package be.sddevelopment.validation.dsl; | ||
|
||
import be.sddevelopment.commons.testing.naming.ReplaceUnderscoredCamelCasing; | ||
import be.sddevelopment.validation.core.ModularRuleset; | ||
import be.sddevelopment.validation.core.Rationale; | ||
import com.opencsv.CSVParser; | ||
import com.opencsv.bean.util.OpencsvUtils; | ||
import org.assertj.core.api.WithAssertions; | ||
import org.junit.jupiter.api.DisplayName; | ||
import org.junit.jupiter.api.DisplayNameGeneration; | ||
import org.junit.jupiter.api.Nested; | ||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.params.ParameterizedTest; | ||
import org.junit.jupiter.params.provider.ValueSource; | ||
|
||
import java.io.IOException; | ||
import java.nio.file.Paths; | ||
|
||
@DisplayName("Parsing of validation rules") | ||
@DisplayNameGeneration(ReplaceUnderscoredCamelCasing.class) | ||
class FileValidatorParserTest implements WithAssertions { | ||
|
||
@Test | ||
void createsAValidatorBasedOnSpecifications() throws IOException, SpecificationParserException { | ||
var validationSpec = Paths.get("src/test/resources/parsing/star_wars/STARWARS_VALIDATOR.puml"); | ||
var dataFile = Paths.get("src/test/resources/parsing/star_wars/STARWARS_INPUT_DATA.csv"); | ||
assertThat(validationSpec).exists(); | ||
assertThat(validationSpec).isRegularFile(); | ||
|
||
var validator = FileValidatorParser.fromSpecification(validationSpec); | ||
assertThat(validator).isNotNull(); | ||
|
||
var result = validator.check(CsvFile.fromFile(dataFile)); | ||
|
||
assertThat(result).isNotNull() | ||
.matches(Rationale::isPassing); | ||
} | ||
|
||
@Nested | ||
class parsesSimplesRulesTest { | ||
|
||
@ParameterizedTest | ||
@ValueSource(strings = { | ||
"RecordIdentifier('NAME')", | ||
"FieldPopulated('SPECIES')", | ||
"FieldExists('HOMEWORLD')", | ||
"RecordExists('C-3PO')" | ||
}) | ||
void recognizesSimpleRule(String ruleToParse) { | ||
assertThat(ruleToParse).matches( | ||
FileValidatorParser::isRuleSpecification, | ||
"is recognized as a rule specification" | ||
); | ||
} | ||
|
||
@Test | ||
void canCheckFieldExistence() { | ||
var dataFile = CsvFile.fromLines( | ||
""" | ||
NAME,HEIGHT,SPECIES | ||
Luke Skywalker,172,Human | ||
C-3PO,167,Droid | ||
R2-D2,96,Droid | ||
Boba Fett,183, Human | ||
""".lines() | ||
); | ||
var rule = "FieldExists('HOMEWORLD')"; | ||
var ruleAdder = FileValidatorParser.<CsvFile>toRuleAdder(rule); | ||
|
||
var ruleset = ModularRuleset.aValid(CsvFile.class); | ||
ruleAdder.apply(ruleset); | ||
|
||
var result = ruleset.iHaveSpoken().check(dataFile); | ||
|
||
assertThat(result).isNotNull().matches(Rationale::isFailing, "fails because the field does not exist"); | ||
} | ||
} | ||
} |
36 changes: 0 additions & 36 deletions
36
dsl/src/test/java/be/sddevelopment/validation/dsl/ValidatorParserTest.java
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters