]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/perlmods/OpenILS/WWW/Exporter.pm
more debugging
[Evergreen.git] / Open-ILS / src / perlmods / OpenILS / WWW / Exporter.pm
1 package OpenILS::WWW::Exporter;
2 use strict;
3 use warnings;
4 use bytes;
5
6 use Apache2::Log;
7 use Apache2::Const -compile => qw(OK REDIRECT DECLINED NOT_FOUND :log);
8 use APR::Const    -compile => qw(:error SUCCESS);
9 use APR::Table;
10
11 use Apache2::RequestRec ();
12 use Apache2::RequestIO ();
13 use Apache2::RequestUtil;
14 use CGI;
15 use Data::Dumper;
16 use Text::CSV;
17
18 use OpenSRF::EX qw(:try);
19 use OpenSRF::Utils qw/:datetime/;
20 use OpenSRF::Utils::Cache;
21 use OpenSRF::System;
22 use OpenSRF::AppSession;
23 use XML::LibXML;
24 use XML::LibXSLT;
25
26 use Encode;
27 use Unicode::Normalize;
28 use OpenILS::Utils::Fieldmapper;
29 use OpenSRF::Utils::Logger qw/$logger/;
30
31 use MARC::Record;
32 use MARC::File::XML;
33
34 use UNIVERSAL::require;
35
36 our @formats = qw/USMARC UNIMARC XML BRE/;
37
38 # set the bootstrap config and template include directory when
39 # this module is loaded
40 my $bootstrap;
41
42 sub import {
43         my $self = shift;
44         $bootstrap = shift;
45 }
46
47
48 sub child_init {
49         OpenSRF::System->bootstrap_client( config_file => $bootstrap );
50 }
51
52 sub handler {
53         my $r = shift;
54         my $cgi = new CGI;
55
56         # find some IDs ...
57         my @records;
58
59         @records = $cgi->param('id');
60
61         if (!@records) { # try for a file
62                 my $file = $cgi->param('idfile');
63                 if ($file) {
64                         warn "FILE $file";
65                         my $col = $cgi->param('idcolumn') || 0;
66                         my $csv = new Text::CSV;
67
68                         while (<$file>) {
69                                 chomp;
70                                 warn "LINE $_";
71                                 $csv->parse($_);
72                                 my @data = $csv->fields;
73                                 my $id = $data[$col];
74                                 warn "ID $id";
75                                 $id =~ s/\D+//o;
76                                 next unless ($id);
77                                 push @records, $id;
78                         }
79                 }
80         }
81
82         if (!@records) { # try pathinfo
83                 my $path_rec = $cgi->path_info();
84                 if ($path_rec) {
85                         @records = map { $_ ? ($_) : () } split '/', $path_rec;
86                 }
87         }
88
89         return show_template($r) unless (@records);
90
91         my $type = $cgi->param('rectype') || 'biblio';
92         if ($type ne 'biblio' && $type ne 'authority') {
93                 die "Bad record type: $type";
94         }
95
96         my $tcn_v = 'tcn_value';
97         my $tcn_s = 'tcn_source';
98
99         if ($type eq 'authority') {
100                 $tcn_v = 'arn_value';
101                 $tcn_s = 'arn_source';
102         }
103
104         my $holdings = $cgi->param('holdings') if ($type eq 'biblio');
105         my $location = $cgi->param('location') || 'gaaagpl'; # just because...
106
107         my $format = $cgi->param('format') || 'USMARC';
108         $format = uc($format);
109
110         my $encoding = $cgi->param('encoding') || 'UTF-8';
111         $encoding = uc($encoding);
112
113         my $filename = $cgi->param('filename') || "export.$type.$encoding.$format";
114
115         binmode(STDOUT, ':raw') if ($encoding ne 'UTF-8');
116         binmode(STDOUT, ':utf8') if ($encoding eq 'UTF-8');
117
118         if (!grep { uc($format) eq $_ } @formats) {
119                 die     "Please select a supported format.  ".
120                         "Right now that means one of [".
121                         join('|',@formats). "]\n";
122         }
123
124         if ($format ne 'XML') {
125                 my $ftype = 'MARC::File::' . $format;
126                 $ftype->require;
127         }
128
129         my $ses = OpenSRF::AppSession->create('open-ils.cstore');
130
131         $r->headers_out->set("Content-Disposition" => "inline; filename=$filename");
132
133         if (uc($format) eq 'XML') {
134                 $r->content_type('application/xml');
135         } else {
136                 $r->content_type('application/octet-stream');
137         }
138
139         $r->print( <<"  HEADER" ) if (uc($format) eq 'XML');
140 <?xml version="1.0" encoding="$encoding"?>
141 <collection xmlns='http://www.loc.gov/MARC21/slim'>
142         HEADER
143
144         my %orgs;
145         my %shelves;
146
147         my $flesh = {};
148         if ($holdings) {
149
150                 my $req = $ses->request( 'open-ils.cstore.direct.actor.org_unit.search', { id => { '!=' => undef } } );
151
152                 while (my $o = $req->recv) {
153                         die $req->failed->stringify if ($req->failed);
154                         $o = $o->content;
155                         last unless ($o);
156                         $orgs{$o->id} = $o;
157                 }
158                 $req->finish;
159
160                 $req = $ses->request( 'open-ils.cstore.direct.asset.copy_location.search', { id => { '!=' => undef } } );
161
162                 while (my $s = $req->recv) {
163                         die $req->failed->stringify if ($req->failed);
164                         $s = $s->content;
165                         last unless ($s);
166                         $shelves{$s->id} = $s;
167                 }
168                 $req->finish;
169
170                 $flesh = { flesh => 2, flesh_fields => { bre => [ 'call_numbers' ], acn => [ 'copies' ] } };
171         }
172
173         for my $i ( @records ) {
174                 my $bib;
175                 try {
176                         local $SIG{ALRM} = sub { die "TIMEOUT\n" };
177                         alarm(1);
178                         $bib = $ses->request( "open-ils.cstore.direct.$type.record_entry.retrieve", $i, $flesh )->gather(1);
179                         alarm(0);
180                 } otherwise {
181                         warn "\n!!!!!! Timed out trying to read record $i\n";
182                 };
183                 alarm(0);
184
185                 next unless $bib;
186
187                 if (uc($format) eq 'BRE') {
188                         $r->print( OpenSRF::Utils::JSON->perl2JSON($bib) );
189                         next;
190                 }
191
192                 try {
193
194                         my $req = MARC::Record->new_from_xml( $bib->marc, $encoding, $format );
195                         $req->delete_field( $_ ) for ($req->field(901));
196
197                         $req->append_fields(
198                                 MARC::Field->new(
199                                         901, '', '', 
200                                         a => $bib->$tcn_v,
201                                         b => $bib->$tcn_s,
202                                         c => $bib->id
203                                 )
204                         );
205
206
207                         if ($holdings) {
208                                 my $cn_list = $bib->call_numbers;
209                                 if ($cn_list && @$cn_list) {
210
211                                         my $cp_list = [ map { @{ $_->copies } } @$cn_list ];
212                                         if ($cp_list && @$cp_list) {
213
214                                                 my %cn_map;
215                                                 push @{$cn_map{$_->call_number}}, $_ for (@$cp_list);
216                                         
217                                                 for my $cn ( @$cn_list ) {
218                                                         my $cn_map_list = $cn_map{$cn->id};
219         
220                                                         for my $cp ( @$cn_map_list ) {
221                                         
222                                                                 $req->append_fields(
223                                                                         MARC::Field->new(
224                                                                                 852, '4', '', 
225                                                                                 a => $location,
226                                                                                 b => $orgs{$cn->owning_lib}->shortname,
227                                                                                 b => $orgs{$cp->circ_lib}->shortname,
228                                                                                 c => $shelves{$cp->location}->name,
229                                                                                 j => $cn->label,
230                                                                                 ($cp->circ_modifier ? ( g => $cp->circ_modifier ) : ()),
231                                                                                 p => $cp->barcode,
232                                                                                 ($cp->price ? ( y => $cp->price ) : ()),
233                                                                                 ($cp->copy_number ? ( t => $cp->copy_number ) : ()),
234                                                                                 ($cp->ref eq 't' ? ( x => 'reference' ) : ()),
235                                                                                 ($cp->holdable eq 'f' ? ( x => 'unholdable' ) : ()),
236                                                                                 ($cp->circulate eq 'f' ? ( x => 'noncirculating' ) : ()),
237                                                                                 ($cp->opac_visible eq 'f' ? ( x => 'hidden' ) : ()),
238                                                                         )
239                                                                 );
240
241                                                         }
242                                                 }
243                                         }
244                                 }
245                         }
246
247                         if (uc($format) eq 'XML') {
248                                 my $x = $req->as_xml_record;
249                                 $x =~ s/^<\?xml version="1.0" encoding="UTF-8"\?>//o;
250                                 $r->print($x);
251                         } elsif (uc($format) eq 'UNIMARC') {
252                                 $r->print($req->as_unimarc);
253                         } elsif (uc($format) eq 'USMARC') {
254                                 $r->print($req->as_usmarc);
255                         }
256
257                 } otherwise {
258                         my $e = shift;
259                         warn "\n$e\n";
260                 };
261
262         }
263
264         $r->print("</collection>\n") if ($format eq 'XML');
265
266         return Apache2::Const::OK;
267
268 }
269
270 sub show_template {
271         my $r = shift;
272
273         $r->content_type('text/html');
274         $r->print(<<HTML);
275
276 <html>
277         <head>
278                 <title>Record Export</title>
279         </head>
280         <body>
281                 <form method="POST" enctype="multipart/form-data">
282                         Use field number <input type="text" size="2" maxlength="2" name="idcolumn" value="0"/> (starting from 0)
283                         from CSV file <input type="file" name="idfile"/>
284                         <br/><br/> <b>or</b> <br/><br/>
285                         Record ID <input type="text" size="12" maxlength="12" name="id"/>
286                         <br/><br/> Record Type:
287                         <select name="type">
288                                 <option value="biblio">Bibliographic Records</option>
289                                 <option value="authority">Authority Records</option>
290                         </select>
291                         <br/> Record Fromat:
292                         <select name="format">
293                                 <option value="USMARC">MARC21</option>
294                                 <option value="UNIMARC">UNIMARC</option>
295                                 <option value="XML">MARC XML</option>
296                                 <option value="BRE">Evergreen BRE</option>
297                         </select>
298                         <br/> Record Encoding:
299                         <select name="encoding">
300                                 <option value="UTF-8">UTF-8</option>
301                                 <option value="MARC8">MARC8</option>
302                         </select>
303                         <br/> Include holdings in Bibliographic Records:
304                         <input type="checkbox" name="holdings" value="1">
305                         <br/><br/><input type="submit" value="Retrieve Records"/>
306                 </form>
307         </body>
308 </html>
309
310 HTML
311
312         return Apache2::Const::OK;
313 }
314
315 1;