Fix a small comment typo
[gitmo/Moose.git] / lib / Moose / Meta / Role / Composite.pm
CommitLineData
fb1e11d5 1package Moose::Meta::Role::Composite;
2
3use strict;
4use warnings;
5use metaclass;
6
b5ae7c00 7use Class::Load qw(load_class);
21f1e231 8use Scalar::Util 'blessed';
fb1e11d5 9
fb1e11d5 10use base 'Moose::Meta::Role';
11
12# NOTE:
d03bd989 13# we need to override the ->name
fb1e11d5 14# method from Class::MOP::Package
d03bd989 15# since we don't have an actual
fb1e11d5 16# package for this.
17# - SL
dc2b7cc8 18__PACKAGE__->meta->add_attribute('name' => (
19 reader => 'name',
20 Class::MOP::_definition_context(),
21));
fb1e11d5 22
23# NOTE:
d03bd989 24# Again, since we don't have a real
25# package to store our methods in,
26# we use a HASH ref instead.
fb1e11d5 27# - SL
0385d05e 28__PACKAGE__->meta->add_attribute('_methods' => (
29 reader => '_method_map',
dc2b7cc8 30 default => sub { {} },
31 Class::MOP::_definition_context(),
fb1e11d5 32));
33
7071e2cb 34__PACKAGE__->meta->add_attribute(
35 'application_role_summation_class',
36 reader => 'application_role_summation_class',
37 default => 'Moose::Meta::Role::Application::RoleSummation',
dc2b7cc8 38 Class::MOP::_definition_context(),
7071e2cb 39);
40
fb1e11d5 41sub new {
42 my ($class, %params) = @_;
12d8c847 43
fb1e11d5 44 # the roles param is required ...
70ea9161 45 foreach ( @{$params{roles}} ) {
46 unless ( $_->isa('Moose::Meta::Role') ) {
47 require Moose;
48 Moose->throw_error("The list of roles must be instances of Moose::Meta::Role, not $_");
49 }
50 }
12d8c847 51
52 my @composition_roles = map {
4701ceff 53 $_->composition_class_roles
12d8c847 54 } @{ $params{roles} };
55
56 if (@composition_roles) {
57 my $meta = Moose::Meta::Class->create_anon_class(
58 superclasses => [ $class ],
59 roles => [ @composition_roles ],
60 cache => 1,
61 );
12d8c847 62 $class = $meta->name;
63 }
64
fb1e11d5 65 # and the name is created from the
66 # roles if one has not been provided
67 $params{name} ||= (join "|" => map { $_->name } @{$params{roles}});
e606ae5f 68 $class->_new(\%params);
fb1e11d5 69}
70
64a05eff 71# This is largely a copy of what's in Moose::Meta::Role (itself
87e63626 72# largely a copy of Class::MOP::Class). However, we can't actually
73# call add_package_symbol, because there's no package to which which
74# add the symbol.
75sub add_method {
fb1e11d5 76 my ($self, $method_name, $method) = @_;
70ea9161 77
78 unless ( defined $method_name && $method_name ) {
79 Moose->throw_error("You must define a method name");
80 }
87e63626 81
82 my $body;
83 if (blessed($method)) {
84 $body = $method->body;
85 if ($method->package_name ne $self->name) {
86 $method = $method->clone(
87 package_name => $self->name,
d03bd989 88 name => $method_name
87e63626 89 ) if $method->can('clone');
90 }
91 }
92 else {
93 $body = $method;
94 $method = $self->wrap_method_body( body => $body, name => $method_name );
95 }
fb1e11d5 96
0385d05e 97 $self->_method_map->{$method_name} = $method;
98}
99
100sub get_method_list {
101 my $self = shift;
102 return keys %{ $self->_method_map };
103}
104
723576c6 105sub _get_local_methods {
106 my $self = shift;
107 return values %{ $self->_method_map };
108}
109
0385d05e 110sub has_method {
111 my ($self, $method_name) = @_;
112
113 return exists $self->_method_map->{$method_name};
114}
115
116sub get_method {
117 my ($self, $method_name) = @_;
118
119 return $self->_method_map->{$method_name};
fb1e11d5 120}
121
7071e2cb 122sub apply_params {
123 my ($self, $role_params) = @_;
b5ae7c00 124 load_class($self->application_role_summation_class);
7071e2cb 125
126 $self->application_role_summation_class->new(
127 role_params => $role_params,
128 )->apply($self);
129
130 return $self;
131}
132
6e04cb0e 133sub reinitialize {
f785aad8 134 my ( $class, $old_meta, @args ) = @_;
135
136 Moose->throw_error(
137 'Moose::Meta::Role::Composite instances can only be reinitialized from an existing metaclass instance'
138 )
139 if !blessed $old_meta
140 || !$old_meta->isa('Moose::Meta::Role::Composite');
141
142 my %existing_classes = map { $_ => $old_meta->$_() } qw(
143 application_role_summation_class
144 );
145
146 return $old_meta->meta->clone_object( $old_meta, %existing_classes, @args );
6e04cb0e 147}
148
fb1e11d5 1491;
150
ad46f524 151# ABSTRACT: An object to represent the set of roles
152
fb1e11d5 153__END__
154
155=pod
156
fb1e11d5 157=head1 DESCRIPTION
158
da5cc486 159A composite is a role that consists of a set of two or more roles.
160
161The API of a composite role is almost identical to that of a regular
162role.
163
164=head1 INHERITANCE
165
166C<Moose::Meta::Role::Composite> is a subclass of L<Moose::Meta::Role>.
167
fb1e11d5 168=head2 METHODS
169
170=over 4
171
da5cc486 172=item B<< Moose::Meta::Role::Composite->new(%options) >>
fb1e11d5 173
da5cc486 174This returns a new composite role object. It accepts the same
175options as its parent class, with a few changes:
fb1e11d5 176
da5cc486 177=over 8
fb1e11d5 178
da5cc486 179=item * roles
fb1e11d5 180
da5cc486 181This option is an array reference containing a list of
182L<Moose::Meta::Role> object. This is a required option.
183
184=item * name
185
186If a name is not given, one is generated from the roles provided.
187
7071e2cb 188=item * apply_params(\%role_params)
189
190Creates a new RoleSummation role application with C<%role_params> and applies
191the composite role to it. The RoleSummation role application class used is
192determined by the composite role's C<application_role_summation_class>
193attribute.
194
6e04cb0e 195=item * reinitialize($metaclass)
196
197Like C<< Class::MOP::Package->reinitialize >>, but doesn't allow passing a
198string with the package name, as there is no real package for composite roles.
199
da5cc486 200=back
fb1e11d5 201
202=back
203
204=head1 BUGS
205
d4048ef3 206See L<Moose/BUGS> for details on reporting bugs.
fb1e11d5 207
e606ae5f 208=cut