package net.sf.openrocket.database;
import java.util.AbstractSet;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import net.sf.openrocket.database.DatabaseListener;
/**
* A database set. This class functions as a <code>Set</code> that contains items
* of a specific type. Additionally, the items can be accessed via an index number.
* The elements are always kept in their natural order.
*
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
*/
public class Database<T extends Comparable<T>> extends AbstractSet<T> {
protected final List<T> list = new ArrayList<T>();
private final ArrayList<DatabaseListener<T>> listeners = new ArrayList<DatabaseListener<T>>();
@Override
public Iterator<T> iterator() {
return new DBIterator();
}
@Override
public int size() {
return list.size();
}
@Override
public boolean add(T element) {
int index;
index = Collections.binarySearch(list, element);
if (index >= 0) {
// List might contain the element
if (list.contains(element)) {
return false;
}
} else {
index = -(index + 1);
}
list.add(index, element);
fireAddEvent(element);
return true;
}
/**
* Get the element with the specified index.
* @param index the index to retrieve.
* @return the element at the index.
*/
public T get(int index) {
return list.get(index);
}
/**
* Return the index of the given <code>Motor</code>, or -1 if not in the database.
*
* @param m the motor
* @return the index of the motor
*/
public int indexOf(T m) {
return list.indexOf(m);
}
public void addDatabaseListener(DatabaseListener<T> listener) {
listeners.add(listener);
}
public void removeChangeListener(DatabaseListener<T> listener) {
listeners.remove(listener);
}
@SuppressWarnings("unchecked")
protected void fireAddEvent(T element) {
Object[] array = listeners.toArray();
for (Object l : array) {
((DatabaseListener<T>) l).elementAdded(element, this);
}
}
@SuppressWarnings("unchecked")
protected void fireRemoveEvent(T element) {
Object[] array = listeners.toArray();
for (Object l : array) {
((DatabaseListener<T>) l).elementRemoved(element, this);
}
}
/**
* Iterator class implementation that fires changes if remove() is called.
*/
private class DBIterator implements Iterator<T> {
private Iterator<T> iterator = list.iterator();
private T current = null;
@Override
public boolean hasNext() {
return iterator.hasNext();
}
@Override
public T next() {
current = iterator.next();
return current;
}
@Override
public void remove() {
iterator.remove();
fireRemoveEvent(current);
}
}
}