/**
  *
  * Programmieraufgabe P-24 (arithmetik.jar)
  * Leonhard Fellermayr (Mat. Nr. 128105090)
  *
  * @author Leonhard Fellermayr
  * @version 1.0
  *
  */

/** Benoetigte Packages */

import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/** Implementierung der Klasse WertVisitor (implementiert ArithmeticVisitor) */

public class WertVisitor implements ArithmeticVisitor
{

	/** @param bindung java.util.Map, die eine Zuweisung von Variablennamen an Werte enthaelt */

	private Map bindung;

	/** Object visitPlus (Ausdruck, Ausdruck) : Besuchsmethode fuer Ausdruck "Plus".
	  *
	  * Addiert linken und rechten Teilausdruck durch rekursiven Aufruf der accept()-Methode.
	  *
	  * @param left Linker Teilausdruck
	  * @param right Rechter Teilausdruck
	  * @return Ergebnisobjekt nach dem Besuch des Visitors beim Ausdruck (= Summe der Teilausdruecke)
	  *
	  */

	public Object visitPlus (Ausdruck left, Ausdruck right)
	{

		return new Integer (((Integer)left.accept (this)).intValue () + ((Integer)right.accept (this)).intValue ());

	}

	/** Object visitMal (Ausdruck, Ausdruck) : Besuchsmethode fuer Ausdruck "Mal".
	  *
	  * Multipliziert linken und rechten Teilausdruck durch rekursiven Aufruf der accept()-Methode.
	  *
	  * @param left Linker Teilausdruck
	  * @param right Rechter Teilausdruck
	  * @return Ergebnisobjekt nach dem Besuch des Visitors beim Ausdruck (= Produkt der Teilausdruecke)
	  *
	  */

	public Object visitMal (Ausdruck left, Ausdruck right)
	{

		return new Integer (((Integer)left.accept (this)).intValue () * ((Integer)right.accept (this)).intValue ());

	}

	/** Object visitKonstante (int) : Besuchsmethode fuer Ausdruck "Konstante".
	  *
	  * Gibt den Wert der int-Konstanten als Integer-Objekt zurueck.
	  *
	  * @param c Wert der Konstanten (int)
	  * @return Wert der Konstanten (Integer)
	  *
	  */

	public Object visitKonstante (int c)
	{

		return new Integer (c);

	}

	/** Object visitVariable (String) : Besuchsmethode fuer Ausdruck "Variable".
	  *
	  * Gibt den Wert der Variablen als Integer-Objekt zurueck. Greift hierzu
	  * auf keyToValue (Map, String) zurueck (s.u.).
	  *
	  * @param v Name der Variablen (String)
	  * @return Wert der Variablen (Integer)
	  *
	  */

	public Object visitVariable (String v)
	{

		return keyToValue (this.bindung, v);

	}

	/** Integer keyToValue (Map, String) : Sucht den uebergebenen String unter
	  * den Keys der Map, und gibt den zugehoerigen Value zurueck.
	  *
	  * Kann der Key nicht gefunden werden, tritt die Ausnahme
	  * VariableUndefiniertAusnahme auf.
	  *
	  * Wird von visitVariable (String) in WertVisitor verwendet,
	  * um Variablen zu evaluieren.
	  *
	  * @param haystack java.util.Map, in der gesucht werden soll
	  * @param needle Gesuchter Key als String
	  * @return Wert (Value) zum gesuchten Key
	  *
	  */

	private Integer keyToValue (Map haystack, String needle)
	{
		/** @param keySet Stelle den Heuhaufen als Set-of-keys bereit */
		Set keySet = haystack.keySet ();

		/** @param iter Bei der Suche ist ein Iterator nuetzlich */
		Iterator iter = keySet.iterator ();

		/** @param thisKey Aktuell bearbeitetes Element (initial null) */
		Object thisKey = null;

		/** Eigentlicher Suchvorgang */

		while (iter.hasNext ())
		{
			/** Speichere naechstes Element des Sets in thisKey */
			thisKey = iter.next ();

			/** Vergleiche Heuhaufen-Element mit der Nadel -
			  * falls identisch, gib das Element an Aufrufer zurueck */

			if (thisKey.equals (needle))
				return (Integer) haystack.get (thisKey);
		}

		/** Falls hier angelangt, wurde kein Element gefunden => Exception "werfen" :) */

		throw new VariableUndefiniertAusnahme ("Variable " + needle + " ist nicht definiert!");

	} // keyToValue ()

	/** WertVisitor (Map) : Konstruktor der Klasse.
	  *
	  * Besetzt die Instanzvariable Bindung mit der uebergebenen Bindungs-Map.
	  *
	  * @param bindung java.util.Map, die eine Zuweisung von Variablennamen an Werte enthaelt
	  *
	  */

	public WertVisitor (Map bindung)
	{

		this.bindung = bindung;

	}

} // WertVisitor
