summaryrefslogtreecommitdiff
path: root/lib/Moose/Meta/Attribute/Native/Trait.pm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Moose/Meta/Attribute/Native/Trait.pm')
-rw-r--r--lib/Moose/Meta/Attribute/Native/Trait.pm244
1 files changed, 244 insertions, 0 deletions
diff --git a/lib/Moose/Meta/Attribute/Native/Trait.pm b/lib/Moose/Meta/Attribute/Native/Trait.pm
new file mode 100644
index 0000000..d61ce06
--- /dev/null
+++ b/lib/Moose/Meta/Attribute/Native/Trait.pm
@@ -0,0 +1,244 @@
+package Moose::Meta::Attribute::Native::Trait;
+our $VERSION = '2.1405';
+
+use Moose::Role;
+use Module::Runtime 'require_module';
+use Moose::Deprecated;
+use Moose::Util 'throw_exception';
+use Moose::Util::TypeConstraints;
+
+requires '_helper_type';
+
+before '_process_options' => sub {
+ my ( $self, $name, $options ) = @_;
+
+ $self->_check_helper_type( $options, $name );
+};
+
+sub _check_helper_type {
+ my ( $self, $options, $name ) = @_;
+
+ my $type = $self->_helper_type;
+
+ $options->{isa} = $type
+ unless exists $options->{isa};
+
+ my $isa;
+ my $isa_name;
+
+ if ( blessed( $options->{isa} )
+ && $options->{isa}->can('does')
+ && $options->{isa}->does('Specio::Constraint::Role::Interface') ) {
+
+ $isa = $options->{isa};
+ require Specio::Library::Builtins;
+ return if $isa->is_a_type_of( Specio::Library::Builtins::t($type) );
+ $isa_name = $isa->name() || $isa->description();
+ }
+ else {
+ $isa = Moose::Util::TypeConstraints::find_or_create_type_constraint(
+ $options->{isa} );
+ return if $isa->is_a_type_of($type);
+ $isa_name = $isa->name();
+ }
+
+ throw_exception( WrongTypeConstraintGiven => required_type => $type,
+ given_type => $isa_name,
+ attribute_name => $name,
+ params => $options
+ );
+}
+
+before 'install_accessors' => sub { (shift)->_check_handles_values };
+
+sub _check_handles_values {
+ my $self = shift;
+
+ my %handles = $self->_canonicalize_handles;
+
+ for my $original_method ( values %handles ) {
+ my $name = $original_method->[0];
+
+ my $accessor_class = $self->_native_accessor_class_for($name);
+
+ ( $accessor_class && $accessor_class->can('new') )
+ || confess
+ "$name is an unsupported method type - $accessor_class";
+ }
+}
+
+around '_canonicalize_handles' => sub {
+ shift;
+ my $self = shift;
+ my $handles = $self->handles;
+
+ return unless $handles;
+
+ unless ( 'HASH' eq ref $handles ) {
+ throw_exception( HandlesMustBeAHashRef => instance => $self,
+ given_handles => $handles
+ );
+ }
+
+ return
+ map { $_ => $self->_canonicalize_handles_value( $handles->{$_} ) }
+ keys %$handles;
+};
+
+sub _canonicalize_handles_value {
+ my $self = shift;
+ my $value = shift;
+
+ if ( ref $value && 'ARRAY' ne ref $value ) {
+ throw_exception( InvalidHandleValue => instance => $self,
+ handle_value => $value
+ );
+ }
+
+ return ref $value ? $value : [$value];
+}
+
+around '_make_delegation_method' => sub {
+ my $next = shift;
+ my ( $self, $handle_name, $method_to_call ) = @_;
+
+ my ( $name, @curried_args ) = @$method_to_call;
+
+ my $accessor_class = $self->_native_accessor_class_for($name);
+
+ die "Cannot find an accessor class for $name"
+ unless $accessor_class && $accessor_class->can('new');
+
+ return $accessor_class->new(
+ name => $handle_name,
+ package_name => $self->associated_class->name,
+ delegate_to_method => $name,
+ attribute => $self,
+ is_inline => 1,
+ curried_arguments => \@curried_args,
+ root_types => [ $self->_root_types ],
+ );
+};
+
+sub _root_types {
+ return $_[0]->_helper_type;
+}
+
+sub _native_accessor_class_for {
+ my ( $self, $suffix ) = @_;
+
+ my $role
+ = 'Moose::Meta::Method::Accessor::Native::'
+ . $self->_native_type . '::'
+ . $suffix;
+
+ require_module($role);
+ return Moose::Meta::Class->create_anon_class(
+ superclasses =>
+ [ $self->accessor_metaclass, $self->delegation_metaclass ],
+ roles => [$role],
+ cache => 1,
+ )->name;
+}
+
+sub _build_native_type {
+ my $self = shift;
+
+ for my $role_name ( map { $_->name } $self->meta->calculate_all_roles ) {
+ return $1 if $role_name =~ /::Native::Trait::(\w+)$/;
+ }
+
+ throw_exception( CannotCalculateNativeType => instance => $self );
+}
+
+has '_native_type' => (
+ is => 'ro',
+ isa => 'Str',
+ lazy => 1,
+ builder => '_build_native_type',
+);
+
+no Moose::Role;
+no Moose::Util::TypeConstraints;
+
+1;
+
+# ABSTRACT: Shared role for native delegation traits
+
+__END__
+
+=pod
+
+=encoding UTF-8
+
+=head1 NAME
+
+Moose::Meta::Attribute::Native::Trait - Shared role for native delegation traits
+
+=head1 VERSION
+
+version 2.1405
+
+=head1 BUGS
+
+See L<Moose/BUGS> for details on reporting bugs.
+
+=head1 SEE ALSO
+
+Documentation for Moose native traits can be found in
+L<Moose::Meta::Attribute::Native>.
+
+=head1 AUTHORS
+
+=over 4
+
+=item *
+
+Stevan Little <stevan.little@iinteractive.com>
+
+=item *
+
+Dave Rolsky <autarch@urth.org>
+
+=item *
+
+Jesse Luehrs <doy@tozt.net>
+
+=item *
+
+Shawn M Moore <code@sartak.org>
+
+=item *
+
+יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
+
+=item *
+
+Karen Etheridge <ether@cpan.org>
+
+=item *
+
+Florian Ragwitz <rafl@debian.org>
+
+=item *
+
+Hans Dieter Pearcey <hdp@weftsoar.net>
+
+=item *
+
+Chris Prather <chris@prather.org>
+
+=item *
+
+Matt S Trout <mst@shadowcat.co.uk>
+
+=back
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is copyright (c) 2006 by Infinity Interactive, Inc..
+
+This is free software; you can redistribute it and/or modify it under
+the same terms as the Perl 5 programming language system itself.
+
+=cut