/** Beispiel fuer die sofortige Umsetzung eines Analysemodells in ein * lauffaehiges Java-Programm.  Diese Version demonstriert eine moegliche * Umsetzung von Zustandsmodellen nach dem Prinzip der "Protokollmaschine" * aus der Vorlesung.  * "Terminverwaltung" zur Vorlesung "Softwaretechnologie". * @author (c) Heinrich Hussmann, TU Dresden 1997-2000 */      /** Die Klasse Hour dient dazu, in relativ einfacher Weise Datumsangaben zu * benutzen. Es gibt vordefinierte Klassen in Java, die bei fortgeschrittener * Programmierung geeigneter waeren!  Hier besteht eine Stundenangabe aus * zwei int-Zahlen fuer den Tag und die Stunde. */ class Hour {	private int tag;	private int std;		public Hour (int tag, int std) {		this.tag = tag;		this.std = std;	}	/** Die Operation inKonflikt() wird weiter unten benoetigt, um die Ueberschneidungzwischen zwei Terminen festzustellen, die jeweils durch eine "Hour"	und eine Dauergegeben sind. */	static public 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 String toString() {		return "[Tag "+tag+" Std "+std+"]";	}}/** Die Klasse Termin aus dem Analyse-Modell der Vorlesung. */abstract class Termin {	protected String titel;	protected Hour beginn;	protected int dauer; 		public 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;	}}/** Die Klasse Privater Termin aus dem Analyse-Modell der Vorlesung */class PrivTermin extends Termin {	private String ort;	private int wegzeit;	private Teammitglied fuer;	/** Fuer private Termine wird hier die Operation verschieben() der Oberklasse Terminso ueberdefiniert, dass keinerlei Ueberpruefungen durchgefuehrt werden. */	public boolean verschieben (Hour neu) {		this.beginn = neu;		return true;	};		public PrivTermin (String titel, Hour beginn, int dauer, String ort, int wegzeit) {		super(titel, beginn, dauer);		this.ort = ort;		this.wegzeit = wegzeit;	}}/** Die Klasse Teambesprechung aus dem Analyse-Modell der Vorlesung */class Teambesprechung extends Termin {	private Teammitglied[] teilnahme; // Assoziation aufgeloest mittels Array	private Besprechungsraum veranstOrt; 		private final static int ZUSTAND_fixiert = 0;	private final static int ZUSTAND_konflikt = 1;	private final static int ZUSTAND_konfliktfrei = 2;	private final static int ZUSTAND_raumproblem = 3;		private int zustand;	/** Die private Operation abstimmen() dient dazu, Terminkonflikte mit anderen fuer dieTeilnehmer bestehenden Terminen festzustellen. Zu Testzwecken wird bei Auftreten eines Terminkonflikts eine Meldung ausgegeben. */	private boolean abstimmen (Hour beginn, int dauer) {		boolean ok = true;		for (int i=0; i<teilnahme.length; i++) {			ok = ok && teilnahme[i].terminBestaetigen(beginn, dauer);			if (!ok)				System.out.println("Terminkonflikt fuer "+titel+" bei "+teilnahme[i]+" !");		};		return ok;	}		void raumFestlegen () {		int teilnAnz = teilnahme.length;		Besprechungsraum r = Raumverwaltung.freienRaumSuchen(teilnAnz, beginn, dauer);		if (r != null) {			r.reservieren(this); // Hierdurch wird die Referenz beim Raum r auf this gesetzt.			veranstOrt = r; // Hier wird die lokale Referenz auf r gesetzt. 			if (zustand == ZUSTAND_konfliktfrei)		  		zustand = ZUSTAND_fixiert;			}		else {			System.out.println("Kein passender Raum gefunden fuer Besprechung am: "+beginn);			zustand = ZUSTAND_raumproblem;		}	}	/** Fuer Teambesprechung wird die Operation verschieben() der Oberklasse Termin  so ueberdefiniert,dass eine Verschiebung nur stattfindet, wenn kein Terminkonflikt vorliegt. */	public boolean verschieben (Hour neu) {		boolean ok = abstimmen(neu, dauer);		if (ok) {			beginn = neu;			raumFestlegen();			zustand = ZUSTAND_konfliktfrei;		};		return ok;	}		public Teambesprechung (String titel, Hour beginn, int dauer, Teammitglied[] teilnehmer) {		super(titel, beginn, dauer);		this.teilnahme = teilnehmer;		if (! abstimmen(beginn, dauer)) {			System.out.println("Termin bitte verschieben!");			zustand = ZUSTAND_konflikt;		}		else {			for (int i=0; i<teilnahme.length; i++)				teilnahme[i].teilnahmeSetzen(this);			zustand = ZUSTAND_konfliktfrei;		}	}		private String stateToString() {	  if (zustand == ZUSTAND_fixiert) return "fixiert";	  if (zustand == ZUSTAND_konflikt) return "mit Konflikt";	  if (zustand == ZUSTAND_konfliktfrei) return "konfliktfrei";	  if (zustand == ZUSTAND_raumproblem) return "mit Raumproblem";	  return("unbekannter Zustand");	}		public String toString() {		return "Teambesprechung ("+super.toString()+", Anzahl Teiln. = "+teilnahme.length+", "+			(veranstOrt!=null?"Raum ="+veranstOrt.toString():"Kein Raum festgelegt")+", Zustand: "+stateToString()+")";	}}/** Die Klasse Besprechungsraum aus dem Analysemodell der Vorlesung */class Besprechungsraum {    private static final int maxReserv = 100; // Vereinfachung:maximal 100 Reservierungen    // In diesem Fall sind Arrays ausgesprochen unguenstig, bessere Realisierungen sh. spaeter !	private String raumNr;	private int kapazitaet;	private Teambesprechung[] reserv; // Assoziation zu den Teambesprechungen, fuer die der Raum reserviert wurde		private int numReserv = 0; // Anzahl derzeit eingetragener Reservierungen in fuer-Array		boolean grossGenug (int persAnz) {		return persAnz <= kapazitaet;	}/** Die Operation frei() wird von der Raumverwaltung benoetigt, um einen gegebenen Besprechungsraumabfragen zu koennen, ob er zu einem bestimmten zeitraum frei ist. */	public boolean frei (Hour angDatum, int angDauer) {		boolean konflikt = false;		int i = 0;		while (i < numReserv && !konflikt) {			if (reserv[i].inKonflikt(angDatum, angDauer)) 				konflikt = true;			else				i++;		};		return !konflikt;	}			public void reservieren (Teambesprechung fuer) {		reserv[numReserv] = fuer;		numReserv++;	}		public Besprechungsraum (String raumNr, int kapazitaet) {		this.raumNr = raumNr;		this.kapazitaet = kapazitaet;		this.reserv = new Teambesprechung[maxReserv];		Raumverwaltung.anmelden(this);	}		public String toString() {		return "Besprechungsraum (Nr = "+raumNr+", Kapazitaet = "+kapazitaet+")";	}}		/** Raumverwaltung ist eine zusaetzliche Klasse zum Analysemodell derVorlesung zur Realisierung der Funktionen, die alle Raeume kennen muessen */class Raumverwaltung {	private static final int maxRaeume = 10;	private static Besprechungsraum[] vorhandeneRaeume; // Vereinfachung: maximal 10 Raeume	private static int anzRaeume = 0;		public static Besprechungsraum freienRaumSuchen (int groesse, Hour beginn, int dauer) {		boolean found = false;		int i = 0;		while (!found && i<anzRaeume) {			if (vorhandeneRaeume[i].grossGenug(groesse) && vorhandeneRaeume[i].frei(beginn, dauer)) 				found = true;			else 				i++;		};		if (found)			return vorhandeneRaeume[i];		else			return null;	}		public static void anmelden (Besprechungsraum r) {		if (anzRaeume == maxRaeume)			System.out.println("Fehler: zu viele Raeume!");		else			if (vorhandeneRaeume == null)				vorhandeneRaeume = new Besprechungsraum[maxRaeume];			vorhandeneRaeume[anzRaeume] = r;			anzRaeume++;	}}				/** Die Klasse Teammitglied aus dem Analysemodell der Vorlesung */class Teammitglied {	private static final int maxTeilnahme = 10; // Vereinfachung: Max. 10 Besprechungsteilnahmen	// Vereinfachung noetig, um mit Arrays arbeiten zu koennen, bessere Loesungen sh. spaeter !		private String name;	private String abteilung;	private Teambesprechung[] teilnahme; // Assoziation realisiert als Array	private PrivTermin[] privateTermine; // Nicht weiter ausgefuehrt		private int anzahlBesprechungen = 0;			public boolean terminBestaetigen (Hour beginn,int dauer) {		boolean konflikt = false;		int i = 0;		while (i < anzahlBesprechungen && !konflikt) {			if (teilnahme[i].inKonflikt(beginn, dauer))				konflikt = true;			else				i++;		};		return !konflikt;	}		/** Die Operation teilnahmeSetzen() wird von Teambesprechung benoetigt, um eine korrekteRealisierung der bidirektionalen Teilnahme-Assoziation sicherzustellen. */	public void teilnahmeSetzen (Teambesprechung b) {		teilnahme[anzahlBesprechungen] = b;		anzahlBesprechungen++;	}		public Teammitglied (String name, String abteilung) {		this.name = name;		this.abteilung = abteilung;		this.teilnahme = new Teambesprechung[maxTeilnahme];	}		public String toString() {		return "Teammitglied (Name = "+name+", Abt. = "+abteilung+")";	}}/** Das Hauptprogramm besteht aus einer Reihe typischer Testfaelle fuer die Funktionender Terminverwaltung. */class Terminv {	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);		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);		Teammitglied[] teilnTb2 = {mm, fm};		Teambesprechung tb2 = new Teambesprechung("Besprechung 2", t2s3, 2, teilnTb2);		System.out.println(tb2);		tb2.raumFestlegen();		System.out.println(tb2);		Teammitglied[] teilnTb3 = {es, fm};		Teambesprechung tb3 = new Teambesprechung("Besprechung 3", t2s4, 2, teilnTb3);		System.out.println(tb3);		tb3.raumFestlegen();		System.out.println(tb3);		Teammitglied[] teilnTb4 = {es, hb};		Teambesprechung tb4 = new Teambesprechung("Besprechung 4", t2s4, 1, teilnTb4);		System.out.println(tb4);		tb4.raumFestlegen();		System.out.println(tb4);	}}