From 00eff51ccd2b2fa5a882dea4ceb7c67575ecbe4d Mon Sep 17 00:00:00 2001 From: Mike Rylander Date: Wed, 26 Jan 2022 16:36:27 -0500 Subject: [PATCH] LP#1729620: Polish up sets and visibility tests This commit improves the logic needed to control record inclusion in OAI Sets. Sets for bib records are currently based on copy visibility, Located URI visibility, or bib source. Generally useful combinations are generated for item, Located URI, and transcendant [sic] bib sources. Sets for authority records are based on the browse axis of the heading for the record. All generated Sets for bib records currently test for effective search visibilty on the three described components. In order to retrieve item data from a specific branch of the org tree, a harvester must use a Set that contains COPIES:. The hierarchial shortnames of the org units follow the colon, so in a freshly installed system a Set with the setSpec of COPIES:CONS:SYS2:BR3 will retrieve all bib records that have visible copies at BR3, and include only the item data for that org unit. To retrieve records with Located URIs, which behave in the heirarchical reverse of copies by limiting display to those org units "inside" the branch of the tree where the licensing "lives", a harvester should supply a setSpec with an org unit shortname that would display the Located URI. For example: LURIS:CONS:SYS2:BR3 Note: the LURI: org unit is also used to restrict any item data that may be available for LURI-filtered records. To retrive records are in a transcendant [sic] bib source, a harvester can used a setSpec starting with SOURCES: followed by the source name. To harvest all records, including deleted records, simply omit the setSpec from the request. All item data will be included. Signed-off-by: Mike Rylander Signed-off-by: Jane Sandberg --- Open-ILS/examples/fm_IDL.xml | 12 +- Open-ILS/examples/opensrf.xml.example | 3 +- .../lib/OpenILS/Application/SuperCat/OAI.pm | 143 ++++++++++++++------- .../src/perlmods/lib/OpenILS/WWW/SuperCat/OAI.pm | 112 ++++++++++------ .../src/sql/Pg/upgrade/XXXX.schema.oai_views.sql | 27 +++- Open-ILS/xsl/OAI2_MARC21slim.xsl | 18 --- Open-ILS/xsl/OAI2_OAIDC.xsl | 13 -- 7 files changed, 198 insertions(+), 130 deletions(-) delete mode 100644 Open-ILS/xsl/OAI2_MARC21slim.xsl delete mode 100644 Open-ILS/xsl/OAI2_OAIDC.xsl diff --git a/Open-ILS/examples/fm_IDL.xml b/Open-ILS/examples/fm_IDL.xml index 878ea54e27..e3bdba88d4 100644 --- a/Open-ILS/examples/fm_IDL.xml +++ b/Open-ILS/examples/fm_IDL.xml @@ -75,21 +75,21 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - - - + + - - - + + diff --git a/Open-ILS/examples/opensrf.xml.example b/Open-ILS/examples/opensrf.xml.example index ca1ff3eaf3..05d945fdeb 100644 --- a/Open-ILS/examples/opensrf.xml.example +++ b/Open-ILS/examples/opensrf.xml.example @@ -834,12 +834,11 @@ vim:et:ts=4:sw=4: http://www.openarchives.org/OAI/2.0/oai_dc/ http://www.openarchives.org/OAI/2.0/oai_dc.xsd - OAI2_OAIDC.xsl + MARC21slim2OAIDC.xsl http://www.loc.gov/MARC21/slim http://www.loc.gov/standards/marcxml/schema/MARC21slim.xsd - OAI2_MARC21slim.xsl --> diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/SuperCat/OAI.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/SuperCat/OAI.pm index 89107353d6..c2a83b6fc8 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/SuperCat/OAI.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/SuperCat/OAI.pm @@ -74,7 +74,7 @@ sub child_init { OpenSRF::Utils::SettingsClient ->new ->config_value( dirs => 'xsl' ). - "/OAI2_OAIDC.xsl" + "/MARC21slim2OAIDC.xsl" ); # and stash a transformer $record_xslt{oai_dc}{xslt} = $_xslt->parse_stylesheet( $xslt ); @@ -82,28 +82,18 @@ sub child_init { $record_xslt{oai_dc}{schema_location} = 'http://www.openarchives.org/OAI/2.0/oai_dc.xsd'; } - # If not defined, use the natural marcxml metadata setting - unless ( exists $record_xslt{marcxml}) { - $logger->info('Loading default marcxml schema') ; - my $xslt = $_parser->parse_file( - OpenSRF::Utils::SettingsClient - ->new - ->config_value( dirs => 'xsl' ). - "/OAI2_MARC21slim.xsl" - ); - # and stash a transformer - $record_xslt{marcxml}{xslt} = $_xslt->parse_stylesheet( $xslt ); - $record_xslt{marcxml}{namespace_uri} = 'http://www.loc.gov/MARC21/slim'; - $record_xslt{marcxml}{docs} = 'http://www.loc.gov/MARC21/slim'; - $record_xslt{marcxml}{schema_location} = 'http://www.loc.gov/standards/marcxml/schema/MARC21slim.xsd'; - } + # Store info about the natural marcxml metadata setting. We don't actually use this to drive XSLT, but we can report support. + $logger->info('Loading default marcxml schema') ; + $record_xslt{marcxml}{namespace_uri} = 'http://www.loc.gov/MARC21/slim'; + $record_xslt{marcxml}{docs} = 'http://www.loc.gov/MARC21/slim'; + $record_xslt{marcxml}{schema_location} = 'http://www.loc.gov/standards/marcxml/schema/MARC21slim.xsd'; # Load the mapping of 852 holdings. my $copies = OpenSRF::Utils::SettingsClient->new->config_value(apps => 'open-ils.supercat')->{'app_settings'}->{'oai'}->{'copies'} ; if ( $copies ) { foreach my $subfield_code (keys %$copies) { my $value = $copies->{$subfield_code}; - $logger->info('Set 852 map ' . $subfield_code . '=' . $value ); + $logger->debug('Set 852 map ' . $subfield_code . '=' . $value ); $copies{$subfield_code} = $value; } } else { # if not defined, fall back on these defaults. @@ -164,6 +154,19 @@ sub oai_biblio_retrieve { my $client = shift; my $rec_id = shift; my $metadataPrefix = shift; + my $set = shift; + my $copy_org; + my %copy_org_filter; + + (undef, $copy_org) = _set_spec_to_query('biblio',$set) if ($set); + + my $flesh = {}; + if ($copy_org) { + $U->walk_org_tree($copy_org, sub { + my $c = shift; + $copy_org_filter{$c->id} = 1; + }); + } # holdings hold an array of call numbers, which hold an array of copies # holdings => [ label: { library, [ copies: { barcode, location, status, circ_lib } ] } ] @@ -177,13 +180,15 @@ sub oai_biblio_retrieve { $rec_id, { flesh => 5, flesh_fields => { - bre => [qw/marc edit_date call_numbers/], - acn => [qw/edit_date copies owning_lib prefix suffix/], - acp => [qw/edit_date location status circ_lib parts/], + bre => [qw/call_numbers/], + acn => [qw/copies owning_lib prefix suffix uris/], + acp => [qw/location status circ_lib parts/], } } )->gather(1); + $tree->call_numbers([]) if (!$tree->call_numbers); + # Create a MARC::Record object with the marc. my $marc = MARC::Record->new_from_xml( $tree->marc, 'UTF8', 'XML'); @@ -211,21 +216,21 @@ sub oai_biblio_retrieve { for my $cn (@{$tree->call_numbers}) { next unless ( $cn->deleted eq 'f' || !$cn->deleted ); - my $_visible = 0; - for my $c (@{$cn->copies}) { - $_visible = _cp_is_visible($cn, $c); - last if ( $_visible ); + + my @visible_copies = @{$cn->copies}; + if ($copy_org) { + @visible_copies = grep { $copy_org_filter{$_->circ_lib->id} } @visible_copies; } - next unless $_visible; + @visible_copies = grep { _cp_is_visible($cn, $_) } @visible_copies; + next unless @visible_copies; my $cn_label = $cn->label; $holdings{$cn_label}{'owning_lib'} = $cn->owning_lib->shortname; $edit_date = most_recent_date( $cn->edit_date, $edit_date ); - for my $cp (@{$cn->copies}) { + for my $cp (@visible_copies) { - next unless _cp_is_visible($cn, $cp); $edit_date = most_recent_date( $cp->edit_date, $edit_date ); # find the corresponding serial. @@ -250,7 +255,7 @@ sub oai_biblio_retrieve { barcode => $cp->barcode, status => $cp->status->name, location => $cp->location->name, - circlib => $circlib, + circlib => $cp->circ_lib->shortname, ser => $ser }; } @@ -297,6 +302,9 @@ sub oai_biblio_retrieve { } + $XML::LibXML::skipXMLDeclaration = 1; + return $marc->as_xml_record() if ($metadataPrefix eq 'marcxml'); + my $xslt = $record_xslt{$metadataPrefix}{xslt} ; my $xml = $xslt->transform( $_parser->parse_string( $marc->as_xml_record()) ); return $xslt->output_as_chars( $xml ) ; @@ -392,6 +400,9 @@ sub oai_authority_retrieve { ); } + local $XML::LibXML::skipXMLDeclaration = 1; + return $marc->as_xml_record() if ($metadataPrefix eq 'marcxml'); + my $xslt = $record_xslt{$metadataPrefix}{xslt} ; my $xml = $record_xslt{$metadataPrefix}{xslt}->transform( $_parser->parse_string( $marc->as_xml_record()) @@ -442,7 +453,8 @@ sub oai_list_retrieve { my $max_count = shift; my $deleted_record = shift || 'yes'; - my $query = $set ? _set_spec_to_query($set) : {}; + my ($query) = _set_spec_to_query($record_class,$set) if ($set); + $query->{'rec_id'} = ($max_count eq 1) ? $rec_id : {'>=' => $rec_id} ; $query->{'deleted'} = 'f' unless ( $deleted_record eq 'yes' ); $query->{'datestamp'} = {'>=', $from} if ( $from && !$until ) ; @@ -512,22 +524,67 @@ __PACKAGE__->register_method( ); sub _set_spec_to_query { - my $self = shift; - my $set_spec = shift; - - if (index($set_spec, 'ORG_UNIT:') == 0) { - my $shortname = (split ':', $set_spec)[-1]; - my $org_unit = OpenSRF::AppSession - ->create('open-ils.actor') - ->request('open-ils.actor.org_unit.retrieve_by_shortname', $shortname) - ->gather(1); - if ($org_unit && ref($org_unit) ne 'HASH') { - return { - 'id' => {'=' => ['oai.bib_is_visible_at_org', 'id', $org_unit->id]} - }; + my $type = shift; + my $set_spec = shift; + my $query_part = {}; + my $copy_org; + + if ($type eq 'biblio') { + if ($set_spec =~ /COPIES:([^!]+)/) { + my $org_list = $1; + my $shortname = (split ':', $org_list)[-1]; + my $org_unit = $U->find_org_by_shortname($U->get_org_tree, $shortname); + if ($org_unit) { + $copy_org = $org_unit; + $$query_part{'-or'} //= []; + push @{$$query_part{'-or'}}, {rec_id => {'=' => { + transform => 'oai.bib_is_visible_at_org_by_copy', + params => [$org_unit->id], + value => ['bool','1'] + }}}; + } + } + + if ($set_spec =~ /LURIS:([^!]+)/) { + my $org_list = $1; + my $shortname = (split ':', $org_list)[-1]; + my $org_unit = $U->find_org_by_shortname($U->get_org_tree, $shortname); + if ($org_unit) { + $copy_org = $org_unit; + $$query_part{'-or'} //= []; + push @{$$query_part{'-or'}}, {rec_id => {'=' => { + transform => 'oai.bib_is_visible_at_org_by_luri', + params => [$org_unit->id], + value => ['bool','1'] + }}}; + } + } + + if ($set_spec =~ /SOURCES:([^!]+)/) { + my $list = $1; + my @sources = split ':', $list; + for my $source (@sources) { + $$query_part{'-or'} //= []; + push @{$$query_part{'-or'}}, {rec_id => {'=' => { + transform => 'oai.bib_is_visible_by_source', + params => [$source], + value => ['bool','1'] + }}}; + } + } + } elsif ($type eq 'authority') { + my @axes = split ':', $set_spec; + for my $axis (@axes) { + $$query_part{'-or'} //= []; + push @{$$query_part{'-or'}}, {rec_id => {'=' => { + transform => 'oai.auth_is_visible_by_axis', + params => [$axis], + value => ['bool','1'] + }}}; } } - return {}; + + return ($query_part, $copy_org); } diff --git a/Open-ILS/src/perlmods/lib/OpenILS/WWW/SuperCat/OAI.pm b/Open-ILS/src/perlmods/lib/OpenILS/WWW/SuperCat/OAI.pm index a348ad1269..e05d436a81 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/WWW/SuperCat/OAI.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/WWW/SuperCat/OAI.pm @@ -32,9 +32,14 @@ use MARC::Record; use MIME::Base64; use OpenSRF::EX qw(:try); use OpenSRF::Utils::Logger qw/$logger/; +use OpenILS::Utils::Fieldmapper; +use OpenILS::Utils::CStoreEditor; +use OpenILS::Application::AppUtils; use XML::LibXML; use XML::LibXSLT; +my $U = 'OpenILS::Application::AppUtils'; + my ( $bootstrap, $base_url, @@ -50,7 +55,6 @@ my ( $sample_identifier, $oai_metadataformats, $oai_sets, - $oai, $parser, $xslt ); @@ -69,8 +73,8 @@ sub child_init { my $idl = OpenSRF::Utils::SettingsClient->new->config_value('IDL'); Fieldmapper->import(IDL => $idl); + OpenILS::Utils::CStoreEditor->init; # just in case - $oai = OpenSRF::AppSession->create('open-ils.supercat'); $parser = new XML::LibXML; $xslt = new XML::LibXSLT; @@ -88,10 +92,14 @@ sub child_init { $delimiter = $app_settings->{'delimiter'} || ':'; $sample_identifier = $app_settings->{'sample_identifier'} || $scheme . $delimiter . $repository_identifier . $delimiter . '12345' ; - _load_oaisets_authority(); + $logger->info('Default OAI repo settings in place, loading sets...'); + _load_oaisets_biblio(); + _load_oaisets_authority(); _load_oai_metadataformats(); + $logger->info('... sets loaded.'); + return Apache2::Const::OK; } @@ -168,7 +176,7 @@ sub handler { $response = listSets( $record_class, $requestURL ); } elsif ( $verb eq 'GetRecord' ) { - $response = getRecord( $record_class, $requestURL, $identifier, $metadataPrefix); + $response = getRecord( $record_class, $requestURL, $identifier, $metadataPrefix, $set); } elsif ( $verb eq 'ListIdentifiers' ) { $response = listIdentifiers( $record_class, $requestURL, $from, $until, $set, $metadataPrefix, $offset); @@ -264,7 +272,7 @@ sub listSets { sub getRecord { - my ($record_class, $requestURL, $identifier, $metadataPrefix ) = @_; + my ($record_class, $requestURL, $identifier, $metadataPrefix, $set ) = @_; my $response ; my @errors; @@ -275,11 +283,10 @@ sub getRecord { my $rec_id = $1 ; # Do we have a record ? - my $record = $oai->request('open-ils.supercat.oai.list.retrieve', $record_class, $rec_id, undef, undef, undef, 1, $deleted_record)->gather(1) ; + my $record = $U->simplereq('open-ils.supercat','open-ils.supercat.oai.list.retrieve', $record_class, $rec_id, undef, undef, undef, 1, $deleted_record); if (@$record) { $response = HTTP::OAI::GetRecord->new(); - my $o = "Fieldmapper::oai::$record_class"->new(@$record[0]); - $response->record(_record($record_class, $o, $metadataPrefix)); + $response->record(_record($record_class, $$record[0], $metadataPrefix, $set)); } else { push @errors, new HTTP::OAI::Error(code=>'idDoesNotExist', message=>'The value of the identifier argument is unknown or illegal in this repository.') ; } @@ -302,18 +309,17 @@ sub listIdentifiers { my ($record_class, $requestURL, $from, $until, $set, $metadataPrefix, $offset ) = @_; my $response; - my $r = $oai->request('open-ils.supercat.oai.list.retrieve', $record_class, $offset, $from, $until, $set, $max_count, $deleted_record)->gather(1) ; + my $r = $U->simplereq('open-ils.supercat','open-ils.supercat.oai.list.retrieve', $record_class, $offset, $from, $until, $oai_sets->{$set}->{setSpec}, $max_count, $deleted_record); if (@$r) { my $cursor = 0 ; $response = HTTP::OAI::ListIdentifiers->new(); for my $record (@$r) { - my $o = "Fieldmapper::oai::$record_class"->new($record) ; if ( $cursor++ == $max_count ) { - my $token = new HTTP::OAI::ResumptionToken( resumptionToken => encode_base64(join( '$', $metadataPrefix, $from, $until, $oai_sets->{$set}->{setSpec}, $o->rec_id ), '' ) ) ; + my $token = new HTTP::OAI::ResumptionToken( resumptionToken => encode_base64(join( '$', $metadataPrefix, $from, $until, $oai_sets->{$set}->{setSpec}, $record->rec_id ), '' ) ) ; $token->cursor($offset); $response->resumptionToken($token) ; } else { - $response->identifier( _header($record_class, $o)) ; + $response->identifier( _header($record_class, $record)) ; } } } else { @@ -331,18 +337,17 @@ sub listRecords { my ($record_class, $requestURL, $from, $until, $set, $metadataPrefix, $offset ) = @_; my $response; - my $r = $oai->request('open-ils.supercat.oai.list.retrieve', $record_class, $offset, $from, $until, $set, $max_count, $deleted_record)->gather(1) ; + my $r = $U->simplereq('open-ils.supercat','open-ils.supercat.oai.list.retrieve', $record_class, $offset, $from, $until, $oai_sets->{$set}->{setSpec}, $max_count, $deleted_record); if (@$r) { my $cursor = 0 ; $response = HTTP::OAI::ListRecords->new(); for my $record (@$r) { - my $o = "Fieldmapper::oai::$record_class"->new($record) ; if ( $cursor++ == $max_count ) { - my $token = new HTTP::OAI::ResumptionToken( resumptionToken => encode_base64(join( '$', $metadataPrefix, $from, $until, $oai_sets->{$set}->{setSpec}, $o->rec_id ), '' ) ) ; + my $token = new HTTP::OAI::ResumptionToken( resumptionToken => encode_base64(join( '$', $metadataPrefix, $from, $until, $oai_sets->{$set}->{setSpec}, $record->rec_id ), '' ) ) ; $token->cursor($offset); $response->resumptionToken($token) ; } else { - $response->record(_record($record_class, $o, $metadataPrefix)); + $response->record(_record($record_class, $record, $metadataPrefix, $set)); } } } else { @@ -379,14 +384,15 @@ sub _header { sub _record { - my ($record_class, $o, $metadataPrefix ) = @_; + my ($record_class, $o, $metadataPrefix, $set ) = @_; my $record = HTTP::OAI::Record->new(); $record->header( _header($record_class, $o) ); if ( $o->deleted eq 'f' ) { my $md = new HTTP::OAI::Metadata() ; - my $xml = $oai->request('open-ils.supercat.oai.' . $record_class . '.retrieve', $o->rec_id, $metadataPrefix)->gather(1) ; + my $xml = $U->simplereq('open-ils.supercat','open-ils.supercat.oai.' . $record_class . '.retrieve', $o->rec_id, $metadataPrefix, $oai_sets->{$set}->{setSpec}); + $xml =~ s/^<\?xml[^?]+?\?>//; $md->dom( $parser->parse_string('' . $xml . '') ); # Not sure why I need to add the metadata element, $record->metadata( $md ); # because I expect ->metadata() would provide the wrapper for it. } @@ -400,12 +406,9 @@ sub _record { # oai_sets = {id\setSpec => {id, setSpec, setName, record_class = 'authority' }} sub _load_oaisets_authority { - my $ses = OpenSRF::AppSession->create('open-ils.cstore'); - my $r = $ses->request('open-ils.cstore.direct.authority.browse_axis.search.atomic', - {code => {'!=' => undef } } )->gather(1); + my $axes = $U->simplereq('open-ils.cstore','open-ils.cstore.direct.authority.browse_axis.search.atomic', {code => {'!=' => undef } } ); - for my $record (@$r) { - my $o = Fieldmapper::authority::browse_axis->new($record) ; + for my $o (@$axes) { $oai_sets->{$o->code} = { id => $o->code, setSpec => $o->code, @@ -419,35 +422,62 @@ sub _load_oaisets_authority { # _load_oaisets_biblio # Populate the $oai_sets hash with the sets for bibliographic records. Those are org_type records # oai_sets = {id\setSpec => {id, setSpec, setName, record_class = 'biblio' }} +my $org_tree; +my $bib_sources; sub _load_oaisets_biblio { my $node = shift; - my $types = shift; my $parent = shift; - unless ( $node ) { - my $ses = OpenSRF::AppSession->create('open-ils.actor'); - $node = $ses->request('open-ils.actor.org_tree.retrieve')->gather(1); - my $aout = $ses->request('open-ils.actor.org_types.retrieve')->gather(1); - $ses->disconnect; - return unless ($node) ; - - my @_types; - foreach my $type (@$aout) { - $_types[int($type->id)] = $type; - } - $types = \@_types; + if (!$node) { + $org_tree ||= $U->get_org_tree; + $bib_sources ||= $U->simplereq('open-ils.cat','open-ils.cat.bib_sources.retrieve.all'); + + $node = $org_tree; } return unless ($node->opac_visible =~ /^[y1t]+/i); + my $ou_hierarchy_string = ($parent) ? $parent . ':' . $node->shortname : $node->shortname ; - my $spec = 'ORG_UNIT:'.$ou_hierarchy_string; - $oai_sets->{$spec} = {id => $node->id, record_class => 'biblio' }; - $oai_sets->{$node->id} = {setSpec => $spec, setName => $node->name, record_class => 'biblio' }; + $logger->info('Registering setSpec list for ' . $ou_hierarchy_string); + + my $cspec = 'COPIES:'.$ou_hierarchy_string; + $oai_sets->{$cspec} = {id => 'C'.$node->id, record_class => 'biblio' }; + $oai_sets->{'C'.$node->id} = {setSpec => $cspec, setName => $node->name . ' / by copies', record_class => 'biblio' }; + + my $lspec = 'LURIS:'.$ou_hierarchy_string; + $oai_sets->{$lspec} = {id => 'L'.$node->id, record_class => 'biblio' }; + $oai_sets->{'L'.$node->id} = {setSpec => $lspec, setName => $node->name . ' / by LURIs', record_class => 'biblio' }; + + my $clspec = $cspec . '!' . $lspec; + $oai_sets->{$clspec} = {id => 'CL'.$node->id, record_class => 'biblio' }; + $oai_sets->{'CL'.$node->id} = {setSpec => $clspec, setName => $node->name . ' / by copies and LURIs', record_class => 'biblio' }; + + + my $source_string; + for my $s (@$bib_sources) { + + my $sspec = 'SOURCES:'.$s->source; + $oai_sets->{$sspec} = {id => 'S'.$s->id, record_class => 'biblio' }; + $oai_sets->{'S'.$s->id} = {setSpec => $sspec, setName => $s->source . ' / by source', record_class => 'biblio' }; + + my $csspec = $cspec . '!' . $sspec; + $oai_sets->{$csspec} = {id => $s->id.'CS'.$node->id, record_class => 'biblio' }; + $oai_sets->{$s->id.'CS'.$node->id} = {setSpec => $csspec, setName => $node->name . ' / by copies and source', record_class => 'biblio' }; + + my $lsspec = $lspec . '!' . $sspec; + $oai_sets->{$lsspec} = {id => $s->id.'LS'.$node->id, record_class => 'biblio' }; + $oai_sets->{$s->id.'LS'.$node->id} = {setSpec => $lsspec, setName => $node->name . ' / by LURIs and source', record_class => 'biblio' }; + + my $clsspec = $clspec . '!' . $sspec; + $oai_sets->{$clsspec} = {id => $s->id.'CLS'.$node->id, record_class => 'biblio' }; + $oai_sets->{$s->id.'CLS'.$node->id} = {setSpec => $clsspec, setName => $node->name . ' / by copies, LURIs, and source', record_class => 'biblio' }; + + } my $kids = $node->children; - _load_oaisets_biblio($_, $types, $ou_hierarchy_string) for (@$kids); + _load_oaisets_biblio($_, $ou_hierarchy_string) for (@$kids); } @@ -456,7 +486,7 @@ sub _load_oaisets_biblio { # oai_metadataformats = { metadataPrefix => { schema, metadataNamespace } } sub _load_oai_metadataformats { - my $list = $oai->request('open-ils.supercat.oai.record.formats')->gather(1); + my $list = $U->simplereq('open-ils.supercat','open-ils.supercat.oai.record.formats'); for my $record_browse_format ( @$list ) { my %h = %$record_browse_format ; my $metadataPrefix = (keys %h)[0] ; diff --git a/Open-ILS/src/sql/Pg/upgrade/XXXX.schema.oai_views.sql b/Open-ILS/src/sql/Pg/upgrade/XXXX.schema.oai_views.sql index 233f490352..2b9d007d18 100644 --- a/Open-ILS/src/sql/Pg/upgrade/XXXX.schema.oai_views.sql +++ b/Open-ILS/src/sql/Pg/upgrade/XXXX.schema.oai_views.sql @@ -9,7 +9,7 @@ CREATE SCHEMA oai; CREATE VIEW oai.biblio AS SELECT bre.id AS rec_id, - bre.edit_date AS datestamp, + bre.edit_date AT TIME ZONE 'UTC' AS datestamp, bre.deleted AS deleted FROM biblio.record_entry bre @@ -19,17 +19,30 @@ CREATE VIEW oai.biblio AS -- The view presents a lean table with unique are.tc-numbers for oai paging; CREATE VIEW oai.authority AS SELECT - are.id AS rec_id, - are.edit_date AS datestamp, - are.deleted AS deleted + are.id AS rec_id, + are.edit_date AT TIME ZONE 'UTC' AS datestamp, + are.deleted AS deleted FROM authority.record_entry AS are ORDER BY are.id; -CREATE OR REPLACE function oai.bib_is_visible_at_org(bib BIGINT, org INT) RETURNS BOOL AS $F$ -WITH orgs AS (SELECT array_accum(id) id FROM actor.org_unit_descendants(org)) -SELECT EXISTS (SELECT 1 FROM asset.copy_vis_attr_cache, orgs WHERE vis_attr_vector @@ search.calculate_visibility_attribute_test('circ_lib', orgs.id)::query_int AND bib=record) +CREATE OR REPLACE function oai.bib_is_visible_at_org_by_copy(bib BIGINT, org INT) RETURNS BOOL AS $F$ +WITH corgs AS (SELECT array_accum(id) AS list FROM actor.org_unit_descendants(org)) + SELECT EXISTS (SELECT 1 FROM asset.copy_vis_attr_cache, corgs WHERE vis_attr_vector @@ search.calculate_visibility_attribute_test('circ_lib', corgs.list)::query_int AND bib=record) +$F$ LANGUAGE SQL STABLE; + +CREATE OR REPLACE function oai.bib_is_visible_at_org_by_luri(bib BIGINT, org INT) RETURNS BOOL AS $F$ +WITH lorgs AS(SELECT array_accum(id) AS list FROM actor.org_unit_ancestors(org)) + SELECT EXISTS (SELECT 1 FROM biblio.record_entry, lorgs WHERE vis_attr_vector @@ search.calculate_visibility_attribute_test('luri_org', lorgs.list)::query_int AND bib=id) +$F$ LANGUAGE SQL STABLE; + +CREATE OR REPLACE function oai.bib_is_visible_by_source(bib BIGINT, src TEXT) RETURNS BOOL AS $F$ + SELECT EXISTS (SELECT 1 FROM biblio.record_entry b JOIN config.bib_source s ON (b.source = s.id) WHERE transcendant AND s.source = src AND bib=b.id) +$F$ LANGUAGE SQL STABLE; + +CREATE OR REPLACE function oai.auth_is_visible_by_axis(auth BIGINT, ax TEXT) RETURNS BOOL AS $F$ + SELECT EXISTS (SELECT 1 FROM authority.browse_axis_authority_field_map m JOIN authority.simple_heading r on (r.atag = m.field AND r.record = auth AND m.axis = ax)) $F$ LANGUAGE SQL STABLE; COMMIT; diff --git a/Open-ILS/xsl/OAI2_MARC21slim.xsl b/Open-ILS/xsl/OAI2_MARC21slim.xsl deleted file mode 100644 index 3bf4226953..0000000000 --- a/Open-ILS/xsl/OAI2_MARC21slim.xsl +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Open-ILS/xsl/OAI2_OAIDC.xsl b/Open-ILS/xsl/OAI2_OAIDC.xsl deleted file mode 100644 index 4434360f20..0000000000 --- a/Open-ILS/xsl/OAI2_OAIDC.xsl +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file -- 2.11.0