Skip to content

Commit

Permalink
MCR-3126 improve ocfl
Browse files Browse the repository at this point in the history
* unify ocfl version handling
* rm transaction folder on startup
* add javadoc and more test cases
  • Loading branch information
Mewel committed Oct 24, 2024
1 parent bc747ae commit 4f561ce
Show file tree
Hide file tree
Showing 12 changed files with 236 additions and 117 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,19 @@

package org.mycore.ocfl.classification;

import io.ocfl.api.OcflOption;
import io.ocfl.api.OcflRepository;
import io.ocfl.api.exception.NotFoundException;
import io.ocfl.api.exception.ObjectOutOfSyncException;
import io.ocfl.api.model.ObjectVersionId;
import io.ocfl.api.model.VersionInfo;
import static org.mycore.ocfl.util.MCROCFLVersionHelper.MESSAGE_CREATED;
import static org.mycore.ocfl.util.MCROCFLVersionHelper.MESSAGE_DELETED;
import static org.mycore.ocfl.util.MCROCFLVersionHelper.MESSAGE_UPDATED;
import static org.mycore.ocfl.util.MCROCFLVersionHelper.convertMessageToType;

import java.io.IOException;
import java.io.InputStream;
import java.time.ZoneOffset;
import java.util.Date;
import java.util.Objects;

import org.jdom2.Document;
import org.jdom2.JDOMException;
import org.mycore.common.MCRPersistenceException;
import org.mycore.common.MCRUsageException;
import org.mycore.common.config.annotation.MCRProperty;
import org.mycore.common.content.MCRContent;
Expand All @@ -39,43 +43,24 @@
import org.mycore.ocfl.util.MCROCFLMetadataVersion;
import org.mycore.ocfl.util.MCROCFLObjectIDPrefixHelper;

import java.io.IOException;
import java.io.InputStream;
import java.time.ZoneOffset;
import java.util.Date;
import java.util.Map;
import java.util.Objects;
import io.ocfl.api.OcflOption;
import io.ocfl.api.OcflRepository;
import io.ocfl.api.exception.NotFoundException;
import io.ocfl.api.exception.ObjectOutOfSyncException;
import io.ocfl.api.model.ObjectVersionId;
import io.ocfl.api.model.VersionInfo;

