MyTimer.java

/*
 * Copyright © 2012 Nokia Corporation. All rights reserved.
 * Nokia and Nokia Connecting People are registered trademarks of Nokia Corporation.
 * Oracle and Java are trademarks or registered trademarks of Oracle and/or its
 * affiliates. Other product and company names mentioned herein may be trademarks
 * or trade names of their respective owners.
 * See LICENSE.TXT for license information.
 */

package com.nokia.example.amaze.model;

/**
 * A general, easy-to-use timer. 
 */
public class MyTimer {
	// Constants
	private static final int MAX_LISTENER_COUNT = 5;
	
	// Members
	private static MyTimer _instance = null;
	private MyListener[] _listeners = null;
	private long _time = 0;
	
	/** 
	 * @return The singleton instance of MyTimer.
	 */
	static public MyTimer instance() {
		if (_instance == null) {
			_instance = new MyTimer();
		}
		
		return _instance;
	}
	
	/**
	 * Constructor.
	 */
	private MyTimer() {
		_listeners = new MyListener[MAX_LISTENER_COUNT];
	}

	/**
	 * Updates the internal time of the timer. If enough time has passed, the
	 * timer will trigger (call the listener(s)).
	 * @param time The current time.
	 */
	public void update(final long time) {
		_time = time;
		MyListener listener = null;
		
		for (int i = 0; i < MAX_LISTENER_COUNT; ++i) {
			listener = _listeners[i];
			
			if (listener == null) {
				continue;
			}
			
			if (_time - listener._lastTime >= listener._interval) {
				// Notify the listener
				listener._object.onTimeout();
				
				if (listener._repeat) {
					listener._lastTime = _time;
				}
				else {
					// Not repetitive. Thus, remove the listener
					_listeners[i] = null;
				}
			}
		}
	}
	
	/**
	 * For convenience.
	 */
	public void update() {
		update(System.currentTimeMillis());
	}		
	
	/**
	 * Adds the given listener.
	 * @param listener The listener to add.
	 * @param repeat If true, the timer will call the listener repeatedly.
	 * @param interval The interval (or delay) for calling the listener.
	 * @return True if the listener was added successfully, false otherwise.
	 */
	public boolean addListener(Listener listener,
							   boolean repeat,
							   int interval)
	{
		if (listener == null || interval <= 0) {
			return false;
		}
		
		for (int i = 0; i < MAX_LISTENER_COUNT; ++i) {
			if (_listeners[i] != null
					&& _listeners[i]._object == listener)
			{
				// Listener already exists
				System.out.println("MyTimer::addListener(): Listener already exists.");
				return false;
			}
		}
		
		for (int i = 0; i < MAX_LISTENER_COUNT; ++i) {
			if (_listeners[i] == null) {
				MyListener myListener = new MyListener();
				myListener._object = listener;
				myListener._repeat = repeat;
				myListener._interval = interval;
				myListener._lastTime = System.currentTimeMillis();
				_listeners[i] = myListener;
				return true;
			}
		}
		
		return false;
	}
	
	/**
	 * Removes the given listener.
	 * @param listener The listener to remove.
	 * @return True if the listener was found and removed, false otherwise.
	 */
	public boolean removeListener(Listener listener) {
		if (listener != null) {
			for (int i = 0; i < MAX_LISTENER_COUNT; ++i) {
				if (_listeners[i] != null && _listeners[i]._object == listener) {
					_listeners[i] = null;
					return true;
				}
			}
		}
		
		return false;
	}
	
	/**
	 * Interface for the listeners.
	 */
	public interface Listener {
		void onTimeout();
	}
	
	/**
	 * Internal class for reserving the meta information related to a listener.
	 */
	private class MyListener {
		private Listener _object;
		private boolean _repeat = false;
		private int _interval = 0; // Milliseconds
		private long _lastTime = 0;
	}
}