Merge the parameterized_type_fixes to trunk
[gitmo/Moose.git] / lib / Moose / Meta / TypeConstraint / Union.pm
CommitLineData
8ee73eeb 1
2package Moose::Meta::TypeConstraint::Union;
3
4use strict;
5use warnings;
6use metaclass;
7
3726f905 8use Moose::Meta::TypeCoercion::Union;
9
2351f08e 10our $VERSION = '0.59';
75b95414 11$VERSION = eval $VERSION;
d44714be 12our $AUTHORITY = 'cpan:STEVAN';
8ee73eeb 13
d67145ed 14use base 'Moose::Meta::TypeConstraint';
15
8ee73eeb 16__PACKAGE__->meta->add_attribute('type_constraints' => (
17 accessor => 'type_constraints',
18 default => sub { [] }
19));
20
21sub new {
3726f905 22 my ($class, %options) = @_;
23 my $self = $class->SUPER::new(
90e78884 24 name => (join '|' => sort {$a cmp $b}
25 map { $_->name } @{$options{type_constraints}}),
3726f905 26 parent => undef,
27 message => undef,
28 hand_optimized_type_constraint => undef,
29 compiled_type_constraint => sub {
30 my $value = shift;
31 foreach my $type (@{$options{type_constraints}}) {
32 return 1 if $type->check($value);
33 }
34 return undef;
35 },
36 %options
37 );
38 $self->_set_constraint(sub { $self->check($_[0]) });
39 $self->coercion(Moose::Meta::TypeCoercion::Union->new(
40 type_constraint => $self
41 ));
8ee73eeb 42 return $self;
43}
44
dabed765 45sub equals {
46 my ( $self, $type_or_name ) = @_;
47
48 my $other = Moose::Util::TypeConstraints::find_type_constraint($type_or_name);
49
50 return unless $other->isa(__PACKAGE__);
51
52 my @self_constraints = @{ $self->type_constraints };
53 my @other_constraints = @{ $other->type_constraints };
54
55 return unless @self_constraints == @other_constraints;
56
57 # FIXME presort type constraints for efficiency?
58 constraint: foreach my $constraint ( @self_constraints ) {
59 for ( my $i = 0; $i < @other_constraints; $i++ ) {
60 if ( $constraint->equals($other_constraints[$i]) ) {
61 splice @other_constraints, $i, 1;
62 next constraint;
63 }
64 }
65 }
66
67 return @other_constraints == 0;
68}
69
70sub parents {
71 my $self = shift;
72 $self->type_constraints;
73}
74
8ee73eeb 75sub validate {
3726f905 76 my ($self, $value) = @_;
8ee73eeb 77 my $message;
78 foreach my $type (@{$self->type_constraints}) {
79 my $err = $type->validate($value);
80 return unless defined $err;
81 $message .= ($message ? ' and ' : '') . $err
82 if defined $err;
83 }
84 return ($message . ' in (' . $self->name . ')') ;
85}
86
87sub is_a_type_of {
88 my ($self, $type_name) = @_;
89 foreach my $type (@{$self->type_constraints}) {
90 return 1 if $type->is_a_type_of($type_name);
91 }
92 return 0;
93}
94
95sub is_subtype_of {
96 my ($self, $type_name) = @_;
97 foreach my $type (@{$self->type_constraints}) {
98 return 1 if $type->is_subtype_of($type_name);
99 }
100 return 0;
101}
102
9ceb576e 103sub create_childtype {
104 my ($self, %opts) = @_;
105 my $class = ref $self;
106 my $constraint = Moose::Meta::TypeConstraint->new(%opts, parent => $self);
107
108 # if we have a type constraint union, and no
109 # type check, this means we are just aliasing
110 # the union constraint, which means we need to
111 # handle this differently.
112 # - SL
113 if (
114 not(defined $opts{constraint})
115 && $self->has_coercion
116 ) {
117 $constraint->coercion(Moose::Meta::TypeCoercion::Union->new(
118 type_constraint => $self,
119 ));
120 }
121
122 return $constraint;
123}
124
8ee73eeb 1251;
126
127__END__
128
129=pod
130
39b3bc94 131=head1 NAME
132
ecb59493 133Moose::Meta::TypeConstraint::Union - A union of Moose type constraints
39b3bc94 134
135=head1 DESCRIPTION
136
ecb59493 137This metaclass represents a union of Moose type constraints. More
5cfe3805 138details to be explained later (possibly in a Cookbook recipe).
ecb59493 139
140This actually used to be part of Moose::Meta::TypeConstraint, but it
141is now better off in it's own file.
142
39b3bc94 143=head1 METHODS
144
ecb59493 145This class is not a subclass of Moose::Meta::TypeConstraint,
146but it does provide the same API
147
39b3bc94 148=over 4
149
ecb59493 150=item B<meta>
39b3bc94 151
ecb59493 152=item B<new>
39b3bc94 153
ecb59493 154=item B<name>
155
156=item B<type_constraints>
39b3bc94 157
dabed765 158=item B<parents>
159
39b3bc94 160=item B<constraint>
161
1b58cb9f 162=item B<includes_type>
163
dabed765 164=item B<equals>
165
ecb59493 166=back
39b3bc94 167
ecb59493 168=head2 Overriden methods
169
170=over 4
171
172=item B<check>
173
174=item B<coerce>
175
176=item B<validate>
39b3bc94 177
178=item B<is_a_type_of>
179
180=item B<is_subtype_of>
181
ecb59493 182=back
39b3bc94 183
ecb59493 184=head2 Empty or Stub methods
39b3bc94 185
ecb59493 186These methods tend to not be very relevant in
187the context of a union. Either that or they are
188just difficult to specify and not very useful
189anyway. They are here for completeness.
39b3bc94 190
ecb59493 191=over 4
39b3bc94 192
193=item B<parent>
194
ecb59493 195=item B<coercion>
39b3bc94 196
ecb59493 197=item B<has_coercion>
198
199=item B<message>
200
201=item B<has_message>
39b3bc94 202
0eec94be 203=item B<hand_optimized_type_constraint>
204
205=item B<has_hand_optimized_type_constraint>
206
9ceb576e 207=item B<create_childtype>
208
39b3bc94 209=back
210
211=head1 BUGS
212
213All complex software has bugs lurking in it, and this module is no
214exception. If you find a bug please either email me, or add the bug
215to cpan-RT.
216
217=head1 AUTHOR
218
219Stevan Little E<lt>stevan@iinteractive.comE<gt>
220
39b3bc94 221=head1 COPYRIGHT AND LICENSE
222
778db3ac 223Copyright 2006-2008 by Infinity Interactive, Inc.
39b3bc94 224
225L<http://www.iinteractive.com>
226
227This library is free software; you can redistribute it and/or modify
228it under the same terms as Perl itself.
229
8ee73eeb 230=cut