[Moose-commits] r7884 - in MooseX-Types-Structured/tags: . 0.10 0.10/lib/MooseX/Meta/TypeConstraint 0.10/lib/MooseX/Types 0.10/t

jnapiorkowski at code2.0beta.co.uk jnapiorkowski at code2.0beta.co.uk
Thu Apr 2 16:10:45 BST 2009


Author: jnapiorkowski
Date: 2009-04-02 08:10:44 -0700 (Thu, 02 Apr 2009)
New Revision: 7884

Added:
   MooseX-Types-Structured/tags/0.10/
   MooseX-Types-Structured/tags/0.10/Changes
   MooseX-Types-Structured/tags/0.10/lib/MooseX/Meta/TypeConstraint/Structured.pm
   MooseX-Types-Structured/tags/0.10/lib/MooseX/Types/Structured.pm
   MooseX-Types-Structured/tags/0.10/t/12-error.t
Removed:
   MooseX-Types-Structured/tags/0.10/Changes
   MooseX-Types-Structured/tags/0.10/lib/MooseX/Meta/TypeConstraint/Structured.pm
   MooseX-Types-Structured/tags/0.10/lib/MooseX/Types/Structured.pm
   MooseX-Types-Structured/tags/0.10/t/12-error.t
Log:
tagged for release

Copied: MooseX-Types-Structured/tags/0.10 (from rev 7879, MooseX-Types-Structured/trunk)


Property changes on: MooseX-Types-Structured/tags/0.10
___________________________________________________________________
Name: svn:mergeinfo
   + 
Name: svk:merge
   + 3efe9002-19ed-0310-8735-a98156148065:/MooseX-Types-Structured/tags/0.02:6432

Deleted: MooseX-Types-Structured/tags/0.10/Changes
===================================================================
--- MooseX-Types-Structured/trunk/Changes	2009-04-01 03:11:50 UTC (rev 7879)
+++ MooseX-Types-Structured/tags/0.10/Changes	2009-04-02 15:10:44 UTC (rev 7884)
@@ -1,65 +0,0 @@
-Revision history for MooseX-Types-Structured
-
-0.09    07 March 2009
-        - I guess we don't support the "subtype MyType, [TypeConstraint]" syntax
-          anymore.  Changed the recursion test to reflect that, which should fix
-          my 100% fail rate :)
-0.08    06 March 2009
-        - New Feature: slurpy method for when you want a structured type
-          constraint that allows trailing arguments of indeterminate length.
-          Please see the documentation and the '11-overflow.t' test for more.
-        - Documentation for above as well as a bunch of POD cleanups, spell
-          checks and improvements to formatting.
-        - Stevan Little submitted a sweet  update to the '10-recursion.t' test
-          that blows my mind.  Will probably form the core of a to be done set
-          of cookbook style PODs.  Worth looking at.
-        - First step at improving the error message you get when validation
-          fails.  A full error stacktrace is not in this release, but you now
-          at least get to see part of the offending value.
-
-0.07    09 December 2008
-        - Fixed typo in previous changelog
-        - documentation improvements and updates
-        - increased version requirement for MooseX::Types so that we can take
-          advantage of the recursion support added.
-        - added test for recursion.
-
-0.06    06 December 2008
-        - Added a 'helper' type constraint called Optional. See docs for more.
-        - added lots of tests to cover the API better, coverage and fixes for
-          the ->parameterize method in particular have been clarified.
-        - changes so that the type contraints are more forgiving when null
-          values appear in method calls.
-        - used ->make_immutable which should speed up the constraints.
-        - removed some unnecessary calls to use Moose when I wasn't using Moose.
-        - lots of little code cleanup work and more internal documentation.
-        - This version requires a newer Moose than previous versions.  The
-          Makefile.PL has been updated to reflect this.  This is a required
-          update.
-        
-0.05    08 November 2008
-        - Fixed some wackiness in the documentation.
-        
-0.04    07 November 2008
-        - Bumped minimum required versions of Moose and MooseX-Types to solve
-          problem with overloading and type constraint names (issue resolved
-          in Moose code.)
-        - Changed the way the required Perl version string is used to increase
-          compatibility and lowered minimum required Perl
-
-0.03    29 October 2008
-        - Fixed incorrect Perl version string (rafl)
-        - hide the meta classes from pause.  This should clarify which POD is
-          the right one to read and also I want to discourage people from
-          subclassing that stuff since it will probably change
-        - various documentation cleanup
-        - new test 'example.t' with runable versions of the code in the example
-          POD section.
-        
-0.02    28 October 2008
-        - cleared up some typos in the test suite
-        - Fixed some POD formatting issues, mostly some dumb tabs I ended up
-          with when I switched editors.  Added a bit more documentation
-        
-0.01    27 October 2008
-        - Completed basic requirements, documentation and tests.

Copied: MooseX-Types-Structured/tags/0.10/Changes (from rev 7883, MooseX-Types-Structured/trunk/Changes)
===================================================================
--- MooseX-Types-Structured/tags/0.10/Changes	                        (rev 0)
+++ MooseX-Types-Structured/tags/0.10/Changes	2009-04-02 15:10:44 UTC (rev 7884)
@@ -0,0 +1,73 @@
+Revision history for MooseX-Types-Structured
+
+0.10    02 April 2009
+        - Minor documentation grammar fixes and one major example error fixed
+        - Much improved error reporting.  Now we return the 'internal' error
+          that kicked a validation failure.  It's still best to use this for
+          debugging rather than for actual user error messages, since I think
+          we are rapidly approaching a need for Moose constraints needing more
+          in the error and message reporting.
+        - Documentation for the above.
+0.09    07 March 2009
+        - I guess we don't support the "subtype MyType, [TypeConstraint]" syntax
+          anymore.  Changed the recursion test to reflect that, which should fix
+          my 100% fail rate :)
+0.08    06 March 2009
+        - New Feature: slurpy method for when you want a structured type
+          constraint that allows trailing arguments of indeterminate length.
+          Please see the documentation and the '11-overflow.t' test for more.
+        - Documentation for above as well as a bunch of POD cleanups, spell
+          checks and improvements to formatting.
+        - Stevan Little submitted a sweet  update to the '10-recursion.t' test
+          that blows my mind.  Will probably form the core of a to be done set
+          of cookbook style PODs.  Worth looking at.
+        - First step at improving the error message you get when validation
+          fails.  A full error stacktrace is not in this release, but you now
+          at least get to see part of the offending value.
+
+0.07    09 December 2008
+        - Fixed typo in previous changelog
+        - documentation improvements and updates
+        - increased version requirement for MooseX::Types so that we can take
+          advantage of the recursion support added.
+        - added test for recursion.
+
+0.06    06 December 2008
+        - Added a 'helper' type constraint called Optional. See docs for more.
+        - added lots of tests to cover the API better, coverage and fixes for
+          the ->parameterize method in particular have been clarified.
+        - changes so that the type contraints are more forgiving when null
+          values appear in method calls.
+        - used ->make_immutable which should speed up the constraints.
+        - removed some unnecessary calls to use Moose when I wasn't using Moose.
+        - lots of little code cleanup work and more internal documentation.
+        - This version requires a newer Moose than previous versions.  The
+          Makefile.PL has been updated to reflect this.  This is a required
+          update.
+        
+0.05    08 November 2008
+        - Fixed some wackiness in the documentation.
+        
+0.04    07 November 2008
+        - Bumped minimum required versions of Moose and MooseX-Types to solve
+          problem with overloading and type constraint names (issue resolved
+          in Moose code.)
+        - Changed the way the required Perl version string is used to increase
+          compatibility and lowered minimum required Perl
+
+0.03    29 October 2008
+        - Fixed incorrect Perl version string (rafl)
+        - hide the meta classes from pause.  This should clarify which POD is
+          the right one to read and also I want to discourage people from
+          subclassing that stuff since it will probably change
+        - various documentation cleanup
+        - new test 'example.t' with runable versions of the code in the example
+          POD section.
+        
+0.02    28 October 2008
+        - cleared up some typos in the test suite
+        - Fixed some POD formatting issues, mostly some dumb tabs I ended up
+          with when I switched editors.  Added a bit more documentation
+        
+0.01    27 October 2008
+        - Completed basic requirements, documentation and tests.

