/**
 * Linkitetty lista on yksinkertainen kollektio.  Lista koostuu jonosta
 * solmuja, joissa kussakin on viittaus johonkin 
 * olioon (muuttuja <code>data</code>) sekä viittaus listan seuraavaan
 * solmuun. Tyhjä lista esitetään arvolla <code>null</code>.  Tämän
 * takia ennen kuin kutsutaan listan operaatioita, on tarkistettava,
 * että käsillä oleva lista ei ole <code>null</code>, koska muuten
 * suoritus päättyy virheeseen.  Huomaa, että mitä tahansa olioita
 * voidaan lisätä listaan, mutta yksinkertaisia arvoja, esimerkiksi
 * int- ja double-tyyppisiä arvoja, ei voi suoraan lisätä listaan.
 * Javassa on kuitenkin käytössä luokat <a
 * href="http://java.sun.com/j2se/1.3/docs/api/java/lang/Integer.html">Integer</a>,
 * <a
 * href="http://java.sun.com/j2se/1.3/docs/api/java/lang/Double.html">Double</a>,
 * ym. joilla yksinkertaisia arvoja voidaan käsitellä
 * olioina. <br>Huom! Tämä esimerkki ei käytä Javan collection
 * frameworkia.
 */
public class List {
    Object data;
    List next;

    /**
     * Luo uuden solmun, joka sisältää annetun olion ja viittauksen
     * seuraavaan solmuun.
     * @param element Solmun sisältämä olio.
     * @param n Listan seuraava solmu.
     */
    public List(Object element, List n) {
	data = element;
	next = n;
    }

    /**
     * Listan pituuden palauttaminen.
     * @return listan pituus
     */
    public int length() {
	List x = this;
	int len = 0;
	while (x != null) {
	    len++;
	    x = x.next;
	}
	return len;
    }

    /** 
     * Solmun sisältämän olion palauttaminen.
     * @return solmun sisältämä olio.
     */
    public Object getData() {
	return data;
    }

    /** 
     * Solmun sisältämän olion asettaminen.
     * @param newData uusi olio.
     */
    public void setData(Object newData) {
	data = newData;
    }

    /**
     * Listan seuraavan solmun palauttaminen.
     * @return listan seuraava solmu tai <code>null</code>, jos tämä
     * on listan viimeinen solmu.
     */
    public List getNext() {
	return next;
    }

    /**
     * Listan seuraavan solmun asettaminen.
     * @param newNext uusi seuraava solmu.
     */
    public void setNext(List newNext) {
	next = newNext;
    }

    /**
     * Lisätään olio listan loppuun. Huomaa, että listan alkuun voi
     * olion lisätä suoraan konstruktorilla. Metodin toiminta on
     * esitetty havainnollisesti <a
     * href="List.insertElementLast.html">täällä</a>.
     * @param element Lisättävä olio.
     */
    public void insertElementLast(Object element) {
	List list = this;
	while (list.next != null) {
	    list = list.next;
	}
	list.next = new List(element, null);
    }

    /**
     * Lisätään listan loppuun toinen lista.
     * @param other Lisättävä lista.
     */
    public void append(List other) {
	List list = this;
	while (list.next != null) {
	    list = list.next;
	}
	list.next = other;
    }

    /**
     * Poistetaan listasta annettu olio.
     * @param element Poistettava olio.
     * @return Lista poiston jälkeen.
     */
    public List removeElement(Object element) {
	if (data == element) {
	    return next;
	} else {
	    List list = this;
	    while (list.next != null && list.next.data != element) {
		list = list.next;
	    }
	    if (list.next != null) {
		list.next = list.next.next;
	    }
	    return this;
	}
    }

    /**
     * Sisältääkö lista annetun olion?
     * @param element Etsittävä olio.
     * @return <code>true</code>, jos lista sisältää olion,
     * <code>false</code>, jos ei sisällä.  */
    public boolean containsElement(Object element) {
	List list = this;
	while (list != null && list.data != element) {
	    list = list.next;
	}
	if (list.data == element) {
	    return true;
	} else {
	    return false;
	}
    }

    /**
     * Luokan <code>Object</code> metodin uudelleenmääritys.
     */
    public String toString() {
	String representation = "(" + data;
	List x = next;
	while (x != null) {
	    representation = representation + ", " + x.data;
	    x = x.next;
	}
	representation = representation + ")";
	return representation;
    }
}
