/*
*
* Copyright (c) 2007
* Adrian Michel
* http://www.tradery.com
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. Adrian Michel makes no
* representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied warranty.
*/
package com.tradery.collections;
import java.util.Enumeration;
/**
* A doubly linked list of objects
*
* Note: this is not used anywhere and it has not been tested.
* It looks like there are flaws in the copy constructor and append/prepend lists
*/
public class List implements Cloneable
{
/**
* The first element in the list
*/
private Node first = null;
/**
* The last element in th elist
*/
private Node last = null;
/**
* A node in the list.
*
* Has links to the previous and next node in the list, and holds a reference
* to the payload object
*/
private class Node
{
/**
* Link to the previous node
*/
private Node prev = null;
/**
* Link to the next node
*/
private Node next = null;
/**
* The payload object
*/
private Object obj;
/**
* Constructor taking a payload object
*
* @param _obj
*/
Node( Object _obj ) { obj = _obj; }
/**
* Creates a new node with a reference the the payload object of anothre node.
*
* @param node
*/
Node( Node node ) { obj = node.getObject(); }
/**
* set/get methods for pref/next references
*
* @param node
*/
void setNext( Node node ) { next = node; }
void setPrev( Node node ) { prev = node; }
Node getNext() { return next; }
Node getPrev() { return prev; }
/**
* Indicate if the node has a next/prev node
*
* @return true if it has, false if it does not.
*/
boolean hasNext() { return next != null; }
boolean hasPrev() { return prev != null; }
/**
* Returns the payload object
*
* @return The payload object
*/
Object getObject() { return obj; }
public Object clone()
{
return null;
}
}
/**
* Implements an Enumerator object that allows a forward traversal of the tree
*/
private class ForwardEnumerator implements Enumeration
{
private Node crtNode = null;
public ForwardEnumerator( List list ) { crtNode = list.getFirst(); }
public boolean hasMoreElements() { return crtNode != null; }
public Object nextElement()
{
if( crtNode != null )
return ( crtNode = crtNode.getNext() ).getObject();
else
return null;
}
}
/**
* Appends a new node to the list
*
* @return
*/
private class ReverseEnumerator implements Enumeration
{
private Node crtNode = null;
public ReverseEnumerator( List list ) { crtNode = list.getLast(); }
public boolean hasMoreElements() { return crtNode != null; }
public Object nextElement()
{
if( crtNode != null )
return ( crtNode = crtNode.getPrev() ).getObject();
else
return null;
}
}
void append( Object obj )
{
Node node = new Node( obj );
Node oldLast = last;
if( last != null )
{
last = node;
oldLast.setNext( last );
}
last.setPrev( oldLast );
}
/**
* Prepends a new node to the list
*
* @param obj The new node
*/
void prepend( Object obj )
{
Node node = new Node( obj );
Node oldFirst = first;
if( first != null )
{
first = node;
oldFirst.setPrev( first );
}
first.setNext( oldFirst );
}
/**
* Gets the node at the beginning of the list
*
* @return the node at the beginning of the list
*/
Node getFirst() { return first; }
/**
* Gets the node at the end of the list
*
* @return The node at the and of the list
*/
Node getLast() { return last; }
/**
* Returns a forward enumerator initialized to the beginning of the list
*
* @return The enumerator object
*/
Enumeration getForwardEnumeration() { return new ForwardEnumerator( this ); }
/**
* Returns a reverse enumerator initialized to the end of the list
*
* @return The reverse enumerator
*/
Enumeration getReverseEnumeration() { return new ReverseEnumerator( this ); }
/**
* Appends a list to the current list. The old list disappears as a standalone list
*
* @param list The new list
* @return The combined list
*/
List append( List list )
{
append( list.getFirst() );
last = list.getLast();
list.empty();
return this;
}
/**
* Prepends a list to the current list. The old list disappears as a standalone list
*
* @param list The list to be prepended
* @return The combined list
*/
List prepend( List list )
{
prepend( list.getLast() );
first = list.getFirst();
list.empty();
return this;
}
/**
* Prepends a copy of the list to the current list (preserves the list).
*
* @todo make sure it makes sense
* @param list The list to be prepended
* @return The combined list
*/
List prependAndPreserve( List list )
{
prepend( new List( list ) );
return this;
}
List appendAndPreserve( List list )
{
append( new List( list ) );
return this;
}
public void empty() { first = last = null; }
/**
* Copy constructor. Creates a new list based on an existing list.
*
* Note: this may not work as expected - to check.
*
* @param list
*/
List( List list )
{
for( Enumeration e = list.getForwardEnumeration(); e.hasMoreElements(); )
{
append( (Node)e.nextElement() );
}
}
/**
* Default constructor. Creates an empty list
*/
List(){}
}