Die Schnittstelle PropertiesProvider
Das Document
-Interface erweitert die Schnittstelle PropertiesProvider
. Diese
Schnittstelle findet sich noch in einer ganzen Reihe weiterer Klassen und Interfaces der
document platform. In allen Fällen dient sie dem gleichen Zweck, nämlich es zu erlauben,
integrationsspezifische Zusatzdaten an diese Objekte anzuhängen. PropertiesProvider
stellen zu diesem Zweck eine Map
zur Verfügung, die Strings als
Schlüssel verlangt, jedoch beliebige Objekte als
Werte enthalten kann. Diese Funktionalität gab es bereits in jadice
4 in Form der Methoden
putUserProperty(key,value)/getUserProperty(key),
allerdings haben wir in der neuen Version einige wesentliche Änderungen vorgenommen:
Statt das API der
PropertiesProvider
implementierenden Klasse mit einer Vielzahl von Methoden zu überfrachten, sind wir wieder den Weg der Komposition gegangen.PropertiesProvider
definiert exakt eine Methode, nämlich Map<String, Object> getProperties().Die Schnittstelle wird nun einheitlich an verschiedenen Stellen in unserem API verwendet, statt mehrfach mit ähnlicher aber teilweise leicht abweichender Funktionalität implementiert zu sein.
Es besteht eine klare Aufgabentrennung zwischen Informationsbereitstellung (entsprechend der ehemaligen InfoProvider-Funktionalität) und der Haltung eher technisch orientierter Zusatzdaten.
PropertiesProvider
ist rein für letzteres zuständig, was aber natürlich nicht heißt, dass Informationen einesPropertiesProvider
einem Benutzer nicht in bestimmten Situationen präsentiert werden können.
Die Beschreibung der in einem PropertiesProvider
geführten Daten als
›integrationsspezifische Zusatzdaten‹ bedeutet allerdings nicht, dass die jadice document
platform nicht selbst Zusatzdaten an PropertiesProvider
anhängt. Vielmehr nutzen wir
diese auch selbst, und zwar in Fällen, in denen eine Anwendung zu speziell ist, als dass
eine API-Erweiterung gerechtfertigt wäre. Generell sollten Sie
allerdings keine Annahmen über die verwendeten Keys machen. Selbst
wenn wir für die Implementierung einer Funktionalität Properties eines
PropertiesProvider
zur Speicherung benutzen, werden wir immer ein
API zur Verfügung stellen, das dieses Implementierungsdetail
verbirgt. Darüber hinaus verwenden wir als Keys generell Zeichenfolgen, die mit
com.levigo.
beginnen. Sie haben also ohne Weiteres die Möglichkeit,
Kollisionen zu vermeiden und können leicht erkennen, wo es sich um jadice-eigene
Properties handelt. Wir halten es für eine gute Idee, für die Keys eine Namenskonvention
ähnlich der von Java-Packages zu verwenden, dies ist aber keineswegs verpflichtend.
Als Inspiration hier ein Beispiel, wie sie Properties verwenden könnten:
// Erzeugen eines Dokumentes final Document doc = new BasicDocument(); // Laden des Dokumentes... final File sourceFile = new File("MeineBeispieldatei.txt"); // ... // Anreichern mit Properties doc.getProperties().put("org.example.SourceFile", sourceFile); doc.getProperties().put("org.example.LoadTime", new Date()); doc.getProperties().put("org.example.Weather", Weather.Cloudy); // ... später System.out.println("Eigenschaften des Dokuments"); for (final Map.Entry<String, Object> e : doc.getProperties().entrySet()) System.out.println(" " + e.getKey() + " -> " + e.getValue());
Neben dem Document
sind derzeit noch folgende weitere Klassen beziehungsweise
Interfaces PropertiesProvider
:
sowie darüber hinaus noch einige mehr.
Properties sind in der Regel an den Lebenszyklus des Objektes gebunden, an dem sie angefügt wurden. Dies bedeutet einerseits, dass Properties automatisch per garbage collection entsorgt werden, sobald das übergeordnete Objekt entsorgt wird und der Eigenschaftswert nicht noch anderweitig referenziert wird. Andererseits müssen Sie aber beachten, dass Eigenschaftswerte über hard references gehalten werden. Sie sollten also bei ›teuren‹ Objekten gegebenenfalls darauf achten, diese mittels remove(key)auch wieder zu entfernen, da von ihnen belegter Speicher und andere Ressourcen sonst erst freigegeben werden, wenn das übergeordnete Objekt entsorgt wird.
Manche Klassen, darunter die Standardimplementierungen BasicDocument
und
BasicPage
versenden Benachrichtigungen bei Änderungen an ihren Properties. Um diese
Benachrichtigungen zu empfangen, können auf dem Document
als DocumentListener
beziehungsweise auf der Page
als PageListener
registriert werden. Beide Interfaces
erben die Funktionalität der altbekannten Schnittstelle
java.beans.PropertyChangeListener
. Da sowohl das Document
als
auch die Page
über die Änderungen an den Properties hinaus für Änderungen ihren
Objekteigenschaften ensprechende PropertyChangeEvent
s versenden,
werden den Keys der Properties im PropertyChangeEvent
folgende
String
-Konstanten als Kennzeichnungen vorangestellt:
Änderung einer User-Property auf einem Dokument:
Document.PROPERTY_PREFIX_USER_PROPERTY
Änderung einer User-Property auf einer Seite:
Listener wurde auf der Seite registriert:
Page.PROPERTY_PREFIX_USER_PROPERTY
Listener wurde auf dem Dokument registriert:
Document.PROPERTY_PREFIX_PAGE
+Document.PROPERTY_PREFIX_USER_PROPERTY
Das folgende Beispiel verdeutlicht den Sachverhalt an Hand eines
DocumentListener
s.
Art der Änderung |
PropertyChangeEvent im
DocumentListener |
||
---|---|---|---|
Name | OldValue | NewValue | |
Hinzufügen der Property SourceFile auf
dem Dokument |
Document.PROPERTY_PREFIX_USER_PROPERTY +
"SourceFile" |
null |
File("someFile.txt") |
Ändern der Property SourceFile |
Document.PROPERTY_PREFIX_USER_PROPERTY +
"SourceFile" |
File("someFile.txt") |
File("someOtherFile.txt") |
Entfernen der Property SourceFile |
Document.PROPERTY_PREFIX_USER_PROPERTY +
"SourceFile" |
File("someOtherFile.txt") |
null |
Hinzufügen der Property myPropertyKey auf einer
Seite des Dokuments |
Document.PROPERTY_PREFIX_PAGE +
Document.PROPERTY_PREFIX_USER_PROPERTY +
"myPropertyKey" |
null |
myPropertyValue |
Ändern des Dokumentstatus mittels
Document.setState(CLOSED) |
Document.PROPERTY_STATE |
BasicState.READY |
BasicState.CLOSED |
PropertiesProvider
und Nebenläufigkeit
Die von jadice bereit gestellten Implementierungen von PropertiesProvider
benutzen
ausschließlich ConcurrentHashMap
s zur Bereitstellung der
PropertiesProvider
-Funktionalität. Sie sind daher Thread-sicher. Dies ist jedoch keine
Zusage der PropertiesProvider
-Schnittstelle. Im Zweifelsfalle ist es daher besser, die
Dokumentation der fraglichen Implementierung hierzu zu konsultieren.