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