error message fixes.
[gitmo/Class-MOP.git] / lib / Class / MOP / Attribute.pm
1
2 package Class::MOP::Attribute;
3
4 use strict;
5 use warnings;
6
7 use Class::MOP::Method::Accessor;
8
9 use Carp         'confess';
10 use Scalar::Util 'blessed', 'reftype', 'weaken';
11
12 our $VERSION   = '0.17';
13 our $AUTHORITY = 'cpan:STEVAN';
14
15 use base 'Class::MOP::Object';
16
17 sub meta {
18     require Class::MOP::Class;
19     Class::MOP::Class->initialize(blessed($_[0]) || $_[0]);
20 }
21
22 # NOTE: (meta-circularity)
23 # This method will be replaced in the
24 # boostrap section of Class::MOP, by
25 # a new version which uses the
26 # &Class::MOP::Class::construct_instance
27 # method to build an attribute meta-object
28 # which itself is described with attribute
29 # meta-objects.
30 #     - Ain't meta-circularity grand? :)
31 sub new {
32     my $class   = shift;
33     my $name    = shift;
34     my %options = @_;
35
36     (defined $name && $name)
37         || confess "You must provide a name for the attribute";
38
39     $options{init_arg} = $name
40         if not exists $options{init_arg};
41     if(exists $options{builder}){
42         confess("builder must be a defined scalar value which is a method name")
43             if ref $options{builder} || !(defined $options{builder});
44         confess("Setting both default and builder is not allowed.")
45             if exists $options{default};
46     } else {
47         (is_default_a_coderef(\%options))
48             || confess("References are not allowed as default values, you must ".
49                        "wrap then in a CODE reference (ex: sub { [] } and not [])")
50                 if exists $options{default} && ref $options{default};
51     }
52     bless {
53         '$!name'      => $name,
54         '$!accessor'  => $options{accessor},
55         '$!reader'    => $options{reader},
56         '$!writer'    => $options{writer},
57         '$!predicate' => $options{predicate},
58         '$!clearer'   => $options{clearer},
59         '$!builder'   => $options{builder},
60         '$!init_arg'  => $options{init_arg},
61         '$!default'   => $options{default},
62         # keep a weakened link to the
63         # class we are associated with
64         '$!associated_class' => undef,
65         # and a list of the methods
66         # associated with this attr
67         '@!associated_methods' => [],
68     } => $class;
69 }
70
71 # NOTE:
72 # this is a primative (and kludgy) clone operation
73 # for now, it will be replaced in the Class::MOP
74 # bootstrap with a proper one, however we know
75 # that this one will work fine for now.
76 sub clone {
77     my $self    = shift;
78     my %options = @_;
79     (blessed($self))
80         || confess "Can only clone an instance";
81     return bless { %{$self}, %options } => blessed($self);
82 }
83
84 sub initialize_instance_slot {
85     my ($self, $meta_instance, $instance, $params) = @_;
86     my $init_arg = $self->{'$!init_arg'};
87     # try to fetch the init arg from the %params ...
88
89     # if nothing was in the %params, we can use the
90     # attribute's default value (if it has one)
91     if(exists $params->{$init_arg}){
92         $meta_instance->set_slot_value($instance, $self->name, $params->{$init_arg});
93     } elsif (defined $self->{'$!default'}) {
94         $meta_instance->set_slot_value($instance, $self->name, $self->default($instance));
95     } elsif (defined( my $builder = $self->{'$!builder'})) {
96         if($builder = $instance->can($builder) ){
97             $meta_instance->set_slot_value($instance, $self->name, $instance->$builder);
98         } else {
99             confess(blessed($instance)." does not support builder method '". $self->{'$!builder'} ."' for attribute '" . $self->name . "'");
100         }
101     }
102 }
103
104 # NOTE:
105 # the next bunch of methods will get bootstrapped
106 # away in the Class::MOP bootstrapping section
107
108 sub name { $_[0]->{'$!name'} }
109
110 sub associated_class   { $_[0]->{'$!associated_class'}   }
111 sub associated_methods { $_[0]->{'@!associated_methods'} }
112
113 sub has_accessor  { defined($_[0]->{'$!accessor'})  ? 1 : 0 }
114 sub has_reader    { defined($_[0]->{'$!reader'})    ? 1 : 0 }
115 sub has_writer    { defined($_[0]->{'$!writer'})    ? 1 : 0 }
116 sub has_predicate { defined($_[0]->{'$!predicate'}) ? 1 : 0 }
117 sub has_clearer   { defined($_[0]->{'$!clearer'})   ? 1 : 0 }
118 sub has_builder   { defined($_[0]->{'$!builder'})   ? 1 : 0 }
119 sub has_init_arg  { defined($_[0]->{'$!init_arg'})  ? 1 : 0 }
120 sub has_default   { defined($_[0]->{'$!default'})   ? 1 : 0 }
121
122 sub accessor  { $_[0]->{'$!accessor'}  }
123 sub reader    { $_[0]->{'$!reader'}    }
124 sub writer    { $_[0]->{'$!writer'}    }
125 sub predicate { $_[0]->{'$!predicate'} }
126 sub clearer   { $_[0]->{'$!clearer'}   }
127 sub builder   { $_[0]->{'$!builder'}   }
128 sub init_arg  { $_[0]->{'$!init_arg'}  }
129
130 # end bootstrapped away method section.
131 # (all methods below here are kept intact)
132
133 sub get_read_method  { $_[0]->reader || $_[0]->accessor }
134 sub get_write_method { $_[0]->writer || $_[0]->accessor }
135
136 sub is_default_a_coderef {
137     ('CODE' eq (reftype($_[0]->{'$!default'} || $_[0]->{default}) || ''))
138 }
139
140 sub default {
141     my ($self, $instance) = @_;
142     if (defined $instance && $self->is_default_a_coderef) {
143         # if the default is a CODE ref, then
144         # we pass in the instance and default
145         # can return a value based on that
146         # instance. Somewhat crude, but works.
147         return $self->{'$!default'}->($instance);
148     }
149     $self->{'$!default'};
150 }
151
152 # slots
153
154 sub slots { (shift)->name }
155
156 # class association
157
158 sub attach_to_class {
159     my ($self, $class) = @_;
160     (blessed($class) && $class->isa('Class::MOP::Class'))
161         || confess "You must pass a Class::MOP::Class instance (or a subclass)";
162     weaken($self->{'$!associated_class'} = $class);
163 }
164
165 sub detach_from_class {
166     my $self = shift;
167     $self->{'$!associated_class'} = undef;
168 }
169
170 # method association
171
172 sub associate_method {
173     my ($self, $method) = @_;
174     push @{$self->{'@!associated_methods'}} => $method;
175 }
176
177 ## Slot management
178
179 sub set_value {
180     my ($self, $instance, $value) = @_;
181
182     Class::MOP::Class->initialize(blessed($instance))
183                      ->get_meta_instance
184                      ->set_slot_value($instance, $self->name, $value);
185 }
186
187 sub get_value {
188     my ($self, $instance) = @_;
189
190     Class::MOP::Class->initialize(blessed($instance))
191                      ->get_meta_instance
192                      ->get_slot_value($instance, $self->name);
193 }
194
195 sub has_value {
196     my ($self, $instance) = @_;
197
198     Class::MOP::Class->initialize(blessed($instance))
199                      ->get_meta_instance
200                      ->is_slot_initialized($instance, $self->name);
201 }
202
203 sub clear_value {
204     my ($self, $instance) = @_;
205
206     Class::MOP::Class->initialize(blessed($instance))
207                      ->get_meta_instance
208                      ->deinitialize_slot($instance, $self->name);
209 }
210
211 ## load em up ...
212
213 sub accessor_metaclass { 'Class::MOP::Method::Accessor' }
214
215 sub process_accessors {
216     my ($self, $type, $accessor, $generate_as_inline_methods) = @_;
217     if (reftype($accessor)) {
218         (reftype($accessor) eq 'HASH')
219             || confess "bad accessor/reader/writer/predicate/clearer format, must be a HASH ref";
220         my ($name, $method) = %{$accessor};
221         $method = $self->accessor_metaclass->wrap($method);
222         $self->associate_method($method);
223         return ($name, $method);
224     }
225     else {
226         my $inline_me = ($generate_as_inline_methods && $self->associated_class->instance_metaclass->is_inlinable);
227         my $method;
228         eval {
229             $method = $self->accessor_metaclass->new(
230                 attribute     => $self,
231                 is_inline     => $inline_me,
232                 accessor_type => $type,
233             );
234         };
235         confess "Could not create the '$type' method for " . $self->name . " because : $@" if $@;
236         $self->associate_method($method);
237         return ($accessor, $method);
238     }
239 }
240
241 sub install_accessors {
242     my $self   = shift;
243     my $inline = shift;
244     my $class  = $self->associated_class;
245
246     $class->add_method(
247         $self->process_accessors('accessor' => $self->accessor(), $inline)
248     ) if $self->has_accessor();
249
250     $class->add_method(
251         $self->process_accessors('reader' => $self->reader(), $inline)
252     ) if $self->has_reader();
253
254     $class->add_method(
255         $self->process_accessors('writer' => $self->writer(), $inline)
256     ) if $self->has_writer();
257
258     $class->add_method(
259         $self->process_accessors('predicate' => $self->predicate(), $inline)
260     ) if $self->has_predicate();
261
262     $class->add_method(
263         $self->process_accessors('clearer' => $self->clearer(), $inline)
264     ) if $self->has_clearer();
265
266     return;
267 }
268
269 {
270     my $_remove_accessor = sub {
271         my ($accessor, $class) = @_;
272         if (reftype($accessor) && reftype($accessor) eq 'HASH') {
273             ($accessor) = keys %{$accessor};
274         }
275         my $method = $class->get_method($accessor);
276         $class->remove_method($accessor)
277             if (blessed($method) && $method->isa('Class::MOP::Method::Accessor'));
278     };
279
280     sub remove_accessors {
281         my $self = shift;
282         # TODO:
283         # we really need to make sure to remove from the
284         # associates methods here as well. But this is
285         # such a slimly used method, I am not worried
286         # about it right now.
287         $_remove_accessor->($self->accessor(),  $self->associated_class()) if $self->has_accessor();
288         $_remove_accessor->($self->reader(),    $self->associated_class()) if $self->has_reader();
289         $_remove_accessor->($self->writer(),    $self->associated_class()) if $self->has_writer();
290         $_remove_accessor->($self->predicate(), $self->associated_class()) if $self->has_predicate();
291         $_remove_accessor->($self->clearer(),   $self->associated_class()) if $self->has_clearer();
292         return;
293     }
294
295 }
296
297 1;
298
299 __END__
300
301 =pod
302
303 =head1 NAME
304
305 Class::MOP::Attribute - Attribute Meta Object
306
307 =head1 SYNOPSIS
308
309   Class::MOP::Attribute->new('$foo' => (
310       accessor  => 'foo',        # dual purpose get/set accessor
311       predicate => 'has_foo'     # predicate check for defined-ness
312       init_arg  => '-foo',       # class->new will look for a -foo key
313       default   => 'BAR IS BAZ!' # if no -foo key is provided, use this
314   ));
315
316   Class::MOP::Attribute->new('$.bar' => (
317       reader    => 'bar',        # getter
318       writer    => 'set_bar',    # setter
319       predicate => 'has_bar'     # predicate check for defined-ness
320       init_arg  => ':bar',       # class->new will look for a :bar key
321       # no default value means it is undef
322   ));
323
324 =head1 DESCRIPTION
325
326 The Attribute Protocol is almost entirely an invention of this module,
327 and is completely optional to this MOP. This is because Perl 5 does not
328 have consistent notion of what is an attribute of a class. There are
329 so many ways in which this is done, and very few (if any) are
330 easily discoverable by this module.
331
332 So, all that said, this module attempts to inject some order into this
333 chaos, by introducing a consistent API which can be used to create
334 object attributes.
335
336 =head1 METHODS
337
338 =head2 Creation
339
340 =over 4
341
342 =item B<new ($name, ?%options)>
343
344 An attribute must (at the very least), have a C<$name>. All other
345 C<%options> are contained added as key-value pairs. Acceptable keys
346 are as follows:
347
348 =over 4
349
350 =item I<init_arg>
351
352 This should be a string value representing the expected key in
353 an initialization hash. For instance, if we have an I<init_arg>
354 value of C<-foo>, then the following code will Just Work.
355
356   MyClass->meta->construct_instance(-foo => "Hello There");
357
358 In an init_arg is not assigned, it will automatically use the
359 value of C<$name>.
360
361 =item I<default>
362
363 The value of this key is the default value which
364 C<Class::MOP::Class::construct_instance> will initialize the
365 attribute to.
366
367 =item I<builder>
368
369 The value of this key is the name of the method that will be
370 called to obtain the value used to initialize the attribute.
371 This should be a method in the class associated with the attribute,
372 not a method in the attribute class itself.
373
374 B<NOTE:>
375 If the value is a simple scalar (string or number), then it can
376 be just passed as is. However, if you wish to initialize it with
377 a HASH or ARRAY ref, then you need to wrap that inside a CODE
378 reference, like so:
379
380   Class::MOP::Attribute->new('@foo' => (
381       default => sub { [] },
382   ));
383
384   # or ...
385
386   Class::MOP::Attribute->new('%foo' => (
387       default => sub { {} },
388   ));
389
390 If you wish to initialize an attribute with a CODE reference
391 itself, then you need to wrap that in a subroutine as well, like
392 so:
393
394   Class::MOP::Attribute->new('&foo' => (
395       default => sub { sub { print "Hello World" } },
396   ));
397
398 And lastly, if the value of your attribute is dependent upon
399 some other aspect of the instance structure, then you can take
400 advantage of the fact that when the I<default> value is a CODE
401 reference, it is passed the raw (unblessed) instance structure
402 as it's only argument. So you can do things like this:
403
404   Class::MOP::Attribute->new('$object_identity' => (
405       default => sub { Scalar::Util::refaddr($_[0]) },
406   ));
407
408 This last feature is fairly limited as there is no gurantee of
409 the order of attribute initializations, so you cannot perform
410 any kind of dependent initializations. However, if this is
411 something you need, you could subclass B<Class::MOP::Class> and
412 this class to acheive it. However, this is currently left as
413 an exercise to the reader :).
414
415 =back
416
417 The I<accessor>, I<reader>, I<writer>, I<predicate> and I<clearer> keys can
418 contain either; the name of the method and an appropriate default one will be
419 generated for you, B<or> a HASH ref containing exactly one key (which will be
420 used as the name of the method) and one value, which should contain a CODE
421 reference which will be installed as the method itself.
422
423 =over 4
424
425 =item I<accessor>
426
427 The I<accessor> is a standard perl-style read/write accessor. It will
428 return the value of the attribute, and if a value is passed as an argument,
429 it will assign that value to the attribute.
430
431 B<NOTE:>
432 This method will properly handle the following code, by assigning an
433 C<undef> value to the attribute.
434
435   $object->set_something(undef);
436
437 =item I<reader>
438
439 This is a basic read-only accessor, it will just return the value of
440 the attribute.
441
442 =item I<writer>
443
444 This is a basic write accessor, it accepts a single argument, and
445 assigns that value to the attribute. This method does not intentially
446 return a value, however perl will return the result of the last
447 expression in the subroutine, which returns in this returning the
448 same value that it was passed.
449
450 B<NOTE:>
451 This method will properly handle the following code, by assigning an
452 C<undef> value to the attribute.
453
454   $object->set_something();
455
456 =item I<predicate>
457
458 This is a basic test to see if the value of the attribute is not
459 C<undef>. It will return true (C<1>) if the attribute's value is
460 defined, and false (C<0>) otherwise.
461
462 =item I<clearer>
463
464 This is the a method that will uninitialize the attr, reverting lazy values
465 back to their "unfulfilled" state.
466
467 =back
468
469 =item B<clone (%options)>
470
471 =item B<initialize_instance_slot ($instance, $params)>
472
473 =back
474
475 =head2 Value management
476
477 These methods are basically "backdoors" to the instance, which can be used
478 to bypass the regular accessors, but still stay within the context of the MOP.
479
480 These methods are not for general use, and should only be used if you really
481 know what you are doing.
482
483 =over 4
484
485 =item B<set_value ($instance, $value)>
486
487 Set the value without going through the accessor. Note that this may be done to
488 even attributes with just read only accessors.
489
490 =item B<get_value ($instance)>
491
492 Return the value without going through the accessor. Note that this may be done
493 even to attributes with just write only accessors.
494
495 =item B<has_value ($instance)>
496
497 Returns a boolean indicating if the item in the C<$instance> has a value in it.
498 This is basically what the default C<predicate> method calls.
499
500 =item B<clear_value ($instance)>
501
502 This will clear the value in the C<$instance>. This is basically what the default
503 C<clearer> would call. Note that this may be done even if the attirbute does not
504 have any associated read, write or clear methods.
505
506 =back
507
508 =head2 Informational
509
510 These are all basic read-only value accessors for the values
511 passed into C<new>. I think they are pretty much self-explanitory.
512
513 =over 4
514
515 =item B<name>
516
517 =item B<accessor>
518
519 =item B<reader>
520
521 =item B<writer>
522
523 =item B<predicate>
524
525 =item B<clearer>
526
527 =item B<init_arg>
528
529 =item B<is_default_a_coderef>
530
531 =item B<default (?$instance)>
532
533 As noted in the documentation for C<new> above, if the I<default>
534 value is a CODE reference, this accessor will pass a single additional
535 argument C<$instance> into it and return the value.
536
537 =item B<slots>
538
539 Returns a list of slots required by the attribute. This is usually
540 just one, which is the name of the attribute.
541
542 =item B<get_read_method>
543
544 =item B<get_write_method>
545
546 Return the name of a method suitable for reading / writing the value of the
547 attribute in the associated class. Suitable for use whether C<reader> and
548 C<writer> or C<accessor> was used.
549
550 =back
551
552 =head2 Informational predicates
553
554 These are all basic predicate methods for the values passed into C<new>.
555
556 =over 4
557
558 =item B<has_accessor>
559
560 =item B<has_reader>
561
562 =item B<has_writer>
563
564 =item B<has_predicate>
565
566 =item B<has_clearer>
567
568 =item B<has_init_arg>
569
570 =item B<has_default>
571
572 =back
573
574 =head2 Class association
575
576 These methods allow you to manage the attributes association with
577 the class that contains it. These methods should not be used
578 lightly, nor are they very magical, they are mostly used internally
579 and by metaclass instances.
580
581 =over 4
582
583 =item B<associated_class>
584
585 This returns the metaclass this attribute is associated with.
586
587 =item B<attach_to_class ($class)>
588
589 This will store a weaken reference to C<$class> internally. You should
590 note that just changing the class assocation will not remove the attribute
591 from it's old class, and initialize it (and it's accessors) in the new
592 C<$class>. It is up to you to do this manually.
593
594 =item B<detach_from_class>
595
596 This will remove the weakened reference to the class. It does B<not>
597 remove the attribute itself from the class (or remove it's accessors),
598 you must do that yourself if you want too. Actually if that is what
599 you want to do, you should probably be looking at
600 L<Class::MOP::Class::remove_attribute> instead.
601
602 =back
603
604 =head2 Attribute Accessor generation
605
606 =over 4
607
608 =item B<accessor_metaclass>
609
610 Accessors are generated by an accessor metaclass, which is usually
611 a subclass of C<Class::MOP::Method::Accessor>. This method returns
612 the name of the accessor metaclass that this attribute uses.
613
614 =item B<associate_method ($method)>
615
616 This will associate a C<$method> with the given attribute which is
617 used internally by the accessor generator.
618
619 =item B<associated_methods>
620
621 This will return the list of methods which have been associated with
622 the C<associate_method> methods.
623
624 =item B<install_accessors>
625
626 This allows the attribute to generate and install code for it's own
627 I<accessor/reader/writer/predicate> methods. This is called by
628 C<Class::MOP::Class::add_attribute>.
629
630 This method will call C<process_accessors> for each of the possible
631 method types (accessor, reader, writer & predicate).
632
633 =item B<process_accessors ($type, $value)>
634
635 This takes a C<$type> (accessor, reader, writer or predicate), and
636 a C<$value> (the value passed into the constructor for each of the
637 different types). It will then either generate the method itself
638 (using the C<generate_*_method> methods listed below) or it will
639 use the custom method passed through the constructor.
640
641 =item B<remove_accessors>
642
643 This allows the attribute to remove the method for it's own
644 I<accessor/reader/writer/predicate/clearer>. This is called by
645 C<Class::MOP::Class::remove_attribute>.
646
647 NOTE: This does not currently remove methods from the list returned
648 by C<associated_methods>, that is on the TODO list.
649
650 =back
651
652 =head2 Introspection
653
654 =over 4
655
656 =item B<meta>
657
658 This will return a B<Class::MOP::Class> instance which is related
659 to this class.
660
661 It should also be noted that B<Class::MOP> will actually bootstrap
662 this module by installing a number of attribute meta-objects into
663 it's metaclass. This will allow this class to reap all the benifits
664 of the MOP when subclassing it.
665
666 =back
667
668 =head1 AUTHORS
669
670 Stevan Little E<lt>stevan@iinteractive.comE<gt>
671
672 =head1 COPYRIGHT AND LICENSE
673
674 Copyright 2006, 2007 by Infinity Interactive, Inc.
675
676 L<http://www.iinteractive.com>
677
678 This library is free software; you can redistribute it and/or modify
679 it under the same terms as Perl itself.
680
681 =cut
682
683