1c9869d3d538166a78edb5eca42fa2e2dbbfb840
[Biblio-Z3950.git] / CROSBI.pm
1 package CROSBI;
2
3 use warnings;
4 use strict;
5
6 use MARC::Record;
7 use Data::Dump qw/dump/;
8 use DBI;
9 use utf8;
10
11 use base 'Scraper';
12
13 my $debug = $ENV{DEBUG} || 0;
14
15 sub diag {
16         warn "# ", @_, $/;
17 }
18
19
20 # Koha Z39.50 query:
21 #
22 # Bib-1 @and @and @and @and @and @and @and @or
23 # @attr 1=4 title 
24 # @attr 1=7 isbn
25 # @attr 1=8 issn 
26 # @attr 1=1003 author 
27 # @attr 1=16 dewey (godina)
28 # @attr 1=21 subject-holding 
29 # @attr 1=12 control-no 
30 # @attr 1=1007 standard-id 
31 # @attr 1=1016 any
32
33 sub usemap {{
34         4               => 'fti_pr:',
35         7               => 'fti_pr:',
36         8               => 'fti_pr:',
37         1003            => 'fti_au:',
38         16              => 'fti_pr:',
39         21              => 'fti_pr:',
40         12              => 'fti_pr:',
41         1007            => 'pti_pr:',
42         1016            => 'fti_au,fti_pr:',
43 }};
44
45 =for sql
46
47 =cut
48
49 my $dbname = 'bibliografija';
50
51 sub search {
52         my ( $self, $query ) = @_;
53
54         utf8::decode( $query );
55         warn "QUERY",dump( $query );
56
57         die "need query" unless defined $query;
58
59         my $table = lc $self->{database};
60         $table =~ s/^crosbi-//g;
61
62         my $sql = qq{
63
64 select *
65 from $table
66 inner join rad_ustanova using (id)
67 left outer join rad_napomena using (id)
68 left outer join rad_projekt using (id)
69 left outer join rad_godina using (id)
70 left outer join rad_podrucje using (id)
71 left outer join url using (id)
72         };
73
74         my @and = ( qq{ rad_ustanova.sifra = ? } );
75         my @exec =  ( 130 ); # FIXME ustanova
76
77         foreach my $and ( split(/ AND /, $query) ) {
78
79                 if ( $and =~ s/^(fti_.+):// ) {
80                         my $tsquery = join(' & ', split(/\s+/,$and) );
81
82                         my @or;
83                         foreach my $f ( split(/,/,$1) ) {
84                                 push @or, "$f @@ to_tsquery(?)";
85                                 push @exec, $tsquery;
86                         };
87                         push @and, "( " . join(" or ", @or) . ")";
88                 } else {
89                         warn "INVALID QUERY [$query]";
90                 }
91         }
92         $sql .= "where " . join(" and ", @and);
93
94 warn "XXX SQL = ",$sql, dump( @exec );
95
96         my $dbh = DBI->connect_cached("dbi:Pg:dbname=$dbname", '', '', {AutoCommit => 0});
97
98         my $sth = $dbh->prepare( $sql );
99
100         $sth->execute( @exec );
101
102         my $hits = $sth->rows;
103
104         $self->{_sth} = $sth;
105
106         warn "# [$query] $hits hits\n";
107
108         return $self->{hits} = $hits;
109 }
110
111 my $langrecode008 = {
112         'bugarski' => 'bul',
113         'Češki' => 'cze',
114         'češki' => 'cze',
115         'ENG' => 'eng',
116         'Esperanto' => 'epo',
117         'FRA' => 'fra',
118         'GER' => 'ger',
119         'HRV' => 'hrv',
120         'ITA' => 'ita',
121         'Japanski' => 'jpn',
122         'Latinski' => 'lat',
123         'mađarski' => 'hun',
124         'Madžarski' => 'hun',
125         'Makedonski' => 'mac',
126         'nizozemski' => 'dut',
127         'Poljski' => 'pol',
128         'poljski' => 'pol',
129         'Portugalski' => 'por',
130         'portugalski' => 'por',
131         'RUS' => 'rus',
132         'Rumunjski' => 'rum',
133         'rumunjski' => 'rum',
134         'rusinski' => 'sla',
135         'slovački' => 'slo',
136         'slovenski' => 'slv',
137         'SLV' => 'slv',
138         'SPA' => 'spa',
139         'Srpski' => 'srp',
140         'srpski' => 'srp',
141         'Turski' => 'tur',
142         'turski' => 'tur',
143         'ukrajinski' => 'ukr',
144         'HRV-ENG' => 'mul',
145         'HRV-GER' => 'mul',
146         'hrvatsko-francuski' => 'mul',
147 } ;
148
149 sub next_marc {
150         my ($self,$format) = @_;
151
152         $format ||= 'marc';
153
154         my $sth = $self->{_sth} || die "no _sth";
155
156         my $row = $sth->fetchrow_hashref;
157
158         die "no row" unless $row;
159
160         my $id = $row->{id} || die "no id";
161
162         my $marc = MARC::Record->new;
163         $marc->encoding('UTF-8');
164
165         my $leader = $marc->leader;
166
167 # /srv/webpac2/conf/crosbi/2016-12-12/casopis-dbi2marc.pl
168
169 ## LDR 05 - n - new
170 ## LDR 06 - a - language material 
171 ## LDR 07 - a - monographic component part 
172
173         $leader =~ s/^(....)...(.+)/$1naa$2/;
174
175 ## LDR 17 - Encoding level ; 7 - minimal level, u - unknown
176 ## LDR 18 - i = isbd ; u = unknown
177
178         $leader =~ s/^(.{17})..(.+)/$1uu$2/;
179
180         $marc->leader( $leader );
181         warn "# leader [$leader]";
182
183
184 ### 008 - All materials
185
186 ## 008 - 00-05 - Date entered on file 
187
188         my $f008 = $1 . $2 . $3 if $row->{time_date} =~ m/\d\d(\d\d)-(\d\d)-(\d\d)/;
189
190 ## 008 06 - Type of date/Publication status
191
192         $f008 .= 's';
193
194 ## 008 07-10 - Date 1
195
196         $f008 .= substr($row->{datum},0,4);
197
198 ## 008 11-14 - Date 2 
199
200         #$f008 .= '    ';
201
202         $f008 .= ' ' x ( 15 - length($f008) ); # pad to 15 position
203 ## 008 15-17 - Place of publication, production, or execution - ako nema 102, popunjava se s |
204         $f008 .= 'xx ';
205
206 ## 008 35-37 - Language
207         $f008 .= ' ' x ( 35 - length($f008) ); # pad to 35 position
208         if ( my $lng = $langrecode008->{ $row->{jezik} } ) {
209                 $f008 .= $lng;
210         } else {
211                 warn "INFO unknown jezik [$row->{jezik}] insert into langrecode008!";
212                 #$f008 .= '   ';
213         }
214         $f008 .= ' ' x ( 38 - length($f008) );
215 ## 008 38 - Modified record
216         $f008 .= '|';
217 ## 008 39 - Cataloging source - d (other)
218         $f008 .= 'd';
219
220         warn "# 008 ",length($f008);
221         
222         $marc->add_fields('008', $f008); # FIXME - mglavica check
223
224
225         if ( my $doi = $row->{doi} ) {
226
227                 $marc->add_fields('024','7',' ',
228                         2 => 'doi',
229                         a => $doi,
230                 );
231
232         }
233
234 ### 035$
235
236 ## marc 035a - System Number 
237 ## polje moze  sadrzavati slova i razmake
238 ## moguc problem u pretrazivanju ako ima zagrade, kako bi trebalo po standardu
239
240         $marc->add_fields('035',' ',' ',
241                 a => join('', '(CROSBI)', $row->{id})
242         );
243
244 ### 040
245 ## za sve je isti
246
247         $marc->add_fields('040',' ',' ',
248                 'a' => 'HR-ZaFF',
249                 'b' => 'hrv',
250                 'c' => 'HR-ZaFF',
251                 'e' => 'ppiak'
252         );
253
254 ### 041 - indikatori
255 # i1=0 - Item not a translation/does not include a translation
256 # i1=1 - Item is or includes a translation
257 # i1=' ' - No information provided
258
259 ### 041
260 # ponovljivo potpolje (041a) - marc_repeatable_subfield
261 # koristi se kad ima vise od jednog jezika, ili kad se radi o prijevodu
262
263         $marc->add_fields('041',' ',' ', map {
264                 ( a => lc($_) )
265         } split(/-/, $row->{jezik}));
266
267
268 ### 080
269 ### 245 indikatori
270 ## i1 = 0 zza anonimne publikacije, i1 = 1 ako postoji 700 ili 710
271 ## i2 = pretpostavlja se na temelju clana na pocetku naslova i jezika
272
273         my ( $first_author, $authors ) = split(/ ;\s*/,$row->{autori});
274
275         $marc->add_fields(100,'1',' ','a' => $first_author );
276
277
278
279         my $naslov = $row->{naslov}; # XXX title?
280
281         my $i2 =
282                 $naslov =~ m/^Eine /                            ? 5 :
283                 $naslov =~ m/(Die|Das|Der|Ein|Les|Los|The) /    ? 4 :
284                 $naslov =~ m/^(Um|Un|An|La|Le|Lo|Il) /          ? 3 :
285                 $naslov =~ m/^(A|L) /                           ? 2 :
286                 $naslov =~ m/^L'/                               ? 2 :
287                                                                   0;
288
289         $marc->add_fields(245,'1',$i2,
290                 'a' => $naslov . ' /',
291                 'c' => $row->{autori} . '.',
292         );
293
294         $marc->add_fields(246,'3',' ',
295                 'i' => 'Naslov na engleskom:',
296                 'a' => $row->{title}
297         );
298
299         sub page_range {
300                 my ( $prefix, $from, $to ) = @_;
301                 my $out;
302                 if ( $from ) {
303                         $out = $prefix . $from;
304                         $out .= '-' . $to if $to;
305                 }
306                 return $out;
307         }
308
309         $marc->add_fields(300,' ',' ',
310                 a => page_range('',$row->{stranica_prva},$row->{stranica_zadnja}),
311                 f => 'str.'
312         );
313
314         $marc->add_fields(363,' ',' ',
315                 a => $row->{volumen},
316                 b => $row->{broj},
317                 i => $row->{godina},
318         );
319
320 # /data/FF/crosbi/2016-12-12/casopis-rad_napomena.sql
321
322         $marc->add_fields(500,' ',' ',
323                 a => substr($row->{napomena}, 0, 9999), # XXX marc limit for one subfield is 4 digits in dictionary
324         );
325
326         $marc->add_fields(520,' ',' ',
327                 a => substr($row->{sazetak}, 0, 9999)
328         );
329
330
331         if ( $row->{rad_projekt} ) {
332                 $marc->add_fields(536,' ',' ',
333                         a => 'Projekt MZOS',
334                         f => 'projekt',
335                 );
336         }
337
338         $marc->add_fields(546,' ',' ',
339                 a => $row->{jezik}
340         );
341
342         $marc->add_fields(690,' ',' ',
343                 a => $row->{sifra}
344         );
345
346
347         $marc->add_fields(693,' ',' ',
348                 a => $row->{kljucne_rijeci},
349                 1 => 'hrv',
350                 2 => 'crosbi',
351         );
352         $marc->add_fields(693,' ',' ',
353                 a => $row->{key_words},
354                 1 => 'eng',
355                 2 => 'crosbi',
356         );
357
358         if ( $row->{autori} =~ m/ ; / ) {
359                 my @a = split(/ ; /, $row->{autori});
360                 shift @a; # skip first
361                 $marc->add_fields(700,'1',' ',
362                         a => $_,
363                         4 => 'aut'
364                 ) foreach @a;
365         }
366
367         $marc->add_fields(773,'0',' ',
368                 t => $row->{casopis},
369                 x => $row->{issn},
370                 g => "$row->{volumen} ($row->{godina}), $row->{broj} ;" . page_range(' str. ',$row->{stranica_prva}, $row->{stranica_zadnja}),
371         );
372
373         if ( my $file = $row->{datoteka} ) {
374                 $marc->add_fields(856,' ',' ',
375                         u => "http://bib.irb.hr/datoteka/$file",
376                 );
377         };
378
379         foreach my $name (qw( openurl url )) {
380                 next if ! $row->{$name};
381                 $marc->add_fields(856,' ',' ',
382                         u => $row->{$name},
383                 );
384         }
385
386         my @f942 = (
387                 c => 'CLA'
388         );
389         if ( $row->{status_rada} ) {
390                 push @f942, (
391                 f => 1,
392                 g => $row->{status_rada}
393                 );
394         }
395         push @f942, t => '1.01' if $row->{kategorija} =~ m/Znanstveni/;
396         push @f942, t => '1.04' if $row->{kategorija} =~ m/Strucni/;
397
398         $marc->add_fields(942,' ',' ',
399                 @f942,
400                 u => '1',
401                 z => join(' - ', $row->{kategorija}, $row->{vrsta_rada}),
402         );
403
404 =for later
405         $marc->add_fields(999,' ',' ',
406                 a => $row->{}
407         );
408
409 =cut
410
411 #       diag "# hash ",dump($hash);
412         diag "# marc\n", $marc->as_formatted;
413
414         $self->save_marc( "$id.marc", $marc->as_usmarc );
415
416         return $id;
417
418 }
419
420 1;