/**
* OCFL File Manager for MyCoRe Classifications
* @author Tobias Lenhardt [Hammer1279]
*/
public class MCROCFLXMLClassificationManager implements MCRXMLClassificationManager {

public static final String MESSAGE_CREATED = "Created";

public static final String MESSAGE_UPDATED = "Updated";

public static final String MESSAGE_DELETED = "Deleted";

private static final String ROOT_FOLDER = "classification/";

@MCRProperty(name = "Repository")
public String repositoryKey;

// FIXME make seperate versionhelper
protected static final Map<String, Character> MESSAGE_TYPE_MAPPING = Map.ofEntries(
Map.entry(MESSAGE_CREATED, MCROCFLMetadataVersion.CREATED),
Map.entry(MESSAGE_UPDATED, MCROCFLMetadataVersion.UPDATED),
Map.entry(MESSAGE_DELETED, MCROCFLMetadataVersion.DELETED));

protected static char convertMessageToType(String message) throws MCRPersistenceException {
if (!MESSAGE_TYPE_MAPPING.containsKey(message)) {
throw new MCRPersistenceException("Cannot identify version type from message '" + message + "'");
}
return MESSAGE_TYPE_MAPPING.get(message);
}

protected OcflRepository getRepository() throws ClassCastException {
return MCROCFLRepositoryProvider.getRepository(repositoryKey);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

package org.mycore.ocfl.commands;

import static org.mycore.ocfl.util.MCROCFLVersionHelper.MESSAGE_DELETED;

import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
Expand Down Expand Up @@ -399,7 +401,7 @@ public static void purgeMarkedClasses() throws IOException {
repository.listObjectIds()
.filter(obj -> obj.startsWith(MCROCFLObjectIDPrefixHelper.CLASSIFICATION))
.filter(obj -> Objects.equals(repository.describeObject(obj).getHeadVersion().getVersionInfo().getMessage(),
MCROCFLXMLClassificationManager.MESSAGE_DELETED))
MESSAGE_DELETED))
.map(obj -> obj.replace(MCROCFLObjectIDPrefixHelper.CLASSIFICATION, ""))
.forEach(cId -> manager.purge(MCRCategoryID.fromString(cId)));
confirmPurgeMarked = false;
Expand All @@ -422,7 +424,7 @@ public static void purgeMarkedUsers() throws IOException {
repository.listObjectIds()
.filter(obj -> obj.startsWith(MCROCFLObjectIDPrefixHelper.USER))
.filter(obj -> Objects.equals(repository.describeObject(obj).getHeadVersion().getVersionInfo().getMessage(),
MCROCFLXMLUserManager.MESSAGE_DELETED))
MESSAGE_DELETED))
.map(obj -> obj.replace(MCROCFLObjectIDPrefixHelper.USER, ""))
.forEach(u -> new MCROCFLXMLUserManager().purgeUser(u));
confirmPurgeMarked = false;
Expand Down Expand Up @@ -522,7 +524,7 @@ private static List<String> getStaleOCFLClassificationIDs() {
.filter(obj -> obj.startsWith(MCROCFLObjectIDPrefixHelper.CLASSIFICATION))
.filter(
obj -> !Objects.equals(repository.describeObject(obj).getHeadVersion().getVersionInfo().getMessage(),
MCROCFLXMLClassificationManager.MESSAGE_DELETED))
MESSAGE_DELETED))
.map(obj -> obj.replace(MCROCFLObjectIDPrefixHelper.CLASSIFICATION, ""))
.filter(Predicate.not(classDAOList::contains))
.collect(Collectors.toList());
Expand All @@ -538,7 +540,7 @@ private static List<String> getStaleOCFLUserIDs() {
.filter(obj -> obj.startsWith(MCROCFLObjectIDPrefixHelper.USER))
.filter(
obj -> !Objects.equals(repository.describeObject(obj).getHeadVersion().getVersionInfo().getMessage(),
MCROCFLXMLUserManager.MESSAGE_DELETED))
MESSAGE_DELETED))
.map(obj -> obj.replace(MCROCFLObjectIDPrefixHelper.USER, ""))
.filter(Predicate.not(userEMList::contains))
.collect(Collectors.toList());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,26 @@

package org.mycore.ocfl.commands;

import io.ocfl.api.OcflRepository;
import static org.mycore.ocfl.util.MCROCFLVersionHelper.MESSAGE_DELETED;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.mycore.common.config.MCRConfiguration2;
import org.mycore.datamodel.metadata.MCRObjectID;
import org.mycore.frontend.cli.annotation.MCRCommand;
import org.mycore.frontend.cli.annotation.MCRCommandGroup;
import org.mycore.ocfl.classification.MCROCFLXMLClassificationManager;
import org.mycore.ocfl.metadata.MCROCFLXMLMetadataManager;
import org.mycore.ocfl.repository.MCROCFLRepositoryProvider;
import org.mycore.ocfl.user.MCROCFLXMLUserManager;
import org.mycore.ocfl.util.MCROCFLObjectIDPrefixHelper;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import io.ocfl.api.OcflRepository;

