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.[13]
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.[14]Die Erzeugung eines
SwingUIDocument
s erfolgt mit Hilfe der statischenget
-Methode, die ein existierendesDocument
entgegennimmt und umhüllt. Werden Dokumente auf einemPageView
gesetzt, erfolgt die Umhüllung automatisch.
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.[15]
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.
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
.[16] 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.
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 IllegalStateException
s.
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.
[13] Konkret handelt es sich dabei um eine EventList
. Nähere
Informationen finden sich in „EventList
und Erweiterungen an der Collections API“.
[14] Für schreibenden Zugriff ist Locking nach wie vor
notwendig. Generelle Information zum Umgang mit der
Seitenliste und Locking auf EventList
s finden sich in
„EventList
und Erweiterungen an der Collections API“.
[15] Weitere Informationen zum Einlesen von Dokumentdaten finden sich unter „Einlesen von Dokumentdaten“
[16] Auch Annotationen sind PermissionsProvider
s. 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 (Kapitel 4, Berechtigungskonzept von Annotationen).