bump version to 0.91
[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
113d3174 9our $VERSION = '0.91';
e606ae5f 10$VERSION = eval $VERSION;
fb1e11d5 11our $AUTHORITY = 'cpan:STEVAN';
12
13use base 'Moose::Meta::Role';
14
15# NOTE:
d03bd989 16# we need to override the ->name
fb1e11d5 17# method from Class::MOP::Package
d03bd989 18# since we don't have an actual
fb1e11d5 19# package for this.
20# - SL
21__PACKAGE__->meta->add_attribute('name' => (reader => 'name'));
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',
fb1e11d5 30 default => sub { {} }
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',
37);
38
fb1e11d5 39sub new {
40 my ($class, %params) = @_;
12d8c847 41
fb1e11d5 42 # the roles param is required ...
70ea9161 43 foreach ( @{$params{roles}} ) {
44 unless ( $_->isa('Moose::Meta::Role') ) {
45 require Moose;
46 Moose->throw_error("The list of roles must be instances of Moose::Meta::Role, not $_");
47 }
48 }
12d8c847 49
50 my @composition_roles = map {
51 $_->has_composition_class_roles
52 ? @{ $_->composition_class_roles }
53 : ()
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 );
62 $meta->add_method(meta => sub { $meta });
63 $class = $meta->name;
64 }
65
fb1e11d5 66 # and the name is created from the
67 # roles if one has not been provided
68 $params{name} ||= (join "|" => map { $_->name } @{$params{roles}});
e606ae5f 69 $class->_new(\%params);
fb1e11d5 70}
71
87e63626 72# This is largely a cope of what's in Moose::Meta::Role (itself
73# largely a copy of Class::MOP::Class). However, we can't actually
74# call add_package_symbol, because there's no package to which which
75# add the symbol.
76sub add_method {
fb1e11d5 77 my ($self, $method_name, $method) = @_;
70ea9161 78
79 unless ( defined $method_name && $method_name ) {
80 Moose->throw_error("You must define a method name");
81 }
87e63626 82
83 my $body;
84 if (blessed($method)) {
85 $body = $method->body;
86 if ($method->package_name ne $self->name) {
87 $method = $method->clone(
88 package_name => $self->name,
d03bd989 89 name => $method_name
87e63626 90 ) if $method->can('clone');
91 }
92 }
93 else {
94 $body = $method;
95 $method = $self->wrap_method_body( body => $body, name => $method_name );
96 }
fb1e11d5 97
0385d05e 98 $self->_method_map->{$method_name} = $method;
99}
100
101sub get_method_list {
102 my $self = shift;
103 return keys %{ $self->_method_map };
104}
105
106sub has_method {
107 my ($self, $method_name) = @_;
108
109 return exists $self->_method_map->{$method_name};
110}
111
112sub get_method {
113 my ($self, $method_name) = @_;
114
115 return $self->_method_map->{$method_name};
fb1e11d5 116}
117
7071e2cb 118sub apply_params {
119 my ($self, $role_params) = @_;
120 Class::MOP::load_class($self->application_role_summation_class);
121
122 $self->application_role_summation_class->new(
123 role_params => $role_params,
124 )->apply($self);
125
126 return $self;
127}
128
6e04cb0e 129sub reinitialize {
130 my ($class, $old_meta, @args) = @_;
131 Moose->throw_error('Moose::Meta::Role::Composite instances can only be reinitialized from an existing metaclass instance')
132 if !blessed $old_meta || !$old_meta->isa('Moose::Meta::Role::Composite');
133 return $old_meta->meta->clone_object($old_meta, @args);
134}
135
fb1e11d5 1361;
137
138__END__
139
140=pod
141
142=head1 NAME
143
144Moose::Meta::Role::Composite - An object to represent the set of roles
145
146=head1 DESCRIPTION
147
da5cc486 148A composite is a role that consists of a set of two or more roles.
149
150The API of a composite role is almost identical to that of a regular
151role.
152
153=head1 INHERITANCE
154
155C<Moose::Meta::Role::Composite> is a subclass of L<Moose::Meta::Role>.
156
fb1e11d5 157=head2 METHODS
158
159=over 4
160
da5cc486 161=item B<< Moose::Meta::Role::Composite->new(%options) >>
fb1e11d5 162
da5cc486 163This returns a new composite role object. It accepts the same
164options as its parent class, with a few changes:
fb1e11d5 165
da5cc486 166=over 8
fb1e11d5 167
da5cc486 168=item * roles
fb1e11d5 169
da5cc486 170This option is an array reference containing a list of
171L<Moose::Meta::Role> object. This is a required option.
172
173=item * name
174
175If a name is not given, one is generated from the roles provided.
176
7071e2cb 177=item * apply_params(\%role_params)
178
179Creates a new RoleSummation role application with C<%role_params> and applies
180the composite role to it. The RoleSummation role application class used is
181determined by the composite role's C<application_role_summation_class>
182attribute.
183
6e04cb0e 184=item * reinitialize($metaclass)
185
186Like C<< Class::MOP::Package->reinitialize >>, but doesn't allow passing a
187string with the package name, as there is no real package for composite roles.
188
da5cc486 189=back
fb1e11d5 190
191=back
192
193=head1 BUGS
194
195All complex software has bugs lurking in it, and this module is no
196exception. If you find a bug please either email me, or add the bug
197to cpan-RT.
198
199=head1 AUTHOR
200
201Stevan Little E<lt>stevan@iinteractive.comE<gt>
202
203=head1 COPYRIGHT AND LICENSE
204
2840a3b2 205Copyright 2006-2009 by Infinity Interactive, Inc.
fb1e11d5 206
207L<http://www.iinteractive.com>
208
209This library is free software; you can redistribute it and/or modify
210it under the same terms as Perl itself.
211
e606ae5f 212=cut