public class List
{
     private ListNode firstNode;
     private ListNode lastNode;
     private String name;

     // constructors
       public List()
       {
       this( "list" );
       }

       public List( String listName )
       {
          name = listName;
       }
       protected ListNode getFirstNode()
	   {
			return firstNode;
		}

	   	protected ListNode getLastNode()
	   	{
			return lastNode;
	   	}

	   	public String getName()
	   	{
			return name;
	   	}

	   	protected void setFirstNode(ListNode node)
	   	{
			firstNode = node;
	   	}

	   	protected void setLastNode(ListNode node)
	   	{
			lastNode = node;
	   	}

	    public void setName(String name)
	    {
			this.name = name;
	    }
		public synchronized boolean isEmpty()
		{
		  return firstNode == null; // return true indien de lijst
									// leeg is
		}
		public synchronized String print()
		{
		   if ( isEmpty() )
			  return "Empty " + name ;

		   StringBuffer buffer = new StringBuffer();
		   ListNode current = firstNode;
		   // zolang niet einde lijst wordt de inhoud van de
		   // huidige knoop (= current) weergegeven. Vervolgens wordt
		   // de huidige knoop gelijkgesteld aan de volgende knoop
		   while ( current != null )
		   {
				buffer.append( current.getData().toString() + " " );
				current = current.getNext();
		   }
		   return buffer.toString();
		} // einde methode print

		public synchronized void insertAtFront( Object insertItem )
		{
		   if ( isEmpty() )
			  firstNode = lastNode = new ListNode( insertItem );
		   else
			  firstNode = new ListNode( insertItem, firstNode );
		}

		public synchronized void insertAtBack( Object insertItem )
		{
		 if ( isEmpty() )
		  firstNode = lastNode = new ListNode( insertItem );

		 else // lastNode's nextNode zal naar de nieuwe node wijzen
		  { lastNode.setNext(new ListNode( insertItem ));
		    lastNode = lastNode.getNext();}
		}
		public synchronized Object removeFromFront() throws EmptyListException
		{
		  if ( isEmpty() ) // exception wordt gegooid indien de
		                   // gelinkte lijst leeg is
		       throw new EmptyListException( name );
		  Object removedItem = firstNode.getData(); // de data van de
		   // eerste knoop in de lijst wordt toegekend aan removedItem

		  // firstNode wordt gewijzigd. lastNode wordt gewijzigd
		  // indien de lijst maar één knoop bevat.
		  if ( firstNode == lastNode )
		         firstNode = lastNode = null;
		  else
		         firstNode = firstNode.getNext();
		  return removedItem; // de data van de verwijderde knoop
		                      // wordt teruggegeven.
		} // einde methode removeFromFront

		public synchronized Object removeFromBack() throws EmptyListException
		{
		   if ( isEmpty() ) // exception wordt gegooid indien de
		                       // gelinkte lijst leeg is
		          throw new EmptyListException( name );

		   Object removedItem = lastNode.getData(); // de data van de
		   // laatste knoop in de lijst wordt toegekend aan removedItem

		    // lastNode wordt gewijzigd. firstNode wordt gewijzigd
		    // indien de lijst maar één knoop bevat.
		   if ( firstNode == lastNode )
		           firstNode = lastNode = null;
		   else
			{ // de nieuwe laatste knoop zoeken (m.a.w. de voorlaatste
		     // knoop zoeken
		    ListNode current = firstNode;

		    // de gelinkte lijst doorlopen totdat de current.nextnode
		    // (= de volgende knoop in de lijst) gelijk is aan lastnode
		    while (current.getNext() != lastNode )
		             current = current.getNext();

		    lastNode = current; // current is de nieuwe laatste knoop
		    current.setNext(null); // vermits current de nieuwe
		    // laatste knoop is, is er geen volgende knoop meer
		  	}
		  return removedItem; // de data van de verwijderde knoop
		                        // wordt teruggegeven.
		} // einde methode removeFromBack
}
