]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/src/perlmods/OpenILS/Application/Search/Biblio.pm
moved biblio-specific searches to Biblio
[working/Evergreen.git] / Open-ILS / src / perlmods / OpenILS / Application / Search / Biblio.pm
1 package OpenILS::Application::Search::Biblio;
2 use base qw/OpenSRF::Application/;
3 use strict; use warnings;
4
5 use JSON;
6 use OpenILS::Utils::Fieldmapper;
7 use OpenILS::Utils::ModsParser;
8 use OpenSRF::Utils::SettingsClient;
9
10 use OpenILS::Application::AppUtils;
11
12 use Time::HiRes qw(time);
13 use OpenSRF::EX qw(:try);
14 use Digest::MD5 qw(md5_hex);
15
16 # Houses biblio search utilites 
17
18 __PACKAGE__->register_method(
19         method  => "biblio_search_marc",
20         api_name        => "open-ils.search.biblio.marc",
21         argc            => 1, 
22         note            => "Searches biblio information by marc tag",
23 );
24
25 sub biblio_search_marc {
26
27         my( $self, $client, $search_hash, $string ) = @_;
28
29         warn "Building biblio marc session\n";
30         my $session = OpenSRF::AppSession->create("open-ils.storage");
31
32         warn "Sending biblio marc request\n";
33         my $request = $session->request( 
34                         "open-ils.storage.metabib.full_rec.search_fts.index_vector", 
35                         $search_hash, $string );
36
37         warn "Waiting complete\n";
38         $request->wait_complete();
39
40         warn "Calling recv\n";
41         my $response = $request->recv(20);
42
43         warn "out of recv\n";
44         if($response and UNIVERSAL::isa($response,"OpenSRF::EX")) {
45                 throw $response ($response->stringify);
46         }
47
48
49         my $data = [];
50         if($response and UNIVERSAL::can($response,"content")) {
51                 $data = $response->content;
52         }
53         warn "finishing request\n";
54
55         $request->finish();
56         $session->finish();
57         $session->disconnect();
58
59         return $data;
60
61 }
62
63
64
65
66
67 # ---------------------------------------------------------------------------
68 # takes a list of record id's and turns the docs into friendly 
69 # mods structures. Creates one MODS structure for each doc id.
70 # ---------------------------------------------------------------------------
71 sub _records_to_mods {
72         my @ids = @_;
73         
74         my @results;
75         my @marcxml_objs;
76
77         my $session = OpenSRF::AppSession->create("open-ils.storage");
78         my $request = $session->request(
79                         "open-ils.storage.biblio.record_marc.batch.retrieve",  @ids );
80
81         my $last_content = undef;
82
83         while( my $response = $request->recv() ) {
84
85                 if( $last_content ) {
86                         my $u = OpenILS::Utils::ModsParser->new();
87                         $u->start_mods_batch( $last_content->marc );
88                         my $mods = $u->finish_mods_batch();
89                         $mods->{doc_id} = $last_content->id();
90                         warn "Turning doc " . $mods->{doc_id} . " into MODS\n";
91                         $last_content = undef;
92                         push @results, $mods;
93                 }
94
95                 next unless $response;
96
97                 if($response->isa("OpenSRF::EX")) {
98                         throw $response ($response->stringify);
99                 }
100
101                 $last_content = $response->content;
102
103         }
104
105         if( $last_content ) {
106                 my $u = OpenILS::Utils::ModsParser->new();
107                 $u->start_mods_batch( $last_content->marc );
108                 my $mods = $u->finish_mods_batch();
109                 $mods->{doc_id} = $last_content->id();
110                 push @results, $mods;
111         }
112
113         $request->finish();
114         $session->finish();
115         $session->disconnect();
116
117         return \@results;
118
119 }
120
121 __PACKAGE__->register_method(
122         method  => "record_id_to_mods",
123         api_name        => "open-ils.search.biblio.record.mods.retrieve",
124         argc            => 1, 
125         note            => "Provide ID, we provide the mods"
126 );
127
128 # converts a record into a mods object with copy counts attached
129 sub record_id_to_mods {
130
131         my( $self, $client, $org_id, $id ) = @_;
132
133         my $mods_list = _records_to_mods( $id );
134         my $mods_obj = $mods_list->[0];
135         my $cmethod = $self->method_lookup(
136                         "open-ils.search.biblio.record.copy_count");
137         my ($count) = $cmethod->run($org_id, $id);
138         $mods_obj->{copy_count} = $count;
139
140         return $mods_obj;
141 }
142
143
144 __PACKAGE__->register_method(
145         method  => "record_id_to_mods_slim",
146         api_name        => "open-ils.search.biblio.record.mods_slim.retrieve",
147         argc            => 1, 
148         note            => "Provide ID, we provide the mods"
149 );
150
151 # converts a record into a mods object with NO copy counts attached
152 sub record_id_to_mods_slim {
153         my( $self, $client, $id ) = @_;
154         my $mods_list = _records_to_mods( $id );
155         my $mods_obj = $mods_list->[0];
156         return $mods_obj;
157 }
158
159
160 # Returns the number of copies attached to a record based on org location
161 __PACKAGE__->register_method(
162         method  => "record_id_to_copy_count",
163         api_name        => "open-ils.search.biblio.record.copy_count",
164         argc            => 2, 
165         note            => "Provide ID, we provide the copy count"
166 );
167
168 sub record_id_to_copy_count {
169         my( $self, $client, $org_id, $record_id ) = @_;
170
171         my $session = OpenSRF::AppSession->create("open-ils.storage");
172         warn "mods retrieve $record_id\n";
173         my $request = $session->request(
174                 "open-ils.storage.biblio.record_copy_count",  $org_id, $record_id );
175
176         warn "mods retrieve wait $record_id\n";
177         $request->wait_complete;
178
179         warn "mods retrieve recv $record_id\n";
180         my $response = $request->recv();
181         return undef unless $response;
182
183         warn "mods retrieve after recv $record_id\n";
184
185         if( $response and UNIVERSAL::isa($response, "Error")) {
186                 throw $response ($response->stringify);
187         }
188
189         my $count = $response->content;
190
191         $request->finish();
192         $session->finish();
193         $session->disconnect();
194
195         return $count;
196 }
197
198
199 # used for cat search classes
200 my $cat_search_hash =  {
201
202         author => [ 
203                 { tag => "100", subfield => "a"} ,
204                 { tag => "700", subfield => "a"}, 
205         ],
206
207         title => [ 
208                 { tag => "245", subfield => "a"},
209                 { tag => "242", subfield => "a"}, 
210                 { tag => "240", subfield => "a"},
211                 { tag => "210", subfield => "a"},
212         ],
213
214         subject => [ 
215                 { tag => "650", subfield => "_" }, 
216         ],
217
218         tcn     => [
219                 { tag => "035", subfield => "_" },
220         ],
221
222 };
223
224
225 __PACKAGE__->register_method(
226         method  => "cat_biblio_search_tcn",
227         api_name        => "open-ils.search.cat.biblio.tcn",
228         argc            => 3, 
229         note            => "Searches biblio information by search class",
230 );
231
232 sub cat_biblio_search_tcn {
233
234         my( $self, $client, $org_id, $tcn ) = @_;
235
236         $tcn =~ s/.*?(\w+)\s*$/$1/o;
237         warn "Searching TCN $tcn\n";
238
239         my $session = OpenSRF::AppSession->create( "open-ils.storage" );
240         my $request = $session->request( 
241                         "open-ils.storage.biblio.record_entry.search.tcn_value", $tcn );
242         my $response = $request->recv();
243
244
245         unless ($response) { return []; }
246
247         if($response->isa("OpenSRF::EX")) {
248                 throw $response ($response->stringify);
249         }
250
251         my $record_entry = $response->content;
252         my @ids;
253         for my $record (@$record_entry) {
254                 push @ids, $record->id;
255         }
256
257
258         my $record_list = _records_to_mods( @ids );
259
260         for my $rec (@$record_list) {
261                 $client->respond($rec);
262         }
263
264         return undef;
265
266 }
267
268 __PACKAGE__->register_method(
269         method  => "cat_biblio_search_class",
270         api_name        => "open-ils.search.cat.biblio.class",
271         argc            => 3, 
272         note            => "Searches biblio information by search class",
273 );
274
275 sub cat_biblio_search_class {
276
277         my( $self, $client, $org_id, $class, $sort, $string ) = @_;
278
279         throw OpenSRF::EX::InvalidArg 
280                 ("Not enough args to open-ils.search.cat.biblio.class")
281                         unless( defined($org_id) and $class and $sort and $string );
282
283
284         my $search_hash;
285
286         my $method = $self->method_lookup("open-ils.search.biblio.marc");
287         if(!$method) {
288                 throw OpenSRF::EX::PANIC 
289                         ("Can't lookup method 'open-ils.search.biblio.marc'");
290         }
291
292         my ($records) = $method->run( $cat_search_hash->{$class}, $string );
293
294         my @ids;
295         for my $i (@$records) { push @ids, $i->[0]; }
296
297         my $mods_list = _records_to_mods( @ids );
298         return undef unless (ref($mods_list) eq "ARRAY");
299
300         # ---------------------------------------------------------------
301         # append copy count information to the mods objects
302         my $session = OpenSRF::AppSession->create("open-ils.storage");
303
304         my $request = $session->request(
305                 "open-ils.storage.biblio.record_copy_count.batch",  $org_id, @ids );
306
307         for my $id (@ids) {
308
309                 warn "receiving copy counts for doc $id\n";
310
311                 my $response = $request->recv();
312                 next unless $response;
313
314                 if( $response and UNIVERSAL::isa($response, "Error")) {
315                         throw $response ($response->stringify);
316                 }
317
318                 my $count = $response->content;
319                 my $mods_obj = undef;
320                 for my $m (@$mods_list) {
321                         $mods_obj = $m if ($m->{doc_id} == $id)
322                 }
323                 if($mods_obj) {
324                         $mods_obj->{copy_count} = $count;
325                 }
326
327                 $client->respond( $mods_obj );
328
329         }       
330         $request->finish();
331
332         $session->finish();
333         $session->disconnect();
334         $session->kill_me();
335         # ---------------------------------------------------------------
336
337         return undef;
338 }
339
340
341
342 __PACKAGE__->register_method(
343         method  => "cat_biblio_search_class_id",
344         api_name        => "open-ils.search.cat.biblio.class.id",
345         argc            => 3, 
346         note            => "Searches biblio information by search class and returns the IDs",
347 );
348
349 sub cat_biblio_search_class_id {
350
351         my( $self, $client, $org_id, $class, $sort, $string ) = @_;
352
353         $string = OpenILS::Application::Search->filter_search($string);
354         if(!$string) { return undef; }
355
356         warn "Searching cat.biblio.class.id $string\n";
357
358         throw OpenSRF::EX::InvalidArg 
359                 ("Not enough args to open-ils.search.cat.biblio.class")
360                         unless( defined($org_id) and $class and $sort and $string );
361
362
363         my $search_hash;
364
365         my $cache_key = md5_hex( $org_id . $class . $sort . $string );
366         my $id_array = OpenILS::Application::SearchCache->get_cache($cache_key);
367
368         if(ref($id_array)) {
369                 warn "Return search from cache\n";
370                 my $size = @$id_array;
371                 my @ids;
372                 my $x = 0;
373                 for my $i (@$id_array) {
374                         if($x++ > 200){last;}
375                         push @ids, $i;
376                 }
377                 warn "Returning cat.biblio.class.id $string\n";
378                 return { count => $size, ids => \@ids };
379         }
380
381         my $method = $self->method_lookup("open-ils.search.biblio.marc");
382         if(!$method) {
383                 throw OpenSRF::EX::PANIC 
384                         ("Can't lookup method 'open-ils.search.biblio.marc'");
385         }
386
387         my ($records) = $method->run( $cat_search_hash->{$class}, $string );
388
389         my @ids;
390         my @cache_ids;
391
392         # add some sanity checking
393         my $x=0; # Here we're limiting by 200
394         for my $i (@$records) { 
395                 if($x++ < 200 ){
396                         push @ids, $i->[0]; 
397                 }
398                 push @cache_ids, $i->[0]; 
399         }
400         my $size = @$records;
401
402         OpenILS::Application::SearchCache->put_cache( 
403                         $cache_key, \@cache_ids, $size );
404
405         warn "Returning cat.biblio.class.id $string\n";
406         return { count =>$size, ids => \@ids };
407
408 }
409
410
411
412 1;