// Path: src/main/java/org/gzipper/java/application/observer/NotifierImpl.java
// public class NotifierImpl<T> implements Notifier<T> {
// 
//     /**
//      * Unique identifier of this instance.
//      */
//     private final int _id = hashCode();
// 
//     /**
//      * Listeners to be notified if the associated value has been updated.
//      */
//     private final List<Listener<T>> _listeners = new CopyOnWriteArrayList<>();
// 
//     /**
//      * True if value has changed, false otherwise.
//      */
//     private boolean _hasChanged = false;
// 
//     /**
//      * The associated value which may change.
//      */
//     private T _value;
// 
//     @Override
//     public int getId() {
//         return _id;
//     }
// 
//     @Override
//     public final synchronized T getValue() {
//         return _value;
//     }
// 
//     @Override
//     public final synchronized void setValue(T value) {
//         _value = value;
//     }
// 
//     @Override
//     public final void notifyListeners() {
//         if (hasChanged()) {
//             _listeners.forEach((listener) -> listener.update(this, _value));
//             clearChanged();
//         }
//     }
// 
//     @Override
//     public final synchronized boolean hasChanged() {
//         return _hasChanged;
//     }
// 
//     @Override
//     public final synchronized void setChanged() {
//         _hasChanged = true;
//     }
// 
//     @Override
//     public final synchronized void clearChanged() {
//         _hasChanged = false;
//     }
// 
//     @Override
//     public final void attach(Listener<T> listener) {
//         Objects.requireNonNull(listener);
//         if (!_listeners.contains(listener)) {
//             _listeners.add(listener);
//         }
//     }
// 
//     @Override
//     public final boolean detach(Listener<T> listener) {
//         return _listeners.remove(listener);
//     }
// 
//     @Override
//     public final void clearListeners() {
//         _listeners.clear();
//     }
// }
// 
// Path: src/main/java/org/gzipper/java/application/predicates/Predicates.java
// public final class Predicates {
// 
//     private Predicates() {
//         throw new AssertionError("Holds static members only");
//     }
// 
//     /**
//      * Creates a new {@link Predicate} which always evaluates to <b>true</b>.
//      *
//      * @param <T> the type of the object that is to be consumed by the predicate
//      *            and thus the type of the input to the predicate.
//      * @return a new instance of {@link Predicate} with the specified type.
//      */
//     public static <T> Predicate<T> createAlwaysTrue() {
//         return p -> true;
//     }
// 
//     /**
//      * Creates a new {@link Predicate} which always evaluates to <b>false</b>.
//      *
//      * @param <T> the type of the object that is to be consumed by the predicate
//      *            and thus the type of the input to the predicate.
//      * @return a new instance of {@link Predicate} with the specified type.
//      */
//     public static <T> Predicate<T> createAlwaysFalse() {
//         return p -> false;
//     }
// }


import org.apache.commons.compress.archivers.ArchiveException;
import org.apache.commons.compress.compressors.CompressorException;
import org.gzipper.java.application.ArchiveInfo;
import org.gzipper.java.application.observer.NotifierImpl;
import org.gzipper.java.application.predicates.Predicates;
import java.io.File;
import java.io.IOException;
import java.util.Objects;
import java.util.function.Predicate;
/*
 * Copyright (C) 2018 Matthias Fussenegger
 *
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 *
 * 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 General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <http://www.gnu.org/licenses/>.
 */
package org.gzipper.java.application.algorithm;



/**
 * Abstract class that offers generally used attributes and methods for
 * archiving algorithms. Any class that represents an archiving algorithm should
 * derive from this class.
 *
 * @author Matthias Fussenegger
 */
public abstract class AbstractAlgorithm extends NotifierImpl<Integer> implements CompressionAlgorithm {

    /**
     * If set to true the currently running operation will be interrupted.
     */
    protected volatile boolean interrupt = false;

    /**
     * The compression level. Will only be considered if supported by algorithm.
     */
    protected int compressionLevel;

    /**
     * Object used to update the progress of the algorithm.
     */
    protected AlgorithmProgress algorithmProgress;

    /**
     * Predicate used to filter files or entries when processing archives.
     */
    protected Predicate<String> filterPredicate;

