* role exclusion and aliasiing now works in composite roles too
[gitmo/Moose.git] / lib / Moose / Meta / TypeConstraint / Parameterized.pm
CommitLineData
0fbd4b0a 1package Moose::Meta::TypeConstraint::Parameterized;
d67145ed 2
3use strict;
4use warnings;
5use metaclass;
6
7use Scalar::Util 'blessed';
8use Carp 'confess';
acb8a5db 9use Moose::Util::TypeConstraints;
d67145ed 10
25374f01 11our $VERSION = '0.02';
d67145ed 12our $AUTHORITY = 'cpan:STEVAN';
13
14use base 'Moose::Meta::TypeConstraint';
15
0fbd4b0a 16__PACKAGE__->meta->add_attribute('type_parameter' => (
17 accessor => 'type_parameter',
18 predicate => 'has_type_parameter',
d67145ed 19));
20
21sub compile_type_constraint {
22 my $self = shift;
23
0fbd4b0a 24 ($self->has_type_parameter)
25 || confess "You cannot create a Higher Order type without a type parameter";
d67145ed 26
0fbd4b0a 27 my $type_parameter = $self->type_parameter;
d67145ed 28
0fbd4b0a 29 (blessed $type_parameter && $type_parameter->isa('Moose::Meta::TypeConstraint'))
30 || confess "The type parameter must be a Moose meta type";
d67145ed 31
32 my $constraint;
acb8a5db 33 my $name = $self->parent->name;
34
35 my $array_coercion =
36 Moose::Util::TypeConstraints::find_type_constraint('ArrayRef')
37 ->coercion;
38
39 my $hash_coercion =
40 Moose::Util::TypeConstraints::find_type_constraint('HashRef')
41 ->coercion;
42
d093fcf9 43 # ArrayRef[Foo] will check each element for the Foo constraint
39aba5c9 44 my $array_constraint = sub {
45 foreach my $x (@$_) {
46 ($type_parameter->check($x)) || return
47 } 1;
48 };
49
d093fcf9 50 # HashRef[Foo] will check each value for the Foo constraint
39aba5c9 51 my $hash_constraint = sub {
52 foreach my $x (values %$_) {
53 ($type_parameter->check($x)) || return
54 } 1;
55 };
56
d093fcf9 57 # if this is a subtype of ArrayRef, then we can use the ArrayRef[Foo]
58 # constraint directly
39aba5c9 59 if ($self->is_subtype_of('ArrayRef')) {
60 $constraint = $array_constraint;
d67145ed 61 }
d093fcf9 62 # if this is a subtype of HashRef, then we can use the HashRef[Foo]
63 # constraint directly
39aba5c9 64 elsif ($self->is_subtype_of('HashRef')) {
65 $constraint = $hash_constraint;
d67145ed 66 }
d093fcf9 67 # if we can coerce this type to an ArrayRef, do it and use the regular
68 # ArrayRef[Foo] constraint
acb8a5db 69 elsif ($array_coercion && $array_coercion->has_coercion_for_type($name)) {
70 $constraint = sub {
71 local $_ = $array_coercion->coerce($_);
72 $array_constraint->(@_);
73 };
74 }
d093fcf9 75 # if we can coerce this type to a HashRef, do it and use the regular
76 # HashRef[Foo] constraint
acb8a5db 77 elsif ($hash_coercion && $hash_coercion->has_coercion_for_type($name)) {
78 $constraint = sub {
79 local $_ = $hash_coercion->coerce($_);
80 $hash_constraint->(@_);
81 };
82 }
d67145ed 83 else {
acb8a5db 84 confess "The " . $self->name . " constraint cannot be used, because " . $name . " doesn't subtype or coerce ArrayRef or HashRef.";
d67145ed 85 }
86
87 $self->_set_constraint($constraint);
88
89 $self->SUPER::compile_type_constraint;
90}
91
921;
93
94__END__
95
96
97=pod
98
99=head1 NAME
100
0fbd4b0a 101Moose::Meta::TypeConstraint::Parameterized - Higher Order type constraints for Moose
d67145ed 102
d67145ed 103=head1 METHODS
104
105=over 4
106
107=item B<compile_type_constraint>
108
0fbd4b0a 109=item B<type_parameter>
d67145ed 110
0fbd4b0a 111=item B<has_type_parameter>
d67145ed 112
113=item B<meta>
114
115=back
116
117=head1 BUGS
118
119All complex software has bugs lurking in it, and this module is no
120exception. If you find a bug please either email me, or add the bug
121to cpan-RT.
122
123=head1 AUTHOR
124
125Stevan Little E<lt>stevan@iinteractive.comE<gt>
126
127=head1 COPYRIGHT AND LICENSE
128
778db3ac 129Copyright 2006-2008 by Infinity Interactive, Inc.
d67145ed 130
131L<http://www.iinteractive.com>
132
133This library is free software; you can redistribute it and/or modify
134it under the same terms as Perl itself.
135
136=cut