/**
* All OCFL commands utilizing RegEx for bulk operations
Expand Down Expand Up @@ -218,7 +219,7 @@ public static List<String> purgeMarkedMatchClass(String regex) {
return repository.listObjectIds()
.filter(obj -> obj.startsWith(MCROCFLObjectIDPrefixHelper.CLASSIFICATION))
.filter(obj -> Objects.equals(repository.describeObject(obj).getHeadVersion().getVersionInfo().getMessage(),
MCROCFLXMLClassificationManager.MESSAGE_DELETED))
MESSAGE_DELETED))
.map(obj -> obj.replace(MCROCFLObjectIDPrefixHelper.CLASSIFICATION, ""))
.filter(obj -> obj.matches(regex))
.map(id -> "purge classification " + id + " from ocfl")
Expand All @@ -232,7 +233,7 @@ public static List<String> purgeMarkedMatchUsr(String regex) {
return repository.listObjectIds()
.filter(obj -> obj.startsWith(MCROCFLObjectIDPrefixHelper.USER))
.filter(obj -> Objects.equals(repository.describeObject(obj).getHeadVersion().getVersionInfo().getMessage(),
MCROCFLXMLUserManager.MESSAGE_DELETED))
MESSAGE_DELETED))
.map(obj -> obj.replace(MCROCFLObjectIDPrefixHelper.USER, ""))
.filter(obj -> obj.matches(regex))
.map(id -> "purge user " + id + " from ocfl")
Expand Down Expand Up @@ -290,7 +291,7 @@ public static List<String> restoreMatchClass(String regex) {
return repository.listObjectIds()
.filter(obj -> obj.startsWith(MCROCFLObjectIDPrefixHelper.CLASSIFICATION))
.filter(obj -> Objects.equals(repository.describeObject(obj).getHeadVersion().getVersionInfo().getMessage(),
MCROCFLXMLClassificationManager.MESSAGE_DELETED))
MESSAGE_DELETED))
.map(obj -> obj.replace(MCROCFLObjectIDPrefixHelper.CLASSIFICATION, ""))
.filter(obj -> obj.matches(regex))
.map(id -> "restore classification " + id + " from ocfl with version v"
Expand All @@ -306,7 +307,7 @@ public static List<String> restoreMatchUsr(String regex) {
return repository.listObjectIds()
.filter(obj -> obj.startsWith(MCROCFLObjectIDPrefixHelper.USER))
.filter(obj -> Objects.equals(repository.describeObject(obj).getHeadVersion().getVersionInfo().getMessage(),
MCROCFLXMLUserManager.MESSAGE_DELETED))
MESSAGE_DELETED))
.map(obj -> obj.replace(MCROCFLObjectIDPrefixHelper.USER, ""))
.filter(obj -> obj.matches(regex))
.map(id -> "restore user " + id + " from ocfl with version v"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,30 @@

package org.mycore.ocfl.metadata;

import io.ocfl.api.OcflOption;
import io.ocfl.api.OcflRepository;
import io.ocfl.api.exception.NotFoundException;
import io.ocfl.api.exception.OverwriteException;
import io.ocfl.api.model.ObjectVersionId;
import io.ocfl.api.model.OcflObjectVersion;
import io.ocfl.api.model.VersionDetails;
import io.ocfl.api.model.VersionInfo;
import io.ocfl.api.model.VersionNum;
import io.ocfl.core.extension.OcflExtensionConfig;
import io.ocfl.core.extension.storage.layout.HashedNTupleIdEncapsulationLayoutExtension;
import io.ocfl.core.extension.storage.layout.config.HashedNTupleIdEncapsulationLayoutConfig;
import static org.mycore.ocfl.util.MCROCFLVersionHelper.MESSAGE_CREATED;
import static org.mycore.ocfl.util.MCROCFLVersionHelper.MESSAGE_DELETED;
import static org.mycore.ocfl.util.MCROCFLVersionHelper.MESSAGE_UPDATED;
import static org.mycore.ocfl.util.MCROCFLVersionHelper.convertMessageToType;

import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.ZoneOffset;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

import org.jdom2.Document;
import org.jdom2.JDOMException;
import org.mycore.common.MCRCache;
Expand Down Expand Up @@ -57,52 +69,27 @@
import org.mycore.ocfl.util.MCROCFLMetadataVersion;
import org.mycore.ocfl.util.MCROCFLObjectIDPrefixHelper;

import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.ZoneOffset;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import io.ocfl.api.OcflOption;
import io.ocfl.api.OcflRepository;
import io.ocfl.api.exception.NotFoundException;
import io.ocfl.api.exception.OverwriteException;
import io.ocfl.api.model.ObjectVersionId;
import io.ocfl.api.model.OcflObjectVersion;
import io.ocfl.api.model.VersionDetails;
import io.ocfl.api.model.VersionInfo;
import io.ocfl.api.model.VersionNum;
import io.ocfl.core.extension.OcflExtensionConfig;
import io.ocfl.core.extension.storage.layout.HashedNTupleIdEncapsulationLayoutExtension;
import io.ocfl.core.extension.storage.layout.config.HashedNTupleIdEncapsulationLayoutConfig;

/**
* Manages persistence of MCRObject and MCRDerivate xml metadata. Provides
* methods to create, retrieve, update and delete object metadata using OCFL
*/
public class MCROCFLXMLMetadataManager implements MCRXMLMetadataManagerAdapter {

private static final String MESSAGE_CREATED = "Created";

private static final String MESSAGE_UPDATED = "Updated";

private static final String MESSAGE_DELETED = "Deleted";

private static final Map<String, Character> MESSAGE_TYPE_MAPPING = Collections.unmodifiableMap(Map.ofEntries(
Map.entry(MESSAGE_CREATED, MCROCFLMetadataVersion.CREATED),
Map.entry(MESSAGE_UPDATED, MCROCFLMetadataVersion.UPDATED),
Map.entry(MESSAGE_DELETED, MCROCFLMetadataVersion.DELETED)));

private String repositoryKey = "Default";

private static char convertMessageToType(String message) throws MCRPersistenceException {
if (!MESSAGE_TYPE_MAPPING.containsKey(message)) {
throw new MCRPersistenceException("Cannot identify version type from message '" + message + "'");
}
return MESSAGE_TYPE_MAPPING.get(message);
}

public OcflRepository getRepository() {
return MCROCFLRepositoryProvider.getRepository(getRepositoryKey());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ void init() throws IOException {
this.localStorage = MCRConfiguration2
.getSingleInstanceOfOrThrow(MCROCFLTransactionalTempFileStorage.class, tempFileClassProperty);
Files.createDirectories(this.localStorage.getRoot());
this.localStorage.clearTransactional();
boolean remote = MCRConfiguration2.getBoolean(configurationPrefix + "FS.Remote")
.orElseThrow(() -> MCRConfiguration2.createConfigurationException(configurationPrefix + "FS.Remote"));
this.virtualObjectProvider
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,16 @@ public boolean exists(P path) {
return findPath(path) != null;
}

// TODO javadoc & junit tests
/**
* Checks if a path has been newly added to the tracker.
* <p>
* A path is considered added if it exists in the current state of the tracker but
* was not part of the original tracked paths.
* </p>
*
* @param path the path to check.
* @return {@code true} if the path was added, {@code false} otherwise.
*/
public boolean isAdded(P path) {
boolean existsNow = exists(path);
boolean existsInOriginal = this.originalPaths.containsKey(path);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@

package org.mycore.ocfl.niofs;

import static org.mycore.ocfl.util.MCROCFLVersionHelper.MESSAGE_CREATED;
import static org.mycore.ocfl.util.MCROCFLVersionHelper.MESSAGE_UPDATED;

import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
Expand Down Expand Up @@ -848,8 +851,7 @@ public boolean persist() throws IOException {
return true;
}
// persist
// TODO org.mycore.ocfl.metadata.MCROCFLXMLMetadataManager#MESSAGE_CREATED
String type = this.objectVersion == null ? "Created" : "Updated";
String type = this.objectVersion == null ? MESSAGE_CREATED : MESSAGE_UPDATED;
AtomicBoolean updatedFiles = new AtomicBoolean(false);
AtomicBoolean updatedDirectories = new AtomicBoolean(false);
// TODO property?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,14 @@ public void clear() throws IOException {
FileUtils.deleteDirectory(getRoot().toFile());
}

/**
* {@inheritDoc}
*/
@Override
public void clearTransactional() throws IOException {
this.transactionalStorage.clearTransactional();
}

/**
* {@inheritDoc}
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
package org.mycore.ocfl.niofs.storage;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;

import org.apache.commons.io.FileUtils;
Expand Down Expand Up @@ -51,4 +52,16 @@ default Path toPhysicalPath(MCROCFLFileSystemTransaction transaction) {
return this.getRoot().resolve(transaction.getId().toString());
}

/**
* Clears the transactional directory.
*
* @throws IOException if an I/O error occurs during the purge.
*/
default void clearTransactional() throws IOException {
Path root = getRoot();
if (Files.isDirectory(root)) {
FileUtils.cleanDirectory(root.toFile());
}
}

}
Loading

0 comments on commit 4f561ce

Please sign in to comment.