Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
janvanmansum committed Nov 30, 2024
1 parent ae8de2a commit ae06dab
Show file tree
Hide file tree
Showing 9 changed files with 160 additions and 89 deletions.
1 change: 1 addition & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@

<properties>
<main-class>nl.knaw.dans.validatedansbag.DdValidateDansBagApplication</main-class>
<dd-validate-dans-bag-api.version>0.5.1-SNAPSHOT</dd-validate-dans-bag-api.version>
</properties>

<scm>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

package nl.knaw.dans.validatedansbag;

import io.dropwizard.configuration.FileConfigurationSourceProvider;
import io.dropwizard.core.Application;
import io.dropwizard.core.setup.Bootstrap;
import io.dropwizard.core.setup.Environment;
Expand Down Expand Up @@ -45,8 +44,9 @@
import nl.knaw.dans.validatedansbag.core.validator.PolygonListValidatorImpl;
import nl.knaw.dans.validatedansbag.health.XmlSchemaHealthCheck;
import nl.knaw.dans.validatedansbag.resources.IllegalArgumentExceptionMapper;
import nl.knaw.dans.validatedansbag.resources.ValidateOkYamlMessageBodyWriter;
import nl.knaw.dans.validatedansbag.resources.ValidateLocalDirApiResource;
import nl.knaw.dans.validatedansbag.resources.ValidateResource;
import nl.knaw.dans.validatedansbag.resources.ValidateZipApiResource;
import nl.knaw.dans.vaultcatalog.client.invoker.ApiClient;
import nl.knaw.dans.vaultcatalog.client.resources.DefaultApi;

