package database;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import utils.ObserverMessage;
import utils.Pair;
public class SortableList<T, U> extends AbstractList<Pair<T, U>> implements Observer {
private DBMap<T, U> db;
private int index;
private boolean descending;
private int position;
private Iterator<T> iterator;
private Pattern pattern;
private int size;
private Pair<T, U> lastValue;
private Collection<T> keys;
public SortableList(DBMap<T, U> db)
{
this.db = db;
//LOAD DEFAULT ITERATOR
this.index = DBMap.DEFAULT_INDEX;
this.size = db.size();
this.descending = false;
this.iterator = this.filter(db.getIterator(DBMap.DEFAULT_INDEX, this.descending));
this.position = 0;
}
public SortableList(DBMap<T, U> db, Collection<T> keys)
{
this.db = db;
this.keys = keys;
//LOAD DEFAULT ITERATOR
this.index = DBMap.DEFAULT_INDEX;
this.size = keys.size();
this.descending = false;
this.iterator = keys.iterator();
this.position = 0;
}
public void registerObserver()
{
this.db.addObserver(this);
}
public void removeObserver()
{
this.db.deleteObserver(this);
}
@Override
public Pair<T, U> get(int i) {
//CHECK IF LAST VALUE
if(this.position-1 == i && this.lastValue != null)
{
return this.lastValue;
}
if(i < this.position)
{
//RESET ITERATOR
if(this.keys != null)
{
this.iterator = this.filter(this.keys.iterator());
}
else
{
this.iterator = this.filter(this.db.getIterator(this.index, this.descending));
}
this.position = 0;
}
//ITERATE UNTIL WE ARE AT THE POSITION
while(this.position < i)
{
this.iterator.next();
this.position++;
}
//RETURN
T key = this.iterator.next();
U value = this.db.get(key);
this.position++;
this.lastValue = new Pair<T, U>(key, value);
return this.lastValue;
}
@Override
public int size() {
return this.size;
}
public void sort(int index)
{
this.sort(index, false);
}
public void sort(int index, boolean descending)
{
this.index = index;
this.descending = descending;
if(this.keys != null)
{
this.size = this.keys.size();
this.iterator = this.keys.iterator();
}
else
{
this.size = db.size();
this.iterator = this.filter(this.db.getIterator(index, descending));
}
this.position = 0;
this.lastValue = null;
}
@Override
public void update(Observable o, Object object) {
ObserverMessage message = (ObserverMessage) object;
if(message.getType() == this.db.getObservableData().get(DBMap.NOTIFY_ADD) || message.getType() == this.db.getObservableData().get(DBMap.NOTIFY_REMOVE))
{
//RESET DATA
this.sort(this.index, this.descending);
}
}
private Iterator<T> filter(Iterator<T> iterator)
{
if(this.pattern != null)
{
List<T> keys = new ArrayList<T>();
while(iterator.hasNext())
{
T key = iterator.next();
String keyString = key.toString();
Matcher matcher = this.pattern.matcher(keyString);
if(matcher.find())
{
keys.add(key);
}
}
this.size = keys.size();
return (Iterator<T>) keys.iterator();
}
return iterator;
}
public void setFilter(String filter)
{
this.pattern = Pattern.compile(".*" + filter + ".*");
this.sort(this.index, this.descending);
}
}