2 package Moose::Meta::TypeConstraint;
8 use Sub::Name 'subname';
10 use Scalar::Util 'blessed';
12 our $VERSION = '0.04';
14 __PACKAGE__->meta->add_attribute('name' => (reader => 'name' ));
15 __PACKAGE__->meta->add_attribute('parent' => (reader => 'parent' ));
16 __PACKAGE__->meta->add_attribute('constraint' => (reader => 'constraint'));
17 __PACKAGE__->meta->add_attribute('message' => (
18 accessor => 'message',
19 predicate => 'has_message'
21 __PACKAGE__->meta->add_attribute('coercion' => (
22 accessor => 'coercion',
23 predicate => 'has_coercion'
27 __PACKAGE__->meta->add_attribute('compiled_type_constraint' => (
28 accessor => '_compiled_type_constraint'
33 my $self = $class->meta->new_object(@_);
34 $self->compile_type_constraint();
38 sub compile_type_constraint {
40 my $check = $self->constraint;
42 || confess "Could not compile type constraint '" . $self->name . "' because no constraint check";
43 my $parent = $self->parent;
44 if (defined $parent) {
45 # we have a subtype ...
46 $parent = $parent->_compiled_type_constraint;
47 $self->_compiled_type_constraint(subname $self->name => sub {
49 return undef unless defined $parent->($_[0]) && $check->($_[0]);
55 $self->_compiled_type_constraint(subname $self->name => sub {
57 return undef unless $check->($_[0]);
63 sub check { $_[0]->_compiled_type_constraint->($_[1]) }
66 my ($self, $value) = @_;
67 if ($self->_compiled_type_constraint->($value)) {
71 if ($self->has_message) {
73 return $self->message->($value);
76 return "Validation failed for '" . $self->name . "' failed";
82 my ($self, $type_name) = @_;
83 ($self->name eq $type_name || $self->is_subtype_of($type_name));
87 my ($self, $type_name) = @_;
89 while (my $parent = $current->parent) {
90 return 1 if $parent->name eq $type_name;
97 my ($class, @type_constraints) = @_;
98 (scalar @type_constraints >= 2)
99 || confess "You must pass in at least 2 Moose::Meta::TypeConstraint instances to make a union";
100 (blessed($_) && $_->isa('Moose::Meta::TypeConstraint'))
101 || confess "You must pass in only Moose::Meta::TypeConstraint instances to make unions"
102 foreach @type_constraints;
103 return Moose::Meta::TypeConstraint::Union->new(
104 type_constraints => \@type_constraints
108 package Moose::Meta::TypeConstraint::Union;
114 our $VERSION = '0.01';
116 __PACKAGE__->meta->add_attribute('type_constraints' => (
117 accessor => 'type_constraints',
118 default => sub { [] }
123 my $self = $class->meta->new_object(@_);
127 sub name { join ' | ' => map { $_->name } @{$_[0]->type_constraints} }
130 # this should probably never be used
131 # but we include it here for completeness
134 sub { $self->check($_[0]) };
137 # conform to the TypeConstraint API
139 sub coercion { undef }
140 sub has_coercion { 0 }
141 sub message { undef }
142 sub has_message { 0 }
147 foreach my $type (@{$self->type_constraints}) {
148 return 1 if $type->check($value);
157 foreach my $type (@{$self->type_constraints}) {
158 my $err = $type->validate($value);
159 return unless defined $err;
160 $message .= ($message ? ' and ' : '') . $err
163 return ($message . ' in (' . $self->name . ')') ;
167 my ($self, $type_name) = @_;
168 foreach my $type (@{$self->type_constraints}) {
169 return 1 if $type->is_a_type_of($type_name);
175 my ($self, $type_name) = @_;
176 foreach my $type (@{$self->type_constraints}) {
177 return 1 if $type->is_subtype_of($type_name);
190 Moose::Meta::TypeConstraint - The Moose Type Constraint metaclass
194 For the most part, the only time you will ever encounter an
195 instance of this class is if you are doing some serious deep
196 introspection. This API should not be considered final, but
197 it is B<highly unlikely> that this will matter to a regular
200 If you wish to use features at this depth, please come to the
201 #moose IRC channel on irc.perl.org and we can talk :)
211 =item B<is_a_type_of ($type_name)>
213 This checks the current type name, and if it does not match,
214 checks if it is a subtype of it.
216 =item B<is_subtype_of ($type_name)>
218 =item B<compile_type_constraint>
220 =item B<check ($value)>
222 This method will return a true (C<1>) if the C<$value> passes the
223 constraint, and false (C<0>) otherwise.
225 =item B<validate ($value)>
227 This method is similar to C<check>, but it deals with the error
228 message. If the C<$value> passes the constraint, C<undef> will be
229 returned. If the C<$value> does B<not> pass the constraint, then
230 the C<message> will be used to construct a custom error message.
242 =item B<has_coercion>
250 =item B<union (@type_constraints)>
256 All complex software has bugs lurking in it, and this module is no
257 exception. If you find a bug please either email me, or add the bug
262 Stevan Little E<lt>stevan@iinteractive.comE<gt>
264 =head1 COPYRIGHT AND LICENSE
266 Copyright 2006 by Infinity Interactive, Inc.
268 L<http://www.iinteractive.com>
270 This library is free software; you can redistribute it and/or modify
271 it under the same terms as Perl itself.