Beispiel Position-Tagger
Während der Entity-Tagger in der Lage ist die Dokumenten-Entität zu verändern, kann der Position-Tagger nur Informationen auf Basis von einzelnen Fragmenten bereitstellen. Bedeutet, das Dokument besteht unverändert fort.
Das folgende Beispiel wird in den übergebenen Texten nach einem Datumswert im Format „dd.MM.yyyy“ gesucht und bei einem Treffer die Information als Fragment zurückgeliefert.
Für die Umsetzung der relevanten Funktionalität, wird das Interface „IDocumentFragments“ benötigt.

Im Vergleich zu dem Entity-Tagger, verwendet und nutzt der Position-Tagger keine Tags. Weitere Annotation’s wie @ProcessName, @ProcessAuthor und @Description müssen aber gesetzt werden.
Der Funktionsumfang bzw. die zu implementierenden Methoden wurden wie folgt verwendet:
Funktion | Beschreibung |
init | Initialisierung prozessrelevanter Variablen, z.B. Festlegung des Patterns für die Datumserkennung |
doText | Hauptroutine zur Bestimmung der Inhalte. Bei Ausführung werden vom System nur die erste Seite oder alle Dokument-Seiten übergeben. In diesem Beispiel wird gezielt nach dem Pattern „dd.MM.yyyy“ gesucht, der erkannte Wert überprüft und ein Fragment erstellt. Sollte die Funktion ein Fragment gebildet haben, so wird der Wert „True“ zurückgeliefert. |
getFragments | Liefert eine Liste mit den erstellten Fragmenten. Wichtig! Die Liste muss bei einer globalen Deklaration (wie hier im Beispiel) bei jedem Durchlauf gelöscht werden. |
hasFragments | Falls Fragmente gebildet wurden, wird der Wert „true“ ansonsten „false“ zurückgegeben. |
Der Java-Code wird wie folgt umgesetzt:
package de.biffo.datumtagger;
import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.biffo.dms.api.Description;
import org.biffo.dms.api.IDocumentFragments;
import org.biffo.dms.api.IFragmentData;
import org.biffo.dms.api.ProcessAuthor;
import org.biffo.dms.api.ProcessName;
import org.biffo.dms.entity.Fragments.Fragment;
@ProcessName(value = "Datum Tagger")
@ProcessAuthor(author = "mlange", url = "www.biffo.de", major = 0, minor = 1)
@Description("Sucht nach einem Datum im Format dd.MM.yyyy und liefert entsp. ein Fragment zurück.")
public class datumtagger implements IDocumentFragments, Serializable {
private static final long serialVersionUID = 1L;
private SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy");
private Pattern ptDatum;
private List<Fragment> lstFragments = new LinkedList<Fragment>();
@Override
public void init() throws Exception {
ptDatum = Pattern.compile("(\\d{2}\\.\\d{2}\\.\\d{4})");
}
@Override
public boolean doText(String inputText) {
// TODO Auto-generated method stub
boolean found=false;
lstFragments.clear();
Matcher datumsSuche = ptDatum.matcher(inputText);
while(datumsSuche.find()) {
Fragment fragment = new Fragment();
fragment.setErstelltVon(this.getClass().getSimpleName());
fragment.setGeaendertVon(fragment.getErstelltVon());
fragment.setFragmentname("DATUM");
fragment.setFragmentvalue(datumsSuche.group(0));
fragment.setFragmenttype("IDocumentFragments");
fragment.setProbability(0);
fragment.setPage(-1);
try {
Date d = sdf.parse(datumsSuche.group(0));
fragment.setFragmentvalue(sdf.format(d));
fragment.setValid(true);
fragment.setProbability(1);
}catch(Exception e) {
fragment.setFragmentvalue(datumsSuche.group(0));
fragment.setValid(false);
fragment.setProbability(0);
}
lstFragments.add(fragment);
found=true;
}
return found;
}
@Override
public List<Fragment> getFragments() {
return lstFragments;
}
@Override
public boolean hasFragments() {
if(lstFragments.size()>0) return true;
return false;
}
@Override
public List<IFragmentData> getData() {
return null;
}
@Override
public boolean hasData() {
return false;
}
}
Wie bereits beschrieben, liegt die Besonderheit in der Rückgabe von Fragmenten, d.h. es werden Textblöcke entsp. ihres Vorkommens gebildet. Fragmenten werden je nach vorkommen von der Applikation automatisch übernommen und dem jeweiligen Dokument hinzugefügt. Daher muss ein Fragment mit folgenden Informationen gebildet werden:
Methode | Beschreibung |
setErstelltVon | Wer hat das Fragment erstellt |
setGeaendertVon | Von wem wurde das Fragment geändert |
setFragmentname | Name des Fragments |
setFragmentvalue | Wert des Fragments |
setFragmenttype | Type bzw. Interface-Name des Fragments |
setProbability | Zutreffende Wahrscheinlichkeit. Wichtig! der Wert liegt zwischen 0 und 1 |
setPage | Auf welcher Seite wurde das Fragment gefunden. Anmerkung, hier sollte -1 übergeben werden. |
setValid | Enthält das Fragment valide Informationen. Im Beispiel wird überprüft, ob es sich wirklich um ein Datum handelt. |
Die Bereitstellung in der Applikation ist 1:1 wie beim Entity-Tagger mittels JAR Archiv umzusetzen.


