From 7680905239705ecb2a6063cc3c929f4e2276602b Mon Sep 17 00:00:00 2001 From: David Cook Date: Fri, 12 May 2017 14:58:47 +1000 Subject: [PATCH] [SIGNED-OFF] Bug 18585 - Connect to RDF triplestore This commit adds a 'triplestore' method to C4::Context, which returns a RDF::Trine::Model object if triplestore.yaml is properly configured. (At the moment, it just supports RDF::Trine::Store::SPARQL, but it would be trivial to add support for RDF::Trine::Store::DBI too.) This code will provide a base from which people can use RDF::Trine for querying and updating a RDF triplestore. Signed-off-by: Josef Moravec --- C4/Context.pm | 55 ++++++++++++++++++++++++++++++++ debian/scripts/koha-create | 4 +++ debian/templates/koha-conf-site.xml.in | 3 ++ debian/templates/triplestore.yaml.in | 9 ++++++ etc/koha-conf.xml | 3 ++ etc/triplestore.yaml | 9 ++++++ t/db_dependent/triplestore.t | 57 ++++++++++++++++++++++++++++++++++ 7 files changed, 140 insertions(+) create mode 100644 debian/templates/triplestore.yaml.in create mode 100644 etc/triplestore.yaml create mode 100644 t/db_dependent/triplestore.t diff --git a/C4/Context.pm b/C4/Context.pm index a50ddfd..eb390bf 100644 --- a/C4/Context.pm +++ b/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,60 @@ sub restore_dbh # return something, then this function should, too. } +=head2 triplestore + + $triplestore = C4::Context->triplestore + +Returns a handle to an initialised RDF::Trine::Model object + +=cut + +sub triplestore { + my $self = shift; + unless (defined $context->{"triplestore"}) { + my $config_file = $context->config('triplestore_config'); + if ( -f $config_file ){ + my $config = YAML::LoadFile($config_file); + if ($config){ + $context->{"triplestore"} = &_new_triplestore($config); + } + } + } + return + defined( $context->{"triplestore"} ) + ? $context->{"triplestore"} + : undef; +} + +=head _new_triplestore + +=cut + +sub _new_triplestore { + my ($config) = @_; + if ($config){ + my $module = $config->{module}; + if ($module eq 'RDF::Trine::Store::SPARQL'){ + if ($module && can_load( 'modules' => { $module => undef } ) ){ + my $url = URI->new($config->{url}); + if ($url){ + my $ua = RDF::Trine->default_useragent; + if ($ua){ + my $realm = $config->{realm}; + my $username = $config->{username}; + my $password = $config->{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 diff --git a/debian/scripts/koha-create b/debian/scripts/koha-create index b21e472..480c6d4 100755 --- a/debian/scripts/koha-create +++ b/debian/scripts/koha-create @@ -709,6 +709,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 ] diff --git a/debian/templates/koha-conf-site.xml.in b/debian/templates/koha-conf-site.xml.in index 2add4aa..0d62799 100644 --- a/debian/templates/koha-conf-site.xml.in +++ b/debian/templates/koha-conf-site.xml.in @@ -322,5 +322,8 @@ __END_SRU_PUBLICSERVER__ 50 2 + + /etc/koha/sites/__KOHASITE__/triplestore.yaml + diff --git a/debian/templates/triplestore.yaml.in b/debian/templates/triplestore.yaml.in new file mode 100644 index 0000000..258599b --- /dev/null +++ b/debian/templates/triplestore.yaml.in @@ -0,0 +1,9 @@ +--- +#module must be a valid RDF::Trine::Store::* module +module: RDF::Trine::Store::SPARQL + +#When using RDF::Trine::Store::SPARQL: +url: +realm: +username: +password: diff --git a/etc/koha-conf.xml b/etc/koha-conf.xml index 4ccee3a..39d33b3 100644 --- a/etc/koha-conf.xml +++ b/etc/koha-conf.xml @@ -153,5 +153,8 @@ __PAZPAR2_TOGGLE_XML_POST__ 50 2 + + __KOHA_CONF_DIR__/triplestore.yaml + diff --git a/etc/triplestore.yaml b/etc/triplestore.yaml new file mode 100644 index 0000000..258599b --- /dev/null +++ b/etc/triplestore.yaml @@ -0,0 +1,9 @@ +--- +#module must be a valid RDF::Trine::Store::* module +module: RDF::Trine::Store::SPARQL + +#When using RDF::Trine::Store::SPARQL: +url: +realm: +username: +password: diff --git a/t/db_dependent/triplestore.t b/t/db_dependent/triplestore.t new file mode 100644 index 0000000..2ef4c2c --- /dev/null +++ b/t/db_dependent/triplestore.t @@ -0,0 +1,57 @@ +#!/usr/bin/perl + +use Modern::Perl; +use Test::More tests => 3; +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 = { + 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; + +SUCCESS: { + YAML::DumpFile($filename, $temp_config); + + my $context_object = C4::Context->new(); + my $triplestore = $context_object->triplestore; + is(ref $triplestore, 'RDF::Trine::Model', 'C4::Context->new()->triplestore returns RDF::Trine::Model if module equals RDF::Trine::Store::SPARQL'); +} + +MISSING_URL: { + #Reset triplestore context + delete $context->{triplestore}; + + my $url = delete $temp_config->{url}; + YAML::DumpFile($filename, $temp_config); + + my $context_object = C4::Context->new(); + my $triplestore = $context_object->triplestore; + is($triplestore, undef, 'C4::Context->new()->triplestore returns undef if missing url for SPARQL store'); + + #Restore url for other tests + $temp_config->{url} = $url; +} + +BAD_MODULE: { + #Reset triplestore context + delete $context->{triplestore}; + + $temp_config->{module} = 'Local::RDF::Bad::Module'; + YAML::DumpFile($filename, $temp_config); + + my $context_object = C4::Context->new(); + my $triplestore = $context_object->triplestore; + is($triplestore, undef, 'C4::Context->new()->triplestore returns undef if module equals Local::RDF::Bad::Module'); +} -- 2.1.4