Montag, 6. Oktober 2014

BARACUS from Scratch - Part 10 - Writing custom validators

Table of Contents

Previous Tutorial :Using interfaces & implementations

You can download the sourcecode for this demo here

In this tutorial I will explain you how create custom validation objects to be used within your application. This enables you to have your application shipped with customized validators to fit your personal needs. This tutorial is basing on the FormValidation-Tutorial I published earlier.

Step 1 - Define validator


We want to add a constraint for defining names to our software. A name must start with a capital one letter and continue with zero or more small caps letters. This can be achieved by matching this java regex pattern [A-Z]+[a-z]*. So at first, we will define the constraint message plus the class:

strings.xml:

    <string name="nameViolation">Bad string format. Must be lowercase with starting capital letter</string>


public class NameValidator extends AbstractValidator<String>{



    static final String pattern = "[A-Z]+[a-z]*"; // Will allow John but neither JOHN nor john



    @Override

    public boolean validate(ConstrainedView<String> view) {

        return view.getCurrentValue().matches(pattern);

    }



    @Override

    public int getMessageId() {

        return R.string.nameViolation;

    }

}



Step 2 - Register validator


You must register the validator by-name in order to be able to use it. The ValidationRegistry internally used in the BARACUS framework is a managed bean which registers the validators in a postConstruct method. But since this validator is a more or less invariant item, we will add it to the context after the context has been built. This is necessary since the ValidationFactory has not been setup in the Context-initialization phase.

In a prior tutorial we have created an after-context-init trigger (AfterContextInitialized). This is the correct place to add the validator to the registry because in the ApplicationContext's init phase the internal ValidationFactory (which is also a bean) still is null.

So we add the validator to the context :

public class AfterContextInitialized implements ApplicationContextInitializer {

    ...

    @Override

    public void afterContextIsBuilt() {

        if (reinit) {

            ...

            ApplicationContext.registerValidator(new NameValidator());



        }

    }

}



Step 3 - Wire the validator


We are almost done. You simply have to wire the validator by-name inside the desired layout xml file. In our case, we want to have this validator added to the existing validator in the customer_editor.xml :

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

              xmlns:app="http://schemas.android.com/apk/res-auto"

              android:orientation="vertical"

              android:layout_width="match_parent"

              android:layout_height="match_parent">

    ...

    <net.mantucon.baracus.ui.ConstrainedEditText android:id="@+id/txtCustomerFirstName"

                                                 android:layout_width="fill_parent"

                                                 android:layout_height="wrap_content"

                                                 app:validatedBy="stringNotEmpty,nameValidator"

            />

    ...

    <net.mantucon.baracus.ui.ConstrainedEditText android:id="@+id/txtCustomerLastName"

                                                 android:layout_width="fill_parent"

                                                 android:layout_height="wrap_content"

                                                 app:validatedBy="stringNotEmpty,nameValidator"

            />

    ...

</LinearLayout>


The validators are applied in the direction you add them to the list.

Conclusion


Writing custom validators is easy. They make the app design more easy and efficient and allow you to have very specific rules beeing applied to user's form data. But that's not all. You even can have more sophisticated constraints; since you can access any bean through your ApplicationContest statically you even can have database driven checks.

Next Tutorial : Advanced Logging (coming up)

Keine Kommentare:

Kommentar veröffentlichen