Doc deprecation warnings in Changes for Delta.pod
[gitmo/Moose.git] / lib / Moose / Meta / Attribute.pm
CommitLineData
c0e30cf5 1
2package Moose::Meta::Attribute;
3
4use strict;
5use warnings;
6
21f1e231 7use Scalar::Util 'blessed', 'weaken';
fe11f190 8use List::MoreUtils 'any';
1454efcc 9use Try::Tiny;
a909a4df 10use overload ();
a15dff8d 11
72643035 12our $VERSION = '1.08';
d44714be 13our $AUTHORITY = 'cpan:STEVAN';
78cd1d3b 14
8ee73eeb 15use Moose::Meta::Method::Accessor;
a05f85c1 16use Moose::Meta::Method::Delegation;
d5c30e52 17use Moose::Util ();
a3c7e2fe 18use Moose::Util::TypeConstraints ();
bc1e29b5 19
f785aad8 20use base 'Class::MOP::Attribute', 'Moose::Meta::Mixin::AttributeCore';
c0e30cf5 21
82a5b1a7 22__PACKAGE__->meta->add_attribute('traits' => (
23 reader => 'applied_traits',
24 predicate => 'has_applied_traits',
25));
82168dbb 26
d03bd989 27# we need to have a ->does method in here to
28# more easily support traits, and the introspection
0db4f1d7 29# of those traits. We extend the does check to look
30# for metatrait aliases.
31sub does {
32 my ($self, $role_name) = @_;
1454efcc 33 my $name = try {
0db4f1d7 34 Moose::Util::resolve_metatrait_alias(Attribute => $role_name)
35 };
36 return 0 if !defined($name); # failed to load class
e8895723 37 return $self->Moose::Object::does($name);
0db4f1d7 38}
587e457d 39
be05faea 40sub throw_error {
41 my $self = shift;
42 my $class = ( ref $self && $self->associated_class ) || "Moose::Meta::Class";
43 unshift @_, "message" if @_ % 2 == 1;
44 unshift @_, attr => $self if ref $self;
45 unshift @_, $class;
18748ad6 46 my $handler = $class->can("throw_error"); # to avoid incrementing depth by 1
47 goto $handler;
be05faea 48}
49
78cd1d3b 50sub new {
f3c4e20e 51 my ($class, $name, %options) = @_;
c32c2c61 52 $class->_process_options($name, \%options) unless $options{__hack_no_process_options}; # used from clone()... YECHKKK FIXME ICKY YUCK GROSS
aa4c3a8d 53
54 delete $options{__hack_no_process_options};
55
56 my %attrs =
57 ( map { $_ => 1 }
58 grep { defined }
59 map { $_->init_arg() }
60 $class->meta()->get_all_attributes()
61 );
62
63 my @bad = sort grep { ! $attrs{$_} } keys %options;
64
65 if (@bad)
66 {
67 Carp::cluck "Found unknown argument(s) passed to '$name' attribute constructor in '$class': @bad";
68 }
69
f3c4e20e 70 return $class->SUPER::new($name, %options);
1d768fb1 71}
72
d5c30e52 73sub interpolate_class_and_new {
aa4c3a8d 74 my ($class, $name, %args) = @_;
d5c30e52 75
aa4c3a8d 76 my ( $new_class, @traits ) = $class->interpolate_class(\%args);
d03bd989 77
aa4c3a8d 78 $new_class->new($name, %args, ( scalar(@traits) ? ( traits => \@traits ) : () ) );
d5c30e52 79}
80
81sub interpolate_class {
aa4c3a8d 82 my ($class, $options) = @_;
d5c30e52 83
c32c2c61 84 $class = ref($class) || $class;
85
aa4c3a8d 86 if ( my $metaclass_name = delete $options->{metaclass} ) {
c32c2c61 87 my $new_class = Moose::Util::resolve_metaclass_alias( Attribute => $metaclass_name );
d03bd989 88
c32c2c61 89 if ( $class ne $new_class ) {
90 if ( $new_class->can("interpolate_class") ) {
aa4c3a8d 91 return $new_class->interpolate_class($options);
c32c2c61 92 } else {
93 $class = $new_class;
94 }
95 }
d5c30e52 96 }
97
c32c2c61 98 my @traits;
99
aa4c3a8d 100 if (my $traits = $options->{traits}) {
8974015d 101 my $i = 0;
102 while ($i < @$traits) {
103 my $trait = $traits->[$i++];
104 next if ref($trait); # options to a trait we discarded
105
106 $trait = Moose::Util::resolve_metatrait_alias(Attribute => $trait)
107 || $trait;
108
109 next if $class->does($trait);
110
111 push @traits, $trait;
112
113 # are there options?
114 push @traits, $traits->[$i++]
115 if $traits->[$i] && ref($traits->[$i]);
116 }
965743fb 117
118 if (@traits) {
c32c2c61 119 my $anon_class = Moose::Meta::Class->create_anon_class(
120 superclasses => [ $class ],
121 roles => [ @traits ],
122 cache => 1,
123 );
124
125 $class = $anon_class->name;
126 }
d5c30e52 127 }
c32c2c61 128
129 return ( wantarray ? ( $class, @traits ) : $class );
d5c30e52 130}
131
e606ae5f 132# ...
133
ec835085 134# method-generating options shouldn't be overridden
135sub illegal_options_for_inheritance {
136 qw(is reader writer accessor clearer predicate)
137}
e606ae5f 138
139# NOTE/TODO
d03bd989 140# This method *must* be able to handle
141# Class::MOP::Attribute instances as
142# well. Yes, I know that is wrong, but
143# apparently we didn't realize it was
144# doing that and now we have some code
145# which is dependent on it. The real
146# solution of course is to push this
e606ae5f 147# feature back up into Class::MOP::Attribute
148# but I not right now, I am too lazy.
d03bd989 149# However if you are reading this and
150# looking for something to do,.. please
e606ae5f 151# be my guest.
152# - stevan
ce0e8d63 153sub clone_and_inherit_options {
154 my ($self, %options) = @_;
d03bd989 155
e606ae5f 156 # NOTE:
157 # we may want to extends a Class::MOP::Attribute
d03bd989 158 # in which case we need to be able to use the
159 # core set of legal options that have always
e606ae5f 160 # been here. But we allows Moose::Meta::Attribute
161 # instances to changes them.
162 # - SL
7782e1da 163 my @illegal_options = $self->can('illegal_options_for_inheritance')
164 ? $self->illegal_options_for_inheritance
165 : ();
166
ec835085 167 my @found_illegal_options = grep { exists $options{$_} && exists $self->{$_} ? $_ : undef } @illegal_options;
7782e1da 168 (scalar @found_illegal_options == 0)
169 || $self->throw_error("Illegal inherited options => (" . (join ', ' => @found_illegal_options) . ")", data => \%options);
26fbace8 170
ce0e8d63 171 if ($options{isa}) {
172 my $type_constraint;
8de73ff1 173 if (blessed($options{isa}) && $options{isa}->isa('Moose::Meta::TypeConstraint')) {
174 $type_constraint = $options{isa};
175 }
176 else {
d40ce9d5 177 $type_constraint = Moose::Util::TypeConstraints::find_or_create_isa_type_constraint($options{isa});
8de73ff1 178 (defined $type_constraint)
be05faea 179 || $self->throw_error("Could not find the type constraint '" . $options{isa} . "'", data => $options{isa});
8de73ff1 180 }
5e98d2b6 181
7782e1da 182 $options{type_constraint} = $type_constraint;
ce0e8d63 183 }
d03bd989 184
2ea379cb 185 if ($options{does}) {
186 my $type_constraint;
187 if (blessed($options{does}) && $options{does}->isa('Moose::Meta::TypeConstraint')) {
188 $type_constraint = $options{does};
189 }
190 else {
d40ce9d5 191 $type_constraint = Moose::Util::TypeConstraints::find_or_create_does_type_constraint($options{does});
2ea379cb 192 (defined $type_constraint)
be05faea 193 || $self->throw_error("Could not find the type constraint '" . $options{does} . "'", data => $options{does});
2ea379cb 194 }
195
7782e1da 196 $options{type_constraint} = $type_constraint;
d03bd989 197 }
c32c2c61 198
cbd141ca 199 # NOTE:
d03bd989 200 # this doesn't apply to Class::MOP::Attributes,
cbd141ca 201 # so we can ignore it for them.
202 # - SL
203 if ($self->can('interpolate_class')) {
7782e1da 204 ( $options{metaclass}, my @traits ) = $self->interpolate_class(\%options);
c32c2c61 205
cbd141ca 206 my %seen;
207 my @all_traits = grep { $seen{$_}++ } @{ $self->applied_traits || [] }, @traits;
7782e1da 208 $options{traits} = \@all_traits if @all_traits;
cbd141ca 209 }
c32c2c61 210
7782e1da 211 $self->clone(%options);
1d768fb1 212}
213
c32c2c61 214sub clone {
215 my ( $self, %params ) = @_;
216
aa4c3a8d 217 my $class = delete $params{metaclass} || ref $self;
c32c2c61 218
db72153d 219 my ( @init, @non_init );
c32c2c61 220
0772362a 221 foreach my $attr ( grep { $_->has_value($self) } Class::MOP::class_of($self)->get_all_attributes ) {
db72153d 222 push @{ $attr->has_init_arg ? \@init : \@non_init }, $attr;
223 }
c32c2c61 224
db72153d 225 my %new_params = ( ( map { $_->init_arg => $_->get_value($self) } @init ), %params );
c32c2c61 226
db72153d 227 my $name = delete $new_params{name};
c32c2c61 228
db72153d 229 my $clone = $class->new($name, %new_params, __hack_no_process_options => 1 );
c32c2c61 230
db72153d 231 foreach my $attr ( @non_init ) {
232 $attr->set_value($clone, $attr->get_value($self));
c32c2c61 233 }
db72153d 234
235 return $clone;
c32c2c61 236}
237
1d768fb1 238sub _process_options {
239 my ($class, $name, $options) = @_;
8de73ff1 240
f3c4e20e 241 if (exists $options->{is}) {
21f1e231 242
012fcbd1 243 ### -------------------------
244 ## is => ro, writer => _foo # turns into (reader => foo, writer => _foo) as before
245 ## is => rw, writer => _foo # turns into (reader => foo, writer => _foo)
246 ## is => rw, accessor => _foo # turns into (accessor => _foo)
247 ## is => ro, accessor => _foo # error, accesor is rw
248 ### -------------------------
d03bd989 249
8de73ff1 250 if ($options->{is} eq 'ro') {
be05faea 251 $class->throw_error("Cannot define an accessor name on a read-only attribute, accessors are read/write", data => $options)
21f1e231 252 if exists $options->{accessor};
8de73ff1 253 $options->{reader} ||= $name;
8de73ff1 254 }
255 elsif ($options->{is} eq 'rw') {
21f1e231 256 if ($options->{writer}) {
257 $options->{reader} ||= $name;
258 }
259 else {
260 $options->{accessor} ||= $name;
261 }
8de73ff1 262 }
ccd4cff9 263 elsif ($options->{is} eq 'bare') {
264 # do nothing, but don't complain (later) about missing methods
265 }
8de73ff1 266 else {
e606ae5f 267 $class->throw_error("I do not understand this option (is => " . $options->{is} . ") on attribute ($name)", data => $options->{is});
8de73ff1 268 }
f3c4e20e 269 }
8de73ff1 270
f3c4e20e 271 if (exists $options->{isa}) {
f3c4e20e 272 if (exists $options->{does}) {
1454efcc 273 if (try { $options->{isa}->can('does') }) {
f3c4e20e 274 ($options->{isa}->does($options->{does}))
e606ae5f 275 || $class->throw_error("Cannot have an isa option and a does option if the isa does not do the does on attribute ($name)", data => $options);
f3c4e20e 276 }
277 else {
e606ae5f 278 $class->throw_error("Cannot have an isa option which cannot ->does() on attribute ($name)", data => $options);
26fbace8 279 }
26fbace8 280 }
8de73ff1 281
f3c4e20e 282 # allow for anon-subtypes here ...
283 if (blessed($options->{isa}) && $options->{isa}->isa('Moose::Meta::TypeConstraint')) {
8de73ff1 284 $options->{type_constraint} = $options->{isa};
285 }
286 else {
620db045 287 $options->{type_constraint} = Moose::Util::TypeConstraints::find_or_create_isa_type_constraint($options->{isa});
8de73ff1 288 }
f3c4e20e 289 }
290 elsif (exists $options->{does}) {
291 # allow for anon-subtypes here ...
292 if (blessed($options->{does}) && $options->{does}->isa('Moose::Meta::TypeConstraint')) {
238b424d 293 $options->{type_constraint} = $options->{does};
8de73ff1 294 }
295 else {
620db045 296 $options->{type_constraint} = Moose::Util::TypeConstraints::find_or_create_does_type_constraint($options->{does});
8de73ff1 297 }
f3c4e20e 298 }
8de73ff1 299
f3c4e20e 300 if (exists $options->{coerce} && $options->{coerce}) {
301 (exists $options->{type_constraint})
e606ae5f 302 || $class->throw_error("You cannot have coercion without specifying a type constraint on attribute ($name)", data => $options);
303 $class->throw_error("You cannot have a weak reference to a coerced value on attribute ($name)", data => $options)
8de73ff1 304 if $options->{weak_ref};
2b54d2a6 305
470bc652 306 unless ( $options->{type_constraint}->has_coercion ) {
307 my $type = $options->{type_constraint}->name;
308 $class->throw_error("You cannot coerce an attribute ($name) unless its type ($type) has a coercion", data => $options);
309 }
f3c4e20e 310 }
8de73ff1 311
0b7df53c 312 if (exists $options->{trigger}) {
21f1e231 313 ('CODE' eq ref $options->{trigger})
e606ae5f 314 || $class->throw_error("Trigger must be a CODE ref on attribute ($name)", data => $options->{trigger});
0b7df53c 315 }
316
f3c4e20e 317 if (exists $options->{auto_deref} && $options->{auto_deref}) {
318 (exists $options->{type_constraint})
e606ae5f 319 || $class->throw_error("You cannot auto-dereference without specifying a type constraint on attribute ($name)", data => $options);
f3c4e20e 320 ($options->{type_constraint}->is_a_type_of('ArrayRef') ||
8de73ff1 321 $options->{type_constraint}->is_a_type_of('HashRef'))
e606ae5f 322 || $class->throw_error("You cannot auto-dereference anything other than a ArrayRef or HashRef on attribute ($name)", data => $options);
f3c4e20e 323 }
8de73ff1 324
f3c4e20e 325 if (exists $options->{lazy_build} && $options->{lazy_build} == 1) {
e606ae5f 326 $class->throw_error("You can not use lazy_build and default for the same attribute ($name)", data => $options)
8de73ff1 327 if exists $options->{default};
a6c84c69 328 $options->{lazy} = 1;
a6c84c69 329 $options->{builder} ||= "_build_${name}";
330 if ($name =~ /^_/) {
f3c4e20e 331 $options->{clearer} ||= "_clear${name}";
332 $options->{predicate} ||= "_has${name}";
d03bd989 333 }
a6c84c69 334 else {
f3c4e20e 335 $options->{clearer} ||= "clear_${name}";
336 $options->{predicate} ||= "has_${name}";
26fbace8 337 }
f3c4e20e 338 }
8de73ff1 339
f3c4e20e 340 if (exists $options->{lazy} && $options->{lazy}) {
9edba990 341 (exists $options->{default} || defined $options->{builder} )
be05faea 342 || $class->throw_error("You cannot have lazy attribute ($name) without specifying a default value for it", data => $options);
f3c4e20e 343 }
26fbace8 344
9edba990 345 if ( $options->{required} && !( ( !exists $options->{init_arg} || defined $options->{init_arg} ) || exists $options->{default} || defined $options->{builder} ) ) {
be05faea 346 $class->throw_error("You cannot have a required attribute ($name) without a default, builder, or an init_arg", data => $options);
9edba990 347 }
348
78cd1d3b 349}
c0e30cf5 350
d500266f 351sub initialize_instance_slot {
ddd0ec20 352 my ($self, $meta_instance, $instance, $params) = @_;
d500266f 353 my $init_arg = $self->init_arg();
354 # try to fetch the init arg from the %params ...
ddd0ec20 355
26fbace8 356 my $val;
1ed0b94f 357 my $value_is_set;
625d571f 358 if ( defined($init_arg) and exists $params->{$init_arg}) {
d500266f 359 $val = $params->{$init_arg};
d03bd989 360 $value_is_set = 1;
d500266f 361 }
362 else {
363 # skip it if it's lazy
364 return if $self->is_lazy;
365 # and die if it's required and doesn't have a default value
be05faea 366 $self->throw_error("Attribute (" . $self->name . ") is required", object => $instance, data => $params)
26fbace8 367 if $self->is_required && !$self->has_default && !$self->has_builder;
ddd0ec20 368
1ed0b94f 369 # if nothing was in the %params, we can use the
370 # attribute's default value (if it has one)
371 if ($self->has_default) {
372 $val = $self->default($instance);
373 $value_is_set = 1;
d03bd989 374 }
a6c84c69 375 elsif ($self->has_builder) {
e606ae5f 376 $val = $self->_call_builder($instance);
377 $value_is_set = 1;
a0748c37 378 }
26fbace8 379 }
380
1ed0b94f 381 return unless $value_is_set;
382
9c9563c7 383 $val = $self->_coerce_and_verify( $val, $instance );
ddd0ec20 384
759e4e8f 385 $self->set_initial_value($instance, $val);
312e0f0c 386
387 if ( ref $val && $self->is_weak_ref ) {
32881f68 388 $self->_weaken_value($instance);
312e0f0c 389 }
d500266f 390}
391
e606ae5f 392sub _call_builder {
393 my ( $self, $instance ) = @_;
394
395 my $builder = $self->builder();
396
397 return $instance->$builder()
398 if $instance->can( $self->builder );
399
400 $self->throw_error( blessed($instance)
401 . " does not support builder method '"
402 . $self->builder
403 . "' for attribute '"
404 . $self->name
405 . "'",
406 object => $instance,
407 );
408}
409
d617b644 410## Slot management
9e93dd19 411
8abe9636 412# FIXME:
d03bd989 413# this duplicates too much code from
414# Class::MOP::Attribute, we need to
8abe9636 415# refactor these bits eventually.
416# - SL
417sub _set_initial_slot_value {
418 my ($self, $meta_instance, $instance, $value) = @_;
419
420 my $slot_name = $self->name;
421
422 return $meta_instance->set_slot_value($instance, $slot_name, $value)
423 unless $self->has_initializer;
424
8abe9636 425 my $callback = sub {
9c9563c7 426 my $val = $self->_coerce_and_verify( shift, $instance );;
427
8abe9636 428 $meta_instance->set_slot_value($instance, $slot_name, $val);
429 };
d03bd989 430
8abe9636 431 my $initializer = $self->initializer;
432
433 # most things will just want to set a value, so make it first arg
434 $instance->$initializer($value, $callback, $self);
435}
436
946289d1 437sub set_value {
b6af66f8 438 my ($self, $instance, @args) = @_;
439 my $value = $args[0];
26fbace8 440
946289d1 441 my $attr_name = $self->name;
26fbace8 442
b6af66f8 443 if ($self->is_required and not @args) {
be05faea 444 $self->throw_error("Attribute ($attr_name) is required", object => $instance);
946289d1 445 }
26fbace8 446
9c9563c7 447 $value = $self->_coerce_and_verify( $value, $instance );
26fbace8 448
3dda07f5 449 my @old;
450 if ( $self->has_trigger && $self->has_value($instance) ) {
451 @old = $self->get_value($instance, 'for trigger');
452 }
453
312e0f0c 454 $self->SUPER::set_value($instance, $value);
26fbace8 455
312e0f0c 456 if ( ref $value && $self->is_weak_ref ) {
32881f68 457 $self->_weaken_value($instance);
946289d1 458 }
26fbace8 459
946289d1 460 if ($self->has_trigger) {
3dda07f5 461 $self->trigger->($instance, $value, @old);
946289d1 462 }
463}
464
32881f68 465sub _weaken_value {
312e0f0c 466 my ( $self, $instance ) = @_;
467
32881f68 468 my $meta_instance = Class::MOP::Class->initialize( blessed($instance) )
469 ->get_meta_instance;
312e0f0c 470
471 $meta_instance->weaken_slot_value( $instance, $self->name );
472}
473
946289d1 474sub get_value {
3dda07f5 475 my ($self, $instance, $for_trigger) = @_;
26fbace8 476
946289d1 477 if ($self->is_lazy) {
8de73ff1 478 unless ($self->has_value($instance)) {
e606ae5f 479 my $value;
8de73ff1 480 if ($self->has_default) {
e606ae5f 481 $value = $self->default($instance);
3f11800d 482 } elsif ( $self->has_builder ) {
e606ae5f 483 $value = $self->_call_builder($instance);
484 }
9c9563c7 485
486 $value = $self->_coerce_and_verify( $value, $instance );
487
e606ae5f 488 $self->set_initial_value($instance, $value);
8de73ff1 489 }
946289d1 490 }
26fbace8 491
3dda07f5 492 if ( $self->should_auto_deref && ! $for_trigger ) {
26fbace8 493
946289d1 494 my $type_constraint = $self->type_constraint;
495
496 if ($type_constraint->is_a_type_of('ArrayRef')) {
497 my $rv = $self->SUPER::get_value($instance);
498 return unless defined $rv;
499 return wantarray ? @{ $rv } : $rv;
26fbace8 500 }
946289d1 501 elsif ($type_constraint->is_a_type_of('HashRef')) {
502 my $rv = $self->SUPER::get_value($instance);
503 return unless defined $rv;
504 return wantarray ? %{ $rv } : $rv;
26fbace8 505 }
946289d1 506 else {
46cb090f 507 $self->throw_error("Can not auto de-reference the type constraint '" . $type_constraint->name . "'", object => $instance, type_constraint => $type_constraint);
946289d1 508 }
26fbace8 509
946289d1 510 }
511 else {
26fbace8 512
946289d1 513 return $self->SUPER::get_value($instance);
26fbace8 514 }
946289d1 515}
a15dff8d 516
26fbace8 517## installing accessors
c0e30cf5 518
246bbeef 519sub accessor_metaclass { 'Moose::Meta::Method::Accessor' }
520
521sub install_accessors {
ae907ae0 522 my $self = shift;
246bbeef 523 $self->SUPER::install_accessors(@_);
524 $self->install_delegation if $self->has_handles;
28af3424 525 return;
526}
527
9340e346 528sub _check_associated_methods {
28af3424 529 my $self = shift;
86cf196b 530 unless (
0bbd378f 531 @{ $self->associated_methods }
86cf196b 532 || ($self->_is_metadata || '') eq 'bare'
533 ) {
534 Carp::cluck(
8f4450f3 535 'Attribute (' . $self->name . ') of class '
536 . $self->associated_class->name
537 . ' has no associated methods'
86cf196b 538 . ' (did you mean to provide an "is" argument?)'
539 . "\n"
540 )
541 }
e606ae5f 542}
26fbace8 543
3b6e2290 544sub _process_accessors {
545 my $self = shift;
546 my ($type, $accessor, $generate_as_inline_methods) = @_;
547 $accessor = (keys %$accessor)[0] if (ref($accessor)||'') eq 'HASH';
99541dfd 548 my $method = $self->associated_class->get_method($accessor);
549 if ($method && !$method->isa('Class::MOP::Method::Accessor')
550 && (!$self->definition_context
551 || $method->package_name eq $self->definition_context->{package})) {
3b6e2290 552 Carp::cluck(
1d18c898 553 "You are overwriting a locally defined method ($accessor) with "
3b6e2290 554 . "an accessor"
555 );
556 }
3968746e 557 if (!$self->associated_class->has_method($accessor)
558 && $self->associated_class->has_package_symbol('&' . $accessor)) {
559 Carp::cluck(
560 "You are overwriting a locally defined function ($accessor) with "
561 . "an accessor"
562 );
563 }
3b6e2290 564 $self->SUPER::_process_accessors(@_);
e606ae5f 565}
26fbace8 566
e1d6f0a3 567sub remove_accessors {
568 my $self = shift;
569 $self->SUPER::remove_accessors(@_);
570 $self->remove_delegation if $self->has_handles;
571 return;
572}
573
e606ae5f 574sub install_delegation {
575 my $self = shift;
26fbace8 576
e606ae5f 577 # NOTE:
578 # Here we canonicalize the 'handles' option
579 # this will sort out any details and always
580 # return an hash of methods which we want
581 # to delagate to, see that method for details
582 my %handles = $self->_canonicalize_handles;
583
e606ae5f 584
585 # install the delegation ...
586 my $associated_class = $self->associated_class;
587 foreach my $handle (keys %handles) {
588 my $method_to_call = $handles{$handle};
589 my $class_name = $associated_class->name;
590 my $name = "${class_name}::${handle}";
26fbace8 591
452bac1b 592 (!$associated_class->has_method($handle))
cee532a1 593 || $self->throw_error("You cannot overwrite a locally defined method ($handle) with a delegation", method_name => $handle);
26fbace8 594
e606ae5f 595 # NOTE:
596 # handles is not allowed to delegate
597 # any of these methods, as they will
598 # override the ones in your class, which
599 # is almost certainly not what you want.
4fe78472 600
e606ae5f 601 # FIXME warn when $handle was explicitly specified, but not if the source is a regex or something
602 #cluck("Not delegating method '$handle' because it is a core method") and
603 next if $class_name->isa("Moose::Object") and $handle =~ /^BUILD|DEMOLISH$/ || Moose::Object->can($handle);
26fbace8 604
46f7e6a5 605 my $method = $self->_make_delegation_method($handle, $method_to_call);
a05f85c1 606
607 $self->associated_class->add_method($method->name, $method);
0bbd378f 608 $self->associate_method($method);
d03bd989 609 }
452bac1b 610}
611
e1d6f0a3 612sub remove_delegation {
613 my $self = shift;
614 my %handles = $self->_canonicalize_handles;
615 my $associated_class = $self->associated_class;
616 foreach my $handle (keys %handles) {
684323b3 617 next unless any { $handle eq $_ }
618 map { $_->name }
619 @{ $self->associated_methods };
e1d6f0a3 620 $self->associated_class->remove_method($handle);
621 }
622}
623
98aae381 624# private methods to help delegation ...
625
452bac1b 626sub _canonicalize_handles {
627 my $self = shift;
628 my $handles = $self->handles;
c84f324f 629 if (my $handle_type = ref($handles)) {
630 if ($handle_type eq 'HASH') {
631 return %{$handles};
632 }
633 elsif ($handle_type eq 'ARRAY') {
634 return map { $_ => $_ } @{$handles};
635 }
636 elsif ($handle_type eq 'Regexp') {
637 ($self->has_type_constraint)
0286711b 638 || $self->throw_error("Cannot delegate methods based on a Regexp without a type constraint (isa)", data => $handles);
26fbace8 639 return map { ($_ => $_) }
c84f324f 640 grep { /$handles/ } $self->_get_delegate_method_list;
641 }
642 elsif ($handle_type eq 'CODE') {
643 return $handles->($self, $self->_find_delegate_metaclass);
644 }
6cbf4a23 645 elsif (blessed($handles) && $handles->isa('Moose::Meta::TypeConstraint::DuckType')) {
646 return map { $_ => $_ } @{ $handles->methods };
647 }
c7761602 648 elsif (blessed($handles) && $handles->isa('Moose::Meta::TypeConstraint::Role')) {
649 $handles = $handles->role;
650 }
c84f324f 651 else {
be05faea 652 $self->throw_error("Unable to canonicalize the 'handles' option with $handles", data => $handles);
c84f324f 653 }
452bac1b 654 }
c84f324f 655
c7761602 656 Class::MOP::load_class($handles);
657 my $role_meta = Class::MOP::class_of($handles);
d03bd989 658
c7761602 659 (blessed $role_meta && $role_meta->isa('Moose::Meta::Role'))
660 || $self->throw_error("Unable to canonicalize the 'handles' option with $handles because its metaclass is not a Moose::Meta::Role", data => $handles);
661
662 return map { $_ => $_ }
663 grep { $_ ne 'meta' } (
664 $role_meta->get_method_list,
665 map { $_->name } $role_meta->get_required_method_list,
666 );
452bac1b 667}
668
669sub _find_delegate_metaclass {
670 my $self = shift;
98aae381 671 if (my $class = $self->_isa_metadata) {
9031e2c4 672 # we might be dealing with a non-Moose class,
673 # and need to make our own metaclass. if there's
674 # already a metaclass, it will be returned
88389e14 675 return Class::MOP::Class->initialize($class);
452bac1b 676 }
98aae381 677 elsif (my $role = $self->_does_metadata) {
91e6653b 678 return Class::MOP::class_of($role);
452bac1b 679 }
680 else {
be05faea 681 $self->throw_error("Cannot find delegate metaclass for attribute " . $self->name);
452bac1b 682 }
683}
684
685sub _get_delegate_method_list {
686 my $self = shift;
687 my $meta = $self->_find_delegate_metaclass;
688 if ($meta->isa('Class::MOP::Class')) {
e606ae5f 689 return map { $_->name } # NOTE: !never! delegate &meta
690 grep { $_->package_name ne 'Moose::Object' && $_->name ne 'meta' }
691 $meta->get_all_methods;
452bac1b 692 }
693 elsif ($meta->isa('Moose::Meta::Role')) {
26fbace8 694 return $meta->get_method_list;
452bac1b 695 }
696 else {
be05faea 697 $self->throw_error("Unable to recognize the delegate metaclass '$meta'", data => $meta);
452bac1b 698 }
699}
700
bd1226e2 701sub delegation_metaclass { 'Moose::Meta::Method::Delegation' }
702
a05f85c1 703sub _make_delegation_method {
46f7e6a5 704 my ( $self, $handle_name, $method_to_call ) = @_;
a05f85c1 705
3c573ca4 706 my @curried_arguments;
2de18801 707
3c573ca4 708 ($method_to_call, @curried_arguments) = @$method_to_call
2de18801 709 if 'ARRAY' eq ref($method_to_call);
710
bd1226e2 711 return $self->delegation_metaclass->new(
46f7e6a5 712 name => $handle_name,
713 package_name => $self->associated_class->name,
714 attribute => $self,
715 delegate_to_method => $method_to_call,
3c573ca4 716 curried_arguments => \@curried_arguments,
a05f85c1 717 );
718}
719
9c9563c7 720sub _coerce_and_verify {
721 my $self = shift;
722 my $val = shift;
723 my $instance = shift;
724
725 return $val unless $self->has_type_constraint;
726
2b54d2a6 727 $val = $self->type_constraint->coerce($val)
728 if $self->should_coerce;
9c9563c7 729
730 $self->verify_against_type_constraint($val, instance => $instance);
731
732 return $val;
733}
734
5755a9b2 735sub verify_against_type_constraint {
2b86e02b 736 my $self = shift;
737 my $val = shift;
738
739 return 1 if !$self->has_type_constraint;
740
741 my $type_constraint = $self->type_constraint;
742
743 $type_constraint->check($val)
744 || $self->throw_error("Attribute ("
745 . $self->name
746 . ") does not pass the type constraint because: "
747 . $type_constraint->get_message($val), data => $val, @_);
748}
749
21f1e231 750package Moose::Meta::Attribute::Custom::Moose;
751sub register_implementation { 'Moose::Meta::Attribute' }
752
c0e30cf5 7531;
754
755__END__
756
757=pod
758
759=head1 NAME
760
6ba6d68c 761Moose::Meta::Attribute - The Moose attribute metaclass
c0e30cf5 762
763=head1 DESCRIPTION
764
93a708fd 765This class is a subclass of L<Class::MOP::Attribute> that provides
766additional Moose-specific functionality.
6ba6d68c 767
7854b409 768To really understand this class, you will need to start with the
769L<Class::MOP::Attribute> documentation. This class can be understood
770as a set of additional features on top of the basic feature provided
771by that parent class.
e522431d 772
d4b1449e 773=head1 INHERITANCE
774
775C<Moose::Meta::Attribute> is a subclass of L<Class::MOP::Attribute>.
776
c0e30cf5 777=head1 METHODS
778
93a708fd 779Many of the documented below override methods in
780L<Class::MOP::Attribute> and add Moose specific features.
6ba6d68c 781
93a708fd 782=head2 Creation
6ba6d68c 783
c0e30cf5 784=over 4
785
93a708fd 786=item B<< Moose::Meta::Attribute->new(%options) >>
c0e30cf5 787
93a708fd 788This method overrides the L<Class::MOP::Attribute> constructor.
c32c2c61 789
93a708fd 790Many of the options below are described in more detail in the
791L<Moose::Manual::Attributes> document.
6e2840b7 792
93a708fd 793It adds the following options to the constructor:
d500266f 794
93a708fd 795=over 8
452bac1b 796
996b8c8d 797=item * is => 'ro', 'rw', 'bare'
e1d6f0a3 798
93a708fd 799This provides a shorthand for specifying the C<reader>, C<writer>, or
800C<accessor> names. If the attribute is read-only ('ro') then it will
801have a C<reader> method with the same attribute as the name.
e606ae5f 802
93a708fd 803If it is read-write ('rw') then it will have an C<accessor> method
804with the same name. If you provide an explicit C<writer> for a
805read-write attribute, then you will have a C<reader> with the same
806name as the attribute, and a C<writer> with the name you provided.
e1d6f0a3 807
996b8c8d 808Use 'bare' when you are deliberately not installing any methods
809(accessor, reader, etc.) associated with this attribute; otherwise,
810Moose will issue a deprecation warning when this attribute is added to a
9340e346 811metaclass.
996b8c8d 812
93a708fd 813=item * isa => $type
39b3bc94 814
93a708fd 815This option accepts a type. The type can be a string, which should be
816a type name. If the type name is unknown, it is assumed to be a class
817name.
818
819This option can also accept a L<Moose::Meta::TypeConstraint> object.
820
821If you I<also> provide a C<does> option, then your C<isa> option must
822be a class name, and that class must do the role specified with
823C<does>.
824
825=item * does => $role
826
827This is short-hand for saying that the attribute's type must be an
828object which does the named role.
829
830=item * coerce => $bool
831
832This option is only valid for objects with a type constraint
833(C<isa>). If this is true, then coercions will be applied whenever
834this attribute is set.
835
836You can make both this and the C<weak_ref> option true.
837
838=item * trigger => $sub
839
840This option accepts a subroutine reference, which will be called after
841the attribute is set.
842
843=item * required => $bool
844
845An attribute which is required must be provided to the constructor. An
846attribute which is required can also have a C<default> or C<builder>,
36741534 847which will satisfy its required-ness.
93a708fd 848
849A required attribute must have a C<default>, C<builder> or a
850non-C<undef> C<init_arg>
851
852=item * lazy => $bool
853
854A lazy attribute must have a C<default> or C<builder>. When an
855attribute is lazy, the default value will not be calculated until the
856attribute is read.
857
858=item * weak_ref => $bool
859
860If this is true, the attribute's value will be stored as a weak
861reference.
862
863=item * auto_deref => $bool
864
865If this is true, then the reader will dereference the value when it is
866called. The attribute must have a type constraint which defines the
867attribute as an array or hash reference.
868
869=item * lazy_build => $bool
870
871Setting this to true makes the attribute lazy and provides a number of
872default methods.
873
874 has 'size' => (
875 is => 'ro',
876 lazy_build => 1,
877 );
878
879is equivalent to this:
880
881 has 'size' => (
882 is => 'ro',
883 lazy => 1,
884 builder => '_build_size',
885 clearer => 'clear_size',
886 predicate => 'has_size',
887 );
888
889=item * documentation
890
891An arbitrary string that can be retrieved later by calling C<<
892$attr->documentation >>.
893
894=back
895
896=item B<< $attr->clone(%options) >>
897
898This creates a new attribute based on attribute being cloned. You must
899supply a C<name> option to provide a new name for the attribute.
900
901The C<%options> can only specify options handled by
902L<Class::MOP::Attribute>.
903
36741534 904=back
905
93a708fd 906=head2 Value management
907
36741534 908=over 4
909
93a708fd 910=item B<< $attr->initialize_instance_slot($meta_instance, $instance, $params) >>
911
912This method is used internally to initialize the attribute's slot in
913the object C<$instance>.
914
915This overrides the L<Class::MOP::Attribute> method to handle lazy
916attributes, weak references, and type constraints.
bd1226e2 917
946289d1 918=item B<get_value>
919
920=item B<set_value>
921
6549b0d1 922 eval { $point->meta->get_attribute('x')->set_value($point, 'forty-two') };
bcbaa845 923 if($@) {
924 print "Oops: $@\n";
925 }
926
6549b0d1 927I<Attribute (x) does not pass the type constraint (Int) with 'forty-two'>
bcbaa845 928
929Before setting the value, a check is made on the type constraint of
930the attribute, if it has one, to see if the value passes it. If the
cec39889 931value fails to pass, the set operation dies with a L</throw_error>.
bcbaa845 932
933Any coercion to convert values is done before checking the type constraint.
934
935To check a value against a type constraint before setting it, fetch the
ec00fa75 936attribute instance using L<Class::MOP::Class/find_attribute_by_name>,
bcbaa845 937fetch the type_constraint from the attribute using L<Moose::Meta::Attribute/type_constraint>
e606ae5f 938and call L<Moose::Meta::TypeConstraint/check>. See L<Moose::Cookbook::Basics::Recipe4>
bcbaa845 939for an example.
940
a15dff8d 941=back
942
93a708fd 943=head2 Attribute Accessor generation
6ba6d68c 944
a15dff8d 945=over 4
946
93a708fd 947=item B<< $attr->install_accessors >>
be05faea 948
93a708fd 949This method overrides the parent to also install delegation methods.
be05faea 950
7a582117 951If, after installing all methods, the attribute object has no associated
952methods, it throws an error unless C<< is => 'bare' >> was passed to the
953attribute constructor. (Trying to add an attribute that has no associated
954methods is almost always an error.)
955
36741534 956=item B<< $attr->remove_accessors >>
d5c30e52 957
93a708fd 958This method overrides the parent to also remove delegation methods.
d5c30e52 959
93a708fd 960=item B<< $attr->install_delegation >>
961
962This method adds its delegation methods to the attribute's associated
963class, if it has any to add.
964
965=item B<< $attr->remove_delegation >>
966
967This method remove its delegation methods from the attribute's
968associated class.
d5c30e52 969
93a708fd 970=item B<< $attr->accessor_metaclass >>
9e93dd19 971
93a708fd 972Returns the accessor metaclass name, which defaults to
973L<Moose::Meta::Method::Accessor>.
974
975=item B<< $attr->delegation_metaclass >>
976
977Returns the delegation metaclass name, which defaults to
978L<Moose::Meta::Method::Delegation>.
979
980=back
981
982=head2 Additional Moose features
983
984These methods are not found in the superclass. They support features
985provided by Moose.
986
36741534 987=over 4
988
93a708fd 989=item B<< $attr->does($role) >>
990
991This indicates whether the I<attribute itself> does the given
36741534 992role. The role can be given as a full class name, or as a resolvable
93a708fd 993trait name.
994
995Note that this checks the attribute itself, not its type constraint,
996so it is checking the attribute's metaclass and any traits applied to
997the attribute.
998
999=item B<< Moose::Meta::Class->interpolate_class_and_new($name, %options) >>
1000
1001This is an alternate constructor that handles the C<metaclass> and
1002C<traits> options.
9e93dd19 1003
93a708fd 1004Effectively, this method is a factory that finds or creates the
36741534 1005appropriate class for the given C<metaclass> and/or C<traits>.
e606ae5f 1006
93a708fd 1007Once it has the appropriate class, it will call C<< $class->new($name,
1008%options) >> on that class.
e606ae5f 1009
93a708fd 1010=item B<< $attr->clone_and_inherit_options(%options) >>
a15dff8d 1011
93a708fd 1012This method supports the C<has '+foo'> feature. It does various bits
1013of processing on the supplied C<%options> before ultimately calling
1014the C<clone> method.
6ba6d68c 1015
93a708fd 1016One of its main tasks is to make sure that the C<%options> provided
7782e1da 1017does not include the options returned by the
1018C<illegal_options_for_inheritance> method.
a15dff8d 1019
7782e1da 1020=item B<< $attr->illegal_options_for_inheritance >>
a15dff8d 1021
7782e1da 1022This returns a blacklist of options that can not be overridden in a
93a708fd 1023subclass's attribute definition.
2b86e02b 1024
93a708fd 1025This exists to allow a custom metaclass to change or add to the list
7782e1da 1026of options which can not be changed.
2b86e02b 1027
93a708fd 1028=item B<< $attr->type_constraint >>
452bac1b 1029
93a708fd 1030Returns the L<Moose::Meta::TypeConstraint> object for this attribute,
1031if it has one.
452bac1b 1032
93a708fd 1033=item B<< $attr->has_type_constraint >>
452bac1b 1034
93a708fd 1035Returns true if this attribute has a type constraint.
452bac1b 1036
93a708fd 1037=item B<< $attr->verify_against_type_constraint($value) >>
a15dff8d 1038
93a708fd 1039Given a value, this method returns true if the value is valid for the
1040attribute's type constraint. If the value is not valid, it throws an
1041error.
4b598ea3 1042
93a708fd 1043=item B<< $attr->handles >>
ca01a97b 1044
93a708fd 1045This returns the value of the C<handles> option passed to the
1046constructor.
ca01a97b 1047
93a708fd 1048=item B<< $attr->has_handles >>
ca01a97b 1049
93a708fd 1050Returns true if this attribute performs delegation.
ca01a97b 1051
93a708fd 1052=item B<< $attr->is_weak_ref >>
26fbace8 1053
93a708fd 1054Returns true if this attribute stores its value as a weak reference.
26fbace8 1055
93a708fd 1056=item B<< $attr->is_required >>
26fbace8 1057
93a708fd 1058Returns true if this attribute is required to have a value.
26fbace8 1059
93a708fd 1060=item B<< $attr->is_lazy >>
58f85113 1061
93a708fd 1062Returns true if this attribute is lazy.
26fbace8 1063
93a708fd 1064=item B<< $attr->is_lazy_build >>
ca01a97b 1065
93a708fd 1066Returns true if the C<lazy_build> option was true when passed to the
1067constructor.
4b598ea3 1068
93a708fd 1069=item B<< $attr->should_coerce >>
6ba6d68c 1070
93a708fd 1071Returns true if the C<coerce> option passed to the constructor was
1072true.
536f0b17 1073
93a708fd 1074=item B<< $attr->should_auto_deref >>
536f0b17 1075
93a708fd 1076Returns true if the C<auto_deref> option passed to the constructor was
1077true.
536f0b17 1078
93a708fd 1079=item B<< $attr->trigger >>
8c9d74e7 1080
93a708fd 1081This is the subroutine reference that was in the C<trigger> option
1082passed to the constructor, if any.
02a0fb52 1083
36741534 1084=item B<< $attr->has_trigger >>
8c9d74e7 1085
93a708fd 1086Returns true if this attribute has a trigger set.
02a0fb52 1087
93a708fd 1088=item B<< $attr->documentation >>
ddbdc0cb 1089
93a708fd 1090Returns the value that was in the C<documentation> option passed to
1091the constructor, if any.
ddbdc0cb 1092
93a708fd 1093=item B<< $attr->has_documentation >>
ddbdc0cb 1094
93a708fd 1095Returns true if this attribute has any documentation.
ddbdc0cb 1096
93a708fd 1097=item B<< $attr->applied_traits >>
88f23977 1098
93a708fd 1099This returns an array reference of all the traits which were applied
1100to this attribute. If none were applied, this returns C<undef>.
88f23977 1101
93a708fd 1102=item B<< $attr->has_applied_traits >>
88f23977 1103
93a708fd 1104Returns true if this attribute has any traits applied.
88f23977 1105
c0e30cf5 1106=back
1107
1108=head1 BUGS
1109
d4048ef3 1110See L<Moose/BUGS> for details on reporting bugs.
c0e30cf5 1111
c0e30cf5 1112=head1 AUTHOR
1113
1114Stevan Little E<lt>stevan@iinteractive.comE<gt>
1115
98aae381 1116Yuval Kogman E<lt>nothingmuch@woobling.comE<gt>
1117
c0e30cf5 1118=head1 COPYRIGHT AND LICENSE
1119
7e0492d3 1120Copyright 2006-2010 by Infinity Interactive, Inc.
c0e30cf5 1121
1122L<http://www.iinteractive.com>
1123
1124This library is free software; you can redistribute it and/or modify
26fbace8 1125it under the same terms as Perl itself.
c0e30cf5 1126
8a7a9c53 1127=cut