Assign the value of the parameter to a lexical so we don't have to continually look...
[gitmo/Mouse.git] / lib / Mouse / Meta / Class.pm
CommitLineData
c3398f5b 1#!/usr/bin/env perl
306290e8 2package Mouse::Meta::Class;
c3398f5b 3use strict;
4use warnings;
5
fc1d8369 6use Mouse::Meta::Method::Constructor;
8fcbe7fb 7use Mouse::Util qw/get_linear_isa blessed/;
7a59f4e8 8use Carp 'confess';
72b88a88 9
c3398f5b 10do {
11 my %METACLASS_CACHE;
72b88a88 12
13 # because Mouse doesn't introspect existing classes, we're forced to
14 # only pay attention to other Mouse classes
15 sub _metaclass_cache {
16 my $class = shift;
17 my $name = shift;
18 return $METACLASS_CACHE{$name};
19 }
20
c3398f5b 21 sub initialize {
22 my $class = shift;
23 my $name = shift;
24 $METACLASS_CACHE{$name} = $class->new(name => $name)
25 if !exists($METACLASS_CACHE{$name});
26 return $METACLASS_CACHE{$name};
27 }
28};
29
30sub new {
31 my $class = shift;
6cbacbf6 32 my %args = @_;
c3398f5b 33
34 $args{attributes} = {};
35 $args{superclasses} = do {
36 no strict 'refs';
37 \@{ $args{name} . '::ISA' };
38 };
39
40 bless \%args, $class;
41}
42
43sub name { $_[0]->{name} }
44
45sub superclasses {
46 my $self = shift;
47
48 if (@_) {
49 Mouse::load_class($_) for @_;
50 @{ $self->{superclasses} } = @_;
51 }
52
53 @{ $self->{superclasses} };
54}
55
d16fe7d7 56sub add_method {
57 my $self = shift;
58 my $name = shift;
59 my $code = shift;
60
61 my $pkg = $self->name;
62
63 no strict 'refs';
64 *{ $pkg . '::' . $name } = $code;
65}
66
2e92bb89 67# copied from Class::Inspector
68sub get_method_list {
69 my $self = shift;
70 my $name = $self->name;
71
72 no strict 'refs';
73 # Get all the CODE symbol table entries
74 my @functions = grep !/^meta$/,
75 grep { /\A[^\W\d]\w*\z/o }
76 grep { defined &{"${name}::$_"} }
77 keys %{"${name}::"};
78 wantarray ? @functions : \@functions;
79}
80
c3398f5b 81sub add_attribute {
82 my $self = shift;
83 my $attr = shift;
84
85 $self->{'attributes'}{$attr->name} = $attr;
86}
87
72b88a88 88sub compute_all_applicable_attributes {
89 my $self = shift;
90 my (@attr, %seen);
91
92 for my $class ($self->linearized_isa) {
93 my $meta = $self->_metaclass_cache($class)
94 or next;
95
96 for my $name (keys %{ $meta->get_attribute_map }) {
97 next if $seen{$name}++;
98 push @attr, $meta->get_attribute($name);
99 }
100 }
101
102 return @attr;
103}
104
c3398f5b 105sub get_attribute_map { $_[0]->{attributes} }
66eea168 106sub has_attribute { exists $_[0]->{attributes}->{$_[1]} }
c3398f5b 107sub get_attribute { $_[0]->{attributes}->{$_[1]} }
108
00ca1c62 109sub linearized_isa { @{ get_linear_isa($_[0]->name) } }
c3398f5b 110
7a59f4e8 111sub clone_object {
112 my $class = shift;
113 my $instance = shift;
114
115 (blessed($instance) && $instance->isa($class->name))
1a0f0802 116 || confess "You must pass an instance of the metaclass (" . $class->name . "), not ($instance)";
7a59f4e8 117
118 $class->clone_instance($instance, @_);
119}
120
121sub clone_instance {
122 my ($class, $instance, %params) = @_;
123
124 (blessed($instance))
e42bee44 125 || confess "You can only clone instances, ($instance) is not a blessed instance";
7a59f4e8 126
127 my $clone = bless { %$instance }, ref $instance;
128
129 foreach my $attr ($class->compute_all_applicable_attributes()) {
130 if ( defined( my $init_arg = $attr->init_arg ) ) {
131 if (exists $params{$init_arg}) {
132 $clone->{ $attr->name } = $params{$init_arg};
133 }
134 }
135 }
136
137 return $clone;
138
139}
140
fc1d8369 141sub make_immutable {
142 my $self = shift;
143 my $name = $self->name;
144 $self->{is_immutable}++;
145 no strict 'refs';
146 *{"$name\::new"} = Mouse::Meta::Method::Constructor->generate_constructor_method_inline( $self );
147}
148sub make_mutable {
149 Carp::croak "Mouse::Meta::Class->make_mutable does not supported by Mouse";
150}
151sub is_immutable { $_[0]->{is_immutable} }
84ef660f 152
153sub attribute_metaclass { "Mouse::Meta::Class" }
7a59f4e8 154
50dc6ee5 155sub add_before_method_modifier {
156 my ($self, $name, $code) = @_;
4e31595c 157 require Class::Method::Modifiers;
50dc6ee5 158 Class::Method::Modifiers::_install_modifier(
159 $self->name,
160 'before',
161 $name,
162 $code,
163 );
164}
165
166sub add_around_method_modifier {
167 my ($self, $name, $code) = @_;
4e31595c 168 require Class::Method::Modifiers;
50dc6ee5 169 Class::Method::Modifiers::_install_modifier(
170 $self->name,
171 'around',
172 $name,
173 $code,
174 );
175}
176
177sub add_after_method_modifier {
178 my ($self, $name, $code) = @_;
4e31595c 179 require Class::Method::Modifiers;
50dc6ee5 180 Class::Method::Modifiers::_install_modifier(
181 $self->name,
182 'after',
183 $name,
184 $code,
185 );
186}
187
c3398f5b 1881;
189
190__END__
191
192=head1 NAME
193
306290e8 194Mouse::Meta::Class - hook into the Mouse MOP
c3398f5b 195
196=head1 METHODS
197
306290e8 198=head2 initialize ClassName -> Mouse::Meta::Class
c3398f5b 199
306290e8 200Finds or creates a Mouse::Meta::Class instance for the given ClassName. Only
201one instance should exist for a given class.
c3398f5b 202
306290e8 203=head2 new %args -> Mouse::Meta::Class
c3398f5b 204
306290e8 205Creates a new Mouse::Meta::Class. Don't call this directly.
c3398f5b 206
207=head2 name -> ClassName
208
209Returns the name of the owner class.
210
211=head2 superclasses -> [ClassName]
212
213Gets (or sets) the list of superclasses of the owner class.
214
306290e8 215=head2 add_attribute Mouse::Meta::Attribute
c3398f5b 216
306290e8 217Begins keeping track of the existing L<Mouse::Meta::Attribute> for the owner
218class.
c3398f5b 219
72b88a88 220=head2 compute_all_applicable_attributes -> (Mouse::Meta::Attribute)
221
222Returns the list of all L<Mouse::Meta::Attribute> instances associated with
223this class and its superclasses.
224
306290e8 225=head2 get_attribute_map -> { name => Mouse::Meta::Attribute }
c3398f5b 226
227Returns a mapping of attribute names to their corresponding
306290e8 228L<Mouse::Meta::Attribute> objects.
c3398f5b 229
66eea168 230=head2 has_attribute Name -> Boool
231
232Returns whether we have a L<Mouse::Meta::Attribute> with the given name.
233
306290e8 234=head2 get_attribute Name -> Mouse::Meta::Attribute | undef
c3398f5b 235
306290e8 236Returns the L<Mouse::Meta::Attribute> with the given name.
c3398f5b 237
238=head2 linearized_isa -> [ClassNames]
239
240Returns the list of classes in method dispatch order, with duplicates removed.
241
f7b11a21 242=head2 clone_object Instance -> Instance
243
244Clones the given C<Instance> which must be an instance governed by this
245metaclass.
246
247=head2 clone_instance Instance, Parameters -> Instance
248
249Clones the given C<Instance> and sets any additional parameters.
250
c3398f5b 251=cut
252