support requires on Mouse::Role.
[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
c3398f5b 66sub add_attribute {
67 my $self = shift;
68 my $attr = shift;
69
70 $self->{'attributes'}{$attr->name} = $attr;
71}
72
72b88a88 73sub compute_all_applicable_attributes {
74 my $self = shift;
75 my (@attr, %seen);
76
77 for my $class ($self->linearized_isa) {
78 my $meta = $self->_metaclass_cache($class)
79 or next;
80
81 for my $name (keys %{ $meta->get_attribute_map }) {
82 next if $seen{$name}++;
83 push @attr, $meta->get_attribute($name);
84 }
85 }
86
87 return @attr;
88}
89
c3398f5b 90sub get_attribute_map { $_[0]->{attributes} }
66eea168 91sub has_attribute { exists $_[0]->{attributes}->{$_[1]} }
c3398f5b 92sub get_attribute { $_[0]->{attributes}->{$_[1]} }
93
00ca1c62 94sub linearized_isa { @{ get_linear_isa($_[0]->name) } }
c3398f5b 95
7a59f4e8 96sub clone_object {
97 my $class = shift;
98 my $instance = shift;
99
100 (blessed($instance) && $instance->isa($class->name))
1a0f0802 101 || confess "You must pass an instance of the metaclass (" . $class->name . "), not ($instance)";
7a59f4e8 102
103 $class->clone_instance($instance, @_);
104}
105
106sub clone_instance {
107 my ($class, $instance, %params) = @_;
108
109 (blessed($instance))
e42bee44 110 || confess "You can only clone instances, ($instance) is not a blessed instance";
7a59f4e8 111
112 my $clone = bless { %$instance }, ref $instance;
113
114 foreach my $attr ($class->compute_all_applicable_attributes()) {
115 if ( defined( my $init_arg = $attr->init_arg ) ) {
116 if (exists $params{$init_arg}) {
117 $clone->{ $attr->name } = $params{$init_arg};
118 }
119 }
120 }
121
122 return $clone;
123
124}
125
60e2164a 126sub make_immutable {}
84ef660f 127sub is_immutable { 0 }
128
129sub attribute_metaclass { "Mouse::Meta::Class" }
7a59f4e8 130
50dc6ee5 131sub add_before_method_modifier {
132 my ($self, $name, $code) = @_;
4e31595c 133 require Class::Method::Modifiers;
50dc6ee5 134 Class::Method::Modifiers::_install_modifier(
135 $self->name,
136 'before',
137 $name,
138 $code,
139 );
140}
141
142sub add_around_method_modifier {
143 my ($self, $name, $code) = @_;
4e31595c 144 require Class::Method::Modifiers;
50dc6ee5 145 Class::Method::Modifiers::_install_modifier(
146 $self->name,
147 'around',
148 $name,
149 $code,
150 );
151}
152
153sub add_after_method_modifier {
154 my ($self, $name, $code) = @_;
4e31595c 155 require Class::Method::Modifiers;
50dc6ee5 156 Class::Method::Modifiers::_install_modifier(
157 $self->name,
158 'after',
159 $name,
160 $code,
161 );
162}
163
c3398f5b 1641;
165
166__END__
167
168=head1 NAME
169
306290e8 170Mouse::Meta::Class - hook into the Mouse MOP
c3398f5b 171
172=head1 METHODS
173
306290e8 174=head2 initialize ClassName -> Mouse::Meta::Class
c3398f5b 175
306290e8 176Finds or creates a Mouse::Meta::Class instance for the given ClassName. Only
177one instance should exist for a given class.
c3398f5b 178
306290e8 179=head2 new %args -> Mouse::Meta::Class
c3398f5b 180
306290e8 181Creates a new Mouse::Meta::Class. Don't call this directly.
c3398f5b 182
183=head2 name -> ClassName
184
185Returns the name of the owner class.
186
187=head2 superclasses -> [ClassName]
188
189Gets (or sets) the list of superclasses of the owner class.
190
306290e8 191=head2 add_attribute Mouse::Meta::Attribute
c3398f5b 192
306290e8 193Begins keeping track of the existing L<Mouse::Meta::Attribute> for the owner
194class.
c3398f5b 195
72b88a88 196=head2 compute_all_applicable_attributes -> (Mouse::Meta::Attribute)
197
198Returns the list of all L<Mouse::Meta::Attribute> instances associated with
199this class and its superclasses.
200
306290e8 201=head2 get_attribute_map -> { name => Mouse::Meta::Attribute }
c3398f5b 202
203Returns a mapping of attribute names to their corresponding
306290e8 204L<Mouse::Meta::Attribute> objects.
c3398f5b 205
66eea168 206=head2 has_attribute Name -> Boool
207
208Returns whether we have a L<Mouse::Meta::Attribute> with the given name.
209
306290e8 210=head2 get_attribute Name -> Mouse::Meta::Attribute | undef
c3398f5b 211
306290e8 212Returns the L<Mouse::Meta::Attribute> with the given name.
c3398f5b 213
214=head2 linearized_isa -> [ClassNames]
215
216Returns the list of classes in method dispatch order, with duplicates removed.
217
f7b11a21 218=head2 clone_object Instance -> Instance
219
220Clones the given C<Instance> which must be an instance governed by this
221metaclass.
222
223=head2 clone_instance Instance, Parameters -> Instance
224
225Clones the given C<Instance> and sets any additional parameters.
226
c3398f5b 227=cut
228