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