]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/perlmods/OpenILS/Application/Storage/Publisher/authority.pm
fixing authority lookup a bit
[Evergreen.git] / Open-ILS / src / perlmods / OpenILS / Application / Storage / Publisher / authority.pm
1 package OpenILS::Application::Storage::Publisher::authority;
2 use base qw/OpenILS::Application::Storage::Publisher/;
3 use vars qw/$VERSION/;
4 use OpenSRF::EX qw/:try/;
5 use OpenILS::Application::Storage::FTS;
6 use OpenILS::Utils::Fieldmapper;
7 use OpenSRF::Utils::Logger qw/:level/;
8 use OpenSRF::Utils::Cache;
9 use Data::Dumper;
10 use Digest::MD5 qw/md5_hex/;
11 use XML::LibXML;
12 use Time::HiRes qw/time sleep/;
13 use Unicode::Normalize;
14
15 my $log = 'OpenSRF::Utils::Logger';
16
17 $VERSION = 1;
18
19 my $parser = XML::LibXML->new;
20
21 sub find_authority_marc {
22         my $self = shift;
23         my $client = shift;
24         my %args = @_;
25         
26         my $term = NFD(lc($args{term}));
27         my $tag = $args{tag};
28         my $subfield = $args{subfield};
29         my $limit = $args{limit} || 100;
30         my $offset = $args{offset} || 0;
31
32         if ($limit) {
33                 $limit = "LIMIT $limit";
34         } else {
35                 $limit = '';
36         }
37
38         if ($offset) {
39                 $offset = "OFFSET $offset";
40         } else {
41                 $offset = '';
42         }
43
44         my $tag_where = "AND f.tag LIKE '$tag'";
45         if (ref $tag) {
46                 $tag_where = "AND f.tag IN ('".join("','",@$tag)."')";
47         }
48
49         my $sf_where = "AND f.subfield = '$subfield'";
50         if (ref $subfield) {
51                 $sf_where = "AND f.subfield IN ('".join("','",@$subfield)."')";
52         }
53
54         my $search_table = authority::full_rec->table;
55         my $marc_table = authority::record_entry->table;
56
57         my ($index_col) = authority::full_rec->columns('FTS');
58         $index_col ||= 'value';
59
60         my $fts = OpenILS::Application::Storage::FTS->compile($term, 'f.value', "f.$index_col");
61
62         $term =~ s/\W+$//gso;
63         $term =~ s/'/''/gso;
64         $term =~ s/\pM//gso;
65
66         my $fts_where = $fts->sql_where_clause;
67         my $fts_words = join '%', $fts->words;
68         my $fts_words_where = "f.value LIKE '$fts_words\%'";
69         my $fts_start_where = "f.value LIKE '$term\%'";
70         my $fts_eq_where = "f.value = '$term'";
71
72         my $fts_rank = join '+', $fts->fts_rank;
73
74         my $select = <<"        SQL";
75                 SELECT  a.marc, sum($fts_rank), count(f.record), first(f.value)
76                 FROM    $search_table f,
77                         $marc_table a
78                 WHERE   $fts_start_where
79                         $tag_where
80                         $sf_where
81                         AND a.id = f.record
82                         GROUP BY 1
83                         ORDER BY 2 desc, 3 desc, 4
84                         $limit
85                         $offset
86                         
87         SQL
88
89         $log->debug("Authority Search SQL :: [$select]",DEBUG);
90
91         my $recs = authority::full_rec->db_Main->selectcol_arrayref( $select );
92         
93         $log->debug("Search yielded ".scalar(@$recs)." results.",DEBUG);
94
95         $client->respond($_) for (@$recs);
96         return undef;
97 }
98 __PACKAGE__->register_method(
99         api_name        => "open-ils.storage.authority.search.marc",
100         method          => 'find_authority_marc',
101         api_level       => 1,
102         stream          => 1,
103         cachable        => 1,
104 );
105
106 sub _empty_check {
107         my $term = shift;
108         my $class = shift || 'metabib::full_rec';
109
110         my $table = $class->table;
111
112         my ($index_col) = $class->columns('FTS');
113         $index_col ||= 'value';
114
115         my $fts = OpenILS::Application::Storage::FTS->compile($term, 'm.value', "m.$index_col");
116         my $fts_where = $fts->sql_where_clause;
117
118         my $sql = <<"   SQL";
119                 SELECT  TRUE
120                 FROM    $table m
121                 WHERE   $fts_where
122                 LIMIT 1
123         SQL
124
125         return $class->db_Main->selectcol_arrayref($sql)->[0];
126 }
127
128 my $prevtime;
129
130 sub find_see_from_controlled {
131         my $self = shift;
132         my $client = shift;
133         my $term = shift;
134         my $limit = shift;
135         my $offset = shift;
136
137         $prevtime = time;
138
139         (my $class = $self->api_name) =~ s/^.+authority.([^\.]+)\.see.+$/$1/o;
140         my $sf = 'a';
141         $sf = 't' if ($class eq 'title');
142
143         my @marc = $self->method_lookup('open-ils.storage.authority.search.marc')
144                         ->run( term => $term, tag => [400,410,411,430,450,455], subfield => $sf, limit => $limit, offset => $offset );
145
146         
147         for my $m ( @marc ) {
148                 my $doc = $parser->parse_string($m);
149                 my @nodes = $doc->documentElement->findnodes('//*[substring(@tag,1,1)="1"]/*[@code="a" or @code="d" or @code="x"]');
150                 my $list = [ map { $_->textContent } @nodes ];
151                 $client->respond( $list ) if (_empty_check(join(' ',@$list), "metabib::${class}_field_entry"));
152         }
153         return undef;
154 }
155 for my $class ( qw/title author subject keyword series/ ) {
156         __PACKAGE__->register_method(
157                 api_name        => "open-ils.storage.authority.$class.see_from.controlled",
158                 method          => 'find_see_from_controlled',
159                 api_level       => 1,
160                 stream          => 1,
161                 cachable        => 1,
162         );
163 }
164
165 sub find_see_also_from_controlled {
166         my $self = shift;
167         my $client = shift;
168         my $term = shift;
169         my $limit = shift;
170         my $offset = shift;
171
172         (my $class = $self->api_name) =~ s/^.+authority.([^\.]+)\.see.+$/$1/o;
173         my $sf = 'a';
174         $sf = 't' if ($class eq 'title');
175
176         my @marc = $self->method_lookup('open-ils.storage.authority.search.marc')
177                         ->run( term => $term, tag => [500,510,511,530,550,555], subfield => $sf, limit => $limit, offset => $offset );
178         for my $m ( @marc ) {
179                 my $doc = $parser->parse_string($m);
180                 my @nodes = $doc->documentElement->findnodes('//*[substring(@tag,1,1)="1"]/*[@code="a" or @code="d" or @code="x"]');
181                 my $list = [ map { $_->textContent } @nodes ];
182                 $client->respond( $list ) if (_empty_check(join(' ',@$list), "metabib::${class}_field_entry"));
183         }
184         return undef;
185 }
186 for my $class ( qw/title author subject keyword series/ ) {
187         __PACKAGE__->register_method(
188                 api_name        => "open-ils.storage.authority.$class.see_also_from.controlled",
189                 method          => 'find_see_also_from_controlled',
190                 api_level       => 1,
191                 stream          => 1,
192                 cachable        => 1,
193         );
194 }
195
196
197 1;