File Coverage

blib/lib/Data/Differences.pm
Criterion Covered Total %
statement 42 44 95.4
branch 22 26 84.6
condition 16 24 66.6
subroutine 7 7 100.0
pod 0 6 0.0
total 87 107 81.3


line stmt bran cond sub pod time code
1             #!/usr/bin/perl -w
2             #!/usr/bin/perl -d:ptkdb -w
3             #
4             # This is module is based on a module with the same name, implemented
5             # when working for Newtec Cy, located in Belgium,
6             # http://www.newtec.be/.
7             #
8              
9             package Data::Differences;
10              
11              
12             #
13             # Please read the comments of the constructor (new()) before using
14             # this package.
15             #
16             # How it should be done (at least this is what I think at the moment
17             # of writing) :
18             #
19             # 1. A set of differences is essentially a blessed hash which inherits
20             # from this package.
21             #
22             # 2. At the top level the hash contains entries describing meta
23             # information :
24             #
25             # 2.1. The fundamental types that have been compared.
26             #
27             # 3. Additionally the following items are present at the top level :
28             #
29             # 3.1. 'subtractor_operands' : operands for the subtract operation.
30             #
31             # 3.2. 'adder_operands' : operands for the add operation. This should
32             # be feed to Hash::Merge, possibly by first embedding the given
33             # arguments in a top level hash (e.g. if the arguments are arrays).
34             #
35              
36              
37 7     7   40 use strict;
  7         28  
  7         5067  
38              
39              
40             #
41             # is_empty()
42             #
43             # Return true if a differences describing data structure describes no
44             # differences.
45             #
46              
47             sub is_empty
48             {
49 364     364 0 6565 my $self = shift;
50              
51             #t perhaps I should also return false for an array with only
52             #t undefs and likewise for a hash ?
53              
54             # for an empty hash
55              
56 364 100 100     2961 if (("$self" =~ /HASH/ && !%$self)
      100        
      66        
      100        
      66        
57              
58             # or an empty array
59              
60             || ("$self" =~ /ARRAY/ && !@$self)
61              
62             # or an empty scalar
63              
64             || ("$self" =~ /SCALAR/ && !defined $$self))
65             {
66             # return empty
67              
68 357         1528 return 1;
69             }
70              
71             # otherwise
72              
73             else
74             {
75             # return false
76              
77 7         26 return 0;
78             }
79             }
80              
81              
82             #
83             # filter()
84             #
85             # Filter the differences set by removing the undef entries. For
86             # reasons of consistency this sub must be called during construction.
87             #
88              
89             sub filter
90             {
91 399     399 0 400 my $self = shift;
92              
93 399 100 33     1756 if ("$self" =~ /ARRAY/)
    100 33        
    100          
    50          
    50          
94             {
95 66         125 return $self->filter_array();
96             }
97             elsif ("$self" =~ /HASH/)
98             {
99 148         266 return $self->filter_hash();
100             }
101             elsif ("$self" =~ /SCALAR/)
102             {
103 181         354 return $self->filter_scalar();
104             }
105             elsif ("$self" =~ /REF/
106             && !defined $$self)
107             {
108 0         0 return \undef;
109             }
110             elsif ("$self" =~ /REF/
111             && UNIVERSAL::isa($$self,'Data::Differences'))
112             {
113 0         0 return $$self->filter();
114             }
115             else
116             {
117             # a structure that cannot be dissected any further : return it.
118              
119 4         9 return $self;
120             }
121             }
122              
123              
124             sub filter_array
125             {
126 66     66 0 75 my $self = shift;
127              
128 66         70 my $is_empty = 1;
129              
130 66         149 foreach my $entry (@$self)
131             {
132             #t see comments below on ->filter_hash().
133             #t perhaps this needs protection with an additional check, not sure.
134              
135 21 100       47 if (defined $entry)
136             {
137 13 100       21 if ($entry->filter())
138             {
139 8         19 $is_empty = 0;
140             }
141             }
142             }
143              
144 66 100       143 if ($is_empty)
145             {
146 58         87 @$self = ();
147             }
148              
149 66         121 return $self;
150             }
151              
152              
153             sub filter_hash
154             {
155 148     148 0 153 my $self = shift;
156              
157 148         144 my $is_empty = 1;
158              
159 148         348 foreach my $key (keys %$self)
160             {
161             #t
162             #t The first if condition is bogus I guess,
163             #t commented out but perhaps
164             #t it is right for certain scenarios, unresolved.
165             #t The rest of the TODO comments is about the
166             #t commented out condition only.
167             #t
168             #t we can get here with a reference to an empty hash.
169             #t without the eval below, we get the perl error
170             #t 'Not a SCALAR reference'. I simply added the
171             #t eval {} statement to allow to continue the other
172             #t developments. I inspected via the debugger the
173             #t correctness of the software under test,
174             #t I am not sure of the correctness of the testing
175             #t software. Given the fact that this eval {} statement
176             #t also hides a number of warnings, I suspect so far
177             #t unforeseen scenarios that might popup as bugs of
178             #t the testing software.
179              
180             eval
181 8         12 {
182             # if (defined ${$self->{$key}})
183 8 50       19 if (defined $self->{$key})
184             {
185 8 50       32 if ($self->{$key}->filter())
186             {
187 8         23 $is_empty = 0;
188             }
189             }
190             };
191             }
192              
193 148 100       294 if ($is_empty)
194             {
195 140         222 %$self = ();
196             }
197              
198 148         261 return $self;
199             }
200              
201              
202             sub filter_scalar
203             {
204 181     181 0 218 my $self = shift;
205              
206 181 100       321 if (defined $$self)
207             {
208 12         32 return 1;
209             }
210             else
211             {
212 169         325 return undef;
213             }
214             }
215              
216              
217             #
218             # new()
219             #
220             # Create a new structure from the given data structure.
221             #
222             # The given data structure must be compliant with the common
223             # conventions for this data structure, whatever they may be. They
224             # still need complete definition.
225             #
226             # Currently the differences structure only deals with new data (to be
227             # added to existing data), it does not deal with data to be removed.
228             #
229              
230             sub new
231             {
232 378     378 0 442 my $proto = shift;
233              
234 378   33     1208 my $class = ref $proto || $proto;
235              
236 378         360 my $differences = shift;
237              
238 378         635 bless $differences, $class;
239              
240 378         660 $differences->filter();
241              
242 378         1031 return $differences;
243             }
244              
245              
246             1;
247              
248