All Downloads are FREE. Search and download functionalities are using the official Maven repository.

info.freelibrary.pairtree.fs.FsPairtree Maven / Gradle / Ivy


package info.freelibrary.pairtree.fs;

import static info.freelibrary.pairtree.Constants.BUNDLE_NAME;

import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

import info.freelibrary.pairtree.AbstractPairtree;
import info.freelibrary.pairtree.MessageCodes;
import info.freelibrary.pairtree.PairtreeException;
import info.freelibrary.pairtree.PairtreeObject;
import info.freelibrary.util.Logger;
import info.freelibrary.util.LoggerFactory;
import info.freelibrary.util.StringUtils;

import io.vertx.core.AsyncResult;
import io.vertx.core.Future;
import io.vertx.core.Handler;
import io.vertx.core.Vertx;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.file.FileSystem;

/**
 * A file-system backed Pairtree implementation.
 */
public class FsPairtree extends AbstractPairtree {

    /** A logger for the file-system based Pairtree implementation */
    private static final Logger LOGGER = LoggerFactory.getLogger(FsPairtree.class, BUNDLE_NAME);

    /** The underlying file system */
    private final FileSystem myFileSystem;

    /** File system location of Pairtree root */
    private final String myPath;

    /**
     * Creates a file system backed Pairtree in the supplied directory.
     *
     * @param aVertx A VertX object
     * @param aDirPath The directory in which to put the Pairtree
     */
    public FsPairtree(final Vertx aVertx, final String aDirPath) {
        this(null, aVertx, aDirPath);
    }

    /**
     * Creates a file system backed Pairtree, using the supplied Pairtree prefix, in the supplied directory.
     *
     * @param aVertx A VertX object
     * @param aDirPath The directory in which to put the Pairtree
     * @param aPairtreePrefix The Pairtree's prefix
     */
    public FsPairtree(final String aPairtreePrefix, final Vertx aVertx, final String aDirPath) {
        Objects.requireNonNull(aVertx);
        Objects.requireNonNull(aDirPath);

        myPath = Paths.get(aDirPath, PAIRTREE_ROOT).toString();
        myFileSystem = aVertx.fileSystem();

        if (aPairtreePrefix == null) {
            myPrefix = Optional.empty();
            LOGGER.debug(MessageCodes.PT_DEBUG_001, aDirPath);
        } else {
            myPrefix = Optional.of(aPairtreePrefix);
            LOGGER.debug(MessageCodes.PT_DEBUG_002, aDirPath, aPairtreePrefix);
        }
    }

    @Override
    public PairtreeObject getObject(final String aID) {
        return new FsPairtreeObject(myFileSystem, this, aID);
    }

    @Override
    public List getObjects(final List aIDList) {
        final List ptObjList = new ArrayList<>();
        final Iterator iterator = aIDList.iterator();

        while (iterator.hasNext()) {
            final String id = iterator.next();

            Objects.requireNonNull(StringUtils.trimToNull(id));
            ptObjList.add(new FsPairtreeObject(myFileSystem, this, id));
        }

        return ptObjList;
    }

    @Override
    public void exists(final Handler> aHandler) {
        Objects.requireNonNull(aHandler, LOGGER.getMessage(MessageCodes.PT_010));

        final Future future = Future.future().setHandler(aHandler);

        myFileSystem.exists(myPath, result -> {
            if (result.succeeded()) {
                if (result.result()) {
                    checkVersion(future);
                } else {
                    future.complete(result.result());
                }
            } else {
                future.fail(result.cause());
            }
        });
    }

    @Override
    public void create(final Handler> aHandler) {
        Objects.requireNonNull(aHandler, LOGGER.getMessage(MessageCodes.PT_010));

        final Future future = Future.future().setHandler(aHandler);

        LOGGER.debug(MessageCodes.PT_DEBUG_004, myPath);

        myFileSystem.mkdirs(myPath, result -> {
            if (result.succeeded()) {
                setVersion(future);
            } else {
                future.fail(result.cause());
            }
        });
    }

    @Override
    public void delete(final Handler> aHandler) {
        Objects.requireNonNull(aHandler, LOGGER.getMessage(MessageCodes.PT_010));

        final Future future = Future.future().setHandler(aHandler);

        LOGGER.debug(MessageCodes.PT_DEBUG_003, myPath);

        myFileSystem.deleteRecursive(myPath, true, result -> {
            if (result.succeeded()) {
                deleteVersion(future);
            } else {
                future.fail(result.cause());
            }
        });
    }

    @Override
    public String getPrefixFilePath() {
        final String parent = Paths.get(myPath).getParent().toString();
        return Paths.get(parent, getPrefixFileName()).toString();
    }

