File Coverage

blib/lib/XML/CompareML/Base.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             package XML::CompareML::Base;
2              
3 1     1   21480 use strict;
  1         2  
  1         28  
4 1     1   5 use warnings;
  1         2  
  1         31  
5              
6             =head1 NAME
7              
8             XML::CompareML::Base - base class for the CompareML-to-something converters.
9              
10             =head1 SYNOPSIS
11              
12             see L.
13              
14             =head1 METHODS
15              
16             =head2 new()
17              
18             A constructor - should be used by a derived class.
19              
20             =head2 $compare->process()
21              
22             See L
23             =cut
24              
25 1     1   432 use XML::LibXML;
  0            
  0            
26              
27             use XML::CompareML::DTD::Generate;
28              
29             use base qw(Class::Accessor);
30              
31             __PACKAGE__->mk_accessors(
32             qw(_timestamp root_elem impls_indexes impls_names),
33             qw(parser dom),
34             );
35              
36             sub new
37             {
38             my $class = shift;
39             my $self = {};
40             bless $self, $class;
41             $self->_initialize(@_);
42             return $self;
43             }
44              
45             sub _findnodes
46             {
47             my $self = shift;
48             return $self->root_elem->findnodes(@_);
49             }
50              
51             sub _xml_node_contents_to_string
52             {
53             my $self = shift;
54             my $node = shift;
55             my @child_nodes = $node->childNodes();
56             my $ret = join("", map { $_->toString() } @child_nodes);
57             # Remove leading and trailing space.
58             $ret =~ s!^\s+!!mg;
59             $ret =~ s/\s+$//mg;
60             return $ret;
61             }
62              
63             sub _impl_get_tag_text
64             {
65             my $self = shift;
66             my $impl_elem = shift;
67             my $tag = shift;
68             my ($name_elem) = $impl_elem->getChildrenByTagName($tag);
69             if (!defined($name_elem))
70             {
71             return;
72             }
73             return $self->_xml_node_contents_to_string($name_elem);
74             }
75              
76             sub _impl_get_name
77             {
78             my $self = shift;
79             my $impl_elem = shift;
80             return $self->_impl_get_tag_text($impl_elem, "name");
81             }
82              
83             sub _get_implementations
84             {
85             my $self = shift;
86             return
87             [
88             map
89             {
90             +{
91             'id' => $_->getAttribute("id"),
92             'name' => $self->_impl_get_name($_)
93             }
94             }
95             $self->_findnodes("/comparison/meta/implementations/impl")
96             ];
97             }
98              
99             sub _get_timestamp
100             {
101             my $self = shift;
102             my @nodes = $self->_findnodes("/comparison/meta/timestamp");
103             if (@nodes)
104             {
105             return $self->_xml_node_contents_to_string($nodes[0]);
106             }
107             else
108             {
109             return undef;
110             }
111             }
112              
113             sub _initialize
114             {
115             my $self = shift;
116             my %args = (@_);
117             my $parser;
118             my $dom;
119             if ($args{input_filename})
120             {
121             $parser = XML::LibXML->new();
122             $parser->validation(0);
123             $dom = $parser->parse_file($args{input_filename});
124             my $dtd =
125             XML::LibXML::Dtd->parse_string(
126             XML::CompareML::DTD::Generate::get_dtd()
127             );
128             $dom->validate($dtd);
129             }
130             else
131             {
132             die "input_filename must be specified!";
133             }
134             if ($args{output_handle})
135             {
136             $self->{o} = $args{output_handle};
137             }
138             else
139             {
140             die "output_handle must be specified!";
141             }
142             $self->parser($parser);
143             $self->dom($dom);
144             $self->root_elem($dom->getDocumentElement());
145             }
146              
147             sub process
148             {
149             my $self = shift;
150              
151             my ($contents_elem) = $self->root_elem->getChildrenByTagName("contents");
152             my ($top_section_elem) = $contents_elem->getChildrenByTagName("section");
153              
154             my @impls = @{$self->_get_implementations()};
155              
156             $self->{impls} = \@impls;
157             $self->impls_indexes(+{ map { $impls[$_]->{'id'} => $_ } (0 .. $#impls) });
158             $self->impls_names(+{map { $_->{'id'} => $_->{'name'} } @impls });
159             $self->_timestamp($self->_get_timestamp());
160              
161             $self->{document_text} = "";
162             $self->{toc_text} = "";
163              
164             # Make sure we print anything only when we finished extracting all
165             # the meta-data.
166             $self->_print_header();
167              
168             $self->_start_rendering();
169              
170             $self->_render_section('elem' => $top_section_elem, 'depth' => 0,);
171              
172             $self->_finish_rendering();
173              
174             print {*{$self->{o}}} $self->{document_text};
175              
176             $self->_print_footer();
177             }
178              
179             sub _name
180             {
181             my $self = shift;
182             my $id = shift;
183             return $self->impls_names->{$id};
184             }
185              
186             sub _sorter
187             {
188             my $self = shift;
189             my $impl = shift;
190              
191             my $indexes = $self->impls_indexes();
192              
193             if (!exists($indexes->{$impl}))
194             {
195             die "Unknown system $impl";
196             }
197             return $indexes->{$impl};
198             }
199              
200             sub _out
201             {
202             my $self = shift;
203             $self->{document_text} .= join("", @_);
204             }
205              
206             sub _toc_out
207             {
208             my $self = shift;
209             $self->{toc_text} .= join("", @_);
210             }
211              
212             sub _render_section
213             {
214             my $self = shift;
215             my %args = (@_);
216             my $section_elem = $args{elem};
217             my $depth = $args{depth} || 0;
218              
219             my ($expl) = $section_elem->getChildrenByTagName("expl");
220             my ($title) = $section_elem->getChildrenByTagName("title");
221             my ($compare) = $section_elem->getChildrenByTagName("compare");
222             my @sub_sections = $section_elem->getChildrenByTagName("section");
223              
224             my $title_string = $title->string_value();
225              
226             my $id = $section_elem->getAttribute("id");
227              
228             my @args = (
229             'depth' => $depth,
230             'id' => $id,
231             'title_string' => $title_string,
232             'expl' => $expl,
233             'sub_sections' => \@sub_sections,
234             );
235              
236             $self->_render_section_start(
237             @args
238             );
239              
240             if ($compare)
241             {
242             $self->_render_sys_table_start(@args);
243              
244             my @systems = ($compare->getChildrenByTagName("s"));
245             my %kv =
246             (map
247             { $_->getAttribute("id") => $self->_render_s_elem($_) }
248             @systems
249             );
250             my @keys_sorted = (sort { $self->_sorter($a) <=> $self->_sorter($b) } keys(%kv));
251             foreach my $k (@keys_sorted)
252             {
253             $self->_render_sys_table_row(
254             'name' => $self->_name($k),
255             'desc' => $kv{$k},
256             );
257             }
258             $self->_render_sys_table_end();
259             }
260              
261             foreach my $sub (@sub_sections)
262             {
263             $self->_render_section(
264             'elem' => $sub,
265             'depth' => ($depth+1)
266             );
267             }
268              
269             $self->_render_section_end(
270             @args,
271             );
272             }
273              
274             =head1 AUTHOR
275              
276             Shlomi Fish, L.
277              
278             =head1 SEE ALSO
279              
280             L
281              
282             =head1 COPYRIGHT AND LICENSE
283              
284             Copyright 2004, Shlomi Fish. All rights reserved.
285              
286             You can use, modify and distribute this module under the terms of the MIT X11
287             license. ( L ).
288              
289             =cut
290              
291             1;