From 9ccf055366b00cf59b11c84c61dceeafefeee7bf Mon Sep 17 00:00:00 2001 From: Carlos Afonso Date: Fri, 29 Nov 2024 10:58:51 +0000 Subject: [PATCH] Dependencies for CITS SIARD --- .../commons_ip/utils/IPEnums.java | 4 +- .../cli/model/enums/ReportTypeEnums.java | 2 +- .../model/IPContentInformationType.java | 2 +- .../commons_ip2/model/IPContentType.java | 4 + .../model/impl/eark/EARKMETSCreator.java | 90 +++++++++++++++++++ .../commons_ip2/model/impl/eark/EARKSIP.java | 19 ++-- .../model/impl/eark/EARKUtils.java | 63 ++++++++++++- 7 files changed, 173 insertions(+), 11 deletions(-) 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 04e8fdee..a0a4169d 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 @@ -9,7 +9,7 @@ public class IPEnums { public enum IPType { - SIP, AIP, DIP; + SIP, AIP, DIP, SIARD; } public enum IPStatus { @@ -33,7 +33,7 @@ public static IPStatus parse(String value) { } public enum SipType { - EARK2S, EARK2, ERMS + EARK2S, EARK2, SIARD, ERMS } } 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 index 6c9e80d8..5c5d7be1 100644 --- 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 @@ -5,7 +5,7 @@ */ public class ReportTypeEnums { public enum ReportType { - COMMONS_IP("commons-ip"), PYIP("eark-validator"); + COMMONS_IP("commons-ip"), PYIP("eark-validator"), SIARD("siard"); private final String type; 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 5d14cefc..30e3f9e5 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, citserms_v2_1, SIARD1, SIARD2, SIARDDK, GEODATA, MIXED, OTHER, Dataset; + ERMS, citserms_v2_1, SIARD1, SIARD2, SIARDDK, GEODATA, MIXED, OTHER, Dataset, citssiard_v1_0; } 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 d63f7a06..dff1fb96 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 @@ -135,4 +135,8 @@ public static IPContentType getDataset() { return new IPContentType(IPContentTypeEnum.DATASET); } + public static IPContentType getDatabase() { + return new IPContentType(IPContentTypeEnum.DATABASES); + } + } diff --git a/src/main/java/org/roda_project/commons_ip2/model/impl/eark/EARKMETSCreator.java b/src/main/java/org/roda_project/commons_ip2/model/impl/eark/EARKMETSCreator.java index ab6953b8..038431ef 100644 --- a/src/main/java/org/roda_project/commons_ip2/model/impl/eark/EARKMETSCreator.java +++ b/src/main/java/org/roda_project/commons_ip2/model/impl/eark/EARKMETSCreator.java @@ -11,6 +11,7 @@ import javax.xml.datatype.DatatypeConfigurationException; import javax.xml.datatype.XMLGregorianCalendar; +import javax.xml.namespace.QName; import org.apache.commons.lang3.StringUtils; import org.roda_project.commons_ip.utils.IPEnums; @@ -57,6 +58,54 @@ public abstract class EARKMETSCreator { private static final Logger LOGGER = LoggerFactory.getLogger(EARKMETSCreator.class); private final Map dataFileGrp = new HashMap<>(); + public MetsWrapper generateMetsSiard(final String id, final String label, final String profile, final boolean mainMets, + final Optional> ancestors, final Path metsPath, final IPHeader ipHeader, final String type, + final IPContentType contentType, final IPContentInformationType contentInformationType, final boolean isMetadata, + final boolean isMetadataOther, final boolean isSchemas, final boolean isDocumentation, final boolean isSubmission, + final boolean isRepresentations, final boolean isRepresentationsData) throws IPException { + final Mets mets = new Mets(); + final MetsWrapper metsWrapper = new MetsWrapper(mets, metsPath); + + // basic attributes + addBasicAttributesToMets(mets, id, label, profile, contentType, contentInformationType); + // header + + addHeaderToMets(mets, ipHeader, type); + + // administrative section + addAmdSecToMets(mets); + + // file section + + final MetsType.FileSec fileSec = createFileSec(); + + // Add data file grp + addDataFileGrpToMets(metsWrapper, fileSec, mainMets, isRepresentationsData); + + // Add schemas, documentation, submission to main div + addCommonFileGrpToMets(metsWrapper, fileSec, isSchemas, isSubmission, isDocumentation, type); + + if ((mainMets && isRepresentations) || !fileSec.getFileGrp().isEmpty()) { + mets.setFileSec(fileSec); + } + + // E-ARK struct map + final StructMapType structMap = createStructMap(); + + final DivType mainDiv = addCommonDivsToMainDiv(metsWrapper, id, isMetadata, isMetadataOther, isSchemas, + isDocumentation, isSubmission, type); + + // data div + addDataDivToMets(metsWrapper, mainDiv, mainMets, isRepresentationsData); + + structMap.setDiv(mainDiv); + mets.getStructMap().add(structMap); + + addAncestorsToMets(mets, ancestors); + + return metsWrapper; + } + public MetsWrapper generateMETS(final String id, final String label, final String profile, final boolean mainMets, final Optional> ancestors, final Path metsPath, final IPHeader ipHeader, final String type, final IPContentType contentType, final IPContentInformationType contentInformationType, final boolean isMetadata, @@ -251,6 +300,47 @@ public void addRepresentationMETSToZipAndToMainMETS(final Map zipEntries, + final MetsWrapper mainMETSWrapper, final String representationId, final MetsWrapper representationMETSWrapper, + final String representationMetsPath, final Path buildDir) throws IPException, InterruptedException { + try { + if (Thread.interrupted()) { + throw new InterruptedException(); + } + + // create mets pointer + final DivType.Mptr mptr = new DivType.Mptr(); + mptr.setLOCTYPE(METSEnums.LocType.URL.toString()); + mptr.setType(IPConstants.METS_TYPE_SIMPLE); + mptr.setHref(METSUtils.encodeHref(representationMetsPath)); + + + // create file + final FileType fileType = new FileType(); + fileType.setID(Utils.generateRandomAndPrefixedFileID()); + + addMETSToZip(zipEntries, representationMETSWrapper, representationMetsPath, buildDir, false, fileType); + + // add to file group and then to file section + final MetsType.FileSec.FileGrp fileGrp = createFileGroup( + IPConstants.REPRESENTATIONS_WITH_FIRST_LETTER_CAPITAL + "/" + representationId); + final FileType.FLocat fileLocation = METSUtils.createFileLocation(representationMetsPath); + fileType.getFLocat().add(fileLocation); + fileGrp.getFile().add(fileType); + fileGrp.getOtherAttributes().put(QName.valueOf("csip:CONTENTINFORMATIONTYPE"), "citssiard_v1_0"); + fileGrp.getOtherAttributes().put(QName.valueOf("csip:OTHERCONTENTINFORMATIONTYPE"), mainMETSWrapper.getMets().getOTHERCONTENTINFORMATIONTYPE()); + + mainMETSWrapper.getMets().getFileSec().getFileGrp().add(fileGrp); + + // set mets pointer + final DivType representationDiv = createRepresentationDivForStructMap(representationId, mptr); + mptr.setTitle(fileGrp.getID()); + mainMETSWrapper.getMainDiv().getDiv().add(representationDiv); + } catch (JAXBException | IOException e) { + throw new IPException("Error saving representation METS", e); + } + } + protected void addMETSToZip(final Map zipEntries, final MetsWrapper metsWrapper, final String metsPath, final Path buildDir, final boolean mainMets, final FileType fileType) throws JAXBException, IOException, IPException { 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 862492ba..62f9a94f 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 @@ -204,12 +204,19 @@ public Path build(WriteStrategy writeStrategy, final String fileNameWithoutExten boolean isDocumentation = (this.getDocumentation() != null && !this.getDocumentation().isEmpty()); boolean isSchemas = (this.getSchemas() != null && !this.getSchemas().isEmpty()); boolean isRepresentations = (this.getRepresentations() != null && !this.getRepresentations().isEmpty()); - - MetsWrapper mainMETSWrapper = metsCreator.generateMETS(StringUtils.join(this.getIds(), " "), - this.getDescription(), this.getProfile(), true, Optional.ofNullable(this.getAncestors()), null, - this.getHeader(), this.getType(), this.getContentType(), this.getContentInformationType(), isMetadata, - isMetadataOther, isSchemas, isDocumentation, false, isRepresentations, false); - + MetsWrapper mainMETSWrapper; + + if (this.getType().equals("SIARD")) { + mainMETSWrapper = metsCreator.generateMetsSiard(StringUtils.join(this.getIds(), " "), this.getDescription(), + this.getProfile(), true, Optional.ofNullable(this.getAncestors()), null, this.getHeader(), this.getType(), + this.getContentType(), this.getContentInformationType(), isMetadata, isMetadataOther, isSchemas, + isDocumentation, false, isRepresentations, false); + } else { + mainMETSWrapper = metsCreator.generateMETS(StringUtils.join(this.getIds(), " "), this.getDescription(), + this.getProfile(), true, Optional.ofNullable(this.getAncestors()), null, this.getHeader(), this.getType(), + this.getContentType(), this.getContentInformationType(), isMetadata, isMetadataOther, isSchemas, + isDocumentation, false, isRepresentations, false); + } earkUtils.addDescriptiveMetadataToZipAndMETS(zipEntries, mainMETSWrapper, getDescriptiveMetadata(), null); earkUtils.addPreservationMetadataToZipAndMETS(zipEntries, mainMETSWrapper, getPreservationMetadata(), null); earkUtils.addOtherMetadataToZipAndMETS(zipEntries, mainMETSWrapper, getOtherMetadata(), null); 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 f2fb6957..e4a94957 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 @@ -62,6 +62,8 @@ import jakarta.xml.bind.JAXBException; +import javax.xml.namespace.QName; + public class EARKUtils { private EARKMETSCreator metsGenerator; @@ -169,7 +171,16 @@ 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()); + if (representation.getContentInformationType().getOtherType() != null) { + fileType.getOtherAttributes().put(QName.valueOf("csip:OTHERCONTENTINFORMATIONTYPE"), + representation.getContentInformationType().getOtherType()); + } + 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,