diff --git a/src/main/java/org/roda_project/commons_ip/utils/IPEnums.java b/src/main/java/org/roda_project/commons_ip/utils/IPEnums.java index 93999b5c..04e8fdee 100644 --- a/src/main/java/org/roda_project/commons_ip/utils/IPEnums.java +++ b/src/main/java/org/roda_project/commons_ip/utils/IPEnums.java @@ -33,7 +33,7 @@ public static IPStatus parse(String value) { } public enum SipType { - EARK2S, EARK2 + EARK2S, EARK2, ERMS } } diff --git a/src/main/java/org/roda_project/commons_ip2/cli/Validate.java b/src/main/java/org/roda_project/commons_ip2/cli/Validate.java index 594f0e1d..f0732755 100644 --- a/src/main/java/org/roda_project/commons_ip2/cli/Validate.java +++ b/src/main/java/org/roda_project/commons_ip2/cli/Validate.java @@ -11,7 +11,7 @@ import javax.xml.parsers.ParserConfigurationException; import org.roda_project.commons_ip2.cli.model.ExitCodes; -import org.roda_project.commons_ip2.cli.model.enums.ReportType; +import org.roda_project.commons_ip2.cli.model.enums.ReportTypeEnums; import org.roda_project.commons_ip2.cli.model.exception.CLIException; import org.roda_project.commons_ip2.cli.model.exception.ValidationException; import org.roda_project.commons_ip2.cli.utils.CLI.ValidateCommandUtils; @@ -27,6 +27,9 @@ import picocli.CommandLine; +import static org.roda_project.commons_ip2.cli.model.enums.ReportTypeEnums.ReportType.COMMONS_IP; +import static org.roda_project.commons_ip2.cli.model.enums.ReportTypeEnums.ReportType.PYIP; + /** * @author Miguel Guimarães */ @@ -48,7 +51,7 @@ public class Validate implements Callable { @CommandLine.Option(names = {"-r", "--reporter-type"}, paramLabel = "", description = "Report type (possible values: ${COMPLETION-CANDIDATES})") - ReportType reportType = ReportType.COMMONS_IP; + ReportTypeEnums.ReportType reportType = COMMONS_IP; @CommandLine.Option(names = {"-v", "--verbose"}, description = "Verbose command line output with all validation steps") @@ -72,7 +75,7 @@ public Integer call() throws ValidationException, CLIException { return ExitCodes.EXIT_CODE_OK; } - private void handleSipValidation(final String sip, final String reportPathDir, final ReportType reportType, + private void handleSipValidation(final String sip, final String reportPathDir, final ReportTypeEnums.ReportType reportType, final boolean verbose) throws IOException, ParserConfigurationException, SAXException, CLIException, NoSuchAlgorithmException { final Path sipPath = Paths.get(sip); @@ -83,27 +86,25 @@ private void handleSipValidation(final String sip, final String reportPathDir, f LogSystem.logOperatingSystemInfo(); LOGGER.debug("command executed: {}", commandLineString); - switch (reportType) { - case COMMONS_IP -> { - final OutputStream outputStream = ValidateCommandUtils.createReportOutputStream(reportPath); - if (outputStream != null) { - final ValidationReportOutputJson jsonReporter = new ValidationReportOutputJson(sipPath, outputStream); - final EARKSIPValidator earksipValidator = new EARKSIPValidator(jsonReporter, version); - if (verbose) { - earksipValidator.addObserver(new ProgressValidationLoggerObserver()); - } - earksipValidator.validate(version); - } - } - case PYIP -> { - final ValidationReportOutputJSONPyIP jsonReporter = new ValidationReportOutputJSONPyIP(reportPath, sipPath); - final EARKPyIPValidator earkPyIPValidator = new EARKPyIPValidator(jsonReporter, version); + if (reportType.equals(COMMONS_IP)) { + final OutputStream outputStream = ValidateCommandUtils.createReportOutputStream(reportPath); + if (outputStream != null) { + final ValidationReportOutputJson jsonReporter = new ValidationReportOutputJson(sipPath, outputStream); + final EARKSIPValidator earksipValidator = new EARKSIPValidator(jsonReporter, version); if (verbose) { - earkPyIPValidator.addObserver(new ProgressValidationLoggerObserver()); + earksipValidator.addObserver(new ProgressValidationLoggerObserver()); } - earkPyIPValidator.validate(); + earksipValidator.validate(version); + } + } else if (reportType.equals(PYIP)) { + final ValidationReportOutputJSONPyIP jsonReporter = new ValidationReportOutputJSONPyIP(reportPath, sipPath); + final EARKPyIPValidator earkPyIPValidator = new EARKPyIPValidator(jsonReporter, version); + if (verbose) { + earkPyIPValidator.addObserver(new ProgressValidationLoggerObserver()); } - default -> throw new CLIException("Unexpected value: " + reportType); + earkPyIPValidator.validate(); + } else { + throw new CLIException("Unexpected value: " + reportType); } new CommandLine(this).getOut().printf("E-ARK SIP validation report at '%s'%n", reportPath.normalize().toAbsolutePath()); diff --git a/src/main/java/org/roda_project/commons_ip2/cli/model/enums/ReportType.java b/src/main/java/org/roda_project/commons_ip2/cli/model/enums/ReportType.java deleted file mode 100644 index 6d2fae14..00000000 --- a/src/main/java/org/roda_project/commons_ip2/cli/model/enums/ReportType.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.roda_project.commons_ip2.cli.model.enums; - -/** - * @author Miguel Guimarães - */ -public enum ReportType { - COMMONS_IP("commons-ip"), PYIP("eark-validator"); - - private final String type; - - ReportType(String type) { - this.type = type; - } - - @Override - public String toString() { - return type; - } -} diff --git a/src/main/java/org/roda_project/commons_ip2/cli/model/enums/ReportTypeEnums.java b/src/main/java/org/roda_project/commons_ip2/cli/model/enums/ReportTypeEnums.java new file mode 100644 index 00000000..6c9e80d8 --- /dev/null +++ b/src/main/java/org/roda_project/commons_ip2/cli/model/enums/ReportTypeEnums.java @@ -0,0 +1,21 @@ +package org.roda_project.commons_ip2.cli.model.enums; + +/** + * @author Miguel Guimarães + */ +public class ReportTypeEnums { + public enum ReportType { + COMMONS_IP("commons-ip"), PYIP("eark-validator"); + + private final String type; + + ReportType(String type) { + this.type = type; + } + + @Override + public String toString() { + return type; + } + } +} \ No newline at end of file diff --git a/src/main/java/org/roda_project/commons_ip2/cli/utils/SIPBuilderUtils.java b/src/main/java/org/roda_project/commons_ip2/cli/utils/SIPBuilderUtils.java index 56198bf5..79306825 100644 --- a/src/main/java/org/roda_project/commons_ip2/cli/utils/SIPBuilderUtils.java +++ b/src/main/java/org/roda_project/commons_ip2/cli/utils/SIPBuilderUtils.java @@ -91,6 +91,15 @@ private static void addRepresentationToSIP(SIP sip, final RepresentationGroup re } } + public static void addRepresentationGroupsToErmsSIP(SIP sip, final List representationGroups, + boolean targetOnly) throws IPException { + if (representationGroups != null) { + for (RepresentationGroup representationGroup : representationGroups) { + addRepresentationToSIP(sip, representationGroup, targetOnly); + } + } + } + private static void addFileToRepresentation(final IPRepresentation representation, final boolean targetOnly, final Path dataPath, final List relativePath) { if (Files.isDirectory(dataPath)) { diff --git a/src/main/java/org/roda_project/commons_ip2/model/IPContentInformationType.java b/src/main/java/org/roda_project/commons_ip2/model/IPContentInformationType.java index dad7bc89..5d14cefc 100644 --- a/src/main/java/org/roda_project/commons_ip2/model/IPContentInformationType.java +++ b/src/main/java/org/roda_project/commons_ip2/model/IPContentInformationType.java @@ -15,7 +15,7 @@ public class IPContentInformationType implements Serializable { private static final long serialVersionUID = 1191075605637022551L; public enum IPContentInformationTypeEnum { - ERMS, SIARD1, SIARD2, SIARDDK, GEODATA, MIXED, OTHER; + ERMS, citserms_v2_1, SIARD1, SIARD2, SIARDDK, GEODATA, MIXED, OTHER, Dataset; } private IPContentInformationTypeEnum type; diff --git a/src/main/java/org/roda_project/commons_ip2/model/IPContentType.java b/src/main/java/org/roda_project/commons_ip2/model/IPContentType.java index 9a16f81f..d63f7a06 100644 --- a/src/main/java/org/roda_project/commons_ip2/model/IPContentType.java +++ b/src/main/java/org/roda_project/commons_ip2/model/IPContentType.java @@ -26,7 +26,7 @@ public enum IPContentTypeEnum { AUDIO_ON_TANGIBLE_MEDIUM("Audio – On Tangible Medium (digital or analog)"), AUDIO_MEDIA_INDEPENDENT("Audio – Media-independent (digital)"), MOTION_PICTURES("Motion Pictures – Digital and Physical Media"), VIDEO("Video – File-based and Physical Media"), - SOFTWARE("Software"), DATASETS("Datasets"), GEOSPATIAL_DATA("Geospatial Data"), DATABASES("Databases"), + SOFTWARE("Software"), DATASETS("Datasets"), DATASET("Dataset"), GEOSPATIAL_DATA("Geospatial Data"), DATABASES("Databases"), WEBSITES("Websites"), COLLECTION("Collection"), EVENT("Event"), INTERACTIVE_RESOURCE("Interactive resource"), PHYSICAL_OBJECT("Physical object"), SERVICE("Service"), MIXED("Mixed"), OTHER("Other"); @@ -131,4 +131,8 @@ public String asString() { public static IPContentType getMIXED() { return new IPContentType(IPContentTypeEnum.MIXED); } + public static IPContentType getDataset() { + return new IPContentType(IPContentTypeEnum.DATASET); + } + } diff --git a/src/main/java/org/roda_project/commons_ip2/model/impl/eark/EARKSIP.java b/src/main/java/org/roda_project/commons_ip2/model/impl/eark/EARKSIP.java index 00df76a3..862492ba 100644 --- a/src/main/java/org/roda_project/commons_ip2/model/impl/eark/EARKSIP.java +++ b/src/main/java/org/roda_project/commons_ip2/model/impl/eark/EARKSIP.java @@ -147,6 +147,20 @@ public Path build(WriteStrategy writeStrategy) throws IPException, InterruptedEx return build(writeStrategy, false); } + /** + * Builds a SIP. + * + * @param destinationDirectory + * the {@link Path} where the SIP should be build. + * @param onlyManifest + * build only the manifest file? (this parameter is + * ignored). + * @return the {@link Path}. + * @throws IPException + * if some error occurs. + * @throws InterruptedException + * if some error occurs. + */ @Override public Path build(WriteStrategy writeStrategy, final boolean onlyManifest) throws IPException, InterruptedException { @@ -212,7 +226,6 @@ public Path build(WriteStrategy writeStrategy, final String fileNameWithoutExten throw e; } finally { ModelUtils.deleteBuildDir(buildDir); - notifySipBuildPackagingEnded(); } } diff --git a/src/main/java/org/roda_project/commons_ip2/model/impl/eark/EARKUtils.java b/src/main/java/org/roda_project/commons_ip2/model/impl/eark/EARKUtils.java index e61154f6..f2fb6957 100644 --- a/src/main/java/org/roda_project/commons_ip2/model/impl/eark/EARKUtils.java +++ b/src/main/java/org/roda_project/commons_ip2/model/impl/eark/EARKUtils.java @@ -162,7 +162,14 @@ protected void addRepresentationsToZipAndMETS(IPInterface ip, List zipEntries, + MetsWrapper representationMETSWrapper, IPRepresentation representation, String representationId) + throws InterruptedException, IPException { + if (representation.getData() != null && !representation.getData().isEmpty()) { + if (ip instanceof SIP sip) { + sip.notifySipBuildRepresentationProcessingStarted(representation.getData().size()); + } + int i = 0; + for (IPFileInterface file : representation.getData()) { + if (Thread.interrupted()) { + throw new InterruptedException(); + } + + if (file instanceof IPFile) { + String dataFilePath = ModelUtils.getFoldersFromList(file.getRelativeFolders()) + file.getFileName(); + FileType fileType = metsGenerator.addDataFileToMETS(representationMETSWrapper, dataFilePath, file.getPath()); + + dataFilePath = IPConstants.DATA_FOLDER + dataFilePath; + dataFilePath = IPConstants.REPRESENTATIONS_FOLDER + representationId + IPConstants.ZIP_PATH_SEPARATOR + + dataFilePath; + ZIPUtils.addFileTypeFileToZip(zipEntries, file.getPath(), dataFilePath, fileType); + } else if (file instanceof IPFileShallow shallow && (shallow.getFileLocation() != null)) { + metsGenerator.addDataFileToMETS(representationMETSWrapper, shallow); + } + + i++; + if (ip instanceof SIP sip) { + sip.notifySipBuildRepresentationProcessingCurrentStatus(i); + } + } + if (ip instanceof SIP sip) { + sip.notifySipBuildRepresentationProcessingEnded(); + } + } } protected void addRepresentationDataFilesToZipAndMETS(IPInterface ip, Map zipEntries, diff --git a/src/main/java/org/roda_project/commons_ip2/validator/common/FolderManager.java b/src/main/java/org/roda_project/commons_ip2/validator/common/FolderManager.java index a7560340..4b722763 100644 --- a/src/main/java/org/roda_project/commons_ip2/validator/common/FolderManager.java +++ b/src/main/java/org/roda_project/commons_ip2/validator/common/FolderManager.java @@ -59,6 +59,21 @@ public InputStream getMetsRootInputStream(final Path path) throws FileNotFoundEx return new FileInputStream(metsPath); } + public InputStream getErmsInputStream(final Path path) throws FileNotFoundException { + folder = path.toFile(); + String ermsPath = null; + for (File f : folder.listFiles()) { + if (f.getName().endsWith("erms.xml")) { + ermsPath = f.getPath(); + } + } + if (ermsPath == null) { + LOGGER.debug("ERMS.xml not Found"); + throw new FileNotFoundException("ERMS.xml not Found"); + } + return new FileInputStream(ermsPath); + } + public String getSipRootFolderName(final Path path) { final String[] tmp = path.toString().split("/"); return tmp[tmp.length - 1]; diff --git a/src/main/java/org/roda_project/commons_ip2/validator/common/ZipManager.java b/src/main/java/org/roda_project/commons_ip2/validator/common/ZipManager.java index 546821d1..c0d073ba 100644 --- a/src/main/java/org/roda_project/commons_ip2/validator/common/ZipManager.java +++ b/src/main/java/org/roda_project/commons_ip2/validator/common/ZipManager.java @@ -79,6 +79,38 @@ public InputStream getMetsRootInputStream(Path path) throws IOException { return zipFile.getInputStream(zipArchiveEntry); } + /** + * Get ERMS file in IP {@link InputStream}. + * + * @param path + * {@link Path} to the IP + * @return {@link InputStream} to the file. + * @throws IOException + * if some I/O error occurs + */ + public InputStream getErmsInputStream(Path path) throws IOException { + if (zipFile == null) { + zipFile = new ZipFile(path.toFile()); + } + + Enumeration entries = zipFile.entries(); + String entry = null; + while (entries.hasMoreElements()) { + ZipEntry entr = (ZipEntry) entries.nextElement(); + if (entr.getName().endsWith("erms.xml")) { + if (entr.getName().split("/").length == 4) { + entry = entr.getName(); + } + } + } + if (entry == null) { + LOGGER.debug("ERMS.xml not Found"); + throw new IOException("ERMS.xml not Found"); + } + ZipEntry zipArchiveEntry = zipFile.getEntry(entry); + return zipFile.getInputStream(zipArchiveEntry); + } + public Enumeration getEntries() { return zipFile.entries(); } diff --git a/src/main/resources/controlledVocabularies/CSIPVocabularyContentCategory.xml b/src/main/resources/controlledVocabularies/CSIPVocabularyContentCategory.xml index 71a3556d..eca57257 100644 --- a/src/main/resources/controlledVocabularies/CSIPVocabularyContentCategory.xml +++ b/src/main/resources/controlledVocabularies/CSIPVocabularyContentCategory.xml @@ -66,6 +66,10 @@ Datasets Data encoded in a defined structure. + + Dataset + Data encoded in a defined structure. + Geospatial Data