1 package MooseX::ClassAttribute::Role::Meta::Class;
6 use MooseX::ClassAttribute::Role::Meta::Attribute;
7 use Scalar::Util qw( blessed );
9 use namespace::autoclean;
12 with 'MooseX::ClassAttribute::Role::Meta::Mixin::HasClassAttributes';
14 has _class_attribute_values => (
19 'get_class_attribute_value' => 'get',
20 'set_class_attribute_value' => 'set',
21 'has_class_attribute_value' => 'exists',
22 'clear_class_attribute_value' => 'delete',
25 default => sub { $_[0]->_class_attribute_values_hashref() },
29 around add_class_attribute => sub {
33 blessed $_[0] && $_[0]->isa('Class::MOP::Attribute')
35 : $self->_process_class_attribute(@_)
43 sub _post_add_class_attribute {
47 my $name = $attr->name();
51 eval { $attr->install_accessors() };
56 $self->remove_attribute($name);
61 sub _attach_class_attribute {
62 my ($self, $attribute) = @_;
63 $attribute->attach_to_class($self);
66 # It'd be nice if I didn't have to replicate this for class
67 # attributes, since it's basically just a copy of
68 # Moose::Meta::Class->_process_attribute
69 sub _process_class_attribute {
74 @args = %{ $args[0] } if scalar @args == 1 && ref( $args[0] ) eq 'HASH';
76 if ( $name =~ /^\+(.*)/ ) {
77 return $self->_process_inherited_class_attribute( $1, @args );
80 return $self->_process_new_class_attribute( $name, @args );
84 sub _process_new_class_attribute {
90 push @{ $p{traits} }, 'MooseX::ClassAttribute::Role::Meta::Attribute';
93 $p{traits} = ['MooseX::ClassAttribute::Role::Meta::Attribute'];
96 return Moose::Meta::Attribute->interpolate_class_and_new( $name, %p );
99 sub _process_inherited_class_attribute {
104 my $inherited_attr = $self->find_class_attribute_by_name($name);
106 ( defined $inherited_attr )
108 "Could not find an attribute by the name of '$name' to inherit from";
110 return $inherited_attr->clone_and_inherit_options(%p);
113 sub remove_class_attribute {
117 ( defined $name && $name )
118 || confess 'You must provide an attribute name';
120 my $removed_attr = $self->get_class_attribute($name);
121 return unless $removed_attr;
123 $self->_remove_class_attribute($name);
125 $removed_attr->remove_accessors();
126 $removed_attr->detach_from_class();
128 return $removed_attr;
131 sub get_all_class_attributes {
136 my $meta = Class::MOP::class_of($_);
137 $meta && $meta->can('get_class_attribute_map')
138 ? %{ $meta->get_class_attribute_map() }
141 reverse $self->linearized_isa;
143 return values %attrs;
146 sub compute_all_applicable_class_attributes {
148 'The compute_all_applicable_class_attributes method has been deprecated.'
149 . " Use get_all_class_attributes instead.\n";
151 shift->compute_all_applicable_class_attributes(@_);
154 sub find_class_attribute_by_name {
158 foreach my $class ( $self->linearized_isa() ) {
159 my $meta = Class::MOP::class_of($class)
162 return $meta->get_class_attribute($name)
163 if $meta->can('has_class_attribute')
164 && $meta->has_class_attribute($name);
170 sub _class_attribute_values_hashref {
174 return \%{ $self->_class_attribute_var_name() };
177 sub _class_attribute_var_name {
180 return $self->name() . q'::__ClassAttributeValues';
183 sub inline_class_slot_access {
189 . $self->_class_attribute_var_name . '{"'
190 . quotemeta($name) . '"}';
193 sub inline_get_class_slot_value {
197 return $self->inline_class_slot_access($name);
200 sub inline_set_class_slot_value {
203 my $val_name = shift;
205 return $self->inline_class_slot_access($name) . ' = ' . $val_name;
208 sub inline_is_class_slot_initialized {
212 return 'exists ' . $self->inline_class_slot_access($name);
215 sub inline_deinitialize_class_slot {
219 return 'delete ' . $self->inline_class_slot_access($name);
222 sub inline_weaken_class_slot_value {
227 'Scalar::Util::weaken( '
228 . $self->inline_class_slot_access($name) . ')';
239 MooseX::ClassAttribute::Role::Meta::Class - A metaclass role for classes with class attributes
243 for my $attr ( HasClassAttributes->meta()->get_all_class_attributes() )
250 This role adds awareness of class attributes to a metaclass object. It
251 provides a set of introspection methods that largely parallel the
252 existing attribute methods, except they operate on class attributes.
256 Every method provided by this role has an analogous method in
257 C<Class::MOP::Class> or C<Moose::Meta::Class> for regular attributes.
259 =head2 $meta->has_class_attribute($name)
261 =head2 $meta->get_class_attribute($name)
263 =head2 $meta->get_class_attribute_list()
265 =head2 $meta->get_class_attribute_map()
267 These methods operate on the current metaclass only.
269 =head2 $meta->add_class_attribute(...)
271 This accepts the same options as the L<Moose::Meta::Attribute>
272 C<add_attribute()> method. However, if an attribute is specified as
273 "required" an error will be thrown.
275 =head2 $meta->remove_class_attribute($name)
277 If the named class attribute exists, it is removed from the class,
278 along with its accessor methods.
280 =head2 $meta->get_all_class_attributes()
282 This method returns a list of attribute objects for the class and all
285 =head2 $meta->find_class_attribute_by_name($name)
287 This method looks at the class and all its parent classes for the
288 named class attribute.
290 =head2 $meta->get_class_attribute_value($name)
292 =head2 $meta->set_class_attribute_value($name, $value)
294 =head2 $meta->set_class_attribute_value($name)
296 =head2 $meta->clear_class_attribute_value($name)
298 These methods operate on the storage for class attribute values, which
299 is attached to the metaclass object.
301 There's really no good reason for you to call these methods unless
302 you're doing some deep hacking. They are named as public methods
303 solely because they are used by other meta roles and classes in this
306 =head2 inline_class_slot_access($name)
308 =head2 inline_get_class_slot_value($name)
310 =head2 inline_set_class_slot_value($name, $val_name)
312 =head2 inline_is_class_slot_initialized($name)
314 =head2 inline_deinitialize_class_slot($name)
316 =head2 inline_weaken_class_slot_value($name)
318 These methods return code snippets for inlining.
320 There's really no good reason for you to call these methods unless
321 you're doing some deep hacking. They are named as public methods
322 solely because they are used by other meta roles and classes in this
327 Dave Rolsky, C<< <autarch@urth.org> >>
331 See L<MooseX::ClassAttribute> for details.
333 =head1 COPYRIGHT & LICENSE
335 Copyright 2007-2008 Dave Rolsky, All Rights Reserved.
337 This program is free software; you can redistribute it and/or modify
338 it under the same terms as Perl itself.