// $Id: CellCron.java,v 1.8 2006-12-15 10:58:15 tigran Exp $
package dmg.util ;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Iterator;
import java.util.TreeSet;
/**
* Author : Patrick Fuhrmann
* (C) DESY
*/
public class CellCron implements Runnable {
public static final int NEXT = -1 ;
private final TreeSet<TimerTask> _list = new TreeSet<>() ;
public class TimerTask implements Comparable<TimerTask> {
private Long _time;
private Calendar _calendar;
private String _name;
private TaskRunnable _runner;
private TimerTask( int hour , int minute , TaskRunnable runner , String name ){
_runner = runner ;
_name = name ;
_calendar = new GregorianCalendar() ;
long start = _calendar.getTime().getTime() ;
if( hour != NEXT ) {
_calendar.set(Calendar.HOUR_OF_DAY, hour);
}
_calendar.set(Calendar.MINUTE,minute);
_calendar.set(Calendar.SECOND,0);
_time = _calendar.getTime().getTime();
if( (_time - start ) < 0L ){
if( hour == NEXT ){
_calendar.set(Calendar.HOUR_OF_DAY,_calendar.get(Calendar.HOUR_OF_DAY)+1);
}else{
_calendar.set(Calendar.DAY_OF_YEAR,_calendar.get(Calendar.DAY_OF_YEAR)+1);
}
}
_time = _calendar.getTime().getTime();
}
public Calendar getCalendar(){ return _calendar ; }
private void nextTick(){
_time = _time + 1;
}
@Override
public int compareTo( TimerTask other ){
return _time.compareTo( other._time);
}
public int hashCode() {
return 17;
}
public boolean equals( Object other ){
if (other == this) {
return true;
}
return (other instanceof TimerTask) && _time.equals(((TimerTask)other)._time);
}
public void repeatTomorrow(){
tomorrow() ;
add(this);
}
public void repeatNextHour(){
_calendar.set(Calendar.MINUTE,_calendar.get(Calendar.MINUTE)+60);
_time = _calendar.getTime().getTime();
add(this);
}
private void tomorrow(){
_calendar.set(Calendar.DAY_OF_YEAR,_calendar.get(Calendar.DAY_OF_YEAR)+1);
_time = _calendar.getTime().getTime();
}
private long getTime(){
return _time;
}
public String toString(){
return _name + ' ' + new Date(_time) ;
}
}
public interface TaskRunnable {
void run(TimerTask task);
}
public TimerTask add( int minutes , TaskRunnable runner , String name ){
return add( NEXT , minutes , runner , name );
}
public TimerTask add( int hour , int minutes , TaskRunnable runner , String name ){
TimerTask task = new TimerTask( hour , minutes , runner , name ) ;
add( task ) ;
return task ;
}
public void add( TimerTask task ){
synchronized( _list ){
while( _list.contains(task) ) {
task.nextTick();
}
_list.add(task) ;
_list.notifyAll();
}
}
public Iterator<TimerTask> iterator(){
return new ArrayList<>( _list ).iterator() ;
}
@Override
public void run(){
try{
runLoop() ;
}catch(InterruptedException ie){
}
}
private void runLoop() throws InterruptedException {
while( ! Thread.interrupted() ){
synchronized( _list ){
if(_list.isEmpty()){
// System.out.println("wakeup : nothing" ) ;
_list.wait((5*60*1000));
continue ;
}
TimerTask task = _list.first() ;
// System.out.println("wakeup : "+task.toString() ) ;
long diff = task.getTime() - System.currentTimeMillis() ;
if( diff < 15000L ){
_list.remove(task);
try{
task._runner.run(task) ;
}catch(Exception ee ){
ee.printStackTrace();
}
}else if( diff > (5*60*1000) ){
_list.wait(diff-60000L);
}else{
_list.wait(diff);
}
}
}
}
}