org.codice.ddf.configuration.migration.ImportMigrationPropertyReferencedEntryImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.codice.ddf.configuration.migration.ImportMigrationPropertyReferencedEntryImpl.java

Source

/**
 * Copyright (c) Codice Foundation
 *
 * <p>This is free software: you can redistribute it and/or modify it under the terms of the GNU
 * Lesser General Public License as published by the Free Software Foundation, either version 3 of
 * the License, or any later version.
 *
 * <p>This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details. A copy of the GNU Lesser General Public
 * License is distributed along with this program and can be found at
 * <http://www.gnu.org/licenses/lgpl.html>.
 */
package org.codice.ddf.configuration.migration;

import com.google.common.annotations.VisibleForTesting;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.PathMatcher;
import java.util.Map;
import java.util.Optional;
import javax.annotation.Nullable;
import org.apache.commons.lang.Validate;
import org.codice.ddf.migration.ImportMigrationEntry;
import org.codice.ddf.migration.MigrationEntry;
import org.codice.ddf.migration.MigrationException;
import org.codice.ddf.migration.MigrationReport;
import org.codice.ddf.util.function.BiThrowingConsumer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Defines a migration entry representing a property which value references another migration entry.
 */
public abstract class ImportMigrationPropertyReferencedEntryImpl extends ImportMigrationEntryImpl {

    private static final Logger LOGGER = LoggerFactory.getLogger(ImportMigrationPropertyReferencedEntryImpl.class);

    private final String property;

    private final ImportMigrationEntryImpl referenced;

    private volatile boolean verifierRegistered = false;

    ImportMigrationPropertyReferencedEntryImpl(ImportMigrationContextImpl context, Map<String, Object> metadata) {
        super(context, JsonUtils.getStringFrom(metadata, MigrationEntryImpl.METADATA_REFERENCE, true), true);
        this.property = JsonUtils.getStringFrom(metadata, MigrationEntryImpl.METADATA_PROPERTY, true);
        this.referenced = context.getOptionalEntry(getPath())
                .orElseThrow(() -> new MigrationException(Messages.IMPORT_METADATA_FORMAT_ERROR,
                        "referenced path [" + getName() + "] is missing"));
    }

    @Override
    public long getLastModifiedTime() {
        return referenced.getLastModifiedTime();
    }

    @Override
    public boolean isFile() {
        return referenced.isFile();
    }

    @Override
    public boolean isDirectory() {
        return referenced.isDirectory();
    }

    @Override
    public boolean restore(boolean required) {
        if (restored == null) {
            super.restored = false; // until proven otherwise in case next line throws exception
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("Importing {}{}...", (required ? "required " : ""), toDebugString());
            }
            if (referenced.restore(required)) {
                super.restored = true;
                verifyPropertyAfterCompletionOnce();
            }
        }
        return restored;
    }

    @Override
    public boolean restore(boolean required, PathMatcher filter) {
        Validate.notNull(filter, "invalid null path filter");
        if (restored == null) {
            super.restored = false; // until proven otherwise
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("Importing {}{} with path filter...", (required ? "required " : ""), toDebugString());
            }
            if (referenced.restore(required, filter)) {
                super.restored = true;
                // don't bother verifying if the filter didn't match!
                if (required || filter.matches(referenced.getPath())) {
                    verifyPropertyAfterCompletionOnce();
                }
            }
        }
        return restored;
    }

    @Override
    public boolean restore(BiThrowingConsumer<MigrationReport, Optional<InputStream>, IOException> consumer) {
        Validate.notNull(consumer, "invalid null consumer");
        if (restored == null) {
            super.restored = false; // until proven otherwise in case next line throws exception
            if (referenced.restore(consumer)) {
                super.restored = true;
                verifyPropertyAfterCompletionOnce();
            }
        }
        return restored;
    }

    @Override
    public Optional<ImportMigrationEntry> getPropertyReferencedEntry(String name) {
        return referenced.getPropertyReferencedEntry(name);
    }

    @Override
    public int hashCode() {
        return 31 * super.hashCode() + property.hashCode();
    }

    @Override
    public boolean equals(@Nullable Object o) {
        if (o == this) {
            return true;
        } else if (!super.equals(o)) {
            return false;
        } // else - they would be at least of the same class
        final ImportMigrationPropertyReferencedEntryImpl me = (ImportMigrationPropertyReferencedEntryImpl) o;

        return property.equals(me.getProperty());
    }

    @SuppressWarnings("squid:S2259" /* super.compareTo() will never return 0 if null is passed */)
    @Override
    public int compareTo(@Nullable MigrationEntry me) {
        if (me == this) {
            return 0;
        }
        final int c = super.compareTo(me);

        if (c != 0) {
            return c;
        } // else they would be at least of the same class
        final ImportMigrationPropertyReferencedEntryImpl ime = (ImportMigrationPropertyReferencedEntryImpl) me;

        return property.compareTo(ime.getProperty());
    }

    @Override
    protected Optional<InputStream> getInputStream(boolean checkAccess) throws IOException {
        final Optional<InputStream> is = referenced.getInputStream(checkAccess);

        verifyPropertyAfterCompletionOnce();
        return is;
    }

    /**
     * Called after the referenced migration entry is restored to register code to be invoked after
     * the migration operation completion to verify if the property value references the referenced
     * migration entry.
     */
    protected abstract void verifyPropertyAfterCompletion();

    @SuppressWarnings("PMD.DefaultPackage" /* designed to be called from ImportMigrationContextImpl within this package and from subclasses */)
    @VisibleForTesting
    String getProperty() {
        return property;
    }

    @VisibleForTesting
    ImportMigrationEntry getReferencedEntry() {
        return referenced;
    }

    private void verifyPropertyAfterCompletionOnce() {
        if (!verifierRegistered) {
            this.verifierRegistered = true;
            verifyPropertyAfterCompletion();
        }
    }
}