@@ -, +, @@
---
C4/Context.pm | 64 ++++++++++++++++++++++++++++++++
C4/Installer/PerlDependencies.pm | 5 +++
debian/scripts/koha-create | 4 ++
debian/templates/koha-conf-site.xml.in | 3 ++
debian/templates/triplestore.yaml.in | 30 +++++++++++++++
etc/koha-conf.xml | 3 ++
etc/triplestore.yaml | 30 +++++++++++++++
t/db_dependent/triplestore.t | 67 ++++++++++++++++++++++++++++++++++
8 files changed, 206 insertions(+)
create mode 100644 debian/templates/triplestore.yaml.in
create mode 100644 etc/triplestore.yaml
create mode 100644 t/db_dependent/triplestore.t
--- a/C4/Context.pm
+++ a/C4/Context.pm
@@ -96,6 +96,7 @@ use POSIX ();
use DateTime::TimeZone;
use Module::Load::Conditional qw(can_load);
use Carp;
+use YAML;
use C4::Boolean;
use C4::Debug;
@@ -774,6 +775,69 @@ sub restore_dbh
# return something, then this function should, too.
}
+=head2 triplestore
+
+ my $triplestore = C4::Context->triplestore($model_name);
+
+Returns a handle to an initialised RDF::Trine::Model object
+
+=cut
+
+sub triplestore {
+ my ($self,$name) = @_;
+ die "Must provide a model name as an argument for the triplestore() method" unless $name;
+ my $triplestore = ( $context->{triplestore} && $context->{triplestore}->{$name} ) ? $context->{triplestore}->{$name} : undef;
+ if ( ! $triplestore ){
+ my $config_file = $context->config('triplestore_config');
+ if ( -f $config_file ){
+ my $config = YAML::LoadFile($config_file);
+ if ($config && $name){
+ my $new_triplestore = $self->_new_triplestore($config,$name);
+ if ( $new_triplestore && $new_triplestore->isa("RDF::Trine::Model") ){
+ $triplestore = $new_triplestore;
+ $context->{triplestore}->{$name} = $new_triplestore;
+ }
+ }
+ }
+ }
+ return $triplestore;
+}
+
+=head2 _new_triplestore
+
+=cut
+
+sub _new_triplestore {
+ my ($self, $config,$name) = @_;
+ if ($config && $name){
+ my $models = $config->{models};
+ if ($models){
+ my $model = $models->{$name};
+ if ($model){
+ my $module = $model->{module};
+ if ($module && $module eq 'RDF::Trine::Store::SPARQL'){
+ if ($module && can_load( 'modules' => { $module => undef } ) ){
+ my $url = URI->new($model->{url});
+ if ($url){
+ my $ua = RDF::Trine->default_useragent;
+ if ($ua){
+ my $realm = $model->{realm};
+ my $username = $model->{username};
+ my $password = $model->{password};
+ $ua->credentials($url->host.":".$url->port, $realm, $username, $password);
+ }
+ my $store = RDF::Trine::Store::SPARQL->new($url);
+ my $model = RDF::Trine::Model->new($store);
+ return $model;
+ }
+ }
+ }
+ }
+ }
+ }
+ return;
+}
+
=head2 queryparser
$queryparser = C4::Context->queryparser
--- a/C4/Installer/PerlDependencies.pm
+++ a/C4/Installer/PerlDependencies.pm
@@ -862,6 +862,11 @@ our $PERL_DEPS = {
'required' => '0',
'min_ver' => '0.07',
},
+ 'RDF::Trine' => {
+ 'usage' => 'Managing RDF and triplestores',
+ 'required' => '1',
+ 'min_ver' => '1.017',
+ },
};
1;
--- a/debian/scripts/koha-create
+++ a/debian/scripts/koha-create
@@ -711,6 +711,10 @@ eof
generate_config_file zebra.passwd.in \
"/etc/koha/sites/$name/zebra.passwd"
+ # Generate and install triplestore config file
+ generate_config_file triplestore.yaml.in \
+ "/etc/koha/sites/$name/triplestore.yaml"
+
# Create a GPG-encrypted file for requesting a DB to be set up.
if [ "$op" = request ]
--- a/debian/templates/koha-conf-site.xml.in
+++ a/debian/templates/koha-conf-site.xml.in
@@ -327,5 +327,8 @@ __END_SRU_PUBLICSERVER__
koha___KOHASITE__
+
+ /etc/koha/sites/__KOHASITE__/triplestore.yaml
+
--- a/debian/templates/triplestore.yaml.in
+++ a/debian/templates/triplestore.yaml.in
@@ -0,0 +1,30 @@
+---
+models:
+ query:
+ #module must be a valid RDF::Trine::Store::* module
+ module: RDF::Trine::Store::SPARQL
+
+ #When using RDF::Trine::Store::SPARQL:
+ url:
+ realm:
+ username:
+ password:
+ update:
+ #module must be a valid RDF::Trine::Store::* module
+ module: RDF::Trine::Store::SPARQL
+
+ #When using RDF::Trine::Store::SPARQL:
+ url:
+ realm:
+ username:
+ password:
+ #NOTE: Only the above models are likely to be used in Koha
+ read/write:
+ #module must be a valid RDF::Trine::Store::* module
+ module: RDF::Trine::Store::SPARQL
+
+ #When using RDF::Trine::Store::SPARQL:
+ url:
+ realm:
+ username:
+ password:
--- a/etc/koha-conf.xml
+++ a/etc/koha-conf.xml
@@ -153,5 +153,8 @@ __PAZPAR2_TOGGLE_XML_POST__
50
2
+
+ __KOHA_CONF_DIR__/triplestore.yaml
+
--- a/etc/triplestore.yaml
+++ a/etc/triplestore.yaml
@@ -0,0 +1,30 @@
+---
+models:
+ query:
+ #module must be a valid RDF::Trine::Store::* module
+ module: RDF::Trine::Store::SPARQL
+
+ #When using RDF::Trine::Store::SPARQL:
+ url:
+ realm:
+ username:
+ password:
+ update:
+ #module must be a valid RDF::Trine::Store::* module
+ module: RDF::Trine::Store::SPARQL
+
+ #When using RDF::Trine::Store::SPARQL:
+ url:
+ realm:
+ username:
+ password:
+ #NOTE: Only the above models are likely to be used in Koha
+ read/write:
+ #module must be a valid RDF::Trine::Store::* module
+ module: RDF::Trine::Store::SPARQL
+
+ #When using RDF::Trine::Store::SPARQL:
+ url:
+ realm:
+ username:
+ password:
--- a/t/db_dependent/triplestore.t
+++ a/t/db_dependent/triplestore.t
@@ -0,0 +1,67 @@
+#!/usr/bin/perl
+
+use Modern::Perl;
+use Test::More tests => 4;
+use Test::Exception;
+use YAML;
+use File::Temp qw/ tempfile /;
+
+use C4::Context;
+
+#Make a temporary configuration file for the triplestore
+my ($fh, $filename) = tempfile(undef, UNLINK => 1);
+my $temp_config = {
+ models => {
+ test => {
+ module => 'RDF::Trine::Store::SPARQL',
+ url => 'http://localhost/example/rdf',
+ realm => undef,
+ username => undef,
+ password => undef,
+ }
+ }
+};
+
+#Tell C4::Context to use the temporary configuration file as the triplestore_config
+my $context = $C4::Context::context;
+$context->{config}->{triplestore_config} = $filename;
+
+subtest 'success' => sub {
+ YAML::DumpFile($filename, $temp_config);
+
+ my $context_object = C4::Context->new();
+ my $triplestore = $context_object->triplestore("test");
+ is(ref $triplestore, 'RDF::Trine::Model', 'C4::Context->new()->triplestore returns RDF::Trine::Model if module equals RDF::Trine::Store::SPARQL');
+};
+
+subtest 'missing url' => sub {
+ #Reset triplestore context
+ delete $context->{triplestore}->{test};
+
+ my $url = delete $temp_config->{models}->{test}->{url};
+ YAML::DumpFile($filename, $temp_config);
+
+ my $context_object = C4::Context->new();
+ my $triplestore = $context_object->triplestore("test");
+ is($triplestore, undef, 'C4::Context->new()->triplestore returns undef if missing url for SPARQL store');
+
+ #Restore url for other tests
+ $temp_config->{url} = $url;
+};
+
+subtest 'bad module' => sub {
+ #Reset triplestore context
+ delete $context->{triplestore}->{test};
+
+ $temp_config->{module} = 'Local::RDF::Bad::Module';
+ YAML::DumpFile($filename, $temp_config);
+
+ my $context_object = C4::Context->new();
+ my $triplestore = $context_object->triplestore("test");
+ is($triplestore, undef, 'C4::Context->new()->triplestore returns undef if module equals Local::RDF::Bad::Module');
+};
+
+subtest 'missing model name' => sub {
+ my $context_object = C4::Context->new();
+ dies_ok { $context_object->triplestore } 'C4::Context::triplestore() method dies if no model name provided';
+};
--