Added search_class_by_role to Moose::Util
[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
d1e11f1b 8our $VERSION = '0.05';
d44714be 9our $AUTHORITY = 'cpan:STEVAN';
8ee73eeb 10
11__PACKAGE__->meta->add_attribute('type_constraints' => (
12 accessor => 'type_constraints',
13 default => sub { [] }
14));
15
16sub new {
17 my $class = shift;
18 my $self = $class->meta->new_object(@_);
19 return $self;
20}
21
22sub name { join ' | ' => map { $_->name } @{$_[0]->type_constraints} }
23
24# NOTE:
25# this should probably never be used
26# but we include it here for completeness
27sub constraint {
28 my $self = shift;
29 sub { $self->check($_[0]) };
30}
31
32# conform to the TypeConstraint API
33sub parent { undef }
34sub message { undef }
35sub has_message { 0 }
36
37# FIXME:
38# not sure what this should actually do here
39sub coercion { undef }
40
41# this should probably be memoized
42sub has_coercion {
43 my $self = shift;
44 foreach my $type (@{$self->type_constraints}) {
45 return 1 if $type->has_coercion
46 }
47 return 0;
48}
49
50# NOTE:
51# this feels too simple, and may not always DWIM
52# correctly, especially in the presence of
53# close subtype relationships, however it should
54# work for a fair percentage of the use cases
55sub coerce {
56 my $self = shift;
57 my $value = shift;
58 foreach my $type (@{$self->type_constraints}) {
59 if ($type->has_coercion) {
60 my $temp = $type->coerce($value);
61 return $temp if $self->check($temp);
62 }
63 }
64 return undef;
65}
66
67sub _compiled_type_constraint {
68 my $self = shift;
69 return sub {
70 my $value = shift;
71 foreach my $type (@{$self->type_constraints}) {
72 return 1 if $type->check($value);
73 }
74 return undef;
75 }
76}
77
78sub check {
79 my $self = shift;
80 my $value = shift;
81 $self->_compiled_type_constraint->($value);
82}
83
84sub validate {
85 my $self = shift;
86 my $value = shift;
87 my $message;
88 foreach my $type (@{$self->type_constraints}) {
89 my $err = $type->validate($value);
90 return unless defined $err;
91 $message .= ($message ? ' and ' : '') . $err
92 if defined $err;
93 }
94 return ($message . ' in (' . $self->name . ')') ;
95}
96
97sub is_a_type_of {
98 my ($self, $type_name) = @_;
99 foreach my $type (@{$self->type_constraints}) {
100 return 1 if $type->is_a_type_of($type_name);
101 }
102 return 0;
103}
104
105sub is_subtype_of {
106 my ($self, $type_name) = @_;
107 foreach my $type (@{$self->type_constraints}) {
108 return 1 if $type->is_subtype_of($type_name);
109 }
110 return 0;
111}
112
d1e11f1b 113## hand optimized constraints
114
115# NOTE:
116# it will just use all the hand optimized
117# type constraints from it's list of type
118# constraints automatically, but there is
119# no simple way to optimize it even more
120# (without B::Deparse or something). So
121# we just stop here.
122# - SL
123
124sub has_hand_optimized_type_constraint { 0 }
125sub hand_optimized_type_constraint { undef }
126
8ee73eeb 1271;
128
129__END__
130
131=pod
132
39b3bc94 133=head1 NAME
134
ecb59493 135Moose::Meta::TypeConstraint::Union - A union of Moose type constraints
39b3bc94 136
137=head1 DESCRIPTION
138
ecb59493 139This metaclass represents a union of Moose type constraints. More
140details to be explained later (possibly in a Cookbook::Recipe).
141
142This actually used to be part of Moose::Meta::TypeConstraint, but it
143is now better off in it's own file.
144
39b3bc94 145=head1 METHODS
146
ecb59493 147This class is not a subclass of Moose::Meta::TypeConstraint,
148but it does provide the same API
149
39b3bc94 150=over 4
151
ecb59493 152=item B<meta>
39b3bc94 153
ecb59493 154=item B<new>
39b3bc94 155
ecb59493 156=item B<name>
157
158=item B<type_constraints>
39b3bc94 159
160=item B<constraint>
161
ecb59493 162=back
39b3bc94 163
ecb59493 164=head2 Overriden methods
165
166=over 4
167
168=item B<check>
169
170=item B<coerce>
171
172=item B<validate>
39b3bc94 173
174=item B<is_a_type_of>
175
176=item B<is_subtype_of>
177
ecb59493 178=back
39b3bc94 179
ecb59493 180=head2 Empty or Stub methods
39b3bc94 181
ecb59493 182These methods tend to not be very relevant in
183the context of a union. Either that or they are
184just difficult to specify and not very useful
185anyway. They are here for completeness.
39b3bc94 186
ecb59493 187=over 4
39b3bc94 188
189=item B<parent>
190
ecb59493 191=item B<coercion>
39b3bc94 192
ecb59493 193=item B<has_coercion>
194
195=item B<message>
196
197=item B<has_message>
39b3bc94 198
199=back
200
201=head1 BUGS
202
203All complex software has bugs lurking in it, and this module is no
204exception. If you find a bug please either email me, or add the bug
205to cpan-RT.
206
207=head1 AUTHOR
208
209Stevan Little E<lt>stevan@iinteractive.comE<gt>
210
39b3bc94 211=head1 COPYRIGHT AND LICENSE
212
b77fdbed 213Copyright 2006, 2007 by Infinity Interactive, Inc.
39b3bc94 214
215L<http://www.iinteractive.com>
216
217This library is free software; you can redistribute it and/or modify
218it under the same terms as Perl itself.
219
8ee73eeb 220=cut