Provided by: libdeclare-constraints-simple-perl_0.03-1.1_all bug

NAME

       Declare::Constraints::Simple - Declarative Validation of Data Structures

SYNOPSIS

         use Declare::Constraints::Simple-All;

         my $profile = IsHashRef(
                           -keys   => HasLength,
                           -values => IsArrayRef( IsObject ));

         my $result1 = $profile->(undef);
         print $result1->message, "\n";    # 'Not a HashRef'

         my $result2 = $profile->({foo => [23]});

         print $result2->message, "\n";    # 'Not an Object'

         print $result2->path, "\n";
                           # 'IsHashRef[val foo].IsArrayRef[0].IsObject'

DESCRIPTION

       The main purpose of this module is to provide an easy way to build a profile to validate a
       data structure. It does this by giving you a set of declarative keywords in the importing
       namespace.

USAGE

       This is just a brief intro. For details read the documents mentioned in "SEE ALSO".

   Constraint Import
         use Declare::Constraints::Simple-All;

       The above command imports all constraint generators in the library into the current
       namespace. If you want only a selection, use "only":

         use Declare::Constraints::Simple
             Only => qw(IsInt Matches And);

       You can find all constraints (and constraint-like generators, like operators. In fact,
       "And" above is an operator. They're both implemented equally, so the distinction is a
       merely philosophical one) documented in the Declare::Constraints::Simple::Library pod. In
       that document you will also find the exact parameters for their usage, so this here is
       just a brief Intro and not a coverage of all possibilities.

   Building a Profile
       You can use these constraints by building a tree that describes what data structure you
       expect. Every constraint can be used as sub-constraint, as parent, if it accepts other
       constraints, or stand-alone. If you'd just say

         my $check = IsInt;
         print "yes!\n" if $check->(23);

       it will work too. This also allows predefining tree segments, and nesting them:

         my $id_to_objects = IsArrayRef(IsObject);

       Here $id_to_objects would give it's OK on an array reference containing a list of objects.
       But what if we now decide that we actually want a hashref containing two lists of objects?
       Behold:

         my $object_lists =
           IsHashRef( HasAllKeys( qw(good bad) ),
                      OnHashKeys( good => $id_to_objects,
                                  bad  => $id_to_objects ));

       As you can see, constraints like "IsArrayRef" and "IsHashRef" allow you to apply
       constraints to their keys and values. With this, you can step down in the data structure.

   Applying a Profile to a Data Structure
       Constraints return just code references that can be applied to one value (and only one
       value) like this:

         my $result = $object_lists->($value);

       After this call $result contains a Declare::Constraints::Simple::Result object. The first
       think one wants to know is if the validation succeeded:

         if ($result->is_valid) { ... }

       This is pretty straight forward. To shorten things the result object also overloads it's
       "bool"ean context. This means you can alternatively just say

         if ($result) { ... }

       However, if the result indicates a invalid data structure, we have a few options to find
       out what went wrong. There's a human parsable message in the "message" accessor. You can
       override these by forcing it to a message in a subtree with the "Message" declaration. The
       "stack" contains the name of the chain of constraints up to the point of failure.

       You can use the "path" accessor for a joined string path representing the stack.

   Creating your own Libraries
       You can declare a package as a library with

         use Declare::Constraints::Simple-Library;

       which will install the base class and helper methods to define constraints. For a complete
       list read the documentation in Declare::Constraints::Simple::Library::Base. You can use
       other libraries as base classes to include their constraints in your export possibilities.
       This means that with a package setup like

         package MyLibrary;
         use warnings;
         use strict;

         use Declare::Constraints::Simple-Library;
         use base 'Declare::Constraints::Simple::Library';

         constraint 'MyConstraint',
           sub { return _result(($_[0] >= 12), 'Value too small') };

         1;

       you can do

         use MyLibrary-All;

       and have all constraints, from the default library and yours from above, installed into
       your requesting namespace. You can override a constraint just by redeclaring it in a
       subclass.

   Scoping
       Sometimes you want to validate parts of a data structure depending on another part of it.
       As of version 2.0 you can declare scopes and store results in them. Here is a complete
       example:

         my $constraint =
           Scope('foo',
             And(
               HasAllKeys( qw(cmd data) ),
               OnHashKeys(
                 cmd => Or( SetResult('foo', 'cmd_a',
                              IsEq('FOO_A')),
                            SetResult('foo', 'cmd_b',
                              IsEq('FOO_B')) ),
                 data => Or( And( IsValid('foo', 'cmd_a'),
                                  IsArrayRef( IsInt )),
                             And( IsValid('foo', 'cmd_b'),
                                  IsRegex )) )));

       This profile would accept a hash references with the keys "cmd" and "data". If "cmd" is
       set to "FOO_A", then "data" has to be an array ref of integers. But if "cmd" is set to
       "FOO_B", a regular expression is expected.

SEE ALSO

       Declare::Constraints::Simple::Library, Declare::Constraints::Simple::Result,
       Declare::Constraints::Simple::Base, Module::Install

REQUIRES

       Carp::Clan, aliased, Class::Inspector, Scalar::Util, overload and Test::More (for build).

TODO

       •   Examples.

       •   A list of questions that might come up, together with their answers.

       •   A "Custom" constraint that takes a code reference.

       •   Create stack objects that stringify to the current form, but can hold more data.

       •   Give the "Message" constraint the ability to get the generated constraint inserted in
           the message. A possibility would be to replace __Value__ and __Message__. It might
           also accept code references, which return strings.

       •   Allow the "IsCodeRef" constraint to accept further constraints. One might like to
           check, for example, the refaddr of a closure.

       •   A "Captures" constraint that takes a regex and can apply other constraints to the
           matches.

       •   ???

       •   Profit.

INSTALLATION

         perl Makefile.PL
         make
         make test
         make install

       For details read Module::Install.

AUTHOR

       Robert 'phaylon' Sedlacek "<phaylon@dunkelheit.at>"

LICENSE AND COPYRIGHT

       This module is free software, you can redistribute it and/or modify it under the same
       terms as perl itself.