File Coverage

blib/lib/Biblio/ILL/ISO/ISO.pm
Criterion Covered Total %
statement 48 114 42.1
branch 6 48 12.5
condition 0 3 0.0
subroutine 9 17 52.9
pod 2 7 28.5
total 65 189 34.3


line stmt bran cond sub pod time code
1             package Biblio::ILL::ISO::ISO;
2              
3             =head1 NAME
4              
5             Biblio::ILL::ISO - Perl extension for handling ISO 10161 interlibrary loan messages
6              
7             =cut
8              
9 3     3   2725 use Biblio::ILL::ISO::ILL_ASN_types_list;
  3         13  
  3         100  
10 3     3   4121 use Biblio::ILL::ISO::asn;
  3         17  
  3         94  
11 3     3   1261 use Biblio::ILL::ISO::1_0_10161_13_3;
  3         9  
  3         83  
12 3     3   2828 use Convert::ASN1;
  3         233319  
  3         232  
13 3     3   48 use Carp;
  3         7  
  3         644  
14              
15             =head1 VERSION
16              
17             Version 0.06
18              
19             =cut
20              
21             our $VERSION = '0.06';
22             #---------------------------------------------------------------------------
23             # Mods
24             # 0.06 - 2003.12.08 - Fixed t/02.types.t to compare eval'd (pre-existing)
25             # Data::Dumper output to existing hash, rather than
26             # trying to compare (pre-existing) Data::Dumper output
27             # to newly-dumped-from-existing-hash.
28             # 0.05 - 2003.10.26 - DamagedDetails is currently unsupported.
29             # 0.04 - 2003.09.07 - fixed the POD
30             # 0.03 - 2003.08.13 - added:
31             # Forward-Notification
32             # Shipped
33             # Conditional-Reply
34             # Cancel
35             # Cancel-Reply
36             # Received
37             # Recall
38             # Returned
39             # Checked-In
40             # Overdue
41             # Renew
42             # Renew-Answer
43             # Lost
44             # Damaged
45             # Message
46             # Status-Query
47             # Status-Or-Error-Report
48             # Expired
49             # 0.02 - 2003.07.27 - added Answer
50             # - added $self->{"ASN_TYPE"} for encode/decode
51             # 0.01 - 2003.07.15 - original version (Request)
52             #---------------------------------------------------------------------------
53              
54             =head1 DESCRIPTION
55              
56             The base class for the various ISO 10161 interlibrary loan message types
57             (eg: Biblio::ILL::ISO::Request and Biblio::ILL::ISO::Answer).
58              
59             It knows how to handle all (most?) of the ISO 10161 ASN.1 types (eg: ILLString and ClientId) that make up these messages.
60              
61             It knows how to do the ASN.1 encoding (from an existing message-type instance) and decoding (from an encoded message into a message class instance (eg: a Biblio::ILL::ISO::Request)).
62              
63             Treat this class as if it were completely virtual - a program should never instantiate Biblio::ILL::ISO::ISO, but rather the various derived classes (eg: Biblio::ILL:ISO::Request).
64              
65             =head1 EXPORT
66              
67             None.
68              
69             =head1 ERROR HANDLING
70              
71             Each of the underlying ISO 10161 ASN.1 types (eg: ILLString, SystemId) from which this class is derived is very picky about accepting the correct data, and will blow up quite spectacularly if you aren't nice to it.
72              
73             =cut
74              
75             # When I've got this figured out, add it to the ISA list
76             # Biblio::ILL::ISO::Extension
77              
78             # Currently unsupported:
79             #Biblio::ILL::ISO::DamagedDetails
80              
81 3     3   6026 BEGIN{@ISA = qw ( Biblio::ILL::ISO::ILLASNtype
82             Biblio::ILL::ISO::AccountNumber
83             Biblio::ILL::ISO::AlreadyForwarded
84             Biblio::ILL::ISO::AlreadyTriedListType
85             Biblio::ILL::ISO::Amount
86             Biblio::ILL::ISO::AmountString
87             Biblio::ILL::ISO::ClientId
88             Biblio::ILL::ISO::CostInfoType
89             Biblio::ILL::ISO::ConditionalResults
90             Biblio::ILL::ISO::CurrentState
91             Biblio::ILL::ISO::DateDue
92             Biblio::ILL::ISO::DateTime
93             Biblio::ILL::ISO::DeliveryAddress
94             Biblio::ILL::ISO::DeliveryService
95             Biblio::ILL::ISO::EDeliveryDetails
96             Biblio::ILL::ISO::ElectronicDeliveryService
97             Biblio::ILL::ISO::ElectronicDeliveryServiceSequence
98             Biblio::ILL::ISO::ENUMERATED
99             Biblio::ILL::ISO::ErrorReport
100             Biblio::ILL::ISO::EstimateResults
101             Biblio::ILL::ISO::ExpiryFlag
102             Biblio::ILL::ISO::Flag
103             Biblio::ILL::ISO::GeneralProblem
104             Biblio::ILL::ISO::HistoryReport
105             Biblio::ILL::ISO::HoldPlacedResults
106             Biblio::ILL::ISO::ILLAPDUtype
107             Biblio::ILL::ISO::ILLServiceType
108             Biblio::ILL::ISO::ILLServiceTypeSequence
109             Biblio::ILL::ISO::ILLString
110             Biblio::ILL::ISO::IntermediaryProblem
111             Biblio::ILL::ISO::ISODate
112             Biblio::ILL::ISO::ISOTime
113             Biblio::ILL::ISO::ItemId
114             Biblio::ILL::ISO::ItemType
115             Biblio::ILL::ISO::LocationInfo
116             Biblio::ILL::ISO::LocationInfoSequence
117             Biblio::ILL::ISO::LocationsResults
118             Biblio::ILL::ISO::MediumType
119             Biblio::ILL::ISO::MostRecentService
120             Biblio::ILL::ISO::NameOfPersonOrInstitution
121             Biblio::ILL::ISO::PersonOrInstitutionSymbol
122             Biblio::ILL::ISO::PlaceOnHoldType
123             Biblio::ILL::ISO::PostalAddress
124             Biblio::ILL::ISO::Preference
125             Biblio::ILL::ISO::ProtocolVersionNum
126             Biblio::ILL::ISO::ProviderErrorReport
127             Biblio::ILL::ISO::ReasonLocsProvided
128             Biblio::ILL::ISO::ReasonNoReport
129             Biblio::ILL::ISO::ReasonUnfilled
130             Biblio::ILL::ISO::ReasonWillSupply
131             Biblio::ILL::ISO::ReportSource
132             Biblio::ILL::ISO::RequesterCHECKEDIN
133             Biblio::ILL::ISO::RequesterOptionalMessageType
134             Biblio::ILL::ISO::RequesterSHIPPED
135             Biblio::ILL::ISO::ResponderOptionalMessageType
136             Biblio::ILL::ISO::ResponderRECEIVED
137             Biblio::ILL::ISO::ResponderRETURNED
138             Biblio::ILL::ISO::ResultsExplanation
139             Biblio::ILL::ISO::RetryResults
140             Biblio::ILL::ISO::SearchType
141             Biblio::ILL::ISO::SecurityProblem
142             Biblio::ILL::ISO::SendToListType
143             Biblio::ILL::ISO::SendToListTypeSequence
144             Biblio::ILL::ISO::SEQUENCE_OF
145             Biblio::ILL::ISO::ServiceDateTime
146             Biblio::ILL::ISO::ShippedConditions
147             Biblio::ILL::ISO::ShippedServiceType
148             Biblio::ILL::ISO::ShippedVia
149             Biblio::ILL::ISO::StateTransitionProhibited
150             Biblio::ILL::ISO::StatusReport
151             Biblio::ILL::ISO::SupplyDetails
152             Biblio::ILL::ISO::SupplyMediumInfoType
153             Biblio::ILL::ISO::SupplyMediumInfoTypeSequence
154             Biblio::ILL::ISO::SupplyMediumType
155             Biblio::ILL::ISO::SystemAddress
156             Biblio::ILL::ISO::SystemId
157             Biblio::ILL::ISO::ThirdPartyInfoType
158             Biblio::ILL::ISO::TransactionId
159             Biblio::ILL::ISO::TransactionIdProblem
160             Biblio::ILL::ISO::TransactionResults
161             Biblio::ILL::ISO::TransactionType
162             Biblio::ILL::ISO::TransportationMode
163             Biblio::ILL::ISO::UnableToPerform
164             Biblio::ILL::ISO::UnfilledResults
165             Biblio::ILL::ISO::UnitsPerMediumType
166             Biblio::ILL::ISO::UserErrorReport
167             Biblio::ILL::ISO::WillSupplyResults
168             );
169             }
170              
171              
172             # No sense re-preparing all the time....
173             our $_asn_initialized = 0;
174             our $_asn = "";
175              
176              
177              
178             #---------------------------------------------------------------
179             #
180             #---------------------------------------------------------------
181             sub _init {
182 1     1   539 print "---------------\nInitializing\n";
183 1         52 print " Creating ASN1 object for extension....";
184 1         13 my $asn_ext = Convert::ASN1->new;
185 1         167 print "ok\n";
186 1         45 print " Preparing extension 1_0_10161_13_3....";
187 1         8 $asn_ext->prepare( $Biblio::ILL::ISO::1_0_10161_13_3::desc );
188 1 50       12523 if ($asn_ext->error()) {
189 0         0 print "\n" . $asn_ext->error();
190 0         0 exit(1);
191             }
192 1         258 print "ok\n";
193              
194 1         48 print " Creating ASN1 object....";
195 1         10 $_asn = Convert::ASN1->new;
196 1         142 print "ok\n";
197 1         37 print " Preparing ASN1....";
198 1         7 $_asn->prepare( $Biblio::ILL::ISO::asn::desc );
199 1 50       175893 if ($_asn->error()) {
200 0         0 print "\n" . $_asn->error();
201 0         0 exit(1);
202             }
203 1         294 print "ok\n";
204              
205             #print "\n-- asn desc ------\n" . $Biblio::ILL::ISO::asn::desc . "\n-- end asn desc ------\n";
206              
207             #print "\n\n\n-- Dumping ASN1 -------\n";
208             #$_asn->asn_hexdump();
209             #print "\n-- End Dump of ASN1 -------\n\n";
210              
211 1         4 $_asn_initialized = 1;
212              
213 1         53 print " Registering extension(s)....";
214             # This is what is *should* be:
215             #$_asn->registeroid("1.0.10161.13.3",$asn_ext->find("APDU-Delivery-Info"));
216             # This is what it *is* (in the test record from Simon Fraser University):
217 1         8 $_asn->registeroid("1",$asn_ext->find("APDU-Delivery-Info"));
218 1         198 print "ok\n---------------\n";
219              
220             }
221              
222              
223             #---------------------------------------------------------------
224             #
225             #---------------------------------------------------------------
226             sub new {
227 0     0 1 0 my $class = shift;
228 0         0 my $self = {};
229              
230 0 0       0 &_init() if (not $_asn_initialized);
231 0         0 $self->{"ASN_TYPE"} = "This is a base class";
232 0   0     0 bless($self, ref($class) || $class);
233 0         0 return ($self);
234             }
235              
236             #---------------------------------------------------------------
237             #
238             #---------------------------------------------------------------
239             sub encode {
240 20     20 0 35 my $self = shift;
241              
242 20         125 my $href = $self->as_asn();
243              
244             # Debugging:
245             # Verify that this is a 'Convert::ASN1' thingy
246             #print ">>>>>>>>> " . ref($_asn) . "<<<<<<<<<<\n";
247              
248             #my $asn = $_asn->find( 'ILL-Request' ) or warn $_asn->error;
249             #my $asn = $_asn->find( 'ILL-Answer' ) or warn $_asn->error;
250 20 50       107 my $asn = $_asn->find( $self->{"ASN_TYPE"} ) or warn $_asn->error;
251              
252 20 50       398 print STDERR "\nNo asn?\n" unless (defined $asn);
253              
254             #print "-=-=-=-=-=-=-=-\n";
255             #print $self->debug($href);
256             #print "-=-=-=-=-=-=-=-\n";
257              
258 20 50       65 my $pdu = $asn->encode( $href ) or warn $asn->error;
259              
260 20         30875 return $pdu;
261             }
262              
263              
264             #---------------------------------------------------------------
265             #
266             #---------------------------------------------------------------
267             sub decode {
268 0     0 0 0 my $self = shift;
269 0         0 my $pdu = shift;
270              
271 0 0       0 my $asn = $_asn->find( $self->{"ASN_TYPE"} ) or warn $_asn->error;
272              
273             # The big question:
274             # How, during the decode of a PDU that contains an Extension,
275             # do we tell it to start using that extension's ASN.1 definition?
276 0 0       0 my $href = $asn->decode( $pdu ) or warn $asn->error;
277              
278 0         0 return $href;
279             }
280              
281             #---------------------------------------------------------------
282             #
283             #---------------------------------------------------------------
284             sub as_pretty_string {
285 0     0 1 0 my $self = shift;
286              
287 0         0 print "--base class (ISO)--\n";
288              
289 0         0 return;
290             }
291              
292             #---------------------------------------------------------------
293             #
294             #---------------------------------------------------------------
295             sub write {
296 20     20 0 19671 my $self = shift;
297 20         42 my $fname = shift;
298              
299 20         139 my $pdu = $self->encode();
300 20 50       2483 if (open(OUTFILE,"> $fname")) {
301 20         374 print OUTFILE $pdu;
302 20         1064 close OUTFILE;
303             }
304 20         91 return $pdu;
305             }
306              
307             #---------------------------------------------------------------
308             #
309             #---------------------------------------------------------------
310             sub read {
311 0     0 0   my $self = shift;
312 0           my $fname = shift;
313 0           my $debug_flag = shift;
314              
315             # must undefine $INPUT_RECORD_SEPARATOR to slurp entire file
316 0           local $/;
317              
318 0 0         if (open(INFILE, "< $fname")) {
319 0           my $pdu = ;
320 0           close INFILE;
321              
322 0 0         my $asn = $_asn->find( $self->{"ASN_TYPE"} )
323             or warn $_asn->error;
324              
325 0 0         if (defined $debug_flag) {
326 0 0         if ($debug_flag == 1) {
327 0           $asn->dump();
328             } else {
329 0           $asn->hexdump();
330             }
331             }
332              
333 0 0         my $out = $asn->decode( $pdu ) or warn $asn->error;
334              
335             ## This is all from the "old" way....
336             ##
337             #print $out->{"requester-note"}{"generalstring"} . "\n";
338             #debug_print($out->{"requester-note"});
339             ##
340             # How can I have the call be $obj->read("filename"), and have the
341             # read-in data replace the existing data?
342             ##
343             # doesn't work
344             # $self = $out;
345             ##
346             # This is a pain
347             # $self->protocol_version_num( $out->{"protocol-version-num"} );
348             # $self->transaction_id( $out->{"transaction-id"} );
349             # :
350             # :
351             ##
352             # This works if the call is like $obj = $obj->read("filename")
353             #return $self->new(%$out);
354             ##
355              
356 0           return $out;
357              
358             } else {
359 0           croak "$!";
360             }
361             }
362              
363              
364             #---------------------------------------------------------------
365             #
366             #---------------------------------------------------------------
367             sub debug {
368 0     0 0   my $self = shift;
369 0           my $ref = shift;
370              
371 0 0         $ref = $self unless ($ref);
372              
373 0           return _debug_print($ref);
374             }
375              
376              
377             #---------------------------------------------------------------
378             #
379             #---------------------------------------------------------------
380             sub _debug_print {
381             # my $self = shift;
382 0     0     my ($ref, $indent) = @_;
383 0           my $s = "";
384 0 0         $indent = 0 if (not defined($indent));
385              
386             # return _debug_print_hash($self) if (not defined $ref);
387              
388 0 0         return _debug_print_hash($ref, $indent) if (ref($ref) eq "HASH");
389 0 0         return _debug_print_array($ref, $indent) if (ref($ref) eq "ARRAY");
390              
391 0           for ($i=0; $i < $indent; $i++) {
392 0           $s .= " ";
393             }
394              
395 0 0         return ("$s$ref\n") if (not ref($ref));
396              
397             # If it's not any of the above, it is (should be?) an object,
398             # which we treat as a hash. Cheezy, I know - I can't think
399             # of a better way.
400 0           return _debug_print_hash($ref, $indent);
401             }
402              
403              
404             #---------------------------------------------------------------
405             #
406             #---------------------------------------------------------------
407             sub _debug_print_hash {
408 0     0     my ($href, $indent) = @_;
409 0           my $s = "";
410 0 0         $indent = 0 if (not defined($indent));
411              
412 0           foreach $key (sort keys %$href) {
413             # There's got to be a better way :-)
414 0           for ($i=0; $i < $indent; $i++) {
415 0           $s .= " ";
416             }
417              
418 0           $s .= "$key ";
419 0 0         $s .= "=>\n" unless (ref($href->{$key}) eq "HASH");
420 0 0         $s .= "\n" if (ref($href->{$key}) eq "HASH");
421 0 0         $s .= "\n" if (ref($href->{$key}) eq "ARRAY");
422 0           $s .= _debug_print($href->{$key}, $indent+4);
423             }
424 0           return $s;
425             }
426              
427              
428             #---------------------------------------------------------------
429             #
430             #---------------------------------------------------------------
431             sub _debug_print_array {
432 0     0     my ($aref, $indent) = @_;
433 0           my $s = "";
434 0 0         $indent = 0 if (not defined($indent));
435              
436 0           foreach $elm (@$aref) {
437             # There's got to be a better way :-)
438 0           for ($i=0; $i < $indent; $i++) {
439 0           $s .= " ";
440             #print "."; # DC - debugging
441             }
442             #print "\n"; # DC - debugging
443 0           $s .= _debug_print($elm, $indent+4);
444             }
445 0           return $s;
446             }
447              
448             1;