1 package OpenILS::Application::Search::Authority;
2 use base qw/OpenILS::Application/;
3 use strict; use warnings;
5 use OpenILS::Utils::Fieldmapper;
6 use OpenILS::Application::AppUtils;
9 use OpenILS::Utils::Editor q/:funcs/;
10 use OpenSRF::Utils::Logger qw/$logger/;
12 use OpenSRF::Utils::JSON;
14 use Time::HiRes qw(time);
15 use OpenSRF::EX qw(:try);
16 use Digest::MD5 qw(md5_hex);
21 sub validate_authority {
25 my $session = OpenSRF::AppSession->create("open-ils.storage");
26 return $session->request( 'open-ils.storage.authority.validate.tag' => @_ )->gather(1);
28 __PACKAGE__->register_method(
29 method => "validate_authority",
30 api_name => "open-ils.search.authority.validate.tag",
32 note => "Validates authority data from existing controlled terms",
35 sub search_authority {
39 my $session = OpenSRF::AppSession->create("open-ils.storage");
40 return $session->request( 'open-ils.storage.authority.search.marc.atomic' => @_ )->gather(1);
42 __PACKAGE__->register_method(
43 method => "search_authority",
44 api_name => "open-ils.search.authority.fts",
46 note => "Searches authority data for existing controlled terms and crossrefs",
50 sub crossref_authority {
55 my $limit = shift || 10;
57 my $session = OpenSRF::AppSession->create("open-ils.storage");
59 $logger->info("authority xref search for $class=$term, limit=$limit");
60 my $fr = $session->request(
61 "open-ils.storage.authority.$class.see_from.controlled.atomic",$term, $limit)->gather(1);
62 my $al = $session->request(
63 "open-ils.storage.authority.$class.see_also_from.controlled.atomic",$term, $limit)->gather(1);
65 my $data = _auth_flatten( $term, $fr, $al, 1 );
80 last unless ($$x[$i]);
81 if ($string =~ /\W$/o) {
82 $string .= ' '.$$x[$i];
84 $string .= ' -- '.$$x[$i];
87 next if (lc($string) eq lc($term));
89 $hash{$string}++ if (lc($$x[0]) eq lc($term));
91 my $from = [keys %hash]; #[ sort { $hash{$b} <=> $hash{$a} || $a cmp $b } keys %hash ];
93 # $from = [ @$from[0..4] ] if $limit;
99 last unless ($$x[$i]);
100 if ($string =~ /\W$/o) {
101 $string .= ' '.$$x[$i];
103 $string .= ' -- '.$$x[$i];
106 next if (lc($string) eq lc($term));
108 $hash{$string}++ if (lc($$x[0]) eq lc($term));
110 my $also = [keys %hash]; #[ sort { $hash{$b} <=> $hash{$a} || $a cmp $b } keys %hash ];
112 # $also = [ @$also[0..4] ] if $limit;
114 #warn Dumper( { from => $from, also => $also } );
116 return { from => $from, also => $also };
119 __PACKAGE__->register_method(
120 method => "crossref_authority",
121 api_name => "open-ils.search.authority.crossref",
123 note => "Searches authority data for existing controlled terms and crossrefs",
126 __PACKAGE__->register_method(
127 #method => "new_crossref_authority_batch",
128 method => "crossref_authority_batch2",
129 api_name => "open-ils.search.authority.crossref.batch",
132 Takes an array of class,term pair sub-arrays and performs an authority lookup for each
134 PARAMS( [ ["subject", "earth"], ["author","shakespeare"] ] );
136 Returns an object like so:
139 "term" : { "from" : [ ...], "also" : [...] }
140 "term2" : { "from" : [ ...], "also" : [...] }
145 sub new_crossref_authority_batch {
146 my( $self, $client, $reqs ) = @_;
150 my $session = OpenSRF::AppSession->create("open-ils.storage");
152 for my $req (@$reqs) {
154 my $class = $req->[0];
155 my $term = $req->[1];
156 next unless $class and $term;
157 warn "Sending authority request for $class : $term\n";
158 my $fr = $session->request("open-ils.storage.authority.$class.see_from.controlled.atomic",$term, 10)->gather(1);
159 my $al = $session->request("open-ils.storage.authority.$class.see_also_from.controlled.atomic",$term, 10)->gather(1);
161 warn "Flattening $class : $term\n";
162 $response->{$class} = {} unless exists $response->{$class};
163 $response->{$class}->{$term} = _auth_flatten( $term, $fr, $al, 1 );
167 #warn Dumper( $response );
171 sub crossref_authority_batch {
172 my( $self, $client, $reqs ) = @_;
176 my $session = OpenSRF::AppSession->create("open-ils.storage");
178 for my $req (@$reqs) {
180 my $class = $req->[0];
181 my $term = $req->[1];
182 next unless $class and $term;
183 warn "Sending authority request for $class : $term\n";
184 my $freq = $session->request("open-ils.storage.authority.$class.see_from.controlled.atomic",$term, 10);
185 my $areq = $session->request("open-ils.storage.authority.$class.see_also_from.controlled.atomic",$term, 10);
187 if( $lastr->[0] ) { #process old data while waiting on new data
188 my $cls = $lastr->[0];
189 my $trm = $lastr->[1];
190 my $fr = $lastr->[2];
191 my $al = $lastr->[3];
192 warn "Flattening $class : $term\n";
193 $response->{$cls} = {} unless exists $response->{$cls};
194 $response->{$cls}->{$trm} = _auth_flatten( $trm, $fr, $al, 1 );
197 $lastr->[0] = $class;
199 $lastr->[2] = $freq->gather(1);
200 $lastr->[3] = $areq->gather(1);
203 if( $lastr->[0] ) { #process old data while waiting on new data
204 my $cls = $lastr->[0];
205 my $trm = $lastr->[1];
206 my $fr = $lastr->[2];
207 my $al = $lastr->[3];
208 warn "Flattening $cls : $trm\n";
209 $response->{$cls} = {} unless exists $response->{$cls};
210 $response->{$cls}->{$trm} = _auth_flatten( $trm, $fr, $al, 1);
219 sub crossref_authority_batch2 {
220 my( $self, $client, $reqs ) = @_;
224 my $session = OpenSRF::AppSession->create("open-ils.storage");
226 $cache = OpenSRF::Utils::Cache->new('global') unless $cache;
228 for my $req (@$reqs) {
230 my $class = $req->[0];
231 my $term = $req->[1];
232 next unless $class and $term;
236 my $cdata = $cache->get_cache("oils_authority_${class}_$t");
239 $logger->debug("returning authority response from cache..");
240 $response->{$class} = {} unless exists $response->{$class};
241 $response->{$class}->{$term} = $cdata;
245 $logger->debug("authority data not found in cache.. fetching from storage");
247 warn "Sending authority request for $class : $term\n";
248 my $freq = $session->request("open-ils.storage.authority.$class.see_from.controlled.atomic",$term, 10);
249 my $areq = $session->request("open-ils.storage.authority.$class.see_also_from.controlled.atomic",$term, 10);
250 my $fr = $freq->gather(1);
251 my $al = $areq->gather(1);
252 $response->{$class} = {} unless exists $response->{$class};
253 my $auth = _auth_flatten( $term, $fr, $al, 1 );
255 my $timeout = 7200; #two hours
256 $timeout = 300 if @{$auth->{from}} or @{$auth->{also}}; # 5 minutes
257 $response->{$class}->{$term} = $auth;
258 $logger->debug("adding authority lookup to cache with timeout $timeout");
259 $cache->put_cache("oils_authority_${class}_$t", $auth, $timeout);
268 __PACKAGE__->register_method(
269 method => "authority_to_html",
270 api_name => "open-ils.search.authority.to_html" );
272 my $parser = XML::LibXML->new();
273 my $xslt = XML::LibXSLT->new();
277 sub authority_to_html {
278 my( $self, $client, $id ) = @_;
282 my $sclient = OpenSRF::Utils::SettingsClient->new();
283 my $dir = $sclient->config_value( "dirs", "xsl" );
284 my $xsl = $sclient->config_value(
285 "apps", "open-ils.search", "app_settings", "marc_html_xsl" );
286 $xsl = $parser->parse_file("$dir/$xsl");
287 $stylesheet = $xslt->parse_stylesheet( $xsl );
290 my $e = new_editor();
291 my $rec = $e->retrieve_authority_record_entry($id) or return $e->event;
292 my $xmldoc = $parser->parse_string($rec->marc);
293 my $html = $stylesheet->transform($xmldoc);
295 return $html->toString();