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