bump version to 0.93_03
[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
7a10df4d 10our $VERSION = '0.93_03';
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
d03bd989 21sub new {
3726f905 22 my ($class, %options) = @_;
816ef2e2 23
24 my $name = join '|' => sort { $a cmp $b }
25 map { $_->name } @{ $options{type_constraints} };
26
3726f905 27 my $self = $class->SUPER::new(
816ef2e2 28 name => $name,
29 %options,
3726f905 30 );
816ef2e2 31
3726f905 32 $self->_set_constraint(sub { $self->check($_[0]) });
33 $self->coercion(Moose::Meta::TypeCoercion::Union->new(
34 type_constraint => $self
35 ));
8ee73eeb 36 return $self;
37}
38
816ef2e2 39sub _actually_compile_type_constraint {
40 my $self = shift;
41
42 my @constraints = @{ $self->type_constraints };
43
44 return sub {
45 my $value = shift;
46 foreach my $type (@constraints) {
47 return 1 if $type->check($value);
48 }
49 return undef;
50 };
51}
52
53
dabed765 54sub equals {
55 my ( $self, $type_or_name ) = @_;
56
57 my $other = Moose::Util::TypeConstraints::find_type_constraint($type_or_name);
58
59 return unless $other->isa(__PACKAGE__);
60
61 my @self_constraints = @{ $self->type_constraints };
62 my @other_constraints = @{ $other->type_constraints };
63
64 return unless @self_constraints == @other_constraints;
65
66 # FIXME presort type constraints for efficiency?
67 constraint: foreach my $constraint ( @self_constraints ) {
68 for ( my $i = 0; $i < @other_constraints; $i++ ) {
69 if ( $constraint->equals($other_constraints[$i]) ) {
70 splice @other_constraints, $i, 1;
71 next constraint;
72 }
73 }
74 }
75
76 return @other_constraints == 0;
77}
78
79sub parents {
80 my $self = shift;
81 $self->type_constraints;
82}
83
8ee73eeb 84sub validate {
3726f905 85 my ($self, $value) = @_;
8ee73eeb 86 my $message;
87 foreach my $type (@{$self->type_constraints}) {
88 my $err = $type->validate($value);
89 return unless defined $err;
90 $message .= ($message ? ' and ' : '') . $err
91 if defined $err;
92 }
d03bd989 93 return ($message . ' in (' . $self->name . ')') ;
8ee73eeb 94}
95
96sub is_a_type_of {
97 my ($self, $type_name) = @_;
98 foreach my $type (@{$self->type_constraints}) {
99 return 1 if $type->is_a_type_of($type_name);
100 }
d03bd989 101 return 0;
8ee73eeb 102}
103
104sub is_subtype_of {
105 my ($self, $type_name) = @_;
106 foreach my $type (@{$self->type_constraints}) {
107 return 1 if $type->is_subtype_of($type_name);
108 }
109 return 0;
110}
111
85a9908f 112sub create_child_type {
622c9332 113 my ( $self, %opts ) = @_;
114
115 my $constraint
116 = Moose::Meta::TypeConstraint->new( %opts, parent => $self );
117
9ceb576e 118 # if we have a type constraint union, and no
119 # type check, this means we are just aliasing
120 # the union constraint, which means we need to
121 # handle this differently.
122 # - SL
622c9332 123 if ( not( defined $opts{constraint} )
124 && $self->has_coercion ) {
125 $constraint->coercion(
126 Moose::Meta::TypeCoercion::Union->new(
127 type_constraint => $self,
128 )
129 );
9ceb576e 130 }
622c9332 131
9ceb576e 132 return $constraint;
133}
134
8ee73eeb 1351;
136
137__END__
138
139=pod
140
39b3bc94 141=head1 NAME
142
ecb59493 143Moose::Meta::TypeConstraint::Union - A union of Moose type constraints
39b3bc94 144
145=head1 DESCRIPTION
146
ae2f99ea 147This metaclass represents a union of type constraints. A union takes
148multiple type constraints, and is true if any one of its member
149constraints is true.
ecb59493 150
ae2f99ea 151=head1 INHERITANCE
ecb59493 152
ae2f99ea 153C<Moose::Meta::TypeConstraint::Union> is a subclass of
154L<Moose::Meta::TypeConstraint>.
ecb59493 155
39b3bc94 156=over 4
157
ae2f99ea 158=item B<< Moose::Meta::TypeConstraint::Union->new(%options) >>
39b3bc94 159
ae2f99ea 160This creates a new class type constraint based on the given
161C<%options>.
1b58cb9f 162
ae2f99ea 163It takes the same options as its parent. It also requires an
164additional option, C<type_constraints>. This is an array reference
165containing the L<Moose::Meta::TypeConstraint> objects that are the
166members of the union type. The C<name> option defaults to the names
167all of these member types sorted and then joined by a pipe (|).
dabed765 168
ae2f99ea 169The constructor sets the implementation of the constraint so that is
170simply calls C<check> on the newly created object.
ecb59493 171
ae2f99ea 172Finally, the constructor also makes sure that the object's C<coercion>
173attribute is a L<Moose::Meta::TypeCoercion::Union> object.
ecb59493 174
ae2f99ea 175=item B<< $constraint->type_constraints >>
ecb59493 176
ae2f99ea 177This returns the array reference of C<type_constraints> provided to
178the constructor.
39b3bc94 179
ae2f99ea 180=item B<< $constraint->parents >>
39b3bc94 181
ae2f99ea 182This returns the same constraint as the C<type_constraints> method.
39b3bc94 183
ae2f99ea 184=item B<< $constraint->check($value) >>
39b3bc94 185
ae2f99ea 186=item B<< $constraint->validate($value) >>
39b3bc94 187
ae2f99ea 188These two methods simply call the relevant method on each of the
189member type constraints in the union. If any type accepts the value,
190the value is valid.
39b3bc94 191
ae2f99ea 192With C<validate> the error message returned includes all of the error
193messages returned by the member type constraints.
39b3bc94 194
ae2f99ea 195=item B<< $constraint->equals($type_name_or_object) >>
39b3bc94 196
ae2f99ea 197A type is considered equal if it is also a union type, and the two
198unions have the same member types.
39b3bc94 199
ae2f99ea 200=item B<< $constraint->is_a_type_of($type_name_or_object) >>
ecb59493 201
ae2f99ea 202This returns true if any of the member type constraints return true
203for the C<is_a_type_of> method.
ecb59493 204
ae2f99ea 205=item B<< $constraint->is_subtype_of >>
39b3bc94 206
ae2f99ea 207This returns true if any of the member type constraints return true
208for the C<is_a_subtype_of> method.
0eec94be 209
ae2f99ea 210=item B<< $constraint->create_child_type(%options) >>
0eec94be 211
ae2f99ea 212This returns a new L<Moose::Meta::TypeConstraint> object with the type
213as its parent.
9ceb576e 214
39b3bc94 215=back
216
217=head1 BUGS
218
d4048ef3 219See L<Moose/BUGS> for details on reporting bugs.
39b3bc94 220
221=head1 AUTHOR
222
223Stevan Little E<lt>stevan@iinteractive.comE<gt>
224
39b3bc94 225=head1 COPYRIGHT AND LICENSE
226
7e0492d3 227Copyright 2006-2010 by Infinity Interactive, Inc.
39b3bc94 228
229L<http://www.iinteractive.com>
230
231This library is free software; you can redistribute it and/or modify
232it under the same terms as Perl itself.
233
8ee73eeb 234=cut