Add CompositeRole
[gitmo/MooseX-ClassAttribute.git] / lib / MooseX / ClassAttribute / Trait / CompositeRole.pm
CommitLineData
8a44b0a6 1package MooseX::ClassAttribute::Trait::CompositeRole;
2
3use strict;
4use warnings;
5
6use Moose::Util::MetaRole;
7use Moose::Util qw(does_role);
8
9use namespace::autoclean;
10use Moose::Role;
11with 'MooseX::ClassAttribute::Trait::Role';
12
13sub _merge_class_attributes {
14 my $self = shift;
15
16 my @all_attributes;
17 foreach my $role (@{ $self->get_roles }) {
18 if (does_role($role, 'MooseX::ClassAttribute::Trait::Role')) {
19 push @all_attributes,
20 map { $role->get_class_attribute($_) }
21 $role->get_class_attribute_list;
22 }
23 }
24
25 my %seen;
26
27 foreach my $attribute (@all_attributes) {
28 my $name = $attribute->name;
29 if (exists $seen{$name}) {
30 next if $seen{$name} == $attribute;
31
32 require Moose;
33 Moose->throw_error( "Role '"
34 . $self->name()
35 . "' has encountered a class attribute conflict "
36 . "during composition. This is fatal error and cannot be disambiguated."
37 );
38 }
39 $seen{$name} = $attribute;
40 }
41 foreach my $attribute (@all_attributes) {
42 $self->add_class_attribute( $attribute->clone() );
43 }
44
45 return keys %seen;
46}
47
48around apply_params => sub {
49 my ($orig, $self, @args) = @_;
50
51 my $metarole = Moose::Util::MetaRole::apply_metaroles(
52 for => $self->$orig(@args),
53 role_metaroles => {
54 application_to_class =>
55 ['MooseX::ClassAttribute::Trait::Application::ToClass'],
56 application_to_role =>
57 ['MooseX::ClassAttribute::Trait::Application::ToRole'],
58 },
59 );
60 $metarole->_merge_class_attributes;
61 return $metarole;
62};
63
641;
65
66# ABSTRACT: A trait that supports applying multiple roles at once
67
68__END__
69
70=pod
71
72=head1 DESCRIPTION
73
74This trait is used to allow the application of multiple roles (one
75or more of which contain class attributes) to a class or role.
76
77=head1 BUGS
78
79See L<MooseX::ClassAttribute> for details.
80
81=cut