package fha.inf3.set;
import java.util.AbstractSet;
import java.util.Iterator;
/**
 * Implementation eines eigenen Sets mit Hilfe einer Liste.
 * @author tardy
 */
public class ListSet extends AbstractSet
{
	private ListSetNode head;
	private ListSetNode last;
	private int versionNumber;
	/**
	 * Erstellt einen neuen Iterator, der auf das erste Element des Sets zeigt.
	 * @see java.util.Collection#iterator().
	 * @param this.head das erste Element des Sets.
	 * @param this eine Referenz auf das aktuelle Objekt.
	 * @param this.versionNumber die aktuelle Versions-Nummer
	 * @return eine Referenz auf einen Iterator.
	 */
	public Iterator iterator()
	{
		return new ListSetIterator(this.head, this, this.versionNumber);
	}
	/**
	 * Berechnet die Gr?sse des Sets.
	 * @see java.util.Collection#size().
	 * @return eine Integer die den Wert der Gr?sse des Sets hat.
	 */
	public int size()
	{
		ListSetNode tmp = head;
		int count = 0;
		while (tmp != null)
		{
			tmp = tmp.next;
			count++;
		}
		return count;
	}
	/**
	 * F?gt ein Objekt dem Set hinzu, aber testet vorher, ob es bereits vorhanden ist.
	 * @see java.util.Collection#size().
	 * @param x Referenz auf das Objekt, das hinzugef?gt werden soll.
	 * @return ist das Objekt bereits vorhanden, ist der R?ckgabewert false, wurde das Set ver?ndert, ist der R?ckgabewert true.
	 */
	public boolean add(Object x)
	{
		if (!this.contains(x))
		{
			if (this.head == null)
			{
				this.head = new ListSetNode(x,null);
				this.last = this.head;
			}
			else
			{
				this.last.next = new ListSetNode(x,this.last);
				this.last = this.last.next;
			}
			this.versionNumber++;
			return true;
		}
		return false;
	}
	/**
	 * Testet, ob die die Versionsnummern ?bereinstimmen.
	 * @param versionNumber die zu testende Versionsnummer.
	 * @return true, wenn die Nummern ?bereinstimmen, ansonsten false.
	 */
	public boolean checkVersion(int versionNumber)
	{
		return (this.versionNumber == versionNumber);
	}
	/**
	 * Inkrementiert die VersionsNummer des Sets
	 */
	public void incVersion()
	{
		this.versionNumber++;
	}
	/**
	 * Testet ob der mitgegebene Node dem Head entspricht und falls dies zutrifft, wird der Head um eines nach rechts verschoben.
	 * @param head der zu testende Node.
	 * @return wenn der Test positiv ausgefallen ist -> true, ansonsten -> false. 
	 */
	public boolean checkRemoveHead(ListSetNode head)
	{
		if (this.head == head)
		{
			this.head = this.head.next;
			return true;
		}
		else
		{
			return false;
		}
	}
	/**
	 * Testet ob der mitgegebene Node dem Last entspricht und falls dies zutrifft, wird der Last um eines nach links verschoben.
	 * @param last der zu testende Node.
	 * @return wenn der Test positiv ausgefallen ist -> true, ansonsten -> false. 
	 */
	public boolean checkRemoveLast(ListSetNode last)
	{
		if (this.last == last)
		{
			this.last = this.last.prev;
			return true;
		}
		else
		{
			return false;
		}
	}	
}