1 package OpenILS::Application::Search::Biblio;
2 use base qw/OpenSRF::Application/;
3 use strict; use warnings;
6 use OpenILS::Utils::Fieldmapper;
7 use OpenILS::Utils::ModsParser;
8 use OpenSRF::Utils::SettingsClient;
10 use OpenILS::Application::AppUtils;
12 use Time::HiRes qw(time);
13 use OpenSRF::EX qw(:try);
14 use Digest::MD5 qw(md5_hex);
16 # Houses biblio search utilites
18 __PACKAGE__->register_method(
19 method => "biblio_search_marc",
20 api_name => "open-ils.search.biblio.marc",
22 note => "Searches biblio information by marc tag",
25 sub biblio_search_marc {
27 my( $self, $client, $search_hash, $string ) = @_;
29 warn "Building biblio marc session\n";
30 my $session = OpenSRF::AppSession->create("open-ils.storage");
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 );
37 warn "Waiting complete\n";
38 $request->wait_complete();
40 warn "Calling recv\n";
41 my $response = $request->recv(20);
44 if($response and UNIVERSAL::isa($response,"OpenSRF::EX")) {
45 throw $response ($response->stringify);
50 if($response and UNIVERSAL::can($response,"content")) {
51 $data = $response->content;
53 warn "finishing request\n";
57 $session->disconnect();
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 {
77 my $session = OpenSRF::AppSession->create("open-ils.storage");
78 my $request = $session->request(
79 "open-ils.storage.biblio.record_marc.batch.retrieve", @ids );
81 my $last_content = undef;
83 while( my $response = $request->recv() ) {
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;
95 next unless $response;
97 if($response->isa("OpenSRF::EX")) {
98 throw $response ($response->stringify);
101 $last_content = $response->content;
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;
115 $session->disconnect();
121 __PACKAGE__->register_method(
122 method => "record_id_to_mods",
123 api_name => "open-ils.search.biblio.record.mods.retrieve",
125 note => "Provide ID, we provide the mods"
128 # converts a record into a mods object with copy counts attached
129 sub record_id_to_mods {
131 my( $self, $client, $org_id, $id ) = @_;
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;
144 __PACKAGE__->register_method(
145 method => "record_id_to_mods_slim",
146 api_name => "open-ils.search.biblio.record.mods_slim.retrieve",
148 note => "Provide ID, we provide the mods"
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];
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",
165 note => "Provide ID, we provide the copy count"
168 sub record_id_to_copy_count {
169 my( $self, $client, $org_id, $record_id ) = @_;
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 );
176 warn "mods retrieve wait $record_id\n";
177 $request->wait_complete;
179 warn "mods retrieve recv $record_id\n";
180 my $response = $request->recv();
181 return undef unless $response;
183 warn "mods retrieve after recv $record_id\n";
185 if( $response and UNIVERSAL::isa($response, "Error")) {
186 throw $response ($response->stringify);
189 my $count = $response->content;
193 $session->disconnect();
199 # used for cat search classes
200 my $cat_search_hash = {
203 { tag => "100", subfield => "a"} ,
204 { tag => "700", subfield => "a"},
208 { tag => "245", subfield => "a"},
209 { tag => "242", subfield => "a"},
210 { tag => "240", subfield => "a"},
211 { tag => "210", subfield => "a"},
215 { tag => "650", subfield => "_" },
219 { tag => "035", subfield => "_" },
225 __PACKAGE__->register_method(
226 method => "cat_biblio_search_tcn",
227 api_name => "open-ils.search.cat.biblio.tcn",
229 note => "Searches biblio information by search class",
232 sub cat_biblio_search_tcn {
234 my( $self, $client, $org_id, $tcn ) = @_;
236 $tcn =~ s/.*?(\w+)\s*$/$1/o;
237 warn "Searching TCN $tcn\n";
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();
245 unless ($response) { return []; }
247 if($response->isa("OpenSRF::EX")) {
248 throw $response ($response->stringify);
251 my $record_entry = $response->content;
253 for my $record (@$record_entry) {
254 push @ids, $record->id;
258 my $record_list = _records_to_mods( @ids );
260 for my $rec (@$record_list) {
261 $client->respond($rec);
268 __PACKAGE__->register_method(
269 method => "cat_biblio_search_class",
270 api_name => "open-ils.search.cat.biblio.class",
272 note => "Searches biblio information by search class",
275 sub cat_biblio_search_class {
277 my( $self, $client, $org_id, $class, $sort, $string ) = @_;
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 );
286 my $method = $self->method_lookup("open-ils.search.biblio.marc");
288 throw OpenSRF::EX::PANIC
289 ("Can't lookup method 'open-ils.search.biblio.marc'");
292 my ($records) = $method->run( $cat_search_hash->{$class}, $string );
295 for my $i (@$records) { push @ids, $i->[0]; }
297 my $mods_list = _records_to_mods( @ids );
298 return undef unless (ref($mods_list) eq "ARRAY");
300 # ---------------------------------------------------------------
301 # append copy count information to the mods objects
302 my $session = OpenSRF::AppSession->create("open-ils.storage");
304 my $request = $session->request(
305 "open-ils.storage.biblio.record_copy_count.batch", $org_id, @ids );
309 warn "receiving copy counts for doc $id\n";
311 my $response = $request->recv();
312 next unless $response;
314 if( $response and UNIVERSAL::isa($response, "Error")) {
315 throw $response ($response->stringify);
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)
324 $mods_obj->{copy_count} = $count;
327 $client->respond( $mods_obj );
333 $session->disconnect();
335 # ---------------------------------------------------------------
342 __PACKAGE__->register_method(
343 method => "cat_biblio_search_class_id",
344 api_name => "open-ils.search.cat.biblio.class.id",
346 note => "Searches biblio information by search class and returns the IDs",
349 sub cat_biblio_search_class_id {
351 my( $self, $client, $org_id, $class, $sort, $string ) = @_;
353 $string = OpenILS::Application::Search->filter_search($string);
354 if(!$string) { return undef; }
356 warn "Searching cat.biblio.class.id $string\n";
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 );
365 my $cache_key = md5_hex( $org_id . $class . $sort . $string );
366 my $id_array = OpenILS::Application::SearchCache->get_cache($cache_key);
369 warn "Return search from cache\n";
370 my $size = @$id_array;
373 for my $i (@$id_array) {
374 if($x++ > 200){last;}
377 warn "Returning cat.biblio.class.id $string\n";
378 return { count => $size, ids => \@ids };
381 my $method = $self->method_lookup("open-ils.search.biblio.marc");
383 throw OpenSRF::EX::PANIC
384 ("Can't lookup method 'open-ils.search.biblio.marc'");
387 my ($records) = $method->run( $cat_search_hash->{$class}, $string );
392 # add some sanity checking
393 my $x=0; # Here we're limiting by 200
394 for my $i (@$records) {
398 push @cache_ids, $i->[0];
400 my $size = @$records;
402 OpenILS::Application::SearchCache->put_cache(
403 $cache_key, \@cache_ids, $size );
405 warn "Returning cat.biblio.class.id $string\n";
406 return { count =>$size, ids => \@ids };