Das Angebot anzeigen
  Nachdem Kataloge und Bestände vorhanden sind, soll dem Kunden das Angebot auch angezeigt werden.  
  Es muß nun ein FormSheetsp apilogo erzeugt und zurückgegeben werden, das die Tabelle mit dem Angebot enthält. Außerdem sollten die FormSheetssp apilogo Buttons enthalten, nämlich zum Verleihen und Zurückgeben von Videos.  
  Wenn man sich die Klasse FormSheetsp apilogo ansieht, wird man feststellen, daß sie zwei Arten von Konstruktoren hat: Zum einen ist es möglich, einem FormSheetsp apilogo eine Komponente zu übergeben, zum anderem kann man ihm aber auch einen FormSheetContentCreatorsp apilogo übergeben. Ein FormSheetContentCreatorsp apilogo kann vom FormSheetsp apilogo benutzt werden, um seinen Inhalt zu erzeugen. Die Einführung des ContentCreatorssp apilogo in das Framework hat folgende Bewandnis: Es ist nicht immer möglich, Swing-Komponenten korrekt abzuspeichern (zu serialisieren). Daher kann auch ein FormSheetsp apilogo, das mit Hilfe einer Komponente erzeugt wurde, nicht vollständig abgespeichert werden. Ergebnis ist, daß ein solches FormSheetsp apilogo zwar gespeichert und auch wieder geladen wird, jedoch nach dem Laden keinen Inhalt mehr besitzt. Die Swing-Komponente konnte nicht mitgesichert und so auch nicht wiederhergestellt werden. Lösung ist die Einführung eines FormSheetContentCreatorssp apilogo. Dieser besitzt eine Methode createFormSheetContentsp apilogo, die jedesmal aufgerufen wird, wenn der Inhalt des FormSheetssp apilogo neu erzeugt werden muß -- z.B. nach dem Laden. Es sollte also jedes FormSheetsp apilogo, das konkret wiederhergestellt werden soll, mit einem FormSheetContentCreatorsp apilogo ausgestattet werden.  
  Ein weiterer Vorteil dieses Konzepts ist, daß einem FormSheetsp apilogo mit addContentCreatorsp apilogo weitere Objekte vom Typ FormSheetContentCreatorsp apilogo übergeben werden können. Diese werden beim Aufbauen des FormSheetssp apilogo nacheinander aufgerufen und können jeder für sich Veränderungen vornehmen, so daß an einem vorgefertigten FormSheetsp apilogo weitere Anpassungen durch das Hinzufügen eines ContentCreatorssp apilogo möglich sind.  
  Es soll im folgenden ein FormSheetContentCreatorsp apilogo erstellt werden, der in seiner createFormSheetContentsp apilogo-Methode die gewünschte Tabelle und die benötigten Buttons erzeugt. Mit dessen Hilfe wird dann in der getDefaultFormSheetsp apilogo-Methode ein FormSheetsp apilogo erzeugt und zurückgegeben. Es wird zunächst die Klasse DefaultCounterFormCreator wie folgt mit Code gefüllt:  
   neue Javaklasse    DefaultCounterFormCreator.java  
 

  import sale.*;

  public class DefaultCounterFormCreator extends FormSheetContentCreator
  {
    public DefaultCounterFormCreator()
    {
      super();
    }
  }
        
 
  Es wird, wie oben schon erwähnt, die Methode createFormSheetContentsp apilogo in diese Klasse eingefügt. Sie enthält als Parameter das FormSheet, mit dem es arbeiten soll:  
 

  public void createFormSheetContent(FormSheet map)
  {
  }          
        
 
  Zunächst soll die Tabelle mit den Videos in das FormSheetsp apilogo eingefügt werden. Dazu muß der Videobestand aus der globalen Liste der Bestände herausgesucht werden:  
 

  CountingStockImpl cs =
    (CountingStockImpl)Shop.getTheShop().getStock("Video-Countingstock");
        
 
  Es wird mit der statischen Methode getTheShopsp apilogo der derzeit aktive Shopsp apilogo ermittelt und danach von ihm der benötigte Stocksp apilogo geholt.  
  Um dem Compiler die Klasse CountingStockImplsp apilogo bekannt zu machen, ist eine weitere import-Anweisung zu der schon vorhandenen hinzuzufügen:  
 

  import data.ooimpl.*;
        
 
  Um die Tabelle zu erstellen, kann eine der statischen Methoden von SingleTableFormSheetsp apilogo benutzt werden. Diese Klasse aus dem Paket data.stdformssp apilogo ist ideal zum Erstellen von FormSheetssp apilogo, die eine Tabelle mit dem Inhalt eines Stockssp apilogo, Catalogssp apilogo oder DataBasketssp apilogo enthalten sollen. Alles was zu tun ist, ist die passende createsp apilogo-Methode aufzurufen.  
  Ganz so einfach ist es dann aber leider doch nicht. Es gibt zwar eine createsp apilogo-Methode, die lediglich einen Namen, einen CountingStocksp apilogo und ein UIGatesp apilogo, das null sein kann, erwartet (UIGatessp apilogo werden später erklärt). Diese ist aber nicht verwendbar, da sie die Werte vom Typ QuoteValuesp apilogo, die sie von den darzustellenden VideoCassettes über getValuesp apilogo bekommt, nicht verarbeiten kann. Es bleibt also nichts anderes übrig, als die createsp apilogo-Methode zu verwenden, die zusätzlich einen TableEntryDescriptorsp apilogo (kurz TED), also eine Beschreibung des Tabelleneintrags erwartet und ihren eigenen, noch zu erstellenden TableEntryDescriptor zu übergeben.  
  Auf den ersten Blick sollte man meinen, ein derartiger Descriptorsp apilogo ließe sich am besten von DefaultCountingStockItemTEDsp apilogo ableiten. Auf den zweiten Blick hat aber die Ableitung von einer Unterklasse von DefaultCountingStockItemTEDsp apilogo einen bedeutenden Vorteil: DefaultMoneyBagItemTEDsp apilogo macht im wesentlichen das gleiche wie seine Oberklasse, es stellt aber den Wert des Eintrags als Währungsangabe dar, nicht einfach als normale Zahl. Diese Klasse ist zwar ursprünglich für Einträge eines MoneyBagssp apilogo gedacht, daher auch der Name, ist aber auch für alle anderen CountingStockssp apilogo geeignet, deren Wert einen Geldbetrag bezeichnet.  
   neue Javaklasse    OfferTED.java  
 

  import data.swing.*;

  public class OfferTED extends DefaultMoneyBagItemTED
  {
  }
        
 
  Die Tabelle soll zunächst nur zwei Spalten enthalten: zum einen den Namen der Videos und zum anderen deren Preis. Später jedoch, wenn es darum geht, Videos zu verleihen, soll der Kunde auch erfahren, wieviele Videos überhaupt verfügbar sind. Es wird also dem Konstruktor von OfferTED ein Boolescher Wert übergeben, der angibt, ob die dritte Spalte, die die Anzahl der verfügbaren Videos enthält, angezeigt werden soll oder nicht.  
  Dazu wird in der Klasse zunächst folgende Variable deklariert:  
 

  private boolean withCount;
        
 
  Nun folgt der Konstruktor. Dieser ruft zunächst den Konstruktor der Oberklasse mit der zu verwendenden Währung auf. Die Währung wird auf schon bekannte Weise vom aktuellen Shopsp apilogo aus der globalen Katalogliste geholt. Außerdem wird die gerade deklarierte Variable initialisiert:  
 

  public OfferTED(boolean withCount)
  {
    super((Currency)Shop.getTheShop().getCatalog("EURO"));
    this.withCount = withCount;
  }
        
 
  Um dem Compiler die im Konstruktor verwendeten Klassen Currencysp apilogo und Shopsp apilogo bekannt zu machen, sind zwei weitere import-Anweisungen notwendig:  
 

  import data.*;
  import sale.*;
        
 
  Als nächstes muß die Methode getColumnCount implementiert werden. Sie gibt an, aus wieviel Spalten die Tabelle bestehen soll. Der Rückgabewert ist abhängig von withCount:  
 

  public int getColumnCount() 
  {
    return withCount?3:2;
  }
        
 
  Um den Spaltentitel zu verändern, wird die Methode getColumnNamesp apilogo angepaßt:  
 

  public String getColumnName(int nIndex)
  {
    return (new String[]{ "Name",
                          "Price",
                          "Available" }) [nIndex];
  }
        
 
  Die wichtigste Methode, die angepaßt werden muß, ist jedoch getValueAtsp apilogo. Wie angesprochen wurde, ist es DefaultCountingStockItemTEDsp apilogo und damit auch DefaultMoneyBagItemTEDsp apilogo nicht möglich, QuoteValuessp apilogo als Werte zu verarbeiten. Daher muß in getValueAt der Wert der VideoCassettes aufgesplittet und nur der Verkaufspreis zurückgegeben werden. Alle anderen Felder der VideoCassette können ganz normal ausgewertet und daher die betreffenden Anfragen an die Oberklasse weitergeleitet werden.  
  Um die VideoCassette aufsplitten zu können, muß sie erst einmal ermittelt werden. Dazu ist es nötig, die Klasse herauszubekommen, von der der übergebene Record ist. Diese entspricht der Klasse des Rückgabewertes der getRecordsp apilogo-Methode des verwendeten TableModelssp apilogo. Aus der Dokumentation zu MoneyBagItemTEDsp apilogo erfährt man, daß es mit CountingStockTableModelsp apilogo zusammenarbeitet. Dessen getRecordsp apilogo-Methode wiederum liefert Records vom Typ CountingStockTableModel.Recordsp apilogo an die Tabelle.  
  Die getValueAt-Methode sieht also folgendermaßen aus:  
 

  public Object getValueAt(Object oRecord, int nIndex)
  {
    if (nIndex == 1) {
      VideoCassette vidCassette =
        (VideoCassette)
          ((CountingStockTableModel.Record)oRecord).getDescriptor();
      return ((QuoteValue)vidCassette.getValue()).getBid();
    }
    else return super.getValueAt(oRecord, nIndex); 
  }
        
 
  Damit ist die Erstellung des TableEntryDescriptors abgeschlossen.  
   neue Javaklasse    DefaultCounterFormCreator.java  
  Es kann nun in DefaultCounterFormCreator unter der schon bestehenden Anweisung weitergearbeitet werden. Dort wird, wie angesprochen, über eine der createsp apilogo-Methoden aus SingleTableFormSheetsp apilogo ein FormSheetsp apilogo erzeugt, das die gewünschte Tabelle enthält. Die createFormSheetContent-Methode wird um folgende Zeilen erweitert:  
 

  FormSheet fs =
    SingleTableFormSheet.create("Available Videocassettes", cs,
                                null, new OfferTED(false));            
        
 
  Die Parameter bedeuten dabei:
  • Titel des FormSheetssp apilogo
  • darzustellender CountingStocksp apilogo
  • UIGatesp apilogo: hier null (zur Bedeutung später)
  • der zu verwendende TableEntryDescriptorsp apilogo(TED)
 
  Außerdem muß eine import-Anweisung ergänzt werden, denn SingleTableFormSheetsp apilogo ist aus dem Paket data.stdformssp apilogo:  
 

  import data.stdforms.*;
        
 
  Auf diese Weise hat man ein FormSheetsp apilogo mit der Tabelle der Videos erhalten. Leider soll diese Tabelle jedoch nicht in irgendeinem FormSheetsp apilogo enthalten sein, sondern in dem, das createFormSheetContent als Parameter übergeben wurde. Daher wird die in dem neuen FormSheetsp apilogo befindliche Komponente ermittelt und dem übergebenen FormSheetsp apilogo zugewiesen. Also wird die Methode createFormSheetContent wie folgt erweitert:  
 

  map.setComponent(fs.getComponent());  
        
 
  Die Tabelle befindet sich nun an der gewünschten Stelle. Es sind jetzt noch Buttons einzufügen. Dazu werden zunächst alle eventuell schon im FormSheetsp apilogo vorhandenen Buttons entfernt:  
 

  map.removeAllButtons();
        
 
  Die beiden benötigten Buttons "rent" und "give back" werden ergänzt:  
 

  map.addButton("rent", 1, 
    new sale.Action()
    {
      public void doAction(SaleProcess p, SalesPoint s)
      {
        //Code zum Ausführen des Verleihvorgangs
      }
    }
  );

  map.addButton("give back", 2, 
    new sale.Action()
    {
      public void doAction(SaleProcess p, SalesPoint s)
      {
        //Code zum Ausführen des Rückgabevorgangs
      }
    }
  );        
        
 
  Die an addButtonsp apilogo übergebenden Parameter sind die Aufschrift des Buttons, eine Nummer zur Identifikation und die auszulösende Aktion. Sind schon Buttons im FormSheetsp apilogo vorhanden, muß darauf geachtet werden, daß schon vergebene Nummern nicht noch einmal verwendet werden.  
  Die auszulösende Aktion implementiert das Actionsp apilogo-Interface aus dem Paket salesp apilogo. Dieses Paket verlangt eine Methode doActionsp apilogo. In ihr steht der Code, aus dem die Aktion besteht, die beim Betätigen des Buttons ausgeführt werden soll. In diesem Fall bleiben die Methoden noch leer und werden in einem späteren Abschnitt implementiert.  
  Der Aufbau der FormSheetssp apilogo ist nun abgeschlossen. Damit die Kunden das Angebot betrachten können, muß der eigentliche "Verkaufsstand" implementiert werden, an dem die Videos ausgeliehen und zurückgegeben werden können - der Counter.  
   neue Javaklasse    Counter.java  
 

  import sale.*;

  public class Counter extends SalesPoint
  {
    public Counter(String name)
    {
      super(name);
    }
  }
        
 
  Hier wird im Konstruktor der Konstruktor von SalesPointsp apilogo aufgerufen und der Name des Counters übergeben.  
  Außerdem ist eine Methode notwendig, die das Standard-FormSheetsp apilogo für den Counter zurückgibt. Die vorhin erstellte Klasse DefaultCounterFormCreator wird zum Erstellen der Oberfläche verwendet:  
 

  public FormSheet getDefaultFormSheet()
  {
    return new FormSheet("Menu",
                         new DefaultCounterFormCreator(),
                         false);
  }
        
 
  Der Counter muß nun bei VideoMachine angelegt und als SalesPointsp apilogo angemeldet werden. Dies geschieht in der main-Methode. Direkt unter dem Erzeugen der Logsp apilogo-Datei wird die Klasse wie folgt erweitert:  
   neue Javaklasse    VideoMachine.java  
 

  Counter c = new Counter("Video Rental");
  c.attach(new DataBasketImpl());
  c.attach(new User("SalespointUser"));
  vidMachine.addSalesPoint(c);
        
 
  An den SalesPoint wird ein DataBasketsp apilogo "angehängt". In diesem Warenkorb werden die Videos des Kunden nach deren Auswahl so lange aufbewahrt, bis er sie endgültig ausleiht. Der Nutzer des Counters muß der Klasse ebenfalls bekannt gemacht werden. Da Usersp apilogo ein Bestandteil des Pakets userssp apilogo ist, werden die import-Anweisungen von VideoMachine um eine weitere ergänzt:  
 

  import users.*;
        
 
  Das Angebot kann jetzt betrachtet werden.  
 Quelltexte
  Hier der Quelltext der in diesem Kapitel geänderten Klassen:  
 
vorherige Seite  Kataloge und Bestände Der Kunde  naechste Seite
 

by kk15

Valid HTML 4.01!