cadc9d7cf6fbb50e3bff1df94e97eb09b41c2efc
[gitmo/Moose.git] / lib / Moose / Meta / Attribute.pm
1
2 package Moose::Meta::Attribute;
3
4 use strict;
5 use warnings;
6
7 use Scalar::Util 'blessed', 'weaken';
8 use Carp         'confess';
9 use overload     ();
10
11 our $VERSION   = '0.50';
12 our $AUTHORITY = 'cpan:STEVAN';
13
14 use Moose::Meta::Method::Accessor;
15 use Moose::Util ();
16 use Moose::Util::TypeConstraints ();
17
18 use base 'Class::MOP::Attribute';
19
20 # options which are not directly used
21 # but we store them for metadata purposes
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'));
25
26 # these are actual options for the attrs
27 __PACKAGE__->meta->add_attribute('required'   => (reader => 'is_required'      ));
28 __PACKAGE__->meta->add_attribute('lazy'       => (reader => 'is_lazy'          ));
29 __PACKAGE__->meta->add_attribute('lazy_build' => (reader => 'is_lazy_build'    ));
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'));
33 __PACKAGE__->meta->add_attribute('type_constraint' => (
34     reader    => 'type_constraint',
35     predicate => 'has_type_constraint',
36 ));
37 __PACKAGE__->meta->add_attribute('trigger' => (
38     reader    => 'trigger',
39     predicate => 'has_trigger',
40 ));
41 __PACKAGE__->meta->add_attribute('handles' => (
42     reader    => 'handles',
43     predicate => 'has_handles',
44 ));
45 __PACKAGE__->meta->add_attribute('documentation' => (
46     reader    => 'documentation',
47     predicate => 'has_documentation',
48 ));
49 __PACKAGE__->meta->add_attribute('traits' => (
50     reader    => 'applied_traits',
51     predicate => 'has_applied_traits',
52 ));
53
54 # NOTE:
55 # we need to have a ->does method in here to 
56 # more easily support traits, and the introspection 
57 # of those traits. So in order to do this we 
58 # just alias Moose::Object's version of it.
59 # - SL
60 *does = \&Moose::Object::does;
61
62 sub new {
63     my ($class, $name, %options) = @_;
64     $class->_process_options($name, \%options) unless $options{__hack_no_process_options}; # used from clone()... YECHKKK FIXME ICKY YUCK GROSS
65     return $class->SUPER::new($name, %options);
66 }
67
68 sub interpolate_class_and_new {
69     my ($class, $name, @args) = @_;
70
71     my ( $new_class, @traits ) = $class->interpolate_class(@args);
72     
73     $new_class->new($name, @args, ( scalar(@traits) ? ( traits => \@traits ) : () ) );
74 }
75
76 sub interpolate_class {
77     my ($class, %options) = @_;
78
79     $class = ref($class) || $class;
80
81     if ( my $metaclass_name = delete $options{metaclass} ) {
82         my $new_class = Moose::Util::resolve_metaclass_alias( Attribute => $metaclass_name );
83         
84         if ( $class ne $new_class ) {
85             if ( $new_class->can("interpolate_class") ) {
86                 return $new_class->interpolate_class(%options);
87             } else {
88                 $class = $new_class;
89             }
90         }
91     }
92
93     my @traits;
94
95     if (my $traits = $options{traits}) {
96         if ( @traits = grep { not $class->does($_) } map {
97             Moose::Util::resolve_metatrait_alias( Attribute => $_ )
98                 or
99             $_
100         } @$traits ) {
101             my $anon_class = Moose::Meta::Class->create_anon_class(
102                 superclasses => [ $class ],
103                 roles        => [ @traits ],
104                 cache        => 1,
105             );
106
107             $class = $anon_class->name;
108         }
109     }
110
111     return ( wantarray ? ( $class, @traits ) : $class );
112 }
113
114 sub clone_and_inherit_options {
115     my ($self, %options) = @_;
116     my %copy = %options;
117     # you can change default, required, coerce, documentation, lazy, handles, builder, type_constraint (explicitly or using isa/does), metaclass and traits
118     my %actual_options;
119     foreach my $legal_option (qw(default coerce required documentation lazy handles builder type_constraint)) {
120         if (exists $options{$legal_option}) {
121             $actual_options{$legal_option} = $options{$legal_option};
122             delete $options{$legal_option};
123         }
124     }
125
126     if ($options{isa}) {
127         my $type_constraint;
128         if (blessed($options{isa}) && $options{isa}->isa('Moose::Meta::TypeConstraint')) {
129             $type_constraint = $options{isa};
130         }
131         else {
132             $type_constraint = Moose::Util::TypeConstraints::find_or_create_isa_type_constraint($options{isa});
133             (defined $type_constraint)
134                 || confess "Could not find the type constraint '" . $options{isa} . "'";
135         }
136
137         $actual_options{type_constraint} = $type_constraint;
138         delete $options{isa};
139     }
140     
141     if ($options{does}) {
142         my $type_constraint;
143         if (blessed($options{does}) && $options{does}->isa('Moose::Meta::TypeConstraint')) {
144             $type_constraint = $options{does};
145         }
146         else {
147             $type_constraint = Moose::Util::TypeConstraints::find_or_create_does_type_constraint($options{does});
148             (defined $type_constraint)
149                 || confess "Could not find the type constraint '" . $options{does} . "'";
150         }
151
152         $actual_options{type_constraint} = $type_constraint;
153         delete $options{does};
154     }    
155
156     # NOTE:
157     # this doesn't apply to Class::MOP::Attributes, 
158     # so we can ignore it for them.
159     # - SL
160     if ($self->can('interpolate_class')) {
161         ( $actual_options{metaclass}, my @traits ) = $self->interpolate_class(%options);
162
163         my %seen;
164         my @all_traits = grep { $seen{$_}++ } @{ $self->applied_traits || [] }, @traits;
165         $actual_options{traits} = \@all_traits if @all_traits;
166
167         delete @options{qw(metaclass traits)};
168     }
169
170     (scalar keys %options == 0)
171         || confess "Illegal inherited options => (" . (join ', ' => keys %options) . ")";
172
173
174     $self->clone(%actual_options);
175 }
176
177 sub clone {
178     my ( $self, %params ) = @_;
179
180     my $class = $params{metaclass} || ref $self;
181
182     if ( 0 and $class eq ref $self ) {
183         return $self->SUPER::clone(%params);
184     } else {
185         my ( @init, @non_init );
186
187         foreach my $attr ( grep { $_->has_value($self) } $self->meta->compute_all_applicable_attributes ) {
188             push @{ $attr->has_init_arg ? \@init : \@non_init }, $attr;
189         }
190
191         my %new_params = ( ( map { $_->init_arg => $_->get_value($self) } @init ), %params );
192
193         my $name = delete $new_params{name};
194
195         my $clone = $class->new($name, %new_params, __hack_no_process_options => 1 );
196
197         foreach my $attr ( @non_init ) {
198             $attr->set_value($clone, $attr->get_value($self));
199         }
200
201
202         return $clone;
203     }
204 }
205
206 sub _process_options {
207     my ($class, $name, $options) = @_;
208
209     if (exists $options->{is}) {
210
211         ### -------------------------
212         ## is => ro, writer => _foo    # turns into (reader => foo, writer => _foo) as before
213         ## is => rw, writer => _foo    # turns into (reader => foo, writer => _foo)
214         ## is => rw, accessor => _foo  # turns into (accessor => _foo)
215         ## is => ro, accessor => _foo  # error, accesor is rw
216         ### -------------------------
217         
218         if ($options->{is} eq 'ro') {
219             confess "Cannot define an accessor name on a read-only attribute, accessors are read/write"
220                 if exists $options->{accessor};
221             $options->{reader} ||= $name;
222         }
223         elsif ($options->{is} eq 'rw') {
224             if ($options->{writer}) {
225                 $options->{reader} ||= $name;
226             }
227             else {
228                 $options->{accessor} ||= $name;
229             }
230         }
231         else {
232             confess "I do not understand this option (is => " . $options->{is} . ") on attribute $name"
233         }
234     }
235
236     if (exists $options->{isa}) {
237         if (exists $options->{does}) {
238             if (eval { $options->{isa}->can('does') }) {
239                 ($options->{isa}->does($options->{does}))
240                     || confess "Cannot have an isa option and a does option if the isa does not do the does on attribute $name";
241             }
242             else {
243                 confess "Cannot have an isa option which cannot ->does() on attribute $name";
244             }
245         }
246
247         # allow for anon-subtypes here ...
248         if (blessed($options->{isa}) && $options->{isa}->isa('Moose::Meta::TypeConstraint')) {
249             $options->{type_constraint} = $options->{isa};
250         }
251         else {
252             $options->{type_constraint} = Moose::Util::TypeConstraints::find_or_create_isa_type_constraint($options->{isa});
253         }
254     }
255     elsif (exists $options->{does}) {
256         # allow for anon-subtypes here ...
257         if (blessed($options->{does}) && $options->{does}->isa('Moose::Meta::TypeConstraint')) {
258                 $options->{type_constraint} = $options->{does};
259         }
260         else {
261             $options->{type_constraint} = Moose::Util::TypeConstraints::find_or_create_does_type_constraint($options->{does});
262         }
263     }
264
265     if (exists $options->{coerce} && $options->{coerce}) {
266         (exists $options->{type_constraint})
267             || confess "You cannot have coercion without specifying a type constraint on attribute $name";
268         confess "You cannot have a weak reference to a coerced value on attribute $name"
269             if $options->{weak_ref};
270     }
271
272     if (exists $options->{trigger}) {
273         ('CODE' eq ref $options->{trigger})
274             || confess "Trigger must be a CODE ref";
275     }
276
277     if (exists $options->{auto_deref} && $options->{auto_deref}) {
278         (exists $options->{type_constraint})
279             || confess "You cannot auto-dereference without specifying a type constraint on attribute $name";
280         ($options->{type_constraint}->is_a_type_of('ArrayRef') ||
281          $options->{type_constraint}->is_a_type_of('HashRef'))
282             || confess "You cannot auto-dereference anything other than a ArrayRef or HashRef on attribute $name";
283     }
284
285     if (exists $options->{lazy_build} && $options->{lazy_build} == 1) {
286         confess("You can not use lazy_build and default for the same attribute $name")
287             if exists $options->{default};
288         $options->{lazy}      = 1;
289         $options->{required}  = 1;
290         $options->{builder} ||= "_build_${name}";
291         if ($name =~ /^_/) {
292             $options->{clearer}   ||= "_clear${name}";
293             $options->{predicate} ||= "_has${name}";
294         } 
295         else {
296             $options->{clearer}   ||= "clear_${name}";
297             $options->{predicate} ||= "has_${name}";
298         }
299     }
300
301     if (exists $options->{lazy} && $options->{lazy}) {
302         (exists $options->{default} || defined $options->{builder} )
303             || confess "You cannot have lazy attribute ($name) without specifying a default value for it";
304     }
305
306     if ( $options->{required} && !( ( !exists $options->{init_arg} || defined $options->{init_arg} ) || exists $options->{default} || defined $options->{builder} ) ) {
307         confess "You cannot have a required attribute ($name) without a default, builder, or an init_arg";
308     }
309
310 }
311
312 sub initialize_instance_slot {
313     my ($self, $meta_instance, $instance, $params) = @_;
314     my $init_arg = $self->init_arg();
315     # try to fetch the init arg from the %params ...
316
317     my $val;
318     my $value_is_set;
319     if ( defined($init_arg) and exists $params->{$init_arg}) {
320         $val = $params->{$init_arg};
321         $value_is_set = 1;    
322     }
323     else {
324         # skip it if it's lazy
325         return if $self->is_lazy;
326         # and die if it's required and doesn't have a default value
327         confess "Attribute (" . $self->name . ") is required"
328             if $self->is_required && !$self->has_default && !$self->has_builder;
329
330         # if nothing was in the %params, we can use the
331         # attribute's default value (if it has one)
332         if ($self->has_default) {
333             $val = $self->default($instance);
334             $value_is_set = 1;
335         } 
336         elsif ($self->has_builder) {
337             if (my $builder = $instance->can($self->builder)){
338                 $val = $instance->$builder;
339                 $value_is_set = 1;
340             } 
341             else {
342                 confess(blessed($instance)." does not support builder method '".$self->builder."' for attribute '" . $self->name . "'");
343             }
344         }
345     }
346
347     return unless $value_is_set;
348
349     if ($self->has_type_constraint) {
350         my $type_constraint = $self->type_constraint;
351         if ($self->should_coerce && $type_constraint->has_coercion) {
352             $val = $type_constraint->coerce($val);
353         }
354         $type_constraint->check($val)
355             || confess "Attribute (" 
356                      . $self->name 
357                      . ") does not pass the type constraint because: " 
358                      . $type_constraint->get_message($val);
359     }
360
361     $self->set_initial_value($instance, $val);
362     $meta_instance->weaken_slot_value($instance, $self->name)
363         if ref $val && $self->is_weak_ref;
364 }
365
366 ## Slot management
367
368 # FIXME:
369 # this duplicates too much code from 
370 # Class::MOP::Attribute, we need to 
371 # refactor these bits eventually.
372 # - SL
373 sub _set_initial_slot_value {
374     my ($self, $meta_instance, $instance, $value) = @_;
375
376     my $slot_name = $self->name;
377
378     return $meta_instance->set_slot_value($instance, $slot_name, $value)
379         unless $self->has_initializer;
380
381     my ($type_constraint, $can_coerce);
382     if ($self->has_type_constraint) {
383         $type_constraint = $self->type_constraint;
384         $can_coerce      = ($self->should_coerce && $type_constraint->has_coercion);
385     }
386
387     my $callback = sub {
388         my $val = shift;
389         if ($type_constraint) {
390             $val = $type_constraint->coerce($val)
391                 if $can_coerce;
392             $type_constraint->check($val)
393                 || confess "Attribute (" 
394                          . $slot_name 
395                          . ") does not pass the type constraint because: " 
396                          . $type_constraint->get_message($val);            
397         }
398         $meta_instance->set_slot_value($instance, $slot_name, $val);
399     };
400     
401     my $initializer = $self->initializer;
402
403     # most things will just want to set a value, so make it first arg
404     $instance->$initializer($value, $callback, $self);
405 }
406
407 sub set_value {
408     my ($self, $instance, @args) = @_;
409     my $value = $args[0];
410
411     my $attr_name = $self->name;
412
413     if ($self->is_required and not @args) {
414         confess "Attribute ($attr_name) is required";
415     }
416
417     if ($self->has_type_constraint) {
418
419         my $type_constraint = $self->type_constraint;
420
421         if ($self->should_coerce) {
422             $value = $type_constraint->coerce($value);
423         }        
424         $type_constraint->_compiled_type_constraint->($value)
425             || confess "Attribute (" 
426                      . $self->name 
427                      . ") does not pass the type constraint because " 
428                      . $type_constraint->get_message($value);
429     }
430
431     my $meta_instance = Class::MOP::Class->initialize(blessed($instance))
432                                          ->get_meta_instance;
433
434     $meta_instance->set_slot_value($instance, $attr_name, $value);
435
436     if (ref $value && $self->is_weak_ref) {
437         $meta_instance->weaken_slot_value($instance, $attr_name);
438     }
439
440     if ($self->has_trigger) {
441         $self->trigger->($instance, $value, $self);
442     }
443 }
444
445 sub get_value {
446     my ($self, $instance) = @_;
447
448     if ($self->is_lazy) {
449         unless ($self->has_value($instance)) {
450             if ($self->has_default) {
451                 my $default = $self->default($instance);
452                 $self->set_initial_value($instance, $default);
453             } elsif ( $self->has_builder ) {
454                 if (my $builder = $instance->can($self->builder)){
455                     $self->set_initial_value($instance, $instance->$builder);
456                 }
457                 else {
458                     confess(blessed($instance) 
459                           . " does not support builder method '"
460                           . $self->builder 
461                           . "' for attribute '" 
462                           . $self->name 
463                           . "'");
464                 }
465             } 
466             else {
467                 $self->set_initial_value($instance, undef);
468             }
469         }
470     }
471
472     if ($self->should_auto_deref) {
473
474         my $type_constraint = $self->type_constraint;
475
476         if ($type_constraint->is_a_type_of('ArrayRef')) {
477             my $rv = $self->SUPER::get_value($instance);
478             return unless defined $rv;
479             return wantarray ? @{ $rv } : $rv;
480         }
481         elsif ($type_constraint->is_a_type_of('HashRef')) {
482             my $rv = $self->SUPER::get_value($instance);
483             return unless defined $rv;
484             return wantarray ? %{ $rv } : $rv;
485         }
486         else {
487             confess "Can not auto de-reference the type constraint '" . $type_constraint->name . "'";
488         }
489
490     }
491     else {
492
493         return $self->SUPER::get_value($instance);
494     }
495 }
496
497 ## installing accessors
498
499 sub accessor_metaclass { 'Moose::Meta::Method::Accessor' }
500
501 sub install_accessors {
502     my $self = shift;
503     $self->SUPER::install_accessors(@_);
504
505     if ($self->has_handles) {
506
507         # NOTE:
508         # Here we canonicalize the 'handles' option
509         # this will sort out any details and always
510         # return an hash of methods which we want
511         # to delagate to, see that method for details
512         my %handles = $self->_canonicalize_handles();
513
514         # find the accessor method for this attribute
515         my $accessor = $self->get_read_method_ref;
516         # then unpack it if we need too ...
517         $accessor = $accessor->body if blessed $accessor;
518
519         # install the delegation ...
520         my $associated_class = $self->associated_class;
521         foreach my $handle (keys %handles) {
522             my $method_to_call = $handles{$handle};
523             my $class_name = $associated_class->name;
524             my $name = "${class_name}::${handle}";
525
526             (!$associated_class->has_method($handle))
527                 || confess "You cannot overwrite a locally defined method ($handle) with a delegation";
528
529             # NOTE:
530             # handles is not allowed to delegate
531             # any of these methods, as they will
532             # override the ones in your class, which
533             # is almost certainly not what you want.
534
535             # FIXME warn when $handle was explicitly specified, but not if the source is a regex or something
536             #cluck("Not delegating method '$handle' because it is a core method") and
537             next if $class_name->isa("Moose::Object") and $handle =~ /^BUILD|DEMOLISH$/ || Moose::Object->can($handle);
538
539             if ('CODE' eq ref($method_to_call)) {
540                 $associated_class->add_method($handle => Class::MOP::subname($name, $method_to_call));
541             }
542             else {
543                 # NOTE:
544                 # we used to do a goto here, but the
545                 # goto didn't handle failure correctly
546                 # (it just returned nothing), so I took 
547                 # that out. However, the more I thought
548                 # about it, the less I liked it doing 
549                 # the goto, and I prefered the act of 
550                 # delegation being actually represented
551                 # in the stack trace. 
552                 # - SL
553                 $associated_class->add_method($handle => Class::MOP::subname($name, sub {
554                     my $proxy = (shift)->$accessor();
555                     (defined $proxy) 
556                         || confess "Cannot delegate $handle to $method_to_call because " . 
557                                    "the value of " . $self->name . " is not defined";
558                     $proxy->$method_to_call(@_);
559                 }));
560             }
561         }
562     }
563
564     return;
565 }
566
567 # private methods to help delegation ...
568
569 sub _canonicalize_handles {
570     my $self    = shift;
571     my $handles = $self->handles;
572     if (my $handle_type = ref($handles)) {
573         if ($handle_type eq 'HASH') {
574             return %{$handles};
575         }
576         elsif ($handle_type eq 'ARRAY') {
577             return map { $_ => $_ } @{$handles};
578         }
579         elsif ($handle_type eq 'Regexp') {
580             ($self->has_type_constraint)
581                 || confess "Cannot delegate methods based on a RegExpr without a type constraint (isa)";
582             return map  { ($_ => $_) }
583                    grep { /$handles/ } $self->_get_delegate_method_list;
584         }
585         elsif ($handle_type eq 'CODE') {
586             return $handles->($self, $self->_find_delegate_metaclass);
587         }
588         else {
589             confess "Unable to canonicalize the 'handles' option with $handles";
590         }
591     }
592     else {
593         my $role_meta = eval { $handles->meta };
594         if ($@) {
595             confess "Unable to canonicalize the 'handles' option with $handles because : $@";
596         }
597
598         (blessed $role_meta && $role_meta->isa('Moose::Meta::Role'))
599             || confess "Unable to canonicalize the 'handles' option with $handles because ->meta is not a Moose::Meta::Role";
600
601         return map { $_ => $_ } (
602             $role_meta->get_method_list,
603             $role_meta->get_required_method_list
604         );
605     }
606 }
607
608 sub _find_delegate_metaclass {
609     my $self = shift;
610     if (my $class = $self->_isa_metadata) {
611         # if the class does have
612         # a meta method, use it
613         return $class->meta if $class->can('meta');
614         # otherwise we might be
615         # dealing with a non-Moose
616         # class, and need to make
617         # our own metaclass
618         return Moose::Meta::Class->initialize($class);
619     }
620     elsif (my $role = $self->_does_metadata) {
621         # our role will always have
622         # a meta method
623         return $role->meta;
624     }
625     else {
626         confess "Cannot find delegate metaclass for attribute " . $self->name;
627     }
628 }
629
630 sub _get_delegate_method_list {
631     my $self = shift;
632     my $meta = $self->_find_delegate_metaclass;
633     if ($meta->isa('Class::MOP::Class')) {
634         return map  { $_->{name}                     }  # NOTE: !never! delegate &meta
635                grep { $_->{class} ne 'Moose::Object' && $_->{name} ne 'meta' }
636                     $meta->compute_all_applicable_methods;
637     }
638     elsif ($meta->isa('Moose::Meta::Role')) {
639         return $meta->get_method_list;
640     }
641     else {
642         confess "Unable to recognize the delegate metaclass '$meta'";
643     }
644 }
645
646 package Moose::Meta::Attribute::Custom::Moose;
647 sub register_implementation { 'Moose::Meta::Attribute' }
648
649 1;
650
651 __END__
652
653 =pod
654
655 =head1 NAME
656
657 Moose::Meta::Attribute - The Moose attribute metaclass
658
659 =head1 DESCRIPTION
660
661 This is a subclass of L<Class::MOP::Attribute> with Moose specific
662 extensions.
663
664 For the most part, the only time you will ever encounter an
665 instance of this class is if you are doing some serious deep
666 introspection. To really understand this class, you need to refer
667 to the L<Class::MOP::Attribute> documentation.
668
669 =head1 METHODS
670
671 =head2 Overridden methods
672
673 These methods override methods in L<Class::MOP::Attribute> and add
674 Moose specific features. You can safely assume though that they
675 will behave just as L<Class::MOP::Attribute> does.
676
677 =over 4
678
679 =item B<new>
680
681 =item B<clone>
682
683 =item B<does>
684
685 =item B<initialize_instance_slot>
686
687 =item B<install_accessors>
688
689 =item B<accessor_metaclass>
690
691 =item B<get_value>
692
693 =item B<set_value>
694
695   eval { $point->meta->get_attribute('x')->set_value($point, 'fourty-two') };
696   if($@) {
697     print "Oops: $@\n";
698   }
699
700 I<Attribute (x) does not pass the type constraint (Int) with 'fourty-two'>
701
702 Before setting the value, a check is made on the type constraint of
703 the attribute, if it has one, to see if the value passes it. If the
704 value fails to pass, the set operation dies with a L<Carp/confess>.
705
706 Any coercion to convert values is done before checking the type constraint.
707
708 To check a value against a type constraint before setting it, fetch the
709 attribute instance using L<Class::MOP::Class/find_attribute_by_name>,
710 fetch the type_constraint from the attribute using L<Moose::Meta::Attribute/type_constraint>
711 and call L<Moose::Meta::TypeConstraint/check>. See L<Moose::Cookbook::RecipeX>
712 for an example.
713
714 =back
715
716 =head2 Additional Moose features
717
718 Moose attributes support type-constraint checking, weak reference
719 creation and type coercion.
720
721 =over 4
722
723 =item B<interpolate_class_and_new>
724
725 =item B<interpolate_class>
726
727 When called as a class method causes interpretation of the C<metaclass> and
728 C<traits> options.
729
730 =item B<clone_and_inherit_options>
731
732 This is to support the C<has '+foo'> feature, it clones an attribute
733 from a superclass and allows a very specific set of changes to be made
734 to the attribute.
735
736 =item B<has_type_constraint>
737
738 Returns true if this meta-attribute has a type constraint.
739
740 =item B<type_constraint>
741
742 A read-only accessor for this meta-attribute's type constraint. For
743 more information on what you can do with this, see the documentation
744 for L<Moose::Meta::TypeConstraint>.
745
746 =item B<has_handles>
747
748 Returns true if this meta-attribute performs delegation.
749
750 =item B<handles>
751
752 This returns the value which was passed into the handles option.
753
754 =item B<is_weak_ref>
755
756 Returns true if this meta-attribute produces a weak reference.
757
758 =item B<is_required>
759
760 Returns true if this meta-attribute is required to have a value.
761
762 =item B<is_lazy>
763
764 Returns true if this meta-attribute should be initialized lazily.
765
766 NOTE: lazy attributes, B<must> have a C<default> or C<builder> field set.
767
768 =item B<is_lazy_build>
769
770 Returns true if this meta-attribute should be initialized lazily through
771 the builder generated by lazy_build. Using C<lazy_build =E<gt> 1> will
772 make your attribute required and lazy. In addition it will set the builder, clearer
773 and predicate options for you using the following convention.
774
775    #If your attribute name starts with an underscore:
776    has '_foo' => (lazy_build => 1);
777    #is the same as
778    has '_foo' => (lazy => 1, required => 1, predicate => '_has_foo', clearer => '_clear_foo', builder => '_build__foo);
779    # or
780    has '_foo' => (lazy => 1, required => 1, predicate => '_has_foo', clearer => '_clear_foo', default => sub{shift->_build__foo});
781
782    #If your attribute name does not start with an underscore:
783    has 'foo' => (lazy_build => 1);
784    #is the same as
785    has 'foo' => (lazy => 1, required => 1, predicate => 'has_foo', clearer => 'clear_foo', builder => '_build_foo);
786    # or
787    has 'foo' => (lazy => 1, required => 1, predicate => 'has_foo', clearer => 'clear_foo', default => sub{shift->_build_foo});
788
789 The reason for the different naming of the C<builder> is that the C<builder>
790 method is a private method while the C<clearer> and C<predicate> methods
791 are public methods.
792
793 NOTE: This means your class should provide a method whose name matches the value
794 of the builder part, in this case _build__foo or _build_foo.
795
796 =item B<should_coerce>
797
798 Returns true if this meta-attribute should perform type coercion.
799
800 =item B<should_auto_deref>
801
802 Returns true if this meta-attribute should perform automatic
803 auto-dereferencing.
804
805 NOTE: This can only be done for attributes whose type constraint is
806 either I<ArrayRef> or I<HashRef>.
807
808 =item B<has_trigger>
809
810 Returns true if this meta-attribute has a trigger set.
811
812 =item B<trigger>
813
814 This is a CODE reference which will be executed every time the
815 value of an attribute is assigned. The CODE ref will get two values,
816 the invocant and the new value. This can be used to handle I<basic>
817 bi-directional relations.
818
819 =item B<documentation>
820
821 This is a string which contains the documentation for this attribute.
822 It serves no direct purpose right now, but it might in the future
823 in some kind of automated documentation system perhaps.
824
825 =item B<has_documentation>
826
827 Returns true if this meta-attribute has any documentation.
828
829 =item B<applied_traits>
830
831 This will return the ARRAY ref of all the traits applied to this 
832 attribute, or if no traits have been applied, it returns C<undef>.
833
834 =item B<has_applied_traits>
835
836 Returns true if this meta-attribute has any traits applied.
837
838 =back
839
840 =head1 BUGS
841
842 All complex software has bugs lurking in it, and this module is no
843 exception. If you find a bug please either email me, or add the bug
844 to cpan-RT.
845
846 =head1 AUTHOR
847
848 Stevan Little E<lt>stevan@iinteractive.comE<gt>
849
850 Yuval Kogman E<lt>nothingmuch@woobling.comE<gt>
851
852 =head1 COPYRIGHT AND LICENSE
853
854 Copyright 2006-2008 by Infinity Interactive, Inc.
855
856 L<http://www.iinteractive.com>
857
858 This library is free software; you can redistribute it and/or modify
859 it under the same terms as Perl itself.
860
861 =cut