Deleted: MooseX-Types-Structured/tags/0.10/lib/MooseX/Meta/TypeConstraint/Structured.pm
===================================================================
--- MooseX-Types-Structured/trunk/lib/MooseX/Meta/TypeConstraint/Structured.pm	2009-04-01 03:11:50 UTC (rev 7879)
+++ MooseX-Types-Structured/tags/0.10/lib/MooseX/Meta/TypeConstraint/Structured.pm	2009-04-02 15:10:44 UTC (rev 7884)
@@ -1,249 +0,0 @@
-package ## Hide from PAUSE
- MooseX::Meta::TypeConstraint::Structured;
-
-use Moose;
-use Devel::PartialDump;
-use Moose::Util::TypeConstraints ();
-use MooseX::Meta::TypeCoercion::Structured;
-extends 'Moose::Meta::TypeConstraint';
-
-=head1 NAME
-
-MooseX::Meta::TypeConstraint::Structured - Structured type constraints.
-
-=head1 DESCRIPTION
-
-A structure is a set of L<Moose::Meta::TypeConstraint> that are 'aggregated' in
-such a way as that they are all applied to an incoming list of arguments.  The
-idea here is that a Type Constraint could be something like, "An Int followed by
-an Int and then a Str" and that this could be done so with a declaration like:
-
-    Tuple[Int,Int,Str]; ## Example syntax
-    
-So a structure is a list of Type constraints (the "Int,Int,Str" in the above
-example) which are intended to function together.
-
-=head1 ATTRIBUTES
-
-This class defines the following attributes.
-
-=head2 type_constraints
-
-A list of L<Moose::Meta::TypeConstraint> objects.
-
-=cut
-
-has 'type_constraints' => (
-    is=>'ro',
-    isa=>'Ref',
-    predicate=>'has_type_constraints',
-);
-
-=head2 constraint_generator
-
-A subref or closure that contains the way we validate incoming values against
-a set of type constraints.
-
-=cut
-
-has 'constraint_generator' => (
-    is=>'ro',
-    isa=>'CodeRef',
-    predicate=>'has_constraint_generator',
-);
-
-=head1 METHODS
-
-This class defines the following methods.
-
-=head2 new
-
-Initialization stuff.
-
-=cut
-
-around 'new' => sub {
-    my ($new, $class, @args)  = @_;
-    my $self = $class->$new(@args);
-    $self->coercion(MooseX::Meta::TypeCoercion::Structured->new(
-        type_constraint => $self,
-    ));
-    return $self;
-};
-
-=head2 generate_constraint_for ($type_constraints)
-
-Given some type constraints, use them to generate validation rules for an ref
-of values (to be passed at check time)
-
-=cut
-
-sub generate_constraint_for {
-    my ($self, $type_constraints) = @_;
-    return sub {
-        my (@args) = @_;
-        my $constraint_generator = $self->constraint_generator;
-        return $constraint_generator->($type_constraints, @args);
-    };
-}
-
-=head2 parameterize (@type_constraints)
-
-Given a ref of type constraints, create a structured type.
-
-=cut
-
-sub parameterize {
-    
-    my ($self, @type_constraints) = @_;
-    my $class = ref $self;
-    my $name = $self->name .'['. join(',', map {"$_"} @type_constraints) .']';
-    my $constraint_generator = $self->__infer_constraint_generator;
-
-    return $class->new(
-        name => $name,
-        parent => $self,
-        type_constraints => \@type_constraints,
-        constraint_generator => $constraint_generator,
-    );
-}
-
-=head2 __infer_constraint_generator
-
-This returns a CODEREF which generates a suitable constraint generator.  Not
-user servicable, you'll never call this directly.
-
-=cut
-
-sub __infer_constraint_generator {
-    my ($self) = @_;
-    if($self->has_constraint_generator) {
-        return $self->constraint_generator;
-    } else {
-        return sub {
-            ## I'm not sure about this stuff but everything seems to work
-            my $tc = shift @_;
-            my $merged_tc = [@$tc, @{$self->parent->type_constraints}];
-            $self->constraint->($merged_tc, @_);            
-        };
-    }    
-}
-
-=head2 compile_type_constraint
-
-hook into compile_type_constraint so we can set the correct validation rules.
-
-=cut
-
-around 'compile_type_constraint' => sub {
-    my ($compile_type_constraint, $self, @args) = @_;
-    
-    if($self->has_type_constraints) {
-        my $type_constraints = $self->type_constraints;
-        my $constraint = $self->generate_constraint_for($type_constraints);
-        $self->_set_constraint($constraint);        
-    }
-
-    return $self->$compile_type_constraint(@args);
-};
-
-=head2 create_child_type
-
-modifier to make sure we get the constraint_generator
-
-=cut
-
-around 'create_child_type' => sub {
-    my ($create_child_type, $self, %opts) = @_;
-    return $self->$create_child_type(
-        %opts,
-        constraint_generator => $self->__infer_constraint_generator,
-    );
-};
-
-=head2 is_a_type_of
-
-=head2 is_subtype_of
-
-=head2 equals
-
-Override the base class behavior.
-
-=cut
-
-sub equals {
-    my ( $self, $type_or_name ) = @_;
-    my $other = Moose::Util::TypeConstraints::find_type_constraint($type_or_name);
-
-    return unless $other->isa(__PACKAGE__);
-    
-    return (
-        $self->type_constraints_equals($other)
-            and
-        $self->parent->equals( $other->parent )
-    );
-}
-
-=head2 type_constraints_equals
-
-Checks to see if the internal type contraints are equal.
-
-=cut
-
-sub type_constraints_equals {
-    my ($self, $other) = @_;
-    my @self_type_constraints = @{$self->type_constraints||[]};
-    my @other_type_constraints = @{$other->type_constraints||[]};
-    
-    ## Incoming ay be either arrayref or hashref, need top compare both
-    while(@self_type_constraints) {
-        my $self_type_constraint = shift @self_type_constraints;
-        my $other_type_constraint = shift @other_type_constraints
-         || return; ## $other needs the same number of children.
-        
-        if( ref $self_type_constraint) {
-            $self_type_constraint->equals($other_type_constraint)
-             || return; ## type constraints obviously need top be equal
-        } else {
-            $self_type_constraint eq $other_type_constraint
-             || return; ## strings should be equal
-        }
-
-    }
-    
-    return 1; ##If we get this far, everything is good.
-}
-
-=head2 get_message
-
-Give you a better peek into what's causing the error.  For now we stringify the
-incoming deep value with L<Devel::PartialDump> and pass that on to either your
-custom error message or the default one.  In the future we'll try to provide a
-more complete stack trace of the actual offending elements
-
-=cut
-
-around 'get_message' => sub {
-    my ($get_message, $self, $value) = @_;
-    my $new_value = Devel::PartialDump::dump($value);
-    return $self->$get_message($new_value);
-};
-
-=head1 SEE ALSO
-
-The following modules or resources may be of interest.
-
-L<Moose>, L<Moose::Meta::TypeConstraint>
-
-=head1 AUTHOR
-
-John Napiorkowski, C<< <jjnapiork at cpan.org> >>
-
-=head1 COPYRIGHT & LICENSE
-
-This program is free software; you can redistribute it and/or modify
-it under the same terms as Perl itself.
-
-=cut
-
-__PACKAGE__->meta->make_immutable;
\ No newline at end of file

Copied: MooseX-Types-Structured/tags/0.10/lib/MooseX/Meta/TypeConstraint/Structured.pm (from rev 7883, MooseX-Types-Structured/trunk/lib/MooseX/Meta/TypeConstraint/Structured.pm)
===================================================================
--- MooseX-Types-Structured/tags/0.10/lib/MooseX/Meta/TypeConstraint/Structured.pm	                        (rev 0)
+++ MooseX-Types-Structured/tags/0.10/lib/MooseX/Meta/TypeConstraint/Structured.pm	2009-04-02 15:10:44 UTC (rev 7884)
@@ -0,0 +1,274 @@
+package ## Hide from PAUSE
+ MooseX::Meta::TypeConstraint::Structured;
+
+use Moose;
+use Devel::PartialDump;
+use Moose::Util::TypeConstraints ();
+use MooseX::Meta::TypeCoercion::Structured;
+extends 'Moose::Meta::TypeConstraint';
+
+=head1 NAME
+
+MooseX::Meta::TypeConstraint::Structured - Structured type constraints.
+
+=head1 DESCRIPTION
+
+A structure is a set of L<Moose::Meta::TypeConstraint> that are 'aggregated' in
+such a way as that they are all applied to an incoming list of arguments.  The
+idea here is that a Type Constraint could be something like, "An Int followed by
+an Int and then a Str" and that this could be done so with a declaration like:
+
+    Tuple[Int,Int,Str]; ## Example syntax
+    
+So a structure is a list of Type constraints (the "Int,Int,Str" in the above
+example) which are intended to function together.
+
+=head1 ATTRIBUTES
+
+This class defines the following attributes.
+
+=head2 type_constraints
+
+A list of L<Moose::Meta::TypeConstraint> objects.
+
+=cut
+
+has 'type_constraints' => (
+    is=>'ro',
+    isa=>'Ref',
+    predicate=>'has_type_constraints',
+);
+
+=head2 constraint_generator
+
+A subref or closure that contains the way we validate incoming values against
+a set of type constraints.
+
+=cut
+
+has 'constraint_generator' => (
+    is=>'ro',
+    isa=>'CodeRef',
+    predicate=>'has_constraint_generator',
+);
+
+=head1 METHODS
+
+This class defines the following methods.
+
+=head2 new
+
+Initialization stuff.
+
+=cut
+
+around 'new' => sub {
+    my ($new, $class, @args)  = @_;
+    my $self = $class->$new(@args);
+    $self->coercion(MooseX::Meta::TypeCoercion::Structured->new(
+        type_constraint => $self,
+    ));
+    return $self;
+};
+
+=head2 validate
+
+Messing with validate so that we can support niced error messages.
+=cut
+
+override 'validate' => sub {
+    my ($self, @args) = @_;
+    my $compiled_type_constraint = $self->_compiled_type_constraint;
+    my $message = bless {message=>undef}, 'MooseX::Types::Structured::Message';
+    my $result = $compiled_type_constraint->(@args, $message);
+
+    if($result) {
+        return $result;
+    } else {
+        my $args = Devel::PartialDump::dump(@args);
+        if(my $message = $message->{message}) {
+            return $self->get_message("$args, Internal Validation Error is: $message");
+        } else {
+            return $self->get_message($args);
+        }
+    }
+};
+
+=head2 generate_constraint_for ($type_constraints)
+
+Given some type constraints, use them to generate validation rules for an ref
+of values (to be passed at check time)
+
+=cut
+
+sub generate_constraint_for {
+    my ($self, $type_constraints) = @_;
+    return sub {
+        my $arg =  shift @_;
+        my $constraint_generator = $self->constraint_generator;
+        my $result = $constraint_generator->($type_constraints, $arg, $_[0]);
+        return $result;
+    };
+}
+
+=head2 parameterize (@type_constraints)
+
+Given a ref of type constraints, create a structured type.
+
+=cut
+
+sub parameterize {
+    
+    my ($self, @type_constraints) = @_;
+    my $class = ref $self;
+    my $name = $self->name .'['. join(',', map {"$_"} @type_constraints) .']';
+    my $constraint_generator = $self->__infer_constraint_generator;
+
+    return $class->new(
+        name => $name,
+        parent => $self,
+        type_constraints => \@type_constraints,
+        constraint_generator => $constraint_generator,
+    );
+}
+
+=head2 __infer_constraint_generator
+
+This returns a CODEREF which generates a suitable constraint generator.  Not
+user servicable, you'll never call this directly.
+
+=cut
+
+sub __infer_constraint_generator {
+    my ($self) = @_;
+    if($self->has_constraint_generator) {
+        return $self->constraint_generator;
+    } else {
+        return sub {
+            ## I'm not sure about this stuff but everything seems to work
+            my $tc = shift @_;
+            my $merged_tc = [@$tc, @{$self->parent->type_constraints}];
+            $self->constraint->($merged_tc, @_);            
+        };
+    }    
+}
+
+=head2 compile_type_constraint
+
+hook into compile_type_constraint so we can set the correct validation rules.
+
+=cut
+
+around 'compile_type_constraint' => sub {
+    my ($compile_type_constraint, $self, @args) = @_;
+    
+    if($self->has_type_constraints) {
+        my $type_constraints = $self->type_constraints;
+        my $constraint = $self->generate_constraint_for($type_constraints);
+        $self->_set_constraint($constraint);        
+    }
+
+    return $self->$compile_type_constraint(@args);
+};
+
+=head2 create_child_type
+
+modifier to make sure we get the constraint_generator
+
+=cut
+
+around 'create_child_type' => sub {
+    my ($create_child_type, $self, %opts) = @_;
+    return $self->$create_child_type(
+        %opts,
+        constraint_generator => $self->__infer_constraint_generator,
+    );
+};
+
+=head2 is_a_type_of
+
+=head2 is_subtype_of
+
+=head2 equals
+
+Override the base class behavior.
+
+=cut
+
+sub equals {
+    my ( $self, $type_or_name ) = @_;
+    my $other = Moose::Util::TypeConstraints::find_type_constraint($type_or_name);
+
+    return unless $other->isa(__PACKAGE__);
+    
+    return (
+        $self->type_constraints_equals($other)
+            and
+        $self->parent->equals( $other->parent )
+    );
+}
+
+=head2 type_constraints_equals
+
+Checks to see if the internal type contraints are equal.
+
+=cut
+
+sub type_constraints_equals {
+    my ($self, $other) = @_;
+    my @self_type_constraints = @{$self->type_constraints||[]};
+    my @other_type_constraints = @{$other->type_constraints||[]};
+    
+    ## Incoming ay be either arrayref or hashref, need top compare both
+    while(@self_type_constraints) {
+        my $self_type_constraint = shift @self_type_constraints;
+        my $other_type_constraint = shift @other_type_constraints
+         || return; ## $other needs the same number of children.
+        
+        if( ref $self_type_constraint) {
+            $self_type_constraint->equals($other_type_constraint)
+             || return; ## type constraints obviously need top be equal
+        } else {
+            $self_type_constraint eq $other_type_constraint
+             || return; ## strings should be equal
+        }
+
+    }
+    
+    return 1; ##If we get this far, everything is good.
+}
+
+=head2 get_message
+
+Give you a better peek into what's causing the error.  For now we stringify the
+incoming deep value with L<Devel::PartialDump> and pass that on to either your
+custom error message or the default one.  In the future we'll try to provide a
+more complete stack trace of the actual offending elements
+
+=cut
+
+around 'get_message' => sub {
+    my ($get_message, $self, $value) = @_;
+    $value = Devel::PartialDump::dump($value)
+     if ref $value;
+    return $self->$get_message($value);
+};
+
+=head1 SEE ALSO
+
+The following modules or resources may be of interest.
+
+L<Moose>, L<Moose::Meta::TypeConstraint>
+
+=head1 AUTHOR
+
+John Napiorkowski, C<< <jjnapiork at cpan.org> >>
+
+=head1 COPYRIGHT & LICENSE
+
+This program is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself.
+
+=cut
+
+__PACKAGE__->meta->make_immutable;
\ No newline at end of file

