Skip to content

Quick Start

Patrick Moawad edited this page Feb 24, 2016 · 25 revisions

This page gives information to help you get started quickly.

Project setup

If you are using Maven and have access to the internet from your development environment, you may simply add the following dependencies to your Maven project:

<!-- In any case -->
<dependency>
    <groupId>com.google.code.validationframework</groupId>
    <artifactId>validationframework-core</artifact>
    <version>FILL_IT_IN</version>
</dependency>

<!-- If you are using Swing (for Java 6 and up) -->
<dependency>
    <groupId>com.google.code.validationframework</groupId>
    <artifactId>validationframework-swing</artifact>
    <version>FILL_IT_IN</version>
</dependency>

<!-- If you are using JavaFX (for Java 8 and up) -->
<dependency>
    <groupId>com.google.code.validationframework</groupId>
    <artifactId>validationframework-javafx</artifact>
    <version>FILL_IT_IN</version>
</dependency>

Otherwise, you may just grab the latest released artifacts from Maven Central and put them in your classpath: http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.google.code.validationframework%22

Basics

Each validation (for instance, of an input field) is implemented using a validator. A validator needs the following elements:

  • One or more triggers to start the validation process: triggers can be initiated, for instance, on each key stroke in an input field, when a checkbox is ticked, when some event happens in the system, etc.;
  • One or more data providers to retrieve the data to be validated whenever the triggers are initiated: data providers can, for instance, read the text from an input field, get some data from the database, etc.;
  • One or more rules to validate the provided data and produce validation results: rules can, for instance, make sure the number entered by the user is of the correct format, check whether some text matches a regular expression, verify that some mandatory fields are filled in, check several fields against each other, etc.; validation results can be, for instance, a boolean (true for valid, false for invalid), an enumeration (OK, STRING_TOO_LONG, STRING_TOO_SHORT, and so on), etc.;
  • One or more result handlers to process the rule results: result handlers can, for instance, give feedback to the user by making the border of the input field red, show an error icon, show a green check mark, make some components (in-)sensitive, make some components (in-)visible, etc..

Some data providers, rules, result handlers and validators may use transformers to convert the manipulated data. For transformers may be used to convert formatted textfield input before passing it to the rules, to aggregate all the boolean results from all rules before passing the overall result to the result handlers, etc..

Typically, in case of validation of input fields, one validator is used to validate one input field. You may use additional validators to perform group validation: for instance, one validator for each input field, one validator to validate the fields against each other, and one validator to aggregate the results of several groups and enable/disable an Apply button. So the ValidationFramework allows to structure easily the validation inside dialog windows, main frames, etc.

Refer to the quick reference below for a quick overview of triggers, data providers, rules, result handlers, validators and transformers the ValidationFramework provides by default, or browse through the different Java packages.

You may even implement your own in order to fill some needs very specific to your project. The interfaces are very simple.

Code examples

The following examples show you how to quickly validate Swing components input using the DSL. Validation of JavaFX components follow the exact same principles.

Validation of a single field

Suppose you want to validate a single input field and make sure it is not empty:

import static com.google.code.validationframework.base.validator.generalvalidator.dsl.GeneralValidatorBuilder.on;
...

JTextField nameTextField = new JTextField();
...
on(new JTextFieldDocumentChange(nameTextField))        // On any change in the input field,
  .read(new JTextFieldTextProvider(nameTextField))     // get its text,
  .check(new StringNotEmptyRule())                     // make sure the text is not empty,
  .handleWith(new IconBooleanFeedback(nameTextField)); // show the result using an icon in the corner.

This will trigger the validation whenever the contents of the input field is changed (on key strokes, copy/paste, etc.). When triggered, the text from the input field will be read and check against the rule. The rule will produce a result: true if valid, false if invalid. And finally the result will shown to the user using the result handler as an icon in the lower left hand corner of the input field (feedback).

Suppose now that you want to make sure that this same field should also be less than 100 characters. You can just add another rule as follows:

on(new JTextFieldDocumentChangeTrigger(nameTextField)) // On any change in the input field,
  .read(new JTextFieldTextProvider(nameTextField))     // get its text,
  .check(new StringNotEmptyRule())                     // make sure the text is not empty,
  .check(new StringLengthLessThanRule(100))            // make sure the text is less than 100 characters,
  .transform(new AndBooleanAggregator())               // combine the two boolean results with an AND operator,
  .handleWith(new IconBooleanFeedback(nameTextField)); // show the overall result using an icon in the corner.

