File Coverage

blib/lib/Reflex/Role.pm
Criterion Covered Total %
statement 22 24 91.6
branch 2 6 33.3
condition 2 6 33.3
subroutine 7 8 87.5
pod 2 3 66.6
total 35 47 74.4


line stmt bran cond sub pod time code
1             package Reflex::Role;
2             # vim: ts=2 sw=2 noexpandtab
3             $Reflex::Role::VERSION = '0.100';
4 7     7   27 use Moose::Role;
  7         9  
  7         58  
5 7     7   30119 use MooseX::Role::Parameterized;
  7         333945  
  7         29  
6 7     7   167945 use Moose::Exporter;
  7         12  
  7         34  
7              
8             # TODO - All role-based method definition goes through here, as do
9             # callback parameters. We have an opportunity to validate that
10             # the defined callbacks and methods are sane, if Moose doesn't already
11             # do this for us!
12              
13             Moose::Exporter->setup_import_methods(
14             with_caller => [ qw(
15             attribute_parameter method_parameter callback_parameter
16             ) ],
17             also => 'MooseX::Role::Parameterized',
18             # TODO - Work around a known issue in Moose::Exporter
19             # where the meta_lookup isn't propegated properly
20             meta_lookup => sub { MooseX::Role::Parameterized::current_metaclass || Class::MOP::class_of(shift) },
21             );
22              
23              
24             # TODO - Work around a known issue in Moose::Exporter, which may be
25             # https://rt.cpan.org/Public/Bug/Display.html?id=51561
26              
27             sub init_meta {
28 7     7 0 436 my $self = shift;
29 7         22 return MooseX::Role::Parameterized->init_meta(@_);
30             }
31              
32              
33             sub attribute_parameter {
34 20     20 1 89 my $caller = shift();
35              
36 20 50 33     75 confess "'attribute_parameter' may not be used inside of the role block"
37             if (
38             MooseX::Role::Parameterized::current_metaclass() and
39             MooseX::Role::Parameterized::current_metaclass()->genitor->name eq $caller
40             );
41              
42 20         125 my $meta = Class::MOP::class_of($caller);
43              
44 20         128 my ($name, $default) = @_;
45              
46 20         112 $meta->add_parameter(
47             $name, (
48             is => 'rw',
49             isa => 'Str',
50             default => $default
51             )
52             );
53             }
54              
55             sub method_parameter {
56 29     29 1 116 my $caller = shift;
57              
58 29 50 33     85 confess "'method_parameter' may not be used inside of the role block"
59             if (
60             MooseX::Role::Parameterized::current_metaclass() and
61             MooseX::Role::Parameterized::current_metaclass()->genitor->name eq $caller
62             );
63              
64 29         176 my $meta = Class::MOP::class_of($caller);
65              
66 29         185 my ($name, $prefix, $member, $suffix) = @_;
67              
68             # TODO - $member must have been declared as an attribute_parameter.
69              
70             $meta->add_parameter(
71             $name,
72             (
73             is => 'rw',
74             isa => 'Str',
75             lazy => 1,
76             default => sub {
77             join(
78             "_",
79 0 0   0     grep { defined() and $_ ne "_" }
  0            
80             $prefix, shift()->$member(), $suffix
81             )
82             },
83             )
84 29         249 );
85             }
86              
87             # Nearly identical to method_parameter() except it also requires the
88             # callback method.
89              
90             sub callback_parameter {
91             my $caller = shift;
92              
93             confess "'method_parameter' may not be used inside of the role block"
94             if (
95             MooseX::Role::Parameterized::current_metaclass() and
96             MooseX::Role::Parameterized::current_metaclass()->genitor->name eq $caller
97             );
98              
99             my $meta = Class::MOP::class_of($caller);
100              
101             my ($name, $prefix, $member, $suffix) = @_;
102              
103             # TODO - $member must have been declared as an attribute_parameter.
104              
105             $meta->add_parameter(
106             $name,
107             (
108             is => 'rw',
109             isa => 'Str',
110             lazy => 1,
111             default => sub {
112             join(
113             "_",
114             grep { defined() and $_ ne "_" }
115             $prefix, shift()->$member(), $suffix
116             )
117             },
118             )
119             );
120             }
121              
122 7     7   3338 BEGIN { *callback_parameter = *method_parameter; }
123              
124             1;
125              
126             __END__
127              
128             =pod
129              
130             =encoding UTF-8
131              
132             =for :stopwords Rocco Caputo
133              
134             =head1 NAME
135              
136             Reflex::Role - define a Reflex paramaterized role
137              
138             =head1 VERSION
139              
140             This document describes version 0.100, released on April 02, 2017.
141              
142             =head1 SYNOPSIS
143              
144             TODO - Changed again;
145              
146             package Reflex::Role::Streaming;
147             use Reflex::Role;
148              
149             use Scalar::Util qw(weaken);
150              
151             attribute_parameter handle => "handle";
152             callback_parameter cb_data => qw( on handle data );
153             callback_parameter cb_error => qw( on handle error );
154             callback_parameter cb_closed => qw( on handle closed );
155             method_parameter method_put => qw( put handle _ );
156             method_parameter method_stop => qw( stop handle _ );
157              
158             role {
159             my $p = shift;
160              
161             my $h = $p->handle();
162             my $cb_error = $p->cb_error();
163              
164             with 'Reflex::Role::Collectible';
165              
166             method-emit_and_stop $cb_error => $p->ev_error();
167              
168             with 'Reflex::Role::Reading' => {
169             handle => $h,
170             cb_data => $p->cb_data(),
171             cb_error => $cb_error,
172             cb_closed => $p->cb_closed(),
173             };
174              
175             with 'Reflex::Role::Readable' => {
176             handle => $h,
177             active => 1,
178             };
179              
180             with 'Reflex::Role::Writing' => {
181             handle => $h,
182             cb_error => $cb_error,
183             method_put => $p->method_put(),
184             };
185              
186             with 'Reflex::Role::Writable' => {
187             handle => $h,
188             };
189              
190             # Multiplex a single stop() to the sub-roles.
191             method $p->method_stop() => sub {
192             my $self = shift;
193             $self->stop_handle_readable();
194             $self->stop_handle_writable();
195             };
196             };
197              
198             1;
199              
200             =head1 DESCRIPTION
201              
202             Reflex::Role defines a class as a Reflex parameterized role. It adds
203             a few Reflex-specific exports to MooseX::Role::Parameterized.
204              
205             It will be very helpful to understand the MooseX::Role::Parameterized
206             declarations C<parameter>, C<role> and C<method> before continuing. A
207             basic familiarity with Moose::Role is also assumed.
208              
209             =head2 ROLE PARAMETER DECLARATIONS
210              
211             Reflex::Role adds a few declarations to MooseX::Role::Parameterized.
212             The role parameter declarations define new parameters for Reflex
213             roles. They're shorthands for MooseX::Role::Parameterized
214             C<parameter> declarations.
215              
216             =head3 attribute_parameter
217              
218             Synopsis:
219              
220             attribute_parameter attribute_name => "default_name";
221              
222             C<attribute_parameter> declares a role parameter that will accept an
223             attribute name from the consumer. It also specifies a default
224             attribute name.
225              
226             C<attribute_parameter> is a convenience declaration. The synopsis
227             declaration is equivalent to this MooseX::Role::Parameterized syntax
228              
229             parameter attribute_name => (
230             isa => 'Str',
231             default => $default,
232             );
233              
234             =head3 callback_parameter
235              
236             Synopsis:
237              
238             callback_parameter callback_name => qw( prefix attribute_param suffix);
239              
240             C<callback_parameter> declares a role parameter that will accept a
241             callback method name. It alsp specifies a default method name, which
242             is the catenation of a prefix, the value of an attribute parameter,
243             and a suffix. A prefix or suffix of "_" will cause that segment of
244             the default to be ignored.
245              
246             C<callback_parameter> is a convenience declaration. The synopsis is
247             equivalent to this MooseX::Role::Parameterized syntax:
248              
249             parameter callback_name => (
250             isa => 'Str',
251             lazy => 1,
252             default => sub {
253             join(
254             "_",
255             grep { defined() and $_ ne "_" }
256             $prefix, shift()->$attribute_param(), $suffix
257             )
258             },
259             );
260              
261             =head3 method_parameter
262              
263             Synopsis:
264              
265             method_parameter method_name => qw( prefix attribute_param suffix );
266              
267             C<method_parameter> declares a role parameter that will accept a
268             method name from the consumer. It also specifies a default method
269             name, which is the catenation of a prefix, the value of an attribute
270             parameter, and a suffix. A prefix or suffix of "_" will cause that
271             segment of the default to be ignored.
272              
273             C<method_parameter> is a convenience declaration. The synopsis is
274             equivalent to this MooseX::Role::Parameterized syntax:
275              
276             parameter method_name => (
277             isa => 'Str',
278             lazy => 1,
279             default => sub {
280             join(
281             "_",
282             grep { defined() and $_ ne "_" }
283             $prefix, shift()->$attribute_param(), $suffix
284             )
285             },
286             );
287              
288             =for Pod::Coverage init_meta
289              
290             =head1 TODO
291              
292             I'm looking for better names for Reflex::Role's exported declarations.
293             Please suggest some.
294              
295             =head1 EXAMPLES
296              
297             Nearly everything in the Reflex::Role namespace.
298              
299             =head1 SEE ALSO
300              
301             Please see those modules/websites for more information related to this module.
302              
303             =over 4
304              
305             =item *
306              
307             L<Reflex|Reflex>
308              
309             =item *
310              
311             L<Reflex>
312              
313             =item *
314              
315             L<Moose>
316              
317             =item *
318              
319             L<MooseX::Role::Parameterized>
320              
321             =item *
322              
323             L<All the Reflex roles.|All the Reflex roles.>
324              
325             =item *
326              
327             L<Reflex/ACKNOWLEDGEMENTS>
328              
329             =item *
330              
331             L<Reflex/ASSISTANCE>
332              
333             =item *
334              
335             L<Reflex/AUTHORS>
336              
337             =item *
338              
339             L<Reflex/BUGS>
340              
341             =item *
342              
343             L<Reflex/BUGS>
344              
345             =item *
346              
347             L<Reflex/CONTRIBUTORS>
348              
349             =item *
350              
351             L<Reflex/COPYRIGHT>
352              
353             =item *
354              
355             L<Reflex/LICENSE>
356              
357             =item *
358              
359             L<Reflex/TODO>
360              
361             =back
362              
363             =head1 BUGS AND LIMITATIONS
364              
365             You can make new bug reports, and view existing ones, through the
366             web interface at L<http://rt.cpan.org/Public/Dist/Display.html?Name=Reflex>.
367              
368             =head1 AUTHOR
369              
370             Rocco Caputo <rcaputo@cpan.org>
371              
372             =head1 COPYRIGHT AND LICENSE
373              
374             This software is copyright (c) 2017 by Rocco Caputo.
375              
376             This is free software; you can redistribute it and/or modify it under
377             the same terms as the Perl 5 programming language system itself.
378              
379             =head1 AVAILABILITY
380              
381             The latest version of this module is available from the Comprehensive Perl
382             Archive Network (CPAN). Visit L<http://www.perl.com/CPAN/> to find a CPAN
383             site near you, or see L<https://metacpan.org/module/Reflex/>.
384              
385             =head1 DISCLAIMER OF WARRANTY
386              
387             BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
388             FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT
389             WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER
390             PARTIES PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND,
391             EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
392             IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
393             PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
394             SOFTWARE IS WITH YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME
395             THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION.
396              
397             IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
398             WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
399             REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE LIABLE
400             TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL, OR
401             CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
402             SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
403             RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
404             FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
405             SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
406             DAMAGES.
407              
408             =cut