2 package OpenILS::Application::Search::Z3950;
3 use strict; use warnings;
4 use base qw/OpenSRF::Application/;
10 use OpenSRF::Utils::SettingsClient;
12 use OpenILS::Utils::FlatXML;
13 use OpenILS::Application::Cat::Utils;
14 use OpenILS::Application::AppUtils;
16 use OpenSRF::Utils::Logger qw/$logger/;
18 use OpenSRF::EX qw(:try);
20 my $utils = "OpenILS::Application::Cat::Utils";
21 my $apputils = "OpenILS::Application::AppUtils";
23 use OpenILS::Utils::ModsParser;
26 my $output = "USMARC"; # only support output for now
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");
45 $logger->info("z3950: Search App connecting: host=$host, port=$port, ".
46 "db=$database, attr=$attr, username=$username, password=$password" );
50 __PACKAGE__->register_method(
51 method => "marcxml_to_brn",
52 api_name => "open-ils.search.z3950.marcxml_to_brn",
57 my( $self, $client, $marcxml ) = @_;
62 my $flat = OpenILS::Utils::FlatXML->new( xml => $marcxml );
63 my $doc = $flat->xml_to_doc();
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);
70 $logger->debug("z3950: Turning doc into a nodeset...");
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 );
81 $logger->error("z3950: Error turning doc into nodeset/node tree: $err");
88 __PACKAGE__->register_method(
89 method => "z39_search_by_string",
90 api_name => "open-ils.search.z3950.raw_string",
93 sub z39_search_by_string {
95 my( $self, $client, $server,
96 $port, $db, $search, $user, $pw ) = @_;
98 throw OpenSRF::EX::InvalidArg unless(
99 $server and $port and $db and $search);
102 $logger->info("Z3950: searching for $search");
107 my $conn = new Net::Z3950::Connection(
112 preferredRecordSyntax => $output,
116 my $rs = $conn->search( $search );
118 throw OpenSRF::EX::ERROR ("z39 search failed");
121 # We want nice full records
122 $rs->option(elementSetName => "f");
127 $hash->{count} = $rs->size();
128 $logger->info("Z3950: Search recovered " . $hash->{count} . " records");
130 # until there is a more graceful way to handle this
131 if($hash->{count} > 20) { return $hash; }
133 for( my $x = 0; $x != $hash->{count}; $x++ ) {
134 $logger->debug("z3950: Churning on z39 record count $x");
136 my $rec = $rs->record($x+1);
137 my $marc = MARC::Record->new_from_usmarc($rec->rawdata());
139 my $marcxml = $marc->as_xml();
142 my $u = OpenILS::Utils::ModsParser->new();
143 $u->start_mods_batch( $marcxml );
144 $mods = $u->finish_mods_batch();
146 push @$records, { 'mvr' => $mods, 'marcxml' => $marcxml };
149 $logger->debug("z3950: got here near the end with " . scalar(@$records) . " records." );
151 $hash->{records} = $records;
157 __PACKAGE__->register_method(
158 method => "import_search",
159 api_name => "open-ils.search.z3950.import",
163 my($self, $client, $user_session, $string) = @_;
166 $apputils->check_user_session( $user_session ); #throws EX on error
168 return $self->z39_search_by_string(
169 $client, $host, $port, $database,
170 "\@attr 1=$attr \"$string\"", $username, $password );