If there is only one rule, the handleWith() method expects a result handler that can handle a single Boolean result. But if you add several rules, the handleWith() method expects a result handler that can handle a collection of Boolean results (Collection), unless they are previously combined.

In the above example, we combine the results using the AND operator, because the input field is valid if it is not empty AND the input string is less than 100 characters.

You may add several triggers, several data providers, several rules and several result handlers. You can combine and transform the provided data before they are checked by the rules. You can combine and transform the produced results before they are handled by the result handlers.

Initial trigger

Note that the validation is not triggered when the validator is constructed, simply because it may not be appropriate in all cases to have the validation performed at construction time: most of the time, the whole panel is not yet fully constructed, or has no parent, etc.. However, it you want to trigger the validation upon construction, you may trigger it manually. For instance:

on(new JTextFieldDocumentChangeTrigger(nameTextField)) // On any change in the input field,
  .read(new JTextFieldTextProvider(nameTextField))     // get its text,
  .check(new StringNotEmptyRule())                     // make sure the text is not empty,
  .handleWith(new IconBooleanFeedback(nameTextField))  // show the result using an icon in the corner.
  .trigger();                                          // Trigger validation now.

Alternatively, you may want to trigger the validation manually when you find it appropriate. In order to do so, just a ManualTrigger to the validator. For instance:

ManualTrigger manualTrigger = new ManualTrigger();
on(manualTrigger)                                         // On manual trigger,
  .on(new JTextFieldDocumentChangeTrigger(nameTextField)) // and any change in the input field,
  .read(new JTextFieldTextProvider(nameTextField))        // get its text,
  .check(new StringNotEmptyRule())                        // make sure the text is not empty,
  .handleWith(new IconBooleanFeedback(nameTextField));    // show the result using an icon in the corner.
...
manualTrigger.trigger();

Validation of multiple independent fields

You may need to validate a form with multiple independent fields, but still need a conditional logic to enable/disable some Apply button, for example.

In order to do that, you may just create a validator for each field, and an additional validator that will collect all the results from the other validators and make sure that they are all valid before enabling the Apply button. The global validator will need to be triggered whenever the individual validators produce a result, will need to get these independent results and combine them into an overall result, and enable or disable the Apply button accordingly.

This can be achieved by using the ResultCollector class. A ResultCollector serves as a result handler for an individual validator, and as a trigger and data provider for the global validator.

JTextField nameTextField = new JTextField();
JCheckBox agreeCheckBox = new JCheckBox("I agree");
JButton applyButton = new JButton("Apply");
ManualTrigger initialTrigger = new ManualTrigger();
...
// Create validator for the Name textfield
ResultCollector nameResultCollector = new ResultCollector();
on(initialTrigger)                                    // On initial manual trigger (see later),
  .on(new JTextFieldDocumentChange(nameTextField))    // and on any change in the input field,
  .read(new JTextFieldTextProvider(nameTextField))    // get its text,
  .check(new StringNotEmptyRule())                    // make sure the text is not empty,
  .handleWith(new IconBooleanFeedback(nameTextField)) // show the result using an icon in the corner,
  .handleWith(nameResultCollector);                   // and collect the result for the global validation.

// Create validator the "I agree" checkbox
ResultCollector agreeResultCollector = new ResultCollector();
on(initialTrigger)                                     // On initial manual trigger (see later),
  .on(new JCheckBoxModelChangedTrigger(agreeCheckBox)) // and on any change in the checkbox,
  .read(new JCheckBoxValueProvider(agreeCheckBox))     // get its selection state,
  .check(new EqualsRule(true))                         // make sure it is selected,
  .handleWith(nameResultCollector);                    // and collect the result for the global validation.

// Create global validator responsible for the enabling/disabling of the Apply button
collect(nameResultCollector)        // On any validation result of the name textfield,
  .collect(agreeResultCollector)    // and on any validation result of the "I agree" checkbox,
  .check(new AndBooleanRule())      // get both results and combine them using the AND operator,
  .handleWith(new ComponentEnablingBooleanResultHandler(applyButton)); // and enable button if true.

// Perform initial validation and initial enabling/disabling of the Apply button
initialTrigger.trigger();

Property-based conditional logic

TBC...

Going further

For more examples of input validation in Swing and JavaFX, you may check the validationframework-demo module in the source code.

Also, you may refer to the Quick Reference pages for the Core, Swing and JavaFX modules for a list of available triggers, data providers, rules, result handlers, and transformers.

Finally, you may just explore the source code to see what the validation framework offers in the validationframework-core, validationframework-swing and validationframework-javafx modules.