package pt.ist.fenixframework.core.adt.skiplist;
import java.util.Collection;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Random;
import java.util.Set;
import pt.ist.fenixframework.core.AbstractDomainObject;
public class SkipList<T extends AbstractDomainObject> extends SkipList_Base implements Set<T>{
private transient final static double probability = 0.25;
private transient final static int maxLevel = 32;
private transient final static ThreadLocal<Random> random = new ThreadLocal<Random>() {
protected Random initialValue() {
return new Random();
}
};
private transient final static AbstractDomainObject minValue = new AbstractDomainObject() {
protected void ensureOid() {};
public Comparable getOid() {
return Long.MIN_VALUE;
};
};
private transient final static AbstractDomainObject maxValue = new AbstractDomainObject() {
protected void ensureOid() {};
public Comparable getOid() {
return Long.MAX_VALUE;
};
};
public SkipList() {
super();
setLevel(0);
SkipListNode head = new SkipListNode(maxLevel, minValue);
SkipListNode tail = new SkipListNode(maxLevel, maxValue);
setHead(head);
for (int i = 0; i <= maxLevel; i++) {
head.setForward(i, tail);
}
}
protected int randomLevel() {
int l = 0;
while (l < maxLevel && random.get().nextDouble() < probability)
l++;
return l;
}
public boolean insert(T value) {
boolean result;
SkipListNode[] update = new SkipListNode[maxLevel + 1];
SkipListNode node = getHead();
int level = getLevel();
Comparable toInsert = value.getOid();
Comparable oid = node.getOid();
for (int i = level; i >= 0; i--) {
SkipListNode next = node.getForward(i);
while ((oid = next.getValue().getOid()).compareTo(toInsert) < 0) {
node = next;
next = node.getForward(i);
}
update[i] = node;
}
node = node.getForward(0);
if (node.getValue().getOid().compareTo(toInsert) == 0) {
result = false;
} else {
int newLevel = randomLevel();
if (newLevel > level) {
for (int i = level + 1; i <= level; i++)
update[i] = getHead();
setLevel(level);
}
node = new SkipListNode(level, value);
for (int i = 0; i <= level; i++) {
node.setForward(i, update[i].getForward(i));
update[i].setForward(i, node);
}
result = true;
}
return result;
}
public boolean removeObject(T value) {
boolean result;
SkipListNode[] update = new SkipListNode[maxLevel + 1];
SkipListNode node = getHead();
int level = getLevel();
Comparable toInsert = value.getOid();
Comparable oid = node.getOid();
for (int i = level; i >= 0; i--) {
SkipListNode next = node.getForward(i);
while ((oid = next.getValue().getOid()).compareTo(toInsert) < 0) {
node = next;
next = node.getForward(i);
}
update[i] = node;
}
node = node.getForward(0);
if (node.getValue().getOid().compareTo(toInsert) != 0) {
result = false;
} else {
for (int i = 0; i <= level; i++) {
if (update[i].getForward(i).getOid().compareTo(node.getOid()) == 0)
update[i].setForward(i, node.getForward(i));
}
while (level > 0 && getHead().getForward(level).getForward(0) == null) {
level--;
setLevel(level);
}
result = true;
}
return result;
}
public boolean contains(T value) {
boolean result;
SkipListNode node = getHead();
int level = getLevel();
Comparable toInsert = value.getOid();
Comparable oid = node.getOid();
for (int i = level; i >= 0; i--) {
SkipListNode next = node.getForward(i);
while ((oid = next.getValue().getOid()).compareTo(toInsert) < 0) {
node = next;
next = node.getForward(i);
}
}
node = node.getForward(0);
result = (node.getValue().getOid().compareTo(toInsert) == 0);
return result;
}
public Iterator<T> iterator() {
return new Iterator<T>() {
private SkipListNode iter = getHead().getForward(0); // skip head tomb
@Override
public boolean hasNext() {
return iter != null && iter.getValue().getOid().compareTo(maxValue.getOid()) != 0;
}
@Override
public T next() {
if (iter == null || iter.getValue().getOid().compareTo(maxValue.getOid()) == 0) {
throw new NoSuchElementException();
}
Object value = iter.getValue();
iter = iter.getForward(0);
return (T)value;
}
@Override
public void remove() {
throw new UnsupportedOperationException("This implementation does not allow element removal via the iterator");
}
};
}
@Override
public boolean add(T e) {
return insert(e);
}
@Override
public boolean remove(Object o) {
if (! (o instanceof AbstractDomainObject)) {
return false;
}
return removeObject((T)o);
}
@Override
public boolean contains(Object o) {
if (! (o instanceof AbstractDomainObject)) {
return false;
}
return contains((T)o);
}
@Override
public int size() {
Iterator<T> iter = this.iterator();
int size = 0;
while (iter.hasNext()) {
size++;
iter.next();
}
return size;
}
/* The following methods are not needed at the moment but we need to implement Set */
@Override
public boolean addAll(Collection<? extends T> arg0) {
throw new UnsupportedOperationException();
}
@Override
public void clear() {
throw new UnsupportedOperationException();
}
@Override
public boolean containsAll(Collection<?> arg0) {
throw new UnsupportedOperationException();
}
@Override
public boolean isEmpty() {
throw new UnsupportedOperationException();
}
@Override
public boolean removeAll(Collection<?> arg0) {
throw new UnsupportedOperationException();
}
@Override
public boolean retainAll(Collection<?> arg0) {
throw new UnsupportedOperationException();
}
@Override
public Object[] toArray() {
throw new UnsupportedOperationException();
}
@Override
public <T> T[] toArray(T[] arg0) {
throw new UnsupportedOperationException();
}
}