Skip to content

Commit

Permalink
Add validation API
Browse files Browse the repository at this point in the history
  • Loading branch information
pwinckles committed Apr 5, 2021
1 parent aaee98a commit 1dd8f57
Show file tree
Hide file tree
Showing 627 changed files with 121,005 additions and 813 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,8 @@ file within an object. This is useful for identifying at what point
specific files were changed.
* **containsObject**: Indicates whether the OCFL repository contains
an object with the given id.
* **validateObject**: Validates an object against the OCFL 1.0 spec and
returns a list of any errors or warnings found.
* **purgeObject**: Permanently removes an object from the repository.
The object is NOT recoverable.
* **listObjectIds**: Returns a stream containing the ids of all of the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,12 @@
import edu.wisc.library.ocfl.api.exception.NotFoundException;
import edu.wisc.library.ocfl.api.exception.ObjectOutOfSyncException;
import edu.wisc.library.ocfl.api.exception.OcflStateException;
import edu.wisc.library.ocfl.api.exception.ValidationException;
import edu.wisc.library.ocfl.api.model.FileChangeHistory;
import edu.wisc.library.ocfl.api.model.ObjectDetails;
import edu.wisc.library.ocfl.api.model.ObjectVersionId;
import edu.wisc.library.ocfl.api.model.OcflObjectVersion;
import edu.wisc.library.ocfl.api.model.ValidationResults;
import edu.wisc.library.ocfl.api.model.VersionDetails;
import edu.wisc.library.ocfl.api.model.VersionInfo;

