Reorder changes to put most interesting ones first
[gitmo/Moose.git] / lib / Moose / Meta / Role.pm
CommitLineData
e185c027 1
2package Moose::Meta::Role;
3
4use strict;
5use warnings;
6use metaclass;
7
21f1e231 8use Scalar::Util 'blessed';
b6a00b82 9use Carp 'confess';
963c24e1 10use Devel::GlobalDestruction 'in_global_destruction';
bdabd620 11
6d0815b5 12our $VERSION = '0.93';
e606ae5f 13$VERSION = eval $VERSION;
d44714be 14our $AUTHORITY = 'cpan:STEVAN';
e185c027 15
8ee73eeb 16use Moose::Meta::Class;
39b3bc94 17use Moose::Meta::Role::Method;
d67145ed 18use Moose::Meta::Role::Method::Required;
bb153262 19use Moose::Meta::Role::Method::Conflicting;
8ee73eeb 20
68efb014 21use base 'Class::MOP::Module';
80572233 22
fb1e11d5 23## ------------------------------------------------------------------
24## NOTE:
25## I normally don't do this, but I am doing
26## a whole bunch of meta-programmin in this
27## module, so it just makes sense. For a clearer
d03bd989 28## picture of what is going on in the next
29## several lines of code, look at the really
fb1e11d5 30## big comment at the end of this file (right
31## before the POD).
32## - SL
33## ------------------------------------------------------------------
80572233 34
21716c07 35my $META = __PACKAGE__->meta;
36
37## ------------------------------------------------------------------
38## attributes ...
e185c027 39
21716c07 40# NOTE:
41# since roles are lazy, we hold all the attributes
fb1e11d5 42# of the individual role in 'statis' until which
43# time when it is applied to a class. This means
44# keeping a lot of things in hash maps, so we are
21716c07 45# using a little of that meta-programmin' magic
d03bd989 46# here an saving lots of extra typin. And since
fb1e11d5 47# many of these attributes above require similar
48# functionality to support them, so we again use
49# the wonders of meta-programmin' to deliver a
21716c07 50# very compact solution to this normally verbose
51# problem.
52# - SL
53
54foreach my $action (
fb1e11d5 55 {
56 name => 'excluded_roles_map',
57 attr_reader => 'get_excluded_roles_map' ,
21716c07 58 methods => {
fb1e11d5 59 add => 'add_excluded_roles',
55f28f0a 60 get_keys => 'get_excluded_roles_list',
fb1e11d5 61 existence => 'excludes_role',
21716c07 62 }
63 },
fb1e11d5 64 {
65 name => 'required_methods',
21716c07 66 attr_reader => 'get_required_methods_map',
67 methods => {
7c62cb0a 68 remove => 'remove_required_methods',
69 get_values => 'get_required_method_list',
70 existence => 'requires_method',
21716c07 71 }
d03bd989 72 },
21716c07 73 {
ce444596 74 name => '_attribute_map',
75 attr_reader => '_attribute_map',
21716c07 76 methods => {
77 get => 'get_attribute',
55f28f0a 78 get_keys => 'get_attribute_list',
21716c07 79 existence => 'has_attribute',
80 remove => 'remove_attribute',
81 }
82 }
83) {
fb1e11d5 84
21716c07 85 my $attr_reader = $action->{attr_reader};
86 my $methods = $action->{methods};
fb1e11d5 87
88 # create the attribute
89 $META->add_attribute($action->{name} => (
90 reader => $attr_reader,
91 default => sub { {} }
92 ));
93
94 # create some helper methods
21716c07 95 $META->add_method($methods->{add} => sub {
96 my ($self, @values) = @_;
fb1e11d5 97 $self->$attr_reader->{$_} = undef foreach @values;
21716c07 98 }) if exists $methods->{add};
fb1e11d5 99
55f28f0a 100 $META->add_method($methods->{get_keys} => sub {
21716c07 101 my ($self) = @_;
fb1e11d5 102 keys %{$self->$attr_reader};
55f28f0a 103 }) if exists $methods->{get_keys};
fb1e11d5 104
8a0bfed9 105 $META->add_method($methods->{get_values} => sub {
106 my ($self) = @_;
107 values %{$self->$attr_reader};
108 }) if exists $methods->{get_values};
109
21716c07 110 $META->add_method($methods->{get} => sub {
111 my ($self, $name) = @_;
fb1e11d5 112 $self->$attr_reader->{$name}
113 }) if exists $methods->{get};
114
21716c07 115 $META->add_method($methods->{existence} => sub {
116 my ($self, $name) = @_;
fb1e11d5 117 exists $self->$attr_reader->{$name} ? 1 : 0;
118 }) if exists $methods->{existence};
119
21716c07 120 $META->add_method($methods->{remove} => sub {
121 my ($self, @values) = @_;
122 delete $self->$attr_reader->{$_} foreach @values;
fb1e11d5 123 }) if exists $methods->{remove};
21716c07 124}
d79e62fd 125
b05518b2 126$META->add_attribute(
127 'method_metaclass',
128 reader => 'method_metaclass',
129 default => 'Moose::Meta::Role::Method',
130);
131
77ed8b8d 132$META->add_attribute(
133 'required_method_metaclass',
134 reader => 'required_method_metaclass',
135 default => 'Moose::Meta::Role::Method::Required',
136);
137
eec8ca8a 138$META->add_attribute(
bb153262 139 'conflicting_method_metaclass',
140 reader => 'conflicting_method_metaclass',
141 default => 'Moose::Meta::Role::Method::Conflicting',
eec8ca8a 142);
143
07de7559 144$META->add_attribute(
145 'application_to_class_class',
146 reader => 'application_to_class_class',
147 default => 'Moose::Meta::Role::Application::ToClass',
148);
149
150$META->add_attribute(
151 'application_to_role_class',
152 reader => 'application_to_role_class',
153 default => 'Moose::Meta::Role::Application::ToRole',
154);
155
156$META->add_attribute(
157 'application_to_instance_class',
158 reader => 'application_to_instance_class',
159 default => 'Moose::Meta::Role::Application::ToInstance',
160);
161
21716c07 162## some things don't always fit, so they go here ...
80572233 163
21716c07 164sub add_attribute {
165 my $self = shift;
166 my $name = shift;
52ac1d4a 167 unless ( defined $name ) {
70ea9161 168 require Moose;
169 Moose->throw_error("You must provide a name for the attribute");
170 }
21716c07 171 my $attr_desc;
172 if (scalar @_ == 1 && ref($_[0]) eq 'HASH') {
173 $attr_desc = $_[0];
174 }
175 else {
176 $attr_desc = { @_ };
177 }
ce444596 178 $self->_attribute_map->{$name} = $attr_desc;
21716c07 179}
e185c027 180
16d721b3 181sub add_required_methods {
182 my $self = shift;
183
184 for (@_) {
185 my $method = $_;
c9d7e396 186 if (!blessed($method)) {
16d721b3 187 $method = $self->required_method_metaclass->new(
188 name => $method,
189 );
190 }
191 $self->get_required_methods_map->{$method->name} = $method;
192 }
193}
194
bb153262 195sub add_conflicting_method {
09eeab06 196 my $self = shift;
197
198 my $method;
199 if (@_ == 1 && blessed($_[0])) {
200 $method = shift;
201 }
202 else {
bb153262 203 $method = $self->conflicting_method_metaclass->new(@_);
09eeab06 204 }
205
206 $self->add_required_methods($method);
207}
208
21716c07 209## ------------------------------------------------------------------
210## method modifiers
211
21716c07 212# NOTE:
fb1e11d5 213# the before/around/after method modifiers are
21716c07 214# stored by name, but there can be many methods
215# then associated with that name. So again we have
216# lots of similar functionality, so we can do some
217# meta-programmin' and save some time.
218# - SL
219
220foreach my $modifier_type (qw[ before around after ]) {
fb1e11d5 221
222 my $attr_reader = "get_${modifier_type}_method_modifiers_map";
d03bd989 223
fb1e11d5 224 # create the attribute ...
225 $META->add_attribute("${modifier_type}_method_modifiers" => (
226 reader => $attr_reader,
227 default => sub { {} }
d03bd989 228 ));
fb1e11d5 229
230 # and some helper methods ...
21716c07 231 $META->add_method("get_${modifier_type}_method_modifiers" => sub {
232 my ($self, $method_name) = @_;
fb1e11d5 233 #return () unless exists $self->$attr_reader->{$method_name};
d9847263 234 my $mm = $self->$attr_reader->{$method_name};
235 $mm ? @$mm : ();
21716c07 236 });
fb1e11d5 237
21716c07 238 $META->add_method("has_${modifier_type}_method_modifiers" => sub {
239 my ($self, $method_name) = @_;
240 # NOTE:
fb1e11d5 241 # for now we assume that if it exists,..
21716c07 242 # it has at least one modifier in it
243 (exists $self->$attr_reader->{$method_name}) ? 1 : 0;
fb1e11d5 244 });
245
21716c07 246 $META->add_method("add_${modifier_type}_method_modifier" => sub {
247 my ($self, $method_name, $method) = @_;
fb1e11d5 248
249 $self->$attr_reader->{$method_name} = []
21716c07 250 unless exists $self->$attr_reader->{$method_name};
fb1e11d5 251
21716c07 252 my $modifiers = $self->$attr_reader->{$method_name};
fb1e11d5 253
21716c07 254 # NOTE:
fb1e11d5 255 # check to see that we aren't adding the
256 # same code twice. We err in favor of the
21716c07 257 # first on here, this may not be as expected
258 foreach my $modifier (@{$modifiers}) {
259 return if $modifier == $method;
260 }
fb1e11d5 261
21716c07 262 push @{$modifiers} => $method;
263 });
fb1e11d5 264
21716c07 265}
1331430a 266
21716c07 267## ------------------------------------------------------------------
268## override method mofidiers
0558683c 269
fb1e11d5 270$META->add_attribute('override_method_modifiers' => (
271 reader => 'get_override_method_modifiers_map',
272 default => sub { {} }
273));
274
21716c07 275# NOTE:
fb1e11d5 276# these are a little different because there
21716c07 277# can only be one per name, whereas the other
278# method modifiers can have multiples.
279# - SL
0558683c 280
21716c07 281sub add_override_method_modifier {
282 my ($self, $method_name, $method) = @_;
283 (!$self->has_method($method_name))
c245d69b 284 || Moose->throw_error("Cannot add an override of method '$method_name' " .
4c0b3599 285 "because there is a local version of '$method_name'");
fb1e11d5 286 $self->get_override_method_modifiers_map->{$method_name} = $method;
21716c07 287}
0558683c 288
21716c07 289sub has_override_method_modifier {
290 my ($self, $method_name) = @_;
291 # NOTE:
fb1e11d5 292 # for now we assume that if it exists,..
21716c07 293 # it has at least one modifier in it
fb1e11d5 294 (exists $self->get_override_method_modifiers_map->{$method_name}) ? 1 : 0;
21716c07 295}
0558683c 296
21716c07 297sub get_override_method_modifier {
298 my ($self, $method_name) = @_;
fb1e11d5 299 $self->get_override_method_modifiers_map->{$method_name};
21716c07 300}
0558683c 301
21716c07 302## general list accessor ...
80572233 303
21716c07 304sub get_method_modifier_list {
305 my ($self, $modifier_type) = @_;
fb1e11d5 306 my $accessor = "get_${modifier_type}_method_modifiers_map";
21716c07 307 keys %{$self->$accessor};
308}
e185c027 309
e606ae5f 310sub reset_package_cache_flag { (shift)->{'_package_cache_flag'} = undef }
311sub update_package_cache_flag {
312 my $self = shift;
313 $self->{'_package_cache_flag'} = Class::MOP::check_package_cache_flag($self->name);
314}
315
316
317
21716c07 318## ------------------------------------------------------------------
80572233 319## subroles
320
278ca49c 321$META->add_attribute('roles' => (
21716c07 322 reader => 'get_roles',
323 default => sub { [] }
324));
325
80572233 326sub add_role {
327 my ($self, $role) = @_;
328 (blessed($role) && $role->isa('Moose::Meta::Role'))
c245d69b 329 || Moose->throw_error("Roles must be instances of Moose::Meta::Role");
80572233 330 push @{$self->get_roles} => $role;
e606ae5f 331 $self->reset_package_cache_flag;
80572233 332}
333
b8aeb4dc 334sub calculate_all_roles {
335 my $self = shift;
336 my %seen;
fb1e11d5 337 grep {
338 !$seen{$_->name}++
339 } ($self, map {
340 $_->calculate_all_roles
341 } @{ $self->get_roles });
b8aeb4dc 342}
343
80572233 344sub does_role {
345 my ($self, $role_name) = @_;
346 (defined $role_name)
c245d69b 347 || Moose->throw_error("You must supply a role name to look for");
bdabd620 348 # if we are it,.. then return true
349 return 1 if $role_name eq $self->name;
350 # otherwise.. check our children
80572233 351 foreach my $role (@{$self->get_roles}) {
bdabd620 352 return 1 if $role->does_role($role_name);
80572233 353 }
354 return 0;
355}
356
1db8ecc7 357sub find_method_by_name { (shift)->get_method(@_) }
093b12c2 358
fb1e11d5 359sub alias_method {
8b7cb9ab 360 Carp::cluck("The alias_method method is deprecated. Use add_method instead.\n");
89e6757a 361
87e63626 362 my $self = shift;
fb1e11d5 363
87e63626 364 $self->add_method(@_);
fb1e11d5 365}
366
21716c07 367## ------------------------------------------------------------------
fb1e11d5 368## role construction
21716c07 369## ------------------------------------------------------------------
e185c027 370
21716c07 371sub apply {
bca01282 372 my ($self, $other, @args) = @_;
373
374 (blessed($other))
c245d69b 375 || Moose->throw_error("You must pass in an blessed instance");
d03bd989 376
07de7559 377 my $application_class;
1c9db35c 378 if ($other->isa('Moose::Meta::Role')) {
07de7559 379 $application_class = $self->application_to_role_class;
1c9db35c 380 }
381 elsif ($other->isa('Moose::Meta::Class')) {
07de7559 382 $application_class = $self->application_to_class_class;
d03bd989 383 }
1c9db35c 384 else {
07de7559 385 $application_class = $self->application_to_instance_class;
d03bd989 386 }
07de7559 387
388 Class::MOP::load_class($application_class);
389 return $application_class->new(@args)->apply($self, $other);
0558683c 390}
391
4701ceff 392sub composition_class_roles { }
393
21716c07 394sub combine {
a4e516f6 395 my ($class, @role_specs) = @_;
d03bd989 396
d03bd989 397 require Moose::Meta::Role::Composite;
398
28412c0b 399 my (@roles, %role_params);
400 while (@role_specs) {
31d96c3e 401 my ($role_name, $params) = @{ splice @role_specs, 0, 1 };
402 my $requested_role = Class::MOP::class_of($role_name);
403
6bdef412 404 my $actual_role = $requested_role->_role_for_combination($params);
31d96c3e 405 push @roles => $actual_role;
406
28412c0b 407 next unless defined $params;
31d96c3e 408 $role_params{$actual_role->name} = $params;
28412c0b 409 }
d03bd989 410
fb1e11d5 411 my $c = Moose::Meta::Role::Composite->new(roles => \@roles);
7071e2cb 412 return $c->apply_params(\%role_params);
0558683c 413}
414
6bdef412 415sub _role_for_combination {
436d7a28 416 my ($self, $params) = @_;
417 return $self;
418}
419
b6a00b82 420sub create {
2d5f3fab 421 my ( $role, $package_name, %options ) = @_;
b6a00b82 422
2d5f3fab 423 $options{package} = $package_name;
b6a00b82 424
425 (ref $options{attributes} eq 'HASH')
426 || confess "You must pass a HASH ref of attributes"
427 if exists $options{attributes};
428
429 (ref $options{methods} eq 'HASH')
430 || confess "You must pass a HASH ref of methods"
431 if exists $options{methods};
432
2d5f3fab 433 my (%initialize_options) = %options;
b6a00b82 434 delete @initialize_options{qw(
435 package
436 attributes
437 methods
438 version
439 authority
440 )};
441
442 my $meta = $role->initialize( $package_name => %initialize_options );
443
6a4a7c31 444 $meta->_instantiate_module( $options{version}, $options{authority} );
445
b6a00b82 446 # FIXME totally lame
447 $meta->add_method('meta' => sub {
448 $role->initialize(ref($_[0]) || $_[0]);
449 });
450
451 if (exists $options{attributes}) {
452 foreach my $attribute_name (keys %{$options{attributes}}) {
453 my $attr = $options{attributes}->{$attribute_name};
454 $meta->add_attribute($attribute_name => $attr);
455 }
456 }
457
458 if (exists $options{methods}) {
459 foreach my $method_name (keys %{$options{methods}}) {
460 $meta->add_method($method_name, $options{methods}->{$method_name});
461 }
462 }
463
d1765290 464 Class::MOP::weaken_metaclass($meta->name)
465 if $meta->is_anon_role;
466
b6a00b82 467 return $meta;
468}
469
c9ee520d 470# anonymous roles. most of it is copied straight out of Class::MOP::Class.
471# an intrepid hacker might find great riches if he unifies this code with that
472# code in Class::MOP::Module or Class::MOP::Package
473{
474 # NOTE:
475 # this should be sufficient, if you have a
476 # use case where it is not, write a test and
477 # I will change it.
478 my $ANON_ROLE_SERIAL = 0;
479
480 # NOTE:
481 # we need a sufficiently annoying prefix
482 # this should suffice for now, this is
483 # used in a couple of places below, so
484 # need to put it up here for now.
485 my $ANON_ROLE_PREFIX = 'Moose::Meta::Role::__ANON__::SERIAL::';
486
487 sub is_anon_role {
488 my $self = shift;
489 no warnings 'uninitialized';
490 $self->name =~ /^$ANON_ROLE_PREFIX/;
491 }
492
493 sub create_anon_role {
494 my ($role, %options) = @_;
495 my $package_name = $ANON_ROLE_PREFIX . ++$ANON_ROLE_SERIAL;
496 return $role->create($package_name, %options);
497 }
498
499 # NOTE:
500 # this will only get called for
501 # anon-roles, all other calls
502 # are assumed to occur during
503 # global destruction and so don't
504 # really need to be handled explicitly
505 sub DESTROY {
506 my $self = shift;
507
963c24e1 508 return if in_global_destruction(); # it'll happen soon anyway and this just makes things more complicated
c9ee520d 509
510 no warnings 'uninitialized';
511 return unless $self->name =~ /^$ANON_ROLE_PREFIX/;
512
513 # XXX: is this necessary for us? I don't understand what it's doing
514 # -sartak
515
516 # Moose does a weird thing where it replaces the metaclass for
517 # class when fixing metaclass incompatibility. In that case,
518 # we don't want to clean out the namespace now. We can detect
519 # that because Moose will explicitly update the singleton
520 # cache in Class::MOP.
521 #my $current_meta = Class::MOP::get_metaclass_by_name($self->name);
522 #return if $current_meta ne $self;
523
524 my ($serial_id) = ($self->name =~ /^$ANON_ROLE_PREFIX(\d+)/);
525 no strict 'refs';
526 foreach my $key (keys %{$ANON_ROLE_PREFIX . $serial_id}) {
527 delete ${$ANON_ROLE_PREFIX . $serial_id}{$key};
528 }
529 delete ${'main::' . $ANON_ROLE_PREFIX}{$serial_id . '::'};
530 }
531}
532
fb1e11d5 533#####################################################################
534## NOTE:
d03bd989 535## This is Moose::Meta::Role as defined by Moose (plus the use of
536## MooseX::AttributeHelpers module). It is here as a reference to
fb1e11d5 537## make it easier to see what is happening above with all the meta
538## programming. - SL
539#####################################################################
540#
541# has 'roles' => (
a40b446a 542# metaclass => 'Array',
fb1e11d5 543# reader => 'get_roles',
764a7831 544# isa => 'ArrayRef[Moose::Meta::Role]',
fb1e11d5 545# default => sub { [] },
546# provides => {
547# 'push' => 'add_role',
548# }
549# );
d03bd989 550#
fb1e11d5 551# has 'excluded_roles_map' => (
a40b446a 552# metaclass => 'Hash',
fb1e11d5 553# reader => 'get_excluded_roles_map',
554# isa => 'HashRef[Str]',
555# provides => {
556# # Not exactly set, cause it sets multiple
557# 'set' => 'add_excluded_roles',
558# 'keys' => 'get_excluded_roles_list',
559# 'exists' => 'excludes_role',
560# }
561# );
d03bd989 562#
fb1e11d5 563# has 'attribute_map' => (
a40b446a 564# metaclass => 'Hash',
ce444596 565# reader => '_attribute_map',
d03bd989 566# isa => 'HashRef[Str]',
fb1e11d5 567# provides => {
568# # 'set' => 'add_attribute' # has some special crap in it
569# 'get' => 'get_attribute',
570# 'keys' => 'get_attribute_list',
571# 'exists' => 'has_attribute',
572# # Not exactly delete, cause it sets multiple
d03bd989 573# 'delete' => 'remove_attribute',
fb1e11d5 574# }
575# );
d03bd989 576#
fb1e11d5 577# has 'required_methods' => (
a40b446a 578# metaclass => 'Hash',
fb1e11d5 579# reader => 'get_required_methods_map',
72264f10 580# isa => 'HashRef[Moose::Meta::Role::Method::Required]',
d03bd989 581# provides => {
582# # not exactly set, or delete since it works for multiple
fb1e11d5 583# 'set' => 'add_required_methods',
584# 'delete' => 'remove_required_methods',
585# 'keys' => 'get_required_method_list',
d03bd989 586# 'exists' => 'requires_method',
fb1e11d5 587# }
588# );
d03bd989 589#
590# # the before, around and after modifiers are
591# # HASH keyed by method-name, with ARRAY of
fb1e11d5 592# # CODE refs to apply in that order
d03bd989 593#
fb1e11d5 594# has 'before_method_modifiers' => (
a40b446a 595# metaclass => 'Hash',
fb1e11d5 596# reader => 'get_before_method_modifiers_map',
597# isa => 'HashRef[ArrayRef[CodeRef]]',
598# provides => {
599# 'keys' => 'get_before_method_modifiers',
d03bd989 600# 'exists' => 'has_before_method_modifiers',
601# # This actually makes sure there is an
fb1e11d5 602# # ARRAY at the given key, and pushed onto
603# # it. It also checks for duplicates as well
d03bd989 604# # 'add' => 'add_before_method_modifier'
605# }
fb1e11d5 606# );
d03bd989 607#
fb1e11d5 608# has 'after_method_modifiers' => (
a40b446a 609# metaclass => 'Hash',
fb1e11d5 610# reader =>'get_after_method_modifiers_map',
611# isa => 'HashRef[ArrayRef[CodeRef]]',
612# provides => {
613# 'keys' => 'get_after_method_modifiers',
d03bd989 614# 'exists' => 'has_after_method_modifiers',
615# # This actually makes sure there is an
fb1e11d5 616# # ARRAY at the given key, and pushed onto
d03bd989 617# # it. It also checks for duplicates as well
618# # 'add' => 'add_after_method_modifier'
619# }
fb1e11d5 620# );
d03bd989 621#
fb1e11d5 622# has 'around_method_modifiers' => (
a40b446a 623# metaclass => 'Hash',
fb1e11d5 624# reader =>'get_around_method_modifiers_map',
625# isa => 'HashRef[ArrayRef[CodeRef]]',
626# provides => {
627# 'keys' => 'get_around_method_modifiers',
d03bd989 628# 'exists' => 'has_around_method_modifiers',
629# # This actually makes sure there is an
fb1e11d5 630# # ARRAY at the given key, and pushed onto
d03bd989 631# # it. It also checks for duplicates as well
632# # 'add' => 'add_around_method_modifier'
633# }
fb1e11d5 634# );
d03bd989 635#
fb1e11d5 636# # override is similar to the other modifiers
637# # except that it is not an ARRAY of code refs
638# # but instead just a single name->code mapping
d03bd989 639#
fb1e11d5 640# has 'override_method_modifiers' => (
a40b446a 641# metaclass => 'Hash',
fb1e11d5 642# reader =>'get_override_method_modifiers_map',
d03bd989 643# isa => 'HashRef[CodeRef]',
fb1e11d5 644# provides => {
645# 'keys' => 'get_override_method_modifier',
d03bd989 646# 'exists' => 'has_override_method_modifier',
647# 'add' => 'add_override_method_modifier', # checks for local method ..
fb1e11d5 648# }
649# );
d03bd989 650#
fb1e11d5 651#####################################################################
652
653
e185c027 6541;
655
656__END__
657
658=pod
659
660=head1 NAME
661
662Moose::Meta::Role - The Moose Role metaclass
663
664=head1 DESCRIPTION
665
705d4cfd 666This class is a subclass of L<Class::MOP::Module> that provides
667additional Moose-specific functionality.
668
669It's API looks a lot like L<Moose::Meta::Class>, but internally it
670implements many things differently. This may change in the future.
79592a54 671
cf3bb5c5 672=head1 INHERITANCE
673
674C<Moose::Meta::Role> is a subclass of L<Class::MOP::Module>.
675
e185c027 676=head1 METHODS
677
705d4cfd 678=head2 Construction
679
e185c027 680=over 4
681
705d4cfd 682=item B<< Moose::Meta::Role->initialize($role_name) >>
e185c027 683
705d4cfd 684This method creates a new role object with the provided name.
e185c027 685
705d4cfd 686=item B<< Moose::Meta::Role->combine( [ $role => { ... } ], [ $role ], ... ) >>
78cd1d3b 687
705d4cfd 688This method accepts a list of array references. Each array reference
689should contain a role name as its first element. The second element is
c8b8d92f 690an optional hash reference. The hash reference can contain C<-excludes>
691and C<-alias> keys to control how methods are composed from the role.
e606ae5f 692
705d4cfd 693The return value is a new L<Moose::Meta::Role::Composite> that
694represents the combined roles.
db1ab48d 695
4701ceff 696=item B<< $metarole->composition_class_roles >>
697
698When combining multiple roles using C<combine>, this method is used to obtain a
699list of role names to be applied to the L<Moose::Meta::Role::Composite>
700instance returned by C<combine>. The default implementation returns an empty
701list. Extensions that need to hook into role combination may wrap this method
702to return additional role names.
703
705d4cfd 704=item B<< Moose::Meta::Role->create($name, %options) >>
e185c027 705
705d4cfd 706This method is identical to the L<Moose::Meta::Class> C<create>
707method.
708
709=item B<< Moose::Meta::Role->create_anon_role >>
e185c027 710
705d4cfd 711This method is identical to the L<Moose::Meta::Class>
712C<create_anon_class> method.
e185c027 713
705d4cfd 714=item B<< $metarole->is_anon_role >>
e185c027 715
705d4cfd 716Returns true if the role is an anonymous role.
e185c027 717
718=back
719
705d4cfd 720=head2 Role application
721
e185c027 722=over 4
723
705d4cfd 724=item B<< $metarole->apply( $thing, @options ) >>
80572233 725
705d4cfd 726This method applies a role to the given C<$thing>. That can be another
727L<Moose::Meta::Role>, object, a L<Moose::Meta::Class> object, or a
728(non-meta) object instance.
80572233 729
705d4cfd 730The options are passed directly to the constructor for the appropriate
731L<Moose::Meta::Role::Application> subclass.
80572233 732
d05235e1 733Note that this will apply the role even if the C<$thing> in question already
734C<does> this role. L<Moose::Util/does_role> is a convenient wrapper for
735finding out if role application is necessary.
736
80572233 737=back
738
705d4cfd 739=head2 Roles and other roles
740
80572233 741=over 4
742
705d4cfd 743=item B<< $metarole->get_roles >>
d79e62fd 744
705d4cfd 745This returns an array reference of roles which this role does. This
746list may include duplicates.
d79e62fd 747
705d4cfd 748=item B<< $metarole->calculate_all_roles >>
d79e62fd 749
705d4cfd 750This returns a I<unique> list of all roles that this role does, and
751all the roles that its roles do.
d79e62fd 752
705d4cfd 753=item B<< $metarole->does_role($role_name) >>
2b14ac61 754
705d4cfd 755Given a role I<name>, returns true if this role does the given
756role.
d79e62fd 757
705d4cfd 758=item B<< $metarole->add_role($role) >>
d79e62fd 759
705d4cfd 760Given a L<Moose::Meta::Role> object, this adds the role to the list of
761roles that the role does.
68efb014 762
705d4cfd 763=item B<< $metarole->get_excluded_roles_list >>
be4427d0 764
705d4cfd 765Returns a list of role names which this role excludes.
e185c027 766
705d4cfd 767=item B<< $metarole->excludes_role($role_name) >>
e185c027 768
705d4cfd 769Given a role I<name>, returns true if this role excludes the named
770role.
e606ae5f 771
705d4cfd 772=item B<< $metarole->add_excluded_roles(@role_names) >>
e606ae5f 773
705d4cfd 774Given one or more role names, adds those roles to the list of excluded
775roles.
bdabd620 776
705d4cfd 777=back
e185c027 778
705d4cfd 779=head2 Methods
093b12c2 780
705d4cfd 781The methods for dealing with a role's methods are all identical in API
782and behavior to the same methods in L<Class::MOP::Class>.
638853cb 783
705d4cfd 784=over 4
53dd42d8 785
705d4cfd 786=item B<< $metarole->method_metaclass >>
e185c027 787
705d4cfd 788Returns the method metaclass name for the role. This defaults to
789L<Moose::Meta::Role::Method>.
e185c027 790
705d4cfd 791=item B<< $metarole->get_method($name) >>
e185c027 792
705d4cfd 793=item B<< $metarole->has_method($name) >>
e185c027 794
705d4cfd 795=item B<< $metarole->add_method( $name, $body ) >>
e185c027 796
705d4cfd 797=item B<< $metarole->get_method_list >>
e185c027 798
705d4cfd 799=item B<< $metarole->find_method_by_name($name) >>
800
801These methods are all identical to the methods of the same name in
8f6cbfcd 802L<Class::MOP::Package>
e185c027 803
804=back
805
705d4cfd 806=head2 Attributes
807
808As with methods, the methods for dealing with a role's attribute are
809all identical in API and behavior to the same methods in
810L<Class::MOP::Class>.
811
812However, attributes stored in this class are I<not> stored as
813objects. Rather, the attribute definition is stored as a hash
814reference. When a role is composed into a class, this hash reference
815is passed directly to the metaclass's C<add_attribute> method.
816
817This is quite likely to change in the future.
818
e185c027 819=over 4
820
705d4cfd 821=item B<< $metarole->get_attribute($attribute_name) >>
822
823=item B<< $metarole->has_attribute($attribute_name) >>
1331430a 824
705d4cfd 825=item B<< $metarole->get_attribute_list >>
1331430a 826
705d4cfd 827=item B<< $metarole->add_attribute($name, %options) >>
1331430a 828
705d4cfd 829=item B<< $metarole->remove_attribute($attribute_name) >>
1331430a 830
831=back
832
705d4cfd 833=head2 Required methods
834
0558683c 835=over 4
836
705d4cfd 837=item B<< $metarole->get_required_method_list >>
0558683c 838
705d4cfd 839Returns the list of methods required by the role.
0558683c 840
705d4cfd 841=item B<< $metarole->requires_method($name) >>
0558683c 842
705d4cfd 843Returns true if the role requires the named method.
0558683c 844
0ecff16b 845=item B<< $metarole->add_required_methods(@names) >>
0558683c 846
b3c1586a 847Adds the named methods to the role's list of required methods.
0558683c 848
705d4cfd 849=item B<< $metarole->remove_required_methods(@names) >>
0558683c 850
2dda1d28 851Removes the named methods from the role's list of required methods.
0558683c 852
bb153262 853=item B<< $metarole->add_conflicting_method(%params) >>
09eeab06 854
bb153262 855Instantiate the parameters as a L<Moose::Meta::Role::Method::Conflicting>
09eeab06 856object, then add it to the required method list.
857
705d4cfd 858=back
859
860=head2 Method modifiers
0558683c 861
705d4cfd 862These methods act like their counterparts in L<Class::Mop::Class> and
863L<Moose::Meta::Class>.
864
865However, method modifiers are simply stored internally, and are not
866applied until the role itself is applied to a class.
0558683c 867
868=over 4
869
705d4cfd 870=item B<< $metarole->add_after_method_modifier($method_name, $method) >>
0558683c 871
705d4cfd 872=item B<< $metarole->add_around_method_modifier($method_name, $method) >>
0558683c 873
705d4cfd 874=item B<< $metarole->add_before_method_modifier($method_name, $method) >>
0558683c 875
705d4cfd 876=item B<< $metarole->add_override_method_modifier($method_name, $method) >>
0558683c 877
705d4cfd 878These methods all add an appropriate modifier to the internal list of
879modifiers.
0558683c 880
705d4cfd 881=item B<< $metarole->has_after_method_modifiers >>
0558683c 882
705d4cfd 883=item B<< $metarole->has_around_method_modifiers >>
884
885=item B<< $metarole->has_before_method_modifiers >>
886
887=item B<< $metarole->has_override_method_modifier >>
0558683c 888
705d4cfd 889Return true if the role has any modifiers of the given type.
0558683c 890
705d4cfd 891=item B<< $metarole->get_after_method_modifiers($method_name) >>
0558683c 892
705d4cfd 893=item B<< $metarole->get_around_method_modifiers($method_name) >>
0558683c 894
705d4cfd 895=item B<< $metarole->get_before_method_modifiers($method_name) >>
0558683c 896
705d4cfd 897Given a method name, returns a list of the appropriate modifiers for
898that method.
899
900=item B<< $metarole->get_override_method_modifier($method_name) >>
901
902Given a method name, returns the override method modifier for that
903method, if it has one.
0558683c 904
905=back
906
705d4cfd 907=head2 Introspection
505065c4 908
705d4cfd 909=over 4
505065c4 910
705d4cfd 911=item B<< Moose::Meta::Role->meta >>
505065c4 912
705d4cfd 913This will return a L<Class::MOP::Class> instance for this class.
505065c4 914
915=back
916
e185c027 917=head1 BUGS
918
fb1e11d5 919All complex software has bugs lurking in it, and this module is no
e185c027 920exception. If you find a bug please either email me, or add the bug
921to cpan-RT.
922
923=head1 AUTHOR
924
925Stevan Little E<lt>stevan@iinteractive.comE<gt>
926
927=head1 COPYRIGHT AND LICENSE
928
2840a3b2 929Copyright 2006-2009 by Infinity Interactive, Inc.
e185c027 930
931L<http://www.iinteractive.com>
932
933This library is free software; you can redistribute it and/or modify
fb1e11d5 934it under the same terms as Perl itself.
e185c027 935
b8aeb4dc 936=cut