Commit | Line | Data |
30bf0c82 |
1 | package Class::MOP::Mixin::HasAttributes; |
b71bd1cd |
2 | |
3 | use strict; |
4 | use warnings; |
5 | |
6 | use Carp 'confess'; |
7 | use Scalar::Util 'blessed'; |
b71bd1cd |
8 | |
9 | use base 'Class::MOP::Object'; |
10 | |
11 | sub _attribute_map { $_[0]->{'attributes'} } |
12 | sub attribute_metaclass { $_[0]->{'attribute_metaclass'} } |
13 | |
14 | sub add_attribute { |
15 | my $self = shift; |
16 | |
b71bd1cd |
17 | my $attribute |
18 | = blessed( $_[0] ) ? $_[0] : $self->attribute_metaclass->new(@_); |
19 | |
b71bd1cd |
20 | ( $attribute->isa('Class::MOP::Attribute') ) |
21 | || confess |
22 | "Your attribute must be an instance of Class::MOP::Attribute (or a subclass)"; |
23 | |
8860f0f1 |
24 | $self->_attach_attribute($attribute); |
b71bd1cd |
25 | |
26 | my $attr_name = $attribute->name; |
27 | |
8860f0f1 |
28 | $self->remove_attribute($attr_name) |
29 | if $self->has_attribute($attr_name); |
30 | |
b71bd1cd |
31 | my $order = ( scalar keys %{ $self->_attribute_map } ); |
32 | $attribute->_set_insertion_order($order); |
33 | |
b71bd1cd |
34 | $self->_attribute_map->{$attr_name} = $attribute; |
35 | |
8860f0f1 |
36 | # This method is called to allow for installing accessors. Ideally, we'd |
37 | # use method overriding, but then the subclass would be responsible for |
38 | # making the attribute, which would end up with lots of code |
39 | # duplication. Even more ideally, we'd use augment/inner, but this is |
40 | # Class::MOP! |
41 | $self->_post_add_attribute($attribute) |
42 | if $self->can('_post_add_attribute'); |
b71bd1cd |
43 | |
44 | return $attribute; |
45 | } |
46 | |
47 | sub has_attribute { |
48 | my ( $self, $attribute_name ) = @_; |
49 | |
50 | ( defined $attribute_name ) |
51 | || confess "You must define an attribute name"; |
52 | |
53 | exists $self->_attribute_map->{$attribute_name}; |
54 | } |
55 | |
56 | sub get_attribute { |
57 | my ( $self, $attribute_name ) = @_; |
58 | |
59 | ( defined $attribute_name ) |
60 | || confess "You must define an attribute name"; |
61 | |
62 | return $self->_attribute_map->{$attribute_name}; |
63 | } |
64 | |
65 | sub remove_attribute { |
66 | my ( $self, $attribute_name ) = @_; |
67 | |
68 | ( defined $attribute_name ) |
69 | || confess "You must define an attribute name"; |
70 | |
71 | my $removed_attribute = $self->_attribute_map->{$attribute_name}; |
72 | return unless defined $removed_attribute; |
73 | |
74 | delete $self->_attribute_map->{$attribute_name}; |
b71bd1cd |
75 | |
76 | return $removed_attribute; |
77 | } |
78 | |
79 | sub get_attribute_list { |
80 | my $self = shift; |
81 | keys %{ $self->_attribute_map }; |
82 | } |
83 | |
b71bd1cd |
84 | 1; |