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