File Coverage

blib/lib/Data/Range/Compare/Stream/Iterator/Compare/Asc.pm
Criterion Covered Total %
statement 157 175 89.7
branch 61 76 80.2
condition 11 30 36.6
subroutine 9 12 75.0
pod 1 8 12.5
total 239 301 79.4


line stmt bran cond sub pod time code
1             package Data::Range::Compare::Stream::Iterator::Compare::Asc;
2              
3 5     5   55753 use strict;
  5         10  
  5         181  
4 5     5   25 use warnings;
  5         11  
  5         151  
5 5     5   32 use base qw(Data::Range::Compare::Stream::Iterator::Compare::Base);
  5         8  
  5         3900  
6 5     5   28 use Carp qw(croak);
  5         12  
  5         8903  
7              
8             sub has_next {
9 187     187 0 86833 my ($self)=@_;
10 187 100       743 $self->prepare unless $self->prepared;
11 187         1005 $self->{has_next};
12             }
13              
14             sub prepare {
15 40     40 0 113 my ($self,%args)=@_;
16 40 50       137 return undef if $self->prepared;
17            
18 40         79 my $min_range_start;
19             my $min_range_end;
20 0         0 my $iterators_has_next_count;
21 40         65 my $min_range_start_column_id=0;
22              
23 40         191 for(my $id=0;$id<$self->get_column_count_human_readable;++$id) {
24              
25 97         194 my $iterator=$self->{consolidateors}->[$id];
26              
27 97 50       354 unless($iterator->has_next) {
28 0         0 $self->{has_next}=0;
29 0         0 return undef;
30             }
31 97         348 my $raw_range=$iterator->get_next;
32              
33 97         169 push @{$self->{raw_row}},$raw_range;
  97         287  
34 97         118 push @{$self->{last_column_value}},$raw_range->get_common;
  97         427  
35 97 100       248 if(defined($min_range_start)) {
36 57         175 my $common_raw=$raw_range->get_common;
37 57         164 my $common_start=$min_range_start->get_common;
38 57         172 my $common_end=$min_range_end->get_common;
39 57 100       353 if($common_raw->cmp_range_start($common_start)==-1) {
40 10         15 $min_range_start=$raw_range;
41 10         19 $min_range_start_column_id=$id;
42             }
43 57 100       249 if($common_raw->cmp_range_end($common_end)==-1) {
44 14         23 $min_range_end=$raw_range;
45 14         30 $min_range_start_column_id=$id;
46             }
47             } else {
48 40         55 $min_range_start=$raw_range;
49 40         63 $min_range_end=$raw_range;
50             }
51 97 100       293 ++$iterators_has_next_count if $iterator->has_next;
52             }
53              
54 40         116 $self->{iterators_empty}=!$iterators_has_next_count;
55              
56 40         133 my $next_range=$self->create_from_factory($min_range_start->get_common->range_start,$min_range_end->get_common->range_end);
57 40         157 $next_range->on_create_range($min_range_start->get_common->range_start);
58              
59 40         173 for(my $id=0;$id<$self->get_column_count_human_readable;++$id) {
60             # stop here if this is the column started on
61            
62 97         353 my $cmp=$self->{raw_row}->[$id]->get_common;
63 97         337 my $cmp_end=$cmp->previous_range_end;
64              
65 97 100       280 if($next_range->contains_value($cmp_end)) {
66 7 100       28 if($next_range->cmp_values($next_range->range_end,$cmp_end)==1){
67 2         5 my $old_next_range=$next_range;
68 2         10 $next_range=$self->create_from_factory($next_range->range_start,$cmp_end);
69 2         11 $next_range->on_create_range($old_next_range);
70             }
71             }
72              
73             }
74              
75 40         107 $self->{has_next}=1;
76 40         86 $self->{current_row}=$next_range;
77 40         96 $self->{processed_ranges}=1;
78              
79 40         63 $self->{prepared}=1;
80 40         117 1;
81             }
82              
83             sub iterator_in_use {
84 12     12 0 24 my ($self,$id)=@_;
85 12 50       47 croak "id lt 0" if $id<0;
86 12 50       54 croak "id gt max" if $id>$self->get_column_count;
87 12         71 my $raw=$self->{raw_row}->[$id]->get_common;
88 12         47 my $current=$self->get_current_row;
89              
90 12 100       88 return 1 if $raw->overlap($current);
91 9         35 return $raw->cmp_range_end($current)!=-1;
92             }
93              
94             sub iterator_is_dead {
95 0     0 0 0 my ($self,$id)=@_;
96 0 0 0     0 croak 'column id out of bounds' if !defined($id) or $id < 0 or $id > $#{$self->{raw_row}};
  0   0     0  
97 0         0 $self->{dead_columns}->[$id]
98             }
99              
100             sub delete_iterator {
101 12     12 0 3012 my ($self,$id)=@_;
102            
103 12 100       45 croak 'cannot delete an iterator while its results are in use' if $self->iterator_in_use($id);
104              
105             # odds are these objects are in use, so we need to create new ones
106 4         12 $self->{column_map}=[];
107 4         33 $self->{root_ids}=[];
108              
109 4         46 my $con=$self->get_iterator_by_id($id);
110              
111 4         9 splice(@{$self->{dead_columns}},$id,1);
  4         17  
112 4         8 splice(@{$self->{raw_row}},$id,1);
  4         10  
113 4         13 splice(@{$self->{consolidateors}},$id,1);
  4         10  
114              
115 4         33 $con->delete_from_root;
116            
117             }
118              
119             sub get_raw_result {
120 0     0 0 0 my ($self,$id)=@_;
121 0 0 0     0 croak 'column id out of bounds' if !defined($id) or $id < 0 or $id > $#{$self->{raw_row}};
  0   0     0  
122 0         0 $self->{raw_row}->[$id]
123             }
124              
125             sub set_raw_result {
126 0     0 0 0 my ($self,$id,$raw_result)=@_;
127 0 0 0     0 croak 'column id out of bounds' if !defined($id) or $id < 0 or $id > $#{$self->{raw_row}};
  0   0     0  
128 0 0       0 croak 'raw_result not defined' unless defined($raw_result);
129 0         0 $self->{raw_row}->[$id]=$raw_result;
130             }
131              
132             sub get_next {
133 296     296 1 56843 my ($self)=@_;
134              
135 296 100       1345 $self->prepare unless $self->prepared;
136             # get the current row
137 296         1139 my $current_row=$self->get_current_row;
138 296 50       904 croak "Fatal: get_next called befor has_next or after the iterator set is empty" unless defined($current_row);
139              
140 296         824 my $result=[];
141              
142 296         1504 my $next_range_start=$current_row->next_range_start;
143 296         439 my $iterators_has_next_count;
144             my $max_range_end;
145              
146 296         386 my $overlap_count=0;
147 296         538 my $overlap_ids=[];
148 296         438 my $non_overlap_ids=[];
149 296         381 my $created_range=0;
150 296         400 my $next_range;
151 296         541 my $dead_columns=$self->{dead_columns};
152 296         490 my $column_map=$self->{column_map};
153 296         719 my $root_ids=$self->{root_ids};
154              
155 296         7438 GET_ROW_LOOP: for(my $id=0;$id<$self->get_column_count_human_readable;++$id) {
156            
157 879         1620 my $iterator=$self->{consolidateors}->[$id];
158 879 100       2114 if($#$column_map<$id) {
159 111         384 $iterator->set_column_id($id);
160              
161 111 100       366 if($iterator->is_child) {
162 16         32 my $walk=$iterator;
163 16         61 while($walk->is_child) {
164 30         117 $walk=$self->get_iterator_by_id($walk->get_root_column_id);
165             }
166 16         65 $column_map->[$id]=$walk->get_column_id;
167             } else {
168 95         182 $column_map->[$id]=$id;
169 95         197 push @$root_ids,$id;
170             }
171             }
172              
173 879 100 66     2549 if($dead_columns->[$id] and !$iterator->has_next) {
174 78         159 push @$non_overlap_ids,$id;
175 78         158 push @$result,undef;
176 78         320 next GET_ROW_LOOP;
177             }
178              
179             # Objects we will use throught the loop
180 801         1336 my $raw_range=$self->{raw_row}->[$id];
181 801         2596 my $cmp=$raw_range->get_common;
182              
183 801         1161 my $is_dead=0;
184              
185              
186             # current row computations
187 801 100       2584 if($current_row->overlap($cmp)) {
188 402         745 push @$result,$raw_range;
189 402         507 ++$overlap_count;
190 402         655 push @$overlap_ids,$id;
191             } else {
192 399         792 push @$result,undef;
193 399 100       1402 if($current_row->cmp_range_end($cmp)==1) {
194 46         84 ++$is_dead
195             }
196 399         895 push @$non_overlap_ids,$id;
197             }
198              
199 801 100 100     2589 if($cmp->cmp_ranges($current_row)==0 or $cmp->cmp_range_end($current_row)==0) {
200 251 100       832 if($iterator->has_next) {
201 146         506 my $next_range=$iterator->get_next;
202              
203 146         266 $raw_range=$next_range;
204 146         459 $cmp=$raw_range->get_common;
205 146         361 $self->{raw_row}->[$id]=$next_range;
206             }
207             }
208              
209 801 100       3453 if($iterator->has_next) {
210 299         486 ++$iterators_has_next_count;
211             } else {
212 502         837 ++$is_dead;
213             }
214              
215 801 100       1706 if(defined($next_range)) {
216 451         1323 my $cmp_end=$cmp->previous_range_end;
217              
218 451 100 100     1449 if($next_range->contains_value($cmp_end)) {
    100          
219              
220 87 50       287 if($next_range->cmp_values($next_range->range_end,$cmp_end)!=-1){
221            
222 87         183 my $old_next_range=$next_range;
223 87         251 $next_range=$self->create_from_factory($next_range->range_start,$cmp_end);
224 87         271 $next_range->on_create_range($old_next_range);
225              
226             }
227              
228             } elsif($next_range->cmp_range_end($cmp)==1 and $cmp->cmp_values($next_range_start,$cmp->range_end)!=1) {
229              
230 80         133 my $old_next_range=$next_range;
231            
232 80         307 $next_range=$self->create_from_factory($next_range->range_start,$cmp->range_end);
233 80         256 $next_range->on_create_range($old_next_range);
234              
235             }
236             } else {
237              
238 350         5992 my $cmp_end=$cmp->previous_range_end;
239              
240 350 100       1687 if($cmp->cmp_values($next_range_start,$cmp_end)!=1) {
    100          
241              
242 101         784 my $old_next_range=$next_range;
243              
244 101         410 $next_range=$self->create_from_factory($next_range_start,$cmp_end);
245 101         935 $next_range->on_create_range($old_next_range);
246              
247             } elsif($cmp->cmp_values($next_range_start,$cmp->range_end)!=1) {
248              
249 155         242 my $old_next_range=$next_range;
250              
251 155         498 $next_range=$self->create_from_factory($next_range_start,$cmp->range_end);
252 155         554 $next_range->on_create_range($old_next_range);
253              
254             }
255            
256             }
257            
258 801 100       1826 if(defined($max_range_end)) {
259 505 100       1312 $max_range_end=$cmp if $max_range_end->cmp_range_end($cmp)==-1;
260             } else {
261 296         411 $max_range_end=$cmp;
262             }
263 801 100       1636 if($is_dead==2) {
264 46         235 $dead_columns->[$id]=$self->on_dead_iterator($id);
265             } else {
266 755         3475 $dead_columns->[$id]=0;
267             }
268             }
269              
270 296         670 $self->{iterators_empty}=!$iterators_has_next_count;
271              
272 296 100       729 if($self->{last_row}) {
273 40         92 $self->{has_next}=0;
274             } else {
275              
276 256 50       617 unless(defined($next_range)) {
277 0         0 $next_range=$self->create_from_factory($next_range_start,$next_range_start);
278 0         0 $next_range->on_create_range($current_row);
279             }
280              
281 256         476 $self->{current_row}=$next_range;
282 256   100     1066 $self->{last_row}=($self->{iterators_empty} and $next_range->cmp_range_end($max_range_end)!=-1);
283             }
284              
285 296         1971 my $obj=$self->RESULT_CLASS->new(
286             $current_row,
287             $result,
288             $overlap_count,
289             $overlap_ids,
290             $non_overlap_ids,
291             $column_map,
292             $root_ids,
293             );
294 296         1371 return $obj;
295             }
296              
297             1;