1 package MooseX::ClassAttribute::Trait::Class;
6 use MooseX::ClassAttribute::Trait::Attribute;
7 use Scalar::Util qw( blessed );
9 use namespace::autoclean;
12 with 'MooseX::ClassAttribute::Trait::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::Trait::Attribute';
93 $p{traits} = ['MooseX::ClassAttribute::Trait::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 around remove_class_attribute => sub {
117 my $removed_attr = $self->$orig(@_)
120 $removed_attr->remove_accessors();
121 $removed_attr->detach_from_class();
123 return $removed_attr;
126 sub get_all_class_attributes {
131 my $meta = Class::MOP::class_of($_);
132 $meta && $meta->can('get_class_attribute_map')
133 ? %{ $meta->get_class_attribute_map() }
136 reverse $self->linearized_isa;
138 return values %attrs;
141 sub compute_all_applicable_class_attributes {
143 'The compute_all_applicable_class_attributes method has been deprecated.'
144 . " Use get_all_class_attributes instead.\n";
146 shift->compute_all_applicable_class_attributes(@_);
149 sub find_class_attribute_by_name {
153 foreach my $class ( $self->linearized_isa() ) {
154 my $meta = Class::MOP::class_of($class)
157 return $meta->get_class_attribute($name)
158 if $meta->can('has_class_attribute')
159 && $meta->has_class_attribute($name);
165 sub _class_attribute_values_hashref {
169 return \%{ $self->_class_attribute_var_name() };
172 sub _class_attribute_var_name {
175 return $self->name() . q'::__ClassAttributeValues';
178 sub inline_class_slot_access {
184 . $self->_class_attribute_var_name . '{"'
185 . quotemeta($name) . '"}';
188 sub inline_get_class_slot_value {
192 return $self->inline_class_slot_access($name);
195 sub inline_set_class_slot_value {
198 my $val_name = shift;
200 return $self->inline_class_slot_access($name) . ' = ' . $val_name;
203 sub inline_is_class_slot_initialized {
207 return 'exists ' . $self->inline_class_slot_access($name);
210 sub inline_deinitialize_class_slot {
214 return 'delete ' . $self->inline_class_slot_access($name);
217 sub inline_weaken_class_slot_value {
222 'Scalar::Util::weaken( '
223 . $self->inline_class_slot_access($name) . ')';
234 MooseX::ClassAttribute::Trait::Class - A trait for classes with class attributes
238 for my $attr ( HasClassAttributes->meta()->get_all_class_attributes() )
245 This role adds awareness of class attributes to a metaclass object. It
246 provides a set of introspection methods that largely parallel the
247 existing attribute methods, except they operate on class attributes.
251 Every method provided by this role has an analogous method in
252 C<Class::MOP::Class> or C<Moose::Meta::Class> for regular attributes.
254 =head2 $meta->has_class_attribute($name)
256 =head2 $meta->get_class_attribute($name)
258 =head2 $meta->get_class_attribute_list()
260 These methods operate on the current metaclass only.
262 =head2 $meta->add_class_attribute(...)
264 This accepts the same options as the L<Moose::Meta::Attribute>
265 C<add_attribute()> method. However, if an attribute is specified as
266 "required" an error will be thrown.
268 =head2 $meta->remove_class_attribute($name)
270 If the named class attribute exists, it is removed from the class,
271 along with its accessor methods.
273 =head2 $meta->get_all_class_attributes()
275 This method returns a list of attribute objects for the class and all
278 =head2 $meta->find_class_attribute_by_name($name)
280 This method looks at the class and all its parent classes for the
281 named class attribute.
283 =head2 $meta->get_class_attribute_value($name)
285 =head2 $meta->set_class_attribute_value($name, $value)
287 =head2 $meta->set_class_attribute_value($name)
289 =head2 $meta->clear_class_attribute_value($name)
291 These methods operate on the storage for class attribute values, which
292 is attached to the metaclass object.
294 There's really no good reason for you to call these methods unless
295 you're doing some deep hacking. They are named as public methods
296 solely because they are used by other meta roles and classes in this
299 =head2 $meta->inline_class_slot_access($name)
301 =head2 $meta->inline_get_class_slot_value($name)
303 =head2 $meta->inline_set_class_slot_value($name, $val_name)
305 =head2 $meta->inline_is_class_slot_initialized($name)
307 =head2 $meta->inline_deinitialize_class_slot($name)
309 =head2 $meta->inline_weaken_class_slot_value($name)
311 These methods return code snippets for inlining.
313 There's really no good reason for you to call these methods unless
314 you're doing some deep hacking. They are named as public methods
315 solely because they are used by other meta roles and classes in this
320 Dave Rolsky, C<< <autarch@urth.org> >>
324 See L<MooseX::ClassAttribute> for details.
326 =head1 COPYRIGHT & LICENSE
328 Copyright 2007-2008 Dave Rolsky, All Rights Reserved.
330 This program is free software; you can redistribute it and/or modify
331 it under the same terms as Perl itself.