File Coverage

blib/lib/Parse/Crontab/Schedule/Entity.pm
Criterion Covered Total %
statement 72 72 100.0
branch 29 36 80.5
condition n/a
subroutine 12 12 100.0
pod 1 3 33.3
total 114 123 92.6


line stmt bran cond sub pod time code
1             package Parse::Crontab::Schedule::Entity;
2 6     6   43080 use 5.008_001;
  6         22  
  6         284  
3 6     6   34 use strict;
  6         9  
  6         191  
4 6     6   31 use warnings;
  6         11  
  6         215  
5              
6             use overload (
7 6         98 q{""} => 'stringify',
8 6     6   7982 );
  6         15469  
9              
10 6     6   9586 use List::MoreUtils qw/uniq/;
  6         28224  
  6         1048  
11              
12 6     6   3544 use Mouse;
  6         123871  
  6         42  
13              
14             has entity => (
15             is => 'ro',
16             isa => 'Str',
17             required => 1,
18             );
19              
20             has field => (
21             is => 'ro',
22             isa => 'Str',
23             required => 1,
24             );
25              
26             has range => (
27             is => 'ro',
28             isa => 'ArrayRef[Int]',
29             required => 1,
30             );
31              
32             has map => (
33             is => 'ro',
34             isa => 'HashRef',
35             );
36              
37             has range_min => (
38             is => 'ro',
39             isa => 'Int',
40             lazy => 1,
41             default => sub {shift->range->[0]},
42             );
43              
44             has range_max => (
45             is => 'ro',
46             isa => 'Int',
47             lazy => 1,
48             default => sub {shift->range->[1]},
49             );
50              
51             has expanded => (
52             is => 'rw',
53             isa => 'ArrayRef[Int]',
54             );
55              
56             has aliases => (
57             is => 'ro',
58             isa => 'ArrayRef[Str]',
59             auto_deref => 1,
60             );
61              
62             has _aliases_map => (
63             is => 'ro',
64             default => sub {
65             my $self = shift;
66             return unless $self->aliases;
67              
68             my $mapping = {};
69             my $num = $self->range_min;
70             for my $alias ($self->aliases) {
71             $mapping->{$alias} = $num;
72             $num++;
73             }
74             $mapping;
75             },
76             );
77              
78 6     6   5244 no Mouse;
  6         14  
  6         43  
79              
80             sub BUILD {
81 85     85 1 121 my $self = shift;
82              
83 85         98 my @expanded;
84 85         193 my $entity = $self->entity;
85              
86 85 100       252 if ($self->aliases) {
87 33         105 my $reg = '('. join('|', map {quotemeta $_} $self->aliases).')';
  311         1285  
88 33         2461 $entity =~ s/$reg/$self->_aliases_map->{lc($1)}/eig;
  4         34  
89             }
90              
91 85         315 for my $item (split /,/, $entity) {
92 88         187 my ($range_or_num, $increments) = split m!/!, $item, 2;
93 88 100       169 if ($increments) {
94 6 50       39 die 'entity not valid. (range is strange)' unless $self->_is_range($range_or_num);
95              
96 6         12 my $count = 0;
97 6         20 for my $i ($self->_expand_range($range_or_num)) {
98 199 100       323 push @expanded, $i if $count % $increments == 0;
99 199         209 $count++;
100             }
101             }
102             else {
103 82 100       189 if ($self->_is_range($range_or_num)) {
104 44         106 push @expanded, $self->_expand_range($range_or_num);
105             }
106             else {
107 38 100       211 die 'entity not valid. (not a number or strange range)' unless $range_or_num =~ /^[0-9]+$/;
108 35 50       164 die 'entity not valid. (too much item)' if $range_or_num > $self->range_max;
109 35 50       138 die 'entity not valid. (too less item)' if $range_or_num < $self->range_min;
110              
111 35         107 push @expanded, $range_or_num;
112             }
113             }
114             }
115 82 100       297 if ($self->field eq 'day_of_week') {
116 19 100       40 if (grep {$_ == 7} @expanded) {
  109         206  
117 12         22 push @expanded, 0;
118             }
119             }
120 82         327 @expanded = uniq sort {$a <=> $b} @expanded;
  1372         3039  
121 82         1243 $self->expanded([@expanded]);
122             }
123              
124             sub _is_range {
125 88     88   135 my ($self, $str) = @_;
126 88 100       271 return 1 if $str eq '*';
127              
128 41         84 my ($from, $to) = split /-/, $str, 2;
129 41 100       146 return () unless $to;
130 4 50       27 return () unless $from =~ /^[0-9]+$/;
131 4 100       17 return () unless $to =~ /^[0-9]+$/;
132              
133 3 50       13 return () if $to <= $from;
134 3 50       15 return () if $to > $self->range_max;
135 3 50       15 return () if $from < $self->range_min;
136              
137 3         10 return 1;
138             }
139              
140             sub _expand_range {
141 50     50   76 my ($self, $str) = @_;
142              
143 50         57 my ($from, $to);
144              
145 50 100       105 if ($str eq '*') {
146 47         179 $from = $self->range_min;
147 47         205 $to = $self->range_max;
148             }
149             else {
150 3         9 ($from, $to) = split /-/, $str, 2;
151             }
152              
153 50         336 ($from..$to);
154             }
155              
156 30     30 0 4420 sub stringify {shift->entity}
157              
158             sub match {
159 26     26 0 1671 my ($self, $num) = @_;
160              
161 26         26 grep {$num == $_} @{ $self->expanded };
  473         4817  
  26         71  
162             }
163              
164             __PACKAGE__->meta->make_immutable;