package rmblworx.tools.timey;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import rmblworx.tools.timey.exception.NullArgumentException;
import rmblworx.tools.timey.exception.ValueMinimumArgumentException;
import rmblworx.tools.timey.vo.TimeDescriptor;
/*
* Copyright 2014-2015 Christian Raue
* MIT License http://opensource.org/licenses/mit-license.php
*/
/**
* Implementierung eines einfachen Timer's zum ausführen einer Zeitmessung.
*
* @author mmatthies
*/
class SimpleTimer implements ITimer, ApplicationContextAware {
/**
* Maßzahl für die Ausfuehrungsverzögerung des Threads.
*/
private static final int DELAY = 1;
/**
* Größe des Thread-Pools.
*/
private static final int THREAD_POOL_SIZE = 1;
/**
* Scheduler wird verwendet um die Threads zu verwalten und wiederholt
* ausführen zu lassen.
*/
private ScheduledExecutorService scheduler;
/**
* Spring-Kontext.
*/
private ApplicationContext springContext;
/**
* Wertobjekt das die Zeit für die GUI kapselt und liefert.
*/
private final TimeDescriptor timeDescriptor;
/**
* Die bereits vergangene Zeit in Millisekunden.
*/
private long timePassed = 0;
/**
* Referenz auf die Zeitmessungsimplementierung.
*/
private TimerRunnable timer;
/**
* Referenz auf das Future-Objekt der aktuellen Zeitmessung.
*/
private ScheduledFuture<?> timerFuture;
/**
* Merker. Gibt an ob der Timer bereits zuvor gestoppt wurde.
*/
private boolean wasStoppedBefore = false;
/**
* Konstruktor. Erfordert die Referenz auf das Werteobjekt, welches den
* Wert an die GUI liefern wird.
*
* @param descriptor
* das zu setzende Werteobjekt. Es findet keine Pruefung
* auf @code{null} statt!
*/
public SimpleTimer(final TimeDescriptor descriptor) {
if (descriptor == null) {
throw new NullArgumentException();
}
this.timeDescriptor = descriptor;
}
@Override
public Boolean resetStopwatch() {
boolean isRunningAtTheMoment = false;
if (this.scheduler != null && !this.scheduler.isTerminated()) {
isRunningAtTheMoment = true;
this.stopStopwatch();
}
this.timePassed = 0;
this.timeDescriptor.setMilliSeconds(0);
if (isRunningAtTheMoment) {
this.startStopwatch(1, TimeUnit.MILLISECONDS);
}
return isRunningAtTheMoment;
}
@Override
public void setApplicationContext(final ApplicationContext applicationContext) throws BeansException {
this.springContext = applicationContext;
}
/*
* (non-Javadoc)
* @see rmblworx.tools.timey.ITimer#startStopwatch(int, int, java.util.concurrent.TimeUnit)
*/
@Override
public TimeDescriptor startStopwatch(final int delayPerThread, final TimeUnit timeUnit) {
if (delayPerThread < 1) {
throw new ValueMinimumArgumentException();
} else if (timeUnit == null) {
throw new NullArgumentException();
}
this.timer = (TimerRunnable) this.springContext.getBean("timerRunnable", this.timeDescriptor, this.timePassed);
this.scheduler = Executors.newScheduledThreadPool(THREAD_POOL_SIZE);
this.timerFuture = this.scheduler.scheduleAtFixedRate(this.timer, 0, delayPerThread, timeUnit);
this.wasStoppedBefore = false;
return this.timeDescriptor;
}
/*
* (non-Javadoc)
* @see rmblworx.tools.timey.ITimer#stopStopwatch()
*/
@Override
public Boolean stopStopwatch() {
if (this.scheduler != null) {
final TaskStopper stopRunnable = new TaskStopper(this.scheduler, this.timerFuture);
this.scheduler.schedule(stopRunnable, DELAY, TimeUnit.MILLISECONDS);
}
this.timePassed = this.timeDescriptor.getMilliSeconds();
this.wasStoppedBefore = true;
return Boolean.TRUE;
}
@Override
public Boolean toggleTimeModeInStopwatch() {
if (this.wasStoppedBefore) {
this.timeDescriptor.setMilliSeconds(this.timePassed);
}
return this.timer.toggleTimeMode();
}
}