File Coverage

blib/lib/XML/Filter/Distributor.pm
Criterion Covered Total %
statement 65 71 91.5
branch 8 10 80.0
condition 5 12 41.6
subroutine 12 14 85.7
pod 5 7 71.4
total 95 114 83.3


line stmt bran cond sub pod time code
1             package XML::Filter::Distributor;
2             {
3             $XML::Filter::Distributor::VERSION = '0.46';
4             }
5             # ABSTRACT: Multipass processing of documents
6              
7              
8 4     4   6035 use XML::SAX::Base;
  4         89351  
  4         75  
9              
10             @ISA = qw( XML::SAX::Base );
11              
12              
13             @EXPORT_OK = qw( Distributor );
14              
15 4     4   249 use strict;
  4         13  
  4         163  
16 4     4   24 use Carp;
  4         9  
  4         364  
17 4     4   24 use XML::SAX::EventMethodMaker qw( sax_event_names missing_methods compile_methods );
  4         9  
  4         3050  
18              
19              
20             sub new {
21 4     4 1 9 my $proto = shift;
22 4   33     29 my $class = ref $proto || $proto;
23 4         22 my $self = bless {}, $class;
24              
25 4         33 $self->{Channels} = [];
26              
27 4         16 for ( @_ ) {
28 4         7 push @{$self->{Channels}}, $_;
  4         11  
29             }
30              
31 4         14 return $self;
32             }
33              
34              
35             sub set_handlers {
36 0     0 1 0 my $self = shift;
37 0         0 @{$self->{Channels}} = map { { Handler => $_ } } @_;
  0         0  
  0         0  
38             }
39              
40              
41             sub set_handler {
42 0     0 1 0 shift()->set_handlers( @_ );
43             }
44              
45              
46             sub _buffer {
47 18     18   28 my $self = shift;
48 18         22 push @{$self->{BUFFER}}, [ @_ ];
  18         563  
49             }
50              
51             sub set_aggregator {
52 4     4 0 8 my $self = shift;
53 4         22 $self->{Aggregator} = shift;
54             }
55              
56              
57             sub get_aggregator {
58 4     4 0 7 my $self = shift;
59              
60 4         12 return $self->{Aggregator};
61             }
62              
63              
64             sub _change_channels {
65 6     6   12 my $self = shift;
66              
67 6         13 my ( $desired_channel ) = @_;
68 6 100       29 $desired_channel = $self->{CurChannelNum} + 1
69             unless defined $desired_channel;
70 6         34 $desired_channel = undef
71 6 100 66     27 if $desired_channel < 0 || $desired_channel > $#{$self->{Channels}};
72              
73             ## Mess with XML::SAX::Base's internals a bit (ugh).
74             ## TODO: Get less messy when the X::S::B in CVS makes it in to the
75             ## real world.
76 6         16 $self->{Methods} = {};
77 6         66 $self->{Handler} = undef;
78              
79 6 100       17 if ( defined $desired_channel ) {
80 4         13 $self->{CurChannel} = $self->{Channels}->[$desired_channel];
81 4         27 $self->{$_} = $self->{CurChannel}->{$_}
82 4         8 for keys %{$self->{CurChannel}};
83             }
84              
85 6         18 $self->{CurChannelNum} = $desired_channel;
86 6         22 return $desired_channel;
87             }
88              
89              
90             sub _replay {
91 2     2   7 my $self = shift;
92              
93 2         7 my $r;
94 2         4 for ( @{$self->{BUFFER}} ) {
  2         8  
95 16         33 my $event = shift @$_;
96             ## This is ugly, must be a faster way, too tired to think of one.
97 16         29 my $meth = "SUPER::$event";
98 16         63 $self->$meth( @$_ );
99 16         205 unshift @$_, $event;
100             }
101              
102 2         10 return $r;
103             }
104              
105              
106             sub start_document {
107 2     2 1 151 my $self = shift;
108              
109 2         12 @{$self->{BUFFER}} = ();
  2         84  
110 2         10 $self->_buffer( "start_document", @_ );
111              
112 2         10 $self->_change_channels( 0 );
113              
114 2         11 my $aggie = $self->get_aggregator;
115 2 50 33     48 $aggie->start_manifold_document( @_ )
116             if $aggie && $aggie->can( "start_manifold_document" );
117              
118 2         29 return $self->SUPER::start_document( @_ );
119             }
120              
121              
122             sub end_document {
123 2     2 1 136 my $self = shift;
124              
125 2         7 $self->_buffer( "end_document", @_ );
126              
127 2         27 $self->SUPER::end_document( @_ );
128              
129 2         9 $self->_replay
130             while $self->_change_channels;
131            
132 2         5 @{$self->{BUFFER}} = ();
  2         19  
133              
134 2         10 my $aggie = $self->get_aggregator;
135 2 50 33     29 return $aggie->end_manifold_document( @_ )
136             if $aggie && $aggie->can( "end_manifold_document" );
137              
138 0           return ;
139             }
140              
141             compile_methods __PACKAGE__, <<'TPL_END', missing_methods __PACKAGE__, sax_event_names ;
142             sub {
143             my $self = shift;
144             $self->_buffer( "", @_ );
145             return $self->SUPER::( @_ );
146             }
147             TPL_END
148              
149              
150              
151              
152              
153             1;
154              
155             __END__