make MMC->create and MMR->create install meta methods properly
[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;
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
2d5f3fab 482 my (%initialize_options) = %options;
b6a00b82 483 delete @initialize_options{qw(
484 package
485 attributes
486 methods
699a2e32 487 no_meta
b6a00b82 488 version
489 authority
490 )};
491
492 my $meta = $role->initialize( $package_name => %initialize_options );
493
6a4a7c31 494 $meta->_instantiate_module( $options{version}, $options{authority} );
495
699a2e32 496 $meta->_add_meta_method if !$options{no_meta};
b6a00b82 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