/**
*
*/
package xapi.collect.impl;
import xapi.fu.Filter.Filter1;
import xapi.fu.In1;
import xapi.fu.In1Out1;
import xapi.fu.X_Fu;
import java.util.Iterator;
import java.util.ListIterator;
import java.util.NoSuchElementException;
/**
* @author "James X. Nelson (james@wetheinter.net)"
*
*/
public class SimpleLinkedList<T>
extends
AbstractLinkedList<T, SimpleLinkedList.LinkedListNode<T>, SimpleLinkedList<T>> {
protected static class LinkedListNode<T> extends
AbstractLinkedList.Node<T, LinkedListNode<T>> {
LinkedListNode<T> previous;
}
protected final class ListIter implements ListIterator<T> {
private LinkedListNode<T> node;
int pos;
boolean forward, removed;
public ListIter(final LinkedListNode<T> start, final int pos) {
this.node = start;
this.pos = pos;
}
@Override
public void add(final T e) {
final LinkedListNode<T> newNode = newNode(e);
newNode.value = e;
newNode.next = node.next;
newNode.previous = node;
if (node.next == null) {
tail = newNode;
} else {
node.next.previous = newNode;
}
node.next = newNode;
onAdd(node, newNode);
node = newNode;
}
@Override
public boolean hasNext() {
return node != null && node.next != null;
}
@Override
public boolean hasPrevious() {
return node != head;
}
@Override
public T next() {
if (node.next == null) {
throw new NoSuchElementException();
}
try {
forward = true;
removed = false;
return node.next.value;
} finally {
pos++;
node = node.next;
}
}
@Override
public int nextIndex() {
return forward ? pos : pos - 1;
}
@Override
public T previous() {
try {
removed = forward = false;
if (node == head) {
throw new NoSuchElementException();
}
return node.value;
} finally {
pos--;
node = node.previous;
}
}
@Override
public int previousIndex() {
return forward ? pos-1 : pos;
}
@Override
public void remove() {
if (removed) {
throw new IllegalStateException();
}
removed = true;
if (forward) {
final LinkedListNode<T> prev = node.previous;
prev.next = node.next;
if (node.next == null) {
tail = prev;
} else {
prev.next.previous = prev;
}
node.next = null;
node.previous = null;
node.value = null;
node = prev;
pos --;
} else {
final LinkedListNode<T> back = node.next;
node.next = back.next;
if (back.next == null) {
tail = node;
} else {
back.next.previous = node;
}
back.next = null;
back.previous = null;
back.value = null;
if (head != tail) {
pos ++;
}
}
}
@Override
public void set(final T e) {
node.value = e;
}
}
public void forEachReverse(final In1<T> consumer) {
assert consumer != null;
final Iterator<T> reverse = iteratorReverse();
while (reverse.hasNext()) {
consumer.in(reverse.next());
}
}
public T findReverse(final Filter1<T> consumer) {
assert consumer != null;
final Iterator<T> reverse = iteratorReverse();
while (reverse.hasNext()) {
final T next = reverse.next();
if (consumer.filter1(next)) {
return next;
}
}
return null;
}
public <R> R findMappedReverse(final Filter1<T> consumer, In1Out1<T, R> mapper) {
assert consumer != null;
final Iterator<T> reverse = iteratorReverse();
while (reverse.hasNext()) {
final T next = reverse.next();
if (consumer.filter1(next)) {
return mapper.io(next);
}
}
return null;
}
public T findNotNullReverse() {
return findReverse(X_Fu::returnNotNull);
}
public <R> R findNotNullMappedReverse(In1Out1<T, R> mapper) {
return findMappedReverse(X_Fu::returnNotNull, mapper);
}
public Iterator<T> iteratorReverse() {
return new NodeIteratorReverse();
}
public Iterable<T> reverse() {
return NodeIteratorReverse::new;
}
protected final class NodeIteratorReverse implements Iterator<T> {
private LinkedListNode<T> next = tail;
@Override
public boolean hasNext() {
return next != head;
}
@Override
public T next() {
try {
return next.value;
} finally {
next = next.previous;
}
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
}
public ListIterator<T> listIterator() {
return new ListIter(head, 0);
}
@Override
public Iterator<T> iterator() {
// the remove function of the default iterator kinda sucks.
return listIterator();
}
@Override
protected LinkedListNode<T> newNode(final T item) {
return new LinkedListNode<T>();
}
@Override
protected void onAdd(final LinkedListNode<T> previous,
final LinkedListNode<T> next) {
next.previous = previous;
}
public synchronized T pop() {
if (head == tail) {
throw new IllegalStateException("Cannot pop from an empty list");
}
T value = tail.value;
tail.value = null;
tail = tail.previous;
return value;
}
}