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