All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jadex.platform.service.clock.AbstractClock Maven / Gradle / Ivy

package jadex.platform.service.clock;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;

import jadex.bridge.service.types.clock.IClock;
import jadex.bridge.service.types.clock.ITimedObject;
import jadex.bridge.service.types.clock.ITimer;
import jadex.commons.ChangeEvent;
import jadex.commons.IChangeListener;
import jadex.commons.collection.SCollection;
import jadex.commons.future.IResultListener;

/**
 *  Abstract base class for all clocks.
 */
public abstract class AbstractClock implements IClock
{
	//-------- constants --------
	
	/** The default delta (tick time). */
	public static final long	DEFAULT_DELTA	= 100;
	
	//-------- attributes --------

	/** The clock name. */
	protected String name;
	
	/** The start time (model time). */
	protected long starttime;

	/** The current time (last measurement). */
	protected long currenttime;
	
	/** The clock tick delta (relative to base time). */
	protected long delta;
	
	/** The clock state. */
	protected String state;
	
	/** The tick timers. */
	protected List ticktimers;

	/** The timers  (entries ordered by timepoint). */
	public SortedSet timers;
	
	/** The tick timer. */
	protected Timer ticktimer;
	
	/** The change listeners. */
	protected List listeners;
	
	//-------- constructors --------
	
