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