package ru.gelin.android.bells.timers;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Collections of timers.
* Each timer in the collection is identified by the ID.
* ID is assigned to the timer during insertion.
* ID is used to find timer in the collection during update.
*/
public class TimerCollection {
/** Map of timers by ID */
Map<Integer, Timer> timers = new HashMap<Integer, Timer>();
/** IDs counter */
int idCounter;
/**
* Inserts new timer to collection.
* Sets the ID for the timer.
* @param timer ID of this timer is set
*/
public void insert(Timer timer) {
int id = getNextId();
timer.setId(id);
timers.put(id, timer.copy());
}
/**
* Updates timer in the collection.
* The timer with specified ID is updated
* @param timer timer (ID and values) to update
*/
public void update(Timer timer) {
timers.put(timer.getId(), timer.copy());
}
/**
* Selects one timer by ID.
*/
public Timer select(int id) {
return timers.get(id).copy();
}
/**
* Deletes one timer by ID.
*/
public Timer delete(int id) {
return timers.remove(id);
}
/**
* Deletes all timers from the collection.
*/
public void delete() {
timers.clear();
}
/**
* Returns the list of timers in the collection.
* The timers are ordered by the time of the alarm time acceding.
* Not the actual, but the deep copy of the original collection
* is returned, to modify any element of the collection perform
* {@link #update}.
* @param now current time, is used to sort the list
*/
public List<Timer> select(Date now) {
List<Timer> result = new ArrayList<Timer>(timers.size());
for (Timer timer : internalList(now)) {
result.add(timer.copy());
}
return result;
}
/**
* Returns sorted list of actual timers saved in the collection.
* @param now current time, is used to sort the list
*/
protected List<Timer> internalList(Date now) {
List<Timer> result = new ArrayList<Timer>(timers.size());
result.addAll(timers.values());
Collections.sort(result, new TimerComparator(now));
return result;
}
/**
* Returns unsorted list of actual timers saved in the collection.
*/
protected List<Timer> internalList() {
List<Timer> result = new ArrayList<Timer>(timers.size());
result.addAll(timers.values());
return result;
}
/**
* Returns the current size of the collection.
*/
public int size() {
return timers.size();
}
/**
* Selects all timers which alarms have came.
* <pre>
* now
* -------------|---------------
* start alarm
* ----------------|------------
* start alarm
* ----period----
* </pre>
*/
public List<Timer> selectAlarms(Date now) {
Date nowMinute = Timer.normalizeDate(now);
List<Timer> result = new ArrayList<Timer>();
for (Timer timer : internalList(now)) {
if (!timer.isEnabled()) {
continue;
}
Date start = timer.getStartTime();
if (!start.before(nowMinute)) {
continue; //will start in future
}
Date startPlusPeriod = timer.getPeriod().add(timer.getStartTime());
if (!startPlusPeriod.after(nowMinute)) {
result.add(timer.copy());
} else {
break;
}
}
return result;
}
/**
* Normalizes all alarms. I.e. shifts all it's times to make alarm time
* in future.
* Note that after calling this method {@link #selectAlarms} will
* return empty list.
*/
public void normalize(Date now) {
for (Timer timer : internalList(now)) {
timer.normalize(now);
}
}
/**
* Returns nearest alarm time, i.e. the alarm time of the first
* enabled timer in the sorted list.
* @return next alarm date or <code>null</code> if there is no enabled timers
*/
public Date alarmTime(Date now) {
for (Timer timer : internalList(now)) {
if (timer.isEnabled()) {
return timer.getAlarmTime(now);
}
}
return null;
}
/**
* Returns next ID for the inserting Timer
*/
int getNextId() {
return ++idCounter;
}
}
|