commit da330ff62e9356793fb4da1753b5a263cee0d56f Author: Jonas Neugebauer Date: Mon Oct 5 13:06:30 2020 +0200 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9fe8940 --- /dev/null +++ b/.gitignore @@ -0,0 +1,26 @@ +# ---> Java +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt +Dokumente* + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + diff --git a/List.java b/List.java new file mode 100644 index 0000000..864dc70 --- /dev/null +++ b/List.java @@ -0,0 +1,222 @@ +public class List { + + // erstes Element der Liste + ListNode first; + + // letztes Element der Liste + ListNode last; + + // aktuelles Element der Liste + ListNode current; + + /** + * Eine leere Liste wird erzeugt. + */ + public List() { + first = null; + last = null; + current = null; + } + + /** + * 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() { + // Die Liste ist leer, wenn es kein erstes Element gibt. + return first == null; + } + + /** + * 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() { + // Es gibt keinen Zugriff, wenn current auf kein Element verweist. + return current != null; + } + + /** + * 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 + * Ausfuehrung des Auftrags kein aktuelles Objekt, d.h. hasAccess() liefert + * den Wert false. + */ + public void next() { + if( this.hasAccess() ) { + current = current.getNextNode(); + } + } + + /** + * Falls die Liste nicht leer ist, wird das erste Objekt der Liste aktuelles + * Objekt. Ist die Liste leer, geschieht nichts. + */ + public void toFirst() { + if( !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( !isEmpty() ) { + current = last; + } + } + + /** + * Falls es ein aktuelles Objekt gibt (hasAccess() == true), wird das + * aktuelle Objekt zurueckgegeben, andernfalls (hasAccess() == false) gibt + * die Anfrage den Wert null zurueck. + * + * @return das aktuelle Objekt (vom Typ ContentType) oder null, wenn es + * kein aktuelles Objekt gibt + */ + public ContentType getContent() { + if( this.hasAccess() ) { + return current.getContentObject(); + } else { + return null; + } + } + + /** + * Falls es ein aktuelles Objekt gibt (hasAccess() == true) und pContent + * ungleich null ist, wird das aktuelle Objekt durch pContent ersetzt. Sonst + * geschieht nichts. + * + * @param pContent das zu schreibende Objekt vom Typ ContentType + */ + public void setContent( ContentType pContent ) { + // Nichts tun, wenn es keinen Inhalt oder kein aktuelles Element gibt. + if( pContent != null && this.hasAccess() ) { + current.setContentObject(pContent); + } + } + + /** + * 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 pContent 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 pContent gleich null ist, geschieht nichts. + * + * @param pContent das einzufuegende Objekt vom Typ ContentType + */ + public void insert( ContentType pContent ) { + // TODO: Implementiere insert() anhand der Beschreibung oben. + // Achte auf die korrekte Einhaltung des Verkettungsprinzips und + // das neue Element _vor_ dem Aktuellen eingefügt werden soll. + // Nutze bei der Implementierung die Hilfsmethode + // ListNode getPrevious() + } + + /** + * Falls pContent gleich null ist, geschieht nichts.
+ * Ansonsten wird ein neues Objekt pContent am Ende der Liste eingefuegt. + * Das aktuelle Objekt bleibt unveraendert.
+ * Wenn die Liste leer ist, wird das Objekt pContent in die Liste eingefuegt + * und es gibt weiterhin kein aktuelles Objekt (hasAccess() == false). + * + * @param pContent das anzuhaengende Objekt vom Typ ContentType + */ + public void append( ContentType pContent ) { + if( pContent != null ) { // Nichts tun, wenn es keine Inhalt gibt. + + if( this.isEmpty() ) { // Fall: An leere Liste anfuegen. + // Neuen Knoten erstellen. + ListNode newNode = new ListNode<>(pContent); + + first = newNode; + last = newNode; + // current wird nicht gesetzt! + } else { // Fall: An nicht-leere Liste anfuegen. + // Neuen Knoten erstellen. + ListNode newNode = new ListNode<>(pContent); + + last.setNextNode(newNode); + last = newNode; // Letzten Knoten aktualisieren. + } + + } + } + + /** + * Falls es sich bei der Liste und pList um dasselbe Objekt handelt, + * pList null oder eine leere Liste ist, geschieht nichts.
+ * Ansonsten wird die Liste pList an die aktuelle Liste angehaengt. + * Anschliessend wird pList eine leere Liste. Das aktuelle Objekt bleibt + * unveraendert. Insbesondere bleibt hasAccess identisch. + * + * @param pList die am Ende anzuhaengende Liste vom Typ List + */ + public void concat( List pList ) { + if( pList != this && pList != null && !pList.isEmpty() ) { // Nichts tun, + // wenn pList und this identisch, pList leer oder nicht existent. + + if( this.isEmpty() ) { // Fall: An leere Liste anfuegen. + this.first = pList.first; + this.last = pList.last; + } else { // Fall: An nicht-leere Liste anfuegen. + this.last.setNextNode(pList.first); + this.last = pList.last; + } + + // Liste pList loeschen. + pList.first = null; + pList.last = null; + pList.current = null; + } + } + + /** + * Wenn die Liste leer ist oder es kein aktuelles Objekt gibt (hasAccess() + * == false), geschieht nichts.
+ * Falls es ein aktuelles Objekt gibt (hasAccess() == true), wird das + * aktuelle Objekt geloescht und das Objekt hinter dem geloeschten Objekt + * wird zum aktuellen Objekt.
+ * Wird das Objekt, das am Ende der Liste steht, geloescht, gibt es kein + * aktuelles Objekt mehr. + */ + public void remove() { + // TODO: Implementiere remove() anhand der Beschreibung oben. + // Achte auf die korrekte Einhaltung des Verkettungsprinzips. + // Du kannst bei der Implementierung die Hilfsmethode + // ListNode getPrevious() + // nutzen. + } + + /** + * Liefert den Vorgaengerknoten des Knotens pNode. Ist die Liste leer, pNode + * == null, pNode nicht in der Liste oder pNode der erste Knoten der Liste, + * wird null zurueckgegeben. + * + * @param pNode der Knoten, dessen Vorgaenger zurueckgegeben werden soll + * @return der Vorgaenger des Knotens pNode oder null, falls die Liste leer ist, + * pNode == null ist, pNode nicht in der Liste ist oder pNode der erste Knoten + * der Liste ist + */ + private ListNode getPrevious( ListNode pNode ) { + if( pNode != null && pNode != first && !this.isEmpty() ) { + ListNode temp = first; + while( temp != null && temp.getNextNode() != pNode ) { + temp = temp.getNextNode(); + } + return temp; + } else { + return null; + } + } + +} diff --git a/ListNode.java b/ListNode.java new file mode 100644 index 0000000..85eb7a1 --- /dev/null +++ b/ListNode.java @@ -0,0 +1,53 @@ +class ListNode { + + private ContentType contentObject; + private ListNode next; + + /** + * Ein neues Objekt wird erschaffen. Der Verweis ist leer. + * + * @param pContent das Inhaltsobjekt vom Typ ContentType + */ + public ListNode( ContentType pContent ) { + contentObject = pContent; + next = null; + } + + /** + * Der Inhalt des Knotens wird zurueckgeliefert. + * + * @return das Inhaltsobjekt des Knotens + */ + public ContentType getContentObject() { + return contentObject; + } + + /** + * Der Inhalt dieses Kontens wird gesetzt. + * + * @param pContent das Inhaltsobjekt vom Typ ContentType + */ + public void setContentObject( ContentType pContent ) { + contentObject = pContent; + } + + /** + * Der Nachfolgeknoten wird zurueckgeliefert. + * + * @return das Objekt, auf das der aktuelle Verweis zeigt + */ + public ListNode getNextNode() { + return this.next; + } + + /** + * Der Verweis wird auf das Objekt, das als Parameter uebergeben + * wird, gesetzt. + * + * @param pNext der Nachfolger des Knotens + */ + public void setNextNode( ListNode pNext ) { + this.next = pNext; + } + +} diff --git a/ListTest.java b/ListTest.java new file mode 100644 index 0000000..4649e62 --- /dev/null +++ b/ListTest.java @@ -0,0 +1,125 @@ +import static org.junit.Assert.*; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class ListTest { + + @Test + public void testeAppend() { + List liste = new List(); + assertTrue("Eine neue Liste sollte leer sein.", + liste.isEmpty()); + + liste.append("Erstes"); + + assertFalse("Nach append(\"Erstes\") auf der leeren Liste sollte sie nicht leer sein.", + liste.isEmpty()); + assertFalse("Nach append(\"Erstes\") auf der leeren Liste sollte das Aktuelle Element nicht verändert werden.", + liste.hasAccess()); + + liste.toFirst(); + assertTrue("Nach append(\"Erstes\"), toFirst() auf der leeren Liste sollte es ein aktuelles Element geben.", + liste.hasAccess()); + assertEquals("Nach append(\"Erstes\"), toFirst() auf der leeren Liste sollte das aktuelles Element \"Erstes\" sein.", + "Erstes", liste.getContent()); + + liste.append("Zweites"); + + assertEquals("Nach append(\"Erstes\"), toFirst(), append(\"Zweites\") sollte das aktuelles Element \"Erstes\" sein.", + "Erstes", liste.getContent()); + + liste.next(); + assertEquals("Nach append(\"Erstes\"), toFirst(), append(\"Zweites\"), next() sollte das aktuelles Element \"Zweites\" sein.", + "Zweites", liste.getContent()); + + liste.next(); + assertFalse("Nach append(\"Erstes\"), toFirst(), append(\"Zweites\"), next(), next() sollte es kein aktuelles Element geben.", + liste.hasAccess()); + } + + @Test + public void testeInsert() { + List liste = new List(); + assertTrue("Eine neue Liste sollte leer sein.", + liste.isEmpty()); + + liste.insert("Erstes"); + + assertFalse("Nach insert(\"Erstes\") auf der leeren Liste sollte sie nicht leer sein.", + liste.isEmpty()); + assertFalse("Nach insert(\"Erstes\") auf der leeren Liste sollte das Aktuelle Element nicht verändert werden.", + liste.hasAccess()); + + liste.toFirst(); + assertTrue("Nach insert(\"Erstes\"), toFirst() auf der leeren Liste sollte es ein aktuelles Element geben.", + liste.hasAccess()); + assertEquals("Nach insert(\"Erstes\"), toFirst() auf der leeren Liste sollte das aktuelles Element \"Erstes\" sein.", + "Erstes", liste.getContent()); + + liste.insert("Zweites"); + + assertEquals("Nach insert(\"Erstes\"), toFirst(), insert(\"Zweites\") sollte das aktuelles Element \"Erstes\" sein.", + "Erstes", liste.getContent()); + + liste.next(); + assertFalse("Nach insert(\"Erstes\"), toFirst(), insert(\"Zweites\"), next() sollte es kein aktuelles Element geben..", + liste.hasAccess()); + + liste.toFirst(); + assertTrue("Nach insert(\"Erstes\"), toFirst(), insert(\"Zweites\"), next(), toFirst() sollte das aktuelle Element \"Zweites\" sein.", + liste.hasAccess()); + assertEquals("Nach insert(\"Erstes\"), toFirst(), insert(\"Zweites\"), next(), toFirst() sollte das aktuelle Element \"Zweites\" sein.", + "Zweites", liste.getContent()); + } + + @Test + public void testeRemove() { + List liste = new List(); + liste.append("Erstes"); + liste.append("Zweites"); + liste.append("Drittes"); + liste.toFirst(); + liste.next(); + + assertFalse("Die Liste wurde mit drei Elementen befüllt.", + liste.isEmpty()); + assertTrue("Das zweite Element (\"Zweites\") ist das Aktuelle.", + liste.hasAccess()); + assertEquals("Das zweite Element (\"Zweites\") ist das Aktuelle.", + "Zweites", liste.getContent()); + + liste.remove(); + assertTrue("Nach remove() sollte das aktuelle Element \"Drittes\" sein.", + liste.hasAccess()); + assertEquals("Nach remove() sollte das aktuelle Element \"Drittes\" sein.", + "Drittes", liste.getContent()); + + liste.toFirst(); + liste.next(); + assertTrue("Nach remove() sollte das zweite Element in der Liste \"Drittes\" sein.", + liste.hasAccess()); + assertEquals("Nach remove() sollte das zweite Element in der Liste \"Drittes\" sein.", + "Drittes", liste.getContent()); + + liste.remove(); + assertFalse("Nach remove() auf \"Drittes\" sollte es kein aktuelles Element geben.", + liste.hasAccess()); + assertFalse("Nach remove() ohne aktuellem Element, sollte nichts passieren.", + liste.isEmpty()); + + liste.remove(); + assertFalse("Nach remove() ohne aktuellem Element, sollte nichts passieren.", + liste.hasAccess()); + assertFalse("Nach remove() ohne aktuellem Element, sollte nichts passieren.", + liste.isEmpty()); + + liste.toFirst(); + liste.remove(); + assertFalse("Nach remove() auf dem ersten (und einzigsten) Element, sollte die Liste leer sein.", + liste.hasAccess()); + assertTrue("Nach remove() auf dem ersten (und einzigsten) Element, sollte die Liste leer sein.", + liste.isEmpty()); + } +} diff --git a/package.bluej b/package.bluej new file mode 100644 index 0000000..2e4af65 --- /dev/null +++ b/package.bluej @@ -0,0 +1,52 @@ +#BlueJ package file +dependency1.from=Stack +dependency1.to=StackNode +dependency1.type=UsesDependency +dependency2.from=StackTest +dependency2.to=Stack +dependency2.type=UsesDependency +editor.fx.0.height=777 +editor.fx.0.width=1123 +editor.fx.0.x=101 +editor.fx.0.y=23 +objectbench.height=95 +objectbench.width=776 +package.divider.horizontal=0.6 +package.divider.vertical=0.8118081180811808 +package.editor.height=433 +package.editor.width=653 +package.editor.x=140 +package.editor.y=80 +package.frame.height=600 +package.frame.width=800 +package.numDependencies=2 +package.numTargets=3 +package.showExtends=true +package.showUses=true +project.charset=UTF-8 +readme.height=58 +readme.name=@README +readme.width=47 +readme.x=10 +readme.y=10 +target1.height=50 +target1.name=StackNode +target1.showInterface=false +target1.type=ClassTarget +target1.width=160 +target1.x=70 +target1.y=60 +target2.height=50 +target2.name=StackTest +target2.showInterface=false +target2.type=UnitTestTargetJunit4 +target2.width=90 +target2.x=430 +target2.y=110 +target3.height=50 +target3.name=Stack +target3.showInterface=false +target3.type=ClassTarget +target3.width=160 +target3.x=80 +target3.y=300