# NAME

Validation::Class::Document - Data Validation for Hierarchical Data

# VERSION

version 0.000013

# SYNOPSIS

    package MyApp::Person;

    use Validation::Class::Document;

    field  'id' => {
        mixin      => [':str'],
        filters    => ['numeric'],
        max_length => 2,
    };

    field  'name' => {
        mixin      => [':str'],
        pattern    => qr/^[A-Za-z ]+$/,
        max_length => 20,
    };

    field  'rating' => {
        mixin      => [':str'],
        pattern    => qr/^\-?\d+$/,
    };

    field  'tag' => {
        mixin      => [':str'],
        pattern    => qr/^(?!evil)\w+/,
        max_length => 20,
    };

    document 'person' => {
        'id'                             => 'id',
        'name'                           => 'name',
        'company.name'                   => 'name',
        'company.supervisor.name'        => 'name',
        'company.supervisor.rating.@.*'  => 'rating',
        'company.tags.@'                 => 'name'
    };

    package main;

    my $data = {
        "id"      => "1234-ABC",
        "name"    => "Anita Campbell-Green",
        "title"   => "Designer",
        "company" => {
            "name"       => "House of de Vil",
            "supervisor" => {
                "name"   => "Cruella de Vil",
                "rating" => [
                    {   "support"  => -9,
                        "guidance" => -9
                    }
                ]
            },
            "tags" => [
                "evil",
                "cruelty",
                "dogs"
            ]
        },
    };

    my $person = MyApp::Person->new;

    unless ($person->validate_document(person => $data)) {
        warn $person->errors_to_string if $person->error_count;
    }

# DESCRIPTION

Validation::Class::Document inherits all functionality from [Validation::Class](http://search.cpan.org/perldoc?Validation::Class)
and implements additional abilities documented as follows.

This module allows you to validate hierarchical structures using the
[Validation::Class](http://search.cpan.org/perldoc?Validation::Class) framework. This is an experimental yet highly promising
approach toward the consistent processing of nested structures. The current
interface is not expected to change. This module was inspired by
[MooseX::Validation::Doctypes](http://search.cpan.org/perldoc?MooseX::Validation::Doctypes). Gone are the days of data submitted to an
application in key/value form and especially in regards to the increasing demand
for communication between applications, serializing and transmitting structured
data over a network connection.

# OVERVIEW

Validation::Class::Document exports the document (or dom) keyword which allows
you to pre-define/configure your path matching rules for your data structure.
The "path matching rules", which is actually a custom object notation, referred
to as the document notation, can be thought of as a kind-of simplified regular
expression which is executed against the flattened data structure. The following
are a few general use-cases:

    # given the data structure
    {
        "id": "1234-A",
        "name": {
            "first_name" : "Bob",
            "last_name"  : "Smith",
         },
        "title": "CIO",
        "friends" : [],
    }

    # select id to validate against the string rules
    document 'foobar'  =>
        { 'id' => 'string' };

    # select name -> first_name/last_name to validate against the string rules
    document 'foobar'  =>
        {'name.first_name' => 'string', 'name.last_name' => 'string'};

    # or
    document 'foobar'  =>
        {'name.*_name' => 'string'};

    # select each element in friends to validate against the string rules
    document 'foobar'  =>
        { 'friends.@'  => 'string' };

    # or select an element of a hashref in each element in friends to validate
    document 'foobar'  =>
        { 'friends.@.name' => 'string' };

The document declaration's keys should follow the aforementioned document
notation scheme and it's values should be strings which correspond to the names
of fields (or other document declarations) that will be used to preform the
data validation. It is possible to combine document declarations to validate
hierarchical data that contains data structures matching one or more document
patterns. The following is an example of what that might look like.

    package MyApp::Person;

    use Validation::Class::Document;

    field  'name' => {
        mixin      => [':str'],
        pattern    => qr/^[A-Za-z ]+$/,
        max_length => 20,
    };

    document 'friend' => {
        'name' => 'name'
    };

    document 'person' => {
        'name' => 'name',
        'friends.@' => 'friend'
    };

    package main;

    my $data = {
        "name"   => "Anita Campbell-Green",
        "friends" => [
            { "name" => "Horace" },
            { "name" => "Skinner" },
            { "name" => "Alonzo" },
            { "name" => "Frederick" },
        ],
    };

    my $person = MyApp::Person->new;

    unless ($person->validate_document(person => $data)) {
        warn $person->errors_to_string if $person->error_count;
    }

# METHODS

## validate\_document

The validate\_document method (or document\_validates) is used to validate the
specified hierarchical data against the specified document declaration. This is
extremely valuable for validating serialized messages passed between machines.
This method requires two arguments, the name of the document declaration to be
used, and the data to be validated which should be submitted in the form of a
hashref. Additionally, you may submit options in the form of a hashref to
further control the validation process. The following is an example of this.

    # the prune option removes non-matching parameters (nodes)
    my $boolean = $self->validate_document(foobar => $data, { prune => 1 });

# AUTHOR

Al Newkirk <anewkirk@ana.io>

# COPYRIGHT AND LICENSE

This software is copyright (c) 2013 by Al Newkirk.

This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