    /**
     * The default constructor of this class.
     */
    public AbstractAlgorithm() {
        // accepts all files/entries since the test result is never false
// Path: src/main/java/org/gzipper/java/application/observer/NotifierImpl.java
// public class NotifierImpl<T> implements Notifier<T> {
// 
//     /**
//      * Unique identifier of this instance.
//      */
//     private final int _id = hashCode();
// 
//     /**
//      * Listeners to be notified if the associated value has been updated.
//      */
//     private final List<Listener<T>> _listeners = new CopyOnWriteArrayList<>();
// 
//     /**
//      * True if value has changed, false otherwise.
//      */
//     private boolean _hasChanged = false;
// 
//     /**
//      * The associated value which may change.
//      */
//     private T _value;
// 
//     @Override
//     public int getId() {
//         return _id;
//     }
// 
//     @Override
//     public final synchronized T getValue() {
//         return _value;
//     }
// 
//     @Override
//     public final synchronized void setValue(T value) {
//         _value = value;
//     }
// 
//     @Override
//     public final void notifyListeners() {
//         if (hasChanged()) {
//             _listeners.forEach((listener) -> listener.update(this, _value));
//             clearChanged();
//         }
//     }
// 
//     @Override
//     public final synchronized boolean hasChanged() {
//         return _hasChanged;
//     }
// 
//     @Override
//     public final synchronized void setChanged() {
//         _hasChanged = true;
//     }
// 
//     @Override
//     public final synchronized void clearChanged() {
//         _hasChanged = false;
//     }
// 
//     @Override
//     public final void attach(Listener<T> listener) {
//         Objects.requireNonNull(listener);
//         if (!_listeners.contains(listener)) {
//             _listeners.add(listener);
//         }
//     }
// 
//     @Override
//     public final boolean detach(Listener<T> listener) {
//         return _listeners.remove(listener);
//     }
// 
//     @Override
//     public final void clearListeners() {
//         _listeners.clear();
//     }
// }
// 
// Path: src/main/java/org/gzipper/java/application/predicates/Predicates.java
// public final class Predicates {
// 
//     private Predicates() {
//         throw new AssertionError("Holds static members only");
//     }
// 
//     /**
//      * Creates a new {@link Predicate} which always evaluates to <b>true</b>.
//      *
//      * @param <T> the type of the object that is to be consumed by the predicate
//      *            and thus the type of the input to the predicate.
//      * @return a new instance of {@link Predicate} with the specified type.
//      */
//     public static <T> Predicate<T> createAlwaysTrue() {
//         return p -> true;
//     }
// 
//     /**
//      * Creates a new {@link Predicate} which always evaluates to <b>false</b>.
//      *
//      * @param <T> the type of the object that is to be consumed by the predicate
//      *            and thus the type of the input to the predicate.
//      * @return a new instance of {@link Predicate} with the specified type.
//      */
//     public static <T> Predicate<T> createAlwaysFalse() {
//         return p -> false;
//     }
// }


// Path: src/main/java/org/gzipper/java/application/algorithm/AbstractAlgorithm.java
import org.apache.commons.compress.archivers.ArchiveException;
import org.apache.commons.compress.compressors.CompressorException;
import org.gzipper.java.application.ArchiveInfo;
import org.gzipper.java.application.observer.NotifierImpl;
import org.gzipper.java.application.predicates.Predicates;
import java.io.File;
import java.io.IOException;
import java.util.Objects;
import java.util.function.Predicate;

/*
 * Copyright (C) 2018 Matthias Fussenegger
 *
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 *
 * 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 General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <http://www.gnu.org/licenses/>.
 */
package org.gzipper.java.application.algorithm;



/**
 * Abstract class that offers generally used attributes and methods for
 * archiving algorithms. Any class that represents an archiving algorithm should
 * derive from this class.
 *
 * @author Matthias Fussenegger
 */
public abstract class AbstractAlgorithm extends NotifierImpl<Integer> implements CompressionAlgorithm {

    /**
     * If set to true the currently running operation will be interrupted.
     */
    protected volatile boolean interrupt = false;

    /**
     * The compression level. Will only be considered if supported by algorithm.
     */
    protected int compressionLevel;

    /**
     * Object used to update the progress of the algorithm.
     */
    protected AlgorithmProgress algorithmProgress;

    /**
     * Predicate used to filter files or entries when processing archives.
     */
    protected Predicate<String> filterPredicate;

    /**
     * The default constructor of this class.
     */
    public AbstractAlgorithm() {
        // accepts all files/entries since the test result is never false
        filterPredicate = Predicates.createAlwaysTrue();