use of org.mycore.mets.model.struct.SmLink in project mycore by MyCoRe-Org.
the class MCRMETSHierarchyGenerator method createStructLink.
/**
* Creates the mets:structLink part of the mets.xml
*
* @return a newly generated StructLink.
*/
protected StructLink createStructLink() {
StructLink structLink = new StructLink();
String currentLogicalDivId = logicalStructMap.getDivContainer().getId();
PhysicalDiv physicalDiv = this.physicalStructMap.getDivContainer();
List<PhysicalSubDiv> subDivList = physicalDiv.getChildren();
for (PhysicalSubDiv physLink : subDivList) {
if (structLinkMap.containsKey(physLink.getId())) {
ArrayList<String> logicalIdList = new ArrayList<>(structLinkMap.get(physLink.getId()));
Collections.sort(logicalIdList);
for (String logicalId : logicalIdList) {
currentLogicalDivId = logicalId;
structLink.addSmLink(new SmLink(currentLogicalDivId, physLink.getId()));
}
} else {
structLink.addSmLink(new SmLink(currentLogicalDivId, physLink.getId()));
}
}
return structLink;
}
use of org.mycore.mets.model.struct.SmLink in project mycore by MyCoRe-Org.
the class MCRMetsSave method updateOnFileDelete.
/**
* @param mets
* @param file
* @return
*/
private static Document updateOnFileDelete(Document mets, MCRPath file) {
Mets modifiedMets;
try {
modifiedMets = new Mets(mets);
String href = file.getOwnerRelativePath().substring(1);
PhysicalStructMap physStructMap = (PhysicalStructMap) modifiedMets.getStructMap(PhysicalStructMap.TYPE);
PhysicalDiv divContainer = physStructMap.getDivContainer();
// search the right group and remove the file from the group
List<FileGrp> fileGroups = modifiedMets.getFileSec().getFileGroups();
for (FileGrp fileGrp : fileGroups) {
if (fileGrp.contains(href)) {
org.mycore.mets.model.files.File fileToRemove = fileGrp.getFileByHref(href);
fileGrp.removeFile(fileToRemove);
ArrayList<PhysicalSubDiv> physicalSubDivsToRemove = new ArrayList<>();
// remove file from mets:mets/mets:structMap[@TYPE='PHYSICAL']
for (PhysicalSubDiv physicalSubDiv : divContainer.getChildren()) {
ArrayList<Fptr> fptrsToRemove = new ArrayList<>();
for (Fptr fptr : physicalSubDiv.getChildren()) {
if (fptr.getFileId().equals(fileToRemove.getId())) {
if (fileGrp.getUse().equals(FileGrp.USE_MASTER)) {
physicalSubDivsToRemove.add(physicalSubDiv);
} else {
fptrsToRemove.add(fptr);
}
}
}
for (Fptr fptrToRemove : fptrsToRemove) {
LOGGER.warn(String.format(Locale.ROOT, "remove fptr \"%s\" from mets.xml of \"%s\"", fptrToRemove.getFileId(), file.getOwner()));
physicalSubDiv.remove(fptrToRemove);
}
}
for (PhysicalSubDiv physicalSubDivToRemove : physicalSubDivsToRemove) {
// remove links in mets:structLink section
List<SmLink> list = modifiedMets.getStructLink().getSmLinkByTo(physicalSubDivToRemove.getId());
LogicalStructMap logicalStructMap = (LogicalStructMap) modifiedMets.getStructMap(LogicalStructMap.TYPE);
for (SmLink linkToRemove : list) {
LOGGER.warn(String.format(Locale.ROOT, "remove smLink from \"%s\" to \"%s\"", linkToRemove.getFrom(), linkToRemove.getTo()));
modifiedMets.getStructLink().removeSmLink(linkToRemove);
// modify logical struct Map
String logID = linkToRemove.getFrom();
// the deleted file was not directly assigned to a structure
if (logicalStructMap.getDivContainer().getId().equals(logID)) {
continue;
}
LogicalDiv logicalDiv = logicalStructMap.getDivContainer().getLogicalSubDiv(logID);
if (logicalDiv == null) {
LOGGER.error("Could not find {} with id {}", LogicalDiv.class.getSimpleName(), logID);
LOGGER.error("Mets document remains unchanged");
return mets;
}
// there are still files for this logical sub div, nothing to do
if (modifiedMets.getStructLink().getSmLinkByFrom(logicalDiv.getId()).size() > 0) {
continue;
}
// the logical div has other divs included, nothing to do
if (logicalDiv.getChildren().size() > 0) {
continue;
}
/*
* the log div might be in a hierarchy of divs, which may now be empty
* (only containing empty directories), if so the parent of the log div
* must be deleted
* */
handleParents(logicalDiv, modifiedMets);
logicalStructMap.getDivContainer().remove(logicalDiv);
}
divContainer.remove(physicalSubDivToRemove);
}
}
}
} catch (Exception ex) {
LOGGER.error("Error occured while removing file {} from the existing mets file", file, ex);
return null;
}
return modifiedMets.asDocument();
}
use of org.mycore.mets.model.struct.SmLink in project mycore by MyCoRe-Org.
the class MCRMetsSave method updateOnImageFile.
private static void updateOnImageFile(Document mets, String fileId, String path) {
LOGGER.debug("FILE is a image!");
// check if custom files are present and save the ids
String[] customFileGroups = { MCRMetsFileUse.TRANSCRIPTION.toString(), MCRMetsFileUse.ALTO.toString(), MCRMetsFileUse.TRANSLATION.toString() };
// add to structMap physical
PhysicalSubDiv div = new PhysicalSubDiv(PhysicalSubDiv.ID_PREFIX + fileId, PhysicalSubDiv.TYPE_PAGE);
div.add(new Fptr(fileId));
Arrays.stream(customFileGroups).map(customFileGroup -> searchFileInGroup(mets, path, customFileGroup)).filter(Objects::nonNull).map(Fptr::new).forEach(div::add);
// actually alter the mets document
Element structMapPhys = getPhysicalStructmap(mets);
structMapPhys.addContent(div.asElement());
// add to structLink
SmLink smLink = getDefaultSmLink(mets, div);
Element structLink = getStructLink(mets);
structLink.addContent(smLink.asElement());
}
use of org.mycore.mets.model.struct.SmLink in project mycore by MyCoRe-Org.
the class MCRMETSDefaultGenerator method createStructure.
private void createStructure(MCRPath dir, FileSec fileSec, PhysicalDiv physicalDiv, LogicalDiv logicalDiv, StructLink structLink, Map.Entry<MCRPath, BasicFileAttributes> file) throws IOException {
String baseID = MCRMetsSave.getFileBase(file.getKey());
final String physicalID = "phys_" + baseID;
final String href;
String path = file.getKey().getOwnerRelativePath().substring(1);
try {
href = MCRXMLFunctions.encodeURIPath(path, true);
} catch (URISyntaxException uriSyntaxException) {
LOGGER.error("invalid href {}", path, uriSyntaxException);
return;
}
int beginIndex = href.lastIndexOf("/") == -1 ? 0 : href.lastIndexOf("/") + 1;
int endIndex = (href.lastIndexOf(".") == -1 || href.lastIndexOf(".") <= beginIndex) ? href.length() : href.lastIndexOf(".");
String fileName = href.substring(beginIndex, endIndex);
LOGGER.debug("Created fileName: {}", fileName);
if (!(hrefIdMap.containsKey(fileName) || hrefIdMap.containsValue(baseID) && isInExcludedRootFolder(dir))) {
hrefIdMap.put(fileName, baseID);
}
// files
MCRMetsFileUse fileUse = MCRMetsFileUse.get(href);
String fileID = MCRMetsFileUse.getIdPrefix(href) + "_" + baseID;
sortFileToGrp(fileSec, file, fileID, href, fileUse);
// physical
buildPhysDivs(dir, physicalDiv, fileID, physicalID, fileName);
// struct link
if (!isInExcludedRootFolder(dir)) {
SmLink smLink = new SmLink(logicalDiv.getId(), physicalID);
structLink.addSmLink(smLink);
}
}
use of org.mycore.mets.model.struct.SmLink in project mycore by MyCoRe-Org.
the class MCRMetsSave method updateFiles.
/**
* Call this method to update the mets.xml if files of the derivate have changed. Files will be added or removed
* from the mets:fileSec and mets:StructMap[@type=PHYSICAL]. The mets:structLink part will be rebuild after.
*
* <p>This method takes care of the group assignment. For example: image files will be added to the MASTER
* group and ALTO files to the ALTO group. It will also bundle files with the same name e.g. sample1.tiff and
* alto/sample1.xml to the same physical struct map div.</p>
*
* <p><b>Important:</b> This method does not update the mets.xml in the derivate, its just updating the given mets
* instance.</p>
*
* @param mets the mets to update
* @param derivatePath path to the derivate -> required for looking up new files
* @throws IOException derivate couldn't be read
*/
public static void updateFiles(Mets mets, final MCRPath derivatePath) throws IOException {
List<String> metsFiles = mets.getFileSec().getFileGroups().stream().flatMap(g -> g.getFileList().stream()).map(File::getFLocat).map(FLocat::getHref).collect(Collectors.toList());
List<String> derivateFiles = Files.walk(derivatePath).filter(MCRStreamUtils.not(Files::isDirectory)).map(MCRPath::toMCRPath).map(MCRPath::getOwnerRelativePath).map(path -> path.substring(1)).filter(href -> !"mets.xml".equals(href)).collect(Collectors.toList());
ArrayList<String> removedFiles = new ArrayList<>(metsFiles);
removedFiles.removeAll(derivateFiles);
ArrayList<String> addedFiles = new ArrayList<>(derivateFiles);
Collections.sort(addedFiles);
addedFiles.removeAll(metsFiles);
StructLink structLink = mets.getStructLink();
PhysicalStructMap physicalStructMap = mets.getPhysicalStructMap();
List<String> unlinkedLogicalIds = new ArrayList<>();
// remove files
PhysicalDiv physicalDiv = physicalStructMap.getDivContainer();
removedFiles.forEach(href -> {
File file = null;
// remove from fileSec
for (FileGrp grp : mets.getFileSec().getFileGroups()) {
file = grp.getFileByHref(href);
if (file != null) {
grp.removeFile(file);
break;
}
}
if (file == null) {
return;
}
// remove from physical
PhysicalSubDiv physicalSubDiv = physicalDiv.byFileId(file.getId());
physicalSubDiv.remove(physicalSubDiv.getFptr(file.getId()));
if (physicalSubDiv.getChildren().isEmpty()) {
physicalDiv.remove(physicalSubDiv);
}
// remove from struct link
structLink.getSmLinkByTo(physicalSubDiv.getId()).forEach(smLink -> {
structLink.removeSmLink(smLink);
if (structLink.getSmLinkByFrom(smLink.getFrom()).isEmpty()) {
unlinkedLogicalIds.add(smLink.getFrom());
}
});
});
// fix unlinked logical divs
if (!unlinkedLogicalIds.isEmpty()) {
// get first physical div
List<PhysicalSubDiv> physicalChildren = physicalStructMap.getDivContainer().getChildren();
String firstPhysicalID = physicalChildren.isEmpty() ? physicalStructMap.getDivContainer().getId() : physicalChildren.get(0).getId();
// a logical div is not linked anymore -> link with first physical div
unlinkedLogicalIds.forEach(from -> structLink.addSmLink(new SmLink(from, firstPhysicalID)));
}
// get last logical div
LogicalDiv divContainer = mets.getLogicalStructMap().getDivContainer();
List<LogicalDiv> descendants = divContainer.getDescendants();
LogicalDiv lastLogicalDiv = descendants.isEmpty() ? divContainer : descendants.get(descendants.size() - 1);
// add files
addedFiles.forEach(href -> {
MCRPath filePath = (MCRPath) derivatePath.resolve(href);
String fileBase = getFileBase(href);
try {
String fileGroupUse = MCRMetsSave.getFileGroupUse(filePath);
// build file
String mimeType = MCRContentTypes.probeContentType(filePath);
String fileId = fileGroupUse.toLowerCase(Locale.ROOT) + "_" + fileBase;
File file = new File(fileId, mimeType);
file.setFLocat(new FLocat(LOCTYPE.URL, href));
// fileSec
FileGrp fileGroup = mets.getFileSec().getFileGroup(fileGroupUse);
if (fileGroup == null) {
fileGroup = new FileGrp(fileGroupUse);
mets.getFileSec().addFileGrp(fileGroup);
}
fileGroup.addFile(file);
// structMap physical
String existingFileID = mets.getFileSec().getFileGroups().stream().filter(grp -> !grp.getUse().equals(fileGroupUse)).flatMap(grp -> grp.getFileList().stream()).filter(brotherFile -> fileBase.equals(getFileBase(brotherFile.getFLocat().getHref()))).map(File::getId).findAny().orElse(null);
PhysicalSubDiv physicalSubDiv;
if (existingFileID != null) {
// there is a file (e.g. img or alto) which the same file base -> add the file to this mets:div
physicalSubDiv = physicalDiv.byFileId(existingFileID);
physicalSubDiv.add(new Fptr(file.getId()));
} else {
// there is no mets:div with this file
physicalSubDiv = new PhysicalSubDiv(PhysicalSubDiv.ID_PREFIX + fileBase, PhysicalSubDiv.TYPE_PAGE);
physicalSubDiv.add(new Fptr(file.getId()));
physicalDiv.add(physicalSubDiv);
}
// add to struct link
structLink.addSmLink(new SmLink(lastLogicalDiv.getId(), physicalSubDiv.getId()));
} catch (Exception exc) {
LOGGER.error("Unable to add file {} to mets.xml of {}", href, derivatePath.getOwner(), exc);
}
});
}
Aggregations