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