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