File Coverage

blib/lib/Decision/Depends/Var.pm
Criterion Covered Total %
statement 61 64 95.3
branch 30 40 75.0
condition 14 21 66.6
subroutine 11 12 91.6
pod 0 7 0.0
total 116 144 80.5


line stmt bran cond sub pod time code
1             # --8<--8<--8<--8<--
2             #
3             # Copyright (C) 2008 Smithsonian Astrophysical Observatory
4             #
5             # This file is part of Decision::Depends
6             #
7             # Decision-Depends is free software: you can redistribute it and/or modify
8             # it under the terms of the GNU General Public License as published by
9             # the Free Software Foundation, either version 3 of the License, or (at
10             # your option) any later version.
11             #
12             # This program is distributed in the hope that it will be useful,
13             # but WITHOUT ANY WARRANTY; without even the implied warranty of
14             # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15             # GNU General Public License for more details.
16             #
17             # You should have received a copy of the GNU General Public License
18             # along with this program. If not, see .
19             #
20             # -->8-->8-->8-->8--
21              
22             package Decision::Depends::Var;
23 11     11   11606 use Data::Compare ();
  11         165987  
  11         333  
24              
25             require 5.005_62;
26 11     11   117 use strict;
  11         30  
  11         405  
27 11     11   64 use warnings;
  11         22  
  11         385  
28              
29 11     11   65 use Carp;
  11         22  
  11         823  
30 11     11   10081 use Clone qw( clone );
  11         34554  
  11         14375  
31              
32             our $VERSION = '0.20';
33              
34             # regular expression for a floating point number
35             our $RE_Float = qr/^[+-]?(\d+[.]?\d*|[.]\d+)([dDeE][+-]?\d+)?$/;
36              
37             our %attr = ( depend => 1,
38             depends => 1,
39             force => 1,
40             var => 1,
41             case => 1,
42             numcmp => undef,
43             strcmp => undef,
44             no_case => 1,
45             );
46              
47             sub new
48             {
49 36     36 0 79 my $class = shift;
50 36   33     182 $class = ref($class) || $class;
51              
52 36         207 my ( $state, $spec ) = @_;
53              
54 36         280 my $self = { %$spec, state => $state };
55              
56             # ensure that no bogus attributes are set
57 36         76 my @notok = grep { ! exists $attr{$_} } keys %{$self->{attr}};
  71         214  
  36         114  
58              
59             # use the value of the var attribute if it's set (i.e. not 1)
60 36 100       136 if ( '1' ne $self->{attr}{var} )
61             {
62 17 50       57 croak( __PACKAGE__, '->new: too many variable names(s): ',
63             join(', ', $self->{attr}{var}, @notok ) ) if @notok;
64             }
65              
66             # old style: the variable name is an attribute.
67             else
68             {
69 19 50       71 croak( __PACKAGE__, '->new: too many variable names(s): ',
70             join(', ', @notok ) ) if @notok > 1;
71              
72 19 50       65 croak( __PACKAGE__,
73             ": must specify a variable name for `$self->{val}'" )
74             unless @notok == 1;
75 19         58 $self->{attr}{var} = $notok[0];
76             }
77              
78 36 50 66     345 croak( __PACKAGE__,
79             ": specify only one of the attributes `-numcmp' or `-strcmp'" )
80             if exists $self->{attr}{numcmp} && exists $self->{attr}{strcmp};
81              
82             # comparison attributes for arrays and hashes are not allowed
83 40         102 croak( __PACKAGE__,
84             ": comparison attributes on variable dependencies on hash or arrays are not allowed" )
85             if ref($self->{val}) =~ m/^(HASH|ARRAY)$/
86 36 50 66     169 && grep { exists $self->{attr}{$_}} qw( case numcmp strcmp no_case );
87              
88 36 100       194 $self->{val} = clone( $self->{val} ) if ref $self->{val};
89              
90 36         277 bless $self, $class;
91             }
92              
93             sub depends
94             {
95 28     28 0 48 my ( $self, $target ) = @_;
96              
97 28         120 my $var = $self->{attr}{var};
98              
99 28         49 my $state = $self->{state};
100              
101 28         168 my $prev_val = $state->getVar( $target, $var );
102              
103 28         59 my @deps = ();
104              
105 28 100       116 if ( defined $prev_val )
106             {
107 23   100     286 my $is_not_equal =
108             ( exists $self->{attr}{force} ?
109             $self->{attr}{force} : $state->Force ) ||
110             cmpVar( exists $self->{attr}{case},
111             $self->{attr}{numcmp},
112             $self->{attr}{strcmp},
113             $prev_val, $self->{val} );
114              
115 23 100       854 if ( $is_not_equal )
116             {
117 9 100       172 my $curval =
118             ref $self->{val} ? YAML::Dump( $self->{val} )
119             : '(' . $self->{val} . ')';
120 9 100       1692 my $preval =
121             ref $prev_val ? YAML::Dump( $prev_val )
122             : '(' . $prev_val . ')';
123 9 50       1349 print STDOUT
124             " variable `", $var, "' is now $curval, was $preval\n"
125             if $state->Verbose;
126              
127 9         34 push @deps, $var;
128             }
129             else
130             {
131 14 50       59 print STDOUT " variable `", $var, "' is unchanged\n"
132             if $state->Verbose;
133             }
134             }
135             else
136             {
137 5 50       17 print STDOUT " No value on file for variable `", $var, "'\n"
138             if $state->Verbose;
139 5         12 push @deps, $var;
140             }
141              
142 28         215 var => \@deps;
143             }
144              
145             sub cmp_strVar
146             {
147 11     11 0 31 my ( $case, $var1, $var2 ) = @_;
148            
149 11 50       89 ( $case ? uc($var1) ne uc($var2) : $var1 ne $var2 );
150             }
151              
152             sub cmp_numVar
153             {
154 2     2 0 4 my ( $var1, $var2 ) = @_;
155            
156 2         21 $var1 != $var2;
157             }
158              
159             sub cmpVar
160             {
161 21     21 0 121 my ( $case, $num, $str, $var1, $var2 ) = @_;
162              
163             # references that aren't the same
164 21 50 66     250 if ( ref $var1 ne ref $var2 )
    100 66        
    100 66        
    100          
    100          
165             {
166 0         0 return 1;
167             }
168              
169             # references
170             elsif ( ref $var1 )
171             {
172 8         37 ! Data::Compare::Compare( $var1, $var2 );
173             }
174              
175             elsif ( defined $num && $num )
176             {
177 1         9 cmp_numVar( $var1, $var2 );
178             }
179              
180             elsif ( defined $str && $str )
181             {
182 3         45 cmp_strVar( $case, $var1, $var2 );
183             }
184              
185             elsif ( $var1 =~ /$RE_Float/o && $var2 =~ /$RE_Float/o)
186             {
187 1         6 cmp_numVar( $var1, $var2 );
188             }
189              
190             else
191             {
192 8         25 cmp_strVar( $case, $var1, $var2 );
193             }
194             }
195              
196             sub update
197             {
198 19     19 0 41 my ( $self, $target ) = @_;
199              
200 19         176 $self->{state}->setVar( $target, $self->{attr}{var}, $self->{val} );
201             }
202              
203             sub pprint
204             {
205 0     0 0   my $self = shift;
206              
207 0           "$self->{attr}{var} = $self->{val}";
208             }
209              
210             1;