uploadin
[gitmo/Moose.git] / lib / Moose / Meta / Class.pm
1
2 package Moose::Meta::Class;
3
4 use strict;
5 use warnings;
6
7 use Carp         'confess';
8 use Scalar::Util 'weaken', 'blessed';
9
10 our $VERSION = '0.04';
11
12 use base 'Class::MOP::Class';
13
14 sub construct_instance {
15     my ($class, %params) = @_;
16     my $instance = $params{'__INSTANCE__'} || {};
17     foreach my $attr ($class->compute_all_applicable_attributes()) {
18         my $init_arg = $attr->init_arg();
19         # try to fetch the init arg from the %params ...
20         my $val;        
21         if (exists $params{$init_arg}) {
22             $val = $params{$init_arg};
23         }
24         else {
25             # skip it if it's lazy
26             next if $attr->is_lazy;
27             # and die if it is required            
28             confess "Attribute (" . $attr->name . ") is required" 
29                 if $attr->is_required
30         }
31         # if nothing was in the %params, we can use the 
32         # attribute's default value (if it has one)
33         if (!defined $val && $attr->has_default) {
34             $val = $attr->default($instance); 
35         }
36                 if (defined $val) {
37                     if ($attr->has_type_constraint) {
38                     if ($attr->should_coerce && $attr->type_constraint->has_coercion) {
39                         $val = $attr->type_constraint->coercion->coerce($val);
40                     }   
41                 (defined($attr->type_constraint->check($val))) 
42                     || confess "Attribute (" . $attr->name . ") does not pass the type contraint with '$val'";                  
43             }
44                 }
45         $instance->{$attr->name} = $val;
46         if (defined $val && $attr->is_weak_ref) {
47             weaken($instance->{$attr->name});
48         }
49     }
50     return $instance;
51 }
52
53 sub has_method {
54     my ($self, $method_name) = @_;
55     (defined $method_name && $method_name)
56         || confess "You must define a method name";    
57
58     my $sub_name = ($self->name . '::' . $method_name);   
59     
60     no strict 'refs';
61     return 0 if !defined(&{$sub_name});        
62         my $method = \&{$sub_name};
63         
64         return 1 if blessed($method) && $method->isa('Moose::Meta::Role::Method');
65     return $self->SUPER::has_method($method_name);    
66 }
67
68
69 sub add_override_method_modifier {
70     my ($self, $name, $method, $_super_package) = @_;
71     # need this for roles ...
72     $_super_package ||= $self->name;
73     my $super = $self->find_next_method_by_name($name);
74     (defined $super)
75         || confess "You cannot override '$name' because it has no super method";    
76     $self->add_method($name => sub {
77         my @args = @_;
78         no strict   'refs';
79         no warnings 'redefine';
80         local *{$_super_package . '::super'} = sub { $super->(@args) };
81         return $method->(@args);
82     });
83 }
84
85 sub add_augment_method_modifier {
86     my ($self, $name, $method) = @_;    
87     my $super = $self->find_next_method_by_name($name);
88     (defined $super)
89         || confess "You cannot augment '$name' because it has no super method";
90     $self->add_method($name => sub {
91         my @args = @_;
92         no strict   'refs';
93         no warnings 'redefine';
94         local *{$super->package_name . '::inner'} = sub { $method->(@args) };
95         return $super->(@args);
96     });    
97 }
98
99 1;
100
101 __END__
102
103 =pod
104
105 =head1 NAME
106
107 Moose::Meta::Class - The Moose metaclass
108
109 =head1 DESCRIPTION
110
111 This is a subclass of L<Class::MOP::Class> with Moose specific 
112 extensions.
113
114 For the most part, the only time you will ever encounter an 
115 instance of this class is if you are doing some serious deep 
116 introspection. To really understand this class, you need to refer 
117 to the L<Class::MOP::Class> documentation.
118
119 =head1 METHODS
120
121 =over 4
122
123 =item B<construct_instance>
124
125 This provides some Moose specific extensions to this method, you 
126 almost never call this method directly unless you really know what 
127 you are doing. 
128
129 This method makes sure to handle the moose weak-ref, type-constraint
130 and type coercion features. 
131
132 =item B<has_method ($name)>
133
134 This accomidates Moose::Meta::Role::Method instances, which are 
135 aliased, instead of added, but still need to be counted as valid 
136 methods.
137
138 =item B<add_override_method_modifier ($name, $method)>
139
140 =item B<add_augment_method_modifier ($name, $method)>
141
142 =back
143
144 =head1 BUGS
145
146 All complex software has bugs lurking in it, and this module is no 
147 exception. If you find a bug please either email me, or add the bug
148 to cpan-RT.
149
150 =head1 AUTHOR
151
152 Stevan Little E<lt>stevan@iinteractive.comE<gt>
153
154 =head1 COPYRIGHT AND LICENSE
155
156 Copyright 2006 by Infinity Interactive, Inc.
157
158 L<http://www.iinteractive.com>
159
160 This library is free software; you can redistribute it and/or modify
161 it under the same terms as Perl itself. 
162
163 =cut