File Coverage

blib/lib/Religion/Bible/Regex/Versification.pm
Criterion Covered Total %
statement 10 12 83.3
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 14 16 87.5


line stmt bran cond sub pod time code
1             package Religion::Bible::Regex::Versification;
2              
3 1     1   22331 use warnings;
  1         3  
  1         30  
4 1     1   7 use strict;
  1         1  
  1         33  
5 1     1   5 use Carp;
  1         7  
  1         91  
6              
7 1     1   421 use Religion::Bible::Regex::Reference;
  0            
  0            
8              
9             use version; our $VERSION = '0.2';
10              
11             # There are four way to initialize a versification map
12             # 1. Pass in a string representing the location of a versification file
13             # 2. Pass in an array of verse pairs. Ex. [['Ge 1:1', 'Ge 1:2']]
14             # 3. Pass in a hash of vers pairs. Ex. { 'Ge 1:1' => 'Ge 1:2' }
15             # 4. Put the versification map in the YAML configuration file
16             sub new {
17             my ($class, $config, $regex, $versification_file) = @_;
18             my ($self) = {};
19             bless $self, $class;
20              
21             $self->{config} = $config or confess 'Versification requires a Religion::Bible::Regex::Config object';
22             $self->{regex} = $regex or confess 'Versification requires a Religion::Bible::Regex::Builder object';
23              
24             # is the versification map defined in the config object?
25             if (defined($config->get_versification_configurations)) {
26             # Build the versification map from the configuration object
27             $self->{versification} = $self->normalize_map( $config->get_versification_configurations );
28              
29             # does $versification_file exist?
30             } elsif (-e $versification_file) {
31             # Build the versification map from a file
32             $self->{versification} = $self->normalize_map( $self->parse_versification_map($versification_file) );
33              
34             # if $versification_file is an array or hash
35             } elsif (ref($versification_file) eq 'HASH' || ref($versification_file) eq 'ARRAY') {
36             $self->{versification} = $self->normalize_map( $versification_file );
37             }
38              
39             return $self;
40             }
41              
42             # Subroutines related to getting information
43             sub get_regexes {
44             my $self = shift;
45             confess "regex is not defined\n" unless defined($self->{regex});
46             return $self->{regex};
47             }
48              
49             # Returns a reference to a Religion::Bible::Regex::Config object.
50             sub get_configuration {
51             my $self = shift;
52             confess "config is not defined\n" unless defined($self->{config});
53             return $self->{config};
54             }
55              
56             sub parse_versification_map {
57             my $self = shift;
58             my $config = $self->{config};
59             my $map = shift;
60             my $r1 = new Religion::Bible::Regex::Reference($self->get_configuration, $self->get_regexes);
61             my @versification_array;
62              
63             croak "Versification mapping is not defined\n" unless (defined($map));
64              
65             if (-e $map) {
66             open(my ($list), "<:encoding(UTF-8)", $self->{file}) || croak "Could not open versification mapping file, \'$self->{file})\': $!\n";
67              
68             while (<$list>) {
69             chomp; # no newline
70             s/[^\\]#.*//; # no comments si il y a un '\' devant le '#' il n'est pas un commentarie
71             s/^\s+//; # no leading white
72             s/\s+$//; # no trailing white
73             next unless length; # anything left?
74              
75             my ($key, $value) = split /,/;
76             push @versification_array, [$key, $value];
77             }
78             close ($list);
79             }
80              
81             return @versification_array;
82             }
83              
84              
85             sub normalize_map {
86             my $self = shift;
87             my $map = shift;
88             my %versification_map;
89            
90             # Create a reusable Reference Object
91             my $r1 = new Religion::Bible::Regex::Reference($self->get_configuration, $self->get_regexes);
92              
93             # versification_file is an array ... normalize it.
94             if ( ref($map) eq 'ARRAY' ) {
95             foreach my $c (@{$map}) {
96             my $r2 = new Religion::Bible::Regex::Reference($self->get_configuration, $self->get_regexes);
97             $r1->parse($c->[0]);
98             $r2->parse($c->[1]);
99             $versification_map{ $r1->normalize } = $r2;
100             }
101              
102             # versification_file is an array ... normalize it.
103             } elsif ( ref($map) eq 'HASH' ) {
104             while ( my ($key, $value) = each(%$map) ) {
105             my $r2 = new Religion::Bible::Regex::Reference($self->get_configuration, $self->get_regexes);
106             $r1->parse($key);
107             $r2->parse($value);
108             $versification_map{ $r1->normalize } = $r2;
109             }
110            
111             # carp
112             } else {
113             carp "versification_map must be either an array or a hash\n"
114             unless (ref($map) eq 'HASH' || ref($map) eq 'ARRAY');
115             }
116              
117             # if map is not a HASH or an ARRAY then an empty hash is returned
118             return \%versification_map;
119             }
120              
121             sub decalage {
122             my $self = shift;
123             my $reference = shift;
124              
125             # Versification can only be done for references with a book, chapter and verse
126             return $reference unless ($reference->is_explicit);
127              
128             # Since the versification files that we have only contain LCV style references
129             # If we have a references like Ps 3:1-9, where Ps 3:1 is not shifted, but Ps 3:9 is shifted
130             # then we must break it apart into Ps 3:1 and Ps 3:9, shift both references and recombine them
131             if ($reference->has_interval) {
132             my $r1 = $reference->begin_interval_reference;
133             my $r2 = $reference->end_interval_reference;
134              
135             my $dref1 = $self->decalage($r1);
136             my $dref2 = $self->decalage($r2);
137              
138             return $dref1->interval($dref2);
139             } else {
140             my $normalized_reference = $reference->normalize;
141             if (defined($self->{versification}->{$normalized_reference})) {
142             my $ref_decale = new Religion::Bible::Regex::Reference($self->get_configuration, $self->get_regexes);
143              
144             # Be sure to make a copy of the reference, otherwise changing the reference later would
145             # in the versification map
146             $ref_decale->{reference} = &Storable::dclone($self->{versification}->{$normalized_reference}->{reference});
147             $ref_decale->set_b($reference->ob);
148             $ref_decale->set_b2($reference->ob2);
149             return $ref_decale;
150             }
151             }
152             return $reference;
153             }
154              
155             1; # Magic true value required at end of module
156             __END__