Videoautomat - Das Protokoll ansehen

Der Administrationsprozess

Die Protokolldatei soll vom Automatenbetreiber betrachtet werden können. Entsprechend wird die Anzeige derselben innerhalb des Administrationsprozesses erfolgen. Im Prozess wird zu diesem Zweck genau ein Zustand, der Startzustand definiert.

package videoautomat;
public class SaleProcessAdmin extends SaleProcess {
    private UIGate uig_logfile = new UIGate(null, null);
    public SaleProcessAdmin() {
        super("SaleProcessAdmin");
    }
    protected Gate getInitialGate() {
        return uig_logfile;
    }
}
		

Mehr Zustände werden in diesem Tutorial nicht implementiert. Erweiterungen, wie z.B eine Videobestandsverwaltung, sind jedoch mit wenig Aufwand möglich.


Privilegierte Aktionen

Der Prozess wird vom Hauptzustand des Anmeldeprozesses aus gestartet. Allerdings darf dies nur für berechtigte Personen der Fall sein. Mit Hilfe der Klasse ActionCapability ist es möglich nur bestimmten Personen Aktionen zu gestatten. Grundlage hierfür bildet das Interface Capability. Derartige Fähigkeiten können einer User-Instanz zugeordnet werden. ActionCapability implementiert darüberhinaus die Schnittstelle Action. Es handelt sich also um eine Aktion, zu der ein Nutzer befähigt sein kann oder nicht.

Im Konstruktor der Klasse AutomatUser wird über die Methode setCapability(Capability c) eine neue ActionCapability-Instanz dem Nutzer zugefügt. Bei der Erzeugung dieser Instanz muss ein String-Identifizierer, der die Fähigkeit auszeichnet, übergeben werden. Außerdem muss eine Aktion übergeben werden, die definiert, was die ActionCapability leisten soll. In diesem Fall soll einfach ein neuer Administrationsprozess gestartet werden. Schließlich bedarf es noch eines booleschen Wertes, der aussagt, ob die Aktion für den Nutzer gestattet ist oder nicht, und eines Strings, der angezeigt wird, wenn die Aktion auszuführen versucht wird, ohne dass dies gestattet ist. Der String-Identifizierer wird als Konstante definiert, damit später mittels dieses Werts auf die Fähigkeit zugegriffen werden kann.

public class AutomatUser extends User {
		.
		.
		.
    public static final String CAPABILITY_ADMIN = "admin";
    public AutomatUser(String user_ID, char[] passWd, boolean admin) {
		.
		.
		.
        setCapability(new ActionCapability(
            CAPABILITY_ADMIN,
            Global.MSG_ACCESS,
            new sale.Action() {
            public void doAction(SaleProcess p, SalesPoint sp) throws Throwable {
                sp.runProcess(new SaleProcessAdmin(), new DataBasketImpl());
            }
        }, admin));
    }
		.
		.
		.
}
		

Der String für die Meldung muss noch in der Klasse Global definiert werden.

public class Global {
		.
		.
		.
    public static final String MSG_ACCESS = "Acces denied!!!";
		.
		.
		.
}
		

Da es sich bei ActionCapability selbst um eine Aktion handelt, kann eine Instanz dieser Klasse einfach mit einem Button verknüpft werden. Entsprechend lässt man sich im Hauptzustand des Anmeldeprozesses von der angemeldeten Nutzerinstanz die neu definierte ActionCapability zurückgeben und bindet sie an den Button zum Start des Administrationsprozesses.

public class SaleProcessLogOn extends SaleProcess {
		.
		.
		.
    private Gate getMainGate() {
		.
		.
		.
        fs_main.addContentCreator(new FormSheetContentCreator() {
            protected void createFormSheetContent(FormSheet fs) {
		.
		.
		.
                fs.getButton(LogOn.FB_ADMIN).setAction(
                    (ActionCapability) u_current.getCapability(
                        AutomatUser.CAPABILITY_ADMIN));
            }
        });
        uig_main.setFormSheet(fs_main);
        return uig_main;
    }
		.
		.
		.
}
		

