File Coverage

blib/lib/XML/Filter/Sort/BufferMgr.pm
Criterion Covered Total %
statement 63 82 76.8
branch 14 26 53.8
condition 2 3 66.6
subroutine 10 10 100.0
pod 0 8 0.0
total 89 129 68.9


line stmt bran cond sub pod time code
1             # $Id: BufferMgr.pm,v 1.1.1.1 2002/06/14 20:40:05 grantm Exp $
2              
3             package XML::Filter::Sort::BufferMgr;
4              
5 2     2   162761 use strict;
  2         5  
  2         1142  
6              
7             require XML::Filter::Sort::Buffer;
8              
9              
10             ##############################################################################
11             # G L O B A L V A R I A B L E S
12             ##############################################################################
13              
14 2     2   14 use vars qw($VERSION);
  2         4  
  2         3459  
15              
16             $VERSION = '0.91';
17              
18              
19             ##############################################################################
20             # M E T H O D S
21             ##############################################################################
22              
23             ##############################################################################
24             # Constructor: new()
25             #
26             # Allocates in-memory structures for buffering records.
27             #
28              
29             sub new {
30 4     4 0 2172 my $proto = shift;
31              
32 4   66     27 my $class = ref($proto) || $proto;
33              
34 4         15 my $self = { @_ };
35 4         10 $self->{records} = {};
36            
37 4         23 return(bless($self, $class));
38             }
39              
40              
41             ##############################################################################
42             # Method: compile_matches()
43             #
44             # Returns a list of closures for matching each of the sort keys.
45             #
46              
47             sub compile_matches {
48 3     3 0 6 my $self = shift;
49              
50 3         14 return(XML::Filter::Sort::Buffer->compile_matches(@_));
51             }
52              
53              
54             ##############################################################################
55             # Method: new_buffer()
56             #
57             # Creates and returns an object for buffering a single record.
58             #
59              
60             sub new_buffer {
61 5     5 0 953 my $self = shift;
62              
63 5         32 my %opt = ( Keys => $self->{Keys} );
64 5 100       19 if($self->{_match_subs}) {
65 3         9 $opt{_match_subs} = [ @{$self->{_match_subs}} ];
  3         7  
66             }
67 5         42 return(XML::Filter::Sort::Buffer->new(%opt));
68             }
69              
70              
71             ##############################################################################
72             # Method: close_buffer()
73             #
74             # Takes a buffer, calls its close() method to get the sort key values, filters
75             # the key values and stores the buffer using those values.
76             #
77              
78             sub close_buffer {
79 5     5 0 16 my $self = shift;
80 5         6 my $record = shift;
81              
82 5         17 my @sort_keys = $record->close();
83              
84 5         16 @sort_keys = $self->fix_keys(@sort_keys);
85              
86 5         15 $self->store($record, @sort_keys);
87             }
88              
89              
90             ##############################################################################
91             # Method: fix_keys()
92             #
93             # Takes a list of sort key values and applies various fixes/cleanups to them.
94             #
95              
96             sub fix_keys {
97 5     5 0 10 my $self = shift;
98              
99 5         8 my @sort_keys = @_;
100              
101 5 50       14 if($self->{IgnoreCase}) {
102 0         0 @sort_keys = map { lc($_) } @sort_keys;
  0         0  
103             }
104              
105 5 50       18 if($self->{NormaliseKeySpace}) {
106 0         0 foreach (@sort_keys) {
107 0         0 s/^\s+//s;
108 0         0 s/\s+$//s;
109 0         0 s/\s+/ /sg;
110             }
111             }
112              
113 5 50       13 if($self->{KeyFilterSub}) {
114 0         0 @sort_keys = $self->{KeyFilterSub}->(@sort_keys);
115             }
116            
117 5         17 return(@sort_keys);
118             }
119              
120              
121             ##############################################################################
122             # Method: store()
123             #
124             # Takes a buffer, and a series of key values. Stores the buffer using those
125             # values.
126             #
127              
128             sub store {
129 6     6 0 8 my $self = shift;
130 6         8 my $record = shift;
131 6         8 my $key = shift;
132              
133 6 100       15 if(@_) {
134 1 50       4 unless($self->{records}->{$key}) {
135 1         2 my @key_defs = @{$self->{Keys}};
  1         4  
136 1         1 shift @key_defs;
137 1         4 $self->{records}->{$key} = $self->new(Keys => \@key_defs);
138             }
139 1         49 $self->{records}->{$key}->store($record, @_);
140             }
141             else {
142 5 50       23 unless($self->{records}->{$key}) {
143 5         19 $self->{records}->{$key} = [];
144             }
145 5         6 push @{$self->{records}->{$key}}, $record;
  5         25  
146             }
147              
148             }
149              
150              
151             ##############################################################################
152             # Method: to_sax()
153             #
154             # Takes a reference to the parent XML::Filter::Sort object. Cycles through
155             # each of the buffered records (in appropriate sorted sequence) and streams
156             # them out to the handler object as SAX events.
157             #
158              
159             sub to_sax {
160 4     4 0 5285 my $self = shift;
161 4         8 my $filter = shift;
162              
163 4         14 my $keys = $self->sorted_keys();
164              
165 4         10 foreach my $key (@$keys) {
166 6 100       29 if(ref($self->{records}->{$key}) eq 'ARRAY') {
167 5         7 foreach my $record (@{$self->{records}->{$key}}) {
  5         11  
168 5         23 $record->to_sax($filter);
169             }
170             }
171             else {
172 1         7 $self->{records}->{$key}->to_sax($filter);
173             }
174             }
175              
176             }
177              
178              
179             ##############################################################################
180             # Method: sorted_keys()
181             #
182             # Returns a reference to an array of all the sort keys in order.
183             #
184              
185             sub sorted_keys {
186 4     4 0 7 my $self = shift;
187              
188 4         9 my @keys = keys(%{$self->{records}});
  4         16  
189 4         12 my $cmp = $self->{Keys}->[0]->[1];
190 4         11 my $dir = $self->{Keys}->[0]->[2];
191              
192             # coderef sort comparator
193            
194 4 50       19 if(ref($cmp)) {
    50          
195 0 0       0 if($dir eq 'desc') {
196 0         0 @keys = sort { $cmp->($b, $a) } @keys;
  0         0  
197             }
198             else {
199 0         0 @keys = sort { $cmp->($a, $b) } @keys;
  0         0  
200             }
201             }
202              
203             # numeric comparator
204            
205             elsif($cmp eq 'num') {
206 0 0       0 if($dir eq 'desc') {
207 0         0 @keys = sort { $b <=> $a } @keys;
  0         0  
208             }
209             else {
210 0         0 @keys = sort { $a <=> $b } @keys;
  0         0  
211             }
212             }
213              
214             # alpha comparator (default)
215              
216             else {
217 4 50       21 if($dir eq 'desc') {
218 0         0 @keys = sort { $b cmp $a } @keys;
  0         0  
219             }
220             else {
221 4         14 @keys = sort { $a cmp $b } @keys;
  3         6  
222             }
223             }
224              
225 4         11 return(\@keys);
226              
227             }
228              
229              
230             1;
231              
232             __END__