X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FMouse%2FMeta%2FRole.pm;h=ebb929fe0a7c68a51ee0b81fcdf8bca1166db943;hb=59089ec36675c7df1998945b1446c37794f88306;hp=734bebe0d9feb7693d4a1f755d7e52da95f3bfd4;hpb=ba33632ecfa5155f2bbb3b1b77e4d03c6895adb4;p=gitmo%2FMouse.git diff --git a/lib/Mouse/Meta/Role.pm b/lib/Mouse/Meta/Role.pm index 734bebe..ebb929f 100644 --- a/lib/Mouse/Meta/Role.pm +++ b/lib/Mouse/Meta/Role.pm @@ -2,6 +2,7 @@ package Mouse::Meta::Role; use strict; use warnings; +use Carp 'confess'; do { my %METACLASS_CACHE; @@ -27,33 +28,73 @@ sub new { my $class = shift; my %args = @_; - $args{attributes} ||= {}; + $args{attributes} ||= {}; + $args{required_methods} ||= []; bless \%args, $class; } sub name { $_[0]->{name} } +sub add_required_methods { + my $self = shift; + my @methods = @_; + push @{$self->{required_methods}}, @methods; +} + sub add_attribute { my $self = shift; my $name = shift; - $self->{attributes}->{$name} = [ @_ ]; + my $spec = shift; + $self->{attributes}->{$name} = $spec; } sub has_attribute { exists $_[0]->{attributes}->{$_[1]} } sub get_attribute_list { keys %{ $_[0]->{attributes} } } -sub get_attribute { $_->[0]->{attributes}->{$_[1]} } +sub get_attribute { $_[0]->{attributes}->{$_[1]} } sub apply { my $self = shift; my $class = shift; - my $pkg = $class->name; + + for my $name (@{$self->{required_methods}}) { + unless ($class->name->can($name)) { + confess "'@{[ $self->name ]}' requires the method '$name' to be implemented by '@{[ $class->name ]}'"; + } + } for my $name ($self->get_attribute_list) { + next if $class->has_attribute($name); my $spec = $self->get_attribute($name); - Mouse::Meta::Attribute->create($pkg, $name, @$spec); + Mouse::Meta::Attribute->create($class, $name, %$spec); + } + + for my $modifier_type (qw/before after around/) { + my $add_method = "add_${modifier_type}_method_modifier"; + my $modified = $self->{"${modifier_type}_method_modifiers"}; + + for my $method_name (keys %$modified) { + for my $code (@{ $modified->{$method_name} }) { + $class->$add_method($method_name => $code); + } + } } } +for my $modifier_type (qw/before after around/) { + no strict 'refs'; + *{ __PACKAGE__ . '::' . "add_${modifier_type}_method_modifier" } = sub { + my ($self, $method_name, $method) = @_; + + push @{ $self->{"${modifier_type}_method_modifiers"}->{$method_name} }, + $method; + }; + + *{ __PACKAGE__ . '::' . "get_${modifier_type}_method_modifiers" } = sub { + my ($self, $method_name, $method) = @_; + @{ $self->{"${modifier_type}_method_modifiers"}->{$method_name} || [] } + }; +} + 1;