package agg.util;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Vector;
import java.util.SortedSet;
import agg.util.csp.BinaryPredicate;
/*
* This ordered set does not allow any duplications.
*/
@SuppressWarnings("serial")
public class OrderedSet<E> extends Vector<E> implements SortedSet<E> {
@SuppressWarnings("rawtypes")
Comparator comp;
BinaryPredicate predicate;
Iterator<E> iter;
E obj;
public OrderedSet() {
super();
}
@SuppressWarnings("rawtypes")
public OrderedSet(Comparator comparator) {
this();
this.comp = comparator;
}
public OrderedSet(BinaryPredicate bp) {
this();
this.predicate = bp;
}
public OrderedSet(Collection<E> col) {
this();
Iterator<E> iter = col.iterator();
while (iter.hasNext()) {
this.add(iter.next());
}
}
@SuppressWarnings("rawtypes")
public OrderedSet(Collection<E> col, Comparator comparator) {
this(comparator);
Iterator<E> iter = col.iterator();
while (iter.hasNext()) {
this.add(iter.next());
}
}
public OrderedSet(SortedSet<E> ss) {
super();
this.comp = ss.comparator();
Iterator<E> iter = ss.iterator();
while (iter.hasNext()) {
this.add(iter.next());
}
}
public synchronized boolean add(E e) {
boolean res = false;
if (this.isEmpty()) {
res = super.add(e);
}
else if (this.comp != null) {
res = addByComparator(e);
}
else if (this.predicate != null) {
res = addByPredicate(e);
}
else if (!super.contains(e)) {
res = super.add(e);
}
return res;
}
public boolean remove(Object o) {
int i = (this.iter != null && this.obj != null)? this.indexOf(this.obj): -1;
int i1 = this.indexOf(o);
boolean res = super.remove(o);
if (res) {
if (i == -1 && this.iter != null) {
this.start();
}
else if (i==0 && i1==0) {
this.start();
}
else if (i>0) {
if (i>=i1) {
this.start();
for (int j=0; j<=i-1; j++) {this.get();}
}
else if (i<i1) {
this.start();
for (int j=0; j<=i; j++) {this.get();}
}
}
}
return res;
}
private boolean addByPredicate(E e) {
for (int i=this.size()-1; i>=0; i--) {
if (this.predicate.execute(e, this.get(i))) {
if (i == this.size()-1) {
return super.add(e);
}
else {
super.add(i+1, e);
return true;
}
}
else if (i > 0 && this.predicate.execute(e, this.get(i-1))) {
super.add(i, e);
return true;
}
else if (i == 0) {
super.add(i, e);
return true;
}
}
return false;
}
@SuppressWarnings("unchecked")
private boolean addByComparator(E e) {
for (int i=this.size()-1; i>=0; i--) {
int c = this.comp.compare(e, this.get(i));
if (c == 0) {
return false;
}
if (c > 0) {
if (i == this.size()-1) {
return super.add(e);
}
else {
super.add(i+1, e);
return true;
}
}
else if (i > 0 && this.comp.compare(e, this.get(i-1)) > 0) {
super.add(i, e);
return true;
}
else if (i == 0) {
super.add(i, e);
return true;
}
}
return false;
}
@SuppressWarnings("unchecked")
public Comparator<? super E> comparator() {
return this.comp;
}
public BinaryPredicate binaryPredicate() {
return this.predicate;
}
public SortedSet<E> subSet(E fromElement, E toElement) {
OrderedSet<E> set = new OrderedSet<E>();
int start = this.indexOf(fromElement);
int end = this.indexOf(toElement);
for (int i=start; i<=end; i++) {
set.add(this.get(i));
}
set.comp = this.comp;
set.predicate = this.predicate;
return set;
}
public SortedSet<E> headSet(E toElement) {
OrderedSet<E> set = new OrderedSet<E>(this.comp);
int end = this.indexOf(toElement);
for (int i=0; i<=end; i++) {
set.add(this.get(i));
}
set.comp = this.comp;
set.predicate = this.predicate;
return set;
}
public SortedSet<E> tailSet(E fromElement) {
OrderedSet<E> set = new OrderedSet<E>();
int start = this.indexOf(fromElement);
for (int i=start; i<this.size(); i++) {
set.add(this.get(i));
}
set.comp = this.comp;
set.predicate = this.predicate;
return set;
}
public E first() {
return !this.isEmpty()? this.firstElement(): null;
}
public E last() {
return !this.isEmpty()? this.lastElement(): null;
}
public void start() {
this.iter = this.iterator();
this.obj = null;
}
public E get() {
this.obj = this.iter.hasNext()? this.iter.next(): null;
return this.obj;
}
public boolean hasNext() {
if (this.iter == null)
this.start();
return this.iter.hasNext()? true: false;
}
public OrderedSet<E> union(OrderedSet<E> os) {
OrderedSet<E> set = new OrderedSet<E>();
for (int i=0; i<this.size(); i++) {
set.add(this.get(i));
}
for (int i=0; i<os.size(); i++) {
set.add(os.get(i));
}
set.comp = this.comp;
set.predicate = this.predicate;
return set;
}
}