]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/src/extras/marc_tooltips_to_sql
lp1777675 inventory date support
[working/Evergreen.git] / Open-ILS / src / extras / marc_tooltips_to_sql
1 #!/usr/bin/perl
2
3 # Copyright (C) 2015 Equinox Software, Inc.
4 #
5 # Initial author: Galen Charlton <gmc@esilibrary.com>
6 #
7 # This program is free software; you can redistribute it and/or
8 # modify it under the terms of the GNU General Public License
9 # as published by the Free Software Foundation; either version 2
10 # of the License, or (at your option) any later version.
11 #
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 # GNU General Public License for more details.
16 #
17
18 # Utility to convert a MARC tooltips XML file to an SQL script
19 # containing inserts into config.marc_field, config.marc_subfield,
20 # and, for indicator value lists, config.record_attr_definition
21 # and config.coded_value_map.
22
23 use strict;
24 use warnings;
25
26 use Error qw/:try/;
27 use Getopt::Long;
28 use XML::LibXML;
29
30 my ($infile, $outfile);
31 my $marctype = 'biblio';
32
33 GetOptions(
34     'input:s'   => \$infile,
35     'output:s'  => \$outfile,
36     'type:s'    => \$marctype,
37 );
38
39 unless(defined($infile) && defined($outfile)) {
40     print "Must specify an input file and an output file.\n\n";
41     print_usage();
42     exit 1;
43 }
44
45 unless($marctype eq 'biblio' or $marctype eq 'authority' or $marctype eq 'serial') {
46     print "Must specify a MARC type of 'biblio', 'authority', or 'serial'.\n\n";
47     print_usage();
48     exit 1;
49 }
50
51 open my $OUT, '>', $outfile or die "Cannot open output file $outfile: $!\n";
52 binmode $OUT, ':utf8';
53
54 open my $IN, '<', $infile or die "Cannot open input file $infile: $!\n";
55 binmode $IN; # per XML::LibXML doc, drop all PerlIO layers
56 my $xml;
57 try {
58     $xml = XML::LibXML->load_xml(IO => $IN);
59     close $IN;
60 } catch Error with {
61     my $e = shift;
62     print "Failed to parse MARC tooltips file $infile: $e\n";
63     exit 1;
64 };
65
66 emit_sql($xml, $OUT, $marctype);
67
68 close $OUT;
69
70 exit 0;
71
72 sub print_usage {
73     print <<_USAGE_;
74 Usage: $0 \\
75           --input /path/to/marcedit-tooltips.xml \\
76           --outfile output.sql \\
77           [--type {biblio,authority,serial}]
78 _USAGE_
79 }
80
81 sub emit_sql {
82     my ($xml, $OUT, $marctype) = @_;
83
84     my $seen = {};
85     my @fields = $xml->findnodes('//field');
86     foreach my $field (@fields) {
87         emit_field_sql($field, $OUT, $marctype, $seen);
88     }
89     
90 }
91
92 sub emit_field_sql {
93     my ($field, $OUT, $marctype, $seen) = @_;
94
95     my $name = $field->find('name/text()');
96     my $description = $field->find('description/text()');
97     my $tag = $field->getAttribute('tag');
98     if ($tag !~ /^\d\d\d$/) {
99         print STDERR "Warning: tag $tag is not as expected; skipping.\n";
100         return;
101     }
102     my $ff = $tag lt '010' ? 'TRUE' : 'FALSE';
103     my $repeatable = uc($field->getAttribute('repeatable'));
104     print $OUT <<_FIELD_;
105 INSERT INTO config.marc_field(marc_format, marc_record_type, tag, name, description,
106                               fixed_field, repeatable, mandatory, hidden)
107 VALUES (1, '$marctype', '$tag', \$\$$name\$\$, \$\$$description\$\$,
108 $ff, $repeatable, FALSE, FALSE);
109 _FIELD_
110
111     if (exists $seen->{$tag}) {
112         print STDERR "Warning: we've already seen $tag; skipping.\n";
113         return;
114     } else {
115         $seen->{$tag}++;
116     }
117     if ($ff eq 'FALSE') {
118         emit_indicator_sql($tag, $field, $OUT, $marctype, $seen);
119         emit_subfield_sql($tag, $field, $OUT, $marctype, $seen);
120     }
121 }
122
123 sub emit_indicator_sql {
124     my ($tag, $field, $OUT, $marctype, $seen) = @_;
125
126     my %indvalues = ();
127     my @inds = $field->findnodes('indicator');
128     foreach my $ind (@inds) {
129         my $position = $ind->getAttribute('position');
130         my $value    = $ind->getAttribute('value');
131         my $description = $ind->find('description/text()');
132         if ($position ne '1' and $position ne '2') {
133             print STDERR "Warning: indicator position $position for tag $tag is not expected. Skipping.\n";
134             next;
135         }
136         if (length($value) != 1) {
137             print STDERR "Warning: value $value for indicator $tag.$position is not expected. Skipping.\n";
138             next;
139         }
140         $indvalues{$position}->{$value} = $description;
141     }
142
143     foreach my $pos (sort keys %indvalues) {
144         my $ctype = "marc21_${marctype}_${tag}_ind_${pos}";
145         print $OUT <<_ATTR_;
146 INSERT INTO config.record_attr_definition(name, label)
147 VALUES ('$ctype', 'MARC 21 $marctype field $tag indicator position $pos');
148 _ATTR_
149         foreach my $code (sort keys %{ $indvalues{$pos} }) {
150             my $value = $indvalues{$pos}->{$code};
151             print $OUT <<_IND_;
152 INSERT INTO config.coded_value_map(ctype, code, value, opac_visible, is_simple)
153 VALUES ('$ctype', '$code', \$\$$value\$\$, FALSE, TRUE);
154 _IND_
155         }
156     }
157 }
158
159 sub emit_subfield_sql {
160     my ($tag, $field, $OUT, $marctype, $seen) = @_;
161     
162     my @subfields = $field->findnodes('subfield');
163     foreach my $subfield (@subfields) {
164         my $code = $subfield->getAttribute('code');
165         if (exists $seen->{"$tag-$code"}) {
166             print STDERR "Warning: we've already seen $tag\$$code; skipping.\n";
167             return;
168         } else {
169             $seen->{"$tag-$code"}++;
170         }
171         my $description = $subfield->find('description/text()');
172         my $repeatable = uc($subfield->getAttribute('repeatable'));
173         print $OUT <<_SUBFIELD_;
174 INSERT INTO config.marc_subfield(marc_format, marc_record_type, tag, code, description,
175                                  repeatable, mandatory, hidden)
176 VALUES (1, '$marctype', '$tag', '$code', \$\$$description\$\$,
177 $repeatable, FALSE, FALSE);
178 _SUBFIELD_
179     }
180 }