Der Start des Administrationsprozesses ist damit für berechtigte Nutzer möglich. Nach erfolgter Übersetzung und Ausführung des Programm kann die Funktionsweise überprüft werden.


Die Protokolltabelle

Für die benötigte Anzeige der Protokolldatei kann auf ein spezielles Formular des Frameworks die Klasse LogTableForm zurückgegriffen werden. Es wird eine Ableitung dieser Klasse im Paket videoautomat.gui implementiert.

package videoautomat.gui;
public class LogFileFormSheet extends LogTableForm {
    public static final int FB_CLOSE = 1;
    public LogFileFormSheet(LogInputStream lis) {
        super("Logged information", lis);

        addContentCreator(new FormSheetContentCreator() {
            public void createFormSheetContent(FormSheet fs) {
                fs.removeAllButtons();
                fs.addButton("Close", FB_CLOSE, null);
            }
        });
    }
}
		

Wie in der Definition des Konstruktors zu ersehen ist, benötigt man zur Erzeugung einer derartigen Protokolltabelle eine Instanz von LogInputStream. Dabei handelt es sich um einen Eingabestrom für Protokolldateien. Darüberhinaus lässt sich für den Eingabestrom ein besonderer Filter definieren, so dass nur bestimmte Protokolleinträge angezeigt werden.

Es soll im Folgenden ein solcher Filter, eine Implementation des Interface LogEntryFilter, geschaffen werden. Er filtert Instanzen heraus, die nicht vom Typ LogEntryVideo sind. Das ist erforderlich, da in der globalen Logdatei beispielsweise auch Einträge der Prozesse abgelegt werden, die nicht angezeigt werden sollen. Ein LogEntryFilter muss eine Methode accept(LogEntry le) definieren, die bestimmt, welche Protokolleinträge akzeptiert werden und welche nicht.

package videoautomat;
public class LogEntryFilterImpl implements LogEntryFilter {
    public boolean accept(LogEntry le) {
        if (le instanceof LogEntryVideo)
            return true;
        return false;
    }
}
		

Mit Hilfe des Filters und der globalen Protokolldatei kann nun die Protokolltabelle im Startzustand des Administrationsprozesses initialisiert werden. Außerdem wird der einzige Button des Formulars mit einer Aktion verknüpft, die einen Zustandsübergang zum Stop-Gate einleitet.

public class SaleProcessAdmin extends SaleProcess {
		.
		.
		.
    protected Gate getInitialGate() {
        try {
            FileInputStream fis = new FileInputStream(VideoShop.FILENAME);
            LogInputStream lis = new LogInputStream(fis, new LogEntryFilterImpl());

            LogFileFormSheet lfsf = new LogFileFormSheet(lis);
            lfsf.addContentCreator(new FormSheetContentCreator() {
                public void createFormSheetContent(FormSheet fs) {
                    fs.getButton(LogFileFormSheet.FB_CLOSE).setAction(new Action() {
                        public void doAction(SaleProcess p, SalesPoint sp) {
                            uig_logfile.setNextTransition(
                                GateChangeTransition.CHANGE_TO_STOP_GATE);
                        }
                    });
                }
            });
            uig_logfile.setFormSheet(lfsf);
        } catch (FileNotFoundException e) {
            getStopGate();
            e.printStackTrace();
        } catch (IOException e) {
            MsgForm msf = new MsgForm("Empty-LogFile!",
                "The log file was found empty.n"
                + "Nothing to administrate here.");
            msf.getButton(MsgForm.BTNID_OK).setAction(new Action() 
            {
                public void doAction(SaleProcess p, SalesPoint sp) 
                {
                    uig_logfile.setNextTransition(GateChangeTransition.CHANGE_TO_QUIT_GATE);
                }});
            uig_logfile.setFormSheet(msf);
        }
        return uig_logfile;
    }
}
		

Der Administrationsprozess und damit auch die Anwendung sind nunmehr komplett. Viel Spaß beim Ausprobieren!


 Das ProtokollierenDie fertige Anwendung