import java.io.Serializable;
/**
* <p>Materialien zu den zentralen
* Abiturpruefungen im Fach Informatik ab 2012 in
* Nordrhein-Westfalen.</p>
* <p>Klasse List</p>
* <p>Objekte der Klasse List verwalten beliebig viele,
* linear angeordnete Objekte. Auf hoechstens ein Listenobjekt,
* aktuelles Objekt genannt, kann jeweils zugegriffen werden.
* Wenn eine Liste leer ist, vollstaendig durchlaufen wurde oder
* das aktuelle Objekt am Ende der Liste geloescht wurde, gibt es
* kein aktuelles Objekt. Das erste oder das letzte Objekt einer
* Liste koennen durch einen Auftrag zum aktuellen Objekt gemacht werden.
* Außerdem kann das dem aktuellen Objekt folgende Listenobjekt
* zum neuen aktuellen Objekt werden. Das aktuelle Objekt kann gelesen,
* veraendert oder geloescht werden. Ausserdem kann vor dem aktuellen
* Objekt ein Listenobjekt eingefügt werden.
</p>
*
* <p>NW-Arbeitsgruppe: Materialentwicklung zum Zentralabitur
* im Fach Informatik</p>
*
* @version 2011-01-05
*/
public class List implements Serializable
{ private Node first, tail, current;
// Node
private class Node implements Serializable{
private Object contentObj;
private Node nextNode;
public Node(Object pContent) {
contentObj = pContent;
nextNode = null;
}
public void setContent(Object pContent) {
contentObj = pContent;
}
public Object content() {
return contentObj;
}
public void setNext(Node pNext) {
nextNode = pNext;
}
public Node getNext() {
return nextNode;
}
} // Ende der Klasse Node
/**
* Eine leere Liste wird erzeugt.
*/
public List() {
tail = new Node(null); // Dummy
first = tail;
tail.setNext(tail);
/* Der next-Zeiger des hinteren Dummy-Elementes
* zeigt auf das vorangehende Element.
*/
current=first;
}
/**
* Die Anfrage liefert den Wert true, wenn die Liste
* keine Objekte enthaelt, sonst liefert sie den Wert false.
* @return true, wenn die Liste leer ist, sonst false
*/
public boolean isEmpty() {
return first == tail;
}
/**
* Die Anfrage liefert den Wert true, wenn es ein
* aktuelles Objekt gibt, sonst
* liefert sie den Wert false.
* @return true, falls Zugriff moeglich, sonst false
*/
public boolean hasAccess() {
return (!this.isEmpty()) && (current != tail);
}
/**
* Falls die Liste nicht leer ist, es ein aktuelles
* Objekt gibt und dieses nicht das letzte Objekt der
* Liste ist, wird das dem aktuellen Objekt in der Liste
* folgende Objekt zum aktuellen Objekt, andernfalls gibt
* es nach Ausführung des Auftrags kein aktuelles Objekt,
* d.h. hasAccess() liefert den Wert false.
*/
public void next() {
if (this.hasAccess())
current = current.getNext();
}
/**
* Falls die Liste nicht leer ist, wird das erste
* Objekt der Liste aktuelles Objekt.
* Ist die Liste leer, geschieht nichts.
*/
public void toFirst() {
if (!this.isEmpty())
current = first;
}
/**
* Falls die Liste nicht leer ist, wird das
* letzte Objekt der Liste aktuelles Objekt.
* Ist die Liste leer, geschieht nichts.
*/
public void toLast() {
if (!this.isEmpty())
current = tail.getNext();
}
/**
* Falls es ein aktuelles Objekt gibt
* (hasAccess() == true), wird das aktuelle Objekt
* zurueckgegeben, andernfalls (hasAccess()== false)
* gibt die Anfrage den Wert null zurueck.
* @return Inhaltsobjekt
*/
public Object getObject() {
if (this.hasAccess())
return current.content();
else
return null;
}
/**
* Falls es ein aktuelles Objekt gibt (hasAccess() == true)
* und pObject ungleich null ist, wird das aktuelle Objekt
* durch pObject ersetzt. Sonst bleibt die Liste unveraendert.
* @param pObject Inhaltsobjekt
*/
public void setObject(Object pObject) {
if (pObject != null && this.hasAccess() )
current.setContent(pObject);
}
/**
* Ein neues Objekt pObject wird am Ende der Liste eingefuegt.
* Das aktuelle Objekt bleibt unveraendert. Wenn die Liste
* leer ist, wird das Objekt pObject in die Liste eingefuegt
* und es gibt weiterhin kein aktuelles Objekt
* (hasAccess() == false). Falls pObject gleich null ist,
* bleibt die Liste unveraendert.
*@param pObject Inhaltsobject
*/
public void append(Object pObject) {
if (pObject != null) {
Node lNewNode,lPos0;
lPos0 = current;
lNewNode = new Node(pObject);
lNewNode.setNext(tail);
if (this.isEmpty())
first = lNewNode;
else {
Node lPrevious = tail.getNext();
lPrevious.setNext(lNewNode);
}
tail.setNext(lNewNode);
current = lPos0;
}
}
/**
*Falls es ein aktuelles Objekt gibt (hasAccess() == true),
*wird ein neues Objekt vor dem aktuellen Objekt in die
*Liste eingefuegt. Das aktuelle Objekt bleibt unveraendert.
*Wenn die Liste leer ist, wird pObject in die Liste eingefuegt
*und es gibt weiterhin kein aktuelles Objekt
*(hasAccess() == false). Falls es kein aktuelles Objekt gibt
*(hasAccess() == false) und die Liste nicht leer ist oder
*pObject gleich null ist, bleibt die Liste unveraendert.
*@param pObject Inhaltsobjekt
*/
public void insert(Object pObject) {
if (pObject != null) {
Node lNewNode,lFront,lPos;
if (this.isEmpty())
this.append(pObject);
else
if (this.hasAccess() ) {
lPos = current;
lNewNode = new Node(pObject);
lNewNode.setNext(current);
if (lPos == first )
first = lNewNode;
else {
this.toFirst();
lFront = current;
while (this.hasAccess() & !(current == lPos)) {
lFront = current;
this.next();
}
lFront.setNext(lNewNode);
}
current=lPos;
}
}
}
/**
* Die Liste pList wird an die Liste angehaengt. Anschliessend
* wird pList eine leere Liste. Das aktuelle Objekt bleibt unveraendert.
* Falls pList null oder eine leere Liste ist, bleibt die Liste
* unveraendert.
* @param pList Liste
*/
public void concat(List pList) {
Node lCurrent1,lCurrent2,lPos0;
if (pList != null && !pList.isEmpty() ) {
if (this.isEmpty() ) {
first = pList.first;
tail = pList.tail;
current = tail;
}
else {
lPos0 = current;
current = tail.getNext();
lCurrent1 = current;
pList.toFirst();
current = pList.current;
lCurrent2 = pList.current;
lCurrent1.setNext(lCurrent2);
if (lPos0 != tail)
current = lPos0;
else
current = pList.tail;
tail = pList.tail;
// pList wird zur leeren Liste
pList.tail = new Node(null); // Dummy
pList.first = pList.tail;
pList.tail.setNext(tail);
pList.current = pList.tail;
}
}
}
/**
* Falls es ein aktuelles Objekt gibt (hasAccess() == true),
* wird das aktuelle Objekt geloescht und das Objekt hinter
* dem gelaeschten Objekt wird zum aktuellen Objekt. Wird das
* Objekt, das am Ende der Liste steht, geloescht, gibt es kein
* aktuelles Objekt mehr (hasAccess() == false). Wenn die Liste
* leer ist oder es kein aktuelles Objekt gibt (hasAccess() == false),
* bleibt die Liste unveraendert.
*/
public void remove() {
Node lPos, lFront;
if (this.hasAccess() ) {
if (current == first ) {
first = current.getNext();
if (current.getNext() == tail)
tail.setNext(first);
current = first;
}
else {
lPos = current;
this.toFirst();
lFront = current;
while (this.hasAccess() & !(current == lPos)) {
lFront = current;
this.next();
}
lFront.setNext(lPos.getNext());
current = lFront.getNext();
if (current == tail)
tail.setNext(lFront);
}
}
}
}