// Path: core/src/main/java/org/hashes/algorithm/HashAlgorithm.java
// public interface HashAlgorithm {
// 
//     /**
//      * Computes the hash code of the specified key.
//      * 
//      * @param key the key to compute the hash code
//      * @return the hash code
//      */
//     int hash(String key);
// 
// }
// 
// Path: core/src/main/java/org/hashes/progress/ProgressMonitor.java
// public interface ProgressMonitor {
// 
//     /**
//      * Updates the progress of the task.
//      * <p>
//      * The progress can be updated from several threads, so the incremental work is not assured.
//      * 
//      * @param work a non negative number of work units just completed.
//      */
//     void update(int work);
// 
//     /**
//      * Notifies that the work is done.
//      */
//     void done();
// 
// }


import org.hashes.progress.ProgressMonitor;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableList.Builder;
import java.text.MessageFormat;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hashes.algorithm.HashAlgorithm;
        }
    }

    @Override
    protected List<String> generateNewCollisions(final int numberOfKeys, final ProgressMonitor monitor) {
        final int hash = this.getHashAlgorithm().hash(this.seed);
        final Map<Integer, String> lookupMap = this.createLookupMap(hash);
        final List<Callable<List<String>>> tasks = this.buildTasks(lookupMap, numberOfKeys, monitor);
        final ExecutorService executor = Executors.newFixedThreadPool(tasks.size());

        try {
            List<Future<List<String>>> results = Collections.emptyList();

            try {
                results = executor.invokeAll(tasks);
            } finally {
                executor.shutdown();
            }

            final Builder<String> collisions = ImmutableList.builder();
            for (final Future<List<String>> future : results) {
                collisions.addAll(future.get());
            }

            return collisions.build();
        } catch (final Exception e) {
            throw new ComputationException(e);
        }
    }

// Path: core/src/main/java/org/hashes/algorithm/HashAlgorithm.java
// public interface HashAlgorithm {
// 
//     /**
//      * Computes the hash code of the specified key.
//      * 
//      * @param key the key to compute the hash code
//      * @return the hash code
//      */
//     int hash(String key);
// 
// }
// 
// Path: core/src/main/java/org/hashes/progress/ProgressMonitor.java
// public interface ProgressMonitor {
// 
//     /**
//      * Updates the progress of the task.
//      * <p>
//      * The progress can be updated from several threads, so the incremental work is not assured.
//      * 
//      * @param work a non negative number of work units just completed.
//      */
//     void update(int work);
// 
//     /**
//      * Notifies that the work is done.
//      */
//     void done();
// 
// }


// Path: core/src/main/java/org/hashes/collision/AbstractMITMGenerator.java
import org.hashes.progress.ProgressMonitor;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableList.Builder;
import java.text.MessageFormat;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hashes.algorithm.HashAlgorithm;

        }
    }

    @Override
    protected List<String> generateNewCollisions(final int numberOfKeys, final ProgressMonitor monitor) {
        final int hash = this.getHashAlgorithm().hash(this.seed);
        final Map<Integer, String> lookupMap = this.createLookupMap(hash);
        final List<Callable<List<String>>> tasks = this.buildTasks(lookupMap, numberOfKeys, monitor);
        final ExecutorService executor = Executors.newFixedThreadPool(tasks.size());

        try {
            List<Future<List<String>>> results = Collections.emptyList();

            try {
                results = executor.invokeAll(tasks);
            } finally {
                executor.shutdown();
            }

            final Builder<String> collisions = ImmutableList.builder();
            for (final Future<List<String>> future : results) {
                collisions.addAll(future.get());
            }

            return collisions.build();
        } catch (final Exception e) {
            throw new ComputationException(e);
        }
    }

    private Map<Integer, String> createLookupMap(final int hash) {