package threadPool;

import java.io.*;
import java.util.*;
import java.util.concurrent.*;

/**
 * @version 1.02 2015-06-21
 * @author Cay Horstmann
 */
public class ThreadPoolTest
{
   public static void main(String[] args) throws Exception
   {
      try (Scanner in = new Scanner(System.in))
      {
         System.out.print("Podaj katalog bazowy (np. /usr/local/jdk5.0/src): ");
         String directory = in.nextLine();
         System.out.print("Podaj słowo kluczowe (np. volatile): ");
         String keyword = in.nextLine();
   
         ExecutorService pool = Executors.newCachedThreadPool();
   
         MatchCounter counter = new MatchCounter(new File(directory), keyword, pool);
         Future<Integer> result = pool.submit(counter);
   
         try
         {
            System.out.println(result.get() + " matching files.");
         }
         catch (ExecutionException e)
         {
            e.printStackTrace();
         }
         catch (InterruptedException e)
         {
         }
         pool.shutdown();
   
         int largestPoolSize = ((ThreadPoolExecutor) pool).getLargestPoolSize();
         System.out.println("largest pool size=" + largestPoolSize);
      }
   }
}

/**
 * Zadanie liczące pliki w katalogu i jego podkatalogach, zawierające dane słowo kluczowe
 */
class MatchCounter implements Callable<Integer>
{
   private File directory;
   private String keyword;
   private ExecutorService pool;
   private int count;

   /**
    * Tworzy obiekt typu MatchCounter.
    * @param directory katalog, od którego ma się zacząć szukanie
    * @param keyword słowo kluczowe do znalezienia
    * @param pool pula wątków, do której wysyłane są zadania
    */
   public MatchCounter(File directory, String keyword, ExecutorService pool)
   {
      this.directory = directory;
      this.keyword = keyword;
      this.pool = pool;
   }

   public Integer call()
   {
      count = 0;
      try
      {
         File[] files = directory.listFiles();
         List<Future<Integer>> results = new ArrayList<>();

         for (File file : files)
            if (file.isDirectory())
            {
               MatchCounter counter = new MatchCounter(file, keyword, pool);
               Future<Integer> result = pool.submit(counter);
               results.add(result);
            }
            else
            {
               if (search(file)) count++;
            }

         for (Future<Integer> result : results)
            try
            {
               count += result.get();
            }
            catch (ExecutionException e)
            {
               e.printStackTrace();
            }
      }
      catch (InterruptedException e)
      {
      }
      return count;
   }

   /**
    * Przeszukuje plik w celu znalezienia danego słowa kluczowego.
    * @param file plik do przeszukania
    * @return wartość true, jeśli plik zawiera słowo kluczowe
    */
   public boolean search(File file)
   {
      try
      {
         try (Scanner in = new Scanner(file, "UTF-8"))
         {
            boolean found = false;
            while (!found && in.hasNextLine())
            {
               String line = in.nextLine();
               if (line.contains(keyword)) found = true;
            }         
            return found;
         }
      }
      catch (IOException e)
      {
         return false;
      }
   }
}