	/**
	 *  Create a new clock.
	 */
	public AbstractClock(String name, long starttime, long delta)
	{
		this.name = name;
		this.starttime = starttime;
		this.currenttime = starttime;
		this.delta = delta;
		this.state = STATE_SUSPENDED;
		this.listeners = Collections.synchronizedList(SCollection.createArrayList());
		
		// Sorted set for all entries ordered by due time.
		this.timers	= Collections.synchronizedSortedSet(new TreeSet(new Comparator()
		{
			/**
			 *  Compare two timers.
			 *  @param arg0 The first timer.
			 *  @param arg1 The second timer.
			 */
			public int compare(Object arg0, Object arg1)
			{
				Timer t1 = (Timer)arg0;
				Timer t2 = (Timer)arg1;	
				long ret	= t1.getNotificationTime() - t2.getNotificationTime();
				if(ret==0 && t1!=t2)
					ret	= t1.getNumber()-t2.getNumber();
				return ret>0 ? 1 : ret<0 ? -1 : 0;
			}
		}));
		
		this.ticktimers = SCollection.createArrayList();
		
		// The ticktimer is a normal timer which indicates when the next
		// tick is due. It then notifies all registered tick timers. 
		this.ticktimer = new Timer(0, this, new ITimedObject()
		{
			public void timeEventOccurred(long currenttime)
			{
				TickTimer[] tts;
				
				synchronized(AbstractClock.this)
				{
//					System.out.println("Ticktimer notified: "+ticktimers);
					
					tts = (TickTimer[])ticktimers.toArray(new TickTimer[ticktimers.size()]);
					ticktimers.clear();
				}
				
				for(int i=0; igetTime())
			{
				long num = (getTime()-getStarttime())/getDelta();
				long time = (num+1)*getDelta()+getStarttime();
				ticktimer.setNotificationTime(time);
//				System.out.println("Ticktimer at: "+time);
			}
		}
		
		notifyListeners(new ChangeEvent(this, EVENT_TYPE_NEW_DELTA));
	}

	/**
	 *  Get the next timer.
	 *  @return The next timer.
	 */
	public synchronized ITimer getNextTimer()
	{
		return timers.size()==0? null: (ITimer)timers.first();
	}
	
	/**
	 *  Get the clock state.
	 *  @return The clock state.
	 */
	public String getState()
	{
		return state;
	}
	
	/**
	 *  Start the clock.
	 */
	public void start()
	{
		if(!STATE_RUNNING.equals(state))
		{
			this.state = STATE_RUNNING;
			notifyListeners(new ChangeEvent(this, EVENT_TYPE_STARTED));
		}
	}
	
	/**
	 *  Stop the clock.
	 */
	public void stop()
	{
		if(STATE_RUNNING.equals(state))
		{
			this.state = STATE_SUSPENDED;
			notifyListeners(new ChangeEvent(this, EVENT_TYPE_STOPPED));
		}
	}
	
	/**
	 *  Reset the clock.
	 */
	public synchronized void reset()
	{
		if(STATE_RUNNING.equals(state))
			this.state = STATE_SUSPENDED;
		this.currenttime = starttime;
		this.timers.clear();
		this.ticktimers.clear();
		
		notifyListeners(new ChangeEvent(this, EVENT_TYPE_RESET));
	}
	
	/**
	 *  Create a new timer.
	 *  @param timespan The timespan.
	 *  @param to The timed object.
	 */
	public ITimer createTimer(long timespan, ITimedObject to)
	{
		Timer t = new Timer(getTime()+timespan, this, to);
		addTimer(t);
		return t;
	}
	
	/**
	 *  Create a new tick timer.
	 *  @param to The timed object.
	 *  @param info Optional info object.
	 */
	public ITimer createTickTimer(ITimedObject to)
	{
		TickTimer t = new TickTimer(this, to);
		addTickTimer(t);
		return t;
	}
	
	/**
	 *  Get all active timers.
	 *  @return The active timers.
	 */
	public ITimer[] getTimers()
	{
		ITimer[] ret;
		if(ticktimer!=null)
		{
			List clone = new ArrayList(timers);
			clone.remove(ticktimer);
			ret = (ITimer[])clone.toArray(new ITimer[0]);
		}
		else
		{
			ret = (ITimer[])timers.toArray(new ITimer[0]);
		}
		return ret;
	}
	
	/**
	 *  Get all active tick timers.
	 *  @return The active tick timers.
	 */
	public ITimer[] getTickTimers()
	{
		return (ITimer[])ticktimers.toArray(new ITimer[0]);
	}
	
	/**
	 *  Add a timer.
	 *  @param timer The timer.
	 */
	public void addTimer(ITimer timer)
	{
		synchronized(this)
		{
			timers.add(timer);
//			System.err.println("Added timer: "+timers);
		}
		
		notifyListeners(new ChangeEvent(this, EVENT_TYPE_TIMER_ADDED));
	}
	
	/**
	 *  Remove a timer.
	 *  @param timer The timer.
	 */
	public void removeTimer(ITimer timer)
	{
		synchronized(this)
		{
			boolean	removed	= timers.remove(timer);
//			if(!removed)
//				System.out.println("Could not remove timer: "+timer+" "+timers);
//			System.err.println("Removed timer: "+timers);
		}
		
		notifyListeners(new ChangeEvent(this, EVENT_TYPE_TIMER_REMOVED));
	}
	
	/**
	 *  Add a tick timer.
	 *  @param timer The timer.
	 */
	public void addTickTimer(ITimer timer)
	{
		synchronized(this)
		{
			ticktimers.add(timer);
			activateTickTimer();
			
//			if(!timers.contains(ticktimer))
//			{
//				long num = (getTime()-getStarttime())/getDelta();
//				long time = (num+1)*getDelta()+getStarttime();
//				ticktimer.setNotificationTime(time);
//				System.out.println("Ticktimer at: "+time+" "+getTime());
//			}
		}
		
		notifyListeners(new ChangeEvent(this, EVENT_TYPE_TIMER_ADDED));
	}

	/**
	 *  Activate the tick timer.
	 */
	protected void activateTickTimer()
	{
		if(!timers.contains(ticktimer))
		{
			long num = (getTime()-getStarttime())/getDelta();
			long time = (num+1)*getDelta()+getStarttime();
			ticktimer.setNotificationTime(time);
//			System.out.println("Ticktimer at: "+time+" "+getTime());
		}
	}
	
	/**
	 *  Remove a tick timer.
	 *  @param timer The timer.
	 */
	public void removeTickTimer(ITimer timer)
	{
		synchronized(this)
		{
			ticktimers.remove(timer);
			if(ticktimers.size()==0)
				removeTimer(ticktimer);
		}
		
		notifyListeners(new ChangeEvent(this, EVENT_TYPE_TIMER_REMOVED));
	}
	
	/**
	 *  Add a change listener.
	 *  @param listener The change listener.
	 */
	public void addChangeListener(IChangeListener listener)
	{
		listeners.add(listener);
	}
	
	/**
	 *  Remove a change listener.
	 *  @param listener The change listener.
	 */
	public void removeChangeListener(IChangeListener listener)
	{
		listeners.remove(listener);
	}
	
	/**
	 *  Notify the listeners.
	 */
	protected void notifyListeners(ChangeEvent ce)
	{
//		System.out.println(""+this.getClass()+" "+ce);
		IChangeListener[]	cls	= (IChangeListener[])listeners.toArray(new IChangeListener[0]);
		for(int i=0; i




© 2015 - 2024 Weber Informatics LLC | Privacy Policy