Dokumente in jadice

Ein Dokument ist ein formatunabhängiger Behälter für Seiten und Seitenschichten. Dokumente enthalten eine oder mehrere Seiten, die wiederum in verschiedenen Schichten Seitensegmente beinhalten können. Zur Verdeutlichung betrachten Sie bitte Abbildung 3.1, „Schematische Darstellung des jadice Dokumentenmodells“.

Zur Repräsentation von Dokumenten in der jadice document platform existiert das Interface Document. Diese Schnittstelle bietet einen Zugriff auf die im Dokument enthaltenen Seiten. Neben der Rückgabe einzelner Seiten besteht im Besonderen auch die Möglichkeit, über getPages() alle Seiten in Form einer Liste abzufragen.[14]

Die Klasse BasicDocument stellt eine Default-Implementierung der von Document geforderten Methoden zur Verfügung. Über ihre Konstruktoren kann die Klasse direkt instanziiert werden. Instanzen von BasicDocument erlauben keine Seiten-Duplikate – dieselbe Instanz von Page kann einem BasicDocument also nicht mehrfach hinzugefügt werden.

Das Interface UIDocument und dessen mitgelieferte Implementation SwingUIDocument haben das Ziel, die Arbeit mit jadice-Dokumenten in einem GUI-Umfeld zu erleichtern. Sie bieten zwei Vereinfachungen:

  • Ownership: Jedem UIDocument kann eine GUI-Komponente als Besitzer zugewiesen werden. Zu jedem Zeipunkt kann höchstens ein Besitzer pro Dokument existieren. Die Zuweisung geschieht automatisch, kann aber für besondere Anwendungsfälle auch manuell vorgenommen werden. Hilfreich ist die Kenntnis über einen Besitzer beispielsweise dann, wenn dem Nutzer ein modaler Dialog angezeigt werden soll, der sich zur korrekten Positionierung an einer anderen GUI-Komponente orientieren muss.

  • Threading: Da die Arbeit mit GUI-Elementen unter sämtlichen Java GUI-Toolkits jeweils nur von einem einzigen Thread aus erfolgen darf, unterstützt das SwingUIDocument diese Anforderung für Swing-basierte Oberflächen. Zu diesem Zweck wird sichergestellt, dass sämtliche Benachrichtigungen an registrierte Listener auf dem Event Dispatching Thread durchgeführt werden. Auch Änderungen an der Seitenliste werden automatisch auf diesem Thread durchgeführt. Dies hat den Vorteil, dass Leseoperationen auf der Seitenliste kein Locking mehr durchführen müssen, sofern sie auf dem Event Dispatching Thread stattfinden.[15]

    Die Erzeugung eines SwingUIDocuments erfolgt mit Hilfe der statischen get-Methode, die ein existierendes Document entgegennimmt und umhüllt. Werden Dokumente auf einem PageView gesetzt, erfolgt die Umhüllung automatisch.

Zustände eines Dokuments

Dokumente in jadice verfügen über einen Status, der Auskunft über deren Zustand gibt. Ein Dokumentstatus kann zum Beispiel LOADING sein. Dieser Status signalisiert, dass das Dokument sich in einem Ladevorgang befindet.

Die Verwaltung des Dokumentstatus erfolgt über eine getter/setter-Kombination auf Instanzen von Document.

Die folgenden fünf Zustände bietet jadice über das Enum Document.BasicState standardmäßig an:

READY

Markiert ein Dokument als bereit zur Nutzung. Einige jadice-Komponenten aktivieren ihre Funktionalität nur für Dokumente, die diesen Status tragen.

LOADING

Dieser Status signalisiert, dass ein Einlesevorgang von Daten in dieses Dokument gestartet wurde, aber noch nicht vollständig abgeschlossen ist. Die Reader API setzt diesen Status automatisch auf das sich im Lesevorgang befindliche Dokument.[16]

BUSY

Gibt an, dass auf dem Dokument gearbeitet wird und es deshalb nicht bereit ist für die weitere Verwendung.

