made union tests skip for now, got start on fixing up the named type constraints
[gitmo/MooseX-Types-Structured.git] / lib / MooseX / Meta / TypeConstraint / Structured / Named.pm
CommitLineData
9a491c80 1package MooseX::Meta::TypeConstraint::Structured::Named;
2
3use Moose;
4use Moose::Meta::TypeConstraint ();
9a491c80 5
6extends 'Moose::Meta::TypeConstraint';
bc5c0758 7with 'MooseX::Meta::TypeConstraint::Role::Structured';
9a491c80 8
9=head1 NAME
10
11MooseX::Meta::TypeConstraint::Structured::Named - Structured Type Constraints
12
309c8a6c 13=head1 SYNOPSIS
14
15The follow is example usage:
16
17 use Moose::Util::TypeConstraints;
18 use MooseX::Meta::TypeConstraint::Structured::Named;
19
20 my %required = (key1='Str', key2=>'Int');
21 my %optional = (key3=>'Object');
22
23 my $tc = MooseX::Meta::TypeConstraint::Structured::Named->new(
24 name => 'Dict',
25 parent => find_type_constraint('HashRef'),
26 package_defined_in => __PACKAGE__,
27 signature => {map {
28 $_ => find_type_constraint($required{$_});
29 } keys %required},
30 optional_signature => {map {
31 $_ => find_type_constraint($optional{$_});
32 } keys %optional},
33 );
9a491c80 34
309c8a6c 35=head1 DESCRIPTION
9a491c80 36
37Named structured Constraints expect the internal constraints to be in keys or
309c8a6c 38fields similar to what we expect in a HashRef. Basically, this allows you to
39easily add type constraint checks against values in the wrapping HashRef
40identified by the key name.
9a491c80 41
9a491c80 42=head1 ATTRIBUTES
43
44This class defines the following attributes.
45
46=head2 signature
47
48This is a signature of internal contraints for the contents of the outer
49contraint container.
50
51=cut
52
24dd1d2e 53has '+signature' => (isa=>'HashRef[Moose::Meta::TypeConstraint]');
9a491c80 54
55=head2 optional_signature
56
57This is a signature of internal contraints for the contents of the outer
58contraint container. These are optional constraints.
59
60=cut
61
24dd1d2e 62has '+optional_signature' => (isa=>'HashRef[Moose::Meta::TypeConstraint]');
9a491c80 63
64=head1 METHODS
65
66This class defines the following methods.
67
68=head2 _normalize_args
69
70Get arguments into a known state or die trying. Ideally we try to make this
71into a HashRef so we can match it up with the L</signature> HashRef.
72
73=cut
74
75sub _normalize_args {
76 my ($self, $args) = @_;
77 if(defined $args) {
78 if(ref $args eq 'HASH') {
79 %$args
80 } else {
81 confess 'Signature must be an HashRef type';
82 }
83 } else {
84 confess 'Signature cannot be empty';
85 }
86}
87
88=head2 constraint
89
90The constraint is basically validating the L</signature> against the incoming
91
92=cut
93
94sub constraint {
95 my $self = shift;
96 return sub {
97 my %args = $self->_normalize_args(shift);
67be6b65 98 my @optional_signature;
99
100 if($signature[-1]->isa('MooseX::Meta::TypeConstraint::Structured::Optional')) {
101 my $optional = pop @signature;
102 @optional_signature = @{$optional->signature};
103 }
9a491c80 104
105 ## First make sure all the required type constraints match
6479ca33 106 foreach my $sig_key (keys %{$self->signature}) {
107 my $type_constraint = $self->signature->{$sig_key};
108 if(my $error = $type_constraint->validate($args{$sig_key})) {
9a491c80 109 confess $error;
6479ca33 110 } else {
111 delete $args{$sig_key};
9a491c80 112 }
9a491c80 113 }
114
115 ## Now test the option type constraints.
6479ca33 116 foreach my $arg_key (keys %args) {
117 my $optional_type_constraint = $self->optional_signature->{$arg_key};
9a491c80 118 if(my $error = $optional_type_constraint->validate($args{$arg_key})) {
119 confess $error;
120 }
121 }
122
123 ## If we got this far we passed!
124 return 1;
125 };
126}
127
128=head2 signature_equals
129
130Check that the signature equals another signature.
131
132=cut
133
134sub signature_equals {
135 my ($self, $compared_type_constraint) = @_;
136
137 foreach my $idx (keys %{$self->signature}) {
138 my $this = $self->signature->{$idx};
139 my $that = $compared_type_constraint->signature->{$idx};
140 return unless $this->equals($that);
141 }
142
143 if($self->has_optional_signature) {
144 foreach my $idx (keys %{$self->optional_signature}) {
145 my $this = $self->optional_signature->{$idx};
146 my $that = $compared_type_constraint->optional_signature->{$idx};
147 return unless $this->equals($that);
148 }
149 }
150
151 return 1;
152}
153
9a491c80 154
9a491c80 155
156=head1 AUTHOR
157
158John James Napiorkowski <jjnapiork@cpan.org>
159
160=head1 LICENSE
161
162You may distribute this code under the same terms as Perl itself.
163
164=cut
165
166no Moose; 1;