package net.seninp.jmotif.sax.datastructure;
import java.util.Comparator;
import java.util.Iterator;
import java.util.NoSuchElementException;
import net.seninp.util.StackTrace;
/**
* Implement Iterable doubly linked list.
*
* @author psenin
*
* @param <T> the elemnt type.
*/
public class DoublyLinkedSortedList<T> {
private class MyIterator implements Iterator<T> {
private DoublyLinkedSortedList<T> list;
private Node<T> current;
public MyIterator(DoublyLinkedSortedList<T> doublyLinkedSortedList) {
this.list = doublyLinkedSortedList;
}
@Override
public boolean hasNext() {
if (null == this.current) {
if (this.list.isEmpty()) {
return false;
}
return true;
}
if (null == this.current.next) {
return false;
}
return true;
}
@Override
public T next() {
try {
if (null == current) {
current = this.list.first;
return current.data;
}
current = current.next;
return current.data;
}
catch (Exception e) {
throw new NoSuchElementException(
"There was an exception thrown: " + StackTrace.toString(e));
}
}
@Override
public void remove() {
throw new UnsupportedOperationException("The remove is unsupported.");
}
}
// private classes should be at the end of the file
private static class Node<T> {
protected T data;
protected Node<T> next;
@SuppressWarnings("unused")
protected Node<T> prev;
public Node(T data) {
this.data = data;
}
@Override
public String toString() {
return data.toString();
}
}
private int maxSize;
private Comparator<T> comparator;
private Node<T> first = null;
private int size = 0;
/**
* Constructor.
*
* @param listSize elements that falls off the list are discarded.
* @param comparator the comparator.
*/
public DoublyLinkedSortedList(int listSize, Comparator<T> comparator) {
this.maxSize = listSize;
this.comparator = comparator;
}
/**
* Adds a data instance.
*
* @param data the data to put in the list.
*/
public void addElement(T data) {
Node<T> newNode = new Node<T>(data);
if (isEmpty()) {
//
// if it is the very first node in the list
first = newNode;
size = 1;
}
else {
// if this node is greater than the list's head
//
if (this.comparator.compare(newNode.data, first.data) > 0) {
Node<T> tmp = first;
first = newNode;
first.next = tmp;
tmp.prev = first;
size++;
}
else {
Node<T> prev = first;
Node<T> current = first.next;
while (current != null) {
// if this node is the current node less than the new one
//
if (this.comparator.compare(newNode.data, current.data) > 0) {
prev.next = newNode;
newNode.prev = prev;
current.prev = newNode;
newNode.next = current;
size++;
break;
}
current = current.next;
prev = prev.next;
}
// if all list elements are greater than the new one
//
if (null == current) {
prev.next = newNode;
newNode.prev = prev;
size++;
}
if (size > this.maxSize) {
dropLastElement();
}
}
}
}
private void dropLastElement() {
if (this.size >= 2) {
Node<T> current = first;
while (current.next.next != null) {
current = current.next;
}
current.next.prev = null;
current.next = null;
this.size--;
}
}
public Iterator<T> iterator() {
return new MyIterator(this);
}
public boolean isEmpty() {
return (first == null);
}
}