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   40213 use strict;
  5         7  
  5         133  
4 5     5   23 use warnings;
  5         17  
  5         144  
5 5     5   23 use base qw(Data::Range::Compare::Stream::Iterator::Compare::Base);
  5         9  
  5         3556  
6 5     5   25 use Carp qw(croak);
  5         8  
  5         8658  
7              
8             sub has_next {
9 187     187 0 50759 my ($self)=@_;
10 187 100       643 $self->prepare unless $self->prepared;
11 187         760 $self->{has_next};
12             }
13              
14             sub prepare {
15 40     40 0 97 my ($self,%args)=@_;
16 40 50       134 return undef if $self->prepared;
17            
18 40         66 my $min_range_start;
19             my $min_range_end;
20 0         0 my $iterators_has_next_count;
21 40         58 my $min_range_start_column_id=0;
22              
23 40         159 for(my $id=0;$id<$self->get_column_count_human_readable;++$id) {
24              
25 97         189 my $iterator=$self->{consolidateors}->[$id];
26              
27 97 50       291 unless($iterator->has_next) {
28 0         0 $self->{has_next}=0;
29 0         0 return undef;
30             }
31 97         327 my $raw_range=$iterator->get_next;
32              
33 97         163 push @{$self->{raw_row}},$raw_range;
  97         215  
34 97         133 push @{$self->{last_column_value}},$raw_range->get_common;
  97         391  
35 97 100       222 if(defined($min_range_start)) {
36 57         164 my $common_raw=$raw_range->get_common;
37 57         157 my $common_start=$min_range_start->get_common;
38 57         155 my $common_end=$min_range_end->get_common;
39 57 100       175 if($common_raw->cmp_range_start($common_start)==-1) {
40 10         16 $min_range_start=$raw_range;
41 10         18 $min_range_start_column_id=$id;
42             }
43 57 100       185 if($common_raw->cmp_range_end($common_end)==-1) {
44 14         90 $min_range_end=$raw_range;
45 14         27 $min_range_start_column_id=$id;
46             }
47             } else {
48 40         53 $min_range_start=$raw_range;
49 40         61 $min_range_end=$raw_range;
50             }
51 97 100       302 ++$iterators_has_next_count if $iterator->has_next;
52             }
53              
54 40         108 $self->{iterators_empty}=!$iterators_has_next_count;
55              
56 40         138 my $next_range=$self->create_from_factory($min_range_start->get_common->range_start,$min_range_end->get_common->range_end);
57 40         151 $next_range->on_create_range($min_range_start->get_common->range_start);
58              
59 40         149 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         314 my $cmp=$self->{raw_row}->[$id]->get_common;
63 97         281 my $cmp_end=$cmp->previous_range_end;
64              
65 97 100       294 if($next_range->contains_value($cmp_end)) {
66 7 100       24 if($next_range->cmp_values($next_range->range_end,$cmp_end)==1){
67 2         6 my $old_next_range=$next_range;
68 2         7 $next_range=$self->create_from_factory($next_range->range_start,$cmp_end);
69 2         9 $next_range->on_create_range($old_next_range);
70             }
71             }
72              
73             }
74              
75 40         99 $self->{has_next}=1;
76 40         80 $self->{current_row}=$next_range;
77 40         90 $self->{processed_ranges}=1;
78              
79 40         62 $self->{prepared}=1;
80 40         110 1;
81             }
82              
83             sub iterator_in_use {
84 12     12 0 17 my ($self,$id)=@_;
85 12 50       33 croak "id lt 0" if $id<0;
86 12 50       42 croak "id gt max" if $id>$self->get_column_count;
87 12         48 my $raw=$self->{raw_row}->[$id]->get_common;
88 12         39 my $current=$self->get_current_row;
89              
90 12 100       44 return 1 if $raw->overlap($current);
91 9         31 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 1091 my ($self,$id)=@_;
102            
103 12 100       34 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         11 $self->{column_map}=[];
107 4         9 $self->{root_ids}=[];
108              
109 4         22 my $con=$self->get_iterator_by_id($id);
110              
111 4         7 splice(@{$self->{dead_columns}},$id,1);
  4         12  
112 4         10 splice(@{$self->{raw_row}},$id,1);
  4         11  
113 4         9 splice(@{$self->{consolidateors}},$id,1);
  4         9  
114              
115 4         22 $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 32240 my ($self)=@_;
134              
135 296 100       1301 $self->prepare unless $self->prepared;
136             # get the current row
137 296         900 my $current_row=$self->get_current_row;
138 296 50       661 croak "Fatal: get_next called befor has_next or after the iterator set is empty" unless defined($current_row);
139              
140 296         504 my $result=[];
141              
142 296         1017 my $next_range_start=$current_row->next_range_start;
143 296         506 my $iterators_has_next_count;
144             my $max_range_end;
145              
146 296         407 my $overlap_count=0;
147 296         439 my $overlap_ids=[];
148 296         473 my $non_overlap_ids=[];
149 296         400 my $created_range=0;
150 296         332 my $next_range;
151 296         474 my $dead_columns=$self->{dead_columns};
152 296         423 my $column_map=$self->{column_map};
153 296         451 my $root_ids=$self->{root_ids};
154              
155 296         983 GET_ROW_LOOP: for(my $id=0;$id<$self->get_column_count_human_readable;++$id) {
156            
157 879         1481 my $iterator=$self->{consolidateors}->[$id];
158 879 100       1954 if($#$column_map<$id) {
159 111         345 $iterator->set_column_id($id);
160              
161 111 100       329 if($iterator->is_child) {
162 16         27 my $walk=$iterator;
163 16         50 while($walk->is_child) {
164 30         100 $walk=$self->get_iterator_by_id($walk->get_root_column_id);
165             }
166 16         63 $column_map->[$id]=$walk->get_column_id;
167             } else {
168 95         175 $column_map->[$id]=$id;
169 95         201 push @$root_ids,$id;
170             }
171             }
172              
173 879 100 66     2472 if($dead_columns->[$id] and !$iterator->has_next) {
174 78         132 push @$non_overlap_ids,$id;
175 78         121 push @$result,undef;
176 78         323 next GET_ROW_LOOP;
177             }
178              
179             # Objects we will use throught the loop
180 801         1222 my $raw_range=$self->{raw_row}->[$id];
181 801         2444 my $cmp=$raw_range->get_common;
182              
183 801         1103 my $is_dead=0;
184              
185              
186             # current row computations
187 801 100       2234 if($current_row->overlap($cmp)) {
188 402         758 push @$result,$raw_range;
189 402         512 ++$overlap_count;
190 402         652 push @$overlap_ids,$id;
191             } else {
192 399         688 push @$result,undef;
193 399 100       1052 if($current_row->cmp_range_end($cmp)==1) {
194 46         67 ++$is_dead
195             }
196 399         760 push @$non_overlap_ids,$id;
197             }
198              
199 801 100 100     2414 if($cmp->cmp_ranges($current_row)==0 or $cmp->cmp_range_end($current_row)==0) {
200 251 100       806 if($iterator->has_next) {
201 146         426 my $next_range=$iterator->get_next;
202              
203 146         240 $raw_range=$next_range;
204 146         415 $cmp=$raw_range->get_common;
205 146         368 $self->{raw_row}->[$id]=$next_range;
206             }
207             }
208              
209 801 100       3046 if($iterator->has_next) {
210 299         448 ++$iterators_has_next_count;
211             } else {
212 502         669 ++$is_dead;
213             }
214              
215 801 100       1578 if(defined($next_range)) {
216 451         1260 my $cmp_end=$cmp->previous_range_end;
217              
218 451 100 100     1312 if($next_range->contains_value($cmp_end)) {
    100          
219              
220 87 50       240 if($next_range->cmp_values($next_range->range_end,$cmp_end)!=-1){
221            
222 87         173 my $old_next_range=$next_range;
223 87         248 $next_range=$self->create_from_factory($next_range->range_start,$cmp_end);
224 87         242 $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         107 my $old_next_range=$next_range;
231            
232 80         245 $next_range=$self->create_from_factory($next_range->range_start,$cmp->range_end);
233 80         229 $next_range->on_create_range($old_next_range);
234              
235             }
236             } else {
237              
238 350         1007 my $cmp_end=$cmp->previous_range_end;
239              
240 350 100       1014 if($cmp->cmp_values($next_range_start,$cmp_end)!=1) {
    100          
241              
242 101         136 my $old_next_range=$next_range;
243              
244 101         337 $next_range=$self->create_from_factory($next_range_start,$cmp_end);
245 101         299 $next_range->on_create_range($old_next_range);
246              
247             } elsif($cmp->cmp_values($next_range_start,$cmp->range_end)!=1) {
248              
249 155         188 my $old_next_range=$next_range;
250              
251 155         425 $next_range=$self->create_from_factory($next_range_start,$cmp->range_end);
252 155         478 $next_range->on_create_range($old_next_range);
253              
254             }
255            
256             }
257            
258 801 100       1857 if(defined($max_range_end)) {
259 505 100       1343 $max_range_end=$cmp if $max_range_end->cmp_range_end($cmp)==-1;
260             } else {
261 296         398 $max_range_end=$cmp;
262             }
263 801 100       1613 if($is_dead==2) {
264 46         175 $dead_columns->[$id]=$self->on_dead_iterator($id);
265             } else {
266 755         3208 $dead_columns->[$id]=0;
267             }
268             }
269              
270 296         599 $self->{iterators_empty}=!$iterators_has_next_count;
271              
272 296 100       696 if($self->{last_row}) {
273 40         81 $self->{has_next}=0;
274             } else {
275              
276 256 50       639 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         412 $self->{current_row}=$next_range;
282 256   100     912 $self->{last_row}=($self->{iterators_empty} and $next_range->cmp_range_end($max_range_end)!=-1);
283             }
284              
285 296         1489 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         999 return $obj;
295             }
296              
297             1;