35fa726e01cefec63a06141e27cfe0174269713c
[gitmo/Moose.git] / lib / Moose / Meta / TypeCoercion.pm
1
2 package Moose::Meta::TypeCoercion;
3
4 use strict;
5 use warnings;
6 use metaclass;
7
8 use Carp 'confess';
9
10 use Moose::Meta::Attribute;
11 use Moose::Util::TypeConstraints ();
12
13 our $VERSION   = '0.03';
14 our $AUTHORITY = 'cpan:STEVAN';
15
16 __PACKAGE__->meta->add_attribute('type_coercion_map' => (
17     reader  => 'type_coercion_map',
18     default => sub { [] }
19 ));
20
21 __PACKAGE__->meta->add_attribute(
22     Moose::Meta::Attribute->new('type_constraint' => (
23         reader   => 'type_constraint',
24         weak_ref => 1
25     ))
26 );
27
28 # private accessor
29 __PACKAGE__->meta->add_attribute('compiled_type_coercion' => (
30     accessor => '_compiled_type_coercion'
31 ));
32
33 sub new { 
34     my $class = shift;
35     my $self  = $class->meta->new_object(@_);
36     $self->compile_type_coercion();
37     return $self;
38 }
39
40 sub compile_type_coercion {
41     my $self = shift;
42     my @coercion_map = @{$self->type_coercion_map};
43     my @coercions;
44     while (@coercion_map) {
45         my ($constraint_name, $action) = splice(@coercion_map, 0, 2);
46         my $type_constraint = Moose::Util::TypeConstraints::find_type_constraint($constraint_name);
47         (defined $type_constraint)
48             || confess "Could not find the type constraint ($constraint_name) to coerce from";
49         push @coercions => [ 
50             $type_constraint->_compiled_type_constraint, 
51             $action 
52         ];
53     }
54     $self->_compiled_type_coercion(sub { 
55         my $thing = shift;
56         foreach my $coercion (@coercions) {
57             my ($constraint, $converter) = @$coercion;
58             if (defined $constraint->($thing)) {
59                             local $_ = $thing;                
60                 return $converter->($thing);
61             }
62         }
63         return $thing;
64     });    
65 }
66
67 sub coerce { $_[0]->_compiled_type_coercion->($_[1]) }
68
69
70 1;
71
72 __END__
73
74 =pod
75
76 =head1 NAME
77
78 Moose::Meta::TypeCoercion - The Moose Type Coercion metaclass
79
80 =head1 DESCRIPTION
81
82 For the most part, the only time you will ever encounter an 
83 instance of this class is if you are doing some serious deep 
84 introspection. This API should not be considered final, but 
85 it is B<highly unlikely> that this will matter to a regular 
86 Moose user.
87
88 If you wish to use features at this depth, please come to the 
89 #moose IRC channel on irc.perl.org and we can talk :)
90
91 =head1 METHODS
92
93 =over 4
94
95 =item B<meta>
96
97 =item B<new>
98
99 =item B<compile_type_coercion>
100
101 =item B<coerce>
102
103 =item B<type_coercion_map>
104
105 =item B<type_constraint>
106
107 =back
108
109 =head1 BUGS
110
111 All complex software has bugs lurking in it, and this module is no 
112 exception. If you find a bug please either email me, or add the bug
113 to cpan-RT.
114
115 =head1 AUTHOR
116
117 Stevan Little E<lt>stevan@iinteractive.comE<gt>
118
119 =head1 COPYRIGHT AND LICENSE
120
121 Copyright 2006, 2007 by Infinity Interactive, Inc.
122
123 L<http://www.iinteractive.com>
124
125 This library is free software; you can redistribute it and/or modify
126 it under the same terms as Perl itself. 
127
128 =cut