/* Experiment zur Anwendung des Observer-Mechanismus, basierend auf dem Beispiel"Terminverwaltung" zur Vorlesung "Softwaretechnologie".(c) Heinrich Hussmann, TU Dresden 1997-2000 */import java.util.Set;import java.util.SortedSet;import java.util.HashSet;import java.util.TreeSet;import java.util.Iterator;import java.util.Observable;import java.util.Observer;class Hour {   // Eine einfache selbstdefinierte Klasse, um mit simplen Datumsangaben   // (Tag-Nr. und Stunden-Nr.) umgehen zu koennen.	private int tag;	private int std;		public Hour (int tag, int std) {		this.tag = tag;		this.std = std;	}		public Hour naechste () {		if (std==23)			return new Hour(tag+1,0);		else			return new Hour(tag,std+1);	}			static boolean inKonflikt (Hour aBeginn, int aDauer, Hour bBeginn, int bDauer) {		if (aBeginn.tag != bBeginn.tag)			return false;		else 			if (aBeginn.std == bBeginn.std)				return true;			else				if (aBeginn.std < bBeginn.std)					return (aBeginn.std+aDauer > bBeginn.std);				else					return (bBeginn.std+bDauer > aBeginn.std);	}		public boolean equals (Object obj) {		return (this.tag==((Hour)obj).tag) && (this.std==((Hour)obj).std);	}			public int hashCode () {		return tag*24+std;	}		public String toString() {		return "[Tag "+tag+" Std "+std+"]";	}};abstract class Termin {	protected String titel;	protected Hour beginn;	protected int dauer; 		public Hour getBeginn () {		return beginn;	}		public int getDauer () {		return dauer;	}		abstract boolean verschieben (Hour neu);		public boolean inKonflikt (Hour angDatum, int angDauer) {		return Hour.inKonflikt(beginn, dauer, angDatum, angDauer);	}		public Termin (String titel, Hour beginn) {		this.titel = titel;		this.beginn = beginn;	}		public Termin (String titel, Hour beginn, int dauer) {		this(titel, beginn);		this.dauer = dauer;	}		public String toString() {		return "titel = "+titel+", beginn = "+beginn+", dauer = "+dauer;	}}class PersTermin extends Termin {	private String ort;	private int wegzeit;	private Teammitglied fuer;		boolean verschieben (Hour neu) {		this.beginn = neu;		return true;	}		public PersTermin (String titel, Hour beginn, int dauer, String ort, int wegzeit) {		super(titel, beginn, dauer);		this.ort = ort;		this.wegzeit = wegzeit;	}}class Teambesprechung extends Termin {	private Set teilnahme; // Assoziation aufgeloest mittels Set, Elemente: Teammitglied	private Besprechungsraum veranstOrt; 		private boolean abstimmen (Hour beginn, int dauer) {		boolean ok = true;		Iterator it = teilnahme.iterator();		while (it.hasNext() && ok) {		    Teammitglied m = (Teammitglied)it.next();			ok = ok && m.terminBestaetigen(beginn, dauer);			if (!ok)				System.out.println("Terminkonflikt fuer "+titel+" bei "+m+" !");		};		return ok;	}		void raumFestlegen () {		Besprechungsraum r = Raumverwaltung.freienRaumSuchen(teilnahme.size(), beginn, dauer);		if (r != null) {			r.reservieren(this);			veranstOrt = r; // Hier werden die beiden Referenzen fuer die bidirektionale Assoziation gesetzt.		}		else			System.out.println("Kein passender Raum gefunden fuer Besprechung am: "+beginn);	}		boolean verschieben (Hour neu) {		boolean ok = abstimmen(neu, dauer);		if (ok) {			beginn = neu;			raumFestlegen();		};		return ok;	}		public Teambesprechung (String titel, Hour beginn, int dauer, Teammitglied[] teilnehmer) {		super(titel, beginn, dauer);		// Hier wird als Implementierung fuer Set HashSet ausgewaehlt		this.teilnahme = new HashSet();	    for (int i=0; i<teilnehmer.length; i++)			this.teilnahme.add(teilnehmer[i]);		if (! abstimmen(beginn, dauer))			System.out.println("Termin bitte verschieben!");		else {		    Iterator it = this.teilnahme.iterator();		    while (it.hasNext()) 					((Teammitglied)it.next()).teilnahmeSetzen(this);		}	}		public String toString() {		return "Teambesprechung ("+super.toString()+", Anzahl Teiln. = "+teilnahme.size()+", "+			(veranstOrt!=null?"Raum ="+veranstOrt.toString():"Kein Raum festgelegt")+")";	}}class Besprechungsraum implements Comparable {	private String raumNr;	private int kapazitaet;	private Set belegt;   // Menge der Stunden, fŸr die der Raum reserviert wurde, Elemente: Hour			boolean grossGenug (int persAnz) {		return persAnz <= kapazitaet;	}			boolean frei (Hour angDatum, int angDauer) {		boolean vergeben = false;		Hour stunde = angDatum;		int i = 0;		while (i<angDauer && !vergeben) {			vergeben = belegt.contains(stunde);			stunde = stunde.naechste();			i++;		};		return !vergeben;	}			void reservieren (Teambesprechung fuer) {		Hour stunde = fuer.getBeginn();		for (int i = 0; i<fuer.getDauer(); i++) {			belegt.add(stunde);			stunde = stunde.naechste();		};	}		public Besprechungsraum (String raumNr, int kapazitaet) {		this.raumNr = raumNr;		this.kapazitaet = kapazitaet;		this.belegt = new HashSet();		Raumverwaltung.anmelden(this);	}		public int compareTo (Object o) {	    int oKapazitaet = ((Besprechungsraum)o).kapazitaet;		if (kapazitaet < oKapazitaet)			return -1;		else			if (kapazitaet == oKapazitaet)				return 0;			else				return +1;	}		public String toString() {		return "Besprechungsraum (Nr = "+raumNr+", Kapazitaet = "+kapazitaet+")";	}			public void printBelegung() {		String s = "Besprechungsraum Nr "+raumNr+" ist belegt: ";		Iterator it = belegt.iterator();		while (it.hasNext())			s += ((Hour)it.next())+" ";		System.out.println(s);	}}		class Raumverwaltung {	// Zusaetzliche Klasse zur Realisierung der Funktionen, die alle Raeume kennen muessen	private static SortedSet vorhandeneRaeume = new TreeSet(); 	// Vorhandene Raeume, aufsteigend nach Groesse sortiert, Elemente: Besprechungsraum			static Besprechungsraum freienRaumSuchen (int groesse, Hour beginn, int dauer) {	    Besprechungsraum r = null;	    boolean gefunden = false;		Iterator it = vorhandeneRaeume.iterator();		while (! gefunden && it.hasNext()) {			r = (Besprechungsraum)it.next();			if (r.grossGenug(groesse) && r.frei(beginn,dauer))				gefunden = true;		};		if (gefunden)			return r;		else			return null;	}			static void anmelden (Besprechungsraum r) {		vorhandeneRaeume.add(r);	}}				class Teammitglied extends Observable {		private String name;	private String abteilung;	private Set teilnahme; // Assoziation realisiert als Set, Elemente: Teambesprechung	private PersTermin[] persTermine; // Nicht weiter ausgefuehrt		private int anzahlBesprechungen = 0;			boolean terminBestaetigen (Hour beginn,int dauer) {		boolean konflikt = false;		Iterator it = teilnahme.iterator();		while (it.hasNext() && !konflikt) {			Teambesprechung b = (Teambesprechung) it.next();			if (b.inKonflikt(beginn, dauer))				konflikt = true;		};		return !konflikt;	}			void teilnahmeSetzen (Teambesprechung b) {		teilnahme.add(b);		setChanged();    	notifyObservers(b);	}		public Teammitglied (String name, String abteilung) {		this.name = name;		this.abteilung = abteilung;		this.teilnahme = new HashSet(); //HashSet als Set-Implementierung gewaehlt	}		public String toString() {		return "Teammitglied (Name = "+name+", Abt. = "+abteilung+")";	}}class TeammitglObserver implements Observer {  	public void update (Observable o, Object arg) {    	System.out.println("*** Teammitglied "+o+" nimmt teil an Besprechung "+arg);	}}class TerminvObs {	public static void main (String argv[]) {				Besprechungsraum r1 = new Besprechungsraum("R1", 10);		System.out.println(r1);		Besprechungsraum r2 = new Besprechungsraum("R2", 20);		System.out.println(r2);		Teammitglied mm = new Teammitglied("Max Mueller", "Abt. A");		System.out.println(mm);		TeammitglObserver tmo = new TeammitglObserver();   		mm.addObserver(tmo); 		Teammitglied es = new Teammitglied("Eva Schmidt", "Abt. B");		System.out.println(es);		Teammitglied fm = new Teammitglied("Fritz Maier", "Abt. B");		System.out.println(fm);		Teammitglied hb = new Teammitglied("Hans Bauer", "Abt. A");		System.out.println(hb);		Hour t1s5 = new Hour(1,5);		Hour t2s3 = new Hour(2,3);		Hour t2s4 = new Hour(2,4);		Teammitglied[] teilnTb1 = {mm, es};		Teambesprechung tb1 = new Teambesprechung("Besprechung 1", t1s5, 2, teilnTb1);		System.out.println(tb1);		tb1.raumFestlegen();		System.out.println(tb1);		r1.printBelegung();		r2.printBelegung();		Teammitglied[] teilnTb2 = {mm, fm};		Teambesprechung tb2 = new Teambesprechung("Besprechung 2", t2s3, 2, teilnTb2);		System.out.println(tb2);		tb2.raumFestlegen();		System.out.println(tb2);		r1.printBelegung();		r2.printBelegung();		Teammitglied[] teilnTb3 = {es, fm};		Teambesprechung tb3 = new Teambesprechung("Besprechung 3", t2s4, 2, teilnTb3);		System.out.println(tb3);		tb3.raumFestlegen();		System.out.println(tb3);		r1.printBelegung();		r2.printBelegung();		Teammitglied[] teilnTb4 = {es, hb};		Teambesprechung tb4 = new Teambesprechung("Besprechung 4", t2s4, 1, teilnTb4);		System.out.println(tb4);		tb4.raumFestlegen();		System.out.println(tb4);		r1.printBelegung();		r2.printBelegung();	}}