#!/usr/bin/perl #################################################################### # # Michael Doran, University of Texas at Arlington # [log in to unmask] # # @ OCLC Developer House # February 3-7, 2014 # # Proof-of-concept for extracting, parsing, and displaying # a library's hours from institutional data in the # OCLC WorldCat Registry. # see: http://www.worldcat.org/registry/Institutions # # Requires non-core Perl module(s) and CA Root certs file # #################################################################### use strict; #################################################################### # Configuration -- start #################################################################### # OCLC organization number (not symbol) for main library unit # aka "Institution Registry ID" # examples: # 2928 for University of Texas at Arlington Library # 128807 for OCLC WorldShare Platform Sandbox Institution #my $oclc_org_no = '2928'; my $oclc_org_no = '128807'; # Path to SSL Root Certificate Authority bundle file # - required for HTTPS gets my $cert_file = '../../ssl.crt/ca-bundle.crt'; # Labels for normal and special hours display my $normal_hrs_label = 'REGULAR HOURS'; my $special_hrs_label = 'SPECIAL HOURS'; #################################################################### # Configuration -- end #################################################################### # Required modules use LWP::UserAgent; use RDF::Helper; #use Date::Calc; # Not used yet, but needed for further development my $oclc_org_base_url = "https://www.worldcat.org/wcr/organization/resource/$oclc_org_no"; my $content = ''; my $normal_hours_uri = ''; my $normal_hours_rdf = ''; my $special_hours_uri = ''; my $special_hours_rdf = ''; my $null = undef; my $ua = LWP::UserAgent->new; $ua->timeout(10); $ua->default_header('Accept' => 'application/rdf+xml'); $ua->ssl_opts( SSL_ca_file => "$cert_file" ); my $rdf = RDF::Helper->new( BaseInterface => 'RDF::Trine', namespaces => { rdf => "http://www.w3.org/1999/02/22-rdf-syntax-ns#", wcir => "http://purl.org/oclc/ontology/wcir/", schema => "http://schema.org/", rdfs => "http://www.w3.org/2000/01/rdf-schema#", umbel => "http://umbel.org/umbel#", foaf => "http://xmlns.com/foaf/0.1/", library => "http://purl.org/library/", xsi => "http://www.w3.org/2001/XMLSchema-instance", dcterms => "http://purl.org/dc/terms/" }, ExpandQNames => 1 ); GetInstData(); NormalHours($normal_hours_uri); SpecialHours($special_hours_uri); exit(0); ######################### # GetRDFDoc ######################### sub GetRDFDoc { my ($uri) = @_; my $response = $ua->get("$uri"); if ($response->is_success) { $content = $response->decoded_content; } else { die $response->status_line; } } ######################### # GetInstData ######################### sub GetInstData { GetRDFDoc("$oclc_org_base_url"); $rdf->include_rdfxml(xml => $content); my $hash_ref = $rdf->tied_property_hash($oclc_org_base_url); my %prop_value_hash = %$hash_ref; my $institution = $prop_value_hash{'wcir:institutionName'}; my $library = $prop_value_hash{'wcir:unitName'}; $normal_hours_uri = $prop_value_hash{'wcir:normalHours'}; $special_hours_uri = $prop_value_hash{'wcir:specialHours'}; print "\n" . "$institution" . "\n"; if ($library) { print "$library" . "\n"; } } ######################### # NormalHours ######################### sub NormalHours { my ($normal_hours_uri) = @_; unless ($normal_hours_uri) { return; } print "\n" . "$normal_hrs_label" . "\n\n"; $normal_hours_rdf = GetRDFDoc("$normal_hours_uri"); $rdf->include_rdfxml(xml => $normal_hours_rdf); my $norm_hours_hash_ref = $rdf->tied_property_hash($normal_hours_uri); my %norm_value_hash = %$norm_hours_hash_ref; foreach my $week_day ('Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sunday') { my $day_hash_ref = $rdf->tied_property_hash("$normal_hours_uri#$week_day"); my %day_hash = %$day_hash_ref; my $open_status = $day_hash{'wcir:openStatus'}; my $open_hour = $day_hash{'wcir:opens'}; my $close_hour = $day_hash{'wcir:closes'}; if ($open_status eq "Open24Hours") { print "$week_day open 24 hours" . "\n"; } elsif ($open_status eq "Open") { print "$week_day open from $open_hour to $close_hour" . "\n"; } elsif ($open_status eq "Closed") { print "$week_day is closed" . "\n"; } } } ######################### # SpecialHours ######################### sub SpecialHours { unless ($special_hours_uri) { return; } print "\n" . "$special_hrs_label" . "\n"; $special_hours_rdf = GetRDFDoc ("$special_hours_uri"); $rdf->include_rdfxml(xml => $special_hours_rdf); my $spec_hours_hash_ref = $rdf->tied_property_hash($special_hours_uri); my %spec_value_hash = %$spec_hours_hash_ref; # problem area here - fixed # - when single value returned to $hoursSpecs, can't dereference # - if don't deference, can't handle when it is an array reference returned, # e.g. ARRAY(0x7fd4c2b34f40) # Solution: test with perl 'ref' function my $hoursSpecs = $spec_value_hash{'wcir:hoursSpecifiedBy'}; my @deref_hoursSpecs; if (ref($hoursSpecs)) { @deref_hoursSpecs = @$hoursSpecs; } else { @deref_hoursSpecs = $hoursSpecs; } my %spec_hours_instances; foreach my $i (@deref_hoursSpecs) { my $day_hash_ref = $rdf->tied_property_hash("$i"); my %day_hash = %$day_hash_ref; my $valid_from = $day_hash{'wcir:validFrom'}; $spec_hours_instances{$valid_from} = $i; } foreach my $key (sort keys %spec_hours_instances) { print "\n"; my $day_hash_ref = $rdf->tied_property_hash("$spec_hours_instances{$key}"); my %day_hash = %$day_hash_ref; my $description = $day_hash{'wcir:description'}; my $open_status = $day_hash{'wcir:openStatus'}; my $open_hour = $day_hash{'wcir:opens'}; my $close_hour = $day_hash{'wcir:closes'}; my $valid_from = $day_hash{'wcir:validFrom'}; my $valid_to = $day_hash{'wcir:validTo'}; print "$description" . "\n"; if ($open_status eq "Open24Hours") { print "Open 24 hours" . "\n"; } elsif ($open_status eq "Open") { print "Open from $open_hour to $close_hour" . "\n"; } elsif ($open_status eq "Closed") { print "Closed" . "\n"; } print "From $valid_from to $valid_to" . "\n"; } }