Nada

 

Laboration 5 - Livsträdet

Boken Object-oriented programming in Java av Martin Kalin har tidigare använts som kursbok på DD2385. I boken finns ett program som grafiskt presenterar filkatalogträd med hjälp av en avancerad swingkomponent, JTree. Koden (något lite modifierad) finns här: DirTree.java. Kompilera den och provkör med

java DirTree

som ska visa trädet under den katalog du står i. Försök också till exempel

java DirTree ~henrik/labbar

som visar trädet för den angivna katalogen. Kolla att klickningar fungerar och att man kan få veta detaljer om en fil om Show details är markerad.

Ett minimalt livsträd

Denna första förberedande uppgift är att modifiera programmet så att det visar ett helt annat träd, nämligen livsträdet. I trädets rot ska det stå Liv och roten ska ha tre barn, Växter, Djur och Svampar. Dessa ska senare i sin tur kunna innehålla ordningar, underordningar, familjer, släkten och arter. Börja med några små ändringar för att bekanta dig med programmet:
  • I rotnoden ska ordet "Liv" stå, inte katalognamnet.
  • I metoden private void buildTree() suddar du allt och skriver nya satser som gör följande.
    • Tillverka en nod child på samma sätt som rotnoden men med texten Växter.
    • Addera den till trädmodellen med root som förälder. Några rader längre ner i koden ser du hur det går till.
  • Gör likadant med djur och svampar.
  • Kompilera, kör och kolla att det ser bra ut.

Ett rekursivt livsträd

I stället för att tillverka noderna för hand ska du läsa in livsträdet från filen Liv.xml (finns även som Liv.txt). En liten testversion av filen ser ut så här, finns också i LillaLiv.txt. Om du har problem med svenska bokstäverna, använd följande versioner: Life.txt, Life.xml och TinyLife.txt som är utan prickar och ringar.
<Biosfär namn="Liv"> är allt som fortplantar sej 
<Rike namn="Växter"> kan inte förflytta sej 
</Rike> 
<Rike namn="Djur"> kan förflytta sej 
</Rike>
<Rike namn="Svampar"> är varken djur eller växter 
</Rike>
</Biosfär>
Förutom nodens namn finns i filerna också en nivå (t ex Rike) och en förklarande text men för dom finns ingen plats i klassen DefaultMutableTreeNode. Skriv därför en egen subklass t.ex. MyNode med String-variablerna level och text så att all data från livträdsfilerna får plats. Skriv sedan en rekursiv metod som läser filen och skapar trädet, t.ex. enligt följande:
  root=readNode(starttagg); //Läser XML-filen och skapar hela trädet 
Innan den här metoden anropas bör man ha läst den första vänstervinkeln och starttaggen ur filen. readNode läser data för noden och skapar ett nodobjekt. Lifetree.gif När sluttagg nås ska den läsas och jämföras med starttaggen. Om de är olika ska något Exception kastas eller åtminstone ska en utskrift göras och programmet stanna. Normalt returneras den skapade noden. Ett sätt att genomföra filläsningen och bygga upp trädet förklaras på någon föreläsning, troligen nr 9 eller 10. Det går att göra läsningen av filen på många sätt, var inte "låst" av metodförslaget ovan! Det är självklart tillåtet att ha flera samarbetande metoder. Det är också tillåtet att ha några data (t.ex. senaste inlästa rad från filen) globala (dvs instansvariabler) och tillgängliga för alla rekursiva metodanrop.

Liksom i det ursprungliga programmet DirTree ska man kunna ange filnamn efter exekveringskommandot

java LifeTree livfil

och om inget namn anges ska programmet ta filen Liv.xml.

Detaljupplysningar om livet

I det ursprungliga programmet får man filupplysningar om "Show details" förkryssas. I ditt program ska man i stället få se den förklarande texten, till exempel Art: Mås gillar Vaxholmsbåtar. Fixa så att showDetails(TreePath p) lägger ut denna text i sin JOptionPane.

Läsning från textfil

Görs enklast med klassen Scanner:
    Scanner sc = new Scanner(new File("infil.txt"));
new File(...) kan generera ett FileNotFoundException som måste hanteras men om det gick bra att hitta filen kan man sedan läsa radvis med sc.nextLine().

Krav på programmet

  • Indatafil med godtycklig storlek ska klaras av. Programmet får inte förutsätta att att någon nod har ett fast antal barn eller att trädet har ett visst djup.
  • Rekursion ska användas när filen läses men det är inte nödvändigt att följa anvisningarna ovan i detalj med readNode().
  • Programmet ska kontrollera att starttagg och sluttagg stämmer överens men behöver inte identifiera andra typer av fel i indatafilen.

Filformat m.m.

  • Programmet får förutsätta att indatafilen är formaterad så som exemplen, alltså att filen är radindelad med en "tagg" per rad som exempelfilerna och att det är exakt ett blanktecken mellan nivån och ordet namn (<Biosfär namn="Liv">) samt inga blanktecken alls på andra ställen utom i den förklarande texten i slutet av raderna.
  • Det är tillåtet att läsa filen radvis, dvs att låta programmet hämta in en hel rad från filen vid varje läsning. Alternativet är att läsa ett tecken i taget vilket gör uppgiften svårare.
Självklart är det tillåtet och snyggt att klara av indata som inte är så väl formaterade, t.ex. har flera blanktecken mellan orden, blanktecken före och efter tecknen "=", "<" och ">" samt extra radbyten eller utelämnade radbyten. Det är naturligtvis också utmärkt att identifiera andra syntaxfel än felaktig sluttagg men det krävs inte!

Redovisning

Kör programmet med den större infilen och demonstrera alla funktioner. Glöm inte att be om handledarens signatur på kvittensbladet när han/hon är nöjd med er redovisning!

Extrauppgift (liten!):

Ordna så att man förutom grundinformationen Art: Mås gillar Vaxholmsbåtar också får hela kedjan av namn utskriven på formen men allt som är Mås är Fåglar är Djur är Liv. Användbar metod i TreePath är getLastPathComponent(). I DefaultMutableTreeNode och därmed i MyNode finns metoden getParent(). Det finns även andra metoder som löser uppgiften.


Sidansvarig: <ann@nada.kth.se>
Senast ändrad 30 april 2010
Tekniskt stöd: <webmaster@nada.kth.se>