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:

FunktionBeschreibung
initInitialisierung prozessrelevanter Variablen, z.B. Festlegung des Patterns für die Datumserkennung
doTextHauptroutine 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.
getFragmentsLiefert eine Liste mit den erstellten Fragmenten. Wichtig! Die Liste muss bei einer globalen Deklaration (wie hier im Beispiel) bei jedem Durchlauf gelöscht werden.
hasFragmentsFalls 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:

MethodeBeschreibung
setErstelltVonWer hat das Fragment erstellt
setGeaendertVonVon wem wurde das Fragment geändert
setFragmentnameName des Fragments
setFragmentvalueWert des Fragments
setFragmenttypeType bzw. Interface-Name des Fragments
setProbabilityZutreffende Wahrscheinlichkeit. Wichtig! der Wert liegt zwischen 0 und 1
setPageAuf welcher Seite wurde das Fragment gefunden. Anmerkung, hier sollte -1 übergeben werden.
setValidEnthä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.

EingabeRückgabe
NoneNone

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.

EingabeRückgabe
Stringboolean

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.

EingabeRückgabe
NoneList<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.

EingabeRückgabe
Noneboolean

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.

EingabeRückgabe
NoneList<IFragmentData>

hasData()

Analog wie bei hasFragments(). Sollten Daten erwirtschaftet worden sein, so erfolgt die Rückgabe mittels „true“.

EingabeRückgabe
Noneboolean