Validierer spielen eine wichtige Rolle während der Bearbeitung eines Formulars. Sie kontrollieren die Komponenten auf die erforderlichen Werte, die durch die Anwendung benötigt werden, um sie nach dem submit zu übergeben. Das Validierer-Konzept der *FormEngine sorgt dafür, dass ein Formular nur mit validen Daten verlassen werden kann, so dass eine Validierung der Daten im Backend entfallen kann. Dieser Vorteil kommt vor allem dann zum Tragen, wenn für die Erfassung eines Datensatzes, abhängig vom aktuellen Kontext der Anwendung, unterschiedliche Regeln gelten sollen oder in einer anderen Formular-Ausprägung nur eine Teilmenge der Daten eingegeben werden soll.
Verwendung von Validierern in der XML-Definition
Den Komponenten werden in der Formulardefinition die zu verwendenden Validierer-Klassen zugewiesen. Über boolesche Validierer können auch mehrere Regeln logisch miteinander verknüft werden. Die verfügbaren Standard-Validierer können in der XML-Definition über Elemente angegeben werden, deren Namen genau den Klassennamen der Validierer-Implementierungen entsprechen.
Beispielsweise wird über das Element <length .../> die Validierer-Klasse
LengthValidator aus dem Standard-Package für Validierer de.imatics.forms.validator
verwendet. Die Attribute der Elemente werden direkt als Paramerer an den Validierer übergeben.
<length min="5"/> sorgt also für eine Überprüfung des Komponentenwertes
auf eine Länge von mindestens fünf Zeichen - insofern es sich um eine Text-Komponente handelt.
Einige Validierer können abhängig von ihrer semantischen Bedeutung auch unterschiedliche Datentypen validieren.
Bei einer Mehrfachauswahl (Listen-Komponenten) würden bei diesem Beispiel mindestens fünf Elemente in der Auswahl
erwartet.
Derzeit stehen über 20 Validator-Implementierungen zur Verfügung, die auf diese Weise verwendet werden können. Deren Namen und Beschreibungen können in der im Download-Archiv enthaltenen API-Dokumentation nachgelesen werden.
Im folgenden Beispiel wird eine Längenprüfung und eine Inhaltsprüfung logisch verknüpft,
so dass der eingegebene Text mindestens 50 Zeichen oder die Zeichenkette short
enthalten muss. Für eine UND-Verknüpfung von Regeln, kann dass <and>-Tag direkt unterhalb
<validator>-Elements weggelassen werden, da standardmäßig alle Validierer darin UND-verknüpft werden.
<component ...>
<validator>
<or>
<length min="50"/>
<contains value="short"/>
</or>
</validator>
</component>
Für eigene Validator-Implementierungen steht ein spezielles Element zur Verfügung,
in dem der Name der Validierer-Klasse als Attribut angegeben wird.
<custom class="my.own.ValidatorClass"/>
Dynamische Parameter für Validierer
Die Parameter für die Validierer müssen nicht als feste Werte angegeben werden,
sondern können auch zur Laufzeit durch Calculator berechnet werden.
Im einfachsten Fall liefert der ValueCalculator den Wert einer anderen Komponente.
Das vorherige Beispiel kann so angepasst werden, dass die erforderliche Länge oder der
Teil-String der enthalten sein soll aus einer anderen Komponente ermittelt wird.
Bei Validierern, die genau einen Parameter benötigen, wird der Calculator direkt
als Kind-Element des Validierers angegeben (z.B. bei contains).
Für Validierer mit mehreren möglichen Parametern wird über zusätzliche parameter-Elemente
der name des Parameters und darin der Calculator angegeben (z.B. bei length).
<component ...>
<validator>
<or>
<length>
<parameter name="min">
<value component="componentX"/>
</parameter>
</length>
<contains/>
<value component="componentY"/>
</contains/>
</or>
</validator>
</component>
Ausführung der Validierung
Immer wenn der Wert einer Komponente validiert werden soll, wird der Komponentenwert
vom Framework "von oben" an die Validierer-Hierarchie übergeben. Sobald ein Validierer den Wert
nicht akzeptiert, wirft er eine Exception mit einer Beschreibung des fehlerhaften Wertes.
Die logischen Validierer or und and fassen die Meldungen mehrerer
Validierer ggf. zu einer Meldung zusammen.
Sonderbehandlung von leeren Komponenten
Bei der Verwendung der Validierer muss man die Besonderheit berücksichtigen, dass nur eingegebene Werte überprüft werden. Der Grund dafür ist, dass ein Formularfeld nicht unbedingt ein Pflichtfeld sein muss und der Wert nur überprüft werden soll, wenn tatsächlich etwas eingegeben wurde. Beispielsweise soll das Format einer E-Mail-Adresse überprüft werden, aber es muss nicht unbedingt eine E-mail-Adresse eingegeben werden.
Damit nicht jeder Vaildierer die Akzeptanz von null implementieren muss
oder diese über einen Parameter aktiviert werden muss, wird ein Validierer nur aufgerufen,
wenn der zu prüfende Wert NICHT null ist.
Die einzige Ausnahme ist der <required>-Validierer
(gleichbedeutend mit <not-empty>). Dieser kann mit jedem Validierer
UND-Verknüpft werden, um ein Feld als Pflichtfeld zu definieren.
Im ersten Fall soll der eingegeben Wert mindestens 3 und maximal 10 Zeichen besitzen. Es kann aber auch gar kein Wert eingegeben werden, was ja einer Länge von 0 entspricht und nicht immer der Intuition des verwendeten Validierers entspricht.
<validator>
<length min="3" max="10"/>
</validator>
Um eine Eingabe zu erzwingen, muss also noch der required Validierer hinzugefügt werden.
<validator>
<required/>
<length min="3" max="10"/>
</validator>
Eigene Validierer implementieren
Um spezielle Regeln zu implementieren, die sich mit den Standard-Validierern nicht realisieren lassen,
können auch eigene Validator-Klassen verwendet werden.
Dazu muss die Klasse de.imatics.forms.validator.Validator oder de.imatics.forms.validator.ComponentValidator
abgeleitet und die Methode validate implementiert werden.
Die Methode muss eine ValidatorException werfen, wenn der Wert nicht den Anforderungen entspricht,
und läuft ohne Exception durch, wenn der Wert in Ordnung ist.
Diese Exception erhält dabei eine internationalisierte Fehlermeldung,
die dem Benutzer im Formular angezeigt wird.
Dem Konstruktor der Exception wird dazu ein Message-Objekt übergeben,
das eine Referenz auf ein MessageBundle und einen darin enthaltenen Message-Key darstellt.
Das MessageBundle sollte dabei im selben Verzeichnis liegen, wie die Validator-Klasse.
Um Überschneidungen zwischen gleichen Keys in verschiedenen Klassen zu verhindern,
setzt sich der vollständige Message-Key dann aus dem Namen der Klasse und dem Key zusammen,
der beim Aufruf der message-Methode übergeben wird.
package de.imatics.example.validator;
import de.imatics.forms.validator.*;
import de.imatics.i18n.*;
import de.imatics.forms.DataContext;
public class MyValidator extends ComponentValidator {
private static final I18n i18n = I18n.getInstance(MyValidator.class);
protected void validate(DataContext component) throws ValidatorException {
Object value = component.getValue();
boolean isValid = ...;
if (!isValid) {
Message message = i18n.message("myMessageKey");
throw new ValidatorException(this, component, message);
}
}
}
MyValidator.myMessageKey = My error message
Dieser Validierer kann dann über das custom-Element in der Formular-Definition verwendet werden.
<validator>
<custom class="de.imatics.example.validator.MyValidator"/>
</validator>


