package pl.net.bluesoft.util.lang;
import org.apache.commons.lang3.time.StopWatch;
import java.text.MessageFormat;
import java.util.*;
import java.util.concurrent.Callable;
/**
* @author: amichalak@bluesoft.net.pl
*/
public class TaskWatch {
public static String DEFAULT_HEADER_PATTERN = "TaskWatch \"{0}\" running time:\t{1}\n----------- Task summary -----------";
public static String DEFAULT_ROW_PATTERN = "\t{0}\t\t{1}";
private String name;
private Map<String, StopWatch> watchMap = new HashMap<String, StopWatch>();
private Set<String> watchesRunning = new HashSet<String>();
private StopWatch totalWatch = new StopWatch();
private boolean suspended = false;
private String lastTaskName;
private String headerPattern = DEFAULT_HEADER_PATTERN;
private String rowPattern = DEFAULT_ROW_PATTERN;
public TaskWatch(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getHeaderPattern() {
return headerPattern;
}
public void setHeaderPattern(String headerPattern) {
if (!Strings.hasText(headerPattern)) {
throw new IllegalArgumentException("Header pattern cannot be empty!");
}
this.headerPattern = headerPattern;
}
public String getRowPattern() {
return rowPattern;
}
public void setRowPattern(String rowPattern) {
if (!Strings.hasText(rowPattern)) {
throw new IllegalArgumentException("Row pattern cannot be empty!");
}
this.rowPattern = rowPattern;
}
public void start(String taskName) {
if (watchesRunning.contains(taskName)) {
throw new IllegalArgumentException("Watch for '" + taskName + "' already running");
}
if (!watchMap.containsKey(taskName)) {
watchMap.put(taskName, new StopWatch());
}
StopWatch watch = watchMap.get(taskName);
watch.reset();
watch.start();
if (watchesRunning.isEmpty()) {
if (suspended) {
totalWatch.resume();
}
else {
totalWatch.start();
}
}
watchesRunning.add(taskName);
lastTaskName = taskName;
}
public long stop(String taskName) {
StopWatch watch = watchMap.get(taskName);
if (watch == null) {
throw new IllegalArgumentException("No such task: " + taskName);
}
if (!watchesRunning.contains(taskName)) {
throw new IllegalArgumentException("Watch for '" + taskName + "' is not running");
}
watch.stop();
watchesRunning.remove(taskName);
if (watchesRunning.isEmpty()) {
totalWatch.suspend();
suspended = true;
}
return watch.getTime();
}
public long stopLast() {
if (lastTaskName == null) {
throw new IllegalArgumentException("No task started yet!");
}
return stop(lastTaskName);
}
public void startLast() {
if (lastTaskName == null) {
throw new IllegalArgumentException("No task started yet!");
}
start(lastTaskName);
}
public long stopAll() {
if (!watchesRunning.isEmpty()) {
for (String taskName : watchesRunning) {
watchMap.get(taskName).stop();
}
totalWatch.stop();
}
return totalWatch.getTime();
}
public <T> T watchTask(String taskName, Callable<T> task) throws Exception {
start(taskName);
try {
return task.call();
}
finally {
stop(taskName);
}
}
public void watchTask(String taskName, Runnable task) {
start(taskName);
task.run();
stop(taskName);
}
public String printSummary() {
List<String> taskNames = new ArrayList<String>(watchMap.keySet());
java.util.Collections.sort(taskNames);
StringBuilder sb = new StringBuilder();
sb.append(MessageFormat.format(headerPattern, name, totalWatch.toString())).append("\n");
for (String taskName : taskNames) {
StopWatch watch = watchMap.get(taskName);
sb.append(MessageFormat.format(rowPattern, taskName, watch.toString())).append("\n");
}
return sb.toString();
}
}