/* NotableLinkedList.java

	Purpose:
		
	Description:
		
	History:
		Fri Sep 10 09:03:59 TST 2010, Created by tomyeh

Copyright (C) 2010 Potix Corporation. All Rights Reserved.

*/
package org.zkoss.util;

import java.util.List;
import java.util.ListIterator;
import java.util.LinkedList;
import java.util.AbstractSequentialList;

/**
 * Linked list implementation of the <tt>List</tt> interface
 * that provides the callback methods such as {@link #onAdd}, {@link #onSet}
 * and {@link #onRemove}.
 * @author tomyeh
 * @since 5.0.8
 */
public class NotableLinkedList<E> extends AbstractSequentialList<E>
implements List<E>, Cloneable, java.io.Serializable {
	private final LinkedList<E> _list = new LinkedList<E>();

	public NotableLinkedList() {
	}
	
	public int size() {
		return _list.size();
	}
	
	public ListIterator<E> listIterator(int index) {
		return new ListIter(index);
	}

	/** Called each time an new element is about being added into the array.
	 *
	 * <p>Deriving classes usually put checking codes here.
	 * And, throws exception if failure and nothing will be affected.
	 *
	 * @param newElement the element to be added
	 * @param followingElement the element that will 'follow' the new element.
	 * In other words, newElement will be inserted <b>before</b>
	 * followingElement. If null, it means newElement is appended at the end
	 */
	protected void onAdd(E newElement, E followingElement) {
	}
	/** Called each time an element is about being assigned into the array
	 * and replace an existence one (by ListIterator.set).
	 *
	 * <p>Deriving classes usually put checking codes here.
	 * And, throws exception if failure and nothing will be affected.
	 *
	 * @param newElement the element to be added
	 * @param replaced the element to be replaced
	 */
	protected void onSet(E newElement, E replaced) {
	}
	/** Called each time an element is about being removed from the array.
	 * Deriving classes usually put checking codes here.
	 * And, throws exception if failure.
	 */
	protected void onRemove(E element) {
	}

	private class ListIter implements ListIterator<E> {
		private final ListIterator<E> _iter;
		private E _last;
		private boolean _lastReady;
	
		private ListIter(int index) {
			_iter = _list.listIterator(index);
		}
		
		public void add(E o) {
			final E nxt;
			if (hasNext()) {
				nxt = next();
				previous();
			} else {
				nxt = null;
			}
			onAdd(o, nxt);
			_iter.add(o);
		}
		
		public boolean hasNext() {
			return _iter.hasNext();
		}
		
		public boolean hasPrevious() {
			return _iter.hasPrevious();
		}
		
		public E next() {
			_last = _iter.next();
			_lastReady = true;
			return _last;
		}
		
		public E previous() {
			_last = _iter.previous();
			_lastReady = true;
			return _last;
		}
		
		public int nextIndex() {
			return _iter.nextIndex();
		}
		
		public int previousIndex() {
			return _iter.previousIndex();
		}
		
		public void remove() {
			if (_lastReady)
				onRemove(_last);
			_iter.remove();
			_lastReady = false;
		}
		
		public void set(E o) {
			if (_lastReady)
				onSet(o, _last);
			_iter.set(o);
		}
	}
}
