/* XMLTree.java - Verwaltung von XML-Daten in einem Baum
Copyright (C) 2007 Stefan Schlichthärle (http://www.sscit.de)

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

GPL:
http://www.fsf.org/licensing/licenses/gpl.html#SEC1

*/

import java.io.*;

// XMLTree repräsentiert die ganze XML Datei als Baum
public class XMLTree
{
	Knoten Wurzel;
	
	XMLTree()
	{
		Wurzel = null;
	}
	XMLTree(String tag)
	{
		Wurzel = new Knoten(tag);
	}
	
	// Gibt den ersten Knoten mit dem Tag "tag" zurück
	public Knoten SearchTag(String tag)
	{
		return null;
	}
	
	// Gibt den neu hinzugefügten Knoten zurück
	public Knoten AddTag(String tag, Knoten elter)
	{
		Knoten neu = new Knoten(tag);
		elter.AddNachfolger(neu);
		
		return neu;
	}
	
	// Bei PrintXML wird ein Pre_Order_Tiefendurchlauf gemacht und dabei die ganzen XML Tags ausgegeben
	public void PrintXML()
	{
		PrintXML_Rek(Wurzel, 0);
	}
	private void PrintXML_Rek(Knoten k, int ebene)
	{	
		if(k != null)
		{
			XMLTag e = k.nachfolger.Kopf;
                        XMLTag nf = k.nachfolger.Kopf;
                    
                        PrintTabs(ebene);
			
			// Attribute drucken
			if(k.a.Empty() == true) 
                        {
                            // Gibt es keinen Nachfolger mehr, dann Tag in eine Zeile drucken
                            if(e == null) Sop("<" + k.tag + ">");
                            else Sopln("<" + k.tag + ">");
                        }
			else
			{
				Sop("<" + k.tag + " ");
				XMLAttribute a = k.a.Kopf;
				
				while(a != null)
				{
					Sop("" + a.attribut + "=\"" + a.wert + "\" ");
					a = a.next;
				}
				
                                if(e == null) Sop(">");
                                else Sopln(">");
			}
			
			if(e == null)
			{
				if(k.wert != null) { /*PrintTabs(ebene);*/ Sop(k.wert); }
			}
			else
			{
				while (e != null)
				{
					PrintXML_Rek(e.k, ebene+1);
					e = e.next;
				}
			}
			
			if(nf == null)
                        {
                            Sopln("</" + k.tag + ">");
                        }
                        else
                        {
                            PrintTabs(ebene);
                            Sopln("</" + k.tag + ">");    
                        }
		}
	}
	private void PrintTabs(int ebene)
	{
		// Zeichnet die Tabs, damit die Ausgabe schön im XML Stil ist
		int i = 0;
		
		while(i < ebene) 
		{ 
			Sop("\t"); 
			i++; 
		}	
	}
	
	public void AddWert(String wert, Knoten k)
	{
		k.AddWert(wert);
	}
	
	public void AddAttribut(String attribut, String wert, Knoten k)
	{
		k.AddAttribut(attribut, wert);
	}
	
	private void Sopln(String Message)
	{
		System.out.println(Message);
	}
	
	private void Sop(String Message)
	{
		System.out.print(Message);
	}
}
/* Ein Knoten des Baumes
 * XMLTagsListe ist eine Liste, welche Knoten enthält. Diese Knoten sind die Nachfolger des aktuellen Knoten
 * XMLAttributeListe ist eine Liste mit Attributen des aktuellen Knoten */
class Knoten
{
	XMLTagsListe nachfolger;
	XMLAttributeListe a;
	String tag;
	String wert;
	
	Knoten(String tag)
	{
		this.tag = tag;
		nachfolger = new XMLTagsListe();
		a = new XMLAttributeListe();
	}
	
	// Sobald Knoten nachfolger hat darf er keinen wert mehr haben
	void AddNachfolger(Knoten k)
	{
		nachfolger.Add(k);
		wert = null;
	}
	
	void AddAttribut(String attribut, String wert)
	{
		a.Add(attribut, wert);
	}
	
	// Sobald Knoten wert hat darf er keine nachfolger mehr haben
	void AddWert(String wert)
	{
		this.wert = wert;
		nachfolger.delete();
	}
}

class XMLTagsListe
{
	XMLTag Kopf;
	XMLTag Fuß;
	
	XMLTagsListe()
	{
		Kopf = Fuß = null;
	}
	
	void Add(Knoten k)
	{
		if(Kopf == null)
		{
			Kopf = Fuß = new XMLTag(k);
		}
		else
		{
			Fuß.next = new XMLTag(k);
			Fuß = Fuß.next;
		}
	}
	
	void delete()
	{
		Kopf = Fuß = null;
	}
}
class XMLTag
{
	Knoten k;
	XMLTag next;
	
	XMLTag(Knoten k)
	{
		this.k = k;
	}
}

class XMLAttributeListe
{
	XMLAttribute Kopf;
	XMLAttribute Fuß;
	
	XMLAttributeListe()
	{
		Kopf = Fuß = null;
	}
	
	void Add(String attribut, String wert)
	{
		if(Kopf == null)
		{
			Kopf = Fuß = new XMLAttribute(attribut, wert);
		}
		else
		{
			Fuß.next = new XMLAttribute(attribut, wert);
			Fuß = Fuß.next;	
		}
	}
	
	boolean Empty()
	{
		if(Kopf == null) return true;
		else return false;
	}
}
class XMLAttribute
{
	String attribut;
	String wert;
	XMLAttribute next;
	
	XMLAttribute(String attribut, String wert)
	{
		this.attribut = attribut;
		this.wert = wert;
	}
}