Expand All @@ -55,7 +55,6 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
Expand Down Expand Up @@ -125,7 +124,8 @@ public void run(final DdValidateDansBagConfiguration configuration, final Enviro

environment.jersey().register(new IllegalArgumentExceptionMapper());
environment.jersey().register(new ValidateResource(ruleEngineService, fileService));
environment.jersey().register(new ValidateOkYamlMessageBodyWriter());
environment.jersey().register(new ValidateZipApiResource(ruleEngineService, fileService));
environment.jersey().register(new ValidateLocalDirApiResource(ruleEngineService));

environment.healthChecks().register("xml-schemas", new XmlSchemaHealthCheck(xmlSchemaValidator));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,17 @@

public class FileServiceImpl implements FileService {
private final Path baseFolder;
private final Path tempFolder;

public FileServiceImpl(Path baseFolder) {
this.baseFolder = baseFolder;
this.baseFolder = baseFolder.normalize().toAbsolutePath();

try {
this.tempFolder = Files.createDirectories(this.baseFolder.resolve("temp"));
}
catch (IOException e) {
throw new RuntimeException("Could not create temp directory", e);
}
}

@Override
Expand Down Expand Up @@ -84,7 +92,7 @@ public CharBuffer readFileContents(Path path, Charset charset) throws IOExceptio

@Override
public Path extractZipFile(InputStream inputStream) throws IOException {
var tempPath = Files.createTempDirectory(this.baseFolder, "bag-");
var tempPath = Files.createTempDirectory(this.tempFolder, "bag-");

try (var input = new ZipInputStream(inputStream)) {
var entry = input.getNextEntry();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package nl.knaw.dans.validatedansbag.core.service;

import nl.knaw.dans.validatedansbag.api.ValidateOkDto;
import nl.knaw.dans.validatedansbag.core.engine.DepositType;
import nl.knaw.dans.validatedansbag.core.engine.RuleValidationResult;

Expand All @@ -25,4 +26,5 @@ public interface RuleEngineService {

List<RuleValidationResult> validateBag(Path path, DepositType depositType) throws Exception;

ValidateOkDto validateBag(Path path, DepositType depositType, String bagLocation) throws Exception;
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
package nl.knaw.dans.validatedansbag.core.service;

import lombok.extern.slf4j.Slf4j;
import nl.knaw.dans.validatedansbag.api.ValidateOkDto;
import nl.knaw.dans.validatedansbag.api.ValidateOkRuleViolationsInnerDto;
import nl.knaw.dans.validatedansbag.core.BagNotFoundException;
import nl.knaw.dans.validatedansbag.core.engine.DepositType;
import nl.knaw.dans.validatedansbag.core.engine.NumberedRule;
Expand All @@ -25,6 +27,7 @@

import java.nio.file.Path;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
public class RuleEngineServiceImpl implements RuleEngineService {
Expand All @@ -34,8 +37,8 @@ public class RuleEngineServiceImpl implements RuleEngineService {
private final NumberedRule[] ruleSet;

public RuleEngineServiceImpl(RuleEngine ruleEngine,
FileService fileService,
NumberedRule[] ruleSet) {
FileService fileService,
NumberedRule[] ruleSet) {
this.ruleEngine = ruleEngine;
this.fileService = fileService;
this.ruleSet = ruleSet;
Expand All @@ -54,10 +57,58 @@ public List<RuleValidationResult> validateBag(Path path, DepositType depositType
return ruleEngine.validateRules(path, this.ruleSet, depositType);
}

@Override
public ValidateOkDto validateBag(Path path, DepositType depositType, String bagLocation) throws Exception {
log.info("Validating bag on path '{}'", path);

if (!fileService.isReadable(path)) {
log.warn("Path {} could not not be found or is not readable", path);
throw new BagNotFoundException(String.format("Bag on path '%s' could not be found or read", path));
}

var results = ruleEngine.validateRules(path, this.ruleSet, depositType);
var isValid = results.stream().noneMatch(r -> r.getStatus().equals(RuleValidationResult.RuleValidationResultStatus.FAILURE));

var result = new ValidateOkDto();
result.setBagLocation(bagLocation);
result.setIsCompliant(isValid);
result.setName(path.getFileName().toString());
result.setProfileVersion("1.1.0");
result.setInformationPackageType(toInfoPackageType(depositType));
result.setRuleViolations(results.stream()
.filter(r -> r.getStatus().equals(RuleValidationResult.RuleValidationResultStatus.FAILURE))
.map(rule -> {
var ret = new ValidateOkRuleViolationsInnerDto();
ret.setRule(rule.getNumber());

var message = new StringBuilder();

if (rule.getErrorMessage() != null) {
message.append(rule.getErrorMessage());
}

ret.setViolation(message.toString());
return ret;
})
.collect(Collectors.toList()));

log.debug("Validation result: {}", result);

return result;
}

private ValidateOkDto.InformationPackageTypeEnum toInfoPackageType(DepositType value) {
if (DepositType.MIGRATION.equals(value)) {
return ValidateOkDto.InformationPackageTypeEnum.MIGRATION;
}
return ValidateOkDto.InformationPackageTypeEnum.DEPOSIT;
}

public void validateRuleConfiguration() {
try {
this.ruleEngine.validateRuleConfiguration(this.ruleSet);
} catch (RuleEngineConfigurationException e) {
}
catch (RuleEngineConfigurationException e) {
throw new RuntimeException("Rule configuration is not valid", e);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright (C) 2022 DANS - Data Archiving and Networked Services ([email protected])
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package nl.knaw.dans.validatedansbag.resources;

import lombok.AllArgsConstructor;
import nl.knaw.dans.validatedansbag.api.ValidateCommandDto;
import nl.knaw.dans.validatedansbag.core.engine.DepositType;
import nl.knaw.dans.validatedansbag.core.service.RuleEngineService;

import javax.ws.rs.core.Response;
import java.nio.file.Path;

@AllArgsConstructor
public class ValidateLocalDirApiResource implements ValidateLocalDirApi {
private final RuleEngineService ruleEngineService;

@Override
public Response validateLocalDirPost(ValidateCommandDto validateCommandDto) {
try {
var result = ruleEngineService.validateBag(Path.of(validateCommandDto.getBagLocation()),
DepositType.valueOf(validateCommandDto.getPackageType().toString()),
validateCommandDto.getBagLocation());
return Response.ok(result).build();
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Copyright (C) 2022 DANS - Data Archiving and Networked Services ([email protected])
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package nl.knaw.dans.validatedansbag.resources;

import lombok.AllArgsConstructor;
import nl.knaw.dans.validatedansbag.core.engine.DepositType;
import nl.knaw.dans.validatedansbag.core.service.FileService;
import nl.knaw.dans.validatedansbag.core.service.RuleEngineService;

import javax.ws.rs.core.Response;
import java.io.File;
import java.io.FileInputStream;

@AllArgsConstructor
public class ValidateZipApiResource implements ValidateZipApi {
private final RuleEngineService ruleEngineService;
private final FileService fileService;

@Override
public Response validateZipPost(File body) {
try (var inputStream = new FileInputStream(body)) {
var dir = fileService.extractZipFile(inputStream);
var bagDir = fileService.getFirstDirectory(dir);
if (bagDir.isEmpty()) {
return Response.status(Response.Status.BAD_REQUEST).entity("No bag directory found in zip file").build();
}
var result = ruleEngineService.validateBag(bagDir.get(), DepositType.DEPOSIT, "ZIP");
return Response.ok(result).build();
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ public boolean isValidLicense(String license) {
static {
EXT = ResourceExtension.builder()
.addProvider(MultiPartFeature.class)
.addProvider(ValidateOkYamlMessageBodyWriter.class)
.addResource(buildValidateResource())
.build();
}
Expand Down Expand Up @@ -367,35 +366,6 @@ void validateFormData_should_not_throw_internal_server_error_on_incomplete_manif
.endsWith("original-metadata.zip] is in the payload directory but isn't listed in any manifest!");
}

@Test
void validateZipFile_should_return_a_textual_representation_when_requested() throws Exception {
var inputStream = Files.newInputStream(Path.of(baseTestFolder, "/zips/invalid-sha1.zip"));

var embargoResultJson = """
{
"status": "OK",
"data": {
"message": "24"
}
}""";
var maxEmbargoDurationResult = new MockedDataverseResponse<DataMessage>(embargoResultJson, DataMessage.class);
Mockito.when(dataverseService.getMaxEmbargoDurationInMonths())
.thenReturn(maxEmbargoDurationResult);

var response = EXT.target("/validate")
.request()
.header("accept", "text/plain")
.header("Authorization", basicUsernamePassword("user001", "user001"))
.post(Entity.entity(inputStream, MediaType.valueOf("application/zip")), String.class);

assertTrue(response.contains("Bag location:"));
assertTrue(response.contains("Name:"));
assertTrue(response.contains("Profile version:"));
assertTrue(response.contains("Information package type:"));
assertTrue(response.contains("Is compliant:"));
assertTrue(response.contains("Rule violations:"));
}

@Test
void validateFormData_with_invalid_path_should_return_400_error() {
var data = new ValidateCommandDto();
Expand Down

0 comments on commit ae06dab

Please sign in to comment.