package org.sagebionetworks.logging.collate;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.SortedMap;
import java.util.TreeMap;

import org.sagebionetworks.logging.reader.LogReader;

/**
 * Set of utility functions for collating a set of log files into one.
 * 
 * There are a couple of preconditions for use:
 * 
 *  - the files should all be the same format.  This is meant to be used on a set of
 *    log files generated on different instances of a single Elastic Beanstalk.
 *  - The log files should be from the same period of time.  It will work to use collate on a 
 *    set of log files that have totally non-overlapping timestamp ranges, but it's inefficent.
 *    Those files can simply be concatenated.
 * @author geoff
 *
 */
public class LogCollationUtils {

	public static <T extends LogReader> ArrayList<T> initializeReaders(LogReader.LogReaderFactory<T> factory, List<File> files) throws FileNotFoundException {
		ArrayList<T> readers = new ArrayList<T>();

		for (File file : files) {
			readers.add(factory.create(new BufferedReader(new FileReader(file))));
		}
		return readers;
	}

	public static <T extends LogReader> SortedMap<LogEvent, T> primeCollationMap(List<T> readers) throws IOException {
		SortedMap<LogEvent, T> fileEventMap = new TreeMap<LogEvent, T>();
		for (T stream : readers) {
			LogEvent event = stream.readLogEvent();
			fileEventMap.put(event, stream);
		}
		return fileEventMap;
	}

	public static <T extends LogReader> void collateLogs(SortedMap<LogEvent, T> fileEventMap, BufferedWriter output) throws IOException {

		while (!fileEventMap.isEmpty()) {
			LogEvent firstEvent = fileEventMap.firstKey();
			T rdr = fileEventMap.get(firstEvent);

			output.write(firstEvent.getLine());
			output.newLine();

			fileEventMap.remove(firstEvent);

			LogEvent next = rdr.readLogEvent();
			if (next != null)
				fileEventMap.put(next, rdr);
		}
		output.flush();
	}

}

@@ -966,16 +966,478 @@
 tils %7B%0A%0A
+%09/**%0A%09 * Creates a list of LogReaders on the given files using the factory.  This is a separate method so that%0A%09 * code can hang onto the list of LogReaders opened so they don't leak files.%0A%09 * @param factory The factory class that can create instances of the LogReader for this file type.%0A%09 * @param files A list of files that need to be collated together.  They should all be of the format that is read by T.%0A%09 * @return%0A%09 * @throws FileNotFoundException%0A%09 */%0A
 %09public 
@@ -1754,24 +1754,255 @@
 eaders;%0A%09%7D%0A%0A
+%09/**%0A%09 * Setup the SortedMap used by the collation process.%0A%09 * @param readers A list of readers from the %7B@link initializeReaders%7D method.%0A%09 * @return The SortedMap that is used by %7B@link collateLogs%7D%0A%09 * @throws IOException%0A%09 */%0A
 %09public stat
@@ -2312,16 +2312,305 @@
 ap;%0A%09%7D%0A%0A
+%09/**%0A%09 * Used to collate a set of log files from the same time period into a single %22canonical%22 version of that log file.%0A%09 * @param fileEventMap Should come from %7B@link primeCollationMap%7D.%0A%09 * @param output File to write the collated version of the logs too.%0A%09 * @throws IOException%0A%09 */%0A
 %09public 

Add comments to LogCollationUtils