adding-basic-role-support
[gitmo/Moose.git] / lib / Moose / Meta / Attribute.pm
CommitLineData
c0e30cf5 1
2package Moose::Meta::Attribute;
3
4use strict;
5use warnings;
6
a15dff8d 7use Scalar::Util 'weaken', 'reftype';
8use Carp 'confess';
9
5569c072 10our $VERSION = '0.02';
bc1e29b5 11
c0e30cf5 12use base 'Class::MOP::Attribute';
13
ca01a97b 14__PACKAGE__->meta->add_attribute('required' => (reader => 'is_required' ));
15__PACKAGE__->meta->add_attribute('lazy' => (reader => 'is_lazy' ));
6ba6d68c 16__PACKAGE__->meta->add_attribute('coerce' => (reader => 'should_coerce'));
17__PACKAGE__->meta->add_attribute('weak_ref' => (reader => 'is_weak_ref' ));
82168dbb 18__PACKAGE__->meta->add_attribute('type_constraint' => (
19 reader => 'type_constraint',
20 predicate => 'has_type_constraint',
21));
22
23__PACKAGE__->meta->add_before_method_modifier('new' => sub {
a15dff8d 24 my (undef, undef, %options) = @_;
4b598ea3 25 if (exists $options{coerce} && $options{coerce}) {
26 (exists $options{type_constraint})
27 || confess "You cannot have coercion without specifying a type constraint";
28 confess "You cannot have a weak reference to a coerced value"
29 if $options{weak_ref};
ca01a97b 30 }
31 if (exists $options{lazy} && $options{lazy}) {
32 (exists $options{default})
33 || confess "You cannot have lazy attribute without specifying a default value for it";
34 }
c0e30cf5 35});
36
a15dff8d 37sub generate_accessor_method {
38 my ($self, $attr_name) = @_;
ca01a97b 39 my $value_name = $self->should_coerce ? '$val' : '$_[1]';
40 my $code = 'sub { '
41 . 'if (scalar(@_) == 2) {'
42 . ($self->is_required ?
43 'defined($_[1]) || confess "Attribute ($attr_name) is required, so cannot be set to undef";'
44 : '')
45 . ($self->should_coerce ?
46 'my $val = $self->type_constraint->coercion->coerce($_[1]);'
47 : '')
48 . ($self->has_type_constraint ?
49 ('(defined $self->type_constraint->check(' . $value_name . '))'
50 . '|| confess "Attribute ($attr_name) does not pass the type contraint with \'' . $value_name . '\'"'
51 . 'if defined ' . $value_name . ';')
52 : '')
53 . '$_[0]->{$attr_name} = ' . $value_name . ';'
54 . ($self->is_weak_ref ?
55 'weaken($_[0]->{$attr_name});'
56 : '')
57 . ' }'
58 . ($self->is_lazy ?
59 '$_[0]->{$attr_name} = ($self->has_default ? $self->default($_[0]) : undef)'
60 . 'unless exists $_[0]->{$attr_name};'
61 : '')
62 . ' $_[0]->{$attr_name};'
63 . ' }';
64 my $sub = eval $code;
65 confess "Could not create writer for '$attr_name' because $@ \n code: $code" if $@;
66 return $sub;
a15dff8d 67}
68
69sub generate_writer_method {
70 my ($self, $attr_name) = @_;
ca01a97b 71 my $value_name = $self->should_coerce ? '$val' : '$_[1]';
72 my $code = 'sub { '
73 . ($self->is_required ?
74 'defined($_[1]) || confess "Attribute ($attr_name) is required, so cannot be set to undef";'
75 : '')
76 . ($self->should_coerce ?
77 'my $val = $self->type_constraint->coercion->coerce($_[1]);'
78 : '')
79 . ($self->has_type_constraint ?
80 ('(defined $self->type_constraint->check(' . $value_name . '))'
81 . '|| confess "Attribute ($attr_name) does not pass the type contraint with \'' . $value_name . '\'"'
82 . 'if defined ' . $value_name . ';')
83 : '')
84 . '$_[0]->{$attr_name} = ' . $value_name . ';'
85 . ($self->is_weak_ref ?
86 'weaken($_[0]->{$attr_name});'
87 : '')
88 . ' }';
89 my $sub = eval $code;
90 confess "Could not create writer for '$attr_name' because $@ \n code: $code" if $@;
91 return $sub;
a15dff8d 92}
c0e30cf5 93
d7f17ebb 94sub generate_reader_method {
95 my ($self, $attr_name) = @_;
ca01a97b 96 my $code = 'sub {'
97 . 'confess "Cannot assign a value to a read-only accessor" if @_ > 1;'
98 . ($self->is_lazy ?
99 '$_[0]->{$attr_name} = ($self->has_default ? $self->default($_[0]) : undef)'
100 . 'unless exists $_[0]->{$attr_name};'
101 : '')
102 . '$_[0]->{$attr_name};'
103 . '}';
104 my $sub = eval $code;
105 confess "Could not create reader for '$attr_name' because $@ \n code: $code" if $@;
106 return $sub;
d7f17ebb 107}
108
c0e30cf5 1091;
110
111__END__
112
113=pod
114
115=head1 NAME
116
6ba6d68c 117Moose::Meta::Attribute - The Moose attribute metaclass
c0e30cf5 118
119=head1 DESCRIPTION
120
e522431d 121This is a subclass of L<Class::MOP::Attribute> with Moose specific
6ba6d68c 122extensions.
123
124For the most part, the only time you will ever encounter an
125instance of this class is if you are doing some serious deep
126introspection. To really understand this class, you need to refer
127to the L<Class::MOP::Attribute> documentation.
e522431d 128
c0e30cf5 129=head1 METHODS
130
6ba6d68c 131=head2 Overridden methods
132
133These methods override methods in L<Class::MOP::Attribute> and add
134Moose specific features. You can safely assume though that they
135will behave just as L<Class::MOP::Attribute> does.
136
c0e30cf5 137=over 4
138
139=item B<new>
140
a15dff8d 141=item B<generate_accessor_method>
142
143=item B<generate_writer_method>
144
d7f17ebb 145=item B<generate_reader_method>
146
a15dff8d 147=back
148
6ba6d68c 149=head2 Additional Moose features
150
151Moose attributes support type-contstraint checking, weak reference
152creation and type coercion.
153
a15dff8d 154=over 4
155
156=item B<has_type_constraint>
157
6ba6d68c 158Returns true if this meta-attribute has a type constraint.
159
a15dff8d 160=item B<type_constraint>
161
6ba6d68c 162A read-only accessor for this meta-attribute's type constraint. For
163more information on what you can do with this, see the documentation
164for L<Moose::Meta::TypeConstraint>.
a15dff8d 165
6ba6d68c 166=item B<is_weak_ref>
a15dff8d 167
6ba6d68c 168Returns true of this meta-attribute produces a weak reference.
4b598ea3 169
ca01a97b 170=item B<is_required>
171
172Returns true of this meta-attribute is required to have a value.
173
174=item B<is_lazy>
175
176Returns true of this meta-attribute should be initialized lazily.
177
178NOTE: lazy attributes, B<must> have a C<default> field set.
179
34a66aa3 180=item B<should_coerce>
4b598ea3 181
6ba6d68c 182Returns true of this meta-attribute should perform type coercion.
183
c0e30cf5 184=back
185
186=head1 BUGS
187
188All complex software has bugs lurking in it, and this module is no
189exception. If you find a bug please either email me, or add the bug
190to cpan-RT.
191
c0e30cf5 192=head1 AUTHOR
193
194Stevan Little E<lt>stevan@iinteractive.comE<gt>
195
196=head1 COPYRIGHT AND LICENSE
197
198Copyright 2006 by Infinity Interactive, Inc.
199
200L<http://www.iinteractive.com>
201
202This library is free software; you can redistribute it and/or modify
203it under the same terms as Perl itself.
204
205=cut