/**
* Copyright (c) Rich Hickey. All rights reserved.
* The use and distribution terms for this software are covered by the
* Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
* which can be found in the file epl-v10.html at the root of this distribution.
* By using this software in any fashion, you are agreeing to be bound by
* the terms of this license.
* You must not remove this notice, or any other, from this software.
**/
package com.trifork.clj_ds;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.NoSuchElementException;
public class PersistentList<T> extends ASeq<T> implements IPersistentList<T>, IReduce, List<T>, Counted {
private final T _first;
private final IPersistentList<T> _rest;
private final int _count;
final public static EmptyList EMPTY = new EmptyList(null);
public static final <T> IPersistentList<T> emptyList() {
return (IPersistentList<T>) EMPTY;
}
public PersistentList(T first){
this._first = first;
this._rest = null;
this._count = 1;
}
PersistentList(IPersistentMap meta, T _first, IPersistentList<T> _rest, int _count){
super(meta);
this._first = _first;
this._rest = _rest;
this._count = _count;
}
public static <T> IPersistentList<T> create(List<? extends T> init){
IPersistentList<T> ret = emptyList();
for(ListIterator<? extends T> i = init.listIterator(init.size()); i.hasPrevious();)
{
ret = (IPersistentList) ret.cons(i.previous());
}
return ret;
}
public T first(){
return _first;
}
public ISeq<T> next(){
if(_count == 1)
return null;
return (ISeq) _rest;
}
public T peek(){
return first();
}
public IPersistentList<T> pop(){
if(_rest == null)
return EMPTY.withMeta(_meta);
return _rest;
}
public int count(){
return _count;
}
public PersistentList<T> cons(T o){
return new PersistentList<T>(meta(), o, this, _count + 1);
}
public IPersistentCollection<T> empty(){
return EMPTY.withMeta(meta());
}
public PersistentList<T> withMeta(IPersistentMap meta){
if(meta != _meta)
return new PersistentList<T>(meta, _first, _rest, _count);
return this;
}
public Object reduce(IFn f) throws Exception{
Object ret = first();
for(ISeq s = next(); s != null; s = s.next())
ret = f.invoke(ret, s.first());
return ret;
}
public Object reduce(IFn f, Object start) throws Exception{
Object ret = f.invoke(start, first());
for(ISeq s = next(); s != null; s = s.next())
ret = f.invoke(ret, s.first());
return ret;
}
static class EmptyList<T> extends Obj implements IPersistentList<T>, List<T>, ISeq<T>, Counted{
public int hashCode(){
return 1;
}
public boolean equals(Object o) {
return (o instanceof Sequential || o instanceof List) && RT.seq(o) == null;
}
public boolean equiv(Object o){
return equals(o);
}
EmptyList(IPersistentMap meta){
super(meta);
}
public T first() {
return null;
}
public ISeq<T> next() {
return null;
}
public ISeq<T> more() {
return this;
}
public PersistentList<T> cons(T o){
return new PersistentList<T>(meta(), o, null, 1);
}
public IPersistentCollection<T> empty(){
return this;
}
public EmptyList<T> withMeta(IPersistentMap meta){
if(meta != meta())
return new EmptyList<T>(meta);
return this;
}
public T peek(){
return null;
}
public IPersistentList<T> pop(){
throw new IllegalStateException("Can't pop empty list");
}
public int count(){
return 0;
}
public ISeq<T> seq(){
return null;
}
public int size(){
return 0;
}
public boolean isEmpty(){
return true;
}
public boolean contains(Object o){
return false;
}
public Iterator<T> iterator(){
return new Iterator<T>(){
public boolean hasNext(){
return false;
}
public T next(){
throw new NoSuchElementException();
}
public void remove(){
throw new UnsupportedOperationException();
}
};
}
public Object[] toArray(){
return RT.EMPTY_ARRAY;
}
public boolean add(T o){
throw new UnsupportedOperationException();
}
public boolean remove(Object o){
throw new UnsupportedOperationException();
}
public boolean addAll(Collection<? extends T> collection){
throw new UnsupportedOperationException();
}
public void clear(){
throw new UnsupportedOperationException();
}
public boolean retainAll(Collection collection){
throw new UnsupportedOperationException();
}
public boolean removeAll(Collection collection){
throw new UnsupportedOperationException();
}
public boolean containsAll(Collection collection){
return collection.isEmpty();
}
public Object[] toArray(Object[] objects){
if(objects.length > 0)
objects[0] = null;
return objects;
}
//////////// List stuff /////////////////
private List<T> reify(){
return Collections.unmodifiableList(new ArrayList<T>(this));
}
public List<T> subList(int fromIndex, int toIndex){
return reify().subList(fromIndex, toIndex);
}
public T set(int index, T element){
throw new UnsupportedOperationException();
}
public T remove(int index){
throw new UnsupportedOperationException();
}
public int indexOf(Object o){
ISeq s = seq();
for(int i = 0; s != null; s = s.next(), i++)
{
if(Util.equiv(s.first(), o))
return i;
}
return -1;
}
public int lastIndexOf(Object o){
return reify().lastIndexOf(o);
}
public ListIterator<T> listIterator(){
return reify().listIterator();
}
public ListIterator<T> listIterator(int index){
return reify().listIterator(index);
}
public T get(int index){
return (T) RT.nth(this, index);
}
public void add(int index, Object element){
throw new UnsupportedOperationException();
}
public boolean addAll(int index, Collection c){
throw new UnsupportedOperationException();
}
}
}