Bestand einsehen und editieren
  Als nächstes soll es ermöglicht werden, den aktuellen Bestand an Videos anzuzeigen. Außerdem sollen sowohl Einkaufs-, als auch Verkaufspreise editiert werden können. Es soll also der Katalog, in dem die Preise verzeichnet sind, verändert werden. Somit liegt es nahe, einen Prozeß zu verwenden.  
  Auf diese Weise kann dem Benutzer an einem UIGatesp apilogo der Stocksp apilogo zum Editieren angezeigt werden und die veränderten Preise mit einem Druck auf den "Ok"-Button übernommen oder die alten Preise mit dem "Cancel"-Button beibehalten werden.  
  Zum Darstellen der Tabelle ist natürlich ein TableEntryDescriptorsp apilogo notwendig. Dazu wird die Klasse EditableVideoStockTED wie folgt erstellt:  
   neue Javaklasse    EditableVideoStockTED.java  
 

  import sale.*;
  import util.swing.*;

  public class EditableVideoStockTED
    extends AbstractTableEntryDescriptor
  {
  }
        
 
  Um die Preise editieren zu können, muß in der Klasse der darzustellende Stocksp apilogo und der zu verwendende DataBasketsp apilogo bekannt sein. Dazu werden entsprechende Variablen deklariert:  
 

  private CountingStockImpl videoCountingStock;
  private DataBasket        db;
        
 
  Die Pakete, aus denen die verwendeten Klassen DataBasketsp apilogo und CountingStockImplsp apilogo stammen, müssen importiert werden:  
 

  import data.*;
  import data.ooimpl.*;
        
 
  Die Variablen müssen initialisiert werden. Dazu werden die notwendigen Werte dem Konstruktor als Parameter übergeben und entsprechend zugewiesen:  
 

  public EditableVideoStockTED(CountingStockImpl videoCountingStock,
                               DataBasket db)
  {
    super();
    this.videoCountingStock = videoCountingStock;
    this.db                 = db;
  }
        
 
  Nun sollen zunächst die Eigenschaften des TableEntryDescriptorssp apilogo verändert werden, die mit dem Aussehen, und nichts mit der Editierbarkeit der Tabelle zu tun haben. Dies sind die Anzahl und die Namen der Spalten. Die Anzahl der Spalten wird durch die Methode getColumnCount bestimmt:  
 

  public int getColumnCount()
  {
    return 5;
  }
        
 
  Mit Hilfe eines Arrays werden die Namen Spalten wie folgt in der Methode getColumnNamesp apilogo festgelegt:  
 

  public String getColumnName(int index)
  {
    return (new String[]{"Name",
                         "Buy",
                         "Sell", 
                         "Pieces in Stock",
                         "Rent Pieces"})[index];  
  }
        
 
  Mit diesen zwei angepaßten Methoden ist die Klasse bereits in der Lage, die für den Videobestand darzustellende Tabelle korrekt zu beschreiben. Es kann eine Instanz dieses TableEntryDescriptorssp apilogo einer createsp apilogo-Methode aus SingleTableFormSheetsp apilogo übergeben werden. Daher soll als nächstes der Prozeß aufgebaut werden, der den noch vorhandenen Bestand anzeigt. Dieser wird in der Klasse SeeVideoStockProcess realisiert:  
   neue Javaklasse    SeeVideoStockProcess.java  
 

  import sale.*;

  public class SeeVideoStockProcess extends SaleProcess
  {
  }
        
 
  Der Konstruktor dieser Klasse ruft einfach den Konstruktor der Oberklasse mit einem passenden Parameter auf:  
 

  public SeeVideoStockProcess()
  {
    super("SeeVideoProcess");
  }
        
 
  Es wird noch die Variablendeklarationen für das benötigte Auswahl-Gatesp apilogo gebraucht:  
 

  protected UIGate selectionGate;
        
 
  Die Oberfläche wird, wie im RentProcess, mit der Methode setupMachine aufgebaut:  
 

  protected void setupMachine()
  {
  }
        
 
  Zunächst wird das Auswahl-Gatesp apilogo initialisiert und die noch benötigten Datenstrukturen als lokale Variablen bereitgestellt:  
 

  selectionGate = new UIGate(null, null);

  final DataBasket db = getBasket();    
  final Catalog videoCatalog = Shop.getTheShop().getCatalog("Video-Catalog");
  final CountingStockImpl videoStock = (CountingStockImpl)
          Shop.getTheShop().getStock("Video-Countingstock");
        
 
  Um Catalogsp apilogo und Stocksp apilogo benutzen zu können, wird eine weitere import-Anweisung gebraucht:  
 

  import data.*;
        
 
  Danach wird das darzustellende FormSheetsp apilogo mit Hilfe des EditableVideoStockTED erzeugt:  
 

  final SingleTableFormSheet stfs = 
    SingleTableFormSheet.create("See videos in stock and edit Process",  
                                videoStock,
                                selectionGate,
                                db,
                                true,
                                new EditableVideoStockTED(videoStock, db)
                               );
        
 
  Um SingleTableFormSheetsp apilogo und CountingStockImplsp apilogo dem Compiler bekannt zu machen, wird der Kopf der Klasse um folgende import-Anweisungen ergänzt:  
 

  import data.ooimpl.*;
  import data.stdforms.*;
        
 
  Um Usersp apilogo verwenden zu können, wird folgendes Paket importiert:  
 

  import users.*;
        
 
  In dem vorhin erstellten FormSheetsp apilogo stfs werden zusätzlich mit einem FormSheetContentCreatorsp apilogo die notwendigen Buttons definiert.  
 

  stfs.addContentCreator(new FormSheetContentCreator()
  {
    protected void createFormSheetContent(FormSheet fs)
    {
    }
  });
        
 
  Es werden alle eventuell schon vorhandenen Buttons entfernt:  
 

  fs.removeAllButtons();
        
 
  Zuerst wird ein "New"-Button benötigt, der in seiner doAction-Methode die neuen Videos erzeugt und in den Bestand aufnimmt.  
 

  fs.addButton("New", 100, new sale.Action()
  {
    public void doAction(SaleProcess p, SalesPoint sp)
    {
    }
  });
        
 
  Die Methode doAction enthält alle notwendigen Schritte, die zum Erzeugen eines neuen Videos notwendig sind. Zuerst werden die Eingabefelder für alle relevanten Daten eines neues Videos erstellt:  
 

  JTextField jTextField1 = new JTextField();
  JTextField jTextField2 = new JTextField();
  JTextField jTextField3 = new JTextField();
  JTextField jTextField4 = new JTextField();
        
 
  Um die swing-Klasse verwenden zu können, muß das entsprechende Paket importiert werden.  
 

  import javax.swing.*;
        
 
  Die Textfelder werden in ein JPanel eingebaut:  
 

  JPanel jTextPanel = new JPanel();
  jTextPanel.setLayout(new BoxLayout(jTextPanel, BoxLayout.Y_AXIS));

  jTextPanel.add(new JLabel("Name"));
  jTextPanel.add(jTextField1);
  jTextPanel.add(new JLabel("Buy (in Pf)"));
  jTextPanel.add(jTextField2);
  jTextPanel.add(new JLabel("Sell (in Pf)"));
  jTextPanel.add(jTextField3);
  jTextPanel.add(new JLabel("Amount"));
  jTextPanel.add(jTextField4);
        
 
  Der Dialog muß anschließend dargestellt werden:  
 

  JOptionPane.showMessageDialog(null,
                                jTextPanel,
                                "New Video-Cassette",
                                JOptionPane.QUESTION_MESSAGE);
        
 
  Aus den vorhin erstellten Textfeldern werden die eingegebenen Daten für das hinzuzufügende Video ausgelesen. Einkaufs- und Verkauspreis, sowie die Anzahl sind int-Werte. Fehlerhafte Eingaben resultieren in einer NumberFormatException, die abgefangen werden muß.  
 

  String name = jTextField1();

  int buy = 0;
  try {
    buy = new Integer(jTextField2.getText()).intValue();
  }
  catch (NumberFormatException ne) {
  }

  int sell = 0;
  try {
    sell = new Integer(jTextField3.getText()).intValue();
  }
  catch (NumberFormatException ne) {
  }

  int amount = 0;
  try {
    amount = new Integer(jTextField4.getText()).intValue();
  }
  catch (NumberFormatException ne) {
  }
        
 
  Bei korrekter Eingabe in allen Textfeldern kann das neue Video mit seinen Daten in den Katalog übernommen werden. Existiert ein Video mit diesem Namen bereits, wird eine DuplicateKeyExceptionsp apilogo erzeugt. Ist die Eingabe fehlerhaft, erscheint ein Dialog mit der entsprechenden Fehlermeldung.  
 

  if (sell>0 && buy>0 && amount>0 && !name.equals("")) 
  {
    try {
      videoCatalog.add(new VideoCassette(name,
                         new QuoteValue(new IntegerValue(sell),
                                        new IntegerValue(buy))),
                       db
                      );
      videoStock.add(name, amount, null);
    }
    catch (DuplicateKeyException dke) {
      JOptionPane.showMessageDialog(null, "Element exists");
    }
  }
  else 
  {
    JOptionPane.showMessageDialog(null,
      "The given input was not correct!"); 
  }
        
 
  Analog dazu wird die doAction-Methode des "Remove"-Buttons implementiert.  
 

  fs.addButton("Remove", 101, new sale.Action()
  {
    public void doAction(SaleProcess p, SalesPoint sp)
    {
    }
  });
        
 
  Wenn eine Zeile markiert ist, wird das zu entfernende Video in einer Variable abgespeichert. Falls kein Video markiert ist, wenn der remove-Button gedrückt wird, so gibt die getSelectedRecord-Methode des SingleTableFormSheetssp apilogo null zurück.  
 

  Object record = stfs.getSelectedRecord();
  if (record != null) 
  {
    VideoCassette videoCassette = (VideoCassette)
      ((CountingStockTableModel.Record)record).getDescriptor();
  }
        
 
  CountingStockTableModelsp apilogo ist Bestandteil des Pakets data.swingsp apilogo:  
 

  import data.swing.*;
        
 
  Alle weiteren Anweisungen der doAction-Methode werden in den Anweisungsteil der if-Anweisung ergänzt, weil sie nur ausgeführt werden sollen, wenn ein Video selektiert wurde. Bevor ein Video aus dem Angebot des Automaten genommen werden kann, muß überprüft werden, ob Kunden Exemplare dieses Videos entliehen haben. Es werden alle Kundenkonten durchsucht und die Anzahl der ausgeliehenen Exemplare ermittelt.  
 

  int rented = 0;
  try {
    Iterator i = VideoMachine.getAllCustomer().iterator();
    while (i.hasNext()) {
      rented = rented +
        ((Customer)i.next()).getStoringStock().countItems(
          videoCassette.getName(), null);
    }
  }
  catch (NullPointerException npe) {
  }
        
 
  Um den Iterator verwenden zu können, bedarf es einer weiteren import-Anweisung:  
 

  import java.util.*;
        
 
  Wurden keine Exemplare des Videos entliehen, kann es entfernt werden. Besitzt mindestens ein Kunde ein Exemplar des zu löschenden Videos, kann der Manager dieses Video nicht aus dem Katalog entfernen. Andernfalls führt das zu (geschäftsschädigenden!) Dateninkosistenzen.  
 

  if (rented <= 0) 
  {
    try {
      videoCatalog.remove(videoCassette, db);
    }
    catch (VetoException ve) {
      ve.printStackTrace();
      JOptionPane.showMessageDialog(null, 
        "The selected item can't be removed!");
    }
  }
  else {
    JOptionPane.showMessageDialog(null,
      "There are still rented videos!");
  }
        
 
  Die VetoExceptionsp apilogo ist Bestandteil von data.eventssp apilogo:  
 

  import data.events.*;
        
 
  Weiterhin wird ein "Ok"-Button erstellt, der ein Commit ausführt, und ein "Cancel"-Button, welcher ein Rollback auslöst.  
 

  fs.addButton("Ok", 102, new sale.Action()
  {
    public void doAction(SaleProcess p, SalesPoint sp)
    {
      selectionGate.setNextTransition(
        GateChangeTransition.CHANGE_TO_COMMIT_GATE);
    }
  });

  fs.addButton("Cancel", 103, new sale.Action()
  {
    public void doAction(SaleProcess p, SalesPoint sp)
    {
      selectionGate.setNextTransition(
        GateChangeTransition.CHANGE_TO_ROLLBACK_GATE);
    }
  });
        
 
  Die setupMachine-Methode ist fertig implementiert. Die Klasse SeeVideoStockProcess wird durch die Methoden getInitialGatesp apilogo und getLogGatesp apilogo vervollständigt. Die erste Methode baut den Automaten auf und setzt das Start-Gatesp apilogo. Die zweite Methode übergibt das LogGatesp apilogo. Beim Beenden des Prozesses soll kein Log-Eintrag geschrieben werden, deshalb wird das StopGatesp apilogo zurückgegeben.  
 

  public Gate getInitialGate()
  {
    setupMachine();
    return selectionGate;
  }

  public Gate getLogGate()
  {
    return getStopGate();
  }
        
 
   neue Javaklasse    Office.java  
  Der so aufgebaute Prozeß kann an einem SalesPointsp apilogo gestartet werden. Der Manager erhält in seinem Menü einen neuen Menüpunkt. Dazu wird am Ende der getDefaultMenuSheetsp apilogo-Methode der Klasse Office folgendes eingefügt:  
 

  msSubMenu.add(new MenuSheetItem("Edit Video-Stock",
    new sale.Action()
    {
      public void doAction(SaleProcess p, SalesPoint sp)
      {
        sp.runProcess(new SeeVideoStockProcess());
      }
    }));
        
 
   neue Javaklasse    EditableVideoStockTED.java  
  Jetzt ist es dem Manager möglich, Einsicht in den Bestand des Automaten zu nehmen und ihn ggf. zu verändern. Um die Preise der einzelnen Videos editieren zu können, muß die Klasse EditableVideoStockTED um weitere Methoden ergänzt werden. Im einzelnen sind das die im Interface TableEntryDescriptorsp apilogo definierten Methoden getCellRenderersp apilogo, die die Darstellung der einzelnen Spalten festlegt, und getValueAtsp apilogo, die den Zellinhalt für das übergebene Objekt und die angebene Spalte liefert, desweiteren die Methoden istElementEditablesp apilogo, um zu überprüfen, ob das Element überhaupt editiert werden darf, getCellEditorsp apilogo, um ein Objekt zu ermitteln, mit Hilfe dessen die Elemente einer bestimmten Spalte editiert werden können und setValueAtsp apilogo, um einen bestimmten Wert in einem Datensatz festzulegen.  
  Für die Realisierung der getCellRenderersp apilogo-Methode werden Variablen zur Darstellung der einzelnen Formate benötigt. Es werden über dem Konstruktor von EditableVideoStockTED Variablen für Spalteneinträge mit Währung und für Einträge, die Namen und Mengenangaben repräsentieren, angelegt:  
 

  private TableCellRenderer tcrMoney;
  private TableCellRenderer tcrName;
  private TableCellRenderer tcrCount;
        
 
  Am Ende des Konstruktors der Klasse werden die Variablen dann initialisiert. Die Ausrichtung für die Darstellung der Anzahl wird auf zentriert festgelegt.  
 

  tcrMoney = new CurrencyRenderer(
    (Currency)Shop.getTheShop().getCatalog("EURO"));
  tcrName  = new DefaultTableCellRenderer();
  tcrCount = new DefaultTableCellRenderer();

  ((DefaultTableCellRenderer)tcrCount).setHorizontalAlignment(
    SwingConstants.CENTER);
        
 
  CurrencyRenderersp apilogo verlangt folgende import-Anweisung:  
 

  import data.swing.*;
        
 
  Die Methode getCellRenderersp apilogo liefert z.B. bei den Spalten 1 und 2 tcrMoney als CellRenderer zurück. Mit Hilfe einer switch-Anweisung erfolgt die jeweilge Zuweisung:  
 

  public TableCellRenderer getCellRenderer(int index)
  {
    switch (index) {
      case 0 : return tcrName;
      case 1 : return tcrCount;
      case 2 : return tcrCount;
      default: return tcrMoney;
    }
  }
        
 
  Die Methode ist damit abgeschlossen und die getValueAt-Methode kann erstellt werden.  
 

  public Object getValueAt(Object record, int index)
  {
  }
        
 
  Zuerst wird die ausgewählte VideoCassette bestimmt und in einer typgleichen Variable abgespeichert. Danach wird die Anzahl der Videos, die sich von dieser Sorte im Automaten befinden, ermittelt.  
 

  VideoCassette videoCassette =
    (VideoCassette)((CountingStockTableModel.Record)
      record).getDescriptor();
  int count =
    ((CountingStockTableModel.Record)record).getCount();
        
 
  Der übergebende gewünschte Spalteneintrag wird mit Hilfe einer switch-Anweisung zurückgegeben:  
 

  switch (index) {
    case 0:
      if (videoCassette != null) 
        return videoCassette.getName();
      else 
        return "";
    case 1:
      return ((QuoteValue)videoCassette.getValue()).getOffer;
    case 2:
      return ((QuoteValue)videoCassette.getValue()).getBid;
    case 3:
      return new IntegerValue(count);
  }
        
 
  Die Anzahl der ausgeliehenen Videos läßt sich nicht so einfach feststellen. Mit einem Iterator werden alle Kundenkonten durchsucht und die Anzahl der Videos darüber ermittelt. Für die Verwendung des Iterators wird die Klasse um eine weitere import-Anweisung ergänzt:  
 

  import java.util.*;
        
 
  Der switch-Anweisung wird ein weiterer Fall hinzugefügt:  
 

  case 4:
    int rented = 0;
    try {
      Iterator i = VideoMachine.getAllCustomer().iterator();
      while (i.hasNext()) {
        rented = rented +
          ((Customer)i.next()).getStoringStock().countItems(
            videoCassette.getName, null);
      }
    }
    catch (NullPointerException npe) {
    }
    return new IntegerValue(rented);
        
 
  Tritt durch einen Fehler im Programm ein Wert kleiner null oder größer vier auf, wird als Standard-Wert null geliefert:  
 

  default:
    return null;
        
 
  Die Methode ist damit vollständig implementiert, und die weiteren Methoden können entwickelt werden.  
  isElementEditablesp apilogo ist in diesem Fall sehr einfach: Alle Elemente, die in der zweiten oder dritten Spalte stehen, also alle Einkaufs- und Verkaufspreise, sind editierbar. Es ist zu beachten, daß die Zählung der Spalten bei null beginnt.  
 

  public boolean isElementEditable(Object record, int index)
  {
    return index==1 || index==2;
  }
        
 
  Die Implementation von getCellEditorsp apilogo ist schwieriger. Diese Methode soll einen TableCellEditor, also ein Objekt zum Editieren von Zellen einer Tabelle, zurückgeben, das in der Lage ist, Geldbeträge korrekt verändern zu lassen. Das Interface TableCellEditor ist im Paket javax.swing.table definiert und besitzt lediglich eine exisiterende Implementation: DefaultCellEditor. Diese ist im Paket javax.swing enthalten. Die Klasse ist in der Lage, ein JTextField zum Editieren eines Wertes einer Zelle zu verwenden. Es liegt also nahe, von DefaultCellEditor eine neue Klasse abzuleiten und an die eigenen Bedürfnisse anzupassen. Die Klasse DMCellEditor wird angelegt:  
   neue Javaklasse    DMCellEditor.java  
 

  import javax.swing.*;

  public class DMCellEditor extends DefaultCellEditor
  {
  }
        
 
  Zum Editieren soll eine Unterklasse von JTextField, nämlich das im Framework enthaltene JTextInputsp apilogo, verwendet werden. Der Konstruktor dieser Klasse benötigt als Parameter einen Array von Strings, in dessen ersten Feld zu jeder Zeit der in das Feld eingebene Wert steht, und einen Initialwert. Diese beiden Werte werden als Parameter des Konstruktors von JTextInputsp apilogo weitergereicht. Der Konstruktor von DMCellEditor hat folgendes Aussehen:  
 

  public DMCellEditor(String[] result, String init)
  {
    super(new JTextInput(result, init));
  }
        
 
  Für JTextInputsp apilogo wird das Paket util.swingsp apilogo importiert:  
 

  import util.swing.*;
        
 
  Da das Ergebnis der Eingabe später ausgewertet werden muß, wird die an den Konstruktor übergebene Variable in einer typgleichen Variable in der Klasse gespeichert. Dazu muß sie zunächst vor dem Konstruktor deklariert werden.  
 

  private String[] result;
        
 
  Dieser Variable wird im Konstruktor der entsprechende Parameter unter dem super-Befehl zugewiesen.  
 

  this.result = result;
        
 
  Wenn man sich die in DefaultCellEditor vorhandenen Methoden ansieht, wird deutlich, daß drei Methoden angepasst werden müssen:  
  getTableCellEditor gibt die zum Editieren verwendete Komponente, in diesem Fall also ein Objekt vom Typ JTextInputsp apilogo, mit gesetztem Initialwert zurück. Dazu wird die Komponente zunächst von der entsprechenden Methode der Oberklasse geholt. An ihr wird mit Hilfe der toString-Methode, der unter dem Namen "EURO" in der globalen Katalogliste verzeichneten Währung, der Initialwert gesetzt und die Komponente zurückgeben:  
 

  public Component getTableCellEditorComponent(
    JTable jTable, Object value, boolean isSelected,
    int row, int column)
  {
    Component component =
      super.getTableCellEditorComponent(
        jTable, value, isSelected, row, column);
    ((JTextInput)component).setText(((Currency)
      Shop.getTheShop().getCatalog("EURO")).toString(
        (NumberValue)value));
    return component;  
  }
        
 
  Für die in der Methode verwendeten Klassen werden weitere Pakete importiert:  
 

  import data.*;
  import sale.*;
  import java.awt.*;
        
 
  Die nächste anzupassende Methode ist getCellEditorValue. Diese muß einen, dem Inhalt der Zelle entsprechenden, Geldbetrag zurückgeben. Dazu wird versucht, das erste Feld von result mit Hilfe der Währung "EURO" zu parsen und als Rückgabewert zu verwenden.  
 

  public Object getCellEditorValue()
  {
    try {
      return ((Currency)Shop.getTheShop().getCatalog(
        "EURO").parse(result[0]);
    }
    catch(ParseException psex) {
      return new IntegerValue(0);
    }
  }
        
 
  Die ParseException befindet sich im Paket java.text:  
 

  import java.text.*;
        
 
  Zuletzt muß stopCellEditing angepaßt werden. Diese Methode versucht das Editieren der Tabellenzellen zu beenden und liefert einen Booleschen Wert zurück, der angibt, ob die Operation erfolgreich war. Mit dieser Methode läßt sich verhindern, daß ungültige Werte eingegeben werden. Im Fall der Klasse DMCellEditor darf das Editieren nur beendet werden, wenn der eingegebene Text als Geldbetrag der Währung "EURO" geparst werden kann. Demzufolge wird genau das versucht und im Erfolgsfall der Rückgabewert vom Urteil der entsprechenden Methode der Oberklasse abhängig gemacht. Wurde beim Parsen eine Exception erzeugt, wird false zurückgegeben.  
 

  public boolean stopCellEditing()
  {
    try {
      ((Currency)Shop.getTheShop().getCatalog(
        "EURO")).parse(result[0]);
    }
    catch(ParseException pexc) {
      return false;
    }
    return super.stopCellEditing();
  }
        
 
   neue Javaklasse    EditableVideoStockTED.java  
  Damit ist DMCellEditor fertiggestellt und kann in EditableVideoStockTED verwendet werden. Dort ist nun die Methode getCellEditor zu implementieren. Sie deklariert ein Objekt vom Typ TableCellEditor als Rückgabewert. Diese Klasse muß dem Compiler über eine import-Anweisung bekannt gemacht werden:  
 

  import javax.swing.table.*;
        
 
  Die zu implementierende Methode gibt für die zweite und dritte Spalte ein Objekt des gerade erstellten DMCellEditors zurück. Für alle anderen Spalten bleibt die entsprechende Methode der Oberklasse AbstractTableEntryDescriptor verantwortlich.  
 

  public TableCellEditor getCellEditor(int index)
  {
    if (index==1 || index==2)
      return new DMCellEditor(new String[1], "");
    else
      return super.getCellEditor(index);
  }
        
 
  Die letzte, für diese Klasse zu implementierende, Methode ist setValueAt. Sie bekommt den aktuellen Datensatz, die Spalte und den zu setzenden Wert übergeben.  
 

  public void setValueAt(Object record, int index,
                         Object value)
  {
  }
        
 
  In dieser Methode wird zunächst die zu verändernde VideoCassette aus dem Datensatz ermittelt.  
 

  VideoCassette videoCassette =
    (VideoCassette)((CountingStockTableModel.Record)
      record).getDescriptor();
        
 
  Die so ermittelte VideoCassette darf jedoch nicht direkt verändert werden. Sie wurde nur zur Darstellung in der Tabelle empfangen, aber nicht zum Editieren. Es besteht Lese-, aber kein Schreibrecht. Um die VideoCassette verändern zu können, muß sie mit Schreibrecht empfangen werden. Dazu muß der dafür zuständigen get-Methode des Catalogssp apilogo explizit mitgeteilt werden, daß eine Veränderung geplant ist. Das Item wird darauf speziell vorbereitet:  
 

  try {
    Videocassette videoCassetteToEdit =
      (VideoCassette)videoCountingStock.getCatalog(null).get(
      videoCassette.getName(), db, true);
    QuoteValue quoteValue =
      (QuoteValue)videoCassetteToEdit.getValue();

    if (index == 1)
      videoCassetteToEdit.setValue(
        new QuoteValue(quoteValue.getBid(), (Value)value));
    if (index == 2)
      videoCassetteToEdit.setValue(
        new QuoteValue((Value)value, quoteValue.getOffer()));
  }
  catch(VetoException vexc) {
    JOptionPane.showMessageDialog(null,
      "The editing of that item was vetoed. It might be in use.");
  } 
        
 
  Die VetoExceptionsp apilogo ist Bestandteil des Pakets data.events und JOptionPane von javax.swing.  
 

  import data.events.*;
  import javax.swing.*;
        
 
  Zum Abschluß der Klasse EditableVideoStock wird die Methode getColumnClass mit Code gefüllt. Diese wird immer dann benötigt, wenn die Methoden getCellRenderersp apilogo und getCellEditorsp apilogo null zurückgeben.  
 

  public Class getColumnClass(int index)
  {
    return null;
  }
        
 
  Die Entwicklung des Videoautomaten ist damit beendet. Viel Spaß beim Betreiben des Automaten!!  
 Quelltexte
  Hier der Quelltext der in diesem Kapitel geänderten Klassen:  
 
vorherige Seite  Zeit weiterschalten und Logfile einsehen
 

by Ronny Deuse

Valid HTML 4.01!