File Coverage

blib/lib/Medical/OPCS4/Parser.pm
Criterion Covered Total %
statement 44 44 100.0
branch 5 6 83.3
condition 1 2 50.0
subroutine 9 9 100.0
pod 3 3 100.0
total 62 64 96.8


line stmt bran cond sub pod time code
1 1     1   5 use strict;
  1         2  
  1         42  
2 1     1   5 use warnings;
  1         2  
  1         46  
3              
4             package Medical::OPCS4::Parser;
5             # ABSTRACT: A parser object.
6              
7 1     1   1029 use Text::CSV;
  1         19251  
  1         7  
8 1     1   988 use Medical::OPCS4::Graph;
  1         4  
  1         496  
9              
10             =head1 NAME
11              
12             Medical::OPCS4::Parser - OPCS4 Parser object
13              
14             =head1 METHODS
15              
16             =head2 new
17              
18             Create a new parser object.
19            
20             Do not use directly.
21              
22             =cut
23              
24             sub new {
25 1     1 1 3 my $class = shift;
26 1         3 my $self = { };
27            
28 1         12 $self->{csv} =
29             Text::CSV->new({ 'sep_char' => "," });
30            
31 1         126 $self->{csv}->column_names( qw( opcs description) );
32            
33 1         52 $self->{g} =
34             Medical::OPCS4::Graph->new;
35            
36 1         6 return bless $self, $class;
37            
38             }
39              
40             =head2 parse
41              
42             The main parser function. Accepts a tab separated file of OPCS4 codes
43             along with their descriptions and parses it.
44              
45             Returns true on success and undef on failure.
46              
47             =cut
48              
49             sub parse {
50 1     1 1 27 my $self = shift;
51 1         3 my $filename = shift;
52            
53 1   50 1   11 open my $io, "<:encoding(utf8)", $filename
  1         2  
  1         10  
  1         39  
54             || die "$filename: $!";
55              
56             ##
57             ## First pass: add all the nodes
58            
59 1         16418 while ( my $rh = $self->{csv}->getline_hr( $io) ) {
60 5         13183 my $opcs = $rh->{opcs};
61 5         26 $self->{g}->add_vertex( $rh->{opcs} );
62 5         415 $self->{g}->set_vertex_attribute( $rh->{opcs}, 'description', $rh->{description} );
63             }
64            
65             ##
66             ## Second pass: add all the edges
67            
68 1         329 my @vertices = $self->{g}->vertices;
69            
70 1         100 foreach my $vertex ( @vertices ) {
71 6         936 my $parent = $self->_get_parent( $vertex );
72 6         26 $self->{g}->add_edge( $parent, $vertex );
73             }
74              
75 1         202 return $self->{g};
76            
77             }
78              
79             =head2 _get_parent
80              
81             Internal parser function used to discover the parent
82             of each node.
83            
84             Do not use directly.
85              
86             =cut
87              
88             sub _get_parent {
89 6     6   7 my $self = shift;
90 6         11 my $term = shift;
91              
92 6 100       16 if ( $term eq 'root' ) {
93 1         3 return 'root';
94             }
95              
96 5         9 my $length = length( $term );
97            
98 5 100       11 if ( $length == 3 ) {
99 1         3 return 'root'
100             }
101            
102 4 50       54 if ( $term =~ m/\./ ) {
103 4         16 return substr( $term, 0, ( index $term, '.') );
104             }
105            
106             }
107              
108             =head2 graph
109              
110             Returns the internal Medical::OPCS4::Graph object.
111              
112             =cut
113              
114             sub graph {
115 32     32 1 39 my $self = shift;
116 32         130 return $self->{g};
117             }
118              
119             1;