// Vips - Visual Programming with Structograms
// Copyright (C) 2005 Michael Partheil, michael.partheil@gmx.de
// All rights reserved.
package vips.model.wert;
import java.util.*;
import org.jdom.*;
import vips.model.FalschesDateiFormatException;
import vips.model.events.*;
/**
* Diese Klasse ist eine Sammlung von BenamterWert-Objekten.<BR>
* Ein Wert kann hinzugef�gt oder entfernt werden und man kann �ber einen
* Namen den zugeh�rigen Wert ermitteln. Die BenamterWert-Objekte hier drin
* wissen nichts von ihrer Sammlung.<BR>
* Die Sammlung kann eine Vater-Sammlung haben. Wenn ein Objekt dieser Klasse
* nach einem Wert gefragt wird, der hier nicht drin ist, fragt es seine
* Vater-Sammlung usw.
* <p>
* Events:<br>
* Wenn eine Variable hinzugef�gt oder entfernt wird.
*/
public class BenamterWertSammlung implements Beobachtbar, Cloneable
{
private Map werte;
private BenamterWertSammlung vater;
private ChangeListenerSammlung listeners = new ChangeListenerSammlung();
/**
* Erzeugt ein neues Objekt mit dem gegebenen Vater.
* @param vater Die Vater-Sammlung. Kann auch null sein.
*/
public BenamterWertSammlung(BenamterWertSammlung vater)
{
werte = new HashMap();
this.vater = vater;
}
/**
* Erzeugt Sammlung aus gegebenen XML-Element, welches den Namen
* "variablen" haben muss.
*/
public BenamterWertSammlung(Element e, BenamterWertSammlung vater)
throws FalschesDateiFormatException
{
this(vater);
if (! e.getName().equals("variablen"))
throw new IllegalArgumentException("e ist kein variablen-Element");
List varElemente = e.getChildren("variable");
for (Iterator it=varElemente.iterator(); it.hasNext(); )
{
Element varElement = (Element)it.next();
if (! Wert.isUnterstuetzterTyp(varElement.getAttribute("typ").getValue()))
{
throw new FalschesDateiFormatException("Datentyp wird nicht unterst�tzt: " +
varElement.getAttribute("typ").getValue());
}
try
{
Variable var = new Variable(varElement.getAttribute("name").getValue(),
new Wert(Class.forName(varElement.getAttribute("typ").getValue())).getWert());
wertHinzufuegen(var);
}
catch (ClassNotFoundException cnfe)
{
// Sollte nie passieren, da vorher ja bereits getestet wird, ob
// der Klassenname g�ltig ist
cnfe.printStackTrace();
}
}
List konstElemente = e.getChildren("konstante");
for (Iterator it=konstElemente.iterator(); it.hasNext(); )
{
Element konstElement = (Element)it.next();
if (! Wert.isUnterstuetzterTyp(konstElement.getAttribute("typ").getValue()))
{
throw new FalschesDateiFormatException("Datentyp wird nicht unterst�tzt: " +
konstElement.getAttribute("typ").getValue());
}
try
{
try
{
BenamterWert konst = new BenamterWert(konstElement.getAttribute("name").getValue(),
new Wert(Class.forName(konstElement.getAttribute("typ").getValue()),
konstElement.getAttribute("wert").getValue()).getWert());
wertHinzufuegen(konst);
}
catch (ClassNotFoundException cnfe)
{
// Sollte nie passieren, da vorher ja bereits getestet wird, ob
// der Klassenname g�ltig ist
cnfe.printStackTrace();
}
}
catch (Wert.ConvertException ce)
{
throw new FalschesDateiFormatException("Konnte Konstante \""+
konstElement.getAttribute("name").getValue() + "\" nicht erzeugen: "+
ce.getMessage());
}
}
}
/**
* Setzt den Vater dieser Sammlung, auch null geht.
*/
public void setVater(BenamterWertSammlung neuerVater)
{
vater = neuerVater;
}
/**
* Gibt den Vater dieser Sammlung zur�ck, evtl auch null.
*/
public BenamterWertSammlung getVater()
{
return vater;
}
/**
* Sucht in der Sammlung nach einem Wert mit dem gegebenen Namen und gibt
* ihn zur�ck.<BR>
* Wenn der Wert nicht gefunden wird, werden eventuelle
* Vater-Sammlungen durchsucht.
* @throws IllegalArgumentException Wenn name null ist.
*/
public BenamterWert getWert(String name)
{
if (name == null)
throw new IllegalArgumentException("name ist null");
BenamterWert w = (BenamterWert)werte.get(name.toUpperCase());
if (w == null)
{
if (vater != null)
return vater.getWert(name);
else
return null;
}
else
return w;
}
/**
* Wie <Code>getWert</Code>, allerdings werden keine Vater-Sammlungen
* durchsucht.
*/
public BenamterWert getWertHoechstesLevel(String name)
{
return (BenamterWert)werte.get(name.toUpperCase());
}
/**
* Gibt einen Iterator �ber die BenamterWert-Objekte dieser Sammlung zur�ck,
* die Elementer eine eventuellen Vater-Sammlung sind hier NICHT dabei.
*/
public Iterator iterator()
{
return werte.values().iterator();
}
/**
* Gibt ein Array mit allen BenamterWert-Objekten dieser Sammlung zur�ck.
*/
public BenamterWert[] getWerte()
{
return (BenamterWert[])werte.values().toArray(new BenamterWert[0]);
}
/**
* F�gt einen Wert dieser Sammlung hinzu.
* @throws IllegalArgumentException Wenn bw null ist
* @throws RuntimeException Wenn diese Sammlung bereits einen Wert mit dem
* Namen von bw beinhaltet.
*/
public void wertHinzufuegen(BenamterWert bw)
{
if (bw == null)
throw new IllegalArgumentException("bw ist null");
if (getWertHoechstesLevel(bw.getName()) != null)
throw new RuntimeException("Die Sammlung enth�lt bereits ein Element mit Namen " + bw.getName());
werte.put(bw.getName().toUpperCase(), bw);
listeners.eventAusloesen(this);
}
/**
* Entfernt einen Wert aus der Sammlung.
* @throws IllegalArgumentException Wenn bw null ist
* @throws RuntimeException Wenn bw nicht in dieser Sammlung drin ist.
*/
public void wertEntfernen(BenamterWert bw)
{
if (bw == null)
throw new IllegalArgumentException("bw ist null");
if (werte.remove(bw.getName().toUpperCase()) == null)
throw new RuntimeException("Sammlung enth�lt kein Element mit Namen " + bw.getName());
listeners.eventAusloesen(this);
}
/**
* Entfernt alle Werte (auf dem h�chsten Level) und l�st ein Event aus.
*/
public void alleWerteEntfernen()
{
werte.clear();
listeners.eventAusloesen(this);
}
/**
* F�gt den Listener <Code>l</Code> der Sammlung der Listener
* dieses Objekts hinzu.
* @throws IllegalArgumentException Wenn l null ist
*/
public void changeListenerHinzufuegen(ChangeListener l)
{
listeners.changeListenerHinzufuegen(l);
}
/**
* Entfernt den Listener <Code>l</Code> aus der Liste der Listener
* dieses Objektes.<BR>
* Wenn l nicht in der Sammlung drin ist, passiert nix.
* @throws IllegalArgumentException Wenn l null ist
*/
public void changeListenerEntfernen(ChangeListener l)
{
listeners.changeListenerEntfernen(l);
}
/**
* Fertigt eine tiefe Kopie dieser Sammlung an.<BR>
* Die Listeners werden NICHT geklont, es wird einfach f�r das neue objekt
* eine neue, leere Sammlung angelegt.
*/
public Object clone() throws CloneNotSupportedException
{
BenamterWertSammlung kopie = (BenamterWertSammlung)super.clone();
kopie.werte = new HashMap();
for (Iterator it=werte.entrySet().iterator(); it.hasNext(); )
{
Map.Entry entry = (Map.Entry)it.next();
kopie.werte.put(entry.getKey(), ((BenamterWert)entry.getValue()).clone());
}
kopie.listeners = new ChangeListenerSammlung();
return kopie;
}
public Element toXMLElement()
{
Element e = new Element("variablen");
for (Iterator it=iterator(); it.hasNext(); )
{
BenamterWert bw = (BenamterWert)it.next();
Element varElement;
if (bw instanceof Variable)
{
varElement = new Element("variable");
varElement.setAttribute("name", bw.getName());
varElement.setAttribute("typ", bw.getWert().getClass().getName());
}
else
{
varElement = new Element("konstante");
varElement.setAttribute("name", bw.getName());
varElement.setAttribute("typ", bw.getWert().getClass().getName());
varElement.setAttribute("wert", bw.getWert().toString());
}
e.addContent(varElement);
}
return e;
}
}