Universität des Saarlandes Naturwissenschaftlich-Technische Fakultät I Fachrichtung Informatik Bachelorarbeit Ein Word Plugin für mathematische Assistenzsysteme vorgelegt von Thorsten Hey am 30.03.2009 Angefertigt unter der Leitung von Prof. Dr. Jörg Siekmann Betreut von Dipl.-Inform. Marc Wagner Begutachtet von Prof. Dr. Jörg Siekmann Prof. Dr. Christoph Benzmüller Eidesstattliche Erklärung Ich erkläre hiermit an Eides Statt, dass ich die vorliegende Arbeit selbstständig verfasst und keine anderen als die angegebenen Quellen und Hilfsmittel verwendet habe. Statement under Oath I confirm under oath that I have written this thesis on my own and that I have not used any other media or materials than the ones referred to in this thesis. Einverständniserklärung Ich bin damit einverstanden, dass meine (bestandene) Arbeit in beiden Versionen in die Bibliothek der Informatik aufgenommen und damit veröffentlicht wird. Declaration of Consent I agree to make both versions of my thesis (with a passing grade) accessible to the public by having them added to the library of the Computer Science Department. Saarbrücken,…………………………….. (Datum / Date) …………………………………………. (Unterschrift / Signature) Zusammenfassung Die Weiterentwicklung mathematischer Assistenzsysteme in den letzten Jahren führt dazu, dass auch Benutzer ohne Expertenwissen die Dienste dieser Systeme in ihrer gewohnten Umgebung nutzen möchten. In dieser Arbeit wird zum ersten Mal ein Microsoft Word Plugin entwickelt, das eine generische Schnittstelle zu Dokumenten-basierten Diensten bereitstellt. Das Plugin befähigt den Benutzer, ein Dokument durch ein mathematisches Assistenzsystem zu verizieren und etwaige Fehler durch das Plugin visualisieren zu lassen. Ebenfalls erhält der Benutzer interaktive Unterstützung beim mathematischen Beweisen, beispielsweise indem auf Anfrage weitere Schritte automatisch in das Dokument eingefügt werden. Hierzu wird in dieser Arbeit das neue ISO-zertizierte Dokumentenformat Oce Open XML zum ersten Mal für die Verwaltung mathematischer Inhalte verwendet, so dass Berechnungen und Diagnoseergebnisse von mathematischen Assistenzsystemen dynamisch und inkrementell eingebunden werden können. Danksagung Ich möchte meinem Betreuer Marc Wagner für das Thema dieser Arbeit, seine unermüdliche Unterstützung und die Geduld, die er für meine Fragen aufbrachte, danken. Ausserdem will ich Herrn Prof. Siekmann für die angenehme und motivierende Arbeitsatmosphäre danken, die ich am Lehrstuhl vorgefunden habe. Ich bedanke mich auch bei Marvin Schiller, der mich durch Korrekturlesen und viele Anregungen beim Verfassen der Arbeit sehr unterstützt hat. Ich möchte mich auch bei meiner Familie bedanken, die mir das Studium erst ermöglicht hat. Inhaltsverzeichnis 1 Einleitung 3 2 Architektur 5 2.1 Funktionsweise . . . . . . . . . . . . . . . . . . . . . . . . . . 5 2.2 Sessionverwaltung . . . . . . . . . . . . . . . . . . . . . . . . . 8 2.2.1 Timer . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 2.2.2 Kongurationsdatei . . . . . . . . . . . . . . . . . . . . 11 2.2.3 Kommunikation zwischen Plugin und Server 13 . . . . . . 3 Dokumentenverarbeitung 3.1 3.2 15 Dokumentenmodell . . . . . . . . . . . . . . . . . . . . . . . . 15 3.1.1 XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 3.1.2 Beispiel Dokument . . . . . . . . . . . . . . . . . . . . 18 . . . . . . . . . . . . . . . . . . . . 21 Dokumente in Word 2007 3.2.1 Struktur eines Dokumentes . . . . . . . . . . . . . . . . 21 3.2.2 Repräsentation von Text und Formatierung . . . . . . 22 3.2.3 Oce MathML (oMath) . . . . . . . . . . . . . . . . . 24 3.3 Bereinigung eines Dokumentes . . . . . . . . . . . . . . . . . . 25 3.4 Annotation eines Dokumentes 29 3.5 . . . . . . . . . . . . . . . . . . 3.4.1 Annotationspfade . . . . . . . . . . . . . . . . . . . . . 31 3.4.2 Technik des Annotierens . . . . . . . . . . . . . . . . . 33 3.4.3 Anpassen eines Dokumentes und der Annotationspfade 34 3.4.4 Normalisieren einer Annotationsliste . . . . . . . . . . 44 3.4.5 Einfügen von Annotation in ein Dokument . . . . . . . 45 Updaten eines Dokumentes . . . . . . . . . . . . . . . . . . . . 50 4 Interaktive Dienste 4.1 4.2 53 Kontext-Sensitive Menüs . . . . . . . . . . . . . . . . . . . . . 53 4.1.1 . . . . . . . . . . . . . . . 55 . . . . . . . . . . . . . . . . . 58 Anfragen von Menüinhalten Ergebnisse interaktiver Dienste 1 INHALTSVERZEICHNIS 2 5 Verwandte Arbeiten 59 6 Zusammenfassung und Ausblick 61 Kapitel 1 Einleitung Die enorme Weiterentwicklung mathematischer Assistenzsysteme in den letzten Jahren führt dazu, dass auch Benutzer ohne Expertenwissen solche Systeme bedienen möchten. Somit macht es Sinn als Eingabeschnittstelle ein Textverarbeitungsprogramm zu wählen, das eine hohe Verbreitungsrate und leichte Bedienbarkeit besitzt, um den Arbeitsaufwand zur Benutzung eines mathematischen Assistenzsystems minimal zu halten. Microsoft Word bietet eben diese Verbreitungsrate und Bedienbarkeit und ist der Mehrzahl aller Benutzer bereits bekannt. Ein Benutzer kann so in einer gewohnten Umgebung das Assistenzsystem verwenden, ohne zunächst zusätzliche Spezialsoftware installieren zu müssen und sich mit der Bedienung dieser neuen Software auseinander zu setzen. Wurde in bisherigen MS Word Textverarbeitungsprogrammen noch ein externer Formeleditor benötigt, so kann nun eine mathematische Umgebung deniert werden und dort beliebige mathematische Formeln eingegeben werden. Dieser Umstand verringert den Arbeitsaufwand und wird von Microsoft Word seit Version 2007 unterstützt. Das Ziel dieser Arbeit ist es, ein Plugin für Microsoft Word zu entwickeln, um eine nahtlose und benutzerfreundliche Integration der Dienste eines mathematischen Assistenzsystems zu ermöglichen. Eine Funktionalität des Plugins ist es, ein Dokument von dem Assistenzsystem auf Korrektheit prüfen zu lassen. Das Plugin erhält dabei von einem Server Informationen über Fehler im Dokument, die es dann optisch kennzeichnet. Der Benutzer hat nun die Möglichkeit seine Fehler zu analysieren. Bevor das Dokument wieder bearbeitet wird, werden diese Markierungen wieder entfernt. 3 KAPITEL 1. EINLEITUNG 4 Eine weitere Funktionalität ist das Anfordern von Unterstützung. Ein Benutzer kann für eine bestimmte Stelle im Dokument den nächsten Schritt seiner Beweisführung vom Assistenzsystem ermitteln lassen. Dies geschieht über interaktive Menüs. Auf Anfrage werden dem Benutzer verschiedene Möglichkeiten für den nächsten Schritt in einem Menü angeboten. Die Arbeit ist wie folgt gegliedert. Im zweiten Kapitel wird zunächst die Verwaltung der Dokumente auf dem Server beschrieben. Insbesondere werden wir die Unterstützung multipler Dokumente und das Synchronisieren der Dokumente mit dem Server erläutern. Im dritten Kapitel wird das Dokumentenmodell von Microsoft Word eingeführt, zusammen mit dem Markup mathematischer Formeln, genannt oMath. Auf dieser Grundlage werden dann die Algorithmen zum Bereinigen des Dokumentes, zum Integrieren von Fehlern und zum Einfügen von Änderungen in das Dokument entwickelt. Im vierten Kapitel wird die Funktionsweise der interaktiven Menüs genauer betrachtet, die benötigt werden, um Unterstützung für das Dokument anzufordern. Schliesslich geben wir einen Überblick über verwandte Arbeiten in Kapitel fünf, bevor wir die Resultate dieser Arbeit in Kapitel sechs zusammenfassen. Kapitel 2 Architektur Die nahtlose und benutzerfreundliche Integration der Dienste eines mathematischen Assistenzsystems wird durch ein Erweiterungsmodul realisiert, das die Schnittstellen der Microsoft Word Software verwendet, um MS Word so um die gewünschten Funktionalitäten zu erweiteren. Dieses Erweiterungsmodul wollen wir im Folgenden Mediator Plugin nennen. Bevor wir die Architektur des Mediator Plugins einführen, werden wir im Folgenden die Funktionsweise des Plugins mit Hilfe eines Beispiels erläutern. 2.1 Funktionsweise Ein Benutzer startet Microsoft Word mit aktivem Mediator Plugin und beginnt ein neues Dokument zu erstellen bzw. ein bereits vorhandenes Dokument zu bearbeiten. Ein solches Dokument zeigt Abbildung 2.1. Durch das Starten des Plugins loggt der Benutzer sich auf einem Server für mathematische Assistenzdienste ein, wie etwa dem Ωmega-System [8]. Das Einloggen kann anonym oder mit einem Account erfolgen. In beiden Fällen wird ein Username, ein Passwort und die Adresse des Servers aus einer Kongurationsdatei geladen. Der Inhalt dieser Kongurationsdatei wird später kurz erläutert. Während der Bearbeitung des Dokumentes wird in regelmässigen Intervallen das Dokument zum Server geschickt. Hier werden die Änderungen des Dokumentes erkannt. Der Server berechnet aus dem ihm aktuell übertragenen Dokument Metadaten, die bei einer Prüfung des Dokumentes durch den Serverdienst entstehen und später an der entsprechenden Stelle im Doku- 5 KAPITEL 2. ARCHITEKTUR 6 Abbildung 2.1: Dokument in Word vor dem Annotieren ment eingefügt werden sollen. Diese Metadaten enthalten Informationen zu bestimmten Textabschnitten, wie etwa Fehler oder verizierte Abschnitte. Diese Metadaten wollen wir im Folgenden Annotationen nennen. Die Länge des eben erwähnten Synchronisierungs-Intervalls wird aus einer Kongurationsdatei geladen. Die Intervalllänge gibt an, in welchen Zeitabständen das Dokument zum Server übermittelt wird. Der Benutzer hat während der Bearbeitung zwei Möglichkeiten mit dem Server zu interagieren. Zunächst kann er Hilfestellungen für das aktuelle Dokument anfordern, etwa wenn er bei einem mathematischen Beweis nicht mehr weiter weiss. So wird dann von einem Serverdienst der nächste Schritt des Beweises errechnet und durch ein Update in das aktive Dokument eingefügt. Hierbei fordert der Benutzer zunächst ein Menü vom Server für genau die Stelle im Dokument an, zu der er Hilfe benötigt. In diesem Menü bietet der Server spezielle Hilfestellungen für diese Position. Nach Auswahl der Hilfe werden Updates angefordert und in das aktive Dokument eingefügt. Die zweite Möglichkeit der Interaktion zwischen Benutzer und Server ist das Anfordern von Annotationen, also einer Überprüfung des aktuellen Doku- KAPITEL 2. 7 ARCHITEKTUR mentes, bei der z.B. Fehlermeldungen in das Dokument eingebunden werden. Abbildung 2.2 zeigt ein annotiertes Dokument. Abbildung 2.2: Dokument in Word nach dem Annotieren Durch Betätigung des entsprechenden Buttons innerhalb des Menüs ruft der Benutzer den Serverdienst Prüfen ab. Es wird zunächst das Dokument be- reinigt, indem Teile des Dokumentes entfernt werden, die für die Dienste des Servers nicht relevant sind. Nicht relevante Teile können beispielsweise Formatierungen wie Schriftfarbe, Fonts, aber auch Bilder, Tabellen oder Schriftgrösse sein. Diese bereinigte Fassung wollen wir im Folgenden bereinigtes Dokument nennen. Somit beinhaltet das bereinigte Dokument nur für die Berechnung der Annotationen relevante Informationen. Die zu erhaltenden Elemente können über eine Kongurationsdatei speziziert werden. Das bereinigte Dokument wird nur an den Server verschickt und nicht dem Benutzer angezeigt. Das Plugin erhält nun eine Annotationsliste, die in das Dokument eingebunden werden soll. Zunächst wird eine Sicherungskopie des aktiven Dokumentes erzeugt, damit eine Version ohne Annotationen erhalten bleibt. Nach dem Einbinden der Annotationen in das aktive Dokument wird die Benutzereingabe gesperrt. Das annotierte Dokument wollen wir im Folgenden temporäres Dokument nennen, da dieses nur temporär angezeigt wird und vom KAPITEL 2. ARCHITEKTUR 8 Benutzer nicht verändert werden kann. Der Benutzer kann nun seine Fehler analysieren. Um wieder zur Bearbeitung des Dokumentes zu gelangen, kann ein Bearbeiten-Button betätigt werden. Hierfür wird nun das temporäre Dokument verworfen und die Sicherungskopie des Dokumentes als aktives Dokument angezeigt. Wir können somit die Varianten eines Dokumentes wie folgt klassizieren: • Aktives Dokument: Das geönete Dokument, dass sich im momentan ausgewählten Windows-Fenster bendet, bearbeitet werden kann, keine Annotationen enthält, in das jedoch Updates eingefügt werden können. • Bereinigtes Dokument: Das Dokument, in dem nur zur Berechnung der Annotationen relevante Objekte enthalten sind. • Temporäres (annotiertes) Dokument: Das Dokument, in dem die Annotationen des Servers eingebunden wurden und das nicht zur Bearbeitung freigegeben ist. Das Anfordern von Hilfe oder Annotationen kann beliebig oft wiederholt werden. Sollte der Benutzer nun seine Arbeit beenden wollen, muss er lediglich MS Word schliessen. Der Logout erfolgt automatisch. Die beschriebene Funktionsweise legt eine Aufteilung der Architektur in die zwei Bereiche Sessionverwaltung und Dokumentenverarbeitung nahe. Die Sessionverwaltung ist für den Login, Logout und die Verwaltung der Dokumente auf dem Server verantwortlich, die Dokumentenverarbeitung übernimmt das Annotieren und Updaten des Dokumentes. 2.2 Sessionverwaltung Die Sessionverwaltung implementiert die Idee von multiplen Dokumenten. Diese Idee hat ihren Ursprung darin, dass ein Benutzer mehrere Dokumente während einer Arbeitssitzung bearbeiten möchte. Um mit mehreren Doku- KAPITEL 2. 9 ARCHITEKTUR menten gleichzeitig zu arbeiten, muss jedes Dokument eindeutig vom Server identiziert werden können. Dies kann nur über eine eindeutige ID gelingen, die jedem Dokument zugewiesen wird. Somit können die Forderungen an die Sessionverwaltung wie folgt formuliert werden. Forderung an die Sessionverwaltung 1. Identizierung des Dokumentes Kennzeichnen des Dokumentes um eine eindeutige Identikation auf Serverseite zu ermöglichen. 2. Versionsverwaltung Verwalten der Versionen eines Dokumentes um Änderungen des Inhaltes leichter bestimmen und entsprechende Annotationen leichter berechnen zu können. Im Folgenden wollen wir einige Ansätze zur Sessionverwaltung diskutieren. Identikation über Inhalt Das Berechnen der ID eines Dokumentes über seinen Inhalt liefert einen wenig erfolgversprechenden Ansatz, denn der Inhalt eines Dokumentes kann sich während einer Arbeitssitzung stark ändern. Dies kann sogar soweit gehen, dass der Inhalt eines Dokumentes sich komplett verändert, da der Benutzer den Inhalt löscht und mit einem neuen Inhalt füllt. Identikation über Dateinamen Ein weiterer Ansatz wäre das Identizieren über den Dateinamen. Doch leider führt auch dieser Ansatz bei genauerer Betrachtung ins Leere. Denn ein Dateiname kann ebenfalls während einer Arbeitssitzung geändert werden, so zum Beispiel heisst ein neu erstelltes Dokument in MS Word 2007 standardmässig Ohne-Titel.docx. Der Benutzer wird beim Abspeichern des Dokumentes sicherlich einen weitaus aussagekräftigeren Namen wählen. Wir sehen also, dass auch Dateiname und Pfad nicht x sind und sich deshalb ebensowenig zum Identizieren von Dokumenten eignen. KAPITEL 2. ARCHITEKTUR 10 Identikation über Dokumentvariable Da die beiden intuitivsten Ansätze zu keinem befriedigenden Ergebnis führen würden, ist die naheliegendste Idee, jedem Element eine eindeutige ID zuzuweisen, die vom Server generiert wird und erhalten bleibt. Diese ID wird immer dann angefordert, wenn ein Dokument zum Server geschickt werden soll und noch keine ID besitzt, also dem Server noch nicht bekannt ist. Diese ID wollen wir im Folgenden PaperID nennen. Die PaperID wird mit Hilfe einer Dokumentvariable an das Dokument gebunden. Die Dokumentvariable in MS Word bietet die Möglichkeit Werte eines elementaren Datentyps (bool, int, oat etc.) an ein Dokument zu binden. Ein Dokument kann beliebig viele dieser Dokumentvariablen besitzen, wobei jede über ihren Namen eindeutig identizierbar sein muss. Desweiteren können solche Variablen ausgelesen und manipuliert werden. Da ein Identizieren des Dokumentes möglich ist, können wir uns nun der zweiten Forderung an die Sessionverwaltung widmen. Jedem Dokument soll eine Versionsnummer zugewiesen werden. Diese Versionsnummer wird, wie im einleitenden Beispiel erläutert, dazu genutzt, die Aktualität eines Dokumentes zu überprüfen. Auch diese Information wird wieder mittels Dokumentvariable an das entsprechende Dokument gebunden. Es ist leicht zu sehen, dass eine PaperID pro Dokument nur einmal angefordert werden muss, da diese die ganze Arbeitssitzung hindurch erhalten bleibt und sich nicht ändert. Eine Versionsnummer hingegen muss in regelmässigen Abständen aktualisiert werden und zwar immer dann, wenn ein Dokument zum Server geschickt wird. Das kontinuierliche Synchronisieren des Dokumentes mit dem Server ist deshalb sinnvoll, da so beim Annotieren des Dokumentes nicht mehr das gesamte Dokument geparst werden muss, um die Annotationsliste zu berechnen. Das Assistenzsystem berechnet asynchron für die Version des Dokumentes auf dem Server bereits vor dem Anfordern die Liste der Annotationen. So verringert sich die Wartezeit von Seiten des Benutzers, da nur die Änderungen seit dem letzten Hochladen berücksichtigt werden müssen. Das Updaten der Versionsnummer ist somit an das Hochladen des Dokumentes auf den Server gebunden und erfolgt in regelmässigen Intervallen, deren Abstand in der Kongurationsdatei angegeben ist. KAPITEL 2. ARCHITEKTUR 11 2.2.1 Timer Das regelmässige Hochladen des Dokumentes, wie in Kapitel 2.1 erläutert, wird von einem Timer realisiert. Dieser Timer stellt somit den Motor der Sessionverwaltung dar. Abbildung 2.3 beschreibt die Arbeitsweise des Timers und somit das Verwalten der SessionID, der PaperIDs und der Versionsnummern. Abbildung 2.3: Arbeitsweise Timer Wie man in Abbildung 2.3 erkennen kann, wird eine PaperID nur dann angefordert, wenn das Dokument dem Server noch nicht bekannt ist. Das bedeutet im Einzelnen, dass eine PaperID für ein bestimmtes Dokument nur dann angefordert wird, wenn an eben dieses Dokument per Dokumentvariable keine PaperID gebunden ist. In diesem Fall liefert der Server nach dem Hinzufügen des Dokumentes (SOAP Kommando Add) in die Server-Session des Benutzers eine PaperID und eine Versionsnummer zurück. Falls eine PaperID gefunden wurde, wird nach dem Synchronisieren (SOAP Kommando Commit) nur eine neue Versionsnummer an das Dokument angehängt, die vom Server zurückgeliefert wurde, und somit die veraltete Versionsnummer ersetzt. 2.2.2 Kongurationsdatei Die Kongurationsdatei des Mediator Plugins bietet die Möglichkeit Einstellungen zu verändern. Eine Standard Kongurationsdatei bendet sich im KAPITEL 2. 12 ARCHITEKTUR Installationsverzeichnis des Mediator Plugins. Diese Konguration wird benutzt, wenn keine benutzerspezische Kongurationsdatei im Homeverzeichnis des Benutzers gefunden wurde. Im Folgenden werden die zu steuernden Einstellungen beschrieben, die die Kongurationsdatei beinhaltet. • Farbcodes der einzelnen Annotationstypen Standard: error valid in progress ignore rot grün orange grau Diese Liste kann komplett durch eigene Paare von Annotationstypen und Farbcodes ersetzt werden. • Logindaten des Benutzers Standard: Passwort Benutzername anonym anonym • Zu erhaltende Objekte beim Bereinigen Es werden die Objekte angegeben, die beim Bereinigen des Dokumentes nicht entfernt werden dürfen. Solche Objekte sind <t> <p> (Paragraph), (Text), etc. • Zu markierende Mathematische Markup-Objekte Es werden die mathematischen Markup-Objekte angegeben, die beim Annotieren automatisch mitgekennzeichnet werden sollen. Solche Objekte sind Klammern, Summenzeichen etc. KAPITEL 2. 13 ARCHITEKTUR 2.2.3 Kommunikation zwischen Plugin und Server Im einleitenden Beispiel dieses Kapitels wurde beschrieben, dass beim Starten von Microsoft Word, mit aktivem Mediator Plugin, ein automatischer Login mit Logindaten aus der Kongurationsdatei durchgeführt wird. Desweiteren wurde erwähnt, dass während der Bearbeitung des Dokumentes eine Kommunikation zwischen Plugin und Server besteht, in der das Dokument auf dem Server synchronisiert wird. Wir wollen nun anhand des Message Sequence Chart in Abbildung 2.4 genauer auf diese Kommunikation eingehen. Beim Start wird zunächst der Login ausgeführt, mit dem sich der Benutzer auf dem Server anmeldet und eine SessionID erhält. Hierzu schickt das Plugin die Anmeldedaten zum Server, der bei erfolgreicher Anmeldung eine SessionID zurückliefert. Während des Synchronisierens wird, wie im einleitenden Beispiel beschrieben, das Dokument auf dem Server zur Session hinzugefügt, falls es noch keine PaperID haben sollte. Dies wird von der Funktion Add implementiert. Die Add Funktion übermittelt die SessionID und den Inhalt des Dokumentes zum Server und liefert eine PaperID und eine Versionsnummer zurück, die an das Dokument per Dokumentvariable gebunden werden. Falls schon eine PaperID per Dokumentvariable an das Dokument angefügt worden ist, wird ein Update der Versionsnummer ausgeführt. Das Updaten wird von der Funktion Commit implementiert, die den Inhalt des Dokumentes, die da- zugehörige PaperID, die ID der Session und die aktuelle Versionsnummer zum Server übermittelt. Bei erfolgreichem Commit wird an das Plugin die PaperID und eine neue Versionsnummer zurückgeliefert, mit der die an das Dokument gebundene Versionsnummer überschrieben wird. Die im einleitenden Beispiel erwähnte Interaktion zwischen Server und Plugin beim Anfordern von Unterstützung über eine Menüinteraktion, sowie die Integration von Fehlern durch Annotationen, werden in Abbildung 2.4 noch nicht erwähnt. Wir wollen erst in Kapitel 4.2 dieser Arbeit auf diese Punkte eingehen und dabei das Message Sequence Chart und den Timer entsprechend erweitern. KAPITEL 2. ARCHITEKTUR Abbildung 2.4: Kommunikation zwischen Plugin und Server 14 Kapitel 3 Dokumentenverarbeitung In diesem Kapitel soll zunächst der Begri der eXtensible Markup Language [11], kurz XML, geklärt werden, da dies die Basis des Microsoft Word Dokumentenmodells darstellt. Danach wollen wir das Dokumentenmodell von Microsoft Word 2007 einführen und anhand dieses Modells die Techniken des Bereinigens und des Annotierens vorstellen und erläutern. 3.1 Dokumentenmodell Dokumente werden in Microsoft Word 2007 [7] in dem neuen Oce Open XML Format [6] repräsentiert. Hierbei handelt es sich um einen oenen Standard für XML-basierte Dateiformate zur Speicherung von Bürodokumenten, der den Daten- und Dateienaustausch zwischen verschiedenen Büroanwendungspaketen ermöglichen soll. Oce Open XML wurde mittlerweile von der Normierungsorganisation ECMA international [3] ratiziert und ist als ISO-Standard [4] anerkannt. Das Abspeichern der Dokumente in diesem Format bietet einige Vorteile, die später genauer betrachtet werden sollen. Zunächst einmal soll der Begri des XML Formats eingeführt werden. 3.1.1 XML eXtensible Markup Language, kurz XML, ist eine Auszeichnungssprache, die die Möglichkeit bietet, hierarchisch strukturierte Daten in Form von Textdateien abzuspeichern. Aber nicht nur zum Abspeichern hierarchischer Daten wird XML benutzt, sondern auch zum Austausch von Daten zwischen Computersystemen. 15 KAPITEL 3. 16 DOKUMENTENVERARBEITUNG Aufbau Ein XML Dokument ist eine hierarchisch organisierte Textdatei. Die einzelnen Elemente dieser Hierarchie werden als Tags oder Knoten bezeichnet. Eine Baumstruktur gibt die Hierarchie zwischen den einzelnen Elementen an. Ein Knoten in dieser Hierarchie ist von der Form <name>, wobei name1 den Namen des Knotens angibt. Ein Knoten kann einen beliebigen Namen tragen wie z.B. <color>. Die Menge der Namen aller Knoten innerhalb eines Do- kumentes wird dann als das Vokabular oder Sprache bezeichnet. Ein Knoten kann neben seinem Namen noch zusätzliche Informationen tragen. Diese Informationen werden Attribute eines Knotens genannt. Diese Attribute spezizieren den Knoten genauer. Ein mögliches Attribut für unseren color-Knoten könnte <color val='FF0000'> sein. Dieses zusätzliche Attribut würde die Farbe als rot spezizieren. Nun da wir den Begri des Knotens eingeführt haben, soll auf die Hierarchie der Knoten innerhalb des Dokumentes eingegangen werden. Vater Ein Knoten, der innerhalb der Hierarchie direkt über einem Knoten steht, ist dessen Vater. Jeder Knoten kann Vorfahre maximal einen Vater besitzen. Als Vorfahren eines Knotens bezeichnet man die Knoten, die über ihm in der Hierarchie stehen und die Väter Kinder Nachfahre Geschwister seiner Väter sind. Knoten, die innerhalb der Hierarchie direkt unter einem Knoten stehen, sind die Kinder dieses Knotens. Knoten, die in der Hierarchie unter einem Knoten stehen, werden als dessen Nachfahren bezeichnet. Knoten, die auf der gleichen Ebene der Hierarchie sind und einen gemeinsamen Vater haben, werden Geschwister genannt. Man kann also sagen, dass die Ebene der direkten Nachfahren eines Knotens dessen Kinder sind. Vater eines Knotens ist der Knoten, der nicht nur in der Hierarchie über ihm steht, sondern auch diesen Knoten als Kind besitzt. 1 Wir werden später den Begri Knotentyp für alle Knoten mit dem gleichen Namen verwenden. KAPITEL 3. 17 DOKUMENTENVERARBEITUNG Aus den Begrisdenitionen kann man die Hierarchie innerhalb eines XML Dokumentes wie folgt formulieren. Ein Knoten kann höchstens einen Vater aber beliebig viele Kinder besitzen. Somit kann es nur einen Knoten an der Spitze der Hierarchie geben, der mit seinen Nachfolgern das XML Dokument darstellt. Dieser Knoten wird Wurzelknoten genannt und besitzt keinen Vater und somit auch keine Vorfahren. Jeder Knoten, ausser der Wurzel selbst, ist Nachfahre des Wurzelknotens. Abbildung 3.1 soll den Zusammenhang zwischen Kindern, Nachfahren sowie Vater, Vorfahren und Geschwistern verdeutlichen. Abbildung 3.1: Beziehungen innerhalb der Hierarchie Um aber eine Hierarchie innerhalb einer linearen Textdatei darzustellen, muss eine Schachtelung der einzelnen Knoten erfolgen. So können durch die verschiedenen Ebenen der Schachtelung die verschiedenen Ebenen der Hierarchie dargestellt werden. Um diese Schachtelung zu realisieren muss jeder Knoten ein önendes Tag und ein schliessendes Tag besitzen. Zwischen önenden KAPITEL 3. 18 DOKUMENTENVERARBEITUNG und schliessenden Tags werden die Kinder des Knotens angegeben 2 . Da die Kinder eines Knotens selbst wieder Kinder besitzen können, kann durch diese rekursive Denition eine beliebige Hierarchie dargestellt werden. Ein schliessender Tag ist von der Form </name>. Hierbei gibt name den Namen des Knotens an, der schon beim önenden Tag benutzt wurde, wie in Listing 3.1 zu erkennen ist. Ein schliessender Tag eines Knotens kann keine Attribute besitzen. In Listing 3.1 wird eine lineare Darstellung eines XML Dokumentes angegeben. Um die Hierarchie besser erkennen zu können wird dieses Dokument in Abbildung 3.2 als Baum dargestellt. Als Pfad zu einem Knoten bezeichnet man den Weg durch den Baum von der Wurzel an bis zu diesem Knoten. Mit Hilfe des Pfades kann man also einen Knoten innerhalb eines XML Dokumentes eindeutig bestimmen. Der Pfad setzt sich aus den Namen der Knoten zusammen, die auf dem Weg dorthin besucht werden müssen. Die Namen der einzelnen Knoten werden durch / voneinander getrennt. Ein Pfad beginnt immer mit einem /. Da ein Knoten mehr als ein Kind mit demselben Namen besitzen kann, nummeriert man alle Geschwister mit demselben Name fortlaufend, angefangen bei 1 und von links nach rechts. Dies wird für alle Kinder aller Väter gemacht. Da die Wurzel keinen Vater besitzt und auch keine Geschwister hat, erhält sie die Nummer 1. Die Nummer wird in eckigen Klammern hinter dem Namen des entsprechenden Kindes angebracht. Der Pfad zum ersten r-Knoten im zweiten Paragraphen des Listings 3.1 wäre dann /w:body[1]/w:p[2]/w:r[1]. Hiermit haben wir den Pfad innerhalb einer XML-Datei gemäss dem xPathStandard [10] eingeführt. Ausserdem wollen wir den Begri des Teilpfades (Subpath) und des echten Teilpfades (real Subpath) einführen. Pfad A ist ein Teilpfad von B, genau dann wenn A der Pfad zu einem Vorfahren von B ist oder beide Pfade identisch sind. Pfad A ist ein echter Teilpfad von B, genau dann wenn A der Pfad zu einem Vorfahren von B ist und beide Pfade verschieden sind. 3.1.2 Beispiel Dokument Im folgenden Beispiel sehen wir eine XML Datei, die den Inhalt und auch die Struktur eines Microsoft Word Dokumentes angibt. 2 Wir wollen im Folgenden Knoten ohne Kinder xNodes nennen und Knoten mit Kindern xElements. KAPITEL 3. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 DOKUMENTENVERARBEITUNG <w : body > <w :p > <w :r > <w : rPr > <w : col val = '00 FF00 '> </w: rPr > <w :t > Erster Absatz eines Textdokumentes </w:t > </w:r > </w:p > <w :p > <w :r > <w : rPr > <w : col val =' FF0000 '> </i > </u > </b > </w: rPr > <w :t > Zweiter Absatz eines Textdokumentes </w:t > </w:r > </w:p > : : : <w :p > <w :r > <w :t > letzte Zeile eines Textdokumentes </w:t > </w:r > <w :p/> </w: body > Listing 3.1: Lineare Darstellung einer XML Datei In Abbildung 3.1 wurden folgende Tags verwendet. • <w:body> bildet den Wurzelknoten. • <w:p> stellt einen Paragraph dar. • <w:r> stellt den Inhalt eines Paragraphs dar. • <w:rPr> • <w:t> enthält die Formatierung als Kinder. beinhaltet Text. • <w:col> setzt eine Farbe. • <i> setzt Text kursiv • <u> setzt Text unterstrichen. • <b> setzt Text fett. 19 KAPITEL 3. DOKUMENTENVERARBEITUNG 20 Abbildung 3.2: Hierarchische Baumstruktur des Dokumentes Namespace Um sicher zu gehen, dass es bei Überschneidungen mit einem anderen Vokabular zu keinen Doppeldeutigkeiten kommt, wird ein so genannter Namespace oder Namensraum eingeführt. Dieser Namespace wird genutzt, um in einem Dokument mehrere XML Sprachen zu mischen. Ein Namespace wird durch eine URI angegeben. Unter der angegebenen URI sollte dann eine Dokumenttyp-Denition (DTD) oder ein XML-Schema stehen. Eine DTD ist ein Satz an Regeln, der benutzt wird, um die Grammatik eines Dokumentes zu denieren. Ein XML-Schema ist eine Empfehlung des W3C zum Denieren von Strukturen für XML-Dokumente. Zusätzlich zum Namespace existiert ein Präx-Mechanismus, der es erlaubt, Elemente durch eine Zeichenkette, die vom Elementnamen durch einen Doppelpunkt getrennt wird, in den jeweiligen Namespace zu setzen. In Listing 3.1 wird der Präx w benutzt, der wie beschrieben durch einen Doppelpunkt vom Namen des Knotens getrennt ist. Der Präx w wird für das Vokabular der Oce Open XML Sprache benutzt. Im Folgenden wird der Oce Open XML Standard genauer erläutert. KAPITEL 3. 3.2 21 DOKUMENTENVERARBEITUNG Dokumente in Word 2007 Mit der neusten Microsoft Word Version 2007 hat sich das Dateiformat der Word Dokumente grundlegend geändert. War das Dokumentenformat früher proprietär, so basiert das neue Word Dokumentenformat auf Dokumentenformat wird XML. Dieses Oce Open XML genannt. Die Umstellung verbes- sert die Interoperabilität enorm, da sich das Bearbeiten der Dokumente nun auf das Manipulieren von XML-Dateien reduziert. 3.2.1 Struktur eines Dokumentes Eine Datei mit der Endung .docx stellt nichts anderes als ein komprimiertes Archiv von XML Dateien dar. Das eigentliche Dokument besteht also aus drei Unterordnern, die jeweils mehrere XML-Dateien enthalten. Eine übergeordnete XML-Datei führt die einzelnen, in den Unterordnern liegenden, Dateien zu einem einzigen Word Dokument zusammen. Abbildung 3.3 zeigt den Inhalt des Archivs. Abbildung 3.3: Inhalt der .docx Datei Das Dokument wird in Partknoten unterteilt. [Content_Types].xml fügt letztendlich die Dateien im Archiv zum eigentlichen Word Dokument zusammen. Jeder Partknoten stellt somit eine eigene XML-Datei innerhalb des Archivs dar, die zusammen das komplette Word Dokument ergeben. Jeder Partknoten ist von der Form but name <part name=`` type=''/>, wobei das Attri- den relativen Pfad zur referenzierten Datei innerhalb des Archives beinhaltet. In Abbildung 3.4 sehen wir die komplette XML-Darstellung eines Word Dokumentes. Im Rahmen dieser Arbeit sind jedoch nur zwei Partknoten relevant. Zum einen document.xml, der den Body, also den Inhalt eines Dokumentes dar- stellt und zum anderen comments.xml, da dieser Knoten die vom Plugin erzeugten Kommentare beinhalten wird. Alle weiteren Parts des Dokumentes enthalten Randinformationen wie etwa den Name des Autors oder Themes des Dokumentes. Da diese weiteren Partknoten nur Randinformationen enthalten, haben sie keine Bedeutung für das Plugin und wurden nur der KAPITEL 3. DOKUMENTENVERARBEITUNG 22 Abbildung 3.4: Inhalt der Datei [Content_Types].xml Vollständigkeit wegen in Abbildung 3.4 aufgeführt. Der Partknoten, der die Datei ten <document>. document.xml einbindet, beinhaltet den Kno- Dieser Knoten enthält den tatsächlichen Dokumentkörper. Hier wird nicht nur der Inhalt, sondern auch die Formatierung des Textes abgespeichert, wie wir im Folgenden sehen werden. 3.2.2 Repräsentation von Text und Formatierung Ein Text wird im .docx Format als ein XML-Knoten realisiert, der den von ihm darzustellenden Text enthält. Dies haben wir bereits im Beispiel Dokument zum Aufbau einer XML Datei gesehen. Ein Textknoten gehört jeweils zu einem Paragraphen, der einen übergeordneten Knoten darstellt. Um zu verstehen, wie Formatierungen angebracht werden, muss gesagt werden, dass der Paragraphknoten, der einen Absatz darstellt, nicht der direkte Vaterknoten eines Textknotens ist. Zwischen Text und Paragraph bendet sich ein r-Knoten, dessen erstes Kind die Formatierung des Textes angibt und dessen zweites Kind der Text selbst ist. Ein rPr-Knoten beinhaltet diese Formatierung. Ein r-Knoten muss nicht zwei Kinder besitzen, da es sein kann, dass ein Text keine besondere Formatierung besitzt. Sollte dies der Fall sein, ist der Textknoten das einzige Kind des r-Knotens und als Formatierung wird eine globale Formatierung benutzt, die nicht als Formatierung jedes einzelnen Textknotens abgespeichert wird, sondern einmal für das gesamte Dokument zu Beginn deniert wurde. KAPITEL 3. 23 DOKUMENTENVERARBEITUNG Abbildung 3.5 zeigt die Struktur einer lokalen Formatierung innerhalb eines Paragraphen, Abbildung 3.6 zeigt den Inhalt dieser Formatierung im Detail. Abbildung 3.5: Paragraph mit Text und Formatierung Als Formatierung kann jedes beliebige Tag, das eine Formatierung angibt, wie etwa bold, italic, color etc. an den rPr-Knoten angebracht werden. Abbildung 3.6 zeigt die Beispielformatierung mit fett, kursiv und unterstrichen. Ein Dokument kann aus beliebig vielen Paragraphen bestehen, die letztendlich den Text des Dokumentes mit Formatierung enthalten. Diese Paragraphknoten sind Kinder des Bodyknotens, der die Wurzel des Dokumentes darstellt. Abbildung 3.6: Lokale Formatierung eines Textknotens Ein besonderes Element in diesem Baum ist das <m:oMath> Element, das benutzt wird, um Formeln in Word 2007 darzustellen. Auch diese oMath Elemente werden als Kinder an einen Paragraphen angehängt um in eben diesem Paragraph eine Formel oder ein mathematisches Element darzustellen. Wie dies geschieht wollen wir im Folgenden genauer betrachten. KAPITEL 3. DOKUMENTENVERARBEITUNG 24 3.2.3 Oce MathML (oMath) Um Innerhalb des Oce Open XML Formats mathematische Formeln darstellen zu können, wird das Vokabular des Dokumentes um das Vokabular der Oce MathML(oMath) [6] Sprache erweitert. Die zur oMath-Sprache gehörenden Knoten wollen wir im Folgenden oMath Elemente nennen. Wie wir schon zu Beginn des Kapitels gesehen haben, kommt es zu Überschneidungen des oMath- und des Oce Open XML Vokabulars. Um Konikte zu vermeiden, wird ein neuer Namespace eingeführt. Der Präx des oMath Vokabulars wird mit m bezeichnet. Ein Beispiel für solch eine Überschneidung ist etwa ein Text, der keine mathematischen Zeichen enthält, aber dennoch in einer oMath Umgebung geschrieben wurde. Die Textknoten einer <m:t> bezeichnet, die eines Textes ausserhalb <w:t>. oMath Umgebung werden mit einer oMath Umgebung mit Eine oMath Umgebung kann als Kind eines Paragraphen angebracht werden oder selbst einen Paragraphen denieren. Eine oMath Umgebung, die selbst <oMathPara> deniert werden. Dieser Knoden Paragraphknoten <w:p>. Jede oMath Umgebung wird <m:oMath> eingeleitet. Paragraphen deniert, muss mit ten ersetzt dann mit dem Knoten Aufgrund des grossen oMath Vokabulars kann hier keine vollständige Liste angegeben werden. Zwei Beispiele sollen jedoch die Struktur von oMath beschreiben. Das erste Beispiel zeigt den Body eines Dokumentes, das nur einen Paragraphen besitzt, der ausschliesslich oMath Elemente enthält. Daher wird der Paragraph nicht als <w:p> angegeben, sondern als <m:oMathPara>. Als In3 eingetragen. 4 halt dieses Paragraphens ist der Bruch 1 <w : body > 2 <m : oMathPara > 3 <m : oMath > 4 <m :f > 5 <m : num > 6 <m :r > 7 <m :t >3 </ m:t > 8 </m:r > 9 </m: num > 10 <m : den > 11 <m :r > 12 <m :t >4 </ m:t > 13 </m:r > 14 </m: den > 15 </m:f > KAPITEL 3. DOKUMENTENVERARBEITUNG 25 16 </m: oMath > 17 </m: oMathPara > 18 </w: body > Listing 3.2: Dokument mit Bruch Das zweite Beispiel enthält oMath Elemente und Oce Open XML Elemente, die zusammen in einem einzigen Paragraphen stehen. Die oMath Umgebung enthält den Text a+b=c, wobei a+b rot eingefärbt ist. Nach der oMath Umgebung folgt der Textknoten in Oce Open XML. 1 <w : body > 2 <w :p > 3 <m : oMath > 4 <m :r > 5 <w : rPr > 6 </m: col val =' FF0000 '> 7 </w: rPr > 8 <m :t >a+b </ m:t > 9 </m:r > 10 <m :r > 11 <m :t >= b </ m:t > 12 </m:r > 13 </m: oMath > 14 <w :r > 15 <w :t > Ein kurzer Text </ w:t > 16 </w:r > 17 </w:p > 18 </w: body > Listing 3.3: Dokument mit Text und Formel 3.3 Bereinigung eines Dokumentes In der Einleitung des Kapitels Architektur wurde anhand eines Beispiels die Funktionsweise des Plugins erläutert, wobei das Bereinigen des Dokumentes vor dem Upload zum Server erfolgt. Das Bereinigen stellt eine Funktion dar, die das Dokument zum Upload vorbereitet. Dies bedeutet, dass das Bereinigen es ermöglicht, eine Teilmenge des Dokumentenmodells über eine Kongurationsdatei zu denieren, um das Dokument von irrelevanten Objekten zu befreien. Denition irrelevante Objekte Als irrelevante Objekte werden Knoten betrachtet, die vom Server nicht zur Bereitstellung von Dokumentendiensten benötigt werden. KAPITEL 3. DOKUMENTENVERARBEITUNG 26 Knoten, die Formatierungen wie etwa Färbung enthalten, sind eben solche irrelevanten Objekte. Ein wichtiges Problem stellt sich dennoch. Da die Formatierungen später wieder im temporären Dokument erhalten sein sollen, darf sich die Struktur des Dokuments durch das Bereinigen nicht ändern. Das temporäre Dokument wird mit Hilfe einer Sicherungskopie des aktuellen Dokumentes erstellt und beinhaltet so wieder die benutzerspezischen Formatierungen, zu denen dann die Annotationen hinzugefügt werden. Da diese aber im hochgeladenen, bereinigten Dokument entfernt wurden, würde eine Änderung der Baumstruktur durch das Bereinigen zu einer Annotation führen, die im besten Falle an der falschen Position steht und im ungünstigsten Falle einen Knoten annotiert, der so gar nicht existiert. Daher wird folgende Forderung an das Bereinigen gestellt. Forderung an das Bereinigen Durch das Entfernen irrelevanter Objekte darf die Struktur des Dokumentes nicht verletzt werden. Um zu erläutern, wieso das Entfernen von Formatierung nicht die Struktur verletzen kann, muss man zunächst einmal wissen, wie solche Formatierungsinformationen repräsentiert werden. Abbildung 3.7 zeigt ein Dokument, das zwei Zeilen besitzt. In der ersten Zeile wurde der Text ab einem bestimmten Buchstaben bis zum Ende der Zeile gefärbt. Die zweite Zeile ist ohne jegliche Formatierung. Abbildung 3.8 zeigt das gleiche Dokument ohne die Formatierung. Wie in Abbildung 3.8 zu erkennen ist, führt das Entfernen von Formatierungen zu einem Dokument, bei dem die Pfade vom Body-Knoten zu den Textknoten erhalten bleiben. In unserem Beispiel ist der Pfad zum zweiten Textknoten vor dem Bereinigen /w:body[1]/w:p[1]/w:r[1]/w:t[1]. Dieser Pfad ist nach dem Bereinigen immer noch gültig und führt zum gleichen Knoten. Das diese Pfade erhalten bleiben und immer noch auf den gleichen Knoten referenzieren, hat im wesentlichen drei Gründe. 1. Ein Teilbaum, der einen rPr-Knoten als Wurzel besitzt, enthält nur irrelevante Objekte. Somit führt das Löschen dieses Teilbaums nicht zum Verlust von für die Serverdienste benötigter Objekte innerhalb des XML-Dokumentes. 2. Ein Teilbaum mit irrelevanten Objekten enthält keine relevanten Ob- KAPITEL 3. DOKUMENTENVERARBEITUNG 27 Abbildung 3.7: Dokument mit Formatierung Abbildung 3.8: Dokument ohne Formatierung jekte. Konkret ist die Formatierungsinformation ein Geschwisterknoten eines Textknotens und nicht dessen Vaterknoten. Daher bleibt der Pfad zu einem Textknoten beim Entfernen dieses Knotens erhalten. KAPITEL 3. DOKUMENTENVERARBEITUNG 28 3. Wenn ein Knoten erhalten bleibt, dann auch alle gleichnamigen Geschwisterknoten. Da die Pfade relative Pfade zum Vaterknoten sind, bleibt durch den Erhalt der gleichnamigen Geschwister der relative Pfad aller relevanten Objekte erhalten. Da nun klar ist, dass die Forderung an das Bereinigen nicht verletzt wird, kann der Algorithmus des Bereinigens nun wie folgt realisiert werden. Algorithmus Bereinigen Das Bereinigen wird in einem Algorithmus beschrieben, der den Body-Knoten des Dokumentes als Parameter erhält. Um zu entscheiden, welche Kinder des Body-Knotens erhalten bleiben sollen, wird eine Sammlung von Knotentypen aus der Kongurationsdatei geladen. Anhand dieser Knoten entscheidet der Algorithmus ob ein gegebener Knoten im Dokument bleibt oder nicht. Ein Knoten soll genau dann im Dokument verweilen, wenn dieser Knotentyp auch in der Knotensammlung vorhanden ist. Die Sammlung von zu erhaltenden Knotentypen kann über die Kongurationsdatei erweitert werden. Somit ist eine einfache Erweiterbarkeit des Plugins gewährleistet. Die Bereinigungsprozedur erzeugt also einen Body-Knoten, der keine Formatierungsinformationen im Sinne von Färbungen oder Ähnlichem enthält. Die Struktur bleibt jedoch bestehen, sodass Absätze oder Einrückungen erhalten bleiben. Dieser Umstand beruht auf der Tatsache, dass Formatierungen, wie etwa ein Absatz, durch die Struktur des Dokumentes entstehen und nicht durch zusätzliche Informationen innerhalb der Knoten eines Baumes repräsentiert werden. node = Wurzel des Teilbaums, der bereinigt werden soll 1 Method bereinige ( node ) 2 If | children ( node )| > 0 { 3 For each child in children ( node ) do 4 If name ( child ) ∈ bereinigenmarkup ( config ) { 5 bereinige ( child ); 6 } else { 7 delete ( child ); 8 }; 9 Next ; 10 }; 11 End Method Listing 3.4: Entfernt nicht relevante Knoten KAPITEL 3. 3.4 DOKUMENTENVERARBEITUNG 29 Annotation eines Dokumentes Im Fallbeispiel in Kapitel 2.1 wurde das Dokument nach dem Bereinigen an den Server verschickt. Im weiteren Verlauf werden Annotationen zum Mediator Plugin zurückgeliefert, die in das aktive Dokument eingefügt werden sollen. Die Annotationen dienen zur Visualisierung von semantischen Statusinformationen und Fehlermeldungen zu Dokumentteilen. Das aktive Dokument stellt zusammen mit den eingefügten Annotationen das temporäre Dokument dar. Denition Annotation: Eine Annotation besitzt folgende Parameter • Anfangspfad: Ein xPath, der den Beginn der Annotation im Dokument angibt. • Endpfad: Ein xPath, der das Ende der Annotation im Dokument angibt. • Annotationstyp: Stellt einen in der Kongurationsdatei vordenierten Typ dar, der die Färbung der Annotation angibt. • Beschreibung: Ein String, der eine anzuzeigende Information beinhaltet. Wir wollen nun zunächst den Begri des Annotationspfades und der Abdeckung einführen. Hierbei wollen wir Anfangs- und Endpfad einer Annotation als Annotationspfade dieser Annotation bezeichnen. Denition gültige Annotationspfade: • Die von Anfangs- und Endpfad referenzierten Knoten müssen im Dokument existieren. Diese Knoten wollen wir Anfangs- und Endknoten nennen. • Der Endknoten darf kein Nachfahre des Anfangsknoten sein und umgekehrt. Anfangs- und Endknoten dürfen jedoch identisch sein, solange es nicht der Body-Knoten ist. KAPITEL 3. • DOKUMENTENVERARBEITUNG 30 Die durch den Anfangs- und Endpfad angegebene Abdeckung der Annotation darf nicht leer sein. Denition Abdeckung: Wenn wir jedes Zeichen eines Textknotens als dessen Kind-Knoten betrachten, so können wir die Abdeckung einer Annotation wie folgt denieren. Die Abdeckung einer Annotation ist eine Menge von Knoten des aktiven Dokumentes. Die Berechnung dieser Menge wird durch folgenden Algorithmus beschrieben. Der Aufruf der Funktion getAbdeckung erfolgt mit dem BodyKnoten als node, der Annotation, für die die Abdeckung berechnet werden soll, als anno und mit mode=false. Die Funktion A is SubPath of B prüft, ob A der Pfad eines Vorfahren von B ist. node = Betrachteter Teilbaum annno = Annotation deren Abdekcung gesucht wird mode = Gibt an, ob Anfangspfad bereits gefunden wurde 1 Function getAbdeckung ( node , anno , mode ) 2 abdeckung = {}; 3 For each child in children ( node ) do { 4 aktuPath = pfad ( node ); 5 If mode { 6 If aktuPath = endpfad ( anno ) { 7 abdeckung = abdeckung ∪ { child }; 8 abdeckung = abdeckung ∪ descendants ( child ); 9 Return abdeckung ; 10 } else { 11 If aktuPath is SubPath of endpfad ( anno ) { 12 abdeckung = abdeckung ∪ getAbdeckung ( child , anno , true ); 13 Return abdeckung ; 14 } else { 15 abdeckung = abdeckung ∪ { child }; 16 abdeckung = abdeckung ∪ descendants ( child ); 17 }; 18 }; 19 } else { 20 If aktuPath = anfangspfad ( anno ) { 21 abdeckung = abdeckung ∪ { child }; 22 abdeckung = abdeckung ∪ descendants ( child ); 23 mode = true ; 24 } else { 25 If aktuPath is SubPath of anfangspfad ( anno ) { 26 abdeckung = abdeckung ∪ getAbdeckung ( child , anno , false ); 27 }; 28 }; 29 }; 30 Next ; 31 Return abdeckung ; 32 End Function Listing 3.5: Abdeckung einer Annotation 3 Da wir nun wissen wann einzelne Annotationen 3 Annotationspfade, korrekt sind, wollen wir im die auf ein Zeichen innerhalb eines Textknotens verweisen besitzen KAPITEL 3. 31 DOKUMENTENVERARBEITUNG Folgenden betrachten, wann eine Menge von Annotationen korrekt ist. Denition Menge von Annotationen: • Anfangs- und Endpfad jeder Annotation müssen gültige Annotationspfade sein. • Die Abdeckungen der einzelnen Annotationen müssen paarweise disjunkt sein. Verschiedene Annotationsarten werden durch verschiedene Farben dargestellt. Diese Farbcodes werden aus der Kongurationsdatei geladen und können, ebenso wie die Knotentypen, somit leicht erweitert oder verändert werden. Es werden die Knoten, die in der Abdeckung der entsprechenden Annotation liegen, annotiert. 3.4.1 Annotationspfade Ein Pfad zu einer Annotation ist nicht zwingend fest vorgeschrieben. Ein Knoten kann auf verschiedenen Pfaden annotiert werden. Zwar ist der Pfad des Knotens innerhalb des Dokumentes eindeutig, doch gibt es mehrere Möglichkeiten Annotation so einzufügen, dass in allen Fällen das gleiche Ergebnis vorliegt. Dies ist nicht wirklich ein Problem, doch muss der Annotationsalgorithmus so konzipiert sein, dass er - egal wie der Annotationspfad vorliegt - auch das gewünschte Ergebnis erzeugt. Abbildung 3.9 zeigt einen Paragraphen, der nur einen Textknoten beinhaltet. Anhand dieses Beispiels, soll der Sachverhalt der verschiedenen Annotationspfade im Folgenden erläutert werden. Die Abbildung 3.9 beinhaltet nur einen Absatz, in dem der Text Ein Beispiel steht. Nehmen wir an, die vom Server zurückgelieferte Annotationsliste beinhaltet nur eine Annotation. In dieser Annotation soll der gesamte Text rot gefärbt werden. Der Anfangs- und Endpfad könnte nun auf vier verschiedene Arten angegeben werden: den Sux .../w:t[m]/text[1]/char[n]. Hierbei geben /text[1] und char[n] keinen Knoten innerhalb des Dokumentes an, sondern verweisen auf eine Zeichenkette und die Position eines Zeichens innerhalb dieser Zeichenkette. Dies stellt eine kanonische Erweiterung des xPath-Standards dar. KAPITEL 3. DOKUMENTENVERARBEITUNG 32 Abbildung 3.9: Dokument mit einem Paragaphen 1. Anfangspfad: /w:body[1]/w:p[1]/w:r[1]/text[1]/char[1] Endpfad: /w:body[1]/w:p[1]/w:r[1]/text[1]/char[12] 2. Anfangspfad: /w:body[1]/w:p[1]/w:r[1]/text[1]/ Endpfad: /w:body[1]/w:p[1]/w:r[1]/text[1]/ 3. Anfangspfad: /w:body[1]/w:p[1]/w:r[1]/ Endpfad: /w:body[1]/w:p[1]/w:r[1]/ 4. Anfangspfad: /w:body[1]/w:p[1]/ Endpfad: /w:body[1]/w:p[1]/ Alle vier verschiedenen Annotationspfade würden das gleiche Resultat liefern, da sie die gleiche Annotation angeben. Man sieht also leicht, dass zwar jeder Knoten eindeutig über seinen Pfad bestimmt werden kann, doch Annotationen auf verschiedene Weise angegeben werden können. Eine erwünschte Eigenschaft der Annotation ist, dass sich keine Annotationen überlappen, es kann also kein Knoten des Dokumentes von zwei verschiedenen Annotationen formatiert werden. Dies macht auch keinen Sinn, da z.B. ein Textabschnitt nicht gleichzeitig richtig und falsch sein kann und jede folgende Annotation auf demselben Knoten wieder die vorherige aufheben würde. KAPITEL 3. DOKUMENTENVERARBEITUNG 33 Aber auch aus Sicht der Struktur des Dokumentes würde es zu Problemen kommen. Diese Problematik basiert auf der Tatsache, dass ein von der Annotation veränderter Textknoten nicht mehr den gleichen Pfad im Dokument besitzen muss. Ein Textknoten dessen Inhalt nur teilweise annotiert wird, muss zwangsläug in mindestens zwei neue Textknoten aufgesplittet werden. Wenn nun genau dieser Textknoten zum zweiten Mal annotiert werden soll, existiert dieser gar nicht mehr als ein Knoten, sondern wurde in mehrere Knoten aufgeteilt. 3.4.2 Technik des Annotierens Abbildung 3.10: Einfügen einer Annotation Da wir nun eine Vorstellung von Annotationen haben, wollen wir zunächst anhand eines Beispiels das Annotieren eines Dokumentes verdeutlichen. Mit Hilfe dieses Beispiels werden wir sehen, dass der Prozess des Annotierens selbst wieder in drei Teile unterteilt werden kann. In Abbildung 3.10 ist gut zu erkennen, dass sich die Pfade durch das Einfügen einer Annotation ändern. Der Pfad zum Textknoten, der das Ausrufezeichen beinhaltet, war vor dem Einfügen der Annotation noch w:r[2]/w:t[1]. Doch durch das Aufsplitten des ersten Kno- /w:body[1]/w:p[1]/ tens hat sich der Pfad für alle weiteren Knoten desselben Typs geändert. Dies hat aber nur Auswirkungen auf die r-Knoten, die denselben Vaterknoten besitzen. So werden r-Knoten, die in einem anderen Paragraph stehen davon KAPITEL 3. DOKUMENTENVERARBEITUNG 34 nicht in Mitleidenschaft gezogen. Auch r-Knoten, die vor der Annotation stehen, behalten ihren Pfad. Nach dem Einfügen der Annotation für den ersten Knoten, ist der neue Pfad des Textknotens, der das Ausrufezeichen enthält, w:r[4]/w:t[1]. /w:body[1]/w:p[1]/ Der Algorithmus muss also nicht nur Annotationen in das Dokument einfügen können, sondern auch Annotationspfade anpassen und Textknoten in mehrere Knoten aufsplitten. Somit kann man den Algorithmus in drei Teile aufteilen. 1. Anpassen des Dokumentes und der Annotationspfade: Textknoten werden nach Bedarf in mehrere Textknoten aufgeteilt und die entsprechenden Annotationspfade der Annotationen werden angepasst. 2. Normalisieren der Annotationsliste: Annotationspfade in der Annotationsliste werden nach beendetem Anpassen so normalisiert, dass sie auf einen r-Knoten zeigen. 3. Einfügen der Annotation in das Dokument: Annotationen und Kommentare werden in das Dokument eingefügt. 3.4.3 Anpassen eines Dokumentes und der Annotationspfade Nachdem das Generieren der Annotationen anhand des bereinigten Dokumentes abgeschlossen und diese an das Plugin übermittelt wurden, erfolgt der erste Schritt des Einfügens der Annotationen. Nur das Einfügen der Annotation alleine reicht nicht aus, da wir z.B. nur Teile eines Textes annotieren wollen und somit die Struktur des Dokumentes verändern müssen. Das Annotieren bestimmter Teile eines Textknotens erreichen wir, indem wir Textknoten aufbrechen und sie in mehrere einzelne Knoten aufteilen, die nun verschiedene Formatierungen erhalten. Ebenfalls müssen bestimmte Annotationspfade durch das Splitten von Textknoten angepasst werden, da sonst fehlerhafte Annotationen im Dokument entstehen würden. Bevor nun eine genaue Arbeitsweise eines solchen Algorithmus erörtert werden kann, muss zunächst genauer auf die Idee des Aufsplittens und Anpassens eingegangen werden. Aufbrechen von Textknoten (Split Algorithmus) Das Aufbrechen von Textknoten übernimmt der Split-Algorithmus. Ein Indikator für das Aufsplitten einzelner Textknoten ist das Enden eines Anno- KAPITEL 3. DOKUMENTENVERARBEITUNG 35 tationspfades auf einen bestimmten Buchstaben (.../text[1]/char[n]), da eine Annotation, die nicht auf einem Buchstaben endet, keinen Textknoten verändern kann. Ein Pfad, der auf eine Buchstabenposition endet, addressiert ein Zeichen innerhalb eines Textknotens. Das Aufsplitten eines Textknotens kann in terteilt werden. • drei verschiedene Fälle un- Ein Textknoten mit Pfad p muss gar nicht gesplittet werden, wenn er einen Text der Länge n enthält und die einzufügende Annotation den Anfangspfad p/text[1]/char[1] und den Endpfad p/text[1]/char[n] besitzt. In diesem Fall muss der gesamte Textknoten annotiert und gar nicht aufgeteilt werden. Abbildung 3.11 zeigt diesen Fall. Abbildung 3.11: Knoten muss nicht gesplittet werden • Ein weiterer Fall ist eine Annotation, die einen Knoten in genau zwei neue Knoten aufsplittet. Dies ist genau dann der Fall, wenn eine Annotation vom ersten Zeichen eines Textknotens beginnt, aber noch vor Ende des Strings endet, oder wenn eine Annotation nach dem ersten Zeichen eines Textknotens beginnt und bis zum letzten Zeichen eines Textknotens reicht. Somit müssen aus einem Textknoten zwei erstellt werden. Abbildung 3.12 zeigt einen solchen Split. • Der dritte Fall splittet den Textknoten in drei neue Textknoten auf. Dies muss getan werden, wenn nur ein Teil des Strings innerhalb eines Textknotens annotiert wird und der Anfang und das Ende des Strings nicht in die Annotation einiessen sollen. Abbildung 3.13 zeigt einen solchen Split. KAPITEL 3. DOKUMENTENVERARBEITUNG 36 Abbildung 3.12: Knoten wird nach dem ersten Zeichen bis Ende gesplittet Abbildung 3.13: Knoten wird nach dem ersten Zeichen bis vor Ende gesplittet Algorithmus Split aktunode = Knoten, der durch aktuanno Annotiert werden soll aktuanno = Annotation, die den Split ausgelöst hat mode = Gibt an, ob Anfangs- oder Endpfad den Split angibt. 1 Function Split ( aktunode , aktuanno , mode ) 2 If mode { 3 firsttext = New Textnode ; 4 text ( firsttext ) = text ( aktunode )[1 bis ( char ( anfangspfad ( aktuanno )) -1)]; 5 secondtext = New Textnode ; 6 text ( secondtext ) = text ( aktunode )[ char ( anfangspfad ( aktuanno )) 7 bis length ( text ( aktunode ))]; 8 } else { 9 firsttext = New Textnode ; 10 text ( firsttext ) = text ( aktunode )[1 bis char ( endpfad ( aktuanno ))]; 11 secondtext = New Textnode ; 12 text ( secondtext ) = text ( aktunode )[( char ( anfangspfad ( aktuanno )) +1) 13 bis length ( text ( aktunode ))]; 14 }; 15 mode = not mode ; 16 ersetze aktunode durch secondtext ; 17 fuege firsttext vor secondtext ein ; 18 Return length ( firsttext ); 19 End Function Listing 3.6: Splittet Textknoten KAPITEL 3. 37 DOKUMENTENVERARBEITUNG Anpassen der Annotationspfade Nach dem Aufsplitten der verschiedenen Textknoten müssen die Annotationspfade angepasst werden. Die Forderung an den Algorithmus ist, dass alle Annotationspfade, die auf denselben Knotentyp desselben Vaterknotens enden und in der Baumstruktur rechts gesehen vom aufgesplitteten Knoten liegen, angepasst werden müssen. Diese Änderungen beziehen sich im Wesentlichen auf r-Knoten und char-Knoten, wie wir später bei der Erzeugung der Annotationsknoten noch sehen werden. Der Algorithmus muss also jeden Annotationspfad so anpassen, dass die entsprechenden Annotationspfade innerhalb der Annotationsliste nach dem Splitten eines Textknotens um den entsprechenden Wert inkrementiert werden. Da das Splitten eines Knotens in drei Knoten nicht in einem Schritt passieren wird, muss nach dem ersten Split auch das Oset, das durch das Verkürzen des Strings im Textknoten entstanden ist, im Endpfad der Annotation eingerechnet werden, die das Splitten des besagten Textknotens ausgelöst hat. Somit lässt sich hier schon erkennen, dass es zwei Fälle geben wird, je nachdem ob beim Splitten der betroene Textknoten durch den Anfangsoder Endpfad einer Annotation geteilt worden ist. Ein Textknoten muss aber nicht immer in drei Teile gesplittet werden. Das Aufbrechen könnte einen Text liefern, der keinen Inhalt besitzt, so wird dieser nicht angehängt bzw. erst gar nicht gebildet. Da ein Text der Länge 0 kein Oset besitzt und keinen r-Knoten erzeugt, kann mit der alten Annotation weiter gearbeitet werden. Lediglich der Modus wird gewechselt. Sollte nun auch beim zweiten Aunden der Text nicht gesplittet werden müssen, wird nur der Annotationspfad auf den entsprechenden r-Knoten gesetzt. Das Oset ist hierbei die Länge des abgetrennten Textknotens, d.h. die Anzahl seiner Zeichen. Das Anpassen der Pfade wird von dem Algorithmus Fix realisiert, der durch folgenden Algorithmus beschrieben werden kann. Algorithmus Fix focusanno = Anno die den Split verursacht hat annolist = Liste der Annotationen offset = Das durch den Split entstandene Oset mode = Gibt an, ob Anfangs- oder Endpfad den Split verursacht hat KAPITEL 3. DOKUMENTENVERARBEITUNG 38 1 Method Fix ( focusanno , annolist , offset , mode ) 2 If mode { 3 splitpath = anfangspfad ( focusanno ) = p/r [i ]/ t [1]/ text [1]/ char [ k] 4 } else { 5 splitpath = endpfad ( focusanno ) = p/ r[i ]/ t [1]/ text [1]/ char [k] 6 }; 7 For each anno in annolist do 8 If anfangspfad ( anno ) = p/r [l ]/... with l > i { 9 anfangspfad ( anno ) = p/r[l +1]/... 10 }; 11 If endpfad ( anno ) = p/ r[l ]/... with l >i { 12 endpfad ( anno ) = p /r[l +1]/... 13 }; 14 If anfangspfad ( anno ) = p/r [i ]/ t [1]/ text [1]/ char [ m ]... with m >k { 15 anfangspfad ( anno ) = p/r[i +1]/ t [1]/ text [1]/ char [m - offset ] 16 }; 17 If endpfad ( anno ) = p/ r[i ]/ t [1]/ text [1]/ char [m ]... with m > k { 18 endpfad ( anno ) = p /r[i +1]/ t [1]/ text [1]/ char [m - offset ] 19 }; 20 Next ; 21 End Method Zusammenspiel der Algorithmen Den Algorithmus, der das Anpassen der Annotationen und das Aufsplitten der Textknoten implementiert, wollen wir im Folgenden nun FixAndSplit nennen. Das Abarbeiten aller Elemente auf einer Ebene der Baumstruktur stellt die Grundidee des Algorithmus FixAndSplit dar. Den Anfang stellt hier nun der Body-Knoten, der die Wurzel des Dokuments bildet. Das Abarbeiten der Kinder wird durch einen rekursiven Aufruf der FixAndSplit Funktion realisiert, da jedes Kind wieder einen Teilbaum darstellt. Es gibt zwei Modi. Im Begin-Modus wird nach dem Anfang einer Annotation gesucht. Im End-Modus wird nach dem Ende einer Annotation gesucht. Die Funktion prüft für jedes Kind des Knotens, der beim Funktionsaufruf mitgegeben wurde, ob das Kind ein Teilpfad eines Annotationspfades ist. Im Folgenden wollen wir zwischen den. zwei Arten von Annotationen unterschei- KAPITEL 3. DOKUMENTENVERARBEITUNG 39 Typ Char: Annotationen, deren Anfangs- oder Endpfad einen /char[n] Sux besitzt. Diese Annotationen brechen potenziell Textknoten auf. Typ NotChar: Annotationen, deren Anfangs- und Endpfad keinen /char[n] Sux besitzt. Hier ist kein Handlungsbedarf. Für den Fall, dass eine Annotation keinen Textknoten aufsplittet, muss der Algorithmus FixAndSplit nicht aktiv werden. Für Annotationen des Typs Char wird eventuell ein Split ausgeführt. Zunächst wollen wir uns aber die Fälle betrachten, die der Algorithmus FixAndSplit unterscheiden muss: Fall 1 Pfad des aktuellen Knotens ist ein Vaterpfad eines Annotationspfades: FixAndSplit wird mit entsprechendem Kind als Wurzel-Knoten aufgerufen. Fall 2 Pfad des aktuellen Knotens ist kein Vaterpfad eines Annotationspfades: Knoten wird ausser Acht gelassen, denn wenn der aktuelle Knoten kein Teilpfad einer Annotation ist, dann auch dessen Kinder nicht. Fall 3 Pfad des aktuellen Knotens ist genau der gesuchte Pfad: ggf. Aufbrechen des Knotens und Anpassen der Annotationspfade. Der dritte Fall unterscheidet sich sehr von den ersten beiden Fällen, da sich der Algorithmus in den ersten beiden Fällen auf der Suche nach einem Knoten bendet, der annotiert werden soll. Im dritten Fall wurde eine Annotation zum aktuellen Knoten gefunden. Je nach Modus, in dem sich der Algorithmus bendet, wird ein Anfangs- oder Endpfad gesucht. Sollte die Annotation vom Typ NotChar sein, so ist nicht zu tun. Ist die Annotation, deren Pfad auf den aktuellen Knoten passt, aber vom Typ Char, so muss der Knoten eventuell nun aufgebrochen und die Annotationspfade angepasst werden. Auch der Modus wird nun gewechselt. Bendet sich der Algorithmus durch den Wechsel nun im End-Modus, so ist jetzt der Endpfad der Annotation ausschlaggebend. Der Endpfad der Annotation kann einen zweiten Split angeben, der KAPITEL 3. DOKUMENTENVERARBEITUNG 40 natürlich durch den entstandenen Oset des ersten Splittens angepasst wurde. Der End-Modus arbeitet analog zum Begin-Modus. Das Aufbrechen und Anhängen der Knoten geschieht derart, dass der erste Teil des Knotens, der laut Annotation nicht annotiert werden sollte, sich nun auf der Position im Baum bendet, an der auch der frühere Textknoten war. Der hintere Teil des Textes, der ganz oder nur teilweise annotiert werden soll, ist nun direkt rechts daneben positioniert. Da die Annotation so angepasst wurde, dass sie auf den neuen Knoten zeigt, wird dieser im nächsten Durchlauf wieder gesplittet, falls die Annotation dies angibt. Der Annotationspfad gibt immer genau an, an welcher Position der Text in zwei Teile geteilt werden soll. So kann ein Text durchaus in 3 Teile gesplittet werden. Algorithmus FixAndSplit aktunode = Knoten der durch aktuanno Annotiert werden soll annolist = Liste von Annotationen, die eingefügt werden sollen mode = Mode in dem sich der Algorithmus bendet 1 Method FixAndSplit ( aktunode , annolist , mode ) 2 For each child in children ( aktunode ) do 3 aktupath = path ( aktunode ); 4 If mode { 5 aktuannos = { x ∈ annolist | anfangspfad (x) is SubPath of aktupath } 6 } else { 7 aktuannos = { x ∈ annolist | endpfad ( x) is SubPath of aktupath } 8 }; 9 sort ( aktuannos ); 10 If | aktuannos | > 0 { 11 For each anno in aktuannos do 12 If name ( aktunode ) == "r" and has - char - suffix ( anno ) { 13 If mode { 14 offset = split ( child , anno , mode ); 15 Fix ( anno , annolist , offset , mode ); 16 mode = false ; 17 } else { 18 offset = split ( child , anno , mode ); 19 Fix ( anno , annolist , offset , mode ); 20 mode = true ; 21 }; 22 }; 23 Next ; 24 } else { 25 FixAndSplit ( child , annolist , mode ); 26 }; 27 Next ; 28 End Method Listing 3.7: Splittet Knoten und passt Annotationspfade an KAPITEL 3. DOKUMENTENVERARBEITUNG 41 Die Annotationen werden gemäss der Reihenfolge des Auftretens ihres vom Anfangspfad referenzierten Knotens bei der Tiefensuche geordnet. Zusammenfassend kann man also sagen, dass der erste Schritt des Annotierens die Dokumentstruktur und die Annotationen so vorbereitet, dass ein einfaches Einfügen der Annotationen ermöglicht wird. Diskussion Beispiel zu Fall 1: Abbildung 3.14: Knoten muss nicht gesplittet werden Annotation vor dem ersten Split: Anfangspfad=/w:body[1]/w:p[1]/w:r[1]/w:t[1]/text[1]/char[1] Endpfad=/w:body[1]/w:p[1]/w:r[1]/w:t[1]/text[1]/char[16] Annotation vor dem zweiten Split: Anfangspfad=/w:body[1]/w:p[1]/w:r[1]/w:t[1]/text[1]/char[1] Endpfad=/w:body[1]/w:p[1]/w:r[1]/w:t[1]/text[1]/char[16-0] Annotation nach dem zweiten Split: Anfangspfad=/w:body[1]/w:p[1]/w:r[1]/w:t[1]/text[1]/char[1] Endpfad=/w:body[1]/w:p[1]/w:r[1]/w:t[1]/text[1]/char[16] In Abbildung 3.14 soll nur der gesamte Text Ein kleiner Test des Knotens an- notiert werden. Der Textknoten muss deshalb nicht geteilt werden. Zu Beginn KAPITEL 3. DOKUMENTENVERARBEITUNG 42 ist der Modus des Algorithmus Begin, es ist also der Anfangspfad der Annotation ausschlaggebend. Der Knoten würde nun an der Textstelle 1, also vor dem ersten Zeichen aufgeteilt. Da diese Aufteilung aber einen leeren Textknoten liefern würde, wird kein Aufbrechen des Texknotens durchgeführt. Nur der Modus wird auf End gesetzt, damit nun der Endpfad ausschlaggebend ist. Hier ist es nun so, dass der Text hinter dem 16-ten Zeichen geteilt werden müsste, aber auch diese Aufteilung würde einen leeren Textknoten erzeugen. Es wird also kein Split durchgeführt. Da es beide Male zu keinem Split kam, müssen auch keine Annotationspfade angepasst werden. Der Modus wird wieder auf Begin gesetzt. Beispiel zu Fall 2: Abbildung 3.15: Knoten muss einmal gesplittet werden Annotation vor dem ersten Split: Anfangspfad=/w:body[1]/w:p[1]/w:r[1]/w:t[1]/text[1]/char[1] Endpfad=/w:body[1]/w:p[1]/w:r[1]/w:t[1]/text[1]/char[3] Annotation vor dem zweiten Split: Anfangspfad=/w:body[1]/w:p[1]/w:r[1]/w:t[1]/text[1]/char[1] Endpfad=/w:body[1]/w:p[1]/w:r[1]/w:t[1]/text[1]/char[3-0] Annotation nach dem zweiten Split: Anfangspfad=/w:body[1]/w:p[1]/w:r[1]/w:t[1]/text[1]/char[1] Endpfad=/w:body[1]/w:p[1]/w:r[1]/w:t[1]/text[1]/char[3] In Abbildung 3.15 soll nur das Wort Ein des Textknotens annotiert werden. Der Textknoten muss deshalb nur einmal geteilt werden. Zu Beginn ist der KAPITEL 3. DOKUMENTENVERARBEITUNG 43 Modus des Algorithmus Begin, es ist also der Anfangspfad der Annotation ausschlaggebend. Der Knoten würde nun an der Textstelle 1, also vor dem ersten Zeichen aufgeteilt. Da diese Aufteilung aber einen leeren Textknoten liefern würde, wird kein Split des Texknotens durchgeführt. Nur der Modus wird auf End gesetzt, damit nun der Endpfad ausschlaggebend ist. Hier wird nun ein Split an der im Endpfad unter /char[] angegeben Position durch- geführt und alle in Mitleidenschaft gezogenen Annotationspfade angepasst. Hierzu zählt allerdings nicht der Endpfad der aktuellen Annotation. Der Modus wird wieder auf Begin gesetzt. Beispiel zu Fall 3: Abbildung 3.16: Knoten muss zweimal gesplittet werden Annotation vor dem ersten Split: Anfangspfad=/w:body[1]/w:p[1]/w:r[1]/w:t[1]/text[1]/char[5] Endpfad=/w:body[1]/w:p[1]/w:r[1]/w:t[1]/text[1]/char[12] Annotation vor dem zweiten Split: Anfangspfad=/w:body[1]/w:p[1]/w:r[1+1]/w:t[1]/text[1]/char[5-4] Endpfad=/w:body[1]/w:p[1]/w:r[1+1]/w:t[1]/text[1]/char[12-4)] Annotation nach dem zweiten Split: Anfangspfad=/w:body[1]/w:p[1]/w:r[2]/w:t[1]/text[1]/char[1] Endpfad=/w:body[1]/w:p[1]/w:r[2]/w:t[1]/text[1]/char[7] In Abbildung 3.16 muss der Knoten zweimal aufgeteilt werden, da nur das KAPITEL 3. Wort kleiner DOKUMENTENVERARBEITUNG 44 innerhalb des Textknotens annotiert werden soll. Der Modus des Algorithmus bendet sich vor dem ersten Split auf Begin. Somit ist der Knoten, der gesplittet werden soll, der Knoten, auf den der Anfangspfad der Annotation referenziert. Nun wird der Textknoten an der Stellte gesplittet, die unter /char[] im Anfangspfad angegeben wurde. Danach muss der Endpfad dieser Annotation und alle davon betroenen Annotationspfade angepasst werden. Durch dieses Anpassen referenziert nun der Endpfad auf den Knoten /w:r[2]. Der Modus wird auf End gesetzt, sodass der Endpfad der Annotation ausschlaggebend ist, er gibt nun den zweiten Split an. Der neu entstandene Textknoten wird wieder aufgeteilt. Die betroenen Annotationspfade werden angepasst, wobei der Endpfad der aktuellen Annotation nicht mehr angepasst wird. Der Modus wird auf Begin gesetzt. 3.4.4 Normalisieren einer Annotationsliste Die Annotationspfade werden nun so gekürzt bzw. erweitert, dass sie immer auf einen r-Knoten verweisen. Dies muss für den Anfangspfad und den Endpfad der Annotation durchgeführt werden. Ein Kürzen der Annotation ist deshalb sehr sinnvoll, da die Formatierung, die die Annotation im Dokument darstellt, immer vor dem entsprechenden Textknoten eingefügt wird. Beide besitzen eben diesen r-Knoten als Vater. Somit muss beim Finden der Annotation an den entsprechenden r-Knoten nur die Formatierung als erstes Kind angefügt werden. Folgender Algorithmus gibt das Normalisieren der Annotationen an. Algorithmus Normalisieren annolist = Liste der Annotationen 1 Method normalisiere ( annolist ) 2 For each anno in annolist do 3 Case name ( last ( anfangspfad ( anno ))) 4 { 5 'p ' : setze anfangspfad ( anno ) auf ersten 6 r - Knoten des Paragraphs 7 8 ' oMathPara ' : setze anfangspfad ( anno ) auf ersten 9 r - Knoten des ersten untergeordneten oMath - Knotens 10 11 ' oMath ' : setze anfangspfad ( anno ) auf ersten 12 r - Knoten des oMath - Knotens 13 14 default : setze anfangspfad ( anno ) auf Pfad des r - Vorfahrens 15 }; 16 Case name ( last ( endpfad ( anno ))) KAPITEL 3. DOKUMENTENVERARBEITUNG 17 { 18 'p ' 19 20 21 ' oMathPara ' 22 23 24 ' oMath ' 25 26 27 default 28 }; 29 Next ; 30 End Method 45 : setze endpfad ( anno ) auf ersten r - Knoten des Paragraphs : setze endpfad ( anno ) auf ersten r - Knoten des ersten untergeordneten oMath - Knotens : setze endpfad ( anno ) auf ersten r - Knoten des oMath - Knotens : setze endpfad ( anno ) auf Pfad des r - Vorfahrens Listing 3.8: Normalisiert Annotationspfade 3.4.5 Einfügen von Annotation in ein Dokument Die ersten beiden Schritte des Annotierens stellen ein Vorbereiten des Dokumentes und der Annotationsliste dar. Der dritte Schritt wird nun die Annotationen tatsächlich in das Dokument einfügen. Im Folgenden werden wir diesen Algorithmus deshalb AnnotateAndComment nennen. Der Algorithmus AnnotateAndComment kann, ebenso wie der Algorithmus Algorithmus AnAlgorithmus Comment. Diese Aufteilung FixAndSplit, wieder aufgeteilt werden. Zum einen in den notate, zum anderen in den erklärt sich aus dem Aufbau des Dokumentes. Wir erinnern uns zurück, dass es Annotationen mit Text gibt. Diese Annotationen fügen einen Kommentartext in das Dokument ein, der in der Annotation als Beschreibung angegeben wird. Kommentare stehen aber nur bedingt im Körper eines Dokumentes. Lediglich eine Referenz mit einer Referenznummer wird an der entsprechenden Stelle im Dokument eingefügt. Der eigentliche Kommentar wird in den comment part eingefügt. Da nun der eigentliche Kommentar nicht im Body des Dokumentes steht, ist es sinnvoll, die beiden Objekte separat anzulegen. Zunächst werden die Referenzen im Dokumentbody erstellt und danach im Comment-Algorithmus die Kommentare unter part comment hinzugefügt. Daher wollen wir nun zu- nächst den Algorithmus Annotate genauer betrachten, der alle Annotationen im Dokumentkörper einfügt. Da durch das Vorbereiten des Dokumentkörpers, also dem Splitten der Textknoten, alle Knoten so erzeugt wurden, wie sie von der Annotation gefordert wurden und alle Annotationspfade angepasst sind, ist das Einfügen der Annotation nun kein Problem mehr. KAPITEL 3. DOKUMENTENVERARBEITUNG 46 Annotate Der Algorithmus des Annotierens durchwandert ebenfalls rekursiv den Dokumentbody. Das Durchwandern wurde hier wieder wie im FixAndSplit Algorithmus realisiert. Alle Kinder des mitgelieferten Knotens werden hier betrachtet. Sollte ein Kind nicht Teil eines Pfades einer Annotation sein, kann dieses ignoriert werden. Ist ein Kind Teil eines Pfades einer Annotation, so wird die Funktion mit diesem Kind als Vaterknoten aufgerufen. Auch muss es wieder zwei Modi geben, einen Begin- und einen End-Modus. Ist der Algorithmus im Begin-Modus, so wird eine passende Annotation gesucht. Hierfür wird der aktuelle Pfad mit dem Begin aller Annotationen verglichen. Wurde eine Annotation gefunden, die auf den aktuellen Pfad passt, so wird an diesen Knoten die entsprechende Formatierung als erstes Kind angehängt. Dies kann nur deshalb erfolgen, da alle Annotationen auf einen rKnoten enden. Der Modus wird nun auf End gesetzt und der Endpfad dieser Annotation wird gesucht. Da sich keine Annotationen überlappen können, kann es auch nicht vorkommen, dass eine andere Annotation während der Suche nach dem Ende der aktuellen Annotation beginnt. Während sich der Algorithmus im End-Modus bendet, wird an jeden r-Knoten die Formatierung der aktuellen Annotation angehängt. Eine Forderung an das Anhängen der neuen Formatierung ist es, dass alle schon vorhandenen Formatierungen, die nicht im Widerspruch zur Formatierung der Annotation stehen, erhalten bleiben. Dies gilt für alle Formatierungen, die nicht die Schriftfarbe verändern. Diese Forderung wurde so implementiert, dass beim Aunden einer schon vorhandenen Formatierung nur eine neue Schriftfarbe gesetzt wird. Sollte die Annotation eine Beschreibung besitzen, so wird noch eine Kommentarreferenz an diese Stelle gesetzt. Kommentare werden durch fortlaufende Nummern eindeutig identiziert, so ist es einfach eine solche Kommentarreferenz zu erstellen. Es muss nur die aktuelle ID gespeichert werden, die beim Einfügen einer neuen Referenz inkrementiert wird. Zusätzlich wird ein Eintrag in einer Hashtabelle angelegt mit der KommentarID und dem dazugehörigen Kommentartext. So können später im Comment Algorithmus auch ohne Annotationsliste die entsprechenden Kommentare schnell erzeugt werden. Es werden alle Knoten des Bodys durchlaufen und jede Annotation eingefügt. KAPITEL 3. DOKUMENTENVERARBEITUNG 47 Algorithmus Annotate node = Knoten der Annotiert werden soll anno = Annotation die eingefügt werden soll 1 Method Annotate ( node , anno ) 2 Case name ( node ) 3 { 4 'p ' : For each child in children ( node ) do 5 Annotate ( child , anno ); 6 Next ; 7 8 ' oMath ' : For each child in children ( node ) do 9 Annotate ( child , anno ); 10 Next ; 11 12 'r ' : Formatierung anpassen ; 13 14 else : If name ( node ) ∈ mathemarkup ( config ) { 15 Formatierung anpassen ; 16 For each child in children ( node ) do 17 Annotate ( child , anno ); 18 Next ; 19 } 20 else { 21 For each Child in children ( node ) do 22 Annotate ( child , anno ); 23 Next ; 24 }; 25 }; 26 End Method Listing 3.9: Annotiert einen Teilbaum Comment Nachdem alle Annotationen in den Dokumentbody eingefügt wurden, müssen nun die entsprechenden Kommentare im Part Comment erzeugt werden. Schon vor dem Einfügen der ersten Kommentarreferenz wurde geprüft, ob der Benutzer bereits Kommentare im Dokument angelegt hat. Dies ist wichtig, da die Kommentarreferenzen fortlaufende Nummern sind und dementsprechend die erste freie KommentarID gewählt werden muss. Sollte der Benutzer noch keinen Kommentar eingefügt haben, so existiert der Part Comment im Word Dokument noch nicht und muss ebenfalls vom Plugin erzeugt werden. Existiert dieser Part nun, so kann damit begonnen werden, mit Hilfe der Hashtabelle, die die Kommentartexte und die KommentarIDs enthält, die eigentlichen Kommentare zu erstellen. Dies geschieht, indem aus jedem Eintrag ein Kommentar mit dem dort angegebenen Inhalt erzeugt wird. Diese werden dann in den Comment Part eingefügt. Die Kommentare müssen nicht zwingend in geordneter Reihenfolge dort aufgelistet sein, sondern können dort KAPITEL 3. DOKUMENTENVERARBEITUNG 48 beliebig auftauchen. Jede Kommentarreferenz die im Dokumentbody angegeben ist, muss hier aber genau einmal auftreten, sonst wäre die Struktur des Dokumentes zerstört und das Dokument unbrauchbar. AnnotateAndComment Die Arbeitsweise des Algorithmus AnnotateAndCommet lässt sich also nun wiefolgt zusammenfassen. Der Algorithmus durchwandert den Dokumentbody und erzeugt im Begin Modus eine Formatierung, wenn der entsprechende r-Knoten gefunden wurde. Im End Modus wird an jeden r-Knoten, der gefunden wird, diese Formatierung angehängt. Es werden ebenfalls Kommentarreferenzen eingefügt, die in einer Hashtabelle zusammen mit dem Kommentartext gespeichert werden. Nachdem der Body abgearbeitet wurde, wird die Funktion Comment gestartet, die nun aus der Hashtabelle die entsprechenden Kommentare im Part Comment erzeugt. Algorithmus AnnotateAndComment aktunode = Aktuell betrachteter Knoten. (bei erstem Aufruf Body-Knoten) annolist = Liste der einzufügenden Annotationen parentpath = Pfad zu aktunode anno = Ist in modus == true nicht instanziiert. In anno wird die Annotation gespeichert, deren Anfang gefunden wurde und deren Ende im modus == false gesucht wird. 1 Function AnnotateAndComment ( aktunode , annolist , parentpath , anno ) 2 3 For each child in children ( aktunode ) do 4 aktupath = path ( child ); 5 If exists ( anno ) { 6 aktuanno = x ∈ annolist with anfangspfad (x) == aktupath 7 If exists ( aktuanno ) { 8 If msg ( aktuanno ) <> "" { 9 baue KommentarreferenzBegin ; 10 }; 11 Annotate ( child , aktuanno ); 12 If endpfad ( aktuanno ) == aktupath and msg ( aktuanno ) <> "" { 13 baue KommentarreferenzEnd ; 14 aktuanno := nothing ; 15 }; 16 } else { 17 aktuannos = { x ∈ annolist | anfangspfad (x) is SubPath of aktupath } 18 If | aktuannos | > 0 { 19 AnnotateAndComment ( child , annolist , aktupath ,( nothing )); 20 }; KAPITEL 3. DOKUMENTENVERARBEITUNG 49 21 }; 22 } else { 23 If endpfad ( anno ) == aktupath { 24 Annotate ( child , anno ) 25 if msg ( aktuanno ) <> "" { 26 baue KommentarreferenzEnd ; 27 } 28 } else { 29 30 If endpfad ( anno ) is SubPath of aktupath { 31 AnnotateAndComment { child , annolist , aktupath , anno }; 32 } else { 33 Annotate ( child , anno ); 34 }; 35 }; 36 }; 37 Next ; 38 End Method Listing 3.10: Fügt Annotationen in ein Dokument ein Diskussion Wie man in Listing 3.10 AnnotateAndComment-Algorithmus erkennen kann, muss der Annotate-Algorithmus nicht nur r-Knoten annotieren können. In den ersten beiden Schritten des Annotierens wurden zwar die Knoten so gesplittet und die Annotationen so angepasst, dass deren Anfangs- und EndPfade immer auf einen r-Knoten verweisen, doch reicht dies für Annotationen, die sich über mehrere Knoten erstrecken, nicht aus. Es kann z.B. sein, dass zwischen Anfangs- und Endpfad mehrere Paragraphen und oMath-Elemente liegen. So musste der Annotate-Algorithmus so konzipiert werden, dass er auch ganze Teilbäume des Dokumentes annotieren kann, also auch Paragraphen und Ähnliches. Da aber das Annotieren eines ganzen Paragraphens oder oMathElementes nichts anderes ist, als alle r-Knoten dieses Teilbaums zu annotieren, kann dies sehr einfach durch rekursive Aufrufe und mehrere Fallunterscheidungen realisiert werden. Ausserdem muss noch ein Spezialfall betrachtet werden für Konstrukte wie etwa Klammern und diverse oMath Objekte. In einem oMath Element können sehr verschiedene Unterelemente auftreten. Diese Vielfalt erschwert es, jedes Unterelement einzeln zu benennen und durch die Annotation färben zu lassen. Hier stellt sich ein ähnliches Problem wie bei der Bereinigung des Dokumentes. Denn auch hier müssen alle Unterelemente des oMath Elementes erhalten bleiben, die die Struktur des Elementes angeben. Hierzu zählen Konstrukte wie Klammern, Matrizen oder diverse Operatoren und Symbole. KAPITEL 3. DOKUMENTENVERARBEITUNG 50 Bei der Bereinigung des Dokumentes wurde dies über die Kongurationsdatei gelöst, die die zu erhaltenden Knotentypen des Bodys beinhaltet. Auch im Falle des Annotierens dieser oMath Elemente wird auf die Kongurationsdatei zurückgegrien. Es wird überprüft, ob der Typ des aktuellen Knotens in der Kongurationsdatei als ein zu annotierender mathematischer MarkupKnoten angegeben wurde. Dies ist deshalb so wichtig, da beispielsweise ein Klammerelement nicht als Text abgespeichert wird, sondern als strukturelles Element im Markup auftritt. Eine gezielte Annotation eines einzelnen Klammerelementes ist daher technisch nicht möglich. 3.5 Updaten eines Dokumentes Im einleitenden Beispiel wurde erwähnt, dass ein Benutzer Hilfe für eine bestimmte Stelle im Dokument über einen Serverdienst anfordern kann, um den nächsten Schritt eines mathematischen Beweises automatisch einfügen zu lassen. Das Resultat dieser Hilfe ist eine Liste von Updates für das Dokument, die an den entsprechenden Stellen eingefügt werden. In Anlehnung an den xUpdate [9] Standard denieren wir ein Update wie folgt: • Befehl: Gibt an, welche Art von Update ausgeführt wird. insert-before: Fügt Inhalte direkt vor den im Path angege- benen Knoten ein. insert-after: Fügt Inhalte direkt hinter den im Path angegebenen Knoten ein. replace: Ersetzt den im Path angegeben Knoten. append: Content wird einfach als letztes Kind an den im Path angegebenen Knoten gehängt. remove: Löscht den im Path angegebenen Knoten. • Pfad: Stelle im Dokument, an der das Update ausgeführt werden soll. • Content: Ist eine Liste von Knoten, die in das Dokument eingefügt wird. Bei dem Befehl remove wird kein Content angegeben. KAPITEL 3. 51 DOKUMENTENVERARBEITUNG Wie wir auch schon in Annotationen festgestellt haben, muss es auch hier wieder eine Hierarchie zwischen den einzelnen Arten von Updates geben. Das Einfügen und Entfernen von Textknoten kann die Pfade zu bestimmten Knoten verändern. Daher sortieren wir die Updates wiefolgt: insert-after ≺ insert-before ≺ replace ≺ append ≺ remove Das Einfügen der Updates in das Dokument erfolgt in zwei Schritten. Zunächst wird das Dokument durchlaufen und für jeden Knoten geprüft, ob ein Update für diesen Knoten vorliegt. Das Finden eines solchen Knotens wird in der Funktion Patch realisiert. Findet diese Funktion einen solchen Knoten im Dokument, wird der zweite Schritt des Updatens ausgeführt, das Apply. Diese Funktion führt den Update-Befehl auf das Dokument aus und realisiert somit das Einfügen oder Löschen im Dokument. Algorithmus Patch aktunode = Aktueller Teilbaum. updatelist = Liste der auszuführenden Updates. 1 Method Patch ( aktunode , updatelist ) 2 For each child in children ( aktunode ) do 3 For each update in updatelist do 4 aktupath = path ( child ); 5 If path ( update ) is Subpath of aktupath and path ( update ) <> aktupath { 6 Patch ( focus , updatelist ) 7 }; 8 If path ( update ) = aktupath then { 9 Apply ( child , update ) 10 }; 11 Next ; 12 Next ; 13 End Method Listing 3.11: Ermittelt Knoten zu den Updates und wendet Apply darauf an Apply Die Funktion Apply wird durch den Aufruf der entsprechenden, bereits vorhandenen Funktionen in MS Word realisiert. KAPITEL 3. DOKUMENTENVERARBEITUNG 52 Kapitel 4 Interaktive Dienste Um dem Benutzer die Möglichkeit zu bieten interaktive Dienste zu nutzen, muss eine kontextsensitive Interaktion mit den Diensten des Assistenzsystems möglich sein. Interaktive Dienste im Mediator Plugin sind etwa das Verizieren von Schritten in einer Beweisführung oder das Einfügen des nächsten Beweisschrittes. Diese Interaktion wird im Plugin durch dynamische Menüs realisiert. Es wird also abhängig von der Textstelle, auf der der Fokus des Benutzers liegt, ein Menü mit Hilfestellungen des mathematischen Assistenzsystems angeboten. Das Finden der entsprechenden Stellen im Dokument ist ein Hauptproblem, das in diesem Kapitel gelöst wird. Hierfür sollen im Folgenden die Techniken des Findens der aktuellen Textstelle und des Erstellens des davon abhängigen Menüs vorgestellt werden. 4.1 Kontext-Sensitive Menüs Um in einem kontextsensitiven Menü dem Benutzer die Dienste eines mathematischen Assistenzsystems anzubieten, müssen zunächst die Knoten im Dokument gefunden werden, zu denen das Menü angefordert wurde. Logischerweise kann ohne diesen Bereich im Dokument keine kontextsensitive Menüinteraktion entstehen. Somit ist die erste Forderung, dass die Knoten im Dokument gefunden werden, für die der Benutzer Hilfe erwartet. Im Folgenden wollen wir verschiedene Ansätze zur Implementierung dieser Forderung diskutieren, die entweder die Knoten im Dokument durch die Cursorposition, durch Markierung im Text oder durch beide Techniken zusammen ermitteln. Finden der Textstelle durch Cursorposition Der einfachste Ansatz zum Finden des Knotens, für die ein Menü angefordert wurde, ist das Ermitteln der Cursorposition. Mit dieser Technik würden die 53 KAPITEL 4. INTERAKTIVE DIENSTE 54 Dienste des mathematischen Assistenzsystem für den Textknoten im Word Dokument angefordert, auf dem zum Zeitpunkt der Anfrage an den Server der Cursor steht. Dieser Ansatz bringt zwei Probleme mit sich. Zunächst einmal könnte ein Benutzer Hilfe zu mehr als einem Textknoten erwarten. Dies könnte dann der Fall sein, wenn etwa ein für den Benutzer zusammenhängender Text durch Formatierungen intern als mehr als ein Textknoten repräsentiert wird. Somit müssten vor dem Anfordern der Menüs alle Formatierungen im Dokument entfernt werden. Jedoch kann nicht gewährleistet werden, dass etwa eine Formel als nur ein Formelknoten dargestellt wird. Das Zweite und wohl grössere Problem stellt die Cursorposition selbst dar. Da die Cursorposition nicht im Dokument mitgespeichert und ein Abfragen der Cursorposition in MS Word eine Darstellung liefert, die keine Rückschlüsse mehr auf den Pfad zu einem Knoten innerhalb des XML-Dokumentes ermöglicht, führt dieser Ansatz ins Leere. Finden der Textstelle durch Markierung Bei diesem Ansatz markiert der Benutzer die Textstelle im Dokument, für die er Hilfe vom Assistenzsystem und somit das Menü anfordern möchte. Dieser Ansatz löst das Problem, dass eventuell nicht alle Knoten, für die der Benutzer Hilfe anfordert, ausgewählt werden. Das Problem, dass die Auswahl, ähnlich wie die Cursorposition, nicht auf die XML-Repräsentation übertragen werden kann, bleibt jedoch erhalten. Somit führt auch dieser Ansatz ins Leere. Finden der Textstelle durch Kommentar Bei dem letzten Ansatz wird automatisch ein Kommentar an der Cursorposition bei einer Menüanfrage in das Dokument eingefügt. Durch diesen Kommentar, können die Knoten im Dokument wieder gefunden werden, zu der das Menü angefordert wurde. Sollte ein Benutzer eine Textstelle markieren, wird der Kommentar automatisch um die komplette Auswahl gelegt. Nach der Menüanfrage wird der Kommentar wieder aus dem Dokument entfernt. Mittels dieses Tricks können so die Pfade zu einer Textstelle oder eine Auswahl innerhalb des Dokumentes gefunden werden. Die Cursorposition und eine Markierung stehen hierbei aber nicht in Konkurrenz, da Word einen Kommentar nur dann an der Cursorposition einfügt, wenn keine Textstelle markiert wurde. Diese Lösung ist aber nur eine Näherungslösung, da Kommentare die Struktur des Dokumentes verändern und mittels einer Heuristik die gefundenen Pfade korrigiert werden müssen. Trotzdem stellt dies einen erfolgversprechenden Ansatz dar, dessen Implementierung im Folgenden genauer erörtert werden soll. KAPITEL 4. 55 INTERAKTIVE DIENSTE 4.1.1 Anfragen von Menüinhalten Um ein Menü anfordern zu können wird neben der bereinigten Fassung des Dokumentes auch ein Startpfad und ein Endpfad benötigt. Diese Pfade stellen den Anfang und das Ende der Markierung innerhalb des Dokumentes dar. Sollte ein Benutzer ohne Markierung, also anhand der Cursorposition, ein Menü anfordern, so sind Start- und Endpfad identisch, da nur ein Knoten im Dokument ausgewählt wurde. Um zu verstehen, wie Start- und Endpfade aus dem Dokument mittels Kommentar gewonnen werden können, muss zunächst der Aufbau eines solchen Kommentars genauer betrachtet werden. Kommentarstruktur in Microsoft Word 2007 Kommentare werden nur teilweise im Dokumentkörper abgelegt. Es wird ein <w:CommendRangeStart/> und ein <w:CommentRangeEnd/> um die zu kom- mentierenden Knoten gelegt. Diese Knoten besitzen ein Attribut ID, dessen Wert eine Referenz zu einem Comment-Knoten angibt, der im Part-Knoten Comments des Dokumentes abgelegt ist. Unter Comments kann nun ein Kommentareintrag mit dieser ID gefunden werden, der angibt, wie der Kommentar gebildet wird und somit auch dessen Kommentartext beinhaltet. Eine weitere Möglichkeit einen Kommentar zu bilden besteht darin, ohne <w:CommentRangeStart/> und <w:CommentRangeEnd/> einen Kommentar anzugeben. Diese Form der Kommentare werden gebildet, wenn in einem oMath-Element ohne Markierung im Dokument ein Kommentar eingefügt wird. In diesem Fall ändert sich der Verweis auf den Comment-Knoten im Dokumentkörper. Anstatt den Anfang und das Ende des Kommentars anzugeben, wird lediglich auf der untersten Ebene innerhalb des oMath-Elementes der Knoten ein Attribut ment <w:CommentReference> eingefügt. Dieser Knoten besitzt wieder ID, das wiederum auf einen Kommentar innerhalb des part com- verweist. Innerhalb des Part-Knotens unterscheiden sich diese beiden Techniken nicht. Wir wollen nun eine Technik entwickeln, um die Pfade zu dem ausgewählten Knoten innerhalb des Dokuments zu berechnen. Berechnen von Pfaden Um einen Pfad zu berechnen benötigen wir zunächst einen Kommentar im Dokument, der als erster Schritt der Menüanfrage in das Dokument eingefügt wird. Wie beschrieben wird der Kommentar entweder um die Auswahl im Dokument gelegt oder bei fehlender Auswahl um den Knoten an KAPITEL 4. 56 INTERAKTIVE DIENSTE der Cursorposition. Dieser Kommentar muss nun im Dokument wiedergefunden werden, da es sein kann, dass ein Benutzer eingeständig Kommentare in das Dokument eingefügt hat. Hierfür wird in den von der Menüanfrage automatisch erzeugten Knoten der Text `requesting Menu...` eingefügt. Anhand dieses Textes wird dann die ID des Kommentars innerhalb des Part- <Comments> ermittelt. Mit dieser ID kann auch das entsprechende <w:CommentRangeStart/> und <w:CommentRangeEnd/> gefunden werden. Knotens Mit Hilfe der Kommentar ID werden nun die Pfade zum ersten und letzten Knoten innerhalb des Kommentars ermittelt. Da und <w:CommentRangeEnd/> <w:CommentRangeStart/> immer Kinder eines r-Knotens sind, führt der so ermittelte Pfad immer direkt zu einem Textknoten innerhalb des Dokumentes. Sollte nun ein Kommentar ohne Markierung in eine Formel eingefügt worden sein, so existiert lediglich ein <w:CommentReference> Knoten und das Ergebnis der Pfadsuche ist leer. In diesem Fall wird eine zweite Suchvariante gestartet, die den Pfad zu dem oMath-Element liefert, das eben diesen Knoten beinhaltet. Start- und Endpfad werden in diesem Fall identisch gesetzt. Menüanfrage und Aufbau Da nun die Pfade bekannt sind, kann eine Anfrage für ein Menü an den Server gestellt werden. Resultat dieser Menüanfrage ist der Inhalt des Menüs. Dieser Inhalt ist eine Liste von Objekten, die entweder Menüs sein können oder Aktionen. Falls das Objekt ein Menü sein sollte, wird ein Untermenü erstellt. Sollte das Objekt eine Aktion sein, wird ein Button erstellt, der diese Aktion ausführt. Mit dieser rekursiven Denition, lassen sich beliebig geschachtelte Menüs erstellen. Aktionen werden durch eine sogenannte ActionID eindeutig identiziert. Diese ID wird zusammen mit der Aktion vom Server geliefert und an den dazugehörigen Button im Menü gebunden. Dies ist nötig damit beim Drücken des Buttons eindeutig ist, welche Aktion auf dem Server ausgeführt werden soll. Sollte nun eine bestimmte Aktion im Menü gewählt werden, wird die ActionID zum Server geschickt, der dann die Resultate dieser Aktion berechnet. Den Ablauf dieser Interaktion zwischen Plugin und Server wird in Abbildung 4.1 dargestellt. KAPITEL 4. INTERAKTIVE DIENSTE Abbildung 4.1: Das Message Sequence Chart der Menüinteraktion. 57 KAPITEL 4. 4.2 INTERAKTIVE DIENSTE 58 Ergebnisse interaktiver Dienste Bisher wurde erläutert, wie ein Menü und dessen Aktionen aufgebaut werden. Nun wollen wir betrachten, wie das Resultat einer auf dem Server ausgeführten Aktion in das lokale Dokument eingetragen wird. Der Benutzer fordert zunächst das Menü für eine bestimmte Textstelle im Dokument an und löst dort eine Aktion aus. Nachdem diese Aktion auf dem Server ausgeführt wurde, wird das Resultat zum Plugin zurückgeliefert. Das Resultat wiederum besteht aus folgenden vier Komponenten: eine Liste von Updates, eine Liste von Annotationen, eine neue Versionsnummer und eine Beschreibung. Sollte der Inhalt der Beschreibung nicht leer sein, ist ein Fehler aufgetreten und es wird die Beschreibung als Text einer Ausnahme ausgegeben. Sollte die Beschreibung aber leer sein, verlief das Ausführen der Aktion auf dem Server erfolgreich und Updates und Annotationen können eingetragen werden. Wie in Abbildung 4.1 beschrieben muss nun zwischen synchronen und asynchronen Ergebnissen unterschieden werden. Diese Unterscheidung beruht auf der Tatsache, dass etwa das Berechnen einer Formel oder das Prüfen gewisser Teile des Dokumentes unter Umständen länger dauern kann, da das mathematische Assistenzsystem etwas Zeit benötigt, die entsprechenden Annotationen oder Updates zu berechnen. Deswegen werden die Teile der angeforderten Updates und Annotationen sofort zurückgeliefert, die unmittelbar berechnet werden konnten. Diese Updates und Annotationen sind synchrone Ergebnisse. Durch das Ausführen des Timers (Abbildung 4.1) werden nun nach und nach auch die Ergebnisse der Aktion eingetragen, die nicht direkt als Ergebnis auf die Aktion zurückgeliefert wurden. Diese Ergebnisse nennen wir asynchrone Ergebnisse. Das Eintragen der Ergebnisse geschieht wie folgt: Die Versionsnummer wird an das Dokument angehängt, womit die alte Versionsnummer überschrieben wird. Updates, ob synchron oder asynchron, werden immer direkt bei Erhalt in das Dokument eingetragen. Das Einfügen von Updates in das Dokument wurde in Kapitel 3.5 genauer beschrieben. Im Gegensatz zu Updates werden Annotationen nur dann eingefügt, wenn sich das Dokument im Annotations-Modus bendet. Sollte das Dokument im Bearbeiten-Modus sein, werden die Annotationen gespeichert und erst beim Wechsel in den Annotations-Modus eingefügt, entsprechend der Beschreibung in Kapitel 3 Dokumentenverarbeitung. Kapitel 5 Verwandte Arbeiten Das in dieser Arbeit entwickelte Mediator Plugin stellt eine Weiterentwicklung des in dem Paper [12, PlatΩ: A Mediator between Text-Editors and Proof Assistance Systems] vorgestellten Plugins dar. In diesem Paper wurde mit dem PlatΩ Mediator ein TeXmacs Plugin entwickelt, das die Dienste eines mathematischen Assistenzsystems in den TeXmacs Texteditor integriert. Der Benutzer hat hier die Möglichkeit zwischen einer strukturierten Darstellung des Dokumentes, wie etwa in einem TeX File, und einer gerenderten (WYSIWYG) Darstellung zu wechseln. Das Anzeigen der dynamischen Menüs wurde, anders als in dieser Arbeit, direkt in das Dokument integriert. Das bedeutet, dass der Benutzer bei einer Menüanfrage nicht ein Drop-Down Menü innerhalb der Funktionsleiste erhält, sondern direkt an der entsprechenden Textstelle. Das Konzept der Annotationen, deren Anforderung und Visualisierung wurde hingegen zum ersten Mal in dieser Bachelorarbeit vorgestellt und realisiert. Eine weitere verwandte Arbeit ist [2, A Framework for Interactive Proof]. Dort wird ein Framework für interaktive Beweisführung vorgestellt, dessen Komponenten über das PGIP Protokoll kommunizieren. Als Benutzerschnitt- stelle zu diesem Framework wird ein ASCII basiertes Plugin mit dem Namen ProofGeneral vorgestellt. In diesem Plugin wird jede Zeile nach dem Schreiben zum Prover geschickt. So wird lediglich eine Sequenz von Anweisun- gen erstellt, die von einem mathematischen Assistenzsystem benutzt werden kann, um einen mathematischen Beweis zu erstellen. Das ProofGeneral Plugin wird in [1, Proof General: A Generic Tool for Proof Development] genauer erläutert. Im Gegensatz dazu bietet das in dieser Arbeit vorgestellte Plugin eine generische Schnittstelle zu einem mathematischen Assistenzsystem, welche auf strukturierten Dokumenten basiert. 59 KAPITEL 5. VERWANDTE ARBEITEN 60 In dem Paper [5, Managing proof documents for asynchronous processing] wird ein weiteres Verfahren vorgestellt, um semantische Dienste in TextEditoren anzubieten. Hierbei wird ein Protokoll (IAPP) vorgeschlagen, dass die Rechte an Textabschnitten im Dokument zwischen Autor und semantischen Diensten kontinuierlich überträgt, um Konikte auszuschliessen. Das dadurch zwangsläuge Blockieren von Dokumentteilen tritt in dem in dieser Arbeit vorgestellten Mediator Plugin nicht auf, da eine Update-basierte Schnittstelle verwendet wird. Die Auösung von Konikten wird bei der Mediator Architektur vom Server durchgeführt, wobei die Änderungen des Autors immer die höchste Priorität haben. Ausserdem werden asynchrone Ergebnisse vom Plugin nur dann eingefügt, wenn diese vorher vom Benutzer angefordert wurden. Dies kann in Form von Annotationen im AnnotationsModus oder von Updates während des Bearbeiten-Modus geschehen. Kapitel 6 Zusammenfassung und Ausblick In dieser Arbeit wurde ein Microsoft Word 2007 Plugin entwickelt, das eine generische Schnittstelle zu dokumenten-basierten Diensten bereitstellt. Das Plugin befähigt den Benutzer, ein Dokument durch ein mathematisches Assistenzsystem zu verizieren und etwaige Fehler in MS Word visualisieren zu lassen. Hierzu wurde das Konzept von Annotationen vorgestellt, das es ermöglicht, Statusinformationen und Fehlermeldungen für Dokumentteile anzuzeigen. Die Technik des Annotierens setzt sich zusammen aus der Vorbereitung des Dokumentes mit Aufbrechen von Textknoten und dem anschliessenden Einfügen der Annotationen unter Verwendung der Kommentarfunktion von MS Word. Desweiteren bietet das Plugin eine kontext-sensitive Menüinteraktion an, mit deren Hilfe der Benutzer Unterstützung beim mathematischen Beweisen anfordern kann. Hierzu wurden die Techniken des Updatens eines Dokumentes und das Finden der aktuellen Textstelle entwickelt. Das Zusammenspiel zwischen den Diensten des mathematischen Assistenzsystems und der Dokumentenverwaltung ermöglicht das gewünschte interaktive Verfassen mathematischer Dokumente. Das Plugin ermöglicht hierbei die Integration von synchronen und asynchronen Ergebnissen einer Menüinteraktion in Form von Annotationen und Updates. In dieser Arbeit wurden bereits einige Bestandteile des Oce Open XML Standards vorgestellt und eingesetzt. Es bietet sich an, die entwickelten Methoden schrittweise auf die bisher nicht betrachteten Bestandteile zu erweitern, ein Beispiel hierfür wären etwa Tabellen. Gegebenenfalls müssen die Formatierungs-Heuristiken entsprechend angepasst werden. Eine weitere interessante Fragestellung ist das kollaborative Bearbeiten ei- 61 KAPITEL 6. ZUSAMMENFASSUNG UND AUSBLICK 62 nes Dokumentes. Mehrere Benutzer bearbeiten hierbei gleichzeitig dasselbe Dokument. Hierzu müssten die lokalen Dokumente der Benutzer durch Updates auf den gleichen Stand gebracht, also synchronisiert werden. Um dies umsetzen zu können, müsste eine neuartige Technik der Versionsverwaltung entwickelt werden, die die Semantik des Dokumentes berücksichtigt. Literaturverzeichnis [1] D. Aspinall. Proof General: A generic Tool for Proof Development. Calculemus '07 / MKM '07: Proceedings of the 14th symposium on Towards Mechanized Mathematical, pages 3842, (2000). In [2] D. Aspinall, C. Lüth, and D. Winterstein. A Framework for Interactive Calculemus '07 / MKM '07: Proceedings of the 14th symposium on Towards Mechanized Mathematical Assistants, pages 161175, Berlin, Proof. In Heidelberg, 2007. Springer-Verlag. [3] ECMA International. ECMA-376 / Oce Open XML File Formats, 2008. [4] International Organization for Standardization. ISO Standards. //www.iso.org/iso/home.htm. [5] H. Gast. http: Managing proof documents for asynchronous processing. S. Autexier and C. Benzmüller, editors, In 8th Workshop on User Interfaces for Theorem Provers (UITP'08), August 2008. [6] Microsoft. Das Microsoft Oce Open XML-Format. microsoft.com/de-de/office/bb906068.aspx. [7] Microsoft. Microsoft Oce Word 2007. com/de-de/word/HA101656411031.aspx. http://msdn. http://office.microsoft. [8] J. Siekmann, C. Benzmüller, A. Fiedler, A. Meier, I. Normann, and M. Pollet. Proof Development in ΩMEGA: The Irrationality of √ 2. pages 271314. Kluwer Academic Publishers, 2003. [9] A. Laux und L. Martin. Xupdate xml update language (working draft), 2000. http://xmldb-org.sourceforge.net/xupdate. [10] W3C. XML Path Language (XPath) Version 1.0. TR/xpath, 1999. 63 http://www.w3.org/ 64 LITERATURVERZEICHNIS [11] W3C. Extensible Markup Language(XML) 1.0 (Fifth Edition). //www.w3.org/TR/xml, http: 2008. [12] M. Wagner, S. Autexier, and C. Benzmüller. PLATΩ: A Mediator between Text-Editors and Proof Assistance Systems. In S. Autexier and 7th Workshop on User Interfaces for Theorem Provers (UITP'06), volume 174(2) of Electronic Notes on Theoretical Computer Science, pages 87107. Elsevier, August 2006. C. Benzmüller, editors,