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 {
    public SaleProcessAdmin() {
        super("SaleProcessAdmin");
    }
    protected Gate getInitialGate() {
        UIGate uig_logfile = new UIGate(null, null);        
        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über hinaus 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. Außerdem benötigt man einen String, der angezeigt wird, wenn versucht wird die Aktion auszuführen, 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,
            VideoShop.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 VideoShop definiert werden.

public class VideoShop extends Shop {
		.
		.
		.
    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. Diese Anbindung erfolgt in der Klasse LogOnSTFSContentCreator, welche den FormSheet-Inhalt für das Main-Gate des LogOn-Prozesses beschreibt.

Um die ActionCapability in der Button-Action angeben zu können, muss der Klasse LogOnSTFSContentCreator als Argument im Konstruktor eine Referenz auf den aktuellen Prozess mitgegeben werden, dem SaleProcessLogOn, aus dessen Kontext der aktuelle Nutzer erfragt wird.

		
public class LogOnSTFSContentCreator extends FormSheetContentCreator {

    private User user;
		
    public LogOnSTFSContentCreator(SaleProcessLogOn process)
    {
        user = (User) process.getContext().getCurrentUser(process);
    }
		
    protected void createFormSheetContent(FormSheet fs) {
		.
		.
		.
        fs.addButton("Administrate", 3, 
                (ActionCapability) user.getCapability(AutomatUser.CAPABILITY_ADMIN));
		
}
		

Der Start des Administrationsprozesses ist damit für berechtigte Nutzer möglich. Nach erfolgter Übersetzung und Ausführung des Programmes 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. Im InitialGate des Prozesses wird eine Instanz dieser Klasse erstellt und mit Hilfe der FormSheetContentCreator-Klasse AdminLTFContentCreator dem einzigen Button des FormSheets eine Action zugewiesen, welche zum Stop-Gate des Prozesses leitet.

package videoautomat;
		
public class SaleProcessAdmin extends SaleProcess {
		.
		.
    protected Gate getInitialGate() {
        UIGate uig_logfile = new UIGate(null, null);
		.
		.
            LogTableForm ltf_log = new LogTableForm("Logged information", lis);
            ltf_log.addContentCreator(new AdminLTFContentCreator());
            uig_logfile.setFormSheet(ltf_log);            
		.
		.
        return uig_logfile;
    }
		
package videoautomat.contentcreator;
		
public class AdminLTFContentCreator extends FormSheetContentCreator {
		
    protected void createFormSheetContent(FormSheet fs) {
        fs.removeAllButtons();
        fs.addButton("Close", 1, new StopAction());
    }

}
		
package videoautomat.contentcreator.stdactions;
		
public class StopAction implements Action {
    public void doAction(SaleProcess saleProcess, SalesPoint salePoint) throws Throwable {
        UIGate currentGate = (UIGate)saleProcess.getCurrentGate();
        currentGate.setNextTransition(GateChangeTransition.CHANGE_TO_STOP_GATE);
     }

}
		

Wie in der Definition des LogOnForm-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über hinaus 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.

public class SaleProcessAdmin extends SaleProcess {
		
    protected Gate getInitialGate() {
        UIGate uig_logfile = new UIGate(null, null);

        try
        {
            FileInputStream fis = new FileInputStream(VideoShop.FILENAME);
            LogInputStream lis = new LogInputStream(fis, new LogEntryFilterImpl());
            LogTableForm ltf_log = new LogTableForm("Logged information", lis);
            ltf_log.addContentCreator(new AdminLTFContentCreator());
            uig_logfile.setFormSheet(ltf_log);
        }
        catch(FileNotFoundException e)
        {
            getStopGate();
            e.printStackTrace();
        }
        catch(IOException e)
        {
            MsgForm msf_ioexc = new MsgForm(
                    "Empty-LogFile!",
                    "The log file was found empty.nNothing to administrate here.");
            msf_ioexc.addContentCreator(new AdminMFContentCreator());
            uig_logfile.setFormSheet(msf_ioexc);
        }
        return uig_logfile;
    }
		
}
		

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


previous Das ProtokollierenDie fertige Anwendung next



by s6200595
Valid HTML 4.01!