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