File Coverage

blib/lib/Clustericious/Client/Meta/Route.pm
Criterion Covered Total %
statement 108 112 96.4
branch 47 60 78.3
condition 9 16 56.2
subroutine 14 14 100.0
pod 5 5 100.0
total 183 207 88.4


line stmt bran cond sub pod time code
1             package Clustericious::Client::Meta::Route;
2              
3 27     27   7672 use strict;
  27         59  
  27         715  
4 27     27   137 use warnings;
  27         56  
  27         750  
5 27     27   135 use YAML::XS qw/LoadFile/;
  27         52  
  27         1365  
6 27     27   2549 use DateTime::Format::DateParse;
  27         10506823  
  27         1075  
7 27     27   230 use Getopt::Long qw/GetOptionsFromArray/;
  27         115  
  27         263  
8 27     27   3881 use Mojo::Base qw/-base/;
  27         63  
  27         293  
9 27     27   4825 use Data::Dumper;
  27         64  
  27         1265  
10 27     27   1587 use Clustericious::Log;
  27         65  
  27         260  
11 27     27   20887 use Clustericious::Client::Meta;
  27         64  
  27         31825  
12              
13             # ABSTRACT: metadata about a route'
14             our $VERSION = '1.27'; # VERSION
15              
16              
17             has 'client_class';
18             has 'route_name';
19              
20              
21             sub set {
22 49     49 1 83 my $self = shift;
23 49         130 return Clustericious::Client::Meta->add_route_attribute(
24             $self->client_class, $self->route_name, @_ );
25             }
26              
27              
28             sub get {
29 49     49 1 96 my $self = shift;
30 49         114 return Clustericious::Client::Meta->get_route_attribute(
31             $self->client_class, $self->route_name, @_ );
32             }
33              
34              
35             sub doc {
36 2     2 1 20 my $self = shift;
37 2         7 return Clustericious::Client::Meta->get_route_doc(
38             $self->client_class, $self->route_name, @_
39             );
40             }
41              
42              
43             sub set_doc {
44 17     17 1 155 my $self = shift;
45 17         48 return Clustericious::Client::Meta->add_route(
46             $self->client_class, $self->route_name, @_
47             );
48             }
49              
50              
51             sub process_args {
52 17     17 1 157 my $meta = shift;
53 17         40 my @args = @_;
54 17         25 my $cli;
55 17 50 66     62 if (ref $args[0] eq 'HASH' && $args[0]{command_line}) {
56 5         8 $cli = 1;
57 5         8 shift @args;
58             }
59 17 100       40 my $route_args = $meta->get('args') or return @args;
60 14 100       31 unless ($cli) {
61             # method call, modify @args so that getopt will work.
62             # Prepend a "--" for named params.
63 9         14 my %valid;
64 9         20 for (@$route_args) {
65 29 100       63 next if $_->{positional};
66 17         37 my @name = ( $_->{name} );
67 17 100       31 if ($_->{alt}) {
68 2         9 push @name, split '\|', $_->{alt};
69             }
70 17         26 my $type = $_->{type};
71 17         51 $valid{$_} = $type for @name;
72             }
73 9         13 my @new;
74 9         23 while (my $in = shift @args) {
75 25 100       43 if (exists($valid{$in})) {
76 11         30 push @new, "--$in";
77 11 50 33     71 push @new, shift @args if @args && defined($valid{$in}) && length($valid{$in});
      33        
78             } else {
79 14         32 push @new, $in;
80             }
81             }
82              
83 9         30 @args = @new;
84             }
85              
86 14 100       28 my %req = map { $_->{required} ? ($_->{name} => 1):() } @$route_args;
  48         96  
87             my @getopt = map {
88 14         21 $_->{name}
89             .($_->{alt} ? "|$_->{alt}" : "")
90 48 100 100     154 .($_->{type} || '')
91             } @$route_args;
92              
93             my $doc = join "\n", "Valid options for '".$meta->route_name."' are :",
94             map {
95 14 100 100     35 sprintf(' --%-20s%-15s%s', $_->{name}, $_->{required} ? 'required' : '', $_->{doc} || "" )
  48         265  
96             } @$route_args;
97              
98 14         28 my %method_args;
99 14         52 Getopt::Long::Configure(qw/pass_through/); # TODO use OO interface
100 14 50       382 GetOptionsFromArray(\@args, \%method_args, @getopt) or LOGDIE "Invalid options. $doc\n";
101              
102             # Check for positional args
103 14         5419 for (@$route_args) {
104 48 100       97 next unless @args;
105 20 100       46 my $spec = $_->{positional} or next;
106 12         20 my $name = $_->{name};
107 12         25 for ($spec) {
108 12 100       30 /one/ and do {
109 11         27 $method_args{$name} = shift @args;
110 11         27 next;
111             };
112 1 50       6 /many/ and do {
113 1         4 push @{ $method_args{$name} }, shift @args while @args;
  3         13  
114 1         4 next;
115             };
116 0         0 die "unknown positional spec : $spec";
117             }
118             }
119              
120             # Check for required args
121 14         24 for (@$route_args) {
122 41         60 my $name = $_->{name};
123 41 100       82 next unless $_->{required};
124 7 100       13 next if exists($method_args{$name});
125 2         12 LOGDIE "Missing value for required argument '$name'\n$doc\n";
126             }
127              
128 12 50       29 LOGDIE "Unknown option : @args\n$doc\n" if @args;
129              
130             # Check for preprocessing of args
131 12         22 for (@$route_args) {
132 38         47 my $name = $_->{name};
133 38 100       98 next unless $_->{preprocess};
134 4 50       28 LOGDIE "internal error: cannot handle $_->{preprocess}" unless $_->{preprocess} =~ /yamldoc|list|datetime/;
135 4 50       12 my $filename = $method_args{$name} or next;
136 4 50 33     22 LOGDIE "Argument for $name should be a filename, an arrayref or - for STDIN" if $filename && $filename =~ /\n/;
137 4         8 for ($_->{preprocess}) {
138 4 100       11 /yamldoc/ and do {
139 2 100       7 next if ref $filename;
140 1 50       8 $method_args{$name} = ($filename eq "-" ? Load(join "",<STDIN>) : LoadFile($filename))
    50          
141             or LOGDIE "Error parsing yaml in ($filename)";
142 1         120 next;
143             };
144 2 50       6 /list/ and do {
145 2 100       8 next if ref $filename eq 'ARRAY';
146 1         12 $method_args{$name} = [ map { chomp; $_ } IO::File->new("< $filename")->getlines ];
  3         140  
  3         8  
147 1         8 next;
148             };
149 0 0       0 /^datetime$/ and do {
150 0         0 $method_args{$name} = DateTime::Format::DateParse->parse_datetime($method_args{$name})->iso8601();
151 0         0 next;
152             };
153             }
154             }
155              
156             # Order the args properly
157 12         18 my @method_args;
158 12         21 for (@$route_args) {
159 38         51 my $name = $_->{name};
160 38 100       70 next unless exists($method_args{$name});
161 29         57 push @method_args, $name => $method_args{$name};
162             }
163 12         192 return @method_args;
164             }
165              
166              
167             1;
168              
169             __END__
170              
171             =pod
172              
173             =encoding UTF-8
174              
175             =head1 NAME
176              
177             Clustericious::Client::Meta::Route - metadata about a route'
178              
179             =head1 VERSION
180              
181             version 1.27
182              
183             =head1 SYNOPSIS
184              
185             my $meta = Clustericious::Client::Meta::Route->new(
186             client_class => 'Yars::Client',
187             route_name => 'bucket_map,
188             );
189             $meta->get('auto_failover');
190              
191             =head2 set
192              
193             Set a route attribute.
194              
195             $meta->set(auto_failover => 1);
196              
197             =head2 get
198              
199             Get a route attribute.
200              
201             $meta->get('auto_failover');
202              
203             =head2 doc
204              
205             Get documentation for this route.
206              
207             =head2 set_doc
208              
209             Set the documentation for a route.
210              
211             =head2 client_class
212              
213             The class of the client associated with this object.
214              
215             =head2 route_name
216              
217             The name of the route to which this object refers.
218              
219             =head2 process_args
220              
221             Process an array of arguments sent to this route.
222              
223             This will look at the the route_arg specification that
224             has been set up for this route, and use it to turn
225             an array of parameters into hash for use by the method.
226              
227             If any of the args have a 'preprocess' (C<list>, C<yamldoc>, C<datetime>),
228             then those transformations are applied.
229              
230             If any required parameters are missing, an exception is thrown.
231              
232             If any parameters have an 'alt' entry or are abbreviated, the
233             full name is used instead.
234              
235             Returns a hash of arguments, dies on failure.
236              
237             See route_arg for a complete description of how arguments will
238             be processed. Note that modifies_url entries are not processed
239             here; that occurs just before the request is made.
240              
241             =head1 DESCRIPTION
242              
243             Keep track of metadata about a particular route. This includes
244             documentation and attributes.
245              
246             =head1 SEE ALSO
247              
248             Clustericious::Client::Meta
249              
250             =head1 AUTHOR
251              
252             Original author: Brian Duggan
253              
254             Current maintainer: Graham Ollis E<lt>plicease@cpan.orgE<gt>
255              
256             Contributors:
257              
258             Curt Tilmes
259              
260             Yanick Champoux
261              
262             =head1 COPYRIGHT AND LICENSE
263              
264             This software is copyright (c) 2013 by NASA GSFC.
265              
266             This is free software; you can redistribute it and/or modify it under
267             the same terms as the Perl 5 programming language system itself.
268              
269             =cut