From 952c81190a02cc118b8a44f0b9b345a2fff3509e Mon Sep 17 00:00:00 2001 From: Erlend Klakegg Bergheim <126939+klakegg@users.noreply.github.com> Date: Tue, 12 Sep 2023 12:15:03 +0200 Subject: [PATCH] Removing properties and minor restructuring --- CHANGELOG.md | 2 +- .../vefa/validator/CheckerCacheLoader.java | 19 ++- .../vefa/validator/ValidationInstance.java | 41 ++++--- .../no/difi/vefa/validator/Validator.java | 38 +++--- .../difi/vefa/validator/ValidatorBuilder.java | 12 +- .../vefa/validator/ValidatorDefaults.java | 31 ----- .../difi/vefa/validator/ValidatorEngine.java | 26 ++-- .../vefa/validator/ValidatorInstance.java | 38 +++--- .../vefa/validator/api/ArtifactHolder.java | 69 ----------- .../no/difi/vefa/validator/api/Checker.java | 1 + .../vefa/validator/api/CheckerFactory.java | 1 + .../difi/vefa/validator/api/Properties.java | 22 ---- .../no/difi/vefa/validator/api/Source.java | 2 +- .../vefa/validator/api/SourceInstance.java | 2 + .../difi/vefa/validator/api/Validation.java | 1 + .../vefa/validator/build/task/BuildTask.java | 4 +- .../builder/ConfigurationBuilder.java | 1 + .../builder/ConfigurationsBuilder.java | 1 + .../checker/SchematronCheckerFactory.java | 20 ++-- .../checker/SchematronXsltChecker.java | 10 +- .../checker/SchematronXsltCheckerFactory.java | 16 +-- .../vefa/validator/checker/XsdChecker.java | 2 +- .../validator/checker/XsdCheckerFactory.java | 11 +- .../ValidatorTestConfigurationProvider.java | 1 + .../expectation/ValidatorTestExpectation.java | 48 ++++---- .../validator/expectation/XmlExpectation.java | 2 +- .../vefa/validator/model/ArtifactHolder.java | 70 +++++++++++ .../Detected.java} | 18 +-- .../validator/{api => model}/Document.java | 6 +- .../no/difi/vefa/validator/model/Prop.java | 49 ++++++++ .../no/difi/vefa/validator/model/Props.java | 55 +++++++++ .../vefa/validator/module/CacheModule.java | 28 ----- .../vefa/validator/module/CheckerModule.java | 15 ++- .../vefa/validator/module/DetectorModule.java | 15 +-- .../validator/module/PropertiesModule.java | 28 +---- .../vefa/validator/module/SaxonModule.java | 10 ++ .../validator/module/SchematronModule.java | 29 +---- .../vefa/validator/module/SourceModule.java | 7 +- .../validator/module/ValidatorModule.java | 3 +- .../properties/AbstractProperties.java | 27 ----- .../properties/CombinedProperties.java | 57 --------- .../properties/SimpleProperties.java | 55 --------- .../validator/properties/package-info.java | 4 - .../validator/service/CheckerService.java | 35 ++++++ .../DetectorService.java} | 13 +- .../validator/service/TestingService.java | 93 +++++++++++++++ .../source/AbstractSourceInstance.java | 10 +- .../validator/source/ClasspathSource.java | 5 +- .../source/ClasspathSourceInstance.java | 5 +- .../validator/source/DirectorySource.java | 5 +- .../source/DirectorySourceInstance.java | 6 +- .../validator/source/RepositorySource.java | 5 +- .../source/RepositorySourceInstance.java | 5 +- .../no/difi/vefa/validator/tester/Tester.java | 112 +++++++----------- .../validator/util/ClasspathURIResolver.java | 22 ---- .../vefa/validator/util/ContentLoader.java | 43 +++++++ .../util/HolderLSResolveResource.java | 13 +- .../difi/vefa/validator/util/XsltHelper.java | 28 +++++ .../{ZipArchiver.java => ZipArchive.java} | 2 +- src/main/xsd/vefa-validator.xsd | 2 - .../no/difi/vefa/validator/SimpleTest.java | 7 +- .../config/SimplePropertiesTest.java | 52 -------- .../declaration/EspdDeclarationTest.java | 6 +- .../declaration/SbdhDeclarationTest.java | 6 +- .../declaration/UblDeclarationTest.java | 12 +- .../declaration/UnCefactDeclarationTest.java | 6 +- .../{api => model}/DocumentTest.java | 3 +- .../DetectorServiceTest.java} | 12 +- .../validator/service/TestingServiceTest.java | 37 ++++++ .../validator/source/DirectorySourceTest.java | 4 +- .../source/RepositorySourceTest.java | 4 +- src/test/resources/rules/artifacts.xml | 1 - ...3960978491dff855ae35ec28b582de2405e2.asice | Bin 18035 -> 0 bytes 73 files changed, 707 insertions(+), 744 deletions(-) delete mode 100644 src/main/java/no/difi/vefa/validator/ValidatorDefaults.java delete mode 100644 src/main/java/no/difi/vefa/validator/api/ArtifactHolder.java delete mode 100644 src/main/java/no/difi/vefa/validator/api/Properties.java create mode 100644 src/main/java/no/difi/vefa/validator/model/ArtifactHolder.java rename src/main/java/no/difi/vefa/validator/{util/DeclarationIdentification.java => model/Detected.java} (86%) rename src/main/java/no/difi/vefa/validator/{api => model}/Document.java (96%) create mode 100644 src/main/java/no/difi/vefa/validator/model/Prop.java create mode 100644 src/main/java/no/difi/vefa/validator/model/Props.java delete mode 100644 src/main/java/no/difi/vefa/validator/module/CacheModule.java delete mode 100644 src/main/java/no/difi/vefa/validator/properties/AbstractProperties.java delete mode 100644 src/main/java/no/difi/vefa/validator/properties/CombinedProperties.java delete mode 100644 src/main/java/no/difi/vefa/validator/properties/SimpleProperties.java delete mode 100644 src/main/java/no/difi/vefa/validator/properties/package-info.java create mode 100644 src/main/java/no/difi/vefa/validator/service/CheckerService.java rename src/main/java/no/difi/vefa/validator/{util/DeclarationDetector.java => service/DetectorService.java} (75%) create mode 100644 src/main/java/no/difi/vefa/validator/service/TestingService.java rename src/{test => main}/java/no/difi/vefa/validator/source/ClasspathSource.java (65%) rename src/{test => main}/java/no/difi/vefa/validator/source/ClasspathSourceInstance.java (90%) delete mode 100644 src/main/java/no/difi/vefa/validator/util/ClasspathURIResolver.java create mode 100644 src/main/java/no/difi/vefa/validator/util/ContentLoader.java create mode 100644 src/main/java/no/difi/vefa/validator/util/XsltHelper.java rename src/main/java/no/difi/vefa/validator/util/{ZipArchiver.java => ZipArchive.java} (97%) delete mode 100644 src/test/java/no/difi/vefa/validator/config/SimplePropertiesTest.java rename src/test/java/no/difi/vefa/validator/{api => model}/DocumentTest.java (86%) rename src/test/java/no/difi/vefa/validator/{util/DeclarationDetectorTest.java => service/DetectorServiceTest.java} (76%) create mode 100644 src/test/java/no/difi/vefa/validator/service/TestingServiceTest.java delete mode 100644 src/test/resources/rules/ehf-stylesheet-1c573960978491dff855ae35ec28b582de2405e2.asice diff --git a/CHANGELOG.md b/CHANGELOG.md index 870c7409..dd6102da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,7 +36,7 @@ * Rewrite of Declaration. * Rewrite of Expectation. -* no.difi.vefa.validator.api.Document.getDeclaration() returns a string, not an object. +* no.difi.vefa.validator.model.Document.getDeclaration() returns a string, not an object. * Fixing methods in ValidatorBuilder returning void. * Adding support for Piwik in sample application. Not turned on by default. * Refactoring of validator-build. diff --git a/src/main/java/no/difi/vefa/validator/CheckerCacheLoader.java b/src/main/java/no/difi/vefa/validator/CheckerCacheLoader.java index cc72cb4e..e360b2e7 100644 --- a/src/main/java/no/difi/vefa/validator/CheckerCacheLoader.java +++ b/src/main/java/no/difi/vefa/validator/CheckerCacheLoader.java @@ -5,12 +5,11 @@ import com.google.inject.Singleton; import lombok.NonNull; import lombok.extern.slf4j.Slf4j; -import no.difi.vefa.validator.annotation.Type; import no.difi.vefa.validator.api.Checker; import no.difi.vefa.validator.api.CheckerFactory; import no.difi.vefa.validator.lang.ValidatorException; -import java.util.List; +import java.util.Map; /** * @author erlend @@ -19,26 +18,22 @@ @Singleton public class CheckerCacheLoader extends CacheLoader { - public static final int DEFAULT_SIZE = 250; - @Inject - private List factories; + private Map factories; @Inject private ValidatorEngine validatorEngine; @Override @NonNull - public Checker load(@NonNull String key) throws Exception { + public Checker load(@NonNull String key) throws ValidatorException { try { - for (CheckerFactory factory : factories) { - for (String extension : factory.getClass().getAnnotation(Type.class).value()) { - if (key.toLowerCase().endsWith(extension)) { - return factory.prepare(validatorEngine.getResource(key), key.split("#")[1]); - } + for (var entry : factories.entrySet()) { + if (key.toLowerCase().endsWith(entry.getKey())) { + return entry.getValue().prepare(validatorEngine.getResource(key), key.split("#")[1]); } } - } catch (Exception e) { + } catch (ValidatorException e) { throw new ValidatorException(String.format("Unable to load checker for '%s'.", key), e); } diff --git a/src/main/java/no/difi/vefa/validator/ValidationInstance.java b/src/main/java/no/difi/vefa/validator/ValidationInstance.java index 3c550f53..642e31d2 100644 --- a/src/main/java/no/difi/vefa/validator/ValidationInstance.java +++ b/src/main/java/no/difi/vefa/validator/ValidationInstance.java @@ -1,11 +1,16 @@ package no.difi.vefa.validator; import lombok.extern.slf4j.Slf4j; -import no.difi.vefa.validator.api.*; +import no.difi.vefa.validator.api.Expectation; +import no.difi.vefa.validator.api.FlagFilterer; +import no.difi.vefa.validator.api.Section; +import no.difi.vefa.validator.api.Validation; import no.difi.vefa.validator.lang.UnknownDocumentTypeException; import no.difi.vefa.validator.lang.ValidatorException; -import no.difi.vefa.validator.properties.CombinedProperties; -import no.difi.vefa.validator.util.DeclarationIdentification; +import no.difi.vefa.validator.model.Detected; +import no.difi.vefa.validator.model.Document; +import no.difi.vefa.validator.model.Prop; +import no.difi.vefa.validator.model.Props; import no.difi.xsd.vefa.validator._1.AssertionType; import no.difi.xsd.vefa.validator._1.FileType; import no.difi.xsd.vefa.validator._1.FlagType; @@ -24,7 +29,7 @@ class ValidationInstance implements Validation { private final ValidatorInstance validatorInstance; - private final Properties properties; + private final Props props; private Configuration configuration; @@ -45,8 +50,8 @@ class ValidationInstance implements Validation { private List children; - public static ValidationInstance of(ValidatorInstance validatorInstance, Document document, Properties properties) { - return new ValidationInstance(validatorInstance, document, properties); + public static ValidationInstance of(ValidatorInstance validatorInstance, Document document, Prop... props) { + return new ValidationInstance(validatorInstance, document, props); } /** @@ -54,11 +59,11 @@ public static ValidationInstance of(ValidatorInstance validatorInstance, Documen * * @param validatorInstance Instance of validator. * @param document Source to validate. - * @param properties Properties for validation + * @param props Properties for validation */ - private ValidationInstance(ValidatorInstance validatorInstance, Document document, Properties properties) { + private ValidationInstance(ValidatorInstance validatorInstance, Document document, Prop... props) { this.validatorInstance = validatorInstance; - this.properties = new CombinedProperties(properties, validatorInstance.getProperties()); + this.props = validatorInstance.getProps().update(props); this.report = new Report(); this.report.setUuid(UUID.randomUUID().toString()); @@ -97,16 +102,16 @@ private ValidationInstance(ValidatorInstance validatorInstance, Document documen } } - private DeclarationIdentification loadDocument(Document document) throws ValidatorException, IOException { + private Detected loadDocument(Document document) throws ValidatorException, IOException { // Use declaration implementations to detect declaration to use. - DeclarationIdentification declarationIdentifier = validatorInstance.detect(document); + Detected declarationIdentifier = validatorInstance.detect(document); - if (declarationIdentifier.equals(DeclarationIdentification.UNKNOWN)) + if (declarationIdentifier.equals(Detected.UNKNOWN)) throw new UnknownDocumentTypeException("Unable to detect type of content."); // Detect expectation Expectation expectation = null; - if (properties.getBoolean("feature.expectation")) { + if (props.getBool("feature.expectation", false)) { expectation = declarationIdentifier.expectations(document); if (expectation != null) @@ -130,7 +135,7 @@ private void loadConfiguration() throws UnknownDocumentTypeException { // Get configuration using declaration this.configuration = validatorInstance.getConfiguration(document.getDeclarations()); - if (!properties.getBoolean("feature.suppress_notloaded")) + if (!props.getBool("feature.suppress_notloaded", false)) for (String notLoaded : configuration.getNotLoaded()) section.add("SYSTEM-007", String.format( "Validation artifact '%s' not loaded.", notLoaded), FlagType.WARNING); @@ -173,11 +178,11 @@ private void validate() { /** * Handling nested validation. */ - private void nestedValidation(DeclarationIdentification declarationIdentification) throws ValidatorException { + private void nestedValidation(Detected detected) throws ValidatorException { if (report.getFlag().compareTo(FlagType.FATAL) < 0) { - if (declarationIdentification.hasChildren() && properties.getBoolean("feature.nesting")) { - for (Document child : declarationIdentification.getChildren()) { - addChildValidation(ValidationInstance.of(validatorInstance, child, null)); + if (detected.hasChildren() && props.getBool("feature.nesting", false)) { + for (Document child : detected.getChildren()) { + addChildValidation(ValidationInstance.of(validatorInstance, child)); } } } diff --git a/src/main/java/no/difi/vefa/validator/Validator.java b/src/main/java/no/difi/vefa/validator/Validator.java index 41bc7838..51ecfa8d 100644 --- a/src/main/java/no/difi/vefa/validator/Validator.java +++ b/src/main/java/no/difi/vefa/validator/Validator.java @@ -3,16 +3,15 @@ import com.google.inject.Inject; import com.google.inject.Singleton; import lombok.extern.slf4j.Slf4j; -import no.difi.vefa.validator.api.Document; -import no.difi.vefa.validator.api.Properties; import no.difi.vefa.validator.api.Validation; +import no.difi.vefa.validator.model.Document; +import no.difi.vefa.validator.model.Prop; import no.difi.xsd.vefa.validator._1.PackageType; import java.io.Closeable; import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.nio.file.Files; import java.nio.file.Path; import java.util.List; @@ -34,44 +33,45 @@ public class Validator implements Closeable { /** * Validate file. * - * @param file File to validate. + * @param file File to validate. + * @param props Optional properties. * @return Validation result. */ - public Validation validate(File file) throws IOException { - return validate(file.toPath()); + public Validation validate(File file, Prop... props) throws IOException { + return validate(Document.of(file), props); } /** * Validate file. * - * @param file File to validate. + * @param file File to validate. + * @param props Optional properties. * @return Validation result. */ - public Validation validate(Path file) throws IOException { - try (InputStream inputStream = Files.newInputStream(file)) { - return validate(inputStream); - } + public Validation validate(Path file, Prop... props) throws IOException { + return validate(Document.of(file), props); } /** * Validate content of stream. * * @param inputStream Stream containing content. + * @param props Optional properties. * @return Validation result. */ - public Validation validate(InputStream inputStream) throws IOException { - return validate(inputStream, null); + public Validation validate(InputStream inputStream, Prop... props) throws IOException { + return validate(Document.of(inputStream), props); } /** - * Validate content of stream. + * Validate document. * - * @param inputStream Stream containing content. - * @param properties Properties used for individual validation. + * @param document File to validate. + * @param props Optional properties. * @return Validation result. */ - public Validation validate(InputStream inputStream, Properties properties) throws IOException { - return ValidationInstance.of(this.validatorInstance, Document.of(inputStream), properties); + public Validation validate(Document document, Prop... props) { + return validatorInstance.validate(document, props); } /** @@ -80,7 +80,7 @@ public Validation validate(InputStream inputStream, Properties properties) throw * @return List of packages. */ public List getPackages() { - return this.validatorInstance.getPackages(); + return validatorInstance.getPackages(); } @Override diff --git a/src/main/java/no/difi/vefa/validator/ValidatorBuilder.java b/src/main/java/no/difi/vefa/validator/ValidatorBuilder.java index d65a0791..f3fe8971 100644 --- a/src/main/java/no/difi/vefa/validator/ValidatorBuilder.java +++ b/src/main/java/no/difi/vefa/validator/ValidatorBuilder.java @@ -3,8 +3,8 @@ import com.google.inject.Guice; import com.google.inject.Module; import com.google.inject.util.Modules; -import no.difi.vefa.validator.api.Properties; import no.difi.vefa.validator.api.Source; +import no.difi.vefa.validator.model.Prop; import no.difi.vefa.validator.module.PropertiesModule; import no.difi.vefa.validator.module.SourceModule; import no.difi.vefa.validator.module.ValidatorModule; @@ -19,7 +19,7 @@ public class ValidatorBuilder { private Source source; - private Properties properties; + private Prop[] props; /** * Initiate creation of a new validator. Loads default plugins. @@ -40,11 +40,11 @@ private ValidatorBuilder() { /** * Defines configuration to use for validator. * - * @param properties Configuration + * @param props Configuration * @return Builder object */ - public ValidatorBuilder setProperties(Properties properties) { - this.properties = properties; + public ValidatorBuilder setProperties(Prop... props) { + this.props = props; return this; } @@ -66,7 +66,7 @@ public ValidatorBuilder setSource(Source source) { */ public Validator build() { List modules = new ArrayList<>(); - modules.add(new PropertiesModule(properties)); + modules.add(PropertiesModule.with(props)); modules.add(new SourceModule(source)); return Guice.createInjector(Modules.override(new ValidatorModule()).with(modules)).getInstance(Validator.class); diff --git a/src/main/java/no/difi/vefa/validator/ValidatorDefaults.java b/src/main/java/no/difi/vefa/validator/ValidatorDefaults.java deleted file mode 100644 index 9e140d6b..00000000 --- a/src/main/java/no/difi/vefa/validator/ValidatorDefaults.java +++ /dev/null @@ -1,31 +0,0 @@ -package no.difi.vefa.validator; - -import no.difi.vefa.validator.api.Properties; -import no.difi.vefa.validator.properties.SimpleProperties; - -import java.util.concurrent.TimeUnit; - -/** - * Class to hold defaults in validator. - */ -public class ValidatorDefaults { - - /** - * Default configuration. - */ - public static final Properties PROPERTIES = new SimpleProperties() - - // feature - .set("feature.expectation", false) - .set("feature.nesting", false) - .set("feature.suppress_notloaded", false) - .set("feature.infourl", false) - - // pools.checker - .set("pools.checker.size", CheckerCacheLoader.DEFAULT_SIZE) - .set("pools.checker.expire", TimeUnit.DAYS.toMinutes(1)) - - // finish - ; - -} diff --git a/src/main/java/no/difi/vefa/validator/ValidatorEngine.java b/src/main/java/no/difi/vefa/validator/ValidatorEngine.java index fa186ca4..d8d00b3f 100644 --- a/src/main/java/no/difi/vefa/validator/ValidatorEngine.java +++ b/src/main/java/no/difi/vefa/validator/ValidatorEngine.java @@ -3,19 +3,16 @@ import com.google.inject.Inject; import com.google.inject.Singleton; import jakarta.xml.bind.JAXBContext; -import jakarta.xml.bind.JAXBException; -import jakarta.xml.bind.Unmarshaller; import lombok.extern.slf4j.Slf4j; -import no.difi.vefa.validator.api.ArtifactHolder; import no.difi.vefa.validator.api.SourceInstance; import no.difi.vefa.validator.lang.ValidatorException; +import no.difi.vefa.validator.model.ArtifactHolder; +import no.difi.vefa.validator.model.Document; import no.difi.vefa.validator.util.JaxbUtils; import no.difi.xsd.vefa.validator._1.*; -import javax.xml.transform.stream.StreamSource; import java.io.Closeable; import java.io.IOException; -import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -55,8 +52,7 @@ class ValidatorEngine implements Closeable { * Loading a new validator engine loading configurations from current source. */ @Inject - public ValidatorEngine(SourceInstance sourceInstance, List configurations) - throws ValidatorException { + public ValidatorEngine(SourceInstance sourceInstance, List configurations) throws ValidatorException { // Load configurations from ValidatorBuilder. for (Configurations c : configurations) loadConfigurations("", c); @@ -65,9 +61,9 @@ public ValidatorEngine(SourceInstance sourceInstance, List confi for (Map.Entry entry : sourceInstance.getContent().entrySet()) { for (String filename : entry.getValue().getFilenames()) { if (filename.startsWith("config") && filename.endsWith(".xml")) { - try (InputStream inputStream = entry.getValue().getInputStream(filename)) { + try { content.put(entry.getKey(), entry.getValue()); - loadConfigurations(entry.getKey(), inputStream); + loadConfigurations(entry.getKey(), entry.getValue().getDocument(filename)); } catch (ValidatorException e) { throw new IOException(e.getMessage(), e); } @@ -87,16 +83,10 @@ public ValidatorEngine(SourceInstance sourceInstance, List confi * Load configuration from stream of config.xml. * * @param configurationSource Identifier for resource. - * @param inputStream Stream of config.xml. + * @param document Contents of config.xml. */ - private void loadConfigurations(String configurationSource, InputStream inputStream) throws ValidatorException { - try { - Unmarshaller unmarshaller = JAXB_CONTEXT.createUnmarshaller(); - loadConfigurations(configurationSource, - unmarshaller.unmarshal(new StreamSource(inputStream), Configurations.class).getValue()); - } catch (JAXBException e) { - throw new ValidatorException("Unable to read configurations.", e); - } + private void loadConfigurations(String configurationSource, Document document) throws ValidatorException { + loadConfigurations(configurationSource, document.unmarshal(JAXB_CONTEXT, Configurations.class)); } /** diff --git a/src/main/java/no/difi/vefa/validator/ValidatorInstance.java b/src/main/java/no/difi/vefa/validator/ValidatorInstance.java index ce165d9a..d1ee3cab 100644 --- a/src/main/java/no/difi/vefa/validator/ValidatorInstance.java +++ b/src/main/java/no/difi/vefa/validator/ValidatorInstance.java @@ -1,17 +1,19 @@ package no.difi.vefa.validator; -import com.google.common.cache.LoadingCache; import com.google.inject.Inject; import com.google.inject.Singleton; import lombok.extern.slf4j.Slf4j; import no.difi.vefa.validator.api.Checker; -import no.difi.vefa.validator.api.Document; -import no.difi.vefa.validator.api.Properties; import no.difi.vefa.validator.api.Section; +import no.difi.vefa.validator.api.Validation; import no.difi.vefa.validator.lang.UnknownDocumentTypeException; import no.difi.vefa.validator.lang.ValidatorException; -import no.difi.vefa.validator.util.DeclarationDetector; -import no.difi.vefa.validator.util.DeclarationIdentification; +import no.difi.vefa.validator.model.Detected; +import no.difi.vefa.validator.model.Document; +import no.difi.vefa.validator.model.Prop; +import no.difi.vefa.validator.model.Props; +import no.difi.vefa.validator.service.CheckerService; +import no.difi.vefa.validator.service.DetectorService; import no.difi.xsd.vefa.validator._1.ConfigurationType; import no.difi.xsd.vefa.validator._1.FileType; import no.difi.xsd.vefa.validator._1.FlagType; @@ -40,19 +42,23 @@ class ValidatorInstance implements Closeable { * Current validator configuration. */ @Inject - private Properties properties; + private Props props; /** * Declarations to use. */ @Inject - private DeclarationDetector declarationDetector; + private DetectorService declarationDetector; /** * Cache of checkers. */ @Inject - private LoadingCache checkerCache; + private CheckerService checkerService; + + public Validation validate(Document document, Prop... props) { + return ValidationInstance.of(this, document, props); + } /** * Normalized configurations indexed by document declarations. @@ -73,8 +79,8 @@ protected final List getPackages() { * * @return Current properties. */ - protected final Properties getProperties() { - return properties; + protected final Props getProps() { + return props; } /** @@ -108,7 +114,7 @@ protected Configuration getConfiguration(List declarations) throws Unkno "Configuration for '%s' not found.", declarations.get(0))); } - protected DeclarationIdentification detect(Document document) throws IOException { + protected Detected detect(Document document) throws IOException { return declarationDetector.detect(document); } @@ -125,7 +131,7 @@ protected Section check(FileType fileType, Document document, Configuration conf throws ValidatorException { Checker checker; try { - checker = checkerCache.get(fileType.getPath()); + checker = checkerService.get(fileType.getPath()); } catch (Exception e) { log.warn(e.getMessage(), e); throw new ValidatorException(String.format( @@ -135,19 +141,13 @@ protected Section check(FileType fileType, Document document, Configuration conf Section section = new Section(document.getExpectation()); section.setFlag(FlagType.OK); - if (properties.getBoolean("feature.infourl")) - section.setInfoUrl(fileType.getInfoUrl()); - checker.check(document, section); - - section.setInfoUrl(null); return section; } @Override public void close() throws IOException { - checkerCache.invalidateAll(); - checkerCache.cleanUp(); + checkerService.clear(); // This is last statement, allow to propagate. validatorEngine.close(); diff --git a/src/main/java/no/difi/vefa/validator/api/ArtifactHolder.java b/src/main/java/no/difi/vefa/validator/api/ArtifactHolder.java deleted file mode 100644 index c85bb2fb..00000000 --- a/src/main/java/no/difi/vefa/validator/api/ArtifactHolder.java +++ /dev/null @@ -1,69 +0,0 @@ -package no.difi.vefa.validator.api; - -import com.google.common.io.ByteStreams; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; -import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; - -/** - * @author erlend - */ -public interface ArtifactHolder { - - boolean exists(String path); - - byte[] get(String path); - - InputStream getInputStream(String path); - - Set getFilenames(); - - static ArtifactHolder of(InputStream inputStream) throws IOException { - Map content = new HashMap<>(); - - try (ZipInputStream zipInputStream = new ZipInputStream(inputStream)) { - ZipEntry zipEntry; - while ((zipEntry = zipInputStream.getNextEntry()) != null) { - content.put(zipEntry.getName(), ByteStreams.toByteArray(zipInputStream)); - zipInputStream.closeEntry(); - } - } - - return new ArtifactHolderImpl(content); - } - - class ArtifactHolderImpl implements ArtifactHolder { - - private final Map content; - - public ArtifactHolderImpl(Map content) { - this.content = content; - } - - @Override - public boolean exists(String path) { - return content.containsKey(path); - } - - @Override - public byte[] get(String path) { - return content.get(path); - } - - @Override - public InputStream getInputStream(String path) { - return new ByteArrayInputStream(content.get(path)); - } - - @Override - public Set getFilenames() { - return content.keySet(); - } - } -} diff --git a/src/main/java/no/difi/vefa/validator/api/Checker.java b/src/main/java/no/difi/vefa/validator/api/Checker.java index 63fd6285..47f21e34 100644 --- a/src/main/java/no/difi/vefa/validator/api/Checker.java +++ b/src/main/java/no/difi/vefa/validator/api/Checker.java @@ -1,6 +1,7 @@ package no.difi.vefa.validator.api; import no.difi.vefa.validator.lang.ValidatorException; +import no.difi.vefa.validator.model.Document; /** * Interface for classes performing validation of business documents. diff --git a/src/main/java/no/difi/vefa/validator/api/CheckerFactory.java b/src/main/java/no/difi/vefa/validator/api/CheckerFactory.java index 3a4040ea..cd027ff2 100644 --- a/src/main/java/no/difi/vefa/validator/api/CheckerFactory.java +++ b/src/main/java/no/difi/vefa/validator/api/CheckerFactory.java @@ -1,6 +1,7 @@ package no.difi.vefa.validator.api; import no.difi.vefa.validator.lang.ValidatorException; +import no.difi.vefa.validator.model.ArtifactHolder; /** * @author erlend diff --git a/src/main/java/no/difi/vefa/validator/api/Properties.java b/src/main/java/no/difi/vefa/validator/api/Properties.java deleted file mode 100644 index 607f3a32..00000000 --- a/src/main/java/no/difi/vefa/validator/api/Properties.java +++ /dev/null @@ -1,22 +0,0 @@ -package no.difi.vefa.validator.api; - -public interface Properties { - - boolean contains(String key); - - Object get(String key); - - Object get(String key, Object defaultValue); - - boolean getBoolean(String key); - - boolean getBoolean(String key, boolean defaultValue); - - int getInteger(String key); - - int getInteger(String key, int defaultValue); - - String getString(String key); - - String getString(String key, String defaultValue); -} diff --git a/src/main/java/no/difi/vefa/validator/api/Source.java b/src/main/java/no/difi/vefa/validator/api/Source.java index b420856a..c2899bef 100644 --- a/src/main/java/no/difi/vefa/validator/api/Source.java +++ b/src/main/java/no/difi/vefa/validator/api/Source.java @@ -13,6 +13,6 @@ public interface Source { * @throws ValidatorException * @return Instance containing validation artifacts. */ - SourceInstance createInstance(Properties properties) throws ValidatorException; + SourceInstance createInstance() throws ValidatorException; } diff --git a/src/main/java/no/difi/vefa/validator/api/SourceInstance.java b/src/main/java/no/difi/vefa/validator/api/SourceInstance.java index 49f0006e..59477d9b 100644 --- a/src/main/java/no/difi/vefa/validator/api/SourceInstance.java +++ b/src/main/java/no/difi/vefa/validator/api/SourceInstance.java @@ -1,5 +1,7 @@ package no.difi.vefa.validator.api; +import no.difi.vefa.validator.model.ArtifactHolder; + import java.util.Map; /** diff --git a/src/main/java/no/difi/vefa/validator/api/Validation.java b/src/main/java/no/difi/vefa/validator/api/Validation.java index f1f72e1a..43e0d5b9 100644 --- a/src/main/java/no/difi/vefa/validator/api/Validation.java +++ b/src/main/java/no/difi/vefa/validator/api/Validation.java @@ -1,5 +1,6 @@ package no.difi.vefa.validator.api; +import no.difi.vefa.validator.model.Document; import no.difi.xsd.vefa.validator._1.Report; import java.util.List; diff --git a/src/main/java/no/difi/vefa/validator/build/task/BuildTask.java b/src/main/java/no/difi/vefa/validator/build/task/BuildTask.java index 17dfd453..0ad1b4c5 100644 --- a/src/main/java/no/difi/vefa/validator/build/task/BuildTask.java +++ b/src/main/java/no/difi/vefa/validator/build/task/BuildTask.java @@ -13,7 +13,7 @@ import no.difi.vefa.validator.build.model.Build; import no.difi.vefa.validator.build.util.PreparerProvider; import no.difi.vefa.validator.util.JaxbUtils; -import no.difi.vefa.validator.util.ZipArchiver; +import no.difi.vefa.validator.util.ZipArchive; import no.difi.xsd.vefa.validator._1.BuildConfigurations; import no.difi.xsd.vefa.validator._1.ConfigurationType; import no.difi.xsd.vefa.validator._1.Configurations; @@ -116,7 +116,7 @@ public void build(final Build build) throws IOException, JAXBException { marshaller.marshal(configurations, outputStream); } - ZipArchiver.archive( + ZipArchive.archive( build.getTargetFolder().resolve(String.format("%s-%s.zip", build.getSetting("name"), build.getSetting("build"))), contentsPath); diff --git a/src/main/java/no/difi/vefa/validator/builder/ConfigurationBuilder.java b/src/main/java/no/difi/vefa/validator/builder/ConfigurationBuilder.java index a9a34c19..21afd854 100644 --- a/src/main/java/no/difi/vefa/validator/builder/ConfigurationBuilder.java +++ b/src/main/java/no/difi/vefa/validator/builder/ConfigurationBuilder.java @@ -4,6 +4,7 @@ import no.difi.xsd.vefa.validator._1.DeclarationType; import no.difi.xsd.vefa.validator._1.IdentifierType; +@Deprecated public class ConfigurationBuilder { private final ConfigurationType configuration = new ConfigurationType(); diff --git a/src/main/java/no/difi/vefa/validator/builder/ConfigurationsBuilder.java b/src/main/java/no/difi/vefa/validator/builder/ConfigurationsBuilder.java index 68549528..7a06c4f6 100644 --- a/src/main/java/no/difi/vefa/validator/builder/ConfigurationsBuilder.java +++ b/src/main/java/no/difi/vefa/validator/builder/ConfigurationsBuilder.java @@ -4,6 +4,7 @@ import no.difi.xsd.vefa.validator._1.Configurations; import no.difi.xsd.vefa.validator._1.PackageType; +@Deprecated public class ConfigurationsBuilder { private final Configurations configurations = new Configurations(); diff --git a/src/main/java/no/difi/vefa/validator/checker/SchematronCheckerFactory.java b/src/main/java/no/difi/vefa/validator/checker/SchematronCheckerFactory.java index c47199ce..033d87c8 100644 --- a/src/main/java/no/difi/vefa/validator/checker/SchematronCheckerFactory.java +++ b/src/main/java/no/difi/vefa/validator/checker/SchematronCheckerFactory.java @@ -4,17 +4,17 @@ import com.google.inject.Injector; import com.google.inject.Provider; import com.google.inject.name.Named; -import net.sf.saxon.s9api.*; +import net.sf.saxon.s9api.XdmDestination; +import net.sf.saxon.s9api.XsltCompiler; +import net.sf.saxon.s9api.XsltExecutable; +import net.sf.saxon.s9api.XsltTransformer; import no.difi.vefa.validator.annotation.Type; -import no.difi.vefa.validator.api.ArtifactHolder; import no.difi.vefa.validator.api.Checker; import no.difi.vefa.validator.api.CheckerFactory; import no.difi.vefa.validator.lang.ValidatorException; +import no.difi.vefa.validator.model.ArtifactHolder; import no.difi.vefa.validator.util.SaxonUtils; -import javax.xml.transform.stream.StreamSource; -import java.io.InputStream; - /** * Implementation performing step 3 (compilation) of Schematron. * @@ -28,27 +28,27 @@ public class SchematronCheckerFactory implements CheckerFactory { private Provider schematronCompiler; @Inject - private Processor processor; + private Provider compilerProvider; @Inject private Injector injector; @Override public Checker prepare(ArtifactHolder artifactHolder, String path) throws ValidatorException { - try (InputStream inputStream = artifactHolder.getInputStream(path)) { + try { XdmDestination destination = new XdmDestination(); XsltTransformer xsltTransformer = schematronCompiler.get().load(); xsltTransformer.setErrorListener(SaxonUtils.ERROR_LISTENER); xsltTransformer.setMessageHandler(SaxonUtils.MESSAGE_HANDLER); - xsltTransformer.setSource(new StreamSource(inputStream)); + xsltTransformer.setSource(artifactHolder.getStream(path)); xsltTransformer.setDestination(destination); xsltTransformer.transform(); - XsltCompiler xsltCompiler = processor.newXsltCompiler(); + XsltCompiler xsltCompiler = compilerProvider.get(); xsltCompiler.setErrorListener(SaxonUtils.ERROR_LISTENER); - Checker checker = new SchematronXsltChecker(processor, xsltCompiler.compile(destination.getXdmNode().asSource())); + Checker checker = new SchematronXsltChecker(xsltCompiler.compile(destination.getXdmNode().asSource())); injector.injectMembers(checker); return checker; } catch (Exception e) { diff --git a/src/main/java/no/difi/vefa/validator/checker/SchematronXsltChecker.java b/src/main/java/no/difi/vefa/validator/checker/SchematronXsltChecker.java index 680c1449..3455a06c 100644 --- a/src/main/java/no/difi/vefa/validator/checker/SchematronXsltChecker.java +++ b/src/main/java/no/difi/vefa/validator/checker/SchematronXsltChecker.java @@ -6,11 +6,10 @@ import jakarta.xml.bind.JAXBContext; import jakarta.xml.bind.Unmarshaller; import lombok.extern.slf4j.Slf4j; -import net.sf.saxon.s9api.Processor; import net.sf.saxon.s9api.XsltExecutable; import net.sf.saxon.s9api.XsltTransformer; import no.difi.vefa.validator.api.Checker; -import no.difi.vefa.validator.api.Document; +import no.difi.vefa.validator.model.Document; import no.difi.vefa.validator.api.Section; import no.difi.vefa.validator.lang.ValidatorException; import no.difi.vefa.validator.util.JaxbUtils; @@ -26,16 +25,13 @@ public class SchematronXsltChecker implements Checker { private static final JAXBContext JAXB_CONTEXT = JaxbUtils.context(SectionType.class); - private final Processor processor; - private final XsltExecutable xsltExecutable; @Inject @Named("schematron-svrl-parser") private Provider parser; - public SchematronXsltChecker(Processor processor, XsltExecutable xsltExecutable) { - this.processor = processor; + public SchematronXsltChecker(XsltExecutable xsltExecutable) { this.xsltExecutable = xsltExecutable; } @@ -55,7 +51,7 @@ public void check(Document document, Section section) throws ValidatorException parser.setErrorListener(SaxonUtils.ERROR_LISTENER); parser.setMessageHandler(SaxonUtils.MESSAGE_HANDLER); - parser.setDestination(processor.newSerializer(baos)); + parser.setDestination(xsltExecutable.getProcessor().newSerializer(baos)); schematron.transform(); diff --git a/src/main/java/no/difi/vefa/validator/checker/SchematronXsltCheckerFactory.java b/src/main/java/no/difi/vefa/validator/checker/SchematronXsltCheckerFactory.java index e6c110a8..7961017e 100644 --- a/src/main/java/no/difi/vefa/validator/checker/SchematronXsltCheckerFactory.java +++ b/src/main/java/no/difi/vefa/validator/checker/SchematronXsltCheckerFactory.java @@ -2,18 +2,15 @@ import com.google.inject.Inject; import com.google.inject.Injector; -import net.sf.saxon.s9api.Processor; +import com.google.inject.Provider; import net.sf.saxon.s9api.XsltCompiler; import no.difi.vefa.validator.annotation.Type; -import no.difi.vefa.validator.api.ArtifactHolder; import no.difi.vefa.validator.api.Checker; import no.difi.vefa.validator.api.CheckerFactory; import no.difi.vefa.validator.lang.ValidatorException; +import no.difi.vefa.validator.model.ArtifactHolder; import no.difi.vefa.validator.util.SaxonUtils; -import javax.xml.transform.stream.StreamSource; -import java.io.InputStream; - /** * @author erlend */ @@ -21,21 +18,20 @@ public class SchematronXsltCheckerFactory implements CheckerFactory { @Inject - private Processor processor; + private Provider compilerProvider; @Inject private Injector injector; @Override public Checker prepare(ArtifactHolder artifactHolder, String path) throws ValidatorException { - try (InputStream inputStream = artifactHolder.getInputStream(path)) { - XsltCompiler xsltCompiler = processor.newXsltCompiler(); + try { + XsltCompiler xsltCompiler = compilerProvider.get(); xsltCompiler.setErrorListener(SaxonUtils.ERROR_LISTENER); - Checker checker = new SchematronXsltChecker(processor, xsltCompiler.compile(new StreamSource(inputStream))); + Checker checker = new SchematronXsltChecker(xsltCompiler.compile(artifactHolder.getStream(path))); injector.injectMembers(checker); return checker; - } catch (Exception e) { throw new ValidatorException(e.getMessage(), e); } diff --git a/src/main/java/no/difi/vefa/validator/checker/XsdChecker.java b/src/main/java/no/difi/vefa/validator/checker/XsdChecker.java index 006ee89c..9c473c74 100644 --- a/src/main/java/no/difi/vefa/validator/checker/XsdChecker.java +++ b/src/main/java/no/difi/vefa/validator/checker/XsdChecker.java @@ -1,7 +1,7 @@ package no.difi.vefa.validator.checker; import no.difi.vefa.validator.api.Checker; -import no.difi.vefa.validator.api.Document; +import no.difi.vefa.validator.model.Document; import no.difi.vefa.validator.api.Section; import no.difi.xsd.vefa.validator._1.AssertionType; import no.difi.xsd.vefa.validator._1.FlagType; diff --git a/src/main/java/no/difi/vefa/validator/checker/XsdCheckerFactory.java b/src/main/java/no/difi/vefa/validator/checker/XsdCheckerFactory.java index b654df87..a76763bc 100644 --- a/src/main/java/no/difi/vefa/validator/checker/XsdCheckerFactory.java +++ b/src/main/java/no/difi/vefa/validator/checker/XsdCheckerFactory.java @@ -1,16 +1,14 @@ package no.difi.vefa.validator.checker; import no.difi.vefa.validator.annotation.Type; -import no.difi.vefa.validator.api.ArtifactHolder; import no.difi.vefa.validator.api.Checker; import no.difi.vefa.validator.api.CheckerFactory; import no.difi.vefa.validator.lang.ValidatorException; +import no.difi.vefa.validator.model.ArtifactHolder; import no.difi.vefa.validator.util.HolderLSResolveResource; import javax.xml.XMLConstants; -import javax.xml.transform.stream.StreamSource; import javax.xml.validation.SchemaFactory; -import java.io.InputStream; /** * @author erlend @@ -20,10 +18,11 @@ public class XsdCheckerFactory implements CheckerFactory { @Override public Checker prepare(ArtifactHolder artifactHolder, String path) throws ValidatorException { - try (InputStream inputStream = artifactHolder.getInputStream(path)) { + try { SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); - schemaFactory.setResourceResolver(new HolderLSResolveResource(artifactHolder, path)); - return new XsdChecker(schemaFactory.newSchema(new StreamSource(inputStream))); + schemaFactory.setResourceResolver(new HolderLSResolveResource(artifactHolder)); + + return new XsdChecker(schemaFactory.newSchema(artifactHolder.getStream(path))); } catch (Exception e) { throw new ValidatorException(e.getMessage(), e); } diff --git a/src/main/java/no/difi/vefa/validator/configuration/ValidatorTestConfigurationProvider.java b/src/main/java/no/difi/vefa/validator/configuration/ValidatorTestConfigurationProvider.java index 5a6e9d17..f7b467fb 100644 --- a/src/main/java/no/difi/vefa/validator/configuration/ValidatorTestConfigurationProvider.java +++ b/src/main/java/no/difi/vefa/validator/configuration/ValidatorTestConfigurationProvider.java @@ -5,6 +5,7 @@ import no.difi.vefa.validator.builder.ConfigurationsBuilder; import no.difi.xsd.vefa.validator._1.Configurations; +@Deprecated public class ValidatorTestConfigurationProvider implements ConfigurationProvider { @Override diff --git a/src/main/java/no/difi/vefa/validator/expectation/ValidatorTestExpectation.java b/src/main/java/no/difi/vefa/validator/expectation/ValidatorTestExpectation.java index 4ef9943a..9e8a7ae4 100644 --- a/src/main/java/no/difi/vefa/validator/expectation/ValidatorTestExpectation.java +++ b/src/main/java/no/difi/vefa/validator/expectation/ValidatorTestExpectation.java @@ -3,7 +3,7 @@ import jakarta.xml.bind.JAXBContext; import jakarta.xml.bind.JAXBException; import lombok.extern.slf4j.Slf4j; -import no.difi.vefa.validator.api.Document; +import no.difi.vefa.validator.model.Document; import no.difi.vefa.validator.util.JaxbUtils; import no.difi.xsd.vefa.validator._1.AssertElementType; import no.difi.xsd.vefa.validator._1.AssertType; @@ -18,28 +18,34 @@ public class ValidatorTestExpectation extends AbstractExpectation { public ValidatorTestExpectation(Document document) { try { - Test test = jaxbContext.createUnmarshaller().unmarshal( - new StreamSource(document.asInputStream()), Test.class).getValue(); - AssertType assertType = test.getAssert(); - - if (assertType != null) { - description = test.getId() == null ? - assertType.getDescription() : - String.format("%s) %s", test.getId(), assertType.getDescription()); - scopes.addAll(assertType.getScope()); - - for (AssertElementType a : assertType.getFatal()) - fatals.put(a.getValue(), a.getNumber() == null ? 1 : a.getNumber()); - for (AssertElementType a : assertType.getError()) - errors.put(a.getValue(), a.getNumber() == null ? 1 : a.getNumber()); - for (AssertElementType a : assertType.getWarning()) - warnings.put(a.getValue(), a.getNumber() == null ? 1 : a.getNumber()); - for (String s : assertType.getSuccess()) - successes.put(s, 1); - } - + load(jaxbContext.createUnmarshaller().unmarshal( + new StreamSource(document.asInputStream()), Test.class).getValue()); } catch (JAXBException e) { log.warn(e.getMessage(), e); } } + + public ValidatorTestExpectation(Test test) { + load(test); + } + + private void load(Test test) { + AssertType assertType = test.getAssert(); + + if (assertType != null) { + description = test.getId() == null ? + assertType.getDescription() : + String.format("%s) %s", test.getId(), assertType.getDescription()); + scopes.addAll(assertType.getScope()); + + for (AssertElementType a : assertType.getFatal()) + fatals.put(a.getValue(), a.getNumber() == null ? 1 : a.getNumber()); + for (AssertElementType a : assertType.getError()) + errors.put(a.getValue(), a.getNumber() == null ? 1 : a.getNumber()); + for (AssertElementType a : assertType.getWarning()) + warnings.put(a.getValue(), a.getNumber() == null ? 1 : a.getNumber()); + for (String s : assertType.getSuccess()) + successes.put(s, 1); + } + } } diff --git a/src/main/java/no/difi/vefa/validator/expectation/XmlExpectation.java b/src/main/java/no/difi/vefa/validator/expectation/XmlExpectation.java index eabbc536..c01a0018 100644 --- a/src/main/java/no/difi/vefa/validator/expectation/XmlExpectation.java +++ b/src/main/java/no/difi/vefa/validator/expectation/XmlExpectation.java @@ -1,7 +1,7 @@ package no.difi.vefa.validator.expectation; import lombok.extern.slf4j.Slf4j; -import no.difi.vefa.validator.api.Document; +import no.difi.vefa.validator.model.Document; import java.util.List; import java.util.Map; diff --git a/src/main/java/no/difi/vefa/validator/model/ArtifactHolder.java b/src/main/java/no/difi/vefa/validator/model/ArtifactHolder.java new file mode 100644 index 00000000..762cc273 --- /dev/null +++ b/src/main/java/no/difi/vefa/validator/model/ArtifactHolder.java @@ -0,0 +1,70 @@ +package no.difi.vefa.validator.model; + +import com.google.common.io.ByteStreams; + +import javax.xml.transform.stream.StreamSource; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +/** + * @author erlend + */ +public class ArtifactHolder { + + public static ArtifactHolder of(Map content) { + return new ArtifactHolder(content); + } + + public static ArtifactHolder of(InputStream inputStream) throws IOException { + Map content = new HashMap<>(); + + try (ZipInputStream zipInputStream = new ZipInputStream(inputStream)) { + ZipEntry zipEntry; + while ((zipEntry = zipInputStream.getNextEntry()) != null) { + content.put(zipEntry.getName(), ByteStreams.toByteArray(zipInputStream)); + zipInputStream.closeEntry(); + } + } + + return of(content); + } + + private final Map content; + + private ArtifactHolder(Map content) { + this.content = content; + } + + public byte[] get(String path) { + return content.get(path); + } + + public InputStream getInputStream(String path) throws IOException { + if (!content.containsKey(path)) + throw new IOException(String.format("Resource not found in holder: %s", path)); + + return new ByteArrayInputStream(content.get(path)); + } + + public StreamSource getStream(String path) throws IOException { + return new StreamSource(getInputStream(path), "holder:" + path); + } + + public Document getDocument(String path) throws IOException { + if (!content.containsKey(path)) + throw new IOException(String.format("Resource not found in holder: %s", path)); + + return Document.of(content.get(path)); + } + + public Set getFilenames() { + return content.keySet(); + } + +} diff --git a/src/main/java/no/difi/vefa/validator/util/DeclarationIdentification.java b/src/main/java/no/difi/vefa/validator/model/Detected.java similarity index 86% rename from src/main/java/no/difi/vefa/validator/util/DeclarationIdentification.java rename to src/main/java/no/difi/vefa/validator/model/Detected.java index 7d62a150..54629ad0 100644 --- a/src/main/java/no/difi/vefa/validator/util/DeclarationIdentification.java +++ b/src/main/java/no/difi/vefa/validator/model/Detected.java @@ -1,12 +1,12 @@ -package no.difi.vefa.validator.util; +package no.difi.vefa.validator.model; import jakarta.xml.bind.JAXBContext; import jakarta.xml.bind.JAXBException; -import no.difi.vefa.validator.api.Document; import no.difi.vefa.validator.api.Expectation; import no.difi.vefa.validator.expectation.ValidatorTestExpectation; import no.difi.vefa.validator.expectation.XmlExpectation; import no.difi.vefa.validator.lang.ValidatorException; +import no.difi.vefa.validator.util.JaxbUtils; import no.difi.xsd.vefa.validator._1_0.internal.IdentificationType; import no.difi.xsd.vefa.validator._1_0.internal.PropertyType; import org.w3c.dom.Node; @@ -21,9 +21,9 @@ import java.util.Map; import java.util.stream.Collectors; -public class DeclarationIdentification { +public class Detected { - public static final DeclarationIdentification UNKNOWN = new DeclarationIdentification(); + public static final Detected UNKNOWN = new Detected(); private static final JAXBContext JAXB = JaxbUtils.context(IdentificationType.class); @@ -37,20 +37,20 @@ public class DeclarationIdentification { private final Object converted; - public static DeclarationIdentification of(ByteArrayOutputStream baos) throws ValidatorException { + public static Detected of(ByteArrayOutputStream baos) throws ValidatorException { return of(new ByteArrayInputStream(baos.toByteArray())); } - public static DeclarationIdentification of(InputStream inputStream) throws ValidatorException { + public static Detected of(InputStream inputStream) throws ValidatorException { try { - return new DeclarationIdentification(JAXB.createUnmarshaller() + return new Detected(JAXB.createUnmarshaller() .unmarshal(new StreamSource(inputStream), IdentificationType.class).getValue()); } catch (JAXBException e) { throw new ValidatorException("Unable to parse detector result.", e); } } - private DeclarationIdentification() { + private Detected() { this.type = null; this.identifiers = List.of("unknown"); this.properties = Collections.emptyMap(); @@ -58,7 +58,7 @@ private DeclarationIdentification() { this.converted = null; } - private DeclarationIdentification(IdentificationType it) { + private Detected(IdentificationType it) { this.type = it.getType(); this.identifiers = it.getId(); this.properties = it.getProperty() == null ? Collections.emptyMap() : diff --git a/src/main/java/no/difi/vefa/validator/api/Document.java b/src/main/java/no/difi/vefa/validator/model/Document.java similarity index 96% rename from src/main/java/no/difi/vefa/validator/api/Document.java rename to src/main/java/no/difi/vefa/validator/model/Document.java index 32886f98..b4a6cc29 100644 --- a/src/main/java/no/difi/vefa/validator/api/Document.java +++ b/src/main/java/no/difi/vefa/validator/model/Document.java @@ -1,8 +1,9 @@ -package no.difi.vefa.validator.api; +package no.difi.vefa.validator.model; import com.google.common.io.ByteStreams; import jakarta.xml.bind.JAXBContext; import jakarta.xml.bind.JAXBException; +import no.difi.vefa.validator.api.Expectation; import no.difi.vefa.validator.lang.ValidatorException; import org.w3c.dom.Node; @@ -48,6 +49,9 @@ public static Document of(String content) { public static Document ofResource(String resource) throws IOException { try (var inputStream = Document.class.getResourceAsStream(resource)) { + if (inputStream == null) + throw new IOException(String.format("Resource '%s' not found.", resource)); + return of(inputStream); } } diff --git a/src/main/java/no/difi/vefa/validator/model/Prop.java b/src/main/java/no/difi/vefa/validator/model/Prop.java new file mode 100644 index 00000000..5600153c --- /dev/null +++ b/src/main/java/no/difi/vefa/validator/model/Prop.java @@ -0,0 +1,49 @@ +package no.difi.vefa.validator.model; + +public class Prop { + + public static Prop of(String key, String value) { + return new Prop(key, value); + } + + public static Prop of(String key, boolean value) { + return new Prop(key, Boolean.toString(value)); + } + + public static Prop of(String key, int value) { + return new Prop(key, Integer.toString(value)); + } + + public static Prop of(String key, long value) { + return new Prop(key, Long.toString(value)); + } + + private final String key; + + private final String value; + + private Prop(String key, String value) { + this.key = key; + this.value = value; + } + + public String getKey() { + return key; + } + + public String asString() { + return value; + } + + public int asInt() { + return Integer.parseInt(value); + } + + public long asLong() { + return Long.parseLong(value); + } + + public boolean asBool() { + return Boolean.parseBoolean(value); + } +} diff --git a/src/main/java/no/difi/vefa/validator/model/Props.java b/src/main/java/no/difi/vefa/validator/model/Props.java new file mode 100644 index 00000000..f139967b --- /dev/null +++ b/src/main/java/no/difi/vefa/validator/model/Props.java @@ -0,0 +1,55 @@ +package no.difi.vefa.validator.model; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Supplier; + +public class Props { + + public static Props init() { + return new Props(); + } + + private final Map map; + + private Props() { + map = Collections.emptyMap(); + } + + private Props(Map updated) { + map = updated; + } + + public String getString(String key, String defaultValue) { + return map.containsKey(key) ? map.get(key).asString() : defaultValue; + } + + public String getString(String key, Supplier defaultSupplier) { + return map.containsKey(key) ? map.get(key).asString() : defaultSupplier.get(); + } + + public int getInt(String key, int defaultValue) { + return map.containsKey(key) ? map.get(key).asInt() : defaultValue; + } + + public long getLong(String key, long defaultValue) { + return map.containsKey(key) ? map.get(key).asLong() : defaultValue; + } + + public boolean getBool(String key, boolean defaultValue) { + return map.containsKey(key) ? map.get(key).asBool() : defaultValue; + } + + public Props update(Prop... props) { + if (props == null || props.length == 0) + return this; + + Map updated = new HashMap<>(map); + + for (var prop : props) + updated.put(prop.getKey(), prop); + + return new Props(updated); + } +} diff --git a/src/main/java/no/difi/vefa/validator/module/CacheModule.java b/src/main/java/no/difi/vefa/validator/module/CacheModule.java deleted file mode 100644 index 6abf0b92..00000000 --- a/src/main/java/no/difi/vefa/validator/module/CacheModule.java +++ /dev/null @@ -1,28 +0,0 @@ -package no.difi.vefa.validator.module; - -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.LoadingCache; -import com.google.inject.AbstractModule; -import com.google.inject.Provides; -import com.google.inject.Singleton; -import no.difi.vefa.validator.CheckerCacheLoader; -import no.difi.vefa.validator.api.Checker; -import no.difi.vefa.validator.api.Properties; - -import java.util.concurrent.TimeUnit; - -/** - * @author erlend - */ -public class CacheModule extends AbstractModule { - - @Provides - @Singleton - public LoadingCache getCheckerCache(Properties properties, CheckerCacheLoader loader) { - return CacheBuilder.newBuilder() - .softValues() - .maximumSize(properties.getInteger("pools.checker.size")) - .expireAfterAccess(properties.getInteger("pools.checker.expire"), TimeUnit.MINUTES) - .build(loader); - } -} diff --git a/src/main/java/no/difi/vefa/validator/module/CheckerModule.java b/src/main/java/no/difi/vefa/validator/module/CheckerModule.java index 4e45ed30..743f68cd 100644 --- a/src/main/java/no/difi/vefa/validator/module/CheckerModule.java +++ b/src/main/java/no/difi/vefa/validator/module/CheckerModule.java @@ -4,12 +4,15 @@ import com.google.inject.Provides; import com.google.inject.Singleton; import com.google.inject.multibindings.Multibinder; +import no.difi.vefa.validator.annotation.Type; import no.difi.vefa.validator.api.CheckerFactory; import no.difi.vefa.validator.checker.SchematronCheckerFactory; import no.difi.vefa.validator.checker.SchematronXsltCheckerFactory; import no.difi.vefa.validator.checker.XsdCheckerFactory; -import java.util.List; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; import java.util.Set; public class CheckerModule extends AbstractModule { @@ -24,7 +27,13 @@ protected void configure() { @Provides @Singleton - public List getCheckerFactories(Set factories) { - return List.copyOf(factories); + public Map getMap(Set factories) { + Map result = new HashMap<>(); + + for (var factory : factories) + for (var type : factory.getClass().getAnnotation(Type.class).value()) + result.put(type, factory); + + return Collections.unmodifiableMap(result); } } diff --git a/src/main/java/no/difi/vefa/validator/module/DetectorModule.java b/src/main/java/no/difi/vefa/validator/module/DetectorModule.java index 4df75875..c3fc98eb 100644 --- a/src/main/java/no/difi/vefa/validator/module/DetectorModule.java +++ b/src/main/java/no/difi/vefa/validator/module/DetectorModule.java @@ -4,23 +4,16 @@ import com.google.inject.Provides; import com.google.inject.Singleton; import com.google.inject.name.Named; -import net.sf.saxon.s9api.Processor; -import net.sf.saxon.s9api.SaxonApiException; import net.sf.saxon.s9api.XsltExecutable; - -import javax.xml.transform.stream.StreamSource; -import java.io.IOException; +import no.difi.vefa.validator.lang.ValidatorException; +import no.difi.vefa.validator.util.XsltHelper; public class DetectorModule extends AbstractModule { @Provides @Singleton @Named("detector") - public XsltExecutable getDetectorXslt(Processor processor) throws IOException, SaxonApiException { - var compiler = processor.newXsltCompiler(); - - try (var inputStream = getClass().getResourceAsStream("/vefa-validator/xslt/detector.xslt")) { - return compiler.compile(new StreamSource(inputStream)); - } + public XsltExecutable getDetectorXslt(XsltHelper helper) throws ValidatorException { + return helper.fromResource("/vefa-validator/xslt/detector.xslt"); } } diff --git a/src/main/java/no/difi/vefa/validator/module/PropertiesModule.java b/src/main/java/no/difi/vefa/validator/module/PropertiesModule.java index 0b83daa5..5368ec4a 100644 --- a/src/main/java/no/difi/vefa/validator/module/PropertiesModule.java +++ b/src/main/java/no/difi/vefa/validator/module/PropertiesModule.java @@ -1,31 +1,15 @@ package no.difi.vefa.validator.module; -import com.google.inject.AbstractModule; -import com.google.inject.Provides; -import com.google.inject.Singleton; -import no.difi.vefa.validator.ValidatorDefaults; -import no.difi.vefa.validator.api.Properties; -import no.difi.vefa.validator.properties.CombinedProperties; +import com.google.inject.Module; +import no.difi.vefa.validator.model.Prop; +import no.difi.vefa.validator.model.Props; /** * @author erlend */ -public class PropertiesModule extends AbstractModule { +public interface PropertiesModule { - private final Properties properties; - - public PropertiesModule() { - this(null); - } - - public PropertiesModule(Properties properties) { - this.properties = properties; - } - - @Provides - @Singleton - public Properties getProperties() { - // Create config combined with default values. - return new CombinedProperties(properties, ValidatorDefaults.PROPERTIES); + static Module with(Prop... props) { + return binder -> binder.bind(Props.class).toInstance(Props.init().update(props)); } } diff --git a/src/main/java/no/difi/vefa/validator/module/SaxonModule.java b/src/main/java/no/difi/vefa/validator/module/SaxonModule.java index 181503b5..2e76147b 100644 --- a/src/main/java/no/difi/vefa/validator/module/SaxonModule.java +++ b/src/main/java/no/difi/vefa/validator/module/SaxonModule.java @@ -6,6 +6,8 @@ import net.sf.saxon.Configuration; import net.sf.saxon.lib.Feature; import net.sf.saxon.s9api.Processor; +import net.sf.saxon.s9api.XsltCompiler; +import no.difi.vefa.validator.util.ContentLoader; /** @@ -21,4 +23,12 @@ public Processor getProcessor() { return new Processor(configuration); } + + @Provides + public XsltCompiler getCompiler(Processor processor, ContentLoader resourceResolver) { + var compiler = processor.newXsltCompiler(); + compiler.setResourceResolver(resourceResolver); + + return compiler; + } } diff --git a/src/main/java/no/difi/vefa/validator/module/SchematronModule.java b/src/main/java/no/difi/vefa/validator/module/SchematronModule.java index 245be524..b4108485 100644 --- a/src/main/java/no/difi/vefa/validator/module/SchematronModule.java +++ b/src/main/java/no/difi/vefa/validator/module/SchematronModule.java @@ -5,15 +5,9 @@ import com.google.inject.Singleton; import com.google.inject.name.Named; import lombok.extern.slf4j.Slf4j; -import net.sf.saxon.s9api.Processor; -import net.sf.saxon.s9api.SaxonApiException; -import net.sf.saxon.s9api.XsltCompiler; import net.sf.saxon.s9api.XsltExecutable; -import no.difi.vefa.validator.util.ClasspathURIResolver; - -import javax.xml.transform.stream.StreamSource; -import java.io.IOException; -import java.io.InputStream; +import no.difi.vefa.validator.lang.ValidatorException; +import no.difi.vefa.validator.util.XsltHelper; /** * @author erlend @@ -24,25 +18,14 @@ public class SchematronModule extends AbstractModule { @Provides @Named("schematron-step3") @Singleton - public XsltExecutable getSchematronCompiler(Processor processor) { - try (InputStream inputStream = getClass().getResourceAsStream("/iso-schematron-xslt2/iso_svrl_for_xslt2.xsl")) { - XsltCompiler xsltCompiler = processor.newXsltCompiler(); - xsltCompiler.setURIResolver(new ClasspathURIResolver("/iso-schematron-xslt2")); - return xsltCompiler.compile(new StreamSource(inputStream)); - } catch (IOException | SaxonApiException e) { - throw new IllegalStateException("Unable to load parsing of Schematron."); - } + public XsltExecutable getSchematronCompiler(XsltHelper helper) throws ValidatorException { + return helper.fromResource("/iso-schematron-xslt2/iso_svrl_for_xslt2.xsl"); } @Provides @Named("schematron-svrl-parser") @Singleton - public XsltExecutable getSchematronSvrlParser(Processor processor) { - try (InputStream inputStream = getClass().getResourceAsStream("/vefa-validator/xslt/svrl-parser.xslt")) { - XsltCompiler xsltCompiler = processor.newXsltCompiler(); - return xsltCompiler.compile(new StreamSource(inputStream)); - } catch (IOException | SaxonApiException e) { - throw new IllegalStateException("Unable to load parsing of Schematron reports."); - } + public XsltExecutable getSchematronSvrlParser(XsltHelper helper) throws ValidatorException { + return helper.fromResource("/vefa-validator/xslt/svrl-parser.xslt"); } } diff --git a/src/main/java/no/difi/vefa/validator/module/SourceModule.java b/src/main/java/no/difi/vefa/validator/module/SourceModule.java index 20c0f384..aca8104a 100644 --- a/src/main/java/no/difi/vefa/validator/module/SourceModule.java +++ b/src/main/java/no/difi/vefa/validator/module/SourceModule.java @@ -3,10 +3,10 @@ import com.google.inject.AbstractModule; import com.google.inject.Provides; import com.google.inject.Singleton; -import no.difi.vefa.validator.api.Properties; import no.difi.vefa.validator.api.Source; import no.difi.vefa.validator.api.SourceInstance; import no.difi.vefa.validator.lang.ValidatorException; +import no.difi.vefa.validator.model.Props; import no.difi.vefa.validator.source.RepositorySource; /** @@ -26,9 +26,8 @@ public SourceModule(Source source) { @Provides @Singleton - public SourceInstance getSource(Properties properties) throws ValidatorException { + public SourceInstance getSource(Props props) throws ValidatorException { // Make sure to default to repository source if no source is set. - return (source != null ? source : RepositorySource.forProduction()) - .createInstance(properties); + return (source != null ? source : RepositorySource.forProduction()).createInstance(); } } diff --git a/src/main/java/no/difi/vefa/validator/module/ValidatorModule.java b/src/main/java/no/difi/vefa/validator/module/ValidatorModule.java index 88f0f6d4..976e919a 100644 --- a/src/main/java/no/difi/vefa/validator/module/ValidatorModule.java +++ b/src/main/java/no/difi/vefa/validator/module/ValidatorModule.java @@ -19,10 +19,9 @@ public class ValidatorModule extends AbstractModule { @Override protected void configure() { - install(new CacheModule()); install(new CheckerModule()); install(new DetectorModule()); - install(new PropertiesModule()); + install(PropertiesModule.with()); install(new SaxonModule()); install(new SourceModule()); install(new SchematronModule()); diff --git a/src/main/java/no/difi/vefa/validator/properties/AbstractProperties.java b/src/main/java/no/difi/vefa/validator/properties/AbstractProperties.java deleted file mode 100644 index 85f5012d..00000000 --- a/src/main/java/no/difi/vefa/validator/properties/AbstractProperties.java +++ /dev/null @@ -1,27 +0,0 @@ -package no.difi.vefa.validator.properties; - -import no.difi.vefa.validator.api.Properties; - -abstract class AbstractProperties implements Properties { - - @Override - public Object get(String key) { - return get(key, null); - } - - @Override - public boolean getBoolean(String key) { - return getBoolean(key, false); - } - - @Override - public int getInteger(String key) { - return getInteger(key, 0); - } - - @Override - public String getString(String key) { - return getString(key, null); - } - -} diff --git a/src/main/java/no/difi/vefa/validator/properties/CombinedProperties.java b/src/main/java/no/difi/vefa/validator/properties/CombinedProperties.java deleted file mode 100644 index 00d084b8..00000000 --- a/src/main/java/no/difi/vefa/validator/properties/CombinedProperties.java +++ /dev/null @@ -1,57 +0,0 @@ -package no.difi.vefa.validator.properties; - -import no.difi.vefa.validator.api.Properties; - -/** - * Implementation of Properties making it easy to access multiple instances of Properties. - */ -public class CombinedProperties extends AbstractProperties { - - private final Properties[] properties; - - /** - * Allow combination of configs, the most specific first. - * - * @param properties List containing instances of Properties to be combined. - */ - public CombinedProperties(Properties... properties) { - this.properties = properties; - } - - private Properties detect(String key) { - for (Properties properties : this.properties) - if (properties != null && properties.contains(key)) - return properties; - return null; - } - - @Override - public boolean contains(String key) { - Properties properties = detect(key); - return properties != null; - } - - @Override - public Object get(String key, Object defaultValue) { - Properties properties = detect(key); - return properties == null ? defaultValue : properties.get(key, defaultValue); - } - - @Override - public boolean getBoolean(String key, boolean defaultValue) { - Properties properties = detect(key); - return properties == null ? defaultValue : properties.getBoolean(key, defaultValue); - } - - @Override - public int getInteger(String key, int defaultValue) { - Properties properties = detect(key); - return properties == null ? defaultValue : properties.getInteger(key, defaultValue); - } - - @Override - public String getString(String key, String defaultValue) { - Properties properties = detect(key); - return properties == null ? defaultValue : properties.getString(key, defaultValue); - } -} diff --git a/src/main/java/no/difi/vefa/validator/properties/SimpleProperties.java b/src/main/java/no/difi/vefa/validator/properties/SimpleProperties.java deleted file mode 100644 index cf204387..00000000 --- a/src/main/java/no/difi/vefa/validator/properties/SimpleProperties.java +++ /dev/null @@ -1,55 +0,0 @@ -package no.difi.vefa.validator.properties; - -import lombok.extern.slf4j.Slf4j; - -import java.util.HashMap; -import java.util.Map; - -/** - * Simple implementation of Properties using a HashMap to store values. - */ -@Slf4j -public class SimpleProperties extends AbstractProperties { - - private Map values; - - public SimpleProperties() { - values = new HashMap<>(); - } - - public SimpleProperties set(String key, Object value) { - values.put(key, value); - return this; - } - - @Override - public boolean contains(String key) { - return values.containsKey(key); - } - - @Override - public Object get(String key, Object defaultValue) { - return values.containsKey(key) ? values.get(key) : defaultValue; - } - - @Override - public boolean getBoolean(String key, boolean defaultValue) { - return values.containsKey(key) ? Boolean.parseBoolean(String.valueOf(values.get(key))) : defaultValue; - } - - @Override - public int getInteger(String key, int defaultValue) { - try { - if (values.containsKey(key)) - return Integer.parseInt(String.valueOf(values.get(key))); - } catch (NumberFormatException e) { - log.error(String.format("Error while casting '%s' to integer for key '%s'.", values.get(key), key)); - } - return defaultValue; - } - - @Override - public String getString(String key, String defaultValue) { - return values.containsKey(key) ? String.valueOf(values.get(key)) : defaultValue; - } -} diff --git a/src/main/java/no/difi/vefa/validator/properties/package-info.java b/src/main/java/no/difi/vefa/validator/properties/package-info.java deleted file mode 100644 index 430681e1..00000000 --- a/src/main/java/no/difi/vefa/validator/properties/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * Implementations used for properties. - */ -package no.difi.vefa.validator.properties; \ No newline at end of file diff --git a/src/main/java/no/difi/vefa/validator/service/CheckerService.java b/src/main/java/no/difi/vefa/validator/service/CheckerService.java new file mode 100644 index 00000000..5d7ffba1 --- /dev/null +++ b/src/main/java/no/difi/vefa/validator/service/CheckerService.java @@ -0,0 +1,35 @@ +package no.difi.vefa.validator.service; + +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.LoadingCache; +import com.google.inject.Inject; +import com.google.inject.Singleton; +import no.difi.vefa.validator.CheckerCacheLoader; +import no.difi.vefa.validator.api.Checker; +import no.difi.vefa.validator.model.Props; + +import java.util.concurrent.TimeUnit; + +@Singleton +public class CheckerService { + + private final LoadingCache cache; + + @Inject + public CheckerService(Props props, CheckerCacheLoader loader) { + cache = CacheBuilder.newBuilder() + .softValues() + .maximumSize(props.getInt("pools.checker.size", 250)) + .expireAfterAccess(props.getLong("pools.checker.expire", TimeUnit.DAYS.toMinutes(1)), TimeUnit.MINUTES) + .build(loader); + } + + public Checker get(String key) throws Exception { + return cache.get(key); + } + + public void clear() { + cache.invalidateAll(); + cache.cleanUp(); + } +} diff --git a/src/main/java/no/difi/vefa/validator/util/DeclarationDetector.java b/src/main/java/no/difi/vefa/validator/service/DetectorService.java similarity index 75% rename from src/main/java/no/difi/vefa/validator/util/DeclarationDetector.java rename to src/main/java/no/difi/vefa/validator/service/DetectorService.java index b921610f..4f72740a 100644 --- a/src/main/java/no/difi/vefa/validator/util/DeclarationDetector.java +++ b/src/main/java/no/difi/vefa/validator/service/DetectorService.java @@ -1,4 +1,4 @@ -package no.difi.vefa.validator.util; +package no.difi.vefa.validator.service; import com.google.inject.Inject; import com.google.inject.Singleton; @@ -6,8 +6,9 @@ import lombok.extern.slf4j.Slf4j; import net.sf.saxon.s9api.SaxonApiException; import net.sf.saxon.s9api.XsltExecutable; -import no.difi.vefa.validator.api.Document; +import no.difi.vefa.validator.model.Document; import no.difi.vefa.validator.lang.ValidatorException; +import no.difi.vefa.validator.model.Detected; import javax.xml.transform.stream.StreamSource; import java.io.ByteArrayOutputStream; @@ -15,13 +16,13 @@ @Slf4j @Singleton -public class DeclarationDetector { +public class DetectorService { @Inject @Named("detector") private XsltExecutable detector; - public DeclarationIdentification detect(Document document) throws IOException { + public Detected detect(Document document) throws IOException { try { var baos = new ByteArrayOutputStream(); @@ -30,9 +31,9 @@ public DeclarationIdentification detect(Document document) throws IOException { transformer.setDestination(detector.getProcessor().newSerializer(baos)); transformer.transform(); - return DeclarationIdentification.of(baos); + return Detected.of(baos); } catch (SaxonApiException e) { - return DeclarationIdentification.UNKNOWN; + return Detected.UNKNOWN; } catch (ValidatorException e) { throw new IOException(e.getMessage(), e); } diff --git a/src/main/java/no/difi/vefa/validator/service/TestingService.java b/src/main/java/no/difi/vefa/validator/service/TestingService.java new file mode 100644 index 00000000..9a057dc1 --- /dev/null +++ b/src/main/java/no/difi/vefa/validator/service/TestingService.java @@ -0,0 +1,93 @@ +package no.difi.vefa.validator.service; + +import com.google.inject.Inject; +import com.google.inject.Singleton; +import jakarta.xml.bind.JAXBContext; +import no.difi.vefa.validator.Validator; +import no.difi.vefa.validator.model.Document; +import no.difi.vefa.validator.api.Expectation; +import no.difi.vefa.validator.api.Section; +import no.difi.vefa.validator.api.Validation; +import no.difi.vefa.validator.expectation.ValidatorTestExpectation; +import no.difi.vefa.validator.expectation.XmlExpectation; +import no.difi.vefa.validator.lang.ValidatorException; +import no.difi.vefa.validator.util.JaxbUtils; +import no.difi.xsd.vefa.validator._1.Test; +import no.difi.xsd.vefa.validator._1.TestSet; +import org.w3c.dom.Node; + +import java.io.IOException; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; + +@Singleton +public class TestingService { + + private static final JAXBContext JAXB = JaxbUtils.context(TestSet.class); + + @Inject + private Validator validator; + + @Inject + private DetectorService detectorService; + + public List verify(Path path) throws IOException, ValidatorException { + return verify(Document.of(path)); + } + + public List verify(Document document) throws IOException, ValidatorException { + var detected = detectorService.detect(document); + + if ("http://difi.no/xsd/vefa/validator/1.0".equals(detected.getProperties().get("xml.namespace"))) { + if ("testSet".equals(detected.getProperties().get("xml.element"))) { + return handleTestSet(document); + } else if ("test".equals(detected.getProperties().get("xml.element"))) { + return List.of(handleTest(document)); + } + } else { + return List.of(handleDocument(document)); + } + + throw new ValidatorException("Unable to use provided document as test."); + } + + private List handleTestSet(Document document) throws ValidatorException { + var validations = new ArrayList(); + + for (var test : document.unmarshal(JAXB, TestSet.class).getTest()) { + validations.add(handleTest(test)); + } + + return validations; + } + + private Validation handleTest(Document document) throws ValidatorException { + return handleTest(document.unmarshal(JAXB, Test.class)); + } + + private Validation handleTest(Test test) throws ValidatorException { + if (test.getAny() instanceof Node node) + return handleGeneric(Document.of(node), new ValidatorTestExpectation(test)); + + throw new ValidatorException("Unable to read example XML."); + } + + private Validation handleDocument(Document document) { + return handleGeneric(document, new XmlExpectation(document)); + } + + private Validation handleGeneric(Document document, Expectation expectation) { + var validation = validator.validate(document); + + for (var section : validation.getReport().getSection()) { + for (var assertion : section.getAssertion()) { + expectation.filterFlag(assertion); + } + + expectation.verify((Section) section); + } + + return validation; + } +} diff --git a/src/main/java/no/difi/vefa/validator/source/AbstractSourceInstance.java b/src/main/java/no/difi/vefa/validator/source/AbstractSourceInstance.java index 58807973..f2fdd01b 100644 --- a/src/main/java/no/difi/vefa/validator/source/AbstractSourceInstance.java +++ b/src/main/java/no/difi/vefa/validator/source/AbstractSourceInstance.java @@ -2,9 +2,9 @@ import jakarta.xml.bind.JAXBContext; import lombok.extern.slf4j.Slf4j; -import no.difi.vefa.validator.api.ArtifactHolder; -import no.difi.vefa.validator.api.Properties; import no.difi.vefa.validator.api.SourceInstance; +import no.difi.vefa.validator.model.ArtifactHolder; +import no.difi.vefa.validator.model.Props; import no.difi.vefa.validator.util.JaxbUtils; import no.difi.xsd.vefa.validator._1.Artifacts; @@ -21,14 +21,8 @@ public abstract class AbstractSourceInstance implements SourceInstance, Closeabl protected static final JAXBContext JAXB_CONTEXT = JaxbUtils.context(Artifacts.class); - protected Properties properties; - protected Map content = new HashMap<>(); - public AbstractSourceInstance(Properties properties) { - this.properties = properties; - } - protected void unpackContainer(InputStream inputStream, String targetName) throws IOException { content.put(targetName, ArtifactHolder.of(inputStream)); } diff --git a/src/test/java/no/difi/vefa/validator/source/ClasspathSource.java b/src/main/java/no/difi/vefa/validator/source/ClasspathSource.java similarity index 65% rename from src/test/java/no/difi/vefa/validator/source/ClasspathSource.java rename to src/main/java/no/difi/vefa/validator/source/ClasspathSource.java index c60529c5..2cbfd8f4 100644 --- a/src/test/java/no/difi/vefa/validator/source/ClasspathSource.java +++ b/src/main/java/no/difi/vefa/validator/source/ClasspathSource.java @@ -1,6 +1,5 @@ package no.difi.vefa.validator.source; -import no.difi.vefa.validator.api.Properties; import no.difi.vefa.validator.api.Source; import no.difi.vefa.validator.api.SourceInstance; import no.difi.vefa.validator.lang.ValidatorException; @@ -14,7 +13,7 @@ public ClasspathSource(String location) { } @Override - public SourceInstance createInstance(Properties properties) throws ValidatorException { - return new ClasspathSourceInstance(properties, location); + public SourceInstance createInstance() throws ValidatorException { + return new ClasspathSourceInstance(location); } } diff --git a/src/test/java/no/difi/vefa/validator/source/ClasspathSourceInstance.java b/src/main/java/no/difi/vefa/validator/source/ClasspathSourceInstance.java similarity index 90% rename from src/test/java/no/difi/vefa/validator/source/ClasspathSourceInstance.java rename to src/main/java/no/difi/vefa/validator/source/ClasspathSourceInstance.java index b437d0ac..ae5b3b8c 100644 --- a/src/test/java/no/difi/vefa/validator/source/ClasspathSourceInstance.java +++ b/src/main/java/no/difi/vefa/validator/source/ClasspathSourceInstance.java @@ -1,7 +1,6 @@ package no.difi.vefa.validator.source; import jakarta.xml.bind.Unmarshaller; -import no.difi.vefa.validator.api.Properties; import no.difi.vefa.validator.lang.ValidatorException; import no.difi.xsd.vefa.validator._1.ArtifactType; import no.difi.xsd.vefa.validator._1.Artifacts; @@ -16,9 +15,7 @@ class ClasspathSourceInstance extends AbstractSourceInstance { private static final Logger logger = LoggerFactory.getLogger(ClasspathSourceInstance.class); - public ClasspathSourceInstance(Properties properties, String location) throws ValidatorException { - super(properties); - + public ClasspathSourceInstance(String location) throws ValidatorException { String artifactsUri = location + "artifacts.xml"; try (InputStream inputStream = getClass().getResourceAsStream(artifactsUri)) { diff --git a/src/main/java/no/difi/vefa/validator/source/DirectorySource.java b/src/main/java/no/difi/vefa/validator/source/DirectorySource.java index d145d3ba..b55514ef 100644 --- a/src/main/java/no/difi/vefa/validator/source/DirectorySource.java +++ b/src/main/java/no/difi/vefa/validator/source/DirectorySource.java @@ -1,6 +1,5 @@ package no.difi.vefa.validator.source; -import no.difi.vefa.validator.api.Properties; import no.difi.vefa.validator.api.Source; import no.difi.vefa.validator.api.SourceInstance; import no.difi.vefa.validator.lang.ValidatorException; @@ -24,7 +23,7 @@ public DirectorySource(Path... directories) { } @Override - public SourceInstance createInstance(Properties properties) throws ValidatorException { - return new DirectorySourceInstance(properties, directories); + public SourceInstance createInstance() throws ValidatorException { + return new DirectorySourceInstance(directories); } } diff --git a/src/main/java/no/difi/vefa/validator/source/DirectorySourceInstance.java b/src/main/java/no/difi/vefa/validator/source/DirectorySourceInstance.java index ca568236..7f290efc 100644 --- a/src/main/java/no/difi/vefa/validator/source/DirectorySourceInstance.java +++ b/src/main/java/no/difi/vefa/validator/source/DirectorySourceInstance.java @@ -2,7 +2,6 @@ import jakarta.xml.bind.Unmarshaller; import lombok.extern.slf4j.Slf4j; -import no.difi.vefa.validator.api.Properties; import no.difi.vefa.validator.lang.ValidatorException; import no.difi.xsd.vefa.validator._1.ArtifactType; import no.difi.xsd.vefa.validator._1.Artifacts; @@ -24,10 +23,7 @@ class DirectorySourceInstance extends AbstractSourceInstance { * * @param directories Directories containing validation artifacts. */ - public DirectorySourceInstance(Properties properties, Path... directories) throws ValidatorException { - // Call #AbstractSourceInstance(). - super(properties); - + public DirectorySourceInstance(Path... directories) throws ValidatorException { try { for (Path directory : directories) { log.info("Directory: {}", directory); diff --git a/src/main/java/no/difi/vefa/validator/source/RepositorySource.java b/src/main/java/no/difi/vefa/validator/source/RepositorySource.java index 7f9cf39b..be9f1fb7 100644 --- a/src/main/java/no/difi/vefa/validator/source/RepositorySource.java +++ b/src/main/java/no/difi/vefa/validator/source/RepositorySource.java @@ -1,6 +1,5 @@ package no.difi.vefa.validator.source; -import no.difi.vefa.validator.api.Properties; import no.difi.vefa.validator.api.Source; import no.difi.vefa.validator.api.SourceInstance; import no.difi.vefa.validator.lang.ValidatorException; @@ -58,7 +57,7 @@ public RepositorySource(List uris) { } @Override - public SourceInstance createInstance(Properties properties) throws ValidatorException { - return new RepositorySourceInstance(properties, rootUri); + public SourceInstance createInstance() throws ValidatorException { + return new RepositorySourceInstance(rootUri); } } diff --git a/src/main/java/no/difi/vefa/validator/source/RepositorySourceInstance.java b/src/main/java/no/difi/vefa/validator/source/RepositorySourceInstance.java index 265ad217..dd206410 100644 --- a/src/main/java/no/difi/vefa/validator/source/RepositorySourceInstance.java +++ b/src/main/java/no/difi/vefa/validator/source/RepositorySourceInstance.java @@ -2,7 +2,6 @@ import jakarta.xml.bind.Unmarshaller; import lombok.extern.slf4j.Slf4j; -import no.difi.vefa.validator.api.Properties; import no.difi.vefa.validator.lang.ValidatorException; import no.difi.xsd.vefa.validator._1.ArtifactType; import no.difi.xsd.vefa.validator._1.Artifacts; @@ -14,9 +13,7 @@ @Slf4j class RepositorySourceInstance extends AbstractSourceInstance { - public RepositorySourceInstance(Properties properties, List rootUris) throws ValidatorException { - super(properties); - + public RepositorySourceInstance(List rootUris) throws ValidatorException { try { for (URI rootUri : rootUris) { Unmarshaller unmarshaller = JAXB_CONTEXT.createUnmarshaller(); diff --git a/src/main/java/no/difi/vefa/validator/tester/Tester.java b/src/main/java/no/difi/vefa/validator/tester/Tester.java index 1edd0c60..ddae1fca 100644 --- a/src/main/java/no/difi/vefa/validator/tester/Tester.java +++ b/src/main/java/no/difi/vefa/validator/tester/Tester.java @@ -1,36 +1,43 @@ package no.difi.vefa.validator.tester; +import com.google.inject.Guice; +import com.google.inject.Inject; +import com.google.inject.Module; import com.google.inject.Singleton; +import com.google.inject.util.Modules; import lombok.extern.slf4j.Slf4j; import no.difi.vefa.validator.Validator; -import no.difi.vefa.validator.ValidatorBuilder; +import no.difi.vefa.validator.api.Source; import no.difi.vefa.validator.api.Validation; -import no.difi.vefa.validator.properties.SimpleProperties; +import no.difi.vefa.validator.model.Document; +import no.difi.vefa.validator.model.Prop; +import no.difi.vefa.validator.module.PropertiesModule; +import no.difi.vefa.validator.module.SourceModule; +import no.difi.vefa.validator.module.ValidatorModule; +import no.difi.vefa.validator.service.TestingService; import no.difi.vefa.validator.source.DirectorySource; import no.difi.vefa.validator.source.RepositorySource; import no.difi.xsd.vefa.validator._1.AssertionType; import no.difi.xsd.vefa.validator._1.FlagType; import no.difi.xsd.vefa.validator._1.SectionType; -import java.io.Closeable; -import java.io.File; import java.io.IOException; import java.net.URI; -import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.SimpleFileVisitor; -import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; -import java.util.Collections; import java.util.List; @Slf4j @Singleton -public class Tester implements Closeable { +public class Tester { + @Inject private Validator validator; + @Inject + private TestingService testingService; + private final List validations = new ArrayList<>(); private int tests; @@ -38,63 +45,41 @@ public class Tester implements Closeable { private int failed; public static List perform(Path artifactsPath, List testPaths) throws IOException { - try (Tester tester = new Tester(artifactsPath)) { - for (Path path : testPaths) - tester.perform(path); - return tester.finish(); - } + return perform(new DirectorySource(artifactsPath), testPaths); } public static List perform(URI artifactsUri, List testPaths) throws IOException { - try (Tester tester = new Tester(artifactsUri)) { - for (Path path : testPaths) - tester.perform(path); - return tester.finish(); - } + return perform(new RepositorySource(artifactsUri), testPaths); } - private Tester(Path artifactsPath) { - validator = ValidatorBuilder - .newValidator() - .setProperties(new SimpleProperties() - .set("feature.nesting", true) - .set("feature.expectation", true) - .set("feature.suppress_notloaded", true) - ) - .setSource(new DirectorySource(artifactsPath)) - .build(); + public static List perform(Source source, List testPaths) throws IOException { + Tester tester = new Tester(source); + + for (Path path : testPaths) + tester.perform(path); + + return tester.finish(); } - private Tester(URI artifactsUri) { - validator = ValidatorBuilder - .newValidator() - .setProperties(new SimpleProperties() - .set("feature.nesting", true) - .set("feature.expectation", true) - .set("feature.suppress_notloaded", true) - ) - .setSource(new RepositorySource(artifactsUri)) - .build(); + private Tester(Source source) { + var modules = new ArrayList(); + modules.add(PropertiesModule.with( + Prop.of("feature.nesting", true), + Prop.of("feature.expectation", true), + Prop.of("feature.suppress_notloaded", true) + )); + modules.add(new SourceModule(source)); + + Guice.createInjector(Modules.override(new ValidatorModule()).with(modules)) + .injectMembers(this); } private void perform(Path path) throws IOException { - List files = new ArrayList<>(); - - Files.walkFileTree(path, new SimpleFileVisitor<>() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { - if (file.endsWith(".xml")) - files.add(file.toFile()); - - return super.visitFile(file, attrs); - } - }); - - Collections.sort(files); - - for (File file : files) - if (!file.getName().equals("buildconfig.xml")) - validate(file); + Files.walk(path) + .filter(p -> p.endsWith(".xml")) + .filter(p -> !"buildconfig.xml".equals(p.toFile().getName())) + .sorted() + .forEach(this::validate); } private List finish() { @@ -103,9 +88,12 @@ private List finish() { return validations; } - private void validate(File file) { + private void validate(Path file) { try { - Validation validation = validator.validate(file); + // Load document + var document = Document.of(file); + + Validation validation = validator.validate(document); validation.getReport().setFilename(file.toString()); if (validation.getDocument().getDeclarations() @@ -148,12 +136,4 @@ public void append(String description, Validation validation, Integer numberInSe log.info("Test '{}'", description); } } - - @Override - public void close() { - if (validator != null) { - validator.close(); - validator = null; - } - } } diff --git a/src/main/java/no/difi/vefa/validator/util/ClasspathURIResolver.java b/src/main/java/no/difi/vefa/validator/util/ClasspathURIResolver.java deleted file mode 100644 index ddaee9f7..00000000 --- a/src/main/java/no/difi/vefa/validator/util/ClasspathURIResolver.java +++ /dev/null @@ -1,22 +0,0 @@ -package no.difi.vefa.validator.util; - -import javax.xml.transform.Source; -import javax.xml.transform.URIResolver; -import javax.xml.transform.stream.StreamSource; - -/** - * @author erlend - */ -public class ClasspathURIResolver implements URIResolver { - - private final String path; - - public ClasspathURIResolver(String path) { - this.path = path; - } - - public Source resolve(String href, String base) { - return !"".equals(base) ? null : new StreamSource( - this.getClass().getResourceAsStream(String.format("%s/%s", this.path, href))); - } -} \ No newline at end of file diff --git a/src/main/java/no/difi/vefa/validator/util/ContentLoader.java b/src/main/java/no/difi/vefa/validator/util/ContentLoader.java new file mode 100644 index 00000000..32ee6825 --- /dev/null +++ b/src/main/java/no/difi/vefa/validator/util/ContentLoader.java @@ -0,0 +1,43 @@ +package no.difi.vefa.validator.util; + +import com.google.inject.Singleton; +import net.sf.saxon.lib.ResourceRequest; +import net.sf.saxon.lib.ResourceResolver; +import net.sf.saxon.trans.XPathException; + +import javax.xml.transform.Source; +import javax.xml.transform.stream.StreamSource; +import java.io.IOException; +import java.io.InputStream; + +@Singleton +public class ContentLoader implements ResourceResolver { + + @Override + public Source resolve(ResourceRequest request) throws XPathException { + return resolve(request.uri); + } + + public Source resolve(String uri) throws XPathException { + try { + // Loading resource + return new StreamSource(open(uri), uri); + } catch (IOException e) { + // Make sure to not hand over loading to default resolver + throw new XPathException(String.format("Unable to load resource: %s", uri)); + } + } + + public InputStream open(String uri) throws IOException { + // Loading resource from jar files + if (uri.startsWith("res:")) { + var inputStream = getClass().getResourceAsStream(uri.substring(4)); + if (inputStream == null) + throw new IOException(String.format("Resource not found: %s", uri)); + + return inputStream; + } + + throw new IOException(String.format("Unable to load resource: %s", uri)); + } +} diff --git a/src/main/java/no/difi/vefa/validator/util/HolderLSResolveResource.java b/src/main/java/no/difi/vefa/validator/util/HolderLSResolveResource.java index 0e0bc8ac..3aad01ff 100644 --- a/src/main/java/no/difi/vefa/validator/util/HolderLSResolveResource.java +++ b/src/main/java/no/difi/vefa/validator/util/HolderLSResolveResource.java @@ -1,30 +1,23 @@ package no.difi.vefa.validator.util; -import no.difi.vefa.validator.api.ArtifactHolder; +import no.difi.vefa.validator.model.ArtifactHolder; import org.w3c.dom.ls.LSInput; import org.w3c.dom.ls.LSResourceResolver; -import java.nio.file.Path; import java.nio.file.Paths; public class HolderLSResolveResource implements LSResourceResolver { private final ArtifactHolder artifactHolder; - private final Path rootPath; - public HolderLSResolveResource(ArtifactHolder artifactHolder, String rootPath) { + public HolderLSResolveResource(ArtifactHolder artifactHolder) { this.artifactHolder = artifactHolder; - this.rootPath = Paths.get(rootPath).getParent(); } @Override public LSInput resolveResource(String type, String namespaceURI, String publicId, String systemId, String baseURI) { - Path target; - if (baseURI == null) - target = rootPath.resolve(systemId); - else - target = Paths.get(baseURI.substring(7)).getParent().resolve(systemId); + var target = Paths.get(baseURI.substring(7)).getParent().resolve(systemId); String newPath = ("/" + target.toString().replaceAll("\\\\", "/")).replaceAll("/([^/]+?)/\\.\\.", "").substring(1); diff --git a/src/main/java/no/difi/vefa/validator/util/XsltHelper.java b/src/main/java/no/difi/vefa/validator/util/XsltHelper.java new file mode 100644 index 00000000..78e85cd7 --- /dev/null +++ b/src/main/java/no/difi/vefa/validator/util/XsltHelper.java @@ -0,0 +1,28 @@ +package no.difi.vefa.validator.util; + +import com.google.inject.Inject; +import com.google.inject.Provider; +import com.google.inject.Singleton; +import net.sf.saxon.s9api.SaxonApiException; +import net.sf.saxon.s9api.XsltCompiler; +import net.sf.saxon.s9api.XsltExecutable; +import no.difi.vefa.validator.lang.ValidatorException; + +import javax.xml.transform.stream.StreamSource; +import java.io.IOException; +import java.io.InputStream; + +@Singleton +public class XsltHelper { + + @Inject + private Provider compilerProvider; + + public XsltExecutable fromResource(String path) throws ValidatorException { + try (InputStream inputStream = getClass().getResourceAsStream(path)) { + return compilerProvider.get().compile(new StreamSource(inputStream, "res:" + path)); + } catch (IOException | SaxonApiException e) { + throw new ValidatorException("Unable to load XSLT from resource."); + } + } +} diff --git a/src/main/java/no/difi/vefa/validator/util/ZipArchiver.java b/src/main/java/no/difi/vefa/validator/util/ZipArchive.java similarity index 97% rename from src/main/java/no/difi/vefa/validator/util/ZipArchiver.java rename to src/main/java/no/difi/vefa/validator/util/ZipArchive.java index 9d7b468b..5fc82696 100644 --- a/src/main/java/no/difi/vefa/validator/util/ZipArchiver.java +++ b/src/main/java/no/difi/vefa/validator/util/ZipArchive.java @@ -16,7 +16,7 @@ /** * @author erlend */ -public interface ZipArchiver { +public interface ZipArchive { static void archive(Path target, Path directory) throws IOException { try (OutputStream outputStream = Files.newOutputStream(target); diff --git a/src/main/xsd/vefa-validator.xsd b/src/main/xsd/vefa-validator.xsd index 3762e182..bd6a8c97 100644 --- a/src/main/xsd/vefa-validator.xsd +++ b/src/main/xsd/vefa-validator.xsd @@ -125,7 +125,6 @@ - @@ -174,7 +173,6 @@ - diff --git a/src/test/java/no/difi/vefa/validator/SimpleTest.java b/src/test/java/no/difi/vefa/validator/SimpleTest.java index 0c024698..b566f33b 100644 --- a/src/test/java/no/difi/vefa/validator/SimpleTest.java +++ b/src/test/java/no/difi/vefa/validator/SimpleTest.java @@ -2,7 +2,7 @@ import lombok.extern.slf4j.Slf4j; import no.difi.vefa.validator.api.Validation; -import no.difi.vefa.validator.properties.SimpleProperties; +import no.difi.vefa.validator.model.Prop; import no.difi.vefa.validator.source.ClasspathSource; import no.difi.xsd.vefa.validator._1.AssertionType; import no.difi.xsd.vefa.validator._1.FlagType; @@ -24,8 +24,7 @@ public class SimpleTest { public void beforeClass() { validator = ValidatorBuilder .newValidator() - .setProperties(new SimpleProperties() - .set("feature.expectation", true)) + .setProperties(Prop.of("feature.expectation", true)) .setSource(new ClasspathSource("/rules/")) .build(); } @@ -78,7 +77,7 @@ public void simpleOk() throws IOException { public void simpleValidatorTest() throws IOException { var validation = validator.validate( getClass().getResourceAsStream("/documents/NOGOV-T10-R014.xml"), - new SimpleProperties().set("feature.nesting", true)); + Prop.of("feature.nesting", true)); assertEquals(validation.getReport().getFlag(), FlagType.OK); assertEquals(validation.getChildren().size(), 3); diff --git a/src/test/java/no/difi/vefa/validator/config/SimplePropertiesTest.java b/src/test/java/no/difi/vefa/validator/config/SimplePropertiesTest.java deleted file mode 100644 index 1fedbbac..00000000 --- a/src/test/java/no/difi/vefa/validator/config/SimplePropertiesTest.java +++ /dev/null @@ -1,52 +0,0 @@ -package no.difi.vefa.validator.config; - -import static org.testng.Assert.*; - -import no.difi.vefa.validator.api.Properties; -import no.difi.vefa.validator.properties.SimpleProperties; -import org.testng.annotations.Test; - -public class SimplePropertiesTest { - - @Test - public void simple() { - Properties properties = new SimpleProperties() - .set("some.string", "Hello World!") - .set("some.number", 1) - .set("some.boolean", true) - .set("some.object", new Long(123)); - - assertTrue(properties.contains("some.string")); - assertTrue(properties.contains("some.number")); - assertTrue(properties.contains("some.boolean")); - assertTrue(properties.contains("some.object")); - - assertFalse(properties.contains("some.other.string")); - assertFalse(properties.contains("some.other.number")); - assertFalse(properties.contains("some.other.boolean")); - assertFalse(properties.contains("some.other.object")); - - assertEquals(properties.getString("some.string"), "Hello World!"); - assertEquals(properties.getInteger("some.number"), 1); - assertEquals(properties.getBoolean("some.boolean"), true); - assertEquals(properties.get("some.object").getClass(), Long.class); - - assertEquals(properties.getString("some.string", "No no!"), "Hello World!"); - assertEquals(properties.getInteger("some.number", 0), 1); - assertEquals(properties.getBoolean("some.boolean", false), true); - assertEquals(properties.get("some.object", null).getClass(), Long.class); - - assertEquals(properties.getString("some.other.string"), null); - assertEquals(properties.getInteger("some.other.number"), 0); - assertEquals(properties.getBoolean("some.other.boolean"), false); - assertEquals(properties.get("some.other.object"), null); - - assertEquals(properties.getString("some.other.string", "No no!"), "No no!"); - assertEquals(properties.getInteger("some.other.number", 0), 0); - assertEquals(properties.getBoolean("some.other.boolean", true), true); - assertEquals(properties.get("some.other.object", null), null); - - assertEquals(properties.getInteger("some.boolean", 100), 100); - } - -} diff --git a/src/test/java/no/difi/vefa/validator/declaration/EspdDeclarationTest.java b/src/test/java/no/difi/vefa/validator/declaration/EspdDeclarationTest.java index 1da29ee0..de1dc7c4 100644 --- a/src/test/java/no/difi/vefa/validator/declaration/EspdDeclarationTest.java +++ b/src/test/java/no/difi/vefa/validator/declaration/EspdDeclarationTest.java @@ -2,9 +2,9 @@ import com.google.inject.Guice; import com.google.inject.Inject; -import no.difi.vefa.validator.api.Document; +import no.difi.vefa.validator.model.Document; import no.difi.vefa.validator.module.ValidatorModule; -import no.difi.vefa.validator.util.DeclarationDetector; +import no.difi.vefa.validator.service.DetectorService; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; @@ -13,7 +13,7 @@ public class EspdDeclarationTest { @Inject - private DeclarationDetector declarationDetector; + private DetectorService declarationDetector; @BeforeClass public void beforeClass() { diff --git a/src/test/java/no/difi/vefa/validator/declaration/SbdhDeclarationTest.java b/src/test/java/no/difi/vefa/validator/declaration/SbdhDeclarationTest.java index 584543d1..696e8511 100644 --- a/src/test/java/no/difi/vefa/validator/declaration/SbdhDeclarationTest.java +++ b/src/test/java/no/difi/vefa/validator/declaration/SbdhDeclarationTest.java @@ -2,9 +2,9 @@ import com.google.inject.Guice; import com.google.inject.Inject; -import no.difi.vefa.validator.api.Document; +import no.difi.vefa.validator.model.Document; import no.difi.vefa.validator.module.ValidatorModule; -import no.difi.vefa.validator.util.DeclarationDetector; +import no.difi.vefa.validator.service.DetectorService; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; @@ -13,7 +13,7 @@ public class SbdhDeclarationTest { @Inject - private DeclarationDetector declarationDetector; + private DetectorService declarationDetector; @BeforeClass public void beforeClass() { diff --git a/src/test/java/no/difi/vefa/validator/declaration/UblDeclarationTest.java b/src/test/java/no/difi/vefa/validator/declaration/UblDeclarationTest.java index 60bd88b5..1a696ee4 100644 --- a/src/test/java/no/difi/vefa/validator/declaration/UblDeclarationTest.java +++ b/src/test/java/no/difi/vefa/validator/declaration/UblDeclarationTest.java @@ -2,10 +2,10 @@ import com.google.inject.Guice; import com.google.inject.Inject; -import no.difi.vefa.validator.api.Document; +import no.difi.vefa.validator.model.Document; import no.difi.vefa.validator.module.ValidatorModule; -import no.difi.vefa.validator.util.DeclarationDetector; -import no.difi.vefa.validator.util.DeclarationIdentification; +import no.difi.vefa.validator.service.DetectorService; +import no.difi.vefa.validator.model.Detected; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; @@ -18,7 +18,7 @@ public class UblDeclarationTest { ""); - assertEquals(declarationDetector.detect(document), DeclarationIdentification.UNKNOWN); + assertEquals(declarationDetector.detect(document), Detected.UNKNOWN); } @Test diff --git a/src/test/java/no/difi/vefa/validator/declaration/UnCefactDeclarationTest.java b/src/test/java/no/difi/vefa/validator/declaration/UnCefactDeclarationTest.java index c2fd7582..00979332 100644 --- a/src/test/java/no/difi/vefa/validator/declaration/UnCefactDeclarationTest.java +++ b/src/test/java/no/difi/vefa/validator/declaration/UnCefactDeclarationTest.java @@ -2,9 +2,9 @@ import com.google.inject.Guice; import com.google.inject.Inject; -import no.difi.vefa.validator.api.Document; +import no.difi.vefa.validator.model.Document; import no.difi.vefa.validator.module.ValidatorModule; -import no.difi.vefa.validator.util.DeclarationDetector; +import no.difi.vefa.validator.service.DetectorService; import org.testng.Assert; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; @@ -12,7 +12,7 @@ public class UnCefactDeclarationTest { @Inject - private DeclarationDetector declarationDetector; + private DetectorService declarationDetector; @BeforeClass public void beforeClass() { diff --git a/src/test/java/no/difi/vefa/validator/api/DocumentTest.java b/src/test/java/no/difi/vefa/validator/model/DocumentTest.java similarity index 86% rename from src/test/java/no/difi/vefa/validator/api/DocumentTest.java rename to src/test/java/no/difi/vefa/validator/model/DocumentTest.java index 0db8066a..4d77a77a 100644 --- a/src/test/java/no/difi/vefa/validator/api/DocumentTest.java +++ b/src/test/java/no/difi/vefa/validator/model/DocumentTest.java @@ -1,5 +1,6 @@ -package no.difi.vefa.validator.api; +package no.difi.vefa.validator.model; +import no.difi.vefa.validator.model.Document; import org.testng.Assert; import org.testng.annotations.Test; diff --git a/src/test/java/no/difi/vefa/validator/util/DeclarationDetectorTest.java b/src/test/java/no/difi/vefa/validator/service/DetectorServiceTest.java similarity index 76% rename from src/test/java/no/difi/vefa/validator/util/DeclarationDetectorTest.java rename to src/test/java/no/difi/vefa/validator/service/DetectorServiceTest.java index 2cdee013..c776c5f2 100644 --- a/src/test/java/no/difi/vefa/validator/util/DeclarationDetectorTest.java +++ b/src/test/java/no/difi/vefa/validator/service/DetectorServiceTest.java @@ -1,21 +1,17 @@ -package no.difi.vefa.validator.util; +package no.difi.vefa.validator.service; -import com.google.common.io.ByteStreams; import com.google.inject.Guice; import com.google.inject.Inject; -import no.difi.vefa.validator.api.Document; +import no.difi.vefa.validator.model.Document; import no.difi.vefa.validator.module.ValidatorModule; import org.testng.Assert; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; -import java.io.ByteArrayInputStream; -import java.io.InputStream; - -public class DeclarationDetectorTest { +public class DetectorServiceTest { @Inject - private DeclarationDetector declarationDetector; + private DetectorService declarationDetector; @BeforeClass public void beforeClass() { diff --git a/src/test/java/no/difi/vefa/validator/service/TestingServiceTest.java b/src/test/java/no/difi/vefa/validator/service/TestingServiceTest.java new file mode 100644 index 00000000..bb34eaba --- /dev/null +++ b/src/test/java/no/difi/vefa/validator/service/TestingServiceTest.java @@ -0,0 +1,37 @@ +package no.difi.vefa.validator.service; + +import com.google.inject.Guice; +import com.google.inject.Inject; +import com.google.inject.util.Modules; +import no.difi.vefa.validator.model.Document; +import no.difi.vefa.validator.module.SourceModule; +import no.difi.vefa.validator.module.ValidatorModule; +import no.difi.vefa.validator.source.ClasspathSource; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +public class TestingServiceTest { + + @Inject + private TestingService testingService; + + @BeforeClass + public void beforeClass() { + var module = Modules.override(new ValidatorModule()).with(new SourceModule(new ClasspathSource("/rules/"))); + Guice.createInjector(module).injectMembers(this); + } + + @Test + public void testSetTest() throws Exception { + var document = Document.ofResource("/documents/NOGOV-T10-R014.xml"); + + var validations = testingService.verify(document); + } + + // @Test + public void genericTest() throws Exception { + var document = Document.ofResource("/documents/T10-hode-feilkoder.xml"); + + var validations = testingService.verify(document); + } +} diff --git a/src/test/java/no/difi/vefa/validator/source/DirectorySourceTest.java b/src/test/java/no/difi/vefa/validator/source/DirectorySourceTest.java index 67d9e8d1..2b4be07d 100644 --- a/src/test/java/no/difi/vefa/validator/source/DirectorySourceTest.java +++ b/src/test/java/no/difi/vefa/validator/source/DirectorySourceTest.java @@ -1,8 +1,6 @@ package no.difi.vefa.validator.source; -import no.difi.vefa.validator.api.Properties; import no.difi.vefa.validator.lang.ValidatorException; -import org.mockito.Mockito; import org.testng.annotations.Test; public class DirectorySourceTest { @@ -10,6 +8,6 @@ public class DirectorySourceTest { @Test(expectedExceptions = ValidatorException.class) public void triggerException() throws ValidatorException { DirectorySource source = new DirectorySource(null); - source.createInstance(Mockito.mock(Properties.class)); + source.createInstance(); } } diff --git a/src/test/java/no/difi/vefa/validator/source/RepositorySourceTest.java b/src/test/java/no/difi/vefa/validator/source/RepositorySourceTest.java index 85a846b2..bc47e1a9 100644 --- a/src/test/java/no/difi/vefa/validator/source/RepositorySourceTest.java +++ b/src/test/java/no/difi/vefa/validator/source/RepositorySourceTest.java @@ -1,8 +1,6 @@ package no.difi.vefa.validator.source; -import no.difi.vefa.validator.api.Properties; import no.difi.vefa.validator.lang.ValidatorException; -import org.mockito.Mockito; import org.testng.Assert; import org.testng.annotations.Test; @@ -20,6 +18,6 @@ public void simple() { @Test(expectedExceptions = ValidatorException.class) public void triggerException() throws ValidatorException { RepositorySource source = new RepositorySource((URI) null); - source.createInstance(Mockito.mock(Properties.class)); + source.createInstance(); } } diff --git a/src/test/resources/rules/artifacts.xml b/src/test/resources/rules/artifacts.xml index d9dae604..9c61d188 100644 --- a/src/test/resources/rules/artifacts.xml +++ b/src/test/resources/rules/artifacts.xml @@ -1,7 +1,6 @@ - diff --git a/src/test/resources/rules/ehf-stylesheet-1c573960978491dff855ae35ec28b582de2405e2.asice b/src/test/resources/rules/ehf-stylesheet-1c573960978491dff855ae35ec28b582de2405e2.asice deleted file mode 100644 index ecdf93d987bae15f700d510e7f8ebd8ed61c2223..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18035 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 OGXsML{ID28DI5Tr3C0ru