UNKNOWN

Definiert den aktuellen Dokumentzustand als unbekannt, zum Beispiel aufgrund einer Fehlersituation.

CLOSED

Ein Status der deklariert, dass dieses Dokument geschlossen wurde und deshalb aktuell nicht verwendet werden sollte.

Über die soeben vorgestellten Zustände aus Document.BasicState hinausgehend, besteht die Möglichkeit, integrationsspezifisch weitere zu deklarieren. Ein verwendbarer Dokumentstatus muss dem Interface Document.State genügen und wird typischerweise als Enum implementiert.

Insgesamt folgen die Dokumentzustände einem flexiblen Modell. Übergänge zwischen Zuständen sind nicht eingeschränkt oder an einen vordefinierten Lebenszyklus gebunden. Durch einen Aufruf von Document.setState(…) kann jederzeit ein beliebiger neuer Status angefordert werden. Der boolsche Rückgabewert der setState(…) Methode gibt Auskunft über den Erfolg der Anfrage und damit der Änderung des Dokumentstatus.

Dokumente bieten die Möglichkeit, Realisierungen von DocumentInterceptor zu registrieren. Registrierte DocumentInterceptor Instanzen werden bei angeforderten Statusänderungen nach ihrer Zustimmung gefragt. Stimmen alle registrierten Instanzen der Änderung zu, wird die Statusänderung vollzogen.

Änderungen an Dokumenten verfolgen

Struktur- und Zustandsänderungen eines Dokuments werden an registrierte Interessenten propagiert. Das Interface DocumentListener definiert einen Weg, um Informationen über Änderungen an einem Dokument zu erhalten. Solche Änderungen können zum Beispiel das Hinzufügen, Löschen oder Umsortieren von Seiten, das Verändern von Seiten, Seitensegmenten oder Ebenen oder auch Änderungen des Dokumentstatus sein. Mit DocumentAdapter wird zusätzlich eine Adapterklassse der Schnittstelle DocumentListener angeboten, die grundsätzlich einer direkten Verwendung der Schnittstelle bevorzugt werden sollte.

Setzen von Dokumentrechten (Permissions)

Die jadice document platform bietet umfangreiche Möglichkeiten zur Arbeit mit Dokumenten. Neben dem einfachen Betrachten der Inhalte sind auch verschiedene Modifikationen möglich – nicht in jedem Einsatzszenario sind diese aber zulässig. In manchen Fällen erhalten auch nur einzelne Nutzer die Option, Dokumente zu verändern, während anderen diese Möglichkeit verwehrt wird. Aus diesem Grund bietet die jadice document platform ein feingranulares und erweiterbares Rechtesystem, mit dessen Hilfe durch den Integrator gesteuert werden kann, welche Operationen einem Nutzer zur Verfügung stehen sollen.

In der jadice document platform können Rechte vergeben werden auf jedem Objekt, das die Schnittstelle PermissionsProvider implementiert. Im Besonderen ist jede Instanz von Document auch gleichzeitig PermissionsProvider.[17] Jeder PermissionsProvider stellt, wie sein Name bereits andeutet, eine Instanz von Permissions zur Verfügung. Diese wiederum gibt durch eine Liste von Permission-Objekten Auskunft darüber, welche Rechte einem Benutzer gewährt werden sollen oder auch nicht.

Neben den im Lieferumfang enthaltenen häufig benötigten Permission-Objekten bietet das flexible Modell einem Integrator die Möglichkeit, eigene Rechte zu definieren und zu vergeben. Ob ein bestimmtes Recht einem Benutzer zur Verfügung steht, wird ermittelt, indem sämtliche in den Permissions gesetzte Instanzen von Permission nacheinander befragt werden. Jede von ihnen meldet daraufhin zurück, ob die Berechtigung einem Nutzer aus ihrer Sicht gewährt oder verweigert werden soll. Alternativ kann sich eine Permission zudem für nicht zuständig erklären und somit die Entscheidung anderen überlassen.