Expand Down Expand Up @@ -164,6 +166,23 @@ public interface OcflRepository {
*/
void purgeObject(String objectId);

/**
* Validates an existing object against the OCFL 1.0 spec and returns a report containing all of the issues that
* were found with their accompanying <a href="https://ocfl.io/validation/validation-codes.html">validation code</a>.
*
* <p>The validation does NOT lock the object, which means that if an object is updated while the object is in
* the process of being validated, then the results may be inaccurate.
*
* <p>If a fixity check is requested, then this call may be quite expensive as it will have to calculate the digests
* of every file in the object.
*
* @param objectId the id of the object to validate
* @param contentFixityCheck true if the fixity of the content files should be verified
* @return the validation results
* @throws NotFoundException if the object does not exist.
*/
ValidationResults validateObject(String objectId, boolean contentFixityCheck);

/**
* Creates a new head version by copying the state of the specified version. This is a non-destructive way to roll an
* object back to a prior version without altering its version history.
Expand Down Expand Up @@ -204,9 +223,8 @@ public interface OcflRepository {
*
* @param objectVersionId the id of the object and version to export
* @param outputPath the directory to write the exported version to, if it does not exist it will be created
* @param options optional config options. Use {@link OcflOption#NO_VALIDATION} to disable export validation.
* @param options optional config options.
* @throws NotFoundException when no object can be found for the specified objectVersionId
* @throws CorruptObjectException when the exported version fails validation
*/
void exportVersion(ObjectVersionId objectVersionId, Path outputPath, OcflOption... options);

Expand All @@ -222,7 +240,7 @@ public interface OcflRepository {
* @param outputPath the directory to write the exported object to, if it does not exist it will be created
* @param options optional config options. Use {@link OcflOption#NO_VALIDATION} to disable export validation.
* @throws NotFoundException when no object can be found for the specified objectId
* @throws CorruptObjectException when the exported object fails validation
* @throws ValidationException when the exported object fails validation
*/
void exportObject(String objectId, Path outputPath, OcflOption... options);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 University of Wisconsin Board of Regents
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

package edu.wisc.library.ocfl.api.exception;

import edu.wisc.library.ocfl.api.model.ValidationIssue;
import edu.wisc.library.ocfl.api.model.ValidationResults;

import java.util.List;

/**
* This exception indicates that there were object validation errors
*/
public class ValidationException extends OcflJavaException {

private final ValidationResults validationResults;

public ValidationException(String message, ValidationResults results) {
super(message);
this.validationResults = results;
}

public ValidationResults getValidationResults() {
return validationResults;
}

@Override
public String getMessage() {
var builder = new StringBuilder(super.getMessage());

builder.append("\nErrors:\n");
printIssues(validationResults.getErrors(), builder);

if (validationResults.hasWarnings()) {
builder.append("\nWarnings:\n");
printIssues(validationResults.getWarnings(), builder);
}

if (validationResults.hasInfos()) {
builder.append("\nInfos:\n");
printIssues(validationResults.getInfos(), builder);
}

return builder.toString();
}

private void printIssues(List<ValidationIssue> issues, StringBuilder builder) {
for (int i = 1; i <= issues.size(); i++) {
builder.append(" ").append(i).append(". ");
builder.append(issues.get(i - 1).toString());
if (i < issues.size()) {
builder.append("\n");
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 University of Wisconsin Board of Regents
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

package edu.wisc.library.ocfl.api.model;

/**
* OCFL validation codes: https://ocfl.io/validation/validation-codes.html
*/
public enum ValidationCode {

E001(Type.ERROR),
E002(Type.ERROR),
E003(Type.ERROR),
E004(Type.ERROR),
E005(Type.ERROR),
E006(Type.ERROR),
E007(Type.ERROR),
E008(Type.ERROR),
E009(Type.ERROR),
E010(Type.ERROR),
E011(Type.ERROR),
E012(Type.ERROR),
E013(Type.ERROR),
E014(Type.ERROR),
E015(Type.ERROR),
E016(Type.ERROR),
E017(Type.ERROR),
E018(Type.ERROR),
E019(Type.ERROR),
E020(Type.ERROR),
E021(Type.ERROR),
E022(Type.ERROR),
E023(Type.ERROR),
E024(Type.ERROR),
E025(Type.ERROR),
E026(Type.ERROR),
E027(Type.ERROR),
E028(Type.ERROR),
E029(Type.ERROR),
E030(Type.ERROR),
E031(Type.ERROR),
E032(Type.ERROR),
E033(Type.ERROR),
E034(Type.ERROR),
E035(Type.ERROR),
E036(Type.ERROR),
E037(Type.ERROR),
E038(Type.ERROR),
E039(Type.ERROR),
E040(Type.ERROR),
E041(Type.ERROR),
E042(Type.ERROR),
E043(Type.ERROR),
E044(Type.ERROR),
E045(Type.ERROR),
E046(Type.ERROR),
E047(Type.ERROR),
E048(Type.ERROR),
E049(Type.ERROR),
E050(Type.ERROR),
E051(Type.ERROR),
E052(Type.ERROR),
E053(Type.ERROR),
E054(Type.ERROR),
E055(Type.ERROR),
E056(Type.ERROR),
E057(Type.ERROR),
E058(Type.ERROR),
E059(Type.ERROR),
E060(Type.ERROR),
E061(Type.ERROR),
E062(Type.ERROR),
E063(Type.ERROR),
E064(Type.ERROR),
// https://github.com/OCFL/spec/issues/529
// E065(Type.ERROR),
E066(Type.ERROR),
E067(Type.ERROR),
E068(Type.ERROR),
E069(Type.ERROR),
E070(Type.ERROR),
E071(Type.ERROR),
E072(Type.ERROR),
E073(Type.ERROR),
E074(Type.ERROR),
E075(Type.ERROR),
E076(Type.ERROR),
E077(Type.ERROR),
E078(Type.ERROR),
E079(Type.ERROR),
E080(Type.ERROR),
E081(Type.ERROR),
E082(Type.ERROR),
E083(Type.ERROR),
E084(Type.ERROR),
E085(Type.ERROR),
E086(Type.ERROR),
E087(Type.ERROR),
E088(Type.ERROR),
E089(Type.ERROR),
E090(Type.ERROR),
E091(Type.ERROR),
E092(Type.ERROR),
E093(Type.ERROR),
E094(Type.ERROR),
E095(Type.ERROR),
E096(Type.ERROR),
E097(Type.ERROR),
E098(Type.ERROR),
E099(Type.ERROR),
E100(Type.ERROR),
E101(Type.ERROR),
E102(Type.ERROR),


W001(Type.WARN),
W002(Type.WARN),
W003(Type.WARN),
W004(Type.WARN),
W005(Type.WARN),
W006(Type.WARN),
W007(Type.WARN),
W008(Type.WARN),
W009(Type.WARN),
W010(Type.WARN),
W011(Type.WARN),
W012(Type.WARN),
W013(Type.WARN),
W014(Type.WARN),
W015(Type.WARN);

public enum Type {
INFO, WARN, ERROR
}

private final Type type;

ValidationCode(Type type) {
this.type = type;
}

public Type getType() {
return type;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 University of Wisconsin Board of Regents
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

package edu.wisc.library.ocfl.api.model;

import edu.wisc.library.ocfl.api.util.Enforce;

/**
* Encapsulates a validation code and a descriptive message
*/
public class ValidationIssue {

private final ValidationCode code;
private final String message;

public ValidationIssue(ValidationCode code, String message) {
this.code = Enforce.notNull(code, "code cannot be null");
this.message = Enforce.notBlank(message, "message cannot be blank");
}

/**
* @return the validation code
*/
public ValidationCode getCode() {
return code;
}

/**
* @return the descriptive message
*/
public String getMessage() {
return message;
}

@Override
public String toString() {
return String.format("[%s] %s", code, message);
}
}
Loading

0 comments on commit 1dd8f57

Please sign in to comment.