1 package OpenILS::Application::Search;
2 use OpenILS::Application;
3 use base qw/OpenILS::Application/;
4 use strict; use warnings;
5 use OpenSRF::Utils::JSON;
6 use OpenSRF::Utils::Logger qw(:logger);
8 use OpenILS::Utils::Fieldmapper;
9 use OpenILS::Utils::ModsParser;
10 use OpenSRF::Utils::SettingsClient;
11 use OpenSRF::Utils::Cache;
13 use OpenILS::Application::Search::Biblio;
14 use OpenILS::Application::Search::Authority;
15 use OpenILS::Application::Search::Z3950;
16 use OpenILS::Application::Search::Zips;
17 use OpenILS::Application::Search::CNBrowse;
18 use OpenILS::Application::Search::Serial;
21 use OpenILS::Application::AppUtils;
23 use Time::HiRes qw(time);
24 use OpenSRF::EX qw(:try);
28 # Houses generic search utilites
31 OpenILS::Application::Search::Zips->initialize();
32 OpenILS::Application::Search::Biblio->initialize();
36 OpenILS::Application::Search::Z3950->child_init;
41 # ------------------------------------------------------------------
42 # Create custom dictionaries like so:
43 # aspell --lang=en create master ./oils_authority.dict < /tmp/words
44 # where /tmp/words is a space separated list of words
45 # ------------------------------------------------------------------
47 __PACKAGE__->register_method(
48 method => "spellcheck",
49 api_name => "open-ils.search.spellcheck",
51 desc => 'Returns alternate spelling suggestions',
55 desc => 'Word or phrase to return alternate spelling suggestions for',
59 name => 'Dictionary class',
60 desc => 'Alternate configured dictionary to use (optional)',
65 desc => 'Array with a suggestions hash for each word in the phrase, like: '
66 . q# [{ word: original_word, suggestions: [sug1, sug2, ...], found: 1 }, ... ] #
67 . 'The "found" value will be 1 if the word was found in the dictionary, 0 otherwise.',
73 my $speller = Text::Aspell->new();
76 my( $self, $client, $phrase, $class ) = @_;
78 return [] unless $phrase; # nothing to check, abort.
80 my $conf = OpenSRF::Utils::SettingsClient->new;
83 my @conf_path = (apps => 'open-ils.search' => app_settings => spelling_dictionary => $class);
85 if( my $dict = $conf->config_value(@conf_path) ) {
86 $speller->set_option('master', $dict);
87 $logger->debug("spelling dictionary set to $dict");
90 $speller->set_option('ignore-case', 'true');
94 for my $word (split(/\s+/,$phrase) ) {
96 my @suggestions = $speller->suggest($word);
99 for my $sug (@suggestions) {
101 # suggestion matches alternate case of original word
102 next if lc($sug) eq lc($word);
104 # suggestion matches alternate case of already suggested word
105 next if grep { lc($sug) eq lc($_) } @trimmed;
107 push(@trimmed, $sug);
113 suggestions => (@trimmed) ? [@trimmed] : undef,
114 found => $speller->check($word)