Die Auswertung von Permission-Objekten findet so lange statt, bis erstmalig eine klare Äußerung – erlauben oder verbieten – zurückgemeldet wird. Aus diesem Grund ist bei der Vergabe von Rechten stets darauf zu achten, diese geordnet von der speziellsten hin zur allgemeinsten Einschränkung zu vergeben.

Die im Lieferumfang enthaltenen jadice-Komponenten werten Rechte aus um die Interaktion des Nutzers mit der grafischen Oberfläche entsprechend zu gestalten. Wird die jadice document platform programmatisch mittels API genutzt, bestehen keine Einschränkungen. Es findet keine automatische Überprüfung gesetzter Rechte statt.

Im Standardfall – wenn also keine Rechte explizit vergeben werden und auch das Dokumentenformat selbst keine Einschränkungen definiert – sind alle Operationen auf einem Dokument freigegeben.

Entsorgen von Dokumenten

Je nach Art und Struktur können Dokumente eine Vielzahl von Ressourcen referenzieren. Dies kann schnell zu komplexen Abhängigkeiten führen. Die Folge ist, dass der Java Garbage Collector unter Umständen keine Möglichkeit mehr hat, durch das Dokument belegte Speicherbereiche früh genug freizugeben. Nicht mehr benötigte Dokumente sollten daher frühzeitig entsorgt werden. Dies erfolgt durch einen Aufruf von Document.dispose(). Diese Methode entleert das Dokument und entfernt alle vom Dokument referenzierten Ressourcen. Konkret werden dadurch alle registrierten Listener und Interceptors deregistriert sowie sämtliche Seiten aus dem Dokument entfernt. Die einzelnen Bestandteile sind damit unabhängig voneinander und können durch den Garbage Collector schneller aufgeräumt werden. Der Status eines Dokuments nach dem Entsorgungsvorgang ist stets Document.BasicState.CLOSED.

Nachdem Document.dispose() aufgerufen wurde, kann ein Document nicht mehr weiter verwendet werden. Da sämtliche Ressourcen entfernt wurden, kann die zugesicherte Funktionalität durch das Dokument nicht mehr gewährleistet werden. Die meisten Methodenaufrufe eines ›disposed‹ Dokuments führen daher zu IllegalStateExceptions.

Zusätzlich zur vorgestellten Methode Document.dispose() existiert die Methode Document.close(). Während erstere belegte Ressourcen freigibt und ohne weitere Rückfrage bei registrieren Interceptors den Dokumentstatus auf Document.BasicState.CLOSED setzt, geht letztere den umgekehrten Weg: Zuerst wird auf gewohntem Weg versucht, den Dokumentstatus auf den Zustand Document.BasicState.CLOSED zu ändern. Nur falls keine der registrierten Instanzen von DocumentInterceptor widerspricht, erfolgt die Freigabe von Ressourcen wie in Document.dispose(). Ob der Gesamtvorgang erfolgreich war oder nicht, wird über einen entsprechenden Rückgabewert zurückgemeldet.



[14] Konkret handelt es sich dabei um eine EventList. Nähere Informationen finden sich in EventList und Erweiterungen an der Collections API.

[15] Für schreibenden Zugriff ist Locking nach wie vor notwendig. Generelle Information zum Umgang mit der Seitenliste und Locking auf EventLists finden sich in EventList und Erweiterungen an der Collections API.

[16] Weitere Informationen zum Einlesen von Dokumentdaten finden sich unter „Einlesen von Dokumentdaten“

[17] Auch Annotationen sind PermissionsProviders. Es besteht somit die Möglichkeit, Rechte feingranular pro Annotation zu vergeben. Alternativ dazu können Rechte zur Arbeit mit Annotationen dokumentweit festgelegt werden. Nähere Informationen zu beiden Optionen finden sich in der Annotations-Dokumentation („Berechtigungskonzept von Annotationen“).

[jadice viewer Version 6.1.37: Dokumentation für Entwickler. Veröffentlicht: 2024-11-11]