d513f23b06349b26b9b5012130b67acf1377bf09
[Evergreen.git] / Open-ILS / src / perlmods / OpenILS / Application / Search / Z3950.pm
1 #!/usr/bin/perl
2 package OpenILS::Application::Search::Z3950;
3 use strict; use warnings;
4 use base qw/OpenSRF::Application/;
5
6
7 use Net::Z3950;
8 use MARC::Record;
9 use MARC::File::XML;
10 use OpenSRF::Utils::SettingsClient;
11
12 use OpenILS::Utils::FlatXML;
13 use OpenILS::Application::Cat::Utils;
14 use OpenILS::Application::AppUtils;
15
16 use OpenSRF::Utils::Logger qw/$logger/;
17
18 use OpenSRF::EX qw(:try);
19
20 my $utils = "OpenILS::Application::Cat::Utils";
21 my $apputils = "OpenILS::Application::AppUtils";
22
23 use OpenILS::Utils::ModsParser;
24 use Data::Dumper;
25
26 my $output = "USMARC"; # only support output for now
27 my $host;
28 my $port;
29 my $database;
30 my $attr;
31 my $username;
32 my $password;
33
34 my $settings_client;
35
36 sub initialize {
37         $settings_client = OpenSRF::Utils::SettingsClient->new();
38         $host                   = $settings_client->config_value("z3950", "oclc", "host");
39         $port                   = $settings_client->config_value("z3950", "oclc", "port");
40         $database       = $settings_client->config_value("z3950", "oclc", "db");
41         $attr                   = $settings_client->config_value("z3950", "oclc", "attr");
42         $username       = $settings_client->config_value("z3950", "oclc", "username");
43         $password       = $settings_client->config_value("z3950", "oclc", "password");
44
45         $logger->info("z3950:  Search App connecting:  host=$host, port=$port, ".
46                 "db=$database, attr=$attr, username=$username, password=$password" );
47 }
48
49
50 __PACKAGE__->register_method(
51         method  => "marcxml_to_brn",
52         api_name        => "open-ils.search.z3950.marcxml_to_brn",
53 );
54
55 sub marcxml_to_brn {
56
57         my( $self, $client, $marcxml ) = @_;
58
59         my $tree;
60         my $err;
61
62         my $flat = OpenILS::Utils::FlatXML->new( xml => $marcxml ); 
63         my $doc = $flat->xml_to_doc();
64
65         if( $doc->documentElement->nodeName =~ /collection/io ) {
66                 $doc->setDocumentElement( $doc->documentElement->firstChild );
67                 $doc->documentElement->setNamespace(
68                                 "http://www.loc.gov/MARC21/slim", undef, 1);
69         }
70         $logger->debug("z3950: Turning doc into a nodeset...");
71
72         try {
73                 my $nodes = OpenILS::Utils::FlatXML->new->xmldoc_to_nodeset($doc);
74                 $logger->debug("z3950: turning nodeset into tree");
75                 $tree = $utils->nodeset2tree( $nodes->nodeset );
76         } catch Error with {
77                 $err = shift;
78         };
79
80         if($err) {
81                 $logger->error("z3950: Error turning doc into nodeset/node tree: $err");
82                 return undef;
83         } else {
84                 return $tree;
85         }
86 }
87
88 __PACKAGE__->register_method(
89         method  => "z39_search_by_string",
90         api_name        => "open-ils.search.z3950.raw_string",
91 );
92
93 sub z39_search_by_string {
94
95         my( $self, $client, $server, 
96                         $port, $db, $search, $user, $pw ) = @_;
97
98         throw OpenSRF::EX::InvalidArg unless( 
99                         $server and $port and $db and $search);
100
101
102         $logger->info("Z3950: searching for $search");
103
104         $user ||= "";
105         $pw     ||= "";
106
107         my $conn = new Net::Z3950::Connection(
108                 $server, $port, 
109                 databaseName                            => $db, 
110                 user                                                    => $user,
111                 password                                                => $pw,
112                 preferredRecordSyntax   => $output, 
113         );
114
115
116         my $rs = $conn->search( $search );
117         if(!$rs) {
118                 throw OpenSRF::EX::ERROR ("z39 search failed"); 
119         }
120
121         # We want nice full records
122         $rs->option(elementSetName => "f");
123
124         my $records = [];
125         my $hash = {};
126
127         $hash->{count} =  $rs->size();
128         $logger->info("Z3950: Search recovered " . $hash->{count} . " records");
129
130         # until there is a more graceful way to handle this
131         if($hash->{count} > 20) { return $hash; }
132
133         for( my $x = 0; $x != $hash->{count}; $x++ ) {
134                 $logger->debug("z3950: Churning on z39 record count $x");
135
136                 my $rec = $rs->record($x+1);
137                 my $marc = MARC::Record->new_from_usmarc($rec->rawdata());
138
139                 my $marcxml = $marc->as_xml();
140                 my $mods;
141                         
142                 my $u = OpenILS::Utils::ModsParser->new();
143                 $u->start_mods_batch( $marcxml );
144                 $mods = $u->finish_mods_batch();
145
146                 push @$records, { 'mvr' => $mods, 'marcxml' => $marcxml };
147         }
148
149         $logger->debug("z3950: got here near the end with " . scalar(@$records) . " records." );
150
151         $hash->{records} = $records;
152         return $hash;
153
154 }
155
156
157 __PACKAGE__->register_method(
158         method  => "import_search",
159         api_name        => "open-ils.search.z3950.import",
160 );
161
162 sub import_search {
163         my($self, $client, $user_session, $string) = @_;
164
165         my $user_obj = 
166                 $apputils->check_user_session( $user_session ); #throws EX on error
167
168         return $self->z39_search_by_string(
169                 $client, $host, $port, $database, 
170                         "\@attr 1=$attr \"$string\"", $username, $password );
171 }
172
173
174
175
176 1;