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