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