Deleted: MooseX-Types-Structured/tags/0.10/lib/MooseX/Types/Structured.pm
===================================================================
--- MooseX-Types-Structured/trunk/lib/MooseX/Types/Structured.pm	2009-04-01 03:11:50 UTC (rev 7879)
+++ MooseX-Types-Structured/tags/0.10/lib/MooseX/Types/Structured.pm	2009-04-02 15:10:44 UTC (rev 7884)
@@ -1,785 +0,0 @@
-package MooseX::Types::Structured;
-
-use 5.008;
-
-use Moose::Util::TypeConstraints;
-use MooseX::Meta::TypeConstraint::Structured;
-use MooseX::Types -declare => [qw(Dict Tuple Optional)];
-use Sub::Exporter -setup => { exports => [ qw(Dict Tuple Optional slurpy) ] };
-
-our $VERSION = '0.09';
-our $AUTHORITY = 'cpan:JJNAPIORK';
-
-=head1 NAME
-
-MooseX::Types::Structured - Structured Type Constraints for Moose
-
-=head1 SYNOPSIS
-
-The following is example usage for this module.
-
-    package Person;
-	
-    use Moose;
-    use MooseX::Types::Moose qw(Str Int HashRef);
-    use MooseX::Types::Structured qw(Dict Tuple Optional);
-
-    ## A name has a first and last part, but middle names are not required
-    has name => (
-        isa=>Dict[
-            first => Str,
-            last => Str,
-            middle => Optional[Str],
-        ],
-    );
-    
-    ## description is a string field followed by a HashRef of tagged data.
-    has description => (
-      isa=>Tuple[
-        Str,
-        Optional[HashRef],
-     ],
-    );
-
-Then you can instantiate this class with something like:
-
-    my $john = Person->new(
-        name => {
-            first => 'John',
-            middle => 'James'
-            last => 'Napiorkowski',
-        },
-        description => [
-            'A cool guy who loves Perl and Moose.', {
-                married_to => 'Vanessa Li',
-                born_in => 'USA',
-            };
-        ]
-    );
-
-Or with:
-
-    my $vanessa = Person->new(
-        name => {
-            first => 'Vanessa',
-            last => 'Li'
-        },
-        description => ['A great student!'],
-    );
-
-But all of these would cause a constraint error for the 'name' attribute:
-
-    ## Value for 'name' not a HashRef
-    Person->new( name => 'John' );
-    
-    ## Value for 'name' has incorrect hash key and missing required keys
-    Person->new( name => {
-        first_name => 'John'
-    });
-    
-    ## Also incorrect keys
-    Person->new( name => {
-        first_name => 'John',
-        age => 39,
-    });
-    
-    ## key 'middle' incorrect type, should be a Str not a ArrayRef
-    Person->new( name => {
-        first => 'Vanessa',
-        middle => [1,2],
-        last => 'Li',
-    }); 
-
-And these would cause a constraint error for the 'description' attribute:
-
-    ## Should be an ArrayRef
-    Person->new( description => 'Hello I am a String' );
-    
-    ## First element must be a string not a HashRef.
-    Person->new (description => [{
-        tag1 => 'value1',
-        tag2 => 'value2'
-    }]);
-
-Please see the test cases for more examples.
-
-=head1 DESCRIPTION
-
-A structured type constraint is a standard container L<Moose> type constraint,
-such as an ArrayRef or HashRef, which has been enhanced to allow you to
-explicitly name all the allowed type constraints inside the structure.  The
-generalized form is:
-
-    TypeConstraint[@TypeParameters or %TypeParameters]
-
-Where 'TypeParameters' is an array reference or hash references of 
-L<Moose::Meta::TypeConstraint> objects.
-
-This type library enables structured type constraints. It is built on top of the
-L<MooseX::Types> library system, so you should review the documentation for that
-if you are not familiar with it.
-
-=head2 Comparing Parameterized types to Structured types
-
-Parameterized constraints are built into core Moose and you are probably already
-familar with the type constraints 'HashRef' and 'ArrayRef'.  Structured types
-have similar functionality, so their syntax is likewise similar. For example,
-you could define a parameterized constraint like:
-
-    subtype ArrayOfInts,
-     as Arrayref[Int];
-
-which would constrain a value to something like [1,2,3,...] and so on.  On the
-other hand, a structured type constraint explicitly names all it's allowed
-'internal' type parameter constraints.  For the example:
-
-    subtype StringFollowedByInt,
-     as Tuple[Str,Int];
-	
-would constrain it's value to things like ['hello', 111] but ['hello', 'world']
-would fail, as well as ['hello', 111, 'world'] and so on.  Here's another
-example:
-
-    subtype StringIntOptionalHashRef,
-     as Tuple[
-        Str, Int,
-        Optional[HashRef]
-     ];
-     
-This defines a type constraint that validates values like:
-
-    ['Hello', 100, {key1 => 'value1', key2 => 'value2'}];
-    ['World', 200];
-    
-Notice that the last type constraint in the structure is optional.  This is
-enabled via the helper Optional type constraint, which is a variation of the
-core Moose type constraint 'Maybe'.  The main difference is that Optional type
-constraints are required to validate if they exist, while 'Maybe' permits 
-undefined values.  So the following example would not validate:
-
-    StringIntOptionalHashRef->validate(['Hello Undefined', 1000, undef]);
-    
-Please note the subtle difference between undefined and null.  If you wish to
-allow both null and undefined, you should use the core Moose 'Maybe' type
-constraint instead:
-
-    use MooseX::Types -declare [qw(StringIntMaybeHashRef)];
-    use MooseX::Types::Moose qw(Maybe);
-    use MooseX::Types::Structured qw(Tuple);
-
-    subtype StringIntMaybeHashRef,
-     as Tuple[
-        Str, Int, Maybe[HashRef]
-     ];
-
-This would validate the following:
-
-    ['Hello', 100, {key1 => 'value1', key2 => 'value2'}];
-    ['World', 200, undef];    
-    ['World', 200];
-
-Structured constraints are not limited to arrays.  You can define a structure
-against a HashRef with 'Dict' as in this example:
-
-    subtype FirstNameLastName,
-     as Dict[
-        firstname => Str,
-        lastname => Str,
-     ];
-
-This would constrain a HashRef to something like:
-
-    {firstname => 'Christopher', lastname= > 'Parsons'};
-    
-but all the following would fail validation:
-
-    ## Incorrect keys
-    {first => 'Christopher', last => 'Parsons'};
-    
-    ## Too many keys
-    {firstname => 'Christopher', lastname => 'Parsons', middlename => 'Allen'};
-    
-    ## Not a HashRef
-    ['Christopher', 'Christopher']; 
-
-These structures can be as simple or elaborate as you wish.  You can even
-combine various structured, parameterized and simple constraints all together:
-
-    subtype Crazy,
-     as Tuple[
-        Int,
-        Dict[name=>Str, age=>Int],
-        ArrayRef[Int]
-     ];
-	
-Which would match "[1, {name=>'John', age=>25},[10,11,12]]".  Please notice how
-the type parameters can be visually arranged to your liking and to improve the
-clarity of your meaning.  You don't need to run then altogether onto a single
-line.
-
-=head2 Alternatives
-
-You should exercise some care as to whether or not your complex structured
-constraints would be better off contained by a real object as in the following
-example:
-
-    package MyApp::MyStruct;
-    use Moose;
-    
-    ## lazy way to make a bunch of attributes
-    has $_ for qw(full_name age_in_years);
-    
-    package MyApp::MyClass;
-    use Moose;
-    
-    has person => (isa => 'MyApp::MyStruct');		
-    
-    my $instance = MyApp::MyClass->new(
-        person=>MyApp::MyStruct->new(
-            full_name => 'John',
-            age_in_years => 39,
-        ),
-    );
-	
-This method may take some additional time to setup but will give you more
-flexibility.  However, structured constraints are highly compatible with this
-method, granting some interesting possibilities for coercion.  Try:
-
-    package MyApp::MyClass;
-    
-    use Moose;
-    use MyApp::MyStruct;
-    
-    ## It's recommended your type declarations live in a separate class in order
-    ## to promote reusability and clarity.  Inlined here for brevity.
-    
-    use MooseX::Types::DateTime qw(DateTime);
-    use MooseX::Types -declare [qw(MyStruct)];
-    use MooseX::Types::Moose qw(Str Int);
-    use MooseX::Types::Structured qw(Dict);
-
-    ## Use class_type to create an ISA type constraint if your object doesn't
-    ## inherit from Moose::Object.
-    class_type 'MyApp::MyStruct';
-
-    ## Just a shorter version really.
-    subtype MyStruct,
-     as 'MyApp::MyStruct';
-    
-    ## Add the coercions.
-    coerce MyStruct,
-     from Dict[
-        full_name=>Str,
-        age_in_years=>Int
-     ], via {
-        MyApp::MyStruct->new(%$_);
-     },
-     from Dict[
-        lastname=>Str,
-        firstname=>Str,
-        dob=>DateTime
-     ], via {
-        my $name = $_->{firstname} .' '. $_->{lastname};
-        my $age = DateTime->now - $_->{dob};
-        
-        MyApp::MyStruct->new(
-            full_name=>$name,
-            age_in_years=>$age->years,
-        );
-     };
-     
-    has person => (isa=>MyStruct);	
-     
-This would allow you to instantiate with something like:
-
-    my $obj = MyApp::MyClass->new( person => {
-        full_name=>'John Napiorkowski',
-        age_in_years=>39,
-    });
-    
-Or even:
-
-    my $obj = MyApp::MyClass->new( person => {
-        lastname=>'John',
-        firstname=>'Napiorkowski',
-        dob=>DateTime->new(year=>1969),
-    });
-
-If you are not familiar with how coercions work, check out the L<Moose> cookbook
-entry L<Moose::Cookbook::Recipe5> for an explanation.  The section L</Coercions>
-has additional examples and discussion.
-
-=head2 Subtyping a Structured type constraint
-
-You need to exercise some care when you try to subtype a structured type as in
-this example:
-
-    subtype Person,
-     as Dict[name => Str];
-	 
-    subtype FriendlyPerson,
-     as Person[
-        name => Str,
-        total_friends => Int,
-     ];
-	 
-This will actually work BUT you have to take care that the subtype has a
-structure that does not contradict the structure of it's parent.  For now the
-above works, but I will clarify the syntax for this at a future point, so
-it's recommended to avoid (should not really be needed so much anyway).  For
-now this is supported in an EXPERIMENTAL way.  Your thoughts, test cases and
-patches are welcomed for discussion.  If you find a good use for this, please
-let me know.
-
-=head2 Coercions
-
-Coercions currently work for 'one level' deep.  That is you can do:
-
-    subtype Person,
-     as Dict[
-        name => Str,
-        age => Int
-    ];
-    
-    subtype Fullname,
-     as Dict[
-        first => Str,
-        last => Str
-     ];
-    
-    coerce Person,
-     ## Coerce an object of a particular class
-     from BlessedPersonObject, via {
-        +{
-            name=>$_->name,
-            age=>$_->age,
-        };
-     },
-     
-     ## Coerce from [$name, $age]
-     from ArrayRef, via {
-        +{
-            name=>$_->[0],
-            age=>$_->[1],
-        },
-     },
-     ## Coerce from {fullname=>{first=>...,last=>...}, dob=>$DateTimeObject}
-     from Dict[fullname=>Fullname, dob=>DateTime], via {
-        my $age = $_->dob - DateTime->now;
-        my $firstn = $_->{fullname}->{first};
-        my $lastn = $_->{fullname}->{last}
-        +{
-            name => $_->{fullname}->{first} .' '. ,
-            age =>$age->years
-        }
-     };
-	 
-And that should just work as expected.  However, if there are any 'inner'
-coercions, such as a coercion on 'Fullname' or on 'DateTime', that coercion
-won't currently get activated.
-
-Please see the test '07-coerce.t' for a more detailed example.  Discussion on
-extending coercions to support this welcome on the Moose development channel or
-mailing list.
-
-=head2 Recursion
-
-Newer versions of L<MooseX::Types> support recursive type constraints.  That is
-you can include a type constraint as a contained type constraint of itself.  For
-example:
-
-	subtype Person,
-	 as Dict[
-	 	name=>Str,
-	 	friends=>Optional[
-	 		ArrayRef[Person]
-	 	],
-	 ];
-	 
-This would declare a Person subtype that contains a name and an optional
-ArrayRef of Persons who are friends as in:
-
-	{
-		name => 'Mike',
-		friends => [
-			{ name => 'John' },
-			{ name => 'Vincent' },
-			{
-				name => 'Tracey',
-				friends => [
-					{ name => 'Stephenie' },
-					{ name => 'Ilya' },
-				],
-			},
-		],
-	};
-
-Please take care to make sure the recursion node is either Optional, or declare
-a Union with an non recursive option such as:
-
-	subtype Value
-	 as Tuple[
-	 	Str,
-	 	Str|Tuple,
-	 ];
-	 
-Which validates:
-
-	[
-		'Hello', [
-			'World', [
-				'Is', [
-					'Getting',
-					'Old',
-				],
-			],
-		],
-	];
-
-Otherwise you will define a subtype thatis impossible to validate since it is 
-infinitely recursive.  For more information about defining recursive types,
-please see the documentation in L<MooseX::Types> and the test cases.
-
-=head1 TYPE CONSTRAINTS
-
-This type library defines the following constraints.
-
-=head2 Tuple[@constraints]
-
-This defines an ArrayRef based constraint which allows you to validate a specific
-list of contained constraints.  For example:
-
-    Tuple[Int,Str]; ## Validates [1,'hello']
-    Tuple[Str|Object, Int]; ## Validates ['hello', 1] or [$object, 2]
-
-=head2 Dict[%constraints]
-
-This defines a HashRef based constraint which allowed you to validate a specific
-hashref.  For example:
-
-    Dict[name=>Str, age=>Int]; ## Validates {name=>'John', age=>39}
-
-=head2 Optional[$constraint]
-
-This is primarily a helper constraint for Dict and Tuple type constraints.  What
-this allows if for you to assert that a given type constraint is allowed to be
-null (but NOT undefined).  If the value is null, then the type constraint passes
-but if the value is defined it must validate against the type constraint.  This
-makes it easy to make a Dict where one or more of the keys doesn't have to exist
-or a tuple where some of the values are not required.  For example:
-
-    subtype Name() => as Dict[
-        first=>Str,
-        last=>Str,
-        middle=>Optional[Str],
-    ];
-        
-Creates a constraint that validates against a hashref with the keys 'first' and
-'last' being strings and required while an optional key 'middle' is must be a
-string if it appears but doesn't have to appear.  So in this case both the
-following are valid:
-
-    {first=>'John', middle=>'James', last=>'Napiorkowski'}
-    {first=>'Vanessa', last=>'Li'}
-
-=head1 EXPORTABLE SUBROUTINES
-
-This type library makes available for export the following subroutines
-
-=head2 slurpy
-
-Structured type constraints by their nature are closed; that is validation will
-depend and an exact match between your structure definition and the arguments to
-be checked.  Sometimes you might wish for a slightly looser amount of validation.
-For example, you may wish to validate the first 3 elements of an array reference
-and allow for an arbitrary number of additional elements.  At first thought you
-might think you could do it this way:
-
-    #  I want to validate stuff like: [1,"hello", $obj, 2,3,4,5,6,...]
-    subtype AllowTailingArgs,
-     as Tuple[
-       Int,
-       Str,
-       Object,
-       ArrayRef[Int],
-     ];
-
-However what this will actually validate are structures like this:
-
-    [10,"Hello", $obj, [11,12,13,...] ]; # Notice element 4 is an ArrayRef
-
-In order to allow structured validation of, "and then some", arguments, you can
-use the </slurpy> method against a type constraint.  For example:
-
-    use MooseX::Types::Structured qw(Tuple slurpy);
-    
-    subtype AllowTailingArgs,
-     as Tuple[
-       Int,
-       Str,
-       Object,
-       slurpy ArrayRef[Int],
-     ];
-
-This will now work as expected, validating ArrayRef structures such as:
-
-    [1,"hello", $obj, 2,3,4,5,6,...]
-    
-A few caveats apply.  First, the slurpy type constraint must be the last one in
-the list of type constraint parameters.  Second, the parent type of the slurpy
-type constraint must match that of the containing type constraint.  That means
-that a Tuple can allow a slurpy ArrayRef (or children of ArrayRefs, including
-another Tuple) and a Dict can allow a slurpy HashRef (or children/subtypes of
-HashRef, also including other Dict constraints).
-
-Please note the the technical way this works 'under the hood' is that the
-slurpy keywork transforms the target type constraint into a coderef.  Please do
-not try to create your own custom coderefs; always use the slurpy method.  The
-underlying technology may change in the future but the slurpy keyword will be
-supported.
-
-=head1 EXAMPLES
-
-Here are some additional example usage for structured types.  All examples can
-be found also in the 't/examples.t' test.  Your contributions are also welcomed.
-
-=head2 Normalize a HashRef
-
-You need a hashref to conform to a canonical structure but are required accept a
-bunch of different incoming structures.  You can normalize using the Dict type
-constraint and coercions.  This example also shows structured types mixed which
-other MooseX::Types libraries.
-
-    package Test::MooseX::Meta::TypeConstraint::Structured::Examples::Normalize;
-    
-    use Moose;
-    use DateTime;
-    
-    use MooseX::Types::Structured qw(Dict Tuple);
-    use MooseX::Types::DateTime qw(DateTime);
-    use MooseX::Types::Moose qw(Int Str Object);
-    use MooseX::Types -declare => [qw(Name Age Person)];
-     
-    subtype Person,
-     as Dict[
-     	name=>Str,
-     	age=>Int,
-     ];
-    
-    coerce Person,
-     from Dict[
-     	first=>Str, 
-     	last=>Str, 
-     	years=>Int,
-     ], via { +{
-        name => "$_->{first} $_->{last}",
-        age => $_->{years},
-     }},
-     from Dict[
-     	fullname=>Dict[
-     		last=>Str, 
-     		first=>Str,
-     	], 
-     	dob=>DateTime,
-     ],
-     ## DateTime needs to be inside of single quotes here to disambiguate the
-     ## class package from the DataTime type constraint imported via the
-     ## line "use MooseX::Types::DateTime qw(DateTime);"
-     via { +{
-        name => "$_->{fullname}{first} $_->{fullname}{last}",
-        age => ($_->{dob} - 'DateTime'->now)->years,
-     }};
-     
-    has person => (is=>'rw', isa=>Person, coerce=>1);
-    
-And now you can instantiate with all the following:
-
-    __PACKAGE__->new(
-        name=>'John Napiorkowski',
-        age=>39,
-    );
-        
-    __PACKAGE__->new(
-        first=>'John',
-        last=>'Napiorkowski',
-        years=>39,
-    );
-    
-    __PACKAGE__->new(
-        fullname => {
-            first=>'John',
-            last=>'Napiorkowski'
-        },
-        dob => 'DateTime'->new(
-            year=>1969,
-            month=>2,
-            day=>13
-        ),
-    );
-    
-This technique is a way to support various ways to instantiate your class in a
-clean and declarative way.
-
-=cut
-
-Moose::Util::TypeConstraints::get_type_constraint_registry->add_type_constraint(
-	MooseX::Meta::TypeConstraint::Structured->new(
-		name => "MooseX::Types::Structured::Tuple" ,
-		parent => find_type_constraint('ArrayRef'),
-		constraint_generator=> sub { 
-			## Get the constraints and values to check
-            my ($type_constraints, $values) = @_;
-			my @type_constraints = defined $type_constraints ?
-             @$type_constraints : ();
-            
-            my $overflow_handler;
-            if(ref $type_constraints[-1] eq 'CODE') {
-                $overflow_handler = pop @type_constraints;
-            }
-            
-			my @values = defined $values ? @$values: ();
-			## Perform the checking
-			while(@type_constraints) {
-				my $type_constraint = shift @type_constraints;
-				if(@values) {
-					my $value = shift @values;
-					unless($type_constraint->check($value)) {
-						return;
-					}				
-				} else {
-                    ## Test if the TC supports null values
-					unless($type_constraint->check()) {
-						return;
-					}
-				}
-			}
-			## Make sure there are no leftovers.
-			if(@values) {
-                if($overflow_handler) {
-                    return $overflow_handler->([@values]);
-                } else {
-                    return;
-                }
-			} elsif(@type_constraints) {
-                warn "I failed due to left over TC";
-				return;
-			} else {
-				return 1;
-			}
-		}
-	)
-);
-	
-Moose::Util::TypeConstraints::get_type_constraint_registry->add_type_constraint(
-	MooseX::Meta::TypeConstraint::Structured->new(
-		name => "MooseX::Types::Structured::Dict",
-		parent => find_type_constraint('HashRef'),
-		constraint_generator=> sub { 
-			## Get the constraints and values to check
-            my ($type_constraints, $values) = @_;
-			my @type_constraints = defined $type_constraints ?
-             @$type_constraints : ();
-            
-            my $overflow_handler;
-            if(ref $type_constraints[-1] eq 'CODE') {
-                $overflow_handler = pop @type_constraints;
-            } 
-            my (%type_constraints) = @type_constraints;
-			my %values = defined $values ? %$values: ();
-			## Perform the checking
-			while(%type_constraints) {
-				my($key, $type_constraint) = each %type_constraints;
-				delete $type_constraints{$key};
-				if(exists $values{$key}) {
-					my $value = $values{$key};
-					delete $values{$key};
-					unless($type_constraint->check($value)) {
-						return;
-					}
-				} else {
-                    ## Test to see if the TC supports null values
-					unless($type_constraint->check()) {
-						return;
-					}
-				}
-			}
-			## Make sure there are no leftovers.
-			if(%values) { 
-                if($overflow_handler) {
-                    return $overflow_handler->(+{%values});
-                } else {
-                    return;
-                }
-			} elsif(%type_constraints) {
-				return;
-			} else {
-				return 1;
-			}
-		},
-	)
-);
-
-OPTIONAL: {
-    my $Optional = Moose::Meta::TypeConstraint::Parameterizable->new(
-        name => 'MooseX::Types::Structured::Optional',
-        package_defined_in => __PACKAGE__,
-        parent => find_type_constraint('Item'),
-        constraint => sub { 1 },
-        constraint_generator => sub {
-            my ($type_parameter, @args) = @_;
-            my $check = $type_parameter->_compiled_type_constraint();
-            return sub {
-                my (@args) = @_;
-                ## Does the arg exist?  Something exists if it's a 'real' value
-                ## or if it is set to undef.
-                if(exists($args[0])) {
-                    ## If it exists, we need to validate it
-                    $check->($args[0]);
-                } else {
-                    ## But it's is okay if the value doesn't exists
-                    return 1;
-                }
-            }
-        }
-    );
-
-    Moose::Util::TypeConstraints::register_type_constraint($Optional);
-    Moose::Util::TypeConstraints::add_parameterizable_type($Optional);
-}
-
-sub slurpy($) {
-	my $tc = shift @_;
-	return sub {
-        $tc->check(shift);
-    };
-}
-
-=head1 SEE ALSO
-
-The following modules or resources may be of interest.
-
-L<Moose>, L<MooseX::Types>, L<Moose::Meta::TypeConstraint>,
-L<MooseX::Meta::TypeConstraint::Structured>
-
-=head1 TODO
-
-Here's a list of stuff I would be happy to get volunteers helping with:
-
-All POD examples need test cases in t/documentation/*.t
-Want to break out the examples section to a separate cookbook style POD.
-Want more examples and best practice / usage guidance for authors
-Need to clarify deep coercions, 
-Need to clarify subtypes of subtypes.
-
-=head1 AUTHOR
-
-John Napiorkowski, C<< <jjnapiork at cpan.org> >>
-
-=head1 COPYRIGHT & LICENSE
-
-This program is free software; you can redistribute it and/or modify
-it under the same terms as Perl itself.
-
-=cut
-	
-1;

Copied: MooseX-Types-Structured/tags/0.10/lib/MooseX/Types/Structured.pm (from rev 7883, MooseX-Types-Structured/trunk/lib/MooseX/Types/Structured.pm)
===================================================================
--- MooseX-Types-Structured/tags/0.10/lib/MooseX/Types/Structured.pm	                        (rev 0)
+++ MooseX-Types-Structured/tags/0.10/lib/MooseX/Types/Structured.pm	2009-04-02 15:10:44 UTC (rev 7884)
@@ -0,0 +1,826 @@
+package MooseX::Types::Structured;
+
+use 5.008;
+
+use Moose::Util::TypeConstraints;
+use MooseX::Meta::TypeConstraint::Structured;
+use MooseX::Types -declare => [qw(Dict Tuple Optional)];
+use Sub::Exporter -setup => { exports => [ qw(Dict Tuple Optional slurpy) ] };
+use Devel::PartialDump;
+
+our $VERSION = '0.10';
+our $AUTHORITY = 'cpan:JJNAPIORK';
+
+=head1 NAME
+
+MooseX::Types::Structured - Structured Type Constraints for Moose
+
+=head1 SYNOPSIS
+
+The following is example usage for this module.
+
+    package Person;
+	
+    use Moose;
+    use MooseX::Types::Moose qw(Str Int HashRef);
+    use MooseX::Types::Structured qw(Dict Tuple Optional);
+
+    ## A name has a first and last part, but middle names are not required
+    has name => (
+        isa=>Dict[
+            first => Str,
+            last => Str,
+            middle => Optional[Str],
+        ],
+    );
+    
+    ## description is a string field followed by a HashRef of tagged data.
+    has description => (
+      isa=>Tuple[
+        Str,
+        Optional[HashRef],
+     ],
+    );
+
+Then you can instantiate this class with something like:
+
+    my $john = Person->new(
+        name => {
+            first => 'John',
+            middle => 'James'
+            last => 'Napiorkowski',
+        },
+        description => [
+            'A cool guy who loves Perl and Moose.', {
+                married_to => 'Vanessa Li',
+                born_in => 'USA',
+            };
+        ]
+    );
+
+Or with:
+
+    my $vanessa = Person->new(
+        name => {
+            first => 'Vanessa',
+            last => 'Li'
+        },
+        description => ['A great student!'],
+    );
+
+But all of these would cause a constraint error for the 'name' attribute:
+
+    ## Value for 'name' not a HashRef
+    Person->new( name => 'John' );
+    
+    ## Value for 'name' has incorrect hash key and missing required keys
+    Person->new( name => {
+        first_name => 'John'
+    });
+    
+    ## Also incorrect keys
+    Person->new( name => {
+        first_name => 'John',
+        age => 39,
+    });
+    
+    ## key 'middle' incorrect type, should be a Str not a ArrayRef
+    Person->new( name => {
+        first => 'Vanessa',
+        middle => [1,2],
+        last => 'Li',
+    }); 
+
+And these would cause a constraint error for the 'description' attribute:
+
+    ## Should be an ArrayRef
+    Person->new( description => 'Hello I am a String' );
+    
+    ## First element must be a string not a HashRef.
+    Person->new (description => [{
+        tag1 => 'value1',
+        tag2 => 'value2'
+    }]);
+
+Please see the test cases for more examples.
+
+=head1 DESCRIPTION
+
+A structured type constraint is a standard container L<Moose> type constraint,
+such as an ArrayRef or HashRef, which has been enhanced to allow you to
+explicitly name all the allowed type constraints inside the structure.  The
+generalized form is:
+
+    TypeConstraint[@TypeParameters or %TypeParameters]
+
+Where 'TypeParameters' is an array reference or hash references of 
+L<Moose::Meta::TypeConstraint> objects.
+
+This type library enables structured type constraints. It is built on top of the
+L<MooseX::Types> library system, so you should review the documentation for that
+if you are not familiar with it.
+
+=head2 Comparing Parameterized types to Structured types
+
+Parameterized constraints are built into core Moose and you are probably already
+familar with the type constraints 'HashRef' and 'ArrayRef'.  Structured types
+have similar functionality, so their syntax is likewise similar. For example,
+you could define a parameterized constraint like:
+
+    subtype ArrayOfInts,
+     as Arrayref[Int];
+
+which would constrain a value to something like [1,2,3,...] and so on.  On the
+other hand, a structured type constraint explicitly names all it's allowed
+'internal' type parameter constraints.  For the example:
+
+    subtype StringFollowedByInt,
+     as Tuple[Str,Int];
+	
+would constrain it's value to things like ['hello', 111] but ['hello', 'world']
+would fail, as well as ['hello', 111, 'world'] and so on.  Here's another
+example:
+
+    subtype StringIntOptionalHashRef,
+     as Tuple[
+        Str, Int,
+        Optional[HashRef]
+     ];
+     
+This defines a type constraint that validates values like:
+
+    ['Hello', 100, {key1 => 'value1', key2 => 'value2'}];
+    ['World', 200];
+    
+Notice that the last type constraint in the structure is optional.  This is
+enabled via the helper Optional type constraint, which is a variation of the
+core Moose type constraint 'Maybe'.  The main difference is that Optional type
+constraints are required to validate if they exist, while 'Maybe' permits 
+undefined values.  So the following example would not validate:
+
+    StringIntOptionalHashRef->validate(['Hello Undefined', 1000, undef]);
+    
+Please note the subtle difference between undefined and null.  If you wish to
+allow both null and undefined, you should use the core Moose 'Maybe' type
+constraint instead:
+
+    use MooseX::Types -declare [qw(StringIntMaybeHashRef)];
+    use MooseX::Types::Moose qw(Maybe);
+    use MooseX::Types::Structured qw(Tuple);
+
+    subtype StringIntMaybeHashRef,
+     as Tuple[
+        Str, Int, Maybe[HashRef]
+     ];
+
+This would validate the following:
+
+    ['Hello', 100, {key1 => 'value1', key2 => 'value2'}];
+    ['World', 200, undef];    
+    ['World', 200];
+
+Structured constraints are not limited to arrays.  You can define a structure
+against a HashRef with 'Dict' as in this example:
+
+    subtype FirstNameLastName,
+     as Dict[
+        firstname => Str,
+        lastname => Str,
+     ];
+
+This would constrain a HashRef to something like:
+
+    {firstname => 'Christopher', lastname= > 'Parsons'};
+    
+but all the following would fail validation:
+
+    ## Incorrect keys
+    {first => 'Christopher', last => 'Parsons'};
+    
+    ## Too many keys
+    {firstname => 'Christopher', lastname => 'Parsons', middlename => 'Allen'};
+    
+    ## Not a HashRef
+    ['Christopher', 'Christopher']; 
+
+These structures can be as simple or elaborate as you wish.  You can even
+combine various structured, parameterized and simple constraints all together:
+
+    subtype Crazy,
+     as Tuple[
+        Int,
+        Dict[name=>Str, age=>Int],
+        ArrayRef[Int]
+     ];
+	
+Which would match "[1, {name=>'John', age=>25},[10,11,12]]".  Please notice how
+the type parameters can be visually arranged to your liking and to improve the
+clarity of your meaning.  You don't need to run then altogether onto a single
+line.
+
+=head2 Alternatives
+
+You should exercise some care as to whether or not your complex structured
+constraints would be better off contained by a real object as in the following
+example:
+
+    package MyApp::MyStruct;
+    use Moose;
+    
+    ## lazy way to make a bunch of attributes
+    has $_ for qw(full_name age_in_years);
+    
+    package MyApp::MyClass;
+    use Moose;
+    
+    has person => (isa => 'MyApp::MyStruct');		
+    
+    my $instance = MyApp::MyClass->new(
+        person=>MyApp::MyStruct->new(
+            full_name => 'John',
+            age_in_years => 39,
+        ),
+    );
+	
+This method may take some additional time to setup but will give you more
+flexibility.  However, structured constraints are highly compatible with this
+method, granting some interesting possibilities for coercion.  Try:
+
+    package MyApp::MyClass;
+    
+    use Moose;
+    use MyApp::MyStruct;
+    
+    ## It's recommended your type declarations live in a separate class in order
+    ## to promote reusability and clarity.  Inlined here for brevity.
+    
+    use MooseX::Types::DateTime qw(DateTime);
+    use MooseX::Types -declare [qw(MyStruct)];
+    use MooseX::Types::Moose qw(Str Int);
+    use MooseX::Types::Structured qw(Dict);
+
+    ## Use class_type to create an ISA type constraint if your object doesn't
+    ## inherit from Moose::Object.
+    class_type 'MyApp::MyStruct';
+
+    ## Just a shorter version really.
+    subtype MyStruct,
+     as 'MyApp::MyStruct';
+    
+    ## Add the coercions.
+    coerce MyStruct,
+     from Dict[
+        full_name=>Str,
+        age_in_years=>Int
+     ], via {
+        MyApp::MyStruct->new(%$_);
+     },
+     from Dict[
+        lastname=>Str,
+        firstname=>Str,
+        dob=>DateTime
+     ], via {
+        my $name = $_->{firstname} .' '. $_->{lastname};
+        my $age = DateTime->now - $_->{dob};
+        
+        MyApp::MyStruct->new(
+            full_name=>$name,
+            age_in_years=>$age->years,
+        );
+     };
+     
+    has person => (isa=>MyStruct);	
+     
+This would allow you to instantiate with something like:
+
+    my $obj = MyApp::MyClass->new( person => {
+        full_name=>'John Napiorkowski',
+        age_in_years=>39,
+    });
+    
+Or even:
+
+    my $obj = MyApp::MyClass->new( person => {
+        lastname=>'John',
+        firstname=>'Napiorkowski',
+        dob=>DateTime->new(year=>1969),
+    });
+
+If you are not familiar with how coercions work, check out the L<Moose> cookbook
+entry L<Moose::Cookbook::Recipe5> for an explanation.  The section L</Coercions>
+has additional examples and discussion.
+
+=head2 Subtyping a Structured type constraint
+
+You need to exercise some care when you try to subtype a structured type as in
+this example:
+
+    subtype Person,
+     as Dict[name => Str];
+	 
+    subtype FriendlyPerson,
+     as Person[
+        name => Str,
+        total_friends => Int,
+     ];
+	 
+This will actually work BUT you have to take care that the subtype has a
+structure that does not contradict the structure of it's parent.  For now the
+above works, but I will clarify the syntax for this at a future point, so
+it's recommended to avoid (should not really be needed so much anyway).  For
+now this is supported in an EXPERIMENTAL way.  Your thoughts, test cases and
+patches are welcomed for discussion.  If you find a good use for this, please
+let me know.
+
+=head2 Coercions
+
+Coercions currently work for 'one level' deep.  That is you can do:
+
+    subtype Person,
+     as Dict[
+        name => Str,
+        age => Int
+    ];
+    
+    subtype Fullname,
+     as Dict[
+        first => Str,
+        last => Str
+     ];
+    
+    coerce Person,
+     ## Coerce an object of a particular class
+     from BlessedPersonObject, via {
+        +{
+            name=>$_->name,
+            age=>$_->age,
+        };
+     },
+     
+     ## Coerce from [$name, $age]
+     from ArrayRef, via {
+        +{
+            name=>$_->[0],
+            age=>$_->[1],
+        },
+     },
+     ## Coerce from {fullname=>{first=>...,last=>...}, dob=>$DateTimeObject}
+     from Dict[fullname=>Fullname, dob=>DateTime], via {
+        my $age = $_->dob - DateTime->now;
+        my $firstn = $_->{fullname}->{first};
+        my $lastn = $_->{fullname}->{last}
+        +{
+            name => $_->{fullname}->{first} .' '. ,
+            age =>$age->years
+        }
+     };
+	 
+And that should just work as expected.  However, if there are any 'inner'
+coercions, such as a coercion on 'Fullname' or on 'DateTime', that coercion
+won't currently get activated.
+
+Please see the test '07-coerce.t' for a more detailed example.  Discussion on
+extending coercions to support this welcome on the Moose development channel or
+mailing list.
+
+=head2 Recursion
+
+Newer versions of L<MooseX::Types> support recursive type constraints.  That is
+you can include a type constraint as a contained type constraint of itself.  For
+example:
+
+	subtype Person,
+	 as Dict[
+	 	name=>Str,
+	 	friends=>Optional[
+	 		ArrayRef[Person]
+	 	],
+	 ];
+	 
+This would declare a Person subtype that contains a name and an optional
+ArrayRef of Persons who are friends as in:
+
+	{
+		name => 'Mike',
+		friends => [
+			{ name => 'John' },
+			{ name => 'Vincent' },
+			{
+				name => 'Tracey',
+				friends => [
+					{ name => 'Stephenie' },
+					{ name => 'Ilya' },
+				],
+			},
+		],
+	};
+
+Please take care to make sure the recursion node is either Optional, or declare
+a Union with an non recursive option such as:
+
+	subtype Value
+	 as Tuple[
+	 	Str,
+	 	Str|Tuple,
+	 ];
+	 
+Which validates:
+
+	[
+		'Hello', [
+			'World', [
+				'Is', [
+					'Getting',
+					'Old',
+				],
+			],
+		],
+	];
+
+Otherwise you will define a subtype thatis impossible to validate since it is 
+infinitely recursive.  For more information about defining recursive types,
+please see the documentation in L<MooseX::Types> and the test cases.
+
+=head1 TYPE CONSTRAINTS
+
+This type library defines the following constraints.
+
+=head2 Tuple[@constraints]
+
+This defines an ArrayRef based constraint which allows you to validate a specific
+list of contained constraints.  For example:
+
+    Tuple[Int,Str]; ## Validates [1,'hello']
+    Tuple[Str|Object, Int]; ## Validates ['hello', 1] or [$object, 2]
+
+=head2 Dict[%constraints]
+
+This defines a HashRef based constraint which allowed you to validate a specific
+hashref.  For example:
+
+    Dict[name=>Str, age=>Int]; ## Validates {name=>'John', age=>39}
+
+=head2 Optional[$constraint]
+
+This is primarily a helper constraint for Dict and Tuple type constraints.  What
+this allows if for you to assert that a given type constraint is allowed to be
+null (but NOT undefined).  If the value is null, then the type constraint passes
+but if the value is defined it must validate against the type constraint.  This
+makes it easy to make a Dict where one or more of the keys doesn't have to exist
+or a tuple where some of the values are not required.  For example:
+
+    subtype Name() => as Dict[
+        first=>Str,
+        last=>Str,
+        middle=>Optional[Str],
+    ];
+        
+Creates a constraint that validates against a hashref with the keys 'first' and
+'last' being strings and required while an optional key 'middle' is must be a
+string if it appears but doesn't have to appear.  So in this case both the
+following are valid:
+
+    {first=>'John', middle=>'James', last=>'Napiorkowski'}
+    {first=>'Vanessa', last=>'Li'}
+
+=head1 EXPORTABLE SUBROUTINES
+
+This type library makes available for export the following subroutines
+
+=head2 slurpy
+
+Structured type constraints by their nature are closed; that is validation will
+depend on an exact match between your structure definition and the arguments to
+be checked.  Sometimes you might wish for a slightly looser amount of validation.
+For example, you may wish to validate the first 3 elements of an array reference
+and allow for an arbitrary number of additional elements.  At first thought you
+might think you could do it this way:
+
+    #  I want to validate stuff like: [1,"hello", $obj, 2,3,4,5,6,...]
+    subtype AllowTailingArgs,
+     as Tuple[
+       Int,
+       Str,
+       Object,
+       ArrayRef[Int],
+     ];
+
+However what this will actually validate are structures like this:
+
+    [10,"Hello", $obj, [11,12,13,...] ]; # Notice element 4 is an ArrayRef
+
+In order to allow structured validation of, "and then some", arguments, you can
+use the </slurpy> method against a type constraint.  For example:
+
+    use MooseX::Types::Structured qw(Tuple slurpy);
+    
+    subtype AllowTailingArgs,
+     as Tuple[
+       Int,
+       Str,
+       Object,
+       slurpy ArrayRef[Int],
+     ];
+
+This will now work as expected, validating ArrayRef structures such as:
+
+    [1,"hello", $obj, 2,3,4,5,6,...]
+    
+A few caveats apply.  First, the slurpy type constraint must be the last one in
+the list of type constraint parameters.  Second, the parent type of the slurpy
+type constraint must match that of the containing type constraint.  That means
+that a Tuple can allow a slurpy ArrayRef (or children of ArrayRefs, including
+another Tuple) and a Dict can allow a slurpy HashRef (or children/subtypes of
+HashRef, also including other Dict constraints).
+
+Please note the the technical way this works 'under the hood' is that the
+slurpy keywork transforms the target type constraint into a coderef.  Please do
+not try to create your own custom coderefs; always use the slurpy method.  The
+underlying technology may change in the future but the slurpy keyword will be
+supported.
+
+=head1 ERROR MESSAGES
+
+Error reporting has been improved to return more useful debugging messages. Now
+I will stringify the incoming check value with L<Devel::PartialDump> so that you
+can see the actual structure that is tripping up validation.  Also, I report the
+'internal' validation error, so that if a particular element inside the
+Structured Type is failing validation, you will see that.  There's a limit to
+how deep this internal reporting goes, but you shouldn't see any of the "failed
+with ARRAY(XXXXXX)" that we got with earlier versions of this module.
+
+This support is continuing to expand, so it's best to use these messages for
+debugging purposes and not for creating messages that 'escape into the wild'
+such as error messages sent to the user.
+
+Please see the test '12-error.t' for a more lengthy example.  Your thoughts and
+preferable tests or code patches very welcome!
+
+=head1 EXAMPLES
+
+Here are some additional example usage for structured types.  All examples can
+be found also in the 't/examples.t' test.  Your contributions are also welcomed.
+
+=head2 Normalize a HashRef
+
+You need a hashref to conform to a canonical structure but are required accept a
+bunch of different incoming structures.  You can normalize using the Dict type
+constraint and coercions.  This example also shows structured types mixed which
+other MooseX::Types libraries.
+
+    package Test::MooseX::Meta::TypeConstraint::Structured::Examples::Normalize;
+    
+    use Moose;
+    use DateTime;
+    
+    use MooseX::Types::Structured qw(Dict Tuple);
+    use MooseX::Types::DateTime qw(DateTime);
+    use MooseX::Types::Moose qw(Int Str Object);
+    use MooseX::Types -declare => [qw(Name Age Person)];
+     
+    subtype Person,
+     as Dict[
+     	name=>Str,
+     	age=>Int,
+     ];
+    
+    coerce Person,
+     from Dict[
+     	first=>Str, 
+     	last=>Str, 
+     	years=>Int,
+     ], via { +{
+        name => "$_->{first} $_->{last}",
+        age => $_->{years},
+     }},
+     from Dict[
+     	fullname=>Dict[
+     		last=>Str, 
+     		first=>Str,
+     	], 
+     	dob=>DateTime,
+     ],
+     ## DateTime needs to be inside of single quotes here to disambiguate the
+     ## class package from the DataTime type constraint imported via the
+     ## line "use MooseX::Types::DateTime qw(DateTime);"
+     via { +{
+        name => "$_->{fullname}{first} $_->{fullname}{last}",
+        age => ($_->{dob} - 'DateTime'->now)->years,
+     }};
+     
+    has person => (is=>'rw', isa=>Person, coerce=>1);
+    
+And now you can instantiate with all the following:
+
+    __PACKAGE__->new(
+        person=>{
+            name=>'John Napiorkowski',
+            age=>39,            
+        },
+    );
+        
+    __PACKAGE__->new(
+        person=>{
+            first=>'John',
+            last=>'Napiorkowski',
+            years=>39,
+        },
+    );
+    
+    __PACKAGE__->new(
+        person=>{
+            fullname => {
+                first=>'John',
+                last=>'Napiorkowski'
+            },
+            dob => 'DateTime'->new(
+                year=>1969,
+                month=>2,
+                day=>13
+            ),            
+        },
+    );
+    
+This technique is a way to support various ways to instantiate your class in a
+clean and declarative way.
+
+=cut
+
+Moose::Util::TypeConstraints::get_type_constraint_registry->add_type_constraint(
+	MooseX::Meta::TypeConstraint::Structured->new(
+		name => "MooseX::Types::Structured::Tuple" ,
+		parent => find_type_constraint('ArrayRef'),
+		constraint_generator=> sub { 
+			## Get the constraints and values to check
+            my ($type_constraints, $values) = @_;
+			my @type_constraints = defined $type_constraints ?
+             @$type_constraints : ();
+            
+            my $overflow_handler;
+            if(ref $type_constraints[-1] eq 'CODE') {
+                $overflow_handler = pop @type_constraints;
+            }
+            
+			my @values = defined $values ? @$values: ();
+			## Perform the checking
+			while(@type_constraints) {
+				my $type_constraint = shift @type_constraints;
+				if(@values) {
+					my $value = shift @values;
+					unless($type_constraint->check($value)) {
+                        $_[2]->{message} = $type_constraint->get_message($value)
+                         if ref $_[2];
+						return;
+					}				
+				} else {
+                    ## Test if the TC supports null values
+					unless($type_constraint->check()) {
+                        $_[2]->{message} = $type_constraint->get_message('NULL')
+                         if ref $_[2];
+						return;
+					}
+				}
+			}
+			## Make sure there are no leftovers.
+			if(@values) {
+                if($overflow_handler) {
+                    return $overflow_handler->([@values], $_[2]);
+                } else {
+                    $_[2]->{message} = "More values than Type Constraints!"
+                     if ref $_[2];
+                    return;
+                }
+			} elsif(@type_constraints) {
+                $_[2]->{message} =
+                 "Not enough values for all defined type constraints.  Remaining: ". join(', ', at type_constraints)
+                 if ref $_[2];
+				return;
+			} else {
+				return 1;
+			}
+		}
+	)
+);
+	
+Moose::Util::TypeConstraints::get_type_constraint_registry->add_type_constraint(
+	MooseX::Meta::TypeConstraint::Structured->new(
+		name => "MooseX::Types::Structured::Dict",
+		parent => find_type_constraint('HashRef'),
+		constraint_generator=> sub { 
+			## Get the constraints and values to check
+            my ($type_constraints, $values) = @_;
+			my @type_constraints = defined $type_constraints ?
+             @$type_constraints : ();
+            
+            my $overflow_handler;
+            if(ref $type_constraints[-1] eq 'CODE') {
+                $overflow_handler = pop @type_constraints;
+            } 
+            my (%type_constraints) = @type_constraints;
+			my %values = defined $values ? %$values: ();
+			## Perform the checking
+			while(%type_constraints) {
+				my($key, $type_constraint) = each %type_constraints;
+				delete $type_constraints{$key};
+				if(exists $values{$key}) {
+					my $value = $values{$key};
+					delete $values{$key};
+					unless($type_constraint->check($value)) {
+                        $_[2]->{message} = $type_constraint->get_message($value)
+                         if ref $_[2];
+						return;
+					}
+				} else {
+                    ## Test to see if the TC supports null values
+					unless($type_constraint->check()) {
+                        $_[2]->{message} = $type_constraint->get_message('NULL')
+                         if ref $_[2];
+						return;
+					}
+				}
+			}
+			## Make sure there are no leftovers.
+			if(%values) { 
+                if($overflow_handler) {
+                    return $overflow_handler->(+{%values});
+                } else {
+                    $_[2]->{message} = "More values than Type Constraints!"
+                     if ref $_[2];
+                    return;
+                }
+			} elsif(%type_constraints) {
+                $_[2]->{message} =
+                 "Not enough values for all defined type constraints.  Remaining: ". join(', ',values %values)
+                 if ref $_[2];
+				return;
+			} else {
+				return 1;
+			}
+		},
+	)
+);
+
+OPTIONAL: {
+    my $Optional = Moose::Meta::TypeConstraint::Parameterizable->new(
+        name => 'MooseX::Types::Structured::Optional',
+        package_defined_in => __PACKAGE__,
+        parent => find_type_constraint('Item'),
+        constraint => sub { 1 },
+        constraint_generator => sub {
+            my ($type_parameter, @args) = @_;
+            my $check = $type_parameter->_compiled_type_constraint();
+            return sub {
+                my (@args) = @_;
+                ## Does the arg exist?  Something exists if it's a 'real' value
+                ## or if it is set to undef.
+                if(exists($args[0])) {
+                    ## If it exists, we need to validate it
+                    $check->($args[0]);
+                } else {
+                    ## But it's is okay if the value doesn't exists
+                    return 1;
+                }
+            }
+        }
+    );
+
+    Moose::Util::TypeConstraints::register_type_constraint($Optional);
+    Moose::Util::TypeConstraints::add_parameterizable_type($Optional);
+}
+
+sub slurpy($) {
+	my $tc = shift @_;
+	return sub {
+        $tc->check(shift);
+    };
+}
+
+=head1 SEE ALSO
+
+The following modules or resources may be of interest.
+
+L<Moose>, L<MooseX::Types>, L<Moose::Meta::TypeConstraint>,
+L<MooseX::Meta::TypeConstraint::Structured>
+
+=head1 TODO
+
+Here's a list of stuff I would be happy to get volunteers helping with:
+
+All POD examples need test cases in t/documentation/*.t
+Want to break out the examples section to a separate cookbook style POD.
+Want more examples and best practice / usage guidance for authors
+Need to clarify deep coercions, 
+Need to clarify subtypes of subtypes.
+
+=head1 AUTHOR
+
+John Napiorkowski, C<< <jjnapiork at cpan.org> >>
+
+=head1 COPYRIGHT & LICENSE
+
+This program is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself.
+
+=cut
+	
+1;

Deleted: MooseX-Types-Structured/tags/0.10/t/12-error.t
===================================================================
--- MooseX-Types-Structured/trunk/t/12-error.t	2009-04-01 03:11:50 UTC (rev 7879)
+++ MooseX-Types-Structured/tags/0.10/t/12-error.t	2009-04-02 15:10:44 UTC (rev 7884)
@@ -1,20 +0,0 @@
-BEGIN {
-	use strict;
-	use warnings;
-	use Test::More tests=>4;
-}
-
-use Moose::Util::TypeConstraints;
-use MooseX::Types::Structured qw(Dict Tuple);
-use MooseX::Types::Moose qw(Int Str ArrayRef HashRef);
-
-# Create some TCs from which errors will be generated
-my $simple_tuple = subtype 'simple_tuple', as Tuple[Int,Str];
-my $simple_dict = subtype 'simple_dict', as Dict[name=>Str,age=>Int];
-
-# We probably need more stuff here...
-ok $simple_tuple->check([1,'hello']), "simple_tuple validates: 1,'hello'";
-ok !$simple_tuple->check(['hello',1]), "simple_tuple fails: 'hello',1";
-like $simple_tuple->validate(['hello',1]), qr/"hello", 1/, 'got expected valiate message';
-like $simple_dict->validate(['hello',1]), qr/"hello", 1/, 'got expected valiate message';
-

Copied: MooseX-Types-Structured/tags/0.10/t/12-error.t (from rev 7883, MooseX-Types-Structured/trunk/t/12-error.t)
===================================================================
--- MooseX-Types-Structured/tags/0.10/t/12-error.t	                        (rev 0)
+++ MooseX-Types-Structured/tags/0.10/t/12-error.t	2009-04-02 15:10:44 UTC (rev 7884)
@@ -0,0 +1,121 @@
+BEGIN {
+	use strict;
+	use warnings;
+	use Test::More tests=>24;
+}
+
+use Moose::Util::TypeConstraints;
+use MooseX::Types::Structured qw(Dict Tuple Optional);
+use MooseX::Types::Moose qw(Int Str ArrayRef HashRef);
+
+# Create some TCs from which errors will be generated
+
+my $simple_tuple = subtype 'simple_tuple', as Tuple[Int,Str];
+my $simple_dict = subtype 'simple_dict', as Dict[name=>Str,age=>Int];
+
+# Make sure the constraints we made validate as expected
+
+ok $simple_tuple->check([1,'hello']), "simple_tuple validates: 1,'hello'";
+ok !$simple_tuple->check(['hello',1]), "simple_tuple fails: 'hello',1";
+ok $simple_dict->check({name=>'Vanessa',age=>34}), "simple_dict validates: {name=>'Vanessa',age=>34}";
+ok !$simple_dict->check({name=>$simple_dict,age=>'hello'}), "simple_dict fails: {name=>Object, age=>String}";
+
+## Let's check all the expected validation errors for tuple
+
+like $simple_tuple->validate({a=>1,b=>2}),
+ qr/Validation failed for 'simple_tuple' failed with value { a => 1, b => 2 }/,
+ 'Wrong basic type';
+
+like $simple_tuple->validate(['a','b']),
+ qr/failed for 'simple_tuple' failed with value \[ "a", "b" \]/,
+ 'Correctly failed due to "a" not an Int';
+ 
+like $simple_tuple->validate([1,$simple_tuple]),
+ qr/Validation failed for 'simple_tuple' failed with value \[ 1, MooseX::Meta::TypeConstraint::Structured/,
+ 'Correctly failed due to object not a Str';
+
+like $simple_tuple->validate([1]),
+ qr/Validation failed for 'Str' failed with value NULL/,
+ 'Not enought values';
+
+like $simple_tuple->validate([1,'hello','too many']),
+ qr/More values than Type Constraints!/,
+ 'Too Many values';
+
+## And the same thing for dicts [name=>Str,age=>Int]
+
+like $simple_dict->validate([1,2]),
+ qr/ failed with value \[ 1, 2 \]/,
+ 'Wrong basic type';
+ 
+like $simple_dict->validate({name=>'John',age=>'a'}),
+ qr/failed for 'Int' failed with value a/,
+ 'Correctly failed due to age not an Int';
+ 
+like $simple_dict->validate({name=>$simple_dict,age=>1}),
+ qr/failed with value { age => 1, name => MooseX:/,
+ 'Correctly failed due to object not a Str';
+
+like $simple_dict->validate({name=>'John'}),
+ qr/failed for 'Int' failed with value NULL/,
+ 'Not enought values';
+
+like $simple_dict->validate({name=>'Vincent', age=>15,extra=>'morethanIneed'}),
+ qr/More values than Type Constraints!/,
+ 'Too Many values';
+ 
+ ## TODO some with Optional (or Maybe) and slurpy
+ 
+ my $optional_tuple = subtype 'optional_tuple', as Tuple[Int,Optional[Str]];
+ my $optional_dict = subtype 'optional_dict', as Dict[name=>Str,age=>Optional[Int]];
+ 
+ like $optional_tuple->validate({a=>1,b=>2}),
+ qr/Validation failed for 'optional_tuple' failed with value { a => 1, b => 2 }/,
+ 'Wrong basic type';
+
+like $optional_tuple->validate(['a','b']),
+ qr/failed for 'Int' failed with value a/,
+ 'Correctly failed due to "a" not an Int';
+ 
+like $optional_tuple->validate([1,$simple_tuple]),
+ qr/failed for 'MooseX::Types::Structured::Optional\[Str\]' failed with value MooseX/,
+ 'Correctly failed due to object not a Str';
+
+like $optional_tuple->validate([1,'hello','too many']),
+ qr/More values than Type Constraints!/,
+ 'Too Many values';
+
+like $optional_dict->validate([1,2]),
+ qr/ failed with value \[ 1, 2 \]/,
+ 'Wrong basic type';
+ 
+like $optional_dict->validate({name=>'John',age=>'a'}),
+ qr/Validation failed for 'MooseX::Types::Structured::Optional\[Int\]' failed with value a/,
+ 'Correctly failed due to age not an Int';
+ 
+like $optional_dict->validate({name=>$simple_dict,age=>1}),
+ qr/failed with value { age => 1, name => MooseX:/,
+ 'Correctly failed due to object not a Str';
+
+like $optional_dict->validate({name=>'Vincent', age=>15,extra=>'morethanIneed'}),
+ qr/More values than Type Constraints!/,
+ 'Too Many values';
+ 
+## Deeper constraints
+
+my $deep_tuple = subtype 'deep_tuple',
+  as Tuple[
+    Int,
+    HashRef,
+    Dict[
+      name=>Str,
+      age=>Int,
+    ],
+  ];
+  
+ok $deep_tuple->check([1,{a=>2},{name=>'Vincent',age=>15}]),
+  'Good Constraint';
+  
+like $deep_tuple->validate([1,{a=>2},{name=>'Vincent',age=>'Hello'}]),
+  qr/Error is: Validation failed for 'MooseX::Types::Structured::Dict\[name,Str,age,Int\]'/,
+  'Example deeper error';




More information about the Moose-commits mailing list