Speichern eines Dokuments als Datei

Anforderung

Manchmal besteht der Wunsch das im Viewer angezeigte Dokument als Datei zu exportieren. In der jadice 4er Generation gab es zu diesem Zweck ein eigenes Command. Dieses Command öffnete zunächst einen Datei-Auswahl-Dialog. Hier konnte der Anwender entscheiden, wohin die Datei zu exportieren ist und wie der Name der Datei lauten sollte. Hatte der Anwender sich für ein Datei-Ziel entschieden, wurden die Original-Daten des Dokuments an den Zielort kopiert. Bei zusammengesetzen Dokumenten aus unterschiedlichen Datenquellen exportierte das Command nur das erste Dokument.

Wie kann diese Funktion in der jadice 5er Welt implementiert werden?

Lösungsmöglichkeit

Als ersten Schritt muß ein Ziel und Name der Ausgabe-Datei ermittelt werden. Dazu kann man sich eines JFileChooser Dialogs bedienen. Ist eine passende Ausgabe-Datei gefunden, müssen nur noch die Original-Daten des Dokuments exportiert werden. Idealerweise verwendet man dazu den ursprünglichen Dokument-Datenstrom, der zum Laden des Dokuments bereitgestellt wurde. Leider ist dieser Datenstrom nicht immer zur Hand. Glücklicherweise bieten die PageSegments eine Zugriffsmöglichkeit auf ihre Originaldaten. Mithilfe diesen kleinen Tricks können nun die Original-Daten des Dokuments exportiert werden.
Im Folgenden ist ein Source Code Fragment abgedruckt, das den beschriebenen Prozess verdeutlicht. Beispiel

File outputFile=...
UIDocument<Component> uiDocument = getPageView().getDocument();
if (uiDocument != null && //
    uiDocument.getState() == Document.BasicState.READY && //
    uiDocument.getPageCount() > 0) {
	final EventList<Page> pages = uiDocument.getPages();
	final ReadWriteLock lock = pages.getReadWriteLock();
	lock.readLock().lock();
	try {
		Page page = uiDocument.getPage(0); // jede Seite bietet Zugriff auf die beinhalteten PageSegments, die einen Zugriff auf ihr Original-Datenstrom anbieten. 
		FileOutputStream fos = null;
		try {
			fos = new FileOutputStream(outputFile);
			final PageSegmentSource pss = page.getPageSegment(DocumentLayer.DEFAULT).getSource(); // in diesem Beispiel sollen die Daten aus dem Standard Dokument Layer kopiert werden
			final SeekableInputStream stream = pss.getStream();
			synchronized (stream) { // Der Zugriff auf den Datenstrom muss immer synchronisiert sein, da jadice den Datenstrom konkurrierend nutzt 
				stream.seek(0); // Um die Daten vollständig ausgeben zu können, muss der Lesezeiger auf die Anfangsposition gesetzt werden.
				IOUtils.copy(stream, fos); 
			}
		} catch (final Exception e) {
			e.printStackTrace();
		} finally {
			if (fos != null) {
				try {
					fos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	} finally {
		lock.readLock().unlock();
	}
}