teeny bug
[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             } elsif ( $self->has_builder ) {
456                 if (my $builder = $instance->can($self->builder)){
457                     $self->set_initial_value($instance, $instance->$builder);
458                 }
459                 else {
460                     confess(blessed($instance) 
461                           . " does not support builder method '"
462                           . $self->builder 
463                           . "' for attribute '" 
464                           . $self->name 
465                           . "'");
466                 }
467             } 
468             else {
469                 $self->set_initial_value($instance, undef);
470             }
471         }
472     }
473
474     if ($self->should_auto_deref) {
475
476         my $type_constraint = $self->type_constraint;
477
478         if ($type_constraint->is_a_type_of('ArrayRef')) {
479             my $rv = $self->SUPER::get_value($instance);
480             return unless defined $rv;
481             return wantarray ? @{ $rv } : $rv;
482         }
483         elsif ($type_constraint->is_a_type_of('HashRef')) {
484             my $rv = $self->SUPER::get_value($instance);
485             return unless defined $rv;
486             return wantarray ? %{ $rv } : $rv;
487         }
488         else {
489             confess "Can not auto de-reference the type constraint '" . $type_constraint->name . "'";
490         }
491
492     }
493     else {
494
495         return $self->SUPER::get_value($instance);
496     }
497 }
498
499 ## installing accessors
500
501 sub accessor_metaclass { 'Moose::Meta::Method::Accessor' }
502
503 sub install_accessors {
504     my $self = shift;
505     $self->SUPER::install_accessors(@_);
506
507     if ($self->has_handles) {
508
509         # NOTE:
510         # Here we canonicalize the 'handles' option
511         # this will sort out any details and always
512         # return an hash of methods which we want
513         # to delagate to, see that method for details
514         my %handles = $self->_canonicalize_handles();
515
516         # find the accessor method for this attribute
517         my $accessor = $self->get_read_method_ref;
518         # then unpack it if we need too ...
519         $accessor = $accessor->body if blessed $accessor;
520
521         # install the delegation ...
522         my $associated_class = $self->associated_class;
523         foreach my $handle (keys %handles) {
524             my $method_to_call = $handles{$handle};
525             my $class_name = $associated_class->name;
526             my $name = "${class_name}::${handle}";
527
528             (!$associated_class->has_method($handle))
529                 || confess "You cannot overwrite a locally defined method ($handle) with a delegation";
530
531             # NOTE:
532             # handles is not allowed to delegate
533             # any of these methods, as they will
534             # override the ones in your class, which
535             # is almost certainly not what you want.
536
537             # FIXME warn when $handle was explicitly specified, but not if the source is a regex or something
538             #cluck("Not delegating method '$handle' because it is a core method") and
539             next if $class_name->isa("Moose::Object") and $handle =~ /^BUILD|DEMOLISH$/ || Moose::Object->can($handle);
540
541             if ('CODE' eq ref($method_to_call)) {
542                 $associated_class->add_method($handle => Class::MOP::subname($name, $method_to_call));
543             }
544             else {
545                 # NOTE:
546                 # we used to do a goto here, but the
547                 # goto didn't handle failure correctly
548                 # (it just returned nothing), so I took 
549                 # that out. However, the more I thought
550                 # about it, the less I liked it doing 
551                 # the goto, and I prefered the act of 
552                 # delegation being actually represented
553                 # in the stack trace. 
554                 # - SL
555                 $associated_class->add_method($handle => Class::MOP::subname($name, sub {
556                     my $proxy = (shift)->$accessor();
557                     (defined $proxy) 
558                         || confess "Cannot delegate $handle to $method_to_call because " . 
559                                    "the value of " . $self->name . " is not defined";
560                     $proxy->$method_to_call(@_);
561                 }));
562             }
563         }
564     }
565
566     return;
567 }
568
569 # private methods to help delegation ...
570
571 sub _canonicalize_handles {
572     my $self    = shift;
573     my $handles = $self->handles;
574     if (my $handle_type = ref($handles)) {
575         if ($handle_type eq 'HASH') {
576             return %{$handles};
577         }
578         elsif ($handle_type eq 'ARRAY') {
579             return map { $_ => $_ } @{$handles};
580         }
581         elsif ($handle_type eq 'Regexp') {
582             ($self->has_type_constraint)
583                 || confess "Cannot delegate methods based on a RegExpr without a type constraint (isa)";
584             return map  { ($_ => $_) }
585                    grep { /$handles/ } $self->_get_delegate_method_list;
586         }
587         elsif ($handle_type eq 'CODE') {
588             return $handles->($self, $self->_find_delegate_metaclass);
589         }
590         else {
591             confess "Unable to canonicalize the 'handles' option with $handles";
592         }
593     }
594     else {
595         my $role_meta = eval { $handles->meta };
596         if ($@) {
597             confess "Unable to canonicalize the 'handles' option with $handles because : $@";
598         }
599
600         (blessed $role_meta && $role_meta->isa('Moose::Meta::Role'))
601             || confess "Unable to canonicalize the 'handles' option with $handles because ->meta is not a Moose::Meta::Role";
602
603         return map { $_ => $_ } (
604             $role_meta->get_method_list,
605             $role_meta->get_required_method_list
606         );
607     }
608 }
609
610 sub _find_delegate_metaclass {
611     my $self = shift;
612     if (my $class = $self->_isa_metadata) {
613         # if the class does have
614         # a meta method, use it
615         return $class->meta if $class->can('meta');
616         # otherwise we might be
617         # dealing with a non-Moose
618         # class, and need to make
619         # our own metaclass
620         return Moose::Meta::Class->initialize($class);
621     }
622     elsif (my $role = $self->_does_metadata) {
623         # our role will always have
624         # a meta method
625         return $role->meta;
626     }
627     else {
628         confess "Cannot find delegate metaclass for attribute " . $self->name;
629     }
630 }
631
632 sub _get_delegate_method_list {
633     my $self = shift;
634     my $meta = $self->_find_delegate_metaclass;
635     if ($meta->isa('Class::MOP::Class')) {
636         return map  { $_->{name}                     }  # NOTE: !never! delegate &meta
637                grep { $_->{class} ne 'Moose::Object' && $_->{name} ne 'meta' }
638                     $meta->compute_all_applicable_methods;
639     }
640     elsif ($meta->isa('Moose::Meta::Role')) {
641         return $meta->get_method_list;
642     }
643     else {
644         confess "Unable to recognize the delegate metaclass '$meta'";
645     }
646 }
647
648 package Moose::Meta::Attribute::Custom::Moose;
649 sub register_implementation { 'Moose::Meta::Attribute' }
650
651 1;
652
653 __END__
654
655 =pod
656
657 =head1 NAME
658
659 Moose::Meta::Attribute - The Moose attribute metaclass
660
661 =head1 DESCRIPTION
662
663 This is a subclass of L<Class::MOP::Attribute> with Moose specific
664 extensions.
665
666 For the most part, the only time you will ever encounter an
667 instance of this class is if you are doing some serious deep
668 introspection. To really understand this class, you need to refer
669 to the L<Class::MOP::Attribute> documentation.
670
671 =head1 METHODS
672
673 =head2 Overridden methods
674
675 These methods override methods in L<Class::MOP::Attribute> and add
676 Moose specific features. You can safely assume though that they
677 will behave just as L<Class::MOP::Attribute> does.
678
679 =over 4
680
681 =item B<new>
682
683 =item B<clone>
684
685 =item B<does>
686
687 =item B<initialize_instance_slot>
688
689 =item B<install_accessors>
690
691 =item B<accessor_metaclass>
692
693 =item B<get_value>
694
695 =item B<set_value>
696
697   eval { $point->meta->get_attribute('x')->set_value($point, 'fourty-two') };
698   if($@) {
699     print "Oops: $@\n";
700   }
701
702 I<Attribute (x) does not pass the type constraint (Int) with 'fourty-two'>
703
704 Before setting the value, a check is made on the type constraint of
705 the attribute, if it has one, to see if the value passes it. If the
706 value fails to pass, the set operation dies with a L<Carp/confess>.
707
708 Any coercion to convert values is done before checking the type constraint.
709
710 To check a value against a type constraint before setting it, fetch the
711 attribute instance using L<Class::MOP::Class/find_attribute_by_name>,
712 fetch the type_constraint from the attribute using L<Moose::Meta::Attribute/type_constraint>
713 and call L<Moose::Meta::TypeConstraint/check>. See L<Moose::Cookbook::RecipeX>
714 for an example.
715
716 =back
717
718 =head2 Additional Moose features
719
720 Moose attributes support type-constraint checking, weak reference
721 creation and type coercion.
722
723 =over 4
724
725 =item B<interpolate_class_and_new>
726
727 =item B<interpolate_class>
728
729 When called as a class method causes interpretation of the C<metaclass> and
730 C<traits> options.
731
732 =item B<clone_and_inherit_options>
733
734 This is to support the C<has '+foo'> feature, it clones an attribute
735 from a superclass and allows a very specific set of changes to be made
736 to the attribute.
737
738 =item B<has_type_constraint>
739
740 Returns true if this meta-attribute has a type constraint.
741
742 =item B<type_constraint>
743
744 A read-only accessor for this meta-attribute's type constraint. For
745 more information on what you can do with this, see the documentation
746 for L<Moose::Meta::TypeConstraint>.
747
748 =item B<has_handles>
749
750 Returns true if this meta-attribute performs delegation.
751
752 =item B<handles>
753
754 This returns the value which was passed into the handles option.
755
756 =item B<is_weak_ref>
757
758 Returns true if this meta-attribute produces a weak reference.
759
760 =item B<is_required>
761
762 Returns true if this meta-attribute is required to have a value.
763
764 =item B<is_lazy>
765
766 Returns true if this meta-attribute should be initialized lazily.
767
768 NOTE: lazy attributes, B<must> have a C<default> or C<builder> field set.
769
770 =item B<is_lazy_build>
771
772 Returns true if this meta-attribute should be initialized lazily through
773 the builder generated by lazy_build. Using C<lazy_build =E<gt> 1> will
774 make your attribute required and lazy. In addition it will set the builder, clearer
775 and predicate options for you using the following convention.
776
777    #If your attribute name starts with an underscore:
778    has '_foo' => (lazy_build => 1);
779    #is the same as
780    has '_foo' => (lazy => 1, required => 1, predicate => '_has_foo', clearer => '_clear_foo', builder => '_build__foo);
781    # or
782    has '_foo' => (lazy => 1, required => 1, predicate => '_has_foo', clearer => '_clear_foo', default => sub{shift->_build__foo});
783
784    #If your attribute name does not start with an underscore:
785    has 'foo' => (lazy_build => 1);
786    #is the same as
787    has 'foo' => (lazy => 1, required => 1, predicate => 'has_foo', clearer => 'clear_foo', builder => '_build_foo);
788    # or
789    has 'foo' => (lazy => 1, required => 1, predicate => 'has_foo', clearer => 'clear_foo', default => sub{shift->_build_foo});
790
791 The reason for the different naming of the C<builder> is that the C<builder>
792 method is a private method while the C<clearer> and C<predicate> methods
793 are public methods.
794
795 NOTE: This means your class should provide a method whose name matches the value
796 of the builder part, in this case _build__foo or _build_foo.
797
798 =item B<should_coerce>
799
800 Returns true if this meta-attribute should perform type coercion.
801
802 =item B<should_auto_deref>
803
804 Returns true if this meta-attribute should perform automatic
805 auto-dereferencing.
806
807 NOTE: This can only be done for attributes whose type constraint is
808 either I<ArrayRef> or I<HashRef>.
809
810 =item B<has_trigger>
811
812 Returns true if this meta-attribute has a trigger set.
813
814 =item B<trigger>
815
816 This is a CODE reference which will be executed every time the
817 value of an attribute is assigned. The CODE ref will get two values,
818 the invocant and the new value. This can be used to handle I<basic>
819 bi-directional relations.
820
821 =item B<documentation>
822
823 This is a string which contains the documentation for this attribute.
824 It serves no direct purpose right now, but it might in the future
825 in some kind of automated documentation system perhaps.
826
827 =item B<has_documentation>
828
829 Returns true if this meta-attribute has any documentation.
830
831 =item B<applied_traits>
832
833 This will return the ARRAY ref of all the traits applied to this 
834 attribute, or if no traits have been applied, it returns C<undef>.
835
836 =item B<has_applied_traits>
837
838 Returns true if this meta-attribute has any traits applied.
839
840 =back
841
842 =head1 BUGS
843
844 All complex software has bugs lurking in it, and this module is no
845 exception. If you find a bug please either email me, or add the bug
846 to cpan-RT.
847
848 =head1 AUTHOR
849
850 Stevan Little E<lt>stevan@iinteractive.comE<gt>
851
852 Yuval Kogman E<lt>nothingmuch@woobling.comE<gt>
853
854 =head1 COPYRIGHT AND LICENSE
855
856 Copyright 2006-2008 by Infinity Interactive, Inc.
857
858 L<http://www.iinteractive.com>
859
860 This library is free software; you can redistribute it and/or modify
861 it under the same terms as Perl itself.
862
863 =cut