package org.osgl.util;
import org.osgl.$;
import org.osgl.Osgl;
import org.osgl.exception.NotAppliedException;
import java.util.*;
import static org.osgl.util.C.Feature.SORTED;
public abstract class ListBase<T> extends AbstractList<T> implements C.List<T> {
private boolean sorted = false;
// utilities
protected final boolean isLazy() {
return is(C.Feature.LAZY);
}
protected final boolean isImmutable() {
return is(C.Feature.IMMUTABLE);
}
protected final boolean isReadOnly() {
return is(C.Feature.READONLY);
}
protected final boolean isMutable() {
return !isImmutable() && !isReadOnly();
}
protected void forEachLeft($.Function<? super T, ?> visitor) throws $.Break {
for (T t : this) {
try {
visitor.apply(t);
} catch (NotAppliedException e) {
// ignore
}
}
}
protected void forEachLeft($.Func2<Integer, ? super T, ?> indexedVisitor) throws $.Break {
for (int i = 0, j = size(); i < j; ++i) {
try {
indexedVisitor.apply(i, get(i));
} catch (NotAppliedException e) {
// ignore
}
}
}
protected void forEachRight($.Function<? super T, ?> visitor) throws $.Break {
Iterator<T> itr = reverseIterator();
while (itr.hasNext()) {
try {
visitor.apply(itr.next());
} catch (NotAppliedException e) {
// ignore
}
}
}
protected void forEachRight($.Func2<Integer, ? super T, ?> indexedVisitor) throws $.Break {
for (int i = size() - 1; i >= 0; --i) {
try {
indexedVisitor.apply(i, get(i));
} catch (NotAppliedException e) {
// ignore
}
}
}
@Override
public C.List<T> parallel() {
setFeature(C.Feature.PARALLEL);
return this;
}
@Override
public C.List<T> sequential() {
unsetFeature(C.Feature.PARALLEL);
return this;
}
@Override
public C.List<T> lazy() {
setFeature(C.Feature.LAZY);
return this;
}
@Override
public C.List<T> eager() {
unsetFeature(C.Feature.LAZY);
return this;
}
@Override
public C.List<T> snapshot() {
if (isImmutable()) {
return this;
}
return ListBuilder.toList(this);
}
@Override
public C.List<T> readOnly() {
if (isMutable()) {
return new ReadOnlyDelegatingList<T>(this);
}
return this;
}
@Override
public C.List<T> copy() {
return C.newList(this);
}
@Override
public C.List<T> sorted() {
if (size() == 0) return C.newList();
T t = get(0);
C.List<T> l = copy();
if (!(t instanceof Comparable)) {
return l;
}
Object[] a = l.toArray();
Arrays.sort(a);
ListIterator<T> i = l.listIterator();
for (int j=0; j<a.length; j++) {
i.next();
i.set((T)a[j]);
}
((ListBase)l).setFeature(SORTED);
sorted = true;
return l;
}
@Override
public C.List<T> sorted(Comparator<? super T> comparator) {
C.List<T> l = copy();
Collections.sort(l, comparator);
((ListBase)l).setFeature(SORTED);
return l;
}
@Override
public C.List<T> unique() {
Set<T> set = C.newSet();
C.List<T> retList = null;
int i = 0;
for (T t: this) {
i++;
if (set.contains(t)) {
if (null == retList) {
retList = C.newSizedList(size());
retList.addAll(subList(0, i - 1));
}
} else if (null != retList) {
retList.add(t);
}
set.add(t);
}
return null == retList ? this : retList;
}
public C.List<T> unique(Comparator<T> comp) {
Set<T> set = new TreeSet<T>(comp);
C.List<T> retList = null;
int i = 0;
for (T t: this) {
i++;
if (set.contains(t)) {
if (null == retList) {
retList = C.newSizedList(size());
retList.addAll(subList(0, i - 1));
}
} else if (null != retList) {
retList.add(t);
}
set.add(t);
}
return null == retList ? this : retList;
}
@Override
public C.List<T> subList(int fromIndex, int toIndex) {
if (fromIndex == toIndex) {
return Nil.list();
}
if (is(C.Feature.RANDOM_ACCESS)) {
return new RandomAccessSubList<T>(this, fromIndex, toIndex);
} else {
return new SubList<T>(this, fromIndex, toIndex);
}
}
@Override
public boolean add(T t) {
boolean b = super.add(t);
if (b) {
sorted = false;
}
return b;
}
@Override
public void add(int index, T element) {
super.add(index, element);
sorted = false;
unsetFeature(SORTED);
}
public boolean addAll(Iterable<? extends T> iterable) {
boolean modified = false;
Iterator<? extends T> e = iterable.iterator();
while (e.hasNext()) {
if (add(e.next())) {
modified = true;
}
}
sorted = !modified;
if (!sorted) {
unsetFeature(SORTED);
}
return modified;
}
@Override
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (o instanceof ListBase) {
return $.eq(features_, ((ListBase) o).features_) && super.equals(o);
}
return super.equals(o);
}
@Override
public int hashCode() {
return 31 * super.hashCode() + $.hc(features_);
}
// --- Featured methods
volatile private EnumSet<C.Feature> features_;
protected final EnumSet<C.Feature> features_() {
if (null == features_) {
synchronized (this) {
if (null == features_) {
features_ = initFeatures();
assert (null != features_);
}
}
}
return features_;
}
/**
* Sub class should override this method to provide initial feature
* set for the feature based instance
*
* @return the initial feature set configuration
*/
abstract protected EnumSet<C.Feature> initFeatures();
@Override
public final EnumSet<C.Feature> features() {
return EnumSet.copyOf(features_());
}
@Override
public final boolean is(C.Feature feature) {
return features_().contains(feature);
}
protected ListBase<T> setFeature(C.Feature feature) {
features_().add(feature);
return this;
}
protected ListBase<T> unsetFeature(C.Feature feature) {
features_().remove(feature);
return this;
}
// --- eof Featured methods
// --- Traversal methods
@Override
public boolean allMatch($.Function<? super T, Boolean> predicate) {
return !anyMatch($.F.negate(predicate));
}
@Override
public boolean anyMatch($.Function<? super T, Boolean> predicate) {
return findOne(predicate).isDefined();
}
@Override
public boolean noneMatch($.Function<? super T, Boolean> predicate) {
return !anyMatch(predicate);
}
@Override
public $.Option<T> findOne(final $.Function<? super T, Boolean> predicate) {
try {
forEach(new $.Visitor<T>() {
@Override
public void visit(T t) throws $.Break {
if (predicate.apply(t)) {
throw new $.Break(t);
}
}
});
return $.none();
} catch ($.Break b) {
T t = b.get();
return $.some(t);
}
}
// --- eof Traversal methods
@Override
public Iterator<T> iterator() {
return listIterator();
}
public abstract ListIterator<T> listIterator(int index);
@Override
public Iterator<T> reverseIterator() {
final ListIterator<T> li = listIterator(size());
return new Iterator<T>() {
@Override
public boolean hasNext() {
return li.hasPrevious();
}
@Override
public T next() {
return li.previous();
}
@Override
public void remove() {
li.remove();
}
};
}
@Override
public final T first() throws NoSuchElementException {
return head();
}
@Override
public T head() throws NoSuchElementException {
return iterator().next();
}
@Override
public T last() throws NoSuchElementException {
return reverseIterator().next();
}
@Override
public C.List<T> take(int n) {
boolean immutable = isImmutable();
if (n == 0) {
if (immutable) {
return Nil.list();
} else {
return C.newList();
}
} else if (n < 0) {
return drop(size() + n);
} else if (n >= size()) {
return this;
}
if (immutable) {
return subList(0, n);
}
C.List<T> l = C.newSizedList(n);
l.addAll(subList(0, n));
return l;
}
@Override
public C.List<T> takeWhile($.Function<? super T, Boolean> predicate) {
boolean immutable = isImmutable();
int sz = size();
if (immutable) {
if (0 == sz) {
return Nil.list();
}
ListBuilder<T> lb = new ListBuilder<T>(sz);
for (T t : this) {
if (predicate.apply(t)) {
lb.add(t);
} else {
break;
}
}
return lb.toList();
} else {
if (0 == sz) {
return C.newList();
}
C.List<T> l = C.newSizedList(sz);
for (T t : this) {
if (predicate.apply(t)) {
l.add(t);
} else {
break;
}
}
return l;
}
}
@Override
public C.List<T> drop(int n) throws IndexOutOfBoundsException {
int sz = size();
boolean immutable = isImmutable();
if (n < 0) {
n = -n;
if (n >= sz) {
if (immutable) return C.newList();
else return C.list();
} else {
return take(sz - n);
}
}
if (0 == n) {
return this;
}
// TODO handle lazy drop
if (immutable) {
return subList(n, size());
}
if (n >= sz) {
return C.newList();
}
C.List<T> l = C.newSizedList(sz - n);
l.addAll(subList(n, sz));
return l;
}
@Override
public C.List<T> dropWhile($.Function<? super T, Boolean> predicate) {
boolean immutable = isImmutable();
int sz = size();
if (immutable) {
if (0 == sz) {
return Nil.list();
}
ListBuilder<T> lb = new ListBuilder<T>(sz);
boolean found = false;
for (T t : this) {
if (!found && predicate.apply(t)) {
continue;
} else {
found = true;
lb.add(t);
}
}
return lb.toList();
} else {
if (0 == sz) {
return C.newList();
}
C.List<T> l = C.newSizedList(sz);
boolean found = false;
for (T t : this) {
if (!found && predicate.apply(t)) {
continue;
} else {
found = true;
l.add(t);
}
}
return l;
}
}
@Override
public C.List<T> remove($.Function<? super T, Boolean> predicate) {
boolean immutable = isImmutable();
int sz = size();
// TODO: handle lazy remove
if (immutable) {
if (0 == sz) {
return Nil.list();
}
ListBuilder<T> lb = new ListBuilder<T>(sz);
forEach($.predicate(predicate).elseThen(C.F.addTo(lb)));
return lb.toList();
} else {
if (0 == sz) {
return C.newList();
}
C.List<T> l = C.newSizedList(sz);
forEach($.predicate(predicate).elseThen(C.F.addTo(l)));
return l;
}
}
@Override
public <R> C.List<R> map($.Function<? super T, ? extends R> mapper) {
boolean immutable = isImmutable();
int sz = size();
if (isLazy()) {
return MappedList.of(this, mapper);
}
if (immutable) {
if (0 == sz) {
return Nil.list();
}
ListBuilder<R> lb = new ListBuilder<R>(sz);
forEach($.f1(mapper).andThen(C.F.addTo(lb)));
return lb.toList();
} else {
if (0 == sz) {
return C.newList();
}
C.List<R> l = C.newSizedList(sz);
forEach($.f1(mapper).andThen(C.F.addTo(l)));
return l;
}
}
@Override
public <R> C.List<R> flatMap($.Function<? super T, ? extends Iterable<? extends R>> mapper
) {
boolean immutable = isImmutable();
int sz = size();
// TODO: handle lazy flatmap
if (immutable) {
if (0 == sz) {
return Nil.list();
}
ListBuilder<R> lb = new ListBuilder<R>(sz * 3);
forEach($.f1(mapper).andThen(C.F.addAllTo(lb)));
return lb.toList();
} else {
if (0 == sz) {
return C.newList();
}
C.List<R> l = C.newSizedList(sz * 3);
forEach($.f1(mapper).andThen(C.F.addAllTo(l)));
return l;
}
}
@Override
public C.List<T> filter($.Function<? super T, Boolean> predicate) {
boolean immutable = isImmutable();
int sz = size();
// TODO: handle lazy filter
if (immutable) {
if (0 == sz) {
return Nil.list();
}
ListBuilder<T> lb = new ListBuilder<T>(sz);
forEach($.predicate(predicate).ifThen(C.F.addTo(lb)));
return lb.toList();
} else {
if (0 == sz) {
return C.newList();
}
C.List<T> l = C.newSizedList(sz);
forEach($.predicate(predicate).ifThen(C.F.addTo(l)));
return l;
}
}
@Override
public Osgl.T2<C.List<T>, C.List<T>> split(final Osgl.Function<? super T, Boolean> predicate) {
final C.List<T> left = C.newList();
final C.List<T> right = C.newList();
accept(new $.Visitor<T>() {
@Override
public void visit(T t) throws Osgl.Break {
if (predicate.apply(t)) {
left.add(t);
} else {
right.add(t);
}
}
});
if (isImmutable() || isReadOnly()) {
return $.T2(C.list(left), C.list(right));
}
return $.T2(left, right);
}
private Cursor<T> fromLeft() {
return new ListIteratorCursor<T>(listIterator(0));
}
private Cursor<T> fromRight() {
return new ListIteratorCursor<T>(listIterator(size()));
}
@Override
public Cursor<T> locateFirst($.Function<T, Boolean> predicate) {
Cursor<T> c = fromLeft();
while (c.hasNext()) {
T t = c.forward().get();
if (predicate.apply(t)) {
return c;
}
}
return c;
}
@Override
public Cursor<T> locate($.Function<T, Boolean> predicate) {
return locateFirst(predicate);
}
@Override
public Cursor<T> locateLast($.Function<T, Boolean> predicate) {
Cursor<T> c = fromRight();
while (c.hasPrevious()) {
T t = c.backward().get();
if (predicate.apply(t)) {
return c;
}
}
return c;
}
@Override
public C.List<T> insert(int index, T t) throws IndexOutOfBoundsException {
int sz = size();
if (sz < Math.abs(index)) {
throw new IndexOutOfBoundsException();
}
if (index < 0) {
index = sz + index;
}
if (isMutable()) {
add(index, t);
return this;
}
if (isImmutable()) {
ListBuilder<T> lb = new ListBuilder<T>(sz + 1);
if (index > 0) {
lb.addAll(subList(0, index));
}
lb.add(t);
if (index < sz) {
lb.addAll(subList(index, sz));
}
return lb.toList();
} else {
C.List<T> l = C.newSizedList(sz + 1);
if (index > 0) {
l.addAll(subList(0, index));
}
l.add(t);
if (index < sz) {
l.addAll(subList(index, sz));
}
return l;
}
}
@Override
public C.List<T> insert(int index, T... ta) throws IndexOutOfBoundsException {
if (ta.length == 0) {
return this;
}
return insert(index, C.listOf(ta));
}
@Override
public C.List<T> insert(int index, List<T> subList) throws IndexOutOfBoundsException {
if (subList.isEmpty()) {
return this;
}
int sz = size();
if (sz < Math.abs(index)) {
throw new IndexOutOfBoundsException();
}
if (index < 0) {
index = sz + index;
}
if (isMutable()) {
addAll(index, subList);
return this;
}
if (isImmutable()) {
int delta = subList.size();
ListBuilder<T> lb = new ListBuilder<T>(sz + delta);
if (index > 0) {
lb.addAll(subList(0, index));
}
lb.addAll(subList);
if (index < sz) {
lb.addAll(subList(index, sz));
}
return lb.toList();
} else {
C.List<T> l = C.newSizedList(sz + 1);
if (index > 0) {
l.addAll(subList(0, index));
}
l.addAll(subList);
if (index < sz) {
l.addAll(subList(index, sz));
}
return l;
}
}
@Override
public C.List<T> reverse() {
if (isLazy()) {
return ReverseList.wrap(this);
}
boolean immutable = isImmutable();
int sz = size();
if (immutable) {
if (0 == sz) {
return Nil.list();
}
ListBuilder<T> lb = new ListBuilder<T>(sz);
Iterator<T> itr = reverseIterator();
while (itr.hasNext()) {
lb.add(itr.next());
}
return lb.toList();
} else {
if (0 == sz) {
return C.newList();
}
C.List<T> l = C.newSizedList(sz);
Iterator<T> itr = reverseIterator();
while (itr.hasNext()) {
l.add(itr.next());
}
return l;
}
}
@Override
public C.List<T> without(Collection<? super T> col) {
return filter($.F.negate(C.F.containsIn(col)));
}
@Override
public C.List<T> without(T element) {
return filter(($.F.ne().curry(element)));
}
@Override
public C.List<T> without(T element, T... elements) {
elements = $.concat(elements, element);
C.List<T> l = without(element);
int len = elements.length;
if (0 == len) {
return l;
}
boolean c = false;
if (8 < len) {
T t0 = elements[0];
if (t0 instanceof Comparable) {
c = true;
Arrays.sort(elements);
}
}
C.List<T> lr = C.newSizedList(l.size());
if (c) {
for (T t : l) {
int id = Arrays.binarySearch(elements, t);
if (id == -1) continue;
lr.add(t);
}
} else {
for (T t : l) {
boolean found = false;
for (int i = 0; i < len; ++i) {
if ($.eq(elements[i], t)) {
found = true;
break;
}
}
if (!found) lr.add(t);
}
}
return lr;
}
@Override
public C.List<T> accept($.Function<? super T, ?> visitor) {
forEachLeft(visitor);
return this;
}
@Override
public C.List<T> each($.Function<? super T, ?> visitor) {
return accept(visitor);
}
@Override
public C.List<T> forEach($.Function<? super T, ?> visitor) {
return accept(visitor);
}
@Override
public C.List<T> acceptLeft($.Function<? super T, ?> visitor) {
forEachLeft(visitor);
return this;
}
@Override
public C.List<T> acceptRight($.Function<? super T, ?> visitor) {
forEachRight(visitor);
return this;
}
@Override
public C.List<T> accept($.Func2<Integer, ? super T, ?> indexedVisitor) {
forEachLeft(indexedVisitor);
return this;
}
@Override
public C.List<T> each($.Func2<Integer, ? super T, ?> indexedVisitor) {
return accept(indexedVisitor);
}
@Override
public C.List<T> forEach($.Func2<Integer, ? super T, ?> indexedVisitor) {
return accept(indexedVisitor);
}
@Override
public C.List<T> acceptLeft($.Func2<Integer, ? super T, ?> indexedVisitor) {
forEachLeft(indexedVisitor);
return this;
}
@Override
public C.List<T> acceptRight($.Func2<Integer, ? super T, ?> indexedVisitor) {
forEachRight(indexedVisitor);
return this;
}
@Override
public C.List<T> head(int n) {
return take(n);
}
@Override
public C.List<T> tail() {
int sz = size();
if (0 == sz) {
throw new UnsupportedOperationException();
}
if (isImmutable()) {
return subList(1, sz);
}
C.List<T> l = C.newSizedList(sz - 1);
l.addAll(subList(1, sz));
return l;
}
@Override
public C.List<T> tail(int n) {
boolean immutable = isImmutable();
int sz = size();
if (n < 0) {
return head(-n);
} else if (n == 0) {
if (immutable) {
return Nil.list();
} else {
return C.newList();
}
} else if (n >= sz) {
return this;
}
C.List<T> sl = subList(sz - n, sz);
if (immutable) {
return sl;
}
C.List<T> l = C.newSizedList(n);
l.addAll(sl);
return l;
}
@SuppressWarnings("unchecked")
private C.List<T> unLazyAppend(Iterable<? extends T> iterable) {
if (isMutable()) {
if (iterable instanceof Collection) {
addAll((Collection<? extends T>) iterable);
} else {
C.forEach(iterable, C.F.addTo(this));
}
return this;
}
// immutable
if (isImmutable()) {
ListBuilder<T> lb = new ListBuilder<T>(size() * 2);
lb.append(this).append(iterable);
return lb.toList();
}
// mutable but read only
C.List<T> l = C.newSizedList(size() * 2);
l.addAll(this);
l.addAll(iterable);
return l;
}
private C.List<T> unLazyAppend(Iterator<? extends T> iterator) {
if (isMutable()) {
C.forEach(iterator, C.F.addTo(this));
return this;
}
ListBuilder<T> lb = new ListBuilder<T>(size() * 2);
lb.append(this).append(iterator);
return lb.toList();
}
private C.List<T> unLazyAppend(Enumeration<? extends T> enumeration) {
if (isMutable()) {
C.forEach(new EnumerationIterator<T>(enumeration), C.F.addTo(this));
return this;
}
ListBuilder<T> lb = new ListBuilder<T>(size() * 2);
lb.append(this).append(enumeration);
return lb.toList();
}
@Override
@SuppressWarnings("unchecked")
public C.Sequence<T> append(Iterable<? extends T> iterable) {
if (iterable instanceof C.List) {
return appendList((C.List<T>) iterable);
} else if (iterable instanceof C.Sequence) {
return append((C.Sequence<T>) iterable);
} else if (iterable instanceof Collection) {
return append((Collection<? extends T>) iterable);
} else if (isLazy()) {
return CompositeSeq.of(this, IterableSeq.of(iterable));
} else {
return unLazyAppend(iterable);
}
}
@Override
@SuppressWarnings("unchecked")
public C.List<T> append(Collection<? extends T> collection) {
if (collection instanceof C.List) {
return appendList((C.List<T>) collection);
} else {
return unLazyAppend(collection);
}
}
@Override
public C.Sequence<T> append(C.Sequence<? extends T> seq) {
if (seq instanceof C.List) {
return appendList((C.List<T>) seq);
}
if (isLazy()) {
return CompositeSeq.of(this, seq);
}
return unLazyAppend(seq);
}
@Override
public C.Sequence<T> append(Iterator<? extends T> iterator) {
if (isLazy()) {
return CompositeSeq.of(this, C.seq(iterator));
}
return unLazyAppend(iterator);
}
@Override
public C.Sequence<T> append(Enumeration<? extends T> enumeration) {
return append(new EnumerationIterator<T>(enumeration));
}
protected C.ReversibleSequence<T> appendReversibleSeq(C.ReversibleSequence<T> seq) {
if (seq instanceof C.List) {
return appendList((C.List<T>) seq);
}
// TODO support lazy append reversible sequence
return unLazyAppend(seq);
}
public C.ReversibleSequence<T> append(C.ReversibleSequence<T> seq) {
return appendReversibleSeq(seq);
}
protected C.List<T> appendList(C.List<T> list) {
if (isLazy()) {
return CompositeList.of(this, list);
}
return unLazyAppend(list);
}
@Override
public C.List<T> append(C.List<T> list) {
return appendList(list);
}
@Override
public C.List<T> append(T t) {
if (isMutable()) {
add(t);
return this;
}
// Immutable
if (isImmutable()) {
ListBuilder<T> lb = new ListBuilder<T>(size() + 1);
lb.addAll(this);
lb.add(t);
return lb.toList();
}
// mutable but readonly
C.List<T> l = C.newSizedList(size() + 1);
l.addAll(this);
l.add(t);
return l;
}
private C.List<T> unLazyPrepend(Iterable<? extends T> iterable) {
if (isMutable()) {
int pos = 0;
for (T t : iterable) {
add(pos++, t);
}
return this;
}
// immutable
if (isImmutable()) {
ListBuilder<T> lb = new ListBuilder<T>(size() * 2);
lb.append(iterable).append(this);
return lb.toList();
}
// mutable but read only
C.List<T> l = C.newSizedList(size() * 2);
l.addAll(iterable);
l.addAll(this);
return l;
}
private C.List<T> unLazyPrepend(Iterator<? extends T> iterator) {
if (isMutable()) {
int pos = 0;
while (iterator.hasNext()) {
add(pos++, iterator.next());
}
return this;
}
ListBuilder<T> lb = new ListBuilder<T>(size() * 2);
lb.append(iterator).append(this);
return lb.toList();
}
private C.List<T> unLazyPrepend(Enumeration<? extends T> enumeration) {
if (isMutable()) {
int pos = 0;
while (enumeration.hasMoreElements()) {
add(pos++, enumeration.nextElement());
}
return this;
}
ListBuilder<T> lb = new ListBuilder<T>(size() * 2);
lb.append(enumeration).append(this);
return lb.toList();
}
@Override
@SuppressWarnings("unchecked")
public C.List<T> prepend(Collection<? extends T> collection) {
if (collection instanceof C.List) {
return prependList((C.List<T>) collection);
}
return unLazyPrepend(collection);
}
@Override
@SuppressWarnings("unchecked")
public C.Sequence<T> prepend(Iterable<? extends T> iterable) {
if (iterable instanceof C.List) {
return prependList((C.List<T>) iterable);
} else if (iterable instanceof C.Sequence) {
return prepend((C.Sequence<T>) iterable);
} else if (iterable instanceof Collection) {
return prepend((Collection<? extends T>) iterable);
} else if (isLazy()) {
return CompositeSeq.of(IterableSeq.of(iterable), this);
} else {
return unLazyPrepend(iterable);
}
}
@Override
public C.Sequence<T> prepend(Iterator<? extends T> iterator) {
if (!iterator.hasNext()) {
return this;
}
if (isLazy()) {
return CompositeSeq.of(C.seq(iterator), this);
}
return unLazyAppend(iterator);
}
@Override
public C.Sequence<T> prepend(Enumeration<? extends T> enumeration) {
if (isLazy()) {
return CompositeSeq.of(C.seq(enumeration), this);
}
return unLazyAppend(enumeration);
}
/**
* {@inheritDoc}
* This method will NOT change the underline list
*
* @param seq the sequence to be prepended
* @return the prepended sequence
*/
@Override
public C.Sequence<T> prepend(C.Sequence<? extends T> seq) {
if (seq instanceof C.List) {
return prependList((C.List<T>) seq);
}
if (isLazy()) {
return new CompositeSeq<T>(seq, this);
}
return unLazyPrepend(seq);
}
protected C.ReversibleSequence<T> prependReversibleSeq(C.ReversibleSequence<T> seq) {
if (seq instanceof C.List) {
return prependList((C.List<T>) seq);
}
// TODO support lazy append reversible sequence
return unLazyPrepend(seq);
}
public C.ReversibleSequence<T> prepend(C.ReversibleSequence<T> seq) {
return prependReversibleSeq(seq);
}
protected C.List<T> prependList(C.List<T> list) {
if (isLazy()) {
return CompositeList.of(list, this);
}
return unLazyPrepend(list);
}
/**
* {@inheritDoc}
* This method will NOT change the underline list
*/
@Override
public C.List<T> prepend(C.List<T> list) {
return prependList(list);
}
/**
* {@inheritDoc}
* For mutable list, this method will insert the
* element at {@code 0} position.
*/
@Override
public C.List<T> prepend(T t) {
if (isMutable()) {
add(0, t);
return this;
}
// immutable
if (isImmutable()) {
ListBuilder<T> lb = new ListBuilder<T>(size() + 1);
lb.add(t);
lb.addAll(this);
return lb.toList();
}
// readonly but mutable
C.List<T> l = C.newSizedList(size() + 1);
l.add(t);
l.addAll(this);
return l;
}
@Override
public <R> R reduce(R identity, $.Func2<R, T, R> accumulator) {
return reduceLeft(identity, accumulator);
}
@Override
public <R> R reduceLeft(R identity, $.Func2<R, T, R> accumulator) {
R ret = identity;
for (T t : this) {
ret = accumulator.apply(ret, t);
}
return ret;
}
@Override
public <R> R reduceRight(R identity, $.Func2<R, T, R> accumulator) {
R ret = identity;
Iterator<T> i = reverseIterator();
while (i.hasNext()) {
ret = accumulator.apply(ret, i.next());
}
return ret;
}
@Override
public $.Option<T> reduce($.Func2<T, T, T> accumulator) {
return reduceLeft(accumulator);
}
private $.Option<T> reduceIterator(Iterator<T> itr, $.Func2<T, T, T> accumulator) {
if (!itr.hasNext()) {
return $.none();
}
T ret = itr.next();
while (itr.hasNext()) {
ret = accumulator.apply(ret, itr.next());
}
return $.some(ret);
}
@Override
public $.Option<T> reduceLeft($.Func2<T, T, T> accumulator) {
return reduceIterator(iterator(), accumulator);
}
@Override
public $.Option<T> reduceRight($.Func2<T, T, T> accumulator) {
return reduceIterator(reverseIterator(), accumulator);
}
private $.Option<T> findIterator(Iterator<T> itr, $.Function<? super T, Boolean> predicate) {
while (itr.hasNext()) {
T t = itr.next();
if (predicate.apply(t)) {
return $.some(t);
}
}
return $.none();
}
public $.Option<T> findFirst($.Function<? super T, Boolean> predicate) {
return findIterator(iterator(), predicate);
}
@Override
public $.Option<T> findLast($.Function<? super T, Boolean> predicate) {
return findIterator(reverseIterator(), predicate);
}
@Override
public <T2> C.List<$.T2<T, T2>> zip(List<T2> list) {
return new ZippedList<T, T2>(this, list);
}
@Override
public <T2> C.List<$.T2<T, T2>> zipAll(List<T2> list, T def1, T2 def2) {
return new ZippedList<T, T2>(this, list, def1, def2);
}
@Override
public C.Sequence<$.T2<T, Integer>> zipWithIndex() {
return new ZippedSeq<T, Integer>(this, new IndexIterable(this));
}
@Override
public <T2> C.Sequence<$.T2<T, T2>> zip(Iterable<T2> iterable) {
if (iterable instanceof List) {
return zip((List<T2>) iterable);
}
return new ZippedSeq<T, T2>(this, iterable);
}
@Override
public <T2> C.Sequence<$.T2<T, T2>> zipAll(Iterable<T2> iterable, T def1, T2 def2) {
if (iterable instanceof List) {
return zipAll((List<T2>) iterable, def1, def2);
}
return new ZippedSeq<T, T2>(this, iterable, def1, def2);
}
@Override
public <T2> C.ReversibleSequence<$.T2<T, T2>> zip(C.ReversibleSequence<T2> rseq) {
if (rseq instanceof C.List) {
return zip((java.util.List<T2>) rseq);
}
return new ZippedRSeq<T, T2>(this, rseq);
}
@Override
public <T2> C.ReversibleSequence<$.T2<T, T2>> zipAll(C.ReversibleSequence<T2> rseq, T def1, T2 def2) {
if (rseq instanceof C.List) {
return zipAll((java.util.List<T2>) rseq, def1, def2);
}
return new ZippedRSeq<T, T2>(this, rseq, def1, def2);
}
@Override
public int count(T t) {
if (sorted) {
int pos = indexOf(t);
if (pos < 0) {
return 0;
}
int n = 1;
for (int i = pos + 1; i < size(); ++i) {
if ($.eq(t, get(i))) {
n++;
} else {
break;
}
}
return n;
}
return SequenceBase.count(this, t);
}
int modCount() {
return modCount;
}
void removeRange2(int fromIndex, int toIndex) {
super.removeRange(fromIndex, toIndex);
}
}
class SubList<E> extends ListBase<E> implements C.List<E> {
private ListBase<E> l;
private int offset;
private int size;
private int expectedModCount;
SubList(ListBase<E> list, int fromIndex, int toIndex) {
if (fromIndex < 0)
throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
if (toIndex > list.size())
throw new IndexOutOfBoundsException("toIndex = " + toIndex);
if (fromIndex > toIndex)
throw new IllegalArgumentException("fromIndex(" + fromIndex +
") > toIndex(" + toIndex + ")");
l = list;
offset = fromIndex;
size = toIndex - fromIndex;
expectedModCount = l.modCount();
}
@Override
protected EnumSet<C.Feature> initFeatures() {
return l.features();
}
public E set(int index, E element) {
rangeCheck(index);
checkForComodification();
return l.set(index + offset, element);
}
public E get(int index) {
rangeCheck(index);
checkForComodification();
return l.get(index + offset);
}
public int size() {
checkForComodification();
return size;
}
public void add(int index, E element) {
if (index < 0 || index > size)
throw new IndexOutOfBoundsException();
checkForComodification();
l.add(index + offset, element);
expectedModCount = l.modCount();
size++;
modCount++;
}
public E remove(int index) {
rangeCheck(index);
checkForComodification();
E result = l.remove(index + offset);
expectedModCount = l.modCount();
size--;
modCount++;
return result;
}
protected void removeRange(int fromIndex, int toIndex) {
checkForComodification();
l.removeRange2(fromIndex + offset, toIndex + offset);
expectedModCount = l.modCount();
size -= (toIndex - fromIndex);
modCount++;
}
public boolean addAll(Collection<? extends E> c) {
return addAll(size, c);
}
public boolean addAll(int index, Collection<? extends E> c) {
if (index < 0 || index > size)
throw new IndexOutOfBoundsException(
"Index: " + index + ", Size: " + size);
int cSize = c.size();
if (cSize == 0)
return false;
checkForComodification();
l.addAll(offset + index, c);
expectedModCount = l.modCount();
size += cSize;
modCount++;
return true;
}
public Iterator<E> iterator() {
return listIterator();
}
public ListIterator<E> listIterator(final int index) {
checkForComodification();
if (index < 0 || index > size)
throw new IndexOutOfBoundsException(
"Index: " + index + ", Size: " + size);
return new ListIterator<E>() {
private ListIterator<E> i = l.listIterator(index + offset);
public boolean hasNext() {
return nextIndex() < size;
}
public E next() {
if (hasNext())
return i.next();
else
throw new NoSuchElementException();
}
public boolean hasPrevious() {
return previousIndex() >= 0;
}
public E previous() {
if (hasPrevious())
return i.previous();
else
throw new NoSuchElementException();
}
public int nextIndex() {
return i.nextIndex() - offset;
}
public int previousIndex() {
return i.previousIndex() - offset;
}
public void remove() {
i.remove();
expectedModCount = l.modCount();
size--;
modCount++;
}
public void set(E e) {
i.set(e);
}
public void add(E e) {
i.add(e);
expectedModCount = l.modCount();
size++;
modCount++;
}
};
}
public C.List<E> subList(int fromIndex, int toIndex) {
if (is(C.Feature.RANDOM_ACCESS)) {
return new RandomAccessSubList<E>(this, fromIndex, toIndex);
} else {
return new SubList<E>(this, fromIndex, toIndex);
}
}
private void rangeCheck(int index) {
if (index < 0 || index >= size)
throw new IndexOutOfBoundsException("Index: " + index +
",Size: " + size);
}
protected void checkForComodification() {
if (l.modCount() != expectedModCount)
throw new ConcurrentModificationException();
}
}
class RandomAccessSubList<E> extends SubList<E> implements RandomAccess {
RandomAccessSubList(ListBase<E> list, int fromIndex, int toIndex) {
super(list, fromIndex, toIndex);
}
public C.List<E> subList(int fromIndex, int toIndex) {
return new RandomAccessSubList<E>(this, fromIndex, toIndex);
}
}