File Coverage

lib/XML/XMetaL/Utilities/Iterator.pm
Criterion Covered Total %
statement 18 70 25.7
branch 0 30 0.0
condition 0 12 0.0
subroutine 6 17 35.2
pod 2 3 66.6
total 26 132 19.7


line stmt bran cond sub pod time code
1             package XML::XMetaL::Utilities::Iterator;
2            
3 2     2   12802 use strict;
  2         4  
  2         74  
4 2     2   12 use warnings;
  2         5  
  2         57  
5            
6 2     2   11 use Carp;
  2         3  
  2         142  
7 2     2   11 use Hash::Util qw(lock_keys);
  2         3  
  2         19  
8            
9 2     2   108 use constant TRUE => 1;
  2         4  
  2         198  
10 2     2   10 use constant FALSE => 0;
  2         4  
  2         1542  
11            
12             sub new {
13 0     0 0   my ($class, %args) = @_;
14 0           my $self;
15 0           eval {
16 0           lock_keys(%args, qw(-domnode -filter));
17 0 0         die "-domnode argument is missing or not a DOM node type"
18             unless $args{-domnode}->{nodeType};
19 0 0         die "-filter argument is missing, or is not a subclass of XML::XMetaL::Utilities::Filter::Base"
20             unless $args{-filter}->isa('XML::XMetaL::Utilities::Filter::Base');
21 0   0       $self = bless {
      0        
22             _next_node => $args{-domnode} || croak("-domnode parameter missing or undefined"),
23             _filter => $args{-filter},
24             _depth => 0,
25             }, ref($class) || $class;
26 0           lock_keys(%$self, keys %$self);
27 0           my $next_node = $self->_get_next_node();
28 0           my $filter = $self->_get_filter();
29 0 0         unless ($filter->accept($next_node)) {
30 0           $next_node = $self->_find_next_node($next_node);
31 0           $self->_set_next_node($next_node);
32             }
33             };
34 0 0         croak $@ if $@;
35 0           return $self;
36             }
37            
38 0     0     sub _get_next_node {$_[0]->{_next_node}}
39 0     0     sub _set_next_node {$_[0]->{_next_node} = $_[1];}
40            
41 0     0     sub _get_filter {$_[0]->{_filter}}
42            
43             sub _increment_depth {
44 0     0     $_[0]->{_depth}++;
45             #print "depth: ".$_[0]->_get_depth()."\n";
46             }
47             sub _decrement_depth {
48 0     0     $_[0]->{_depth}--;
49             #print "depth: ".$_[0]->_get_depth()."\n";
50             }
51            
52 0     0     sub _get_depth {$_[0]->{_depth}}
53            
54             sub has_next {
55 0     0 1   my ($self) = @_;
56 0 0         return $self->_get_next_node() ? TRUE : FALSE;
57             }
58            
59             sub next {
60 0     0 1   my ($self) = @_;
61 0           my $current_node = $self->_get_next_node();
62 0           my $next_node = $self->_find_next_node($current_node);
63 0           $self->_set_next_node($next_node);
64 0           return $current_node;
65             }
66            
67             sub _find_next_node {
68 0     0     my ($self, $current_node) = @_;
69 0 0         return undef unless $current_node;
70 0           my $child_nodes;
71             my $next_node;
72 0           my $filter = $self->_get_filter();
73            
74 0 0 0       if ($current_node->hasChildNodes()) {
    0 0        
    0          
75 0           $self->_increment_depth();
76 0           $child_nodes = $current_node->{childNodes};
77 0           $next_node = $child_nodes->item(0);
78 0 0         return $next_node if $filter->accept($next_node);
79             } elsif ($self->_get_depth() >= 1 && $current_node->{nextSibling}) {
80 0           $next_node = $current_node->{nextSibling};
81 0 0         return $next_node if $filter->accept($next_node);
82             #} elsif ($self->_get_depth() > 1 && $current_node->{parentNode}->{nextSibling}) {
83             # $self->_decrement_depth();
84             # $next_node = $current_node->{parentNode}->{nextSibling};
85             # return $next_node if $filter->accept($next_node);
86             } elsif ($self->_get_depth() > 1 && $current_node->{parentNode}) {
87 0           $next_node = $self->_traverse_tree_upwards_recursively($current_node);
88 0 0         return $next_node if $filter->accept($next_node);
89             }
90            
91 0 0         if ($next_node) {
92 0           return $self->_find_next_node($next_node);
93             }
94 0           return undef;
95             }
96            
97             #sub _traverse_tree_downwards {}
98             #
99             #sub _traverse_tree_sideways {}
100            
101             sub _traverse_tree_upwards_recursively {
102 0     0     my ($self, $current_node) = @_;
103 0 0         return undef if $self->_get_depth() < 1;
104 0           my $parent_node = $current_node->{parentNode};
105 0           my $sibling_of_parent = $parent_node->{nextSibling};
106            
107 0           $self->_decrement_depth();
108 0 0         if ($sibling_of_parent) {
109 0           return $sibling_of_parent;
110             } else {
111 0           return $self->_traverse_tree_upwards_recursively($parent_node);
112             }
113             }
114            
115             1;
116            
117             __END__