    @Override
    public String getVersionFilePath() {
        final String parent = Paths.get(myPath).getParent().toString();
        return Paths.get(parent, getVersionFileName()).toString();
    }

    @Override
    public String toString() {
        return myPath;
    }

    @Override
    public String getPath() {
        return myPath;
    }

    /**
     * Checks that Pairtree version file exists.
     *
     * @param aFuture The result of an action that may, or may not, have occurred yet.
     */
    private void checkVersion(final Future aFuture) {
        final String versionFilePath = getVersionFilePath();

        myFileSystem.exists(versionFilePath, result -> {
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug(MessageCodes.PT_DEBUG_007, versionFilePath);
            }

            if (result.succeeded()) {
                if (result.result()) {
                    if (LOGGER.isDebugEnabled()) {
                        LOGGER.debug(MessageCodes.PT_DEBUG_008, versionFilePath);
                    }

                    checkPrefix(aFuture);
                } else {
                    aFuture.complete(!result.result());
                }
            } else {
                aFuture.fail(result.cause());
            }
        });
    }

    /**
     * Checks whether a Pairtree prefix file exists.
     *
     * @param aFuture The result of an action that may, or may not, have occurred yet.
     */
    private void checkPrefix(final Future aFuture) {
        final String prefixFilePath = getPrefixFilePath();

        myFileSystem.exists(prefixFilePath, result -> {
            if (result.succeeded()) {
                if (hasPrefix()) {
                    if (LOGGER.isDebugEnabled()) {
                        LOGGER.debug(MessageCodes.PT_DEBUG_035, prefixFilePath);
                    }

                    if (result.result()) {
                        aFuture.complete(result.result());
                    } else {
                        aFuture.fail(new PairtreeException(MessageCodes.PT_013, prefixFilePath));
                    }
                } else {
                    LOGGER.debug(MessageCodes.PT_DEBUG_009, prefixFilePath);

                    if (result.result()) {
                        aFuture.fail(new PairtreeException(MessageCodes.PT_014, prefixFilePath));
                    } else {
                        aFuture.complete(!result.result());
                    }
                }
            } else {
                aFuture.fail(result.cause());
            }
        });
    }

    /**
     * Deletes a Pairtree version file.
     *
     * @param aFuture The result of an action that may, or may not, have occurred yet.
     */
    private void deleteVersion(final Future aFuture) {
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug(MessageCodes.PT_DEBUG_006, myPath);
        }

        myFileSystem.delete(getVersionFilePath(), result -> {
            if (result.succeeded()) {
                if (hasPrefix()) {
                    deletePrefix(aFuture);
                } else {
                    aFuture.complete();
                }
            } else {
                aFuture.fail(result.cause());
            }
        });
    }

    /**
     * Deletes a Pairtree prefix file.
     *
     * @param aFuture The result of an action that may, or may not, have occurred yet.
     */
    private void deletePrefix(final Future aFuture) {
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug(MessageCodes.PT_DEBUG_034, myPath);
        }

        myFileSystem.delete(getPrefixFilePath(), result -> {
            if (result.succeeded()) {
                aFuture.complete();
            } else {
                aFuture.fail(result.cause());
            }
        });
    }

    /**
     * Creates a Pairtree version file.
     *
     * @param aFuture The result of an action that may, or may not, have occurred yet.
     */
    private void setVersion(final Future aFuture) {
        final StringBuilder specNote = new StringBuilder();
        final String ptVersion = LOGGER.getMessage(MessageCodes.PT_011, PT_VERSION_NUM);
        final String urlString = LOGGER.getMessage(MessageCodes.PT_012);

        specNote.append(ptVersion).append(System.lineSeparator()).append(urlString);

        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug(MessageCodes.PT_DEBUG_005, myPath);
        }

        myFileSystem.writeFile(getVersionFilePath(), Buffer.buffer(specNote.toString()), result -> {
            if (result.succeeded()) {
                if (hasPrefix()) {
                    setPrefix(aFuture);
                } else {
                    aFuture.complete();
                }
            } else {
                aFuture.fail(result.cause());
            }
        });
    }

    /**
     * Creates a Pairtree prefix file.
     *
     * @param aFuture The result of an action that may, or may not, have occurred yet.
     */
    private void setPrefix(final Future aFuture) {
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug(MessageCodes.PT_DEBUG_033, myPath);
        }

        myFileSystem.writeFile(getPrefixFilePath(), Buffer.buffer(myPrefix.get()), result -> {
            if (result.succeeded()) {
                aFuture.complete();
            } else {
                aFuture.fail(result.cause());
            }
        });
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy