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 3     3   16 use strict;
  3         7  
  3         107  
4 3     3   17 use warnings;
  3         4  
  3         91  
5 3     3   19 use YAML::XS qw/LoadFile/;
  3         5  
  3         231  
6 3     3   2677 use DateTime::Format::DateParse;
  3         574274  
  3         119  
7 3     3   3916 use Getopt::Long qw/GetOptionsFromArray/;
  3         35212  
  3         21  
8 3     3   601 use Mojo::Base qw/-base/;
  3         7  
  3         67  
9 3     3   551 use Data::Dumper;
  3         7  
  3         163  
10 3     3   2752 use Clustericious::Log;
  3         31894  
  3         22  
11 3     3   260 use Clustericious::Client::Meta;
  3         7  
  3         5116  
12              
13             # ABSTRACT: metadata about a route'
14             our $VERSION = '0.85'; # VERSION
15              
16              
17             has 'client_class';
18             has 'route_name';
19              
20              
21             sub set {
22 22     22 1 28 my $self = shift;
23 22         461 return Clustericious::Client::Meta->add_route_attribute(
24             $self->client_class, $self->route_name, @_ );
25             }
26              
27              
28             sub get {
29 30     30 1 50 my $self = shift;
30 30         709 return Clustericious::Client::Meta->get_route_attribute(
31             $self->client_class, $self->route_name, @_ );
32             }
33              
34              
35             sub doc {
36 1     1 1 10 my $self = shift;
37 1         19 return Clustericious::Client::Meta->get_route_doc(
38             $self->client_class, $self->route_name, @_
39             );
40             }
41              
42              
43             sub set_doc {
44 6     6 1 10 my $self = shift;
45 6         116 return Clustericious::Client::Meta->add_route(
46             $self->client_class, $self->route_name, @_
47             );
48             }
49              
50              
51             sub process_args {
52 14     14 1 167 my $meta = shift;
53 14         47 my @args = @_;
54 14         19 my $cli;
55 14 100 66     60 if (ref $args[0] eq 'HASH' && $args[0]{command_line}) {
56 5         7 $cli = 1;
57 5         6 shift @args;
58             }
59 14 50       42 my $route_args = $meta->get('args') or return @args;
60 14 100       42 unless ($cli) {
61             # method call, modify @args so that getopt will work.
62             # Prepend a "--" for named params.
63 9         13 my %valid;
64 9         21 for (@$route_args) {
65 29 100       82 next if $_->{positional};
66 17         38 my @name = ( $_->{name} );
67 17 100       39 if ($_->{alt}) {
68 2         10 push @name, split '\|', $_->{alt};
69             }
70 17         28 my $type = $_->{type};
71 17         80 $valid{$_} = $type for @name;
72             }
73 9         14 my @new;
74 9         31 while (my $in = shift @args) {
75 25 100       46 if (exists($valid{$in})) {
76 11         24 push @new, "--$in";
77 11 50 33     116 push @new, shift @args if @args && defined($valid{$in}) && length($valid{$in});
      33        
78             } else {
79 14         45 push @new, $in;
80             }
81             }
82              
83 9         32 @args = @new;
84             }
85              
86 14 100       32 my %req = map { $_->{required} ? ($_->{name} => 1):() } @$route_args;
  48         118  
87 48 100 100     225 my @getopt = map {
88 14         22 $_->{name}
89             .($_->{alt} ? "|$_->{alt}" : "")
90             .($_->{type} || '')
91             } @$route_args;
92              
93 48 100 100     402 my $doc = join "\n", "Valid options for '".$meta->route_name."' are :",
94             map {
95 14         324 sprintf(' --%-20s%-15s%s', $_->{name}, $_->{required} ? 'required' : '', $_->{doc} || "" )
96             } @$route_args;
97              
98 14         26 my %method_args;
99 14         55 Getopt::Long::Configure(qw/pass_through/); # TODO use OO interface
100 14 50       505 GetOptionsFromArray(\@args, \%method_args, @getopt) or LOGDIE "Invalid options. $doc\n";
101              
102             # Check for positional args
103 14         5231 for (@$route_args) {
104 48 100       103 next unless @args;
105 20 100       56 my $spec = $_->{positional} or next;
106 12         16 my $name = $_->{name};
107 12         17 for ($spec) {
108 12 100       33 /one/ and do {
109 11         17 $method_args{$name} = shift @args;
110 11         29 next;
111             };
112 1 50       7 /many/ and do {
113 1         5 push @{ $method_args{$name} }, shift @args while @args;
  3         10  
114 1         4 next;
115             };
116 0         0 die "unknown positional spec : $spec";
117             }
118             }
119              
120             # Check for required args
121 14         34 for (@$route_args) {
122 41         59 my $name = $_->{name};
123 41 100       97 next unless $_->{required};
124 7 100       19 next if exists($method_args{$name});
125 2         16 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         20 for (@$route_args) {
132 38         44 my $name = $_->{name};
133 38 100       81 next unless $_->{preprocess};
134 4 50       27 LOGDIE "internal error: cannot handle $_->{preprocess}" unless $_->{preprocess} =~ /yamldoc|list|datetime/;
135 4 50       11 my $filename = $method_args{$name} or next;
136 4 50 33     23 LOGDIE "Argument for $name should be a filename, an arrayref or - for STDIN" if $filename && $filename =~ /\n/;
137 4         10 for ($_->{preprocess}) {
138 4 100       10 /yamldoc/ and do {
139 2 100       8 next if ref $filename;
140 1 50       10 $method_args{$name} = ($filename eq "-" ? Load(join "",) : LoadFile($filename))
    50          
141             or LOGDIE "Error parsing yaml in ($filename)";
142 1         210 next;
143             };
144 2 50       7 /list/ and do {
145 2 100       11 next if ref $filename eq 'ARRAY';
146 1         13 $method_args{$name} = [ map { chomp; $_ } IO::File->new("< $filename")->getlines ];
  3         200  
  3         8  
147 1         17 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         26 for (@$route_args) {
159 38         45 my $name = $_->{name};
160 38 100       81 next unless exists($method_args{$name});
161 29         59 push @method_args, $name => $method_args{$name};
162             }
163 12         191 return @method_args;
164             }
165              
166              
167             1;
168              
169              
170             __END__