File Coverage

blib/lib/Catmandu/Importer/Z3950.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             package Catmandu::Importer::Z3950;
2              
3 2     2   46894 use Catmandu::Sane;
  2         242596  
  2         13  
4 2     2   493 use Moo;
  2         4  
  2         11  
5 2     2   1317 use ZOOM;
  0            
  0            
6              
7             with 'Catmandu::Importer';
8              
9             # INFO:
10             # http://www.loc.gov/z3950/
11              
12             # Constants. -------------------------------------------------------------------
13              
14             use constant PREFERREDRECORDSYNTAX => 'USMARC';
15             use constant PORT => 210;
16             use constant QUERYTYPE => 'CQL';
17              
18             # Properties. ------------------------------------------------------------------
19              
20             # required.
21             has host => (is => 'ro', required => 1);
22             has databaseName => (is => 'ro', required => 1);
23             has query => (is => 'rw');
24              
25             # optional.
26             has port => (is => 'ro', default => sub { return PORT; });
27             has preferredRecordSyntax => (is => 'ro', default => sub { return PREFERREDRECORDSYNTAX; });
28             has user => (is => 'ro');
29             has password => (is => 'ro');
30             has queryType => (is =>'ro', default => sub { return QUERYTYPE; }); #
31              
32             # internal stuff.
33             has _conn => (is => 'ro');
34             has _qry => (is => 'ro');
35             has _currentRecordSet => (is => 'ro');
36             has _n => (is => 'ro', default => sub { 0 });
37              
38             # Internal Methods. ------------------------------------------------------------
39              
40             sub _setup_connection {
41             my ($self) = @_;
42              
43             my $conn = ZOOM::Connection->new(
44             $self->host,
45             $self->port,
46             databaseName => $self->databaseName
47             );
48              
49             $conn->option(preferredRecordSyntax => $self->preferredRecordSyntax) if $self->preferredRecordSyntax;
50             $conn->option(user => $self->user) if $self->user;
51             $conn->option(password => $self->password) if $self->password;
52              
53             return $conn;
54             }
55              
56             sub _get_query {
57             my ($self) = @_;
58             my $qry;
59              
60             if ($self->queryType eq 'CQL') {
61             $qry = ZOOM::Query::CQL->new($self->query); # 'title=dinosaur'
62             }
63             elsif ($self->queryType eq 'PQF') {
64             $qry = ZOOM::Query::PQF->new($self->query); # '@attr 1=4 dinosaur'
65             }
66              
67             return $qry;
68             }
69              
70             sub _nextRecord {
71             my ($self) = @_;
72            
73             unless ($self->_conn) {
74             $self->_clean;
75             $self->{_conn} = $self->_setup_connection;
76             }
77              
78             unless ($self->_qry) {
79             $self->_clean;
80             $self->{_qry} = $self->_get_query;
81             }
82              
83             unless ($self->_currentRecordSet) {
84             $self->{_currentRecordSet} = $self->{_conn}->search($self->{_qry});
85             $self->{_n} = 0;
86             }
87              
88             my $size = $self->_currentRecordSet->size() || 0;
89              
90             if ($self->{_n} < $size) {
91             return $self->_currentRecordSet->record($self->{_n}++)->get("raw");
92             }
93             else {
94             $self->_clean;
95             return undef;
96             }
97             }
98              
99             sub _clean {
100             my ($self) = @_;
101             $self->{_currentRecordSet}->destroy() if $self->{_currentRecordSet};
102             $self->{_qry}->destroy() if $self->{_qry};
103             $self->{_currentRecordSet} = undef;
104             $self->{_qry} = undef;
105             $self->{_n} = 0;
106             }
107              
108             sub DESTROY {
109             my ($self) = @_;
110            
111             if ($self->_conn) {
112             $self->_conn->destroy();
113             }
114             }
115              
116              
117             # Public Methods. --------------------------------------------------------------
118              
119             sub generator {
120             my ($self) = @_;
121              
122             return sub {
123             $self->_nextRecord;
124             };
125             }
126              
127              
128             # PerlDoc. ---------------------------------------------------------------------
129              
130             =head1 NAME
131              
132             Catmandu::Importer::Z3950 - Package that imports Z3950 data
133              
134             Returns the raw response. So the output depends on the preferredRecordSyntax.
135             You could use the MARC::Record package to parse the MARC output blob.
136              
137             =head1 SYNOPSIS
138              
139             use Catmandu::Importer::Z3950;
140              
141             my %attrs = (
142             host => 'z3950.loc.gov',
143             port => 7090,
144             databaseName => "Voyager",
145             preferredRecordSyntax => "USMARC",
146             queryType => 'PQF', # CQL or PQF
147             query => '@attr 1=4 dinosaur'
148             );
149              
150             my $importer = Catmandu::Importer::Z3950->new(%attrs);
151              
152             my $n = $importer->each(sub {
153             my $hashref = $_[0];
154             ...
155             });
156              
157             print "DONE. ($n). \n";
158              
159             `host`, `database` and `query` are required, `user` and `user` are optional.
160             `port`, `preferredRecordSyntax` and `queryType` will default to 210 'USMARC' and 'CQL' respectively.
161              
162             =cut
163              
164             =head1 REMARK
165              
166             This package uses the ZOOM package internally.
167             For more info visit: http://search.cpan.org/~mirk/Net-Z3950-ZOOM-1.28/lib/ZOOM.pod
168              
169             The ZOOM package has a hard dependency on YAZ toolkit.
170             For more info about YAZ, visit: https://www.indexdata.com/yaz
171              
172             Installing YAZ:
173             - (osx, using homebrew): brew install yaz
174             - (linux, using yum): yum install yaz libyaz
175              
176             =head1 SEE ALSO
177              
178             L
179              
180             =cut
181              
182             1;