Bugzilla – Attachment 64446 Details for
Bug 10662
Build OAI-PMH Harvesting Client
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 10662 - Modify OAI-PMH harvester to import RDFXML
Bug-10662---Modify-OAI-PMH-harvester-to-import-RDF.patch (text/plain), 26.89 KB, created by
David Cook
on 2017-06-20 01:20:45 UTC
(
hide
)
Description:
Bug 10662 - Modify OAI-PMH harvester to import RDFXML
Filename:
MIME Type:
Creator:
David Cook
Created:
2017-06-20 01:20:45 UTC
Size:
26.89 KB
patch
obsolete
>From d8cccc22c4bbe526ae80f72f420426a1fd42c4f8 Mon Sep 17 00:00:00 2001 >From: David Cook <dcook@prosentient.com.au> >Date: Fri, 12 May 2017 12:26:14 +1000 >Subject: [PATCH] Bug 10662 - Modify OAI-PMH harvester to import RDFXML > >Typically, the OAI-PMH harvester only imports MARCXML, but this >patch allows you to also import RDFXML. > >This functionality was requested by Stockholm University Library, >and importing RDFXML requires a parallel import of MARCXML if you >want to be able to use the RDFXML. That is to say, you can download >and import RDFXML using this patch, but it will probably only be >useful if you're also importing MARCXML which can be linked to the RDFXML >using the OAI-PMH repository and identifier as a link. This might change >in the future if Koha moves away from MARCXML as the central required >metadata format. >--- > Koha/OAI/Harvester/Import/RDFXML.pm | 124 ++++++++++++++++++++- > Koha/OAI/Harvester/Import/Record.pm | 113 +++++++++++++++++-- > Koha/OAI/Harvester/Request.pm | 19 ++++ > Koha/OAI/Harvester/Worker/Download/Stream.pm | 2 + > Koha/OAI/Harvester/Worker/Import.pm | 2 + > Koha/Schema/Result/OaiHarvesterRequest.pm | 12 +- > installer/data/mysql/atomicupdate/bug_10662.sql | 1 + > installer/data/mysql/kohastructure.sql | 1 + > .../modules/tools/oai-pmh-harvester/dashboard.tt | 3 + > .../en/modules/tools/oai-pmh-harvester/request.tt | 6 + > t/db_dependent/OAI/Harvester/Importer/rdf.t | 53 +++++++++ > tools/oai-pmh-harvester/dashboard.pl | 3 +- > tools/oai-pmh-harvester/request.pl | 2 + > 13 files changed, 321 insertions(+), 20 deletions(-) > create mode 100644 t/db_dependent/OAI/Harvester/Importer/rdf.t > >diff --git a/Koha/OAI/Harvester/Import/RDFXML.pm b/Koha/OAI/Harvester/Import/RDFXML.pm >index a09696fead..5fa1f07566 100755 >--- a/Koha/OAI/Harvester/Import/RDFXML.pm >+++ b/Koha/OAI/Harvester/Import/RDFXML.pm >@@ -19,6 +19,12 @@ package Koha::OAI::Harvester::Import::RDFXML; > # > > use Modern::Perl; >+use Encode; >+use RDF::Trine; >+use RDF::Query; >+ >+use C4::Context; >+use Koha::RDF; > > sub new { > my ($class, $args) = @_; >@@ -26,21 +32,127 @@ sub new { > return bless ($args, $class); > } > >+sub _parse_rdf_into_model { >+ my ($self, $args) = @_; >+ >+ #Create a RDFXML parser >+ my $parser = RDF::Trine::Parser->new('rdfxml'); >+ >+ #Create a model in memory into which we can parse the incoming triples for processing >+ my $store = RDF::Trine::Store::Memory->new(); >+ my $model = RDF::Trine::Model->new($store); >+ >+ my $dom = $self->{dom}; >+ >+ my $byte_string = $dom->toString(2); >+ >+ #Change a byte string to a character string >+ my $character_string = Encode::decode('UTF-8', $byte_string, Encode::FB_CROAK); >+ #NOTE: RDF::Trine::Parser::RDFXML expects characters and converts them to bytes, so >+ #we have to change to characters before parsing. >+ >+ #FIXME: Should you provide a base uri? Unfortunately, there's no way to do this reliably over OAI-PMH. >+ my $base_uri = undef; >+ >+ #NOTE: UTF-8 encoding problems have been found when using XML::SAX::PurePerl. Make sure >+ #that you're using a parser like XML::LibXML::SAX::Parser instead. You can verify using >+ #sax_parser_print.pl. >+ $parser->parse_into_model($base_uri, $character_string, $model); >+ >+ return $model; >+} >+ >+sub _get_primary_subject { >+ my ($self,$args) = @_; >+ >+ my $primary_subject; >+ my $model = $args->{model}; >+ my $type = $args->{type}; >+ >+ my $object = RDF::Trine::Node::Resource->new($type); >+ my $object_string = $object ? $object->as_string : '?object'; >+ >+ #NOTE: Select only a subject with a particular rdf:type, and filter out >+ #any matches which are also objects in the same model. This is essential >+ #for weeding out triples that share the same rdf:type value but are linked >+ #objects rather than the primary subject. >+ my $sparql = qq~ >+ SELECT DISTINCT ?subject >+ WHERE { >+ ?subject <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> $object_string . >+ FILTER NOT EXISTS { ?os ?op ?subject } >+ } >+ ~; >+ my $query = RDF::Query->new($sparql); >+ my $iterator = $query->execute($model); >+ if ($iterator){ >+ my @all = $iterator->get_all; >+ if (scalar @all == 1 ){ >+ my $primary = shift @all; >+ $primary_subject = $primary->{subject}; >+ } >+ } >+ return $primary_subject; >+} >+ > sub import_record { > my ($self,$args) = @_; >- my $framework = $args->{framework}; > my $record_type = $args->{record_type}; >- my $matcher = $args->{matcher}; > my $koha_id = $args->{koha_id}; >+ my $rdf_type = $args->{rdf_type}; >+ my $oai_pmh_repository = $args->{oai_pmh_repository}; >+ my $oai_pmh_identifier = $args->{oai_pmh_identifier}; > > my $action = "error"; > >- if (! $koha_id && $matcher){ >- #Create minimal MARCXML record from RDFXML to be used for Zebra-based matching. >- } >+ #Create a model for our Koha triplestore backend >+ my $context = C4::Context->new(); >+ my $real_model = $context->triplestore('update') if $context && $context->triplestore('update'); >+ my $memory_model = $self->_parse_rdf_into_model(); >+ my $iterator = $memory_model->as_stream; >+ if ($iterator){ >+ if ($memory_model && $rdf_type){ >+ my $incoming_subject = $self->_get_primary_subject({ >+ model => $memory_model, >+ type => $rdf_type, >+ }); >+ >+ if ($incoming_subject && $incoming_subject->is_resource){ >+ my $rdf = Koha::RDF->new(); >+ if ($rdf){ >+ $real_model->begin_bulk_ops; >+ >+ $rdf->DelNamedGraph({ >+ model => $real_model, >+ context => $incoming_subject, >+ }); >+ $rdf->AddNamedGraph({ >+ model => $real_model, >+ context => $incoming_subject, >+ iterator => $iterator, >+ }); > >+ #NOTE: Insert your own triples containing references to the OAI-PMH repository and the OAI-PMH identifier >+ if ($oai_pmh_repository){ >+ my $repository_predicate = RDF::Trine::Node::Resource->new('http://koha-community.org/vocab/oai-pmh/repository'); >+ my $repository_object = RDF::Trine::Node::Resource->new($oai_pmh_repository); >+ my $repository_quad = RDF::Trine::Statement::Quad->new($incoming_subject, $repository_predicate, $repository_object, $incoming_subject); >+ $real_model->add_statement($repository_quad); >+ } >+ if ($oai_pmh_identifier){ >+ my $identifier_predicate = RDF::Trine::Node::Resource->new('http://koha-community.org/vocab/oai-pmh/identifier'); >+ my $identifier_object = RDF::Trine::Node::Resource->new($oai_pmh_identifier); >+ my $identifier_quad = RDF::Trine::Statement::Quad->new($incoming_subject, $identifier_predicate, $identifier_object, $incoming_subject); >+ $real_model->add_statement($identifier_quad); >+ } > >- #TODO: add/update triplestore >+ $real_model->end_bulk_ops; >+ >+ $action = 'unknown'; #FIXME: RDF::Trine doesn't return meaningful values so we can't really say much else... >+ } >+ } >+ } >+ } > return ($action,$koha_id); > } > >diff --git a/Koha/OAI/Harvester/Import/Record.pm b/Koha/OAI/Harvester/Import/Record.pm >index ba08ca39e2..2841333784 100755 >--- a/Koha/OAI/Harvester/Import/Record.pm >+++ b/Koha/OAI/Harvester/Import/Record.pm >@@ -23,6 +23,7 @@ use XML::LibXML; > use XML::LibXSLT; > use URI; > use File::Basename; >+use RDF::Query; > > use C4::Context; > use C4::Biblio; >@@ -30,6 +31,7 @@ use C4::Biblio; > use Koha::Database; > use Koha::OAI::Harvester::Import::MARCXML; > use Koha::OAI::Harvester::Import::RDFXML; >+use Koha::RDF; > > my $schema = Koha::Database->new()->schema(); > >@@ -179,6 +181,42 @@ sub _find_koha_link { > return $link_id; > } > >+ >+sub _find_rdf_link { >+ my ($self, $args) = @_; >+ my ($subject,$graph); >+ my $repository = $self->{repository}; >+ my $identifier = $self->{header_identifier}; >+ >+ my $context = C4::Context->new; >+ my $triplestore = $context->triplestore('query'); >+ if ($triplestore){ >+ if ( URI->new($repository) && URI->new($identifier) ){ >+ my $sparql = qq~ >+ PREFIX koha-oai: <http://koha-community.org/vocab/oai-pmh/> >+ SELECT ?g ?s ?identifier ?repository >+ WHERE { >+ GRAPH ?g { >+ ?s koha-oai:identifier ?identifier . >+ ?s koha-oai:repository ?repository . >+ ?s koha-oai:identifier <$identifier> . >+ ?s koha-oai:repository <$repository> . >+ } >+ } >+ ~; >+ my $query = RDF::Query->new($sparql); >+ my $iterator = $query->execute($triplestore); >+ my @rows = $iterator->get_all; >+ if (scalar @rows == 1){ >+ my $row = $rows[0]; >+ $subject = $row->{s}; >+ $graph = $row->{g}; >+ } >+ } >+ } >+ return ($subject,$graph); >+} >+ > =head3 > > my ($action,$record_id) = $oai_record->import_record({ >@@ -198,30 +236,57 @@ sub import_record { > my $framework = $args->{framework} || ''; > my $record_type = $args->{record_type} || 'biblio'; > my $matcher = $args->{matcher}; >+ my $rdf_type = $args->{rdf_type}; #NOTE: RDF > > my $action = "error"; > >+ #NOTE: RDF > #Find linkage between OAI-PMH repository-identifier and Koha record id > my $linked_id = $self->_find_koha_link({ > record_type => $record_type, > }); > >+ #NOTE: RDF >+ my $context = C4::Context->new(); >+ #Find linkage between OAI-PMH repository-identifier and RDF records in the triplestore >+ my ($linked_subject, $linked_graph) = $self->_find_rdf_link if $context && $context->triplestore('query'); >+ > if ($self->is_deleted_upstream){ >- #NOTE: If a record is deleted upstream, it will not contain a metadata element >+ #FIXME: If a record is deleted upstream, it will not contain a metadata element, so we don't know what metadata >+ #format we requested. Perhaps we should be recording the metadataPrefix during download and import, so we >+ #can have more targeted deletes. >+ #NOTE: "Other records, with different metadataPrefix but the same unique identifier, may remain available for the item." >+ #https://www.openarchives.org/OAI/openarchivesprotocol.html#DeletedRecords >+ >+ if ($linked_graph){ >+ my $model = $context->triplestore('update') if $context && $context->triplestore('update'); >+ my $rdf = Koha::RDF->new(); >+ if ($rdf){ >+ $model->begin_bulk_ops; >+ $rdf->DelNamedGraph({ >+ model => $model, >+ context => $linked_graph, >+ }); >+ $model->end_bulk_ops; >+ } >+ #NOTE: We don't set action here, since RDF::Trine doesn't return a useful value, plus >+ #the RDF is meaningless without the Koha record mentioned below anyway. >+ } >+ > if ($linked_id){ > $action = $self->delete_koha_record({ > record_id => $linked_id, > record_type => $record_type, > }); >- #TODO: How to handle RDF deletions? >- #NOTE: If we delete the Koha record, then we lose the link to our downloaded record, so I don't know if it matters... >- #...although surely we'd want some way of cleaning up records that aren't needed anymore? I suppose that could come up with a cronjob that scans for triples that aren't linked to... > } > else { > $action = "not_found"; > #NOTE: If there's no OAI-PMH repository-identifier pair in the database, > #then there's no perfect way to find a linked record to delete. > } >+ #NOTE: RDF >+ #TODO: Delete named graph found via $linked_graph... >+ #TODO: Do we also unlink the Koha record from this OAI record? I suppose so... > } > else { > $self->set_filter($filter); >@@ -230,21 +295,47 @@ sub import_record { > my $import_record = $self->filter(); > > if ($import_record){ >+ #NOTE: You can inspect the object's class here for special type handling if necessary... > ($action,$linked_id) = $import_record->import_record({ >+ oai_pmh_repository => $self->{repository}, >+ oai_pmh_identifier => $self->{header_identifier}, > framework => $framework, > record_type => $record_type, > matcher => $matcher, > koha_id => $linked_id, >+ linked_subject => $linked_subject, #NOTE: RDF >+ rdf_type => $rdf_type, #NOTE: RDF > }); > >- if ($linked_id){ >- #Link Koha record ID to OAI-PMH details for this record type, >- #if linkage doesn't already exist. >- $self->link_koha_record({ >- record_type => $record_type, >- koha_id => $linked_id, >- }); >+ if ($import_record->isa('Koha::Import::MARCXML')){ >+ if ($linked_id){ >+ #Link Koha record ID to OAI-PMH details for this record type, >+ #if linkage doesn't already exist. >+ $self->link_koha_record({ >+ record_type => $record_type, >+ koha_id => $linked_id, >+ }); >+ } >+ } >+ >+ #NOTE: Link Koha RDF to Imported RDF >+ if ( ($record_type && $linked_id) && ($linked_subject) ){ >+ my $rdf = Koha::RDF->new(); >+ my $context = C4::Context->new(); >+ my $triplestore = $context->triplestore('update') if $context && $context->triplestore('update'); >+ if ( $triplestore && $rdf ){ >+ my $koha_uri = $rdf->mint_uri($record_type, $linked_id); >+ my $koha_subject = RDF::Trine::Node::Resource->new($koha_uri); >+ $rdf->AddSeeAlso({ >+ model => $triplestore, >+ subject => $koha_subject, >+ object => $linked_subject, >+ }); >+ } > } >+ #NOTE: A link will only be successful when both a MARCXML record and a RDFXML record sharing the >+ #same OAI-PMH repository and OAI-PMH identifier are in Koha. >+ #NOTE: This action is idempotent. > } > } > >diff --git a/Koha/OAI/Harvester/Request.pm b/Koha/OAI/Harvester/Request.pm >index 2659c952a1..535b7e52bd 100644 >--- a/Koha/OAI/Harvester/Request.pm >+++ b/Koha/OAI/Harvester/Request.pm >@@ -140,9 +140,28 @@ sub validate { > } else { > $errors->{http_url}->{malformed} = 1; > } >+ >+ #NOTE: RDF >+ $self->_validate_import_rdf_type({ >+ errors => $errors, >+ }); >+ > return $errors; > } > >+#NOTE: RDF >+sub _validate_import_rdf_type { >+ my ($self,$args) = @_; >+ my $errors = $args->{errors}; >+ my $type = $self->import_rdf_type; >+ if ($type){ >+ my $uri = URI->new($type); >+ if ( ! $uri->scheme ){ >+ $errors->{import_rdf_type}->{malformed} = 1; >+ } >+ } >+} >+ > sub _harvester { > my ( $self ) = @_; > my $harvester; >diff --git a/Koha/OAI/Harvester/Worker/Download/Stream.pm b/Koha/OAI/Harvester/Worker/Download/Stream.pm >index c4a3d439a0..03f64951b7 100644 >--- a/Koha/OAI/Harvester/Worker/Download/Stream.pm >+++ b/Koha/OAI/Harvester/Worker/Download/Stream.pm >@@ -149,6 +149,7 @@ sub do_work { > matcher_code => $import_parameters->{matcher_code}, > frameworkcode => $import_parameters->{frameworkcode}, > record_type => $import_parameters->{record_type}, >+ rdf_type => $import_parameters->{rdf_type}, > }; > eval { > my $json_result = to_json($result, { pretty => 1 }); >@@ -168,6 +169,7 @@ sub do_work { > matcher_code => $import_parameters->{matcher_code}, > frameworkcode => $import_parameters->{frameworkcode}, > record_type => $import_parameters->{record_type}, >+ rdf_type => $import_parameters->{rdf_type}, > }; > eval { > my $json_result = to_json($result, { pretty => 1 }); >diff --git a/Koha/OAI/Harvester/Worker/Import.pm b/Koha/OAI/Harvester/Worker/Import.pm >index ec867368e1..80ebdf0d6f 100644 >--- a/Koha/OAI/Harvester/Worker/Import.pm >+++ b/Koha/OAI/Harvester/Worker/Import.pm >@@ -63,6 +63,7 @@ sub on_start { > my $matcher_code = $result->{matcher_code}; > my $frameworkcode = $result->{frameworkcode}; > my $record_type = $result->{record_type}; >+ my $rdf_type = $result->{rdf_type}; #NOTE: RDF > > my $matcher; > if ($matcher_code){ >@@ -85,6 +86,7 @@ sub on_start { > framework => $frameworkcode, > record_type => $record_type, > matcher => $matcher, >+ rdf_type => $rdf_type, #NOTE: RDF > }); > $debug && print STDOUT qq({ "import_result": { "task_uuid": "$task_uuid", "action": "$action", "filename": "$filename", "koha_id": "$linked_id" } }\n); > } >diff --git a/Koha/Schema/Result/OaiHarvesterRequest.pm b/Koha/Schema/Result/OaiHarvesterRequest.pm >index e3222811c6..e074027d4a 100644 >--- a/Koha/Schema/Result/OaiHarvesterRequest.pm >+++ b/Koha/Schema/Result/OaiHarvesterRequest.pm >@@ -133,6 +133,12 @@ __PACKAGE__->table("oai_harvester_requests"); > is_nullable: 0 > size: 45 > >+=head2 import_rdf_type >+ >+ data_type: 'varchar' >+ is_nullable: 1 >+ size: 255 >+ > =cut > > __PACKAGE__->add_columns( >@@ -186,6 +192,8 @@ __PACKAGE__->add_columns( > { data_type => "integer", extra => { unsigned => 1 }, is_nullable => 0 }, > "name", > { data_type => "varchar", is_nullable => 0, size => 45 }, >+ "import_rdf_type", >+ { data_type => "varchar", is_nullable => 1, size => 255 }, > ); > > =head1 PRIMARY KEY >@@ -201,8 +209,8 @@ __PACKAGE__->add_columns( > __PACKAGE__->set_primary_key("id"); > > >-# Created by DBIx::Class::Schema::Loader v0.07046 @ 2017-04-07 11:26:24 >-# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:Vm/b4yurmr8WF7z+Fo6KEw >+# Created by DBIx::Class::Schema::Loader v0.07046 @ 2017-05-30 16:44:41 >+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:LiH5KlQNzkZtjWujcT3DIw > > > # You can replace this text with custom code or comments, and it will be preserved on regeneration >diff --git a/installer/data/mysql/atomicupdate/bug_10662.sql b/installer/data/mysql/atomicupdate/bug_10662.sql >index f42b732841..7da62f0f16 100644 >--- a/installer/data/mysql/atomicupdate/bug_10662.sql >+++ b/installer/data/mysql/atomicupdate/bug_10662.sql >@@ -69,5 +69,6 @@ CREATE TABLE IF NOT EXISTS `oai_harvester_requests` ( > `import_matcher_code` varchar(10) DEFAULT NULL, > `interval` int(10) unsigned NOT NULL, > `name` varchar(45) NOT NULL, >+ `import_rdf_type` varchar(255) DEFAULT NULL, > PRIMARY KEY (`id`) > ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; >diff --git a/installer/data/mysql/kohastructure.sql b/installer/data/mysql/kohastructure.sql >index 385952eb80..422f0dd48c 100644 >--- a/installer/data/mysql/kohastructure.sql >+++ b/installer/data/mysql/kohastructure.sql >@@ -4171,6 +4171,7 @@ CREATE TABLE IF NOT EXISTS `oai_harvester_requests` ( > `import_matcher_code` varchar(10) DEFAULT NULL, > `interval` int(10) unsigned NOT NULL, > `name` varchar(45) NOT NULL, >+ `import_rdf_type` varchar(255) DEFAULT NULL, > PRIMARY KEY (`id`) > ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; > >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/oai-pmh-harvester/dashboard.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/oai-pmh-harvester/dashboard.tt >index 06d1f4a073..58ec2549f4 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/oai-pmh-harvester/dashboard.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/oai-pmh-harvester/dashboard.tt >@@ -62,6 +62,9 @@ > else if (data == "updated"){ > display_string = _("Updated"); > } >+ else if (data == "unknown"){ >+ display_string = _("Unknown"); >+ } > return display_string; > } > }, >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/oai-pmh-harvester/request.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/oai-pmh-harvester/request.tt >index be48bcbf2a..7c2452e95b 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/oai-pmh-harvester/request.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/oai-pmh-harvester/request.tt >@@ -214,6 +214,12 @@ > </select> > <span class="help">See <a href="/cgi-bin/koha/admin/matching-rules.pl">record matching rules</a> to add or edit rules.</span> > </li> >+ <li> >+ <label for="import_rdf_type">RDF type</label> >+ <input type="text" size="30" id="import_rdf_type" name="import_rdf_type" value="[% oai_pmh_request.import_rdf_type %]"> >+ <span class="help">If you're importing RDF, you need to specify a type for the primary entity or your import will fail.</span> >+ [% IF (errors.import_rdf_type.malformed) %]<span class="error">[This must be a properly formatted URI.]</span>[% END %] >+ </li> > </ol> > </fieldset> > <fieldset class="rows"> >diff --git a/t/db_dependent/OAI/Harvester/Importer/rdf.t b/t/db_dependent/OAI/Harvester/Importer/rdf.t >new file mode 100644 >index 0000000000..90044e9c27 >--- /dev/null >+++ b/t/db_dependent/OAI/Harvester/Importer/rdf.t >@@ -0,0 +1,53 @@ >+#!/usr/bin/perl >+ >+# Copyright 2017 Prosentient Systems >+# >+# This file is part of Koha. >+# >+# Koha is free software; you can redistribute it and/or modify it >+# under the terms of the GNU General Public License as published by >+# the Free Software Foundation; either version 3 of the License, or >+# (at your option) any later version. >+# >+# Koha is distributed in the hope that it will be useful, but >+# WITHOUT ANY WARRANTY; without even the implied warranty of >+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+# GNU General Public License for more details. >+# >+# You should have received a copy of the GNU General Public License >+# along with Koha; if not, see <http://www.gnu.org/licenses>. >+# >+ >+use Modern::Perl; >+use Test::More tests => 2; >+ >+use_ok("Koha::OAI::Harvester::Import::RDFXML"); >+ >+subtest 'find primary entity' => sub { >+ >+ my $store = RDF::Trine::Store::Memory->new(); >+ my $model = RDF::Trine::Model->new($store); >+ >+ my $subject = RDF::Trine::Node::Resource->new("http://koha-community/resource/1"); >+ my $predicate = RDF::Trine::Node::Resource->new("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"); >+ my $object = RDF::Trine::Node::Resource->new("http://koha-community/vocab/type/record"); >+ my $triple = RDF::Trine::Statement->new($subject,$predicate,$object); >+ $model->add_statement($triple); >+ my $other_predicate = RDF::Trine::Node::Resource->new("http://koha-community/vocab/hasAuthor"); >+ my $other_object = RDF::Trine::Node::Resource->new("http://koha-community/author/david-cook"); >+ my $other_triple = RDF::Trine::Statement->new($subject,$other_predicate,$other_object); >+ $model->add_statement($other_triple); >+ >+ my $resource2_subject = RDF::Trine::Node::Resource->new("http://koha-community/resource/2"); >+ my $resource2_predicate = RDF::Trine::Node::Resource->new("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"); >+ my $resource2_object = RDF::Trine::Node::Resource->new("http://koha-community/vocab/type/awesome"); >+ my $resource2_triple = RDF::Trine::Statement->new($resource2_subject, $resource2_predicate, $resource2_object); >+ $model->add_statement($resource2_triple); >+ >+ my $importer = Koha::OAI::Harvester::Import::RDFXML->new(); >+ my $primary_subject = $importer->_get_primary_subject({ >+ model => $model, >+ type => 'http://koha-community/vocab/type/record', >+ }); >+ is($primary_subject && $primary_subject->as_string, "<http://koha-community/resource/1>","Correctly found primary entity"); >+}; >diff --git a/tools/oai-pmh-harvester/dashboard.pl b/tools/oai-pmh-harvester/dashboard.pl >index 16dd15f3f5..eeb1572f81 100755 >--- a/tools/oai-pmh-harvester/dashboard.pl >+++ b/tools/oai-pmh-harvester/dashboard.pl >@@ -78,6 +78,7 @@ if ( ($op eq "send") && $id ){ > frameworkcode => $request->import_framework_code, > matcher_code => $request->import_matcher_code, > record_type => $request->import_record_type, >+ rdf_type => $request->import_rdf_type, #NOTE: RDF > }, > }, > }; >@@ -131,4 +132,4 @@ else { > $template->{VARS}->{ harvester }->{ offline } = 1; > } > >-output_html_with_http_headers($input, $cookie, $template->output); >\ No newline at end of file >+output_html_with_http_headers($input, $cookie, $template->output); >diff --git a/tools/oai-pmh-harvester/request.pl b/tools/oai-pmh-harvester/request.pl >index 0390bf7cc1..e980074d0e 100755 >--- a/tools/oai-pmh-harvester/request.pl >+++ b/tools/oai-pmh-harvester/request.pl >@@ -63,6 +63,7 @@ my $import_filter = $input->param('import_filter') // 'default'; > my $import_framework_code = $input->param('import_framework_code'); > my $import_record_type = $input->param('import_record_type'); > my $import_matcher_code = $input->param('import_matcher_code'); >+my $import_rdf_type = $input->param('import_rdf_type'); #NOTE: RDF > > my $interval = $input->param("interval") ? int ( $input->param("interval") ) : 0; > my $name = $input->param("name"); >@@ -89,6 +90,7 @@ if ($request){ > import_framework_code => $import_framework_code, > import_record_type => $import_record_type, > import_matcher_code => $import_matcher_code, >+ import_rdf_type => $import_rdf_type, > interval => $interval, > }); > } >-- >2.12.0
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 10662
:
20757
|
20758
|
21954
|
42446
|
42447
|
42448
|
44792
|
44793
|
47675
|
48096
|
49832
|
50254
|
50980
|
51510
|
51511
|
51512
|
51514
|
51562
|
51563
|
51564
|
51565
|
51705
|
53258
|
53259
|
53260
|
53361
|
53362
|
64444
|
64445
|
64446
|
64479
|
64480
|
64481
|
65016
|
65017
|
65018
|
65019
|
68508
|
71008
|
71009
|
71010
|
71011
|
71012
|
71013
|
71014
|
71015
|
78569
|
78570
|
78571
|
78572
|
78573
|
78574
|
78575
|
78576
|
78577
|
78583
|
78601
|
78617
|
78754
|
78756
|
78758
|
78760
|
78762
|
78764
|
78767
|
78769
|
78771
|
78859
|
78860
|
78914
|
78956
|
79039
|
79045
|
81783
|
81784
|
81786
|
81789
|
81790
|
81855
|
81856
|
81861
|
81862
|
81863
|
81864
|
81902
|
82219
|
84318
|
84319
|
84320
|
84321
|
84322
|
85152
|
85224
|
85225
|
85226
|
85227
|
85228
|
85229
|
99739
|
99740
|
99741
|
99742
|
99743
|
99744
|
99745