package book; import clojure.lang.*; import java.util.*; //IPersistentVector, Iterable, // List, // RandomAccess, Comparable, // Serializable, IHashEq public class PersistentSortedList extends Obj implements Iterable, RandomAccess, Comparable, IHashEq, IPersistentList, IReduce, ISeq, List, Counted{ final private PersistentTreeMap impl; final private int _count; static private final PersistentSortedList EMPTY_DEFAULT_COMPARATOR = new PersistentSortedList(null, PersistentTreeMap.EMPTY, 0); private int _hasheq = 0; public static PersistentSortedList create(ISeq items){ PersistentSortedList ret = EMPTY_DEFAULT_COMPARATOR; for(; items != null; items = items.next()){ ret = ret.cons(items.first()); } return ret; } public static PersistentSortedList create(Comparator comp, ISeq items){ PersistentSortedList ret = new PersistentSortedList(null, new PersistentTreeMap(null, comp), 0); for(; items != null; items = items.next()){ ret = ret.cons(items.first()); } return ret; } PersistentSortedList(IPersistentMap meta, PersistentTreeMap impl, int count){ super(meta); this.impl = impl; this._count = count; } @Override public int count(){ return _count; } @Override public PersistentSortedList cons(final Object o){ final IPersistentCollection f = (IPersistentCollection) impl.get(o); IPersistentCollection newList = f == null ? new PersistentList(o) : f.cons(o); return new PersistentSortedList(meta(), impl.assoc(o, newList), _count + 1); } @Override public IPersistentCollection empty() { return new PersistentSortedList(null, new PersistentTreeMap(null, this.impl.comp), 0); } @Override public boolean equiv(Object obj) { if(!(obj instanceof Sequential || obj instanceof List)) return false; ISeq ms = RT.seq(obj); for(ISeq s = seq(); s != null; s = s.next(), ms = ms.next()){ if(ms == null || !Util.equiv(s.first(), ms.first())){ return false; } } return ms == null; } @Override public Object peek() { if(_count == 0){ return null; } final PersistentTreeMap.NodeIterator ite = this.impl.iterator(); final AMapEntry node = (AMapEntry) ite.next(); return ((IPersistentCollection) node.val()).seq().first(); } @Override public IPersistentStack pop() { if(_count == 0){ throw new IllegalStateException("Can't pop empty list"); } final PersistentTreeMap.NodeIterator ite = this.impl.iterator(); final AMapEntry node = (AMapEntry) ite.next(); if(((IPersistentCollection) node.val()).count() == 1){ final PersistentTreeMap nextImpl = impl.without(node.getKey()); return new PersistentSortedList(meta(), nextImpl, _count - 1); } final PersistentTreeMap nextImpl = impl.assoc(node.getKey(), ((IPersistentStack) node.getValue()).pop()); return new PersistentSortedList(meta(), nextImpl, _count -1); } @Override public Object reduce(IFn f) { Object ret = first(); for(ISeq s = (ISeq) next(); s != null; s = s.next()) { ret = f.invoke(ret, s.first()); if (RT.isReduced(ret)) return ((IDeref)ret).deref(); } return ret; } @Override public Object reduce(IFn f, Object start) { Object ret = f.invoke(start, first()); for(PersistentSortedList s = next(); s != null; s = s.next()) { if (RT.isReduced(ret)) return ((IDeref)ret).deref(); ret = f.invoke(ret, s.first()); } if (RT.isReduced(ret)) return ((IDeref)ret).deref(); return ret; } public Object first() { return peek(); } public PersistentSortedList next() { if(_count == 0){ return null; } final PersistentTreeMap.NodeIterator ite = this.impl.iterator(); final AMapEntry node = (AMapEntry) ite.next(); final ISeq nextValue = ((IPersistentCollection) node.val()).seq().next(); if(nextValue == null){ final PersistentTreeMap nextImpl = impl.without(node.getKey()); return impl.count() > 1 ? new PersistentSortedList(meta(), nextImpl, _count - 1) : null; } final PersistentTreeMap nextImpl = impl.assoc(node.getKey(), nextValue); return new PersistentSortedList(meta(), nextImpl, _count - 1); } // Things that i did not want to implement. private List reify(){ return Collections.unmodifiableList(new ArrayList(this)); } @Override public ISeq more() { ISeq s = next(); return s == null ? (PersistentSortedList) empty() : s; } @Override public Obj withMeta(IPersistentMap meta) { if(meta != meta()){ return new PersistentSortedList(meta, impl, _count); } return this; } @Override public int hasheq() { if(_hasheq == 0){ _hasheq = Murmur3.hashOrdered(this); } return _hasheq; } @Override public ISeq seq() { return count() == 0 ? null : (ISeq) this; } @Override public int compareTo(Object o) { return 0; } @Override public int size() { return count(); } @Override public boolean isEmpty() { return seq() == null; } @Override public boolean contains(Object o) { return impl.containsKey(o); } @Override public Object[] toArray() { return RT.seqToArray(seq()); } @Override public boolean add(Object o) { throw new UnsupportedOperationException(); } @Override public boolean remove(Object o) { throw new UnsupportedOperationException(); } @Override public boolean addAll(Collection collection) { throw new UnsupportedOperationException(); } @Override public boolean addAll(int i, Collection collection) { throw new UnsupportedOperationException(); } @Override public void clear() { throw new UnsupportedOperationException(); } @Override public Object get(int index) { return RT.nth(this, index); } @Override public Object set(int i, Object o) { throw new UnsupportedOperationException(); } @Override public void add(int i, Object o) { throw new UnsupportedOperationException(); } @Override public Object remove(int i) { throw new UnsupportedOperationException(); } @Override public int indexOf(Object o) { // TODO: make this function fast by using the underlying sorted set. This function should be constant. ISeq s = seq(); for(int i = 0; s != null; s = s.next(), i++) { if(Util.equiv(s.first(), o)){ return i; } } return -1; } @Override public int lastIndexOf(Object o) { // TODO: make this function fast by using the underlying sorted set. This function should be constant. return reify().lastIndexOf(o); } @Override public ListIterator listIterator() { return reify().listIterator(); } @Override public ListIterator listIterator(int index) { return reify().listIterator(index); } @Override public List subList(int fromIndex, int toIndex) { return reify().subList(fromIndex, toIndex); } @Override public boolean retainAll(Collection collection) { throw new UnsupportedOperationException(); } @Override public boolean removeAll(Collection collection) { throw new UnsupportedOperationException(); } @Override public boolean containsAll(Collection collection) { for(Object o : collection) { if(!contains(o)){ return false; } } return true; } @Override public Object[] toArray(Object[] objects) { return RT.seqToPassedArray(seq(), objects); } @Override public Iterator iterator() { return new SeqIterator(this); } }