Thursday, August 30, 2007

An LSID client

The last post was on how to build a resolver. This post is on how to build a client. The simple Perl client below retrieves metadata only (but I think it's fairly obvious which line needs to be changed to retrieve data ;-) )

Here we go!


use LS::ID;
use LS::Locator;

$lsid = LS::ID->new(
'urn:lsid:biomoby.org:servicetype:Retrieval:2001-09-21T16-00-00Z'
);

$locator = LS::Locator->new();
$authority = $locator->resolveAuthority($lsid);
$resource = $authority->getResource($lsid);
$data = $resource->getMetadata();
$response_filehandle = $data->response;
print <$response_filehandle>;
print "\n";


Voila! You hopefully have a bunch of RDF on your screen right now. Sure, that's a couple more lines than LWP::Simple, but some of that could be better encapsulated, so it really is only one or two lines more code than trying to do a GET... and with all sorts of benefits!

Oh! And here's how you get the LSID code from sourceforge. Get yourself a copy of Subversion, then cleck-out the code using subversion as so:

svn co http://lsids.svn.sourceforge.net/svnroot/lsids/trunk/lsid-perl lsids

(windows users will have a nice GUI for this)

Note that the sourceforge site indicates that it should be https://, but it works just as well as http, so you don't have to re-install Subversion to make it SSL compliant.

Wednesday, August 29, 2007

The Hello World LSID authority and metadata server

Since I'm out there advocating for LSIDs, and since the documentaton for LSIDs is hard to find and hard to work-through, I thought I'd take a stab at doing a "Hello World" LSID authority and metadata resolution server.

This is "as easy as it gets", but the process can be much more complex if needed. This solution requires no modification of the DNS/SRV records, and runs as a simple HTTP GET CGI service for metadata resolution.

Here we go! :-)


*** A HELLO WORLD LSID AUTHORITY ***
*** authority.pl ***

#!/usr/bin/perl
use strict;
use warnings;


use LS::Service::Authority;
use LS::Service::DataService;
use LS::HTTP::Service;
use LS::SOAP::Service transport=> 'HTTP::CGI';

my $location = 'http://';
if($ENV{'HTTP_HOST'} ) {
$location .= $ENV{'HTTP_HOST'};
}
else {
$location .= 'localhost:8080';
}


# FIRST create the authority service

my $authority_service = LS::Service::Authority->new(
name=> 'Hello_World',
authority=> 'bioinfo.icapture.ubc.ca',
location=> $location);


# SECOND create an HTTP GET metadata port
# what comes in here will be:
# $location/authority/metadata?lsid=URN:LSID:blah.blah:nspace:id:version

my $metadata_port =
LS::Authority::WSDL::Simple::MetadataPort->newMetadata(
portName=> 'Hello_there_World',
endpoint=> "$location/authority/metadata",
protocol=> $LS::Authority::WSDL::Constants::Protocols::HTTP,
);
$authority_service->addPort(
serviceName=> 'Hello_World',
port=> $metadata_port);


my $authority_server = LS::SOAP::Service->new();
$authority_server->authorityService($authority_service);

my $http_authority = LS::HTTP::Service->new();
$http_authority->dispatch_authority_to($authority_service);

$authority_server->httpServer($http_authority);
$authority_server->dispatch();



***** HELLO WORLD LSID METADATA SERVER *****
***** metadata.pl ******

#!/usr/bin/perl

use CGI qw/:all/;
my $C = CGI->new;

use strict;
use warnings;

use LS::ID;
use LS::Service::Response;
use LS::Service::Fault;
use LS::RDF::SimpleDocument;

my $lsid = param('lsid');
my $format = param('format') || "text/xml";

print header(-type => $format);
print getMetadata($lsid)->response;

sub getMetadata {
my ($lsid, $format) = @_;
$lsid = LS::ID->new($lsid);
$lsid = $lsid->canonical();

my $id = $lsid->object();
$id .= ':' . $lsid->revision() if($lsid->revision());

return LS::Service::Fault->serverFault(
'Can not do what I cannot do', 500)
unless($id);

# Create a new RDF Document to add triples

my $rdfDoc = LS::RDF::SimpleDocument->new();

return LS::Service::Fault->serverFault(
'Internal error, unable to initialize RDF document', 500)
unless($rdfDoc);

return LS::Service::Fault->fault('Unknown LSID')
unless(1); # whatever conditions you want...


$rdfDoc->addTripleLiteral(
$lsid->as_string(),
'http://purl.org/dc/elements/1.1/#title',
"Hello World");

$rdfDoc->addTripleResource(
$lsid->as_string(),
'urn:lsid:example.com:predicates:another_lsid',
'urn:lsid:biomoby.org:objectclass:DNASequence');

$format = 'application/xml' if(!$format);
return LS::Service::Response->new(
response=> '' .
$rdfDoc->output(),
format=> $format);
}



***** APACHE Server Config ******
***** add these lines to your httpd.conf file ****


ScriptAlias /authority/metadata "/usr/local/apache2/LSID/metadata.pl"
ScriptAlias /authority "/usr/local/apache2/LSID/authority.pl"

<Directory /usr/local/apache2/LSID>
Options ExecCGI
Order allow,deny
Allow from all
</Directory>


*** now put your files in the right place

Create a folder /usr/local/apache2/LSID/
save authority.pl to that folder
save metadata.pl to that folder
(get the permissions right!)

DONE!

You now have an LSID authority and metadata resolver! Enjoy!