/*******************************************************************************
 * Copyright (c) 2012 itemis AG (http://www.itemis.eu) and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *******************************************************************************/
package org.eclipse.xtext.junit4.internal;

import java.util.Map;
import java.util.Map.Entry;

import org.eclipse.xtext.util.internal.StopWatches;
import org.eclipse.xtext.util.internal.StopWatches.NumbersForTask;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;

/**
 * @author Sven Efftinge - Initial contribution and API
 */
public class StopWatchRule implements TestRule {

	private boolean watchAll = false;

	public StopWatchRule() {
	}

	/**
	 * @param watchAll
	 *            - whether all tests should be watched (<code>true</code>) or just the ones annotated with @
	 *            {@link StopWatched} (<code>false</code>).
	 */
	public StopWatchRule(boolean watchAll) {
		this.watchAll = watchAll;
	}

	public void printStopWatchData(Description description, Map<String, StopWatches.NumbersForTask> data) {
		System.out
				.println("-------------------------------------------------------------------------------------------------------------------------\n");
		System.out.println("Test '" + description.getDisplayName() + "' :");
		System.out.println(getStopWatchDataAsReadableString(data));
	}

	public String getStopWatchDataAsReadableString(Map<String, NumbersForTask> data) {
		StringBuilder sb = new StringBuilder();
		sb.append("-------------------------------------------------------------------------------------------------------------------------\n");
		for (Entry<String, NumbersForTask> task : data.entrySet()) {
			sb.append("Task '" + task.getKey() + "' took " + task.getValue().getMilliseconds() + "ms ("
					+ task.getValue().getNumberOfMeasurements() + " measurements).\n");
		}
		sb.append("-------------------------------------------------------------------------------------------------------------------------\n");
		return sb.toString();
	}

	public Statement apply(final Statement base, final Description description) {
		if (!watchAll && description.getAnnotation(StopWatched.class) == null)
			return base;
		return new Statement() {
			@Override
			public void evaluate() throws Throwable {
				try {
					StopWatches.setEnabled(true);
					StopWatches.resetAll();
					base.evaluate();
					printStopWatchData(description, StopWatches.allNumbers());
				} finally {
					StopWatches.resetAll();
					StopWatches.setEnabled(false);
				}
			}
		};
	}

}

@@ -513,16 +513,126 @@
 ernal;%0A%0A
+import java.io.File;%0Aimport java.io.FileOutputStream;%0Aimport java.io.IOException;%0Aimport java.io.PrintStream;%0A
 import j
@@ -645,16 +645,16 @@
 il.Map;%0A
-
 import j
@@ -1466,22 +1466,355 @@
 %0A%09%09S
-ystem.out%0A%09%09%09%09
+tring property = System.getProperty(%22stopwatch.file%22);%0A%09%09PrintStream out = System.out;%0A%09%09FileOutputStream outputStream = null;%0A%09%09if (property != null) %7B%0A%09%09%09try %7B%0A%09%09%09%09outputStream = new FileOutputStream(new File(property), true);%0A%09%09%09%09out = new PrintStream(outputStream);%0A%09%09%09%7D catch (IOException e) %7B%0A%09%09%09%09e.printStackTrace();%0A%09%09%09%7D%0A%09%09%7D%0A%09%09try %7B%0A%09%09%09out
 .pri
@@ -1944,31 +1944,25 @@
 ----%5Cn%22);%0A%09%09
-System.
+%09
 out.println(
@@ -2013,23 +2013,17 @@
  :%22);%0A%09%09
-System.
+%09
 out.prin
@@ -2067,16 +2067,180 @@
 data));%0A
+%09%09%7D finally %7B%0A//%09%09%09out.flush();%0A%09%09%09if (outputStream != null)%0A%09%09%09%09try %7B%0A%09%09%09%09%09outputStream.close();%0A%09%09%09%09%7D catch (IOException e) %7B%0A%09%09%09%09%09e.printStackTrace();%0A%09%09%09%09%7D%0A%09%09%7D%0A
 %09%7D%0A%0A%09pub
@@ -3249,24 +3249,40 @@
 evaluate();%0A
+%09%09%09%09%7D finally %7B%0A
 %09%09%09%09%09printSt
@@ -3333,32 +3333,16 @@
 ers());%0A
-%09%09%09%09%7D finally %7B%0A
 %09%09%09%09%09Sto

stop watches rule, can be configured with a system property to append the results to a file.