Ob das Modul korrekt arbeite, kann mittels einer Prüfung aus der Modulansicht erfolgen. In dem Beispiel wird die bereits verarbeitete „Vodafone“ Rechnung mit der ID=7 genutzt. Im Block „Text Input:“ mittels dem Befehl „doc[7]“ den Test starten.

Bereitgestellte Funktionen von „IFragmentEntity“ und deren Nutzung:
init()
Wird beim Laden des Moduls in den Hauptspeicher ausgeführt. Hierüber können z.B. dynamisch OpenNLP Modelle geladen oder Variablen initialisiert werden.
Eingabe | Rückgabe |
None | None |
doText()
Routine zur Überprüfung der einzelnen Seitentexte des jeweiligen Dokumentes, auf die das Modul angewendet wurde. Das Modul kann für die Verwendung „Aller“ oder nur der „ersten Seite“ in den Moduleinstellungen konfiguriert werden.
Eingabe | Rückgabe |
String | boolean |
getFragments()
Liefert eine Liste mit generierten Fragmenten, die während des Aufrufs der „doText“ Funktion erstellt wurden. Die generierten Fragmente werden vor Speicherung auf ein mögliches Vorhandensein überprüft und ggf. mit bestehende Fragmente ersetzt und mit dem Dokument verknüpft.
Eingabe | Rückgabe |
None | List<Fragment> |
hasFragments()
Positive Rückgabe, falls Fragmente dem Ergebnis der „doText“ Funktion zugeordnet werden können. Falls Fragment aufgebaut wurden und die Rückgabe „false“ liefert, erfolgt keine Verarbeitung der Fragmente.
Eingabe | Rückgabe |
None | boolean |
getData()
Die Methode ist vorgesehen um aus Dokumenten strukturierte Informationen zu gewinnen. Hierzu muss das Interface IFragmentData bei der Class-Definition mit implementiert werden. Denkbar ist in der Zukunft mittels REST ein Modul auf Dokumenten zu platzieren und dann strukturierte Daten abzuziehen. Beispiel wäre die Überführung von erkannten Rechnungspositionen in die hierzu entsprechende Struktur.
Wichtig! Die Methode wird derzeit noch nicht verwendet.

Eingabe | Rückgabe |
None | List<IFragmentData> |
hasData()
Analog wie bei hasFragments(). Sollten Daten erwirtschaftet worden sein, so erfolgt die Rückgabe mittels „true“.
Eingabe | Rückgabe |
None | boolean |