Inline all Counter methods
[gitmo/Moose.git] / lib / Moose / Meta / Attribute / Native / Trait.pm
1
2 package Moose::Meta::Attribute::Native::Trait;
3 use Moose::Role;
4 use Moose::Util::TypeConstraints;
5
6 our $VERSION   = '1.14';
7 $VERSION = eval $VERSION;
8 our $AUTHORITY = 'cpan:STEVAN';
9
10 requires '_helper_type';
11
12 before '_process_options' => sub {
13     my ( $self, $name, $options ) = @_;
14
15     $self->_check_helper_type( $options, $name );
16
17     $options->{is} = $self->_default_is
18         if !exists $options->{is} && $self->can('_default_is');
19
20     $options->{default} = $self->_default_default
21         if !exists $options->{default} && $self->can('_default_default');
22 };
23
24 sub _check_helper_type {
25     my ( $self, $options, $name ) = @_;
26
27     my $type = $self->_helper_type;
28
29     $options->{isa} = $type
30         unless exists $options->{isa};
31
32     my $isa = Moose::Util::TypeConstraints::find_or_create_type_constraint(
33         $options->{isa} );
34
35     ( $isa->is_a_type_of($type) )
36         || confess
37         "The type constraint for $name must be a subtype of $type but it's a $isa";
38 }
39
40 before 'install_accessors' => sub { (shift)->_check_handles_values };
41
42 sub _check_handles_values {
43     my $self = shift;
44
45     my $method_constructors = $self->method_constructors;
46
47     my %handles = $self->_canonicalize_handles;
48
49     for my $original_method ( values %handles ) {
50         my $name = $original_method->[0];
51
52         my $accessor_class = $self->_native_accessor_class_for($name);
53
54         # XXX - bridge code
55         ( ( $accessor_class && $accessor_class->can('new') )
56                 || exists $method_constructors->{$name} )
57             || confess "$name is an unsupported method type - $accessor_class";
58     }
59 }
60
61 around '_canonicalize_handles' => sub {
62     shift;
63     my $self    = shift;
64     my $handles = $self->handles;
65
66     return unless $handles;
67
68     unless ( 'HASH' eq ref $handles ) {
69         $self->throw_error(
70             "The 'handles' option must be a HASH reference, not $handles");
71     }
72
73     return map {
74         my $to = $handles->{$_};
75         $to = [$to] unless ref $to;
76         $_ => $to
77     } keys %$handles;
78 };
79
80 around '_make_delegation_method' => sub {
81     my $next = shift;
82     my ( $self, $handle_name, $method_to_call ) = @_;
83
84     my ( $name, @curried_args ) = @$method_to_call;
85
86     my $accessor_class = $self->_native_accessor_class_for($name);
87
88     # XXX - bridge code
89     if ( $accessor_class && $accessor_class->can('new') ) {
90         return $accessor_class->new(
91             name              => $handle_name,
92             package_name      => $self->associated_class->name,
93             attribute         => $self,
94             curried_arguments => \@curried_args,
95             root_types        => [ $self->_root_types ],
96         );
97     }
98     # XXX - bridge code
99     else {
100         my $method_constructors = $self->method_constructors;
101
102         my $code = $method_constructors->{$name}->(
103             $self,
104             $self->get_read_method_ref,
105             $self->get_write_method_ref,
106         );
107
108         return $next->(
109             $self,
110             $handle_name,
111             sub {
112                 my $instance = shift;
113                 return $code->( $instance, @curried_args, @_ );
114             }
115         );
116     }
117 };
118
119 sub _root_types {
120     return $_[0]->_helper_type;
121 }
122
123 sub _native_accessor_class_for {
124     my ( $self, $suffix ) = @_;
125
126     # XXX - bridge code
127     return unless $self->can('_native_type');
128
129     return 'Moose::Meta::Method::Accessor::Native::' . $self->_native_type . '::' . $suffix;
130 }
131
132 has 'method_constructors' => (
133     is      => 'ro',
134     isa     => 'HashRef',
135     lazy    => 1,
136     default => sub {
137         my $self = shift;
138         return +{}
139             unless $self->can('has_method_provider')
140                 && $self->has_method_provider;
141
142         # or grab them from the role/class
143         my $method_provider = $self->method_provider->meta;
144         return +{ map { $_->name => $_ }
145                 $method_provider->_get_local_methods };
146     },
147 );
148
149 no Moose::Role;
150 no Moose::Util::TypeConstraints;
151
152 1;
153
154 __END__
155
156 =head1 NAME
157
158 Moose::Meta::Attribute::Native::Trait - Base role for helpers
159
160 =head1 BUGS
161
162 See L<Moose/BUGS> for details on reporting bugs.
163
164 =head1 SEE ALSO
165
166 Documentation for Moose native traits starts at L<Moose::Meta::Attribute Native>
167
168 =head1 AUTHORS
169
170 Yuval Kogman
171
172 Shawn M Moore
173
174 Jesse Luehrs
175
176 =head1 COPYRIGHT AND LICENSE
177
178 Copyright 2007-2009 by Infinity Interactive, Inc.
179
180 L<http://www.iinteractive.com>
181
182 This library is free software; you can redistribute it and/or modify
183 it under the same terms as Perl itself.
184
185 =cut