]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/perlmods/OpenILS/Application/Search/Biblio.pm
added org_type to the org tree
[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.direct.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.direct.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
154         my( $self, $client, $id ) = @_;
155         warn "Retrieving MODS object for record $id\n";
156         return undef unless(defined $id);
157
158         my $mods_list = _records_to_mods( $id );
159         my $mods_obj = $mods_list->[0];
160         return $mods_obj;
161 }
162
163
164 # Returns the number of copies attached to a record based on org location
165 __PACKAGE__->register_method(
166         method  => "record_id_to_copy_count",
167         api_name        => "open-ils.search.biblio.record.copy_count",
168         argc            => 2, 
169         note            => "Provide ID, we provide the copy count"
170 );
171
172 sub record_id_to_copy_count {
173         my( $self, $client, $org_id, $record_id ) = @_;
174
175         my $session = OpenSRF::AppSession->create("open-ils.storage");
176         warn "copy_count retrieve $record_id\n";
177         return undef unless(defined $record_id);
178
179         my $request = $session->request(
180                 "open-ils.storage.direct.biblio.record_copy_count",  $org_id, $record_id );
181
182         warn "copy_count wait $record_id\n";
183         $request->wait_complete;
184
185         warn "copy_count recv $record_id\n";
186         my $response = $request->recv();
187         return undef unless $response;
188
189         warn "copy_count after recv $record_id\n";
190
191         if( $response and UNIVERSAL::isa($response, "Error")) {
192                 throw $response ($response->stringify);
193         }
194
195         my $count = $response->content;
196
197         $request->finish();
198         $session->finish();
199         $session->disconnect();
200
201         return $count;
202 }
203
204
205 # used for cat search classes
206 my $cat_search_hash =  {
207
208         author => [ 
209                 { tag => "100", subfield => "a"} ,
210                 { tag => "700", subfield => "a"}, 
211         ],
212
213         title => [ 
214                 { tag => "245", subfield => "a"},
215                 { tag => "242", subfield => "a"}, 
216                 { tag => "240", subfield => "a"},
217                 { tag => "210", subfield => "a"},
218         ],
219
220         subject => [ 
221                 { tag => "650", subfield => "_" }, 
222         ],
223
224         tcn     => [
225                 { tag => "035", subfield => "_" },
226         ],
227
228 };
229
230
231 __PACKAGE__->register_method(
232         method  => "cat_biblio_search_tcn",
233         api_name        => "open-ils.search.cat.biblio.tcn",
234         argc            => 3, 
235         note            => "Searches biblio information by search class",
236 );
237
238 sub cat_biblio_search_tcn {
239
240         my( $self, $client, $tcn ) = @_;
241
242         $tcn =~ s/.*?(\w+)\s*$/$1/o;
243         warn "Searching TCN $tcn\n";
244
245         my $session = OpenSRF::AppSession->create( "open-ils.storage" );
246         my $request = $session->request( 
247                         "open-ils.storage.direct.biblio.record_entry.search.tcn_value", $tcn );
248         warn "tcn going into recv\n";
249         my $response = $request->recv();
250
251
252         unless ($response) { return []; }
253
254         if(UNIVERSAL::isa($response,"OpenSRF::EX")) {
255                 warn "Received exception for tcn search\n";
256                 throw $response ($response->stringify);
257         }
258
259         my $record_entry = $response->content;
260         my @ids;
261         for my $record (@$record_entry) {
262                 push @ids, $record->id;
263         }
264
265         warn "received ID's for tcn search @ids\n";
266
267
268         my $record_list = _records_to_mods( @ids );
269
270         for my $rec (@$record_list) {
271                 $client->respond($rec);
272         }
273
274         return undef;
275
276 }
277
278 __PACKAGE__->register_method(
279         method  => "cat_biblio_search_class",
280         api_name        => "open-ils.search.cat.biblio.class",
281         argc            => 3, 
282         note            => "Searches biblio information by search class",
283 );
284
285 sub cat_biblio_search_class {
286
287         my( $self, $client, $org_id, $class, $sort, $string ) = @_;
288
289         throw OpenSRF::EX::InvalidArg 
290                 ("Not enough args to open-ils.search.cat.biblio.class")
291                         unless( defined($org_id) and $class and $sort and $string );
292
293
294         my $search_hash;
295
296         my $method = $self->method_lookup("open-ils.search.biblio.marc");
297         if(!$method) {
298                 throw OpenSRF::EX::PANIC 
299                         ("Can't lookup method 'open-ils.search.biblio.marc'");
300         }
301
302         my ($records) = $method->run( $cat_search_hash->{$class}, $string );
303
304         my @ids;
305         for my $i (@$records) { push @ids, $i->[0]; }
306
307         my $mods_list = _records_to_mods( @ids );
308         return undef unless (ref($mods_list) eq "ARRAY");
309
310         # ---------------------------------------------------------------
311         # append copy count information to the mods objects
312         my $session = OpenSRF::AppSession->create("open-ils.storage");
313
314         my $request = $session->request(
315                 "open-ils.storage.direct.biblio.record_copy_count.batch",  $org_id, @ids );
316
317         for my $id (@ids) {
318
319                 warn "receiving copy counts for doc $id\n";
320
321                 my $response = $request->recv();
322                 next unless $response;
323
324                 if( $response and UNIVERSAL::isa($response, "Error")) {
325                         throw $response ($response->stringify);
326                 }
327
328                 my $count = $response->content;
329                 my $mods_obj = undef;
330                 for my $m (@$mods_list) {
331                         $mods_obj = $m if ($m->{doc_id} == $id)
332                 }
333                 if($mods_obj) {
334                         $mods_obj->{copy_count} = $count;
335                 }
336
337                 $client->respond( $mods_obj );
338
339         }       
340         $request->finish();
341
342         $session->finish();
343         $session->disconnect();
344         $session->kill_me();
345         # ---------------------------------------------------------------
346
347         return undef;
348 }
349
350
351
352 __PACKAGE__->register_method(
353         method  => "cat_biblio_search_class_id",
354         api_name        => "open-ils.search.cat.biblio.class.id",
355         argc            => 3, 
356         note            => "Searches biblio information by search class and returns the IDs",
357 );
358
359 sub cat_biblio_search_class_id {
360
361         my( $self, $client, $org_id, $class, $string, $limit, $offset ) = @_;
362
363         $offset ||= 0;
364         $limit  ||= 100;
365         $limit -= 1;
366
367
368         $string = OpenILS::Application::Search->filter_search($string);
369         if(!$string) { return undef; }
370
371         warn "Searching cat.biblio.class.id string: $string offset: $offset limit: $limit\n";
372
373         throw OpenSRF::EX::InvalidArg 
374                 ("Not enough args to open-ils.search.cat.biblio.class")
375                         unless( defined($org_id) and $class and $string );
376
377
378         my $search_hash;
379
380         my $cache_key = md5_hex( $org_id . $class . $string );
381         my $id_array = OpenILS::Application::SearchCache->get_cache($cache_key);
382
383         if(ref($id_array)) {
384                 warn "Return search from cache\n";
385                 my $size = @$id_array;
386                 my @ids = @$id_array[ $offset..($offset+$limit) ];
387                 warn "Returning cat.biblio.class.id $string\n";
388                 return { count => $size, ids => \@ids };
389         }
390
391         my $method = $self->method_lookup("open-ils.search.biblio.marc");
392         if(!$method) {
393                 throw OpenSRF::EX::PANIC 
394                         ("Can't lookup method 'open-ils.search.biblio.marc'");
395         }
396
397         my ($records) = $method->run( $cat_search_hash->{$class}, $string );
398
399         my @cache_ids;
400
401         for my $i (@$records) { push @cache_ids, $i->[0]; }
402         my @ids = @cache_ids[ $offset..($offset+$limit) ];
403         my $size = @$records;
404
405         OpenILS::Application::SearchCache->put_cache( 
406                         $cache_key, \@cache_ids, $size );
407
408         warn "Returning cat.biblio.class.id $string\n";
409         return { count =>$size, ids => \@ids };
410
411 }
412
413
414
415 1;