NAME

DAIA - Document Availability Information API in Perl

DESCRIPTION

The Document Availability Information API (DAIA) defines a data model with serializations in JSON and XML to encode information about the current availability of documents. See http://purl.org/NET/DAIA for a detailed specification. This package provides Perl classes and functions to easily create and manage DAIA information. It can be used to implement DAIA servers, clients, and other programs that handle availability information.

The DAIA information objects as decriped in the DAIA specification are directly mapped to Perl packages. In addition a couple of functions can be exported if you prefer to handle DAIA data without much object-orientation.

SYNOPSIS

DAIA client

#!/usr/bin/perl
use DAIA;

$daia = DAIA::parse( $url );          # parse from URL
$daia = DAIA::parse( file => $file ); # parse from File

# parse from string
use Encode; # if incoming data is unencoded UTF-8
$data = Encode::decode_utf8( $data ); # skip this if $data is just Unicode
$daia = DAIA::parse( data => $string );

This package also includes and installs the command line and CGI client daia to fetch, validate and convert DAIA data. See also the clients directory for an XML Schema of DAIA/XML and an XSLT script to transform it to HTML.

DAIA server

First an example of a DAIA server as CGI script. You need to implement all get_... methods to return meaningful values. Some more hints how to run a DAIA Server below under under "#DAIA Server hints".

#!/usr/bin/perl
use DAIA qw(is_uri);
use CGI;
use utf8; # if source code containts UTF-8

my $r = response( institution => {
        href    => "http://example.com/homepage.of.institution",
        content => "Name of the Institution" 
} );

my $id = CGI->new->param('id');
$r->addMessage("en" => "Not an URI: $id", errno => 1 ) unless is_uri($id);
my @holdings = get_holding_information($id);  # YOU need to implement this!

if ( @holdings ) {
    my $doc = document( id => $id, href => "http://example.com/docs/$id" );
    foreach my $h ( @holdings ) {
        my $item = item();

        my %sto = get_holding_storage( $h );
        $item->storage( id => $sto{id}, href => $sto{href}, $sto{name} );

        my $label = get_holding_label( $h );
        $item->label( $label );

        my $url = get_holding_url( $h );
        $item->href( $url );

        # add availability services
        my @services;

        if ( get_holding_is_here( $h ) ) {
            push @services, available('presentation'), available('loan');
        } elsif( get_holding_is_not_here( $h ) ) {
            push @services, # expected to be back in 5 days
            unavailable( 'presentation', expected => 'P5D' ),
            unavailable( 'loan', expected => 'P5D' );
        } else {
           #  more cases (depending on the complexity of you application)
        }
        $item->add( @services );
    }
    $r->document( $doc );
} else {
    $r->addMessage( "en" => "No holding information found for id $id" );
}

$r->serve( xslt => "http://path.to/daia.xsl" );

In order to get your script run as CGI, you may have to enable CGI with Options +ExecCGI and AddHandler cgi-script .pl in your Apache configuration or .htaccess.

DAIA Server hints

DAIA server scripts can be tested on command line by providing HTTP parameters as key=value pairs.

It is recommended to run a DAIA server via mod_perl or FastCGI so it does not need to be compiled each time it is run. For mod_perl you simply put your script in a directory which PerlResponseHandler has been set for (for instance to Apache::Registry or ModPerl::PerlRun).

For FastCGI you need to install FCGI and set the CGI handler to "AddHandler fcgid-script .pl" in .htaccess. Your DAIA server must consist of an initialization section and a response loop:

#!/usr/bin/perl
use DAIA;
use CGI::Fast;

# ...initialization section, which is executed only once ...

while (my $q = new CGI::Fast) { # response loop
    my $id = $q->param('id');

    # ... create response ...
   
    $response->serve( cgi => $q, exitif => 0 );
}

The serve methods needs a cgi or format parameter and it is been told not to exit the script. It is recommended to check every given timespan whether the script has been modified and restart in this case:

#!/usr/bin/perl
use DAIA;
use CGI::Fast;

my $started = time;
my $thisscript = $0;
my $lastmod = stat($thisscript)->mtime;

sub restart {
    return 0 if time - $started < 10; # check every 10 seconds
    return 1 if stat($thisscript)->mtime > $lastmod;
}

while (my $q = new CGI::Fast) { # response loop

    # ... create response ...

    $response->serve( $q, exitif => \&restart } );
}

EXPORTED FUNCTIONS

If you prefer function calls in favor of constructor calls, this package providesfunctions for each DAIA class constructor. The functions are named by the object that they create but in lowercase - for instance response for the DAIA::Response object. The functions can be exported in groups. To disable exporting of the functions include DAIA like this:

use DAIA qw();      # do not export any functions
use DAIA qw(serve); # only export function 'serve'

By default all functions are exported (group :all) in addition you can specify the following groups:

:core

Includes the functions response (DAIA::Response), document (DAIA::Document), item (DAIA::Item), available (DAIA::Available), unavailable (DAIA::Unavailable), and availability (DAIA::Availability)

:entities

Includes the functions institution (DAIA::Institution), department (DAIA::department), storage (DAIA::Storage), and limitation (DAIA::Limitation)

serve( [ [ format => ] $format ] [ %options ] )

Calls the method method serve of DAIA::Response or another DAIA object to serialize and send a response to STDOUT with appropriate HTTP headers. You can call it this way:

serve( $response, @additionlArgs );  # as function
$response->serve( @additionlArgs );  # as method

ADDITIONAL FUNCTIONS

The following functions are not exportted but you can call both them as function and as method:

DAIA->parse_xml( $xml );
DAIA::parse_xml( $xml );

parse_xml( $xml, [ xmlns => 0|1 ] )

Parse DAIA/XML from a file or string. The first parameter must be a filename, a string of XML, or a IO::Handle object. The optional parameter xmlns defines whether parsing is namespace-aware - in this case all elements outside the DAIA XML namespace http://ws.gbv.de/daia/ are ignored.

Parsing is more lax then the specification so it silently ignores elements and attributes in foreign namespaces. Returns either a DAIA object or croaks on uncoverable errors.

parse_json( $json )

Parse DAIA/JSON from a file or string. The first parameter must be a filename, a string of XML, or a IO::Handle object.

parse ( $from [ %parameters ] )

Parse DAIA/XML or DAIA/JSON from a file or string. You can specify the source as filename, string, or IO::Handle object as first parameter or with the named from parameter. Alternatively you can either pass a filename or URL with parameter file or a string with parameter data. If the filename is an URL, its content will be fetched via HTTP. The format parameter (json or xml) is required unless the format can be detected automatically the following way:

  • A scalar starting with < and ending with > is parsed as DAIA/XML.

  • A scalar starting with { and ending with } is parsed as DAIA/JSON.

  • A scalar ending with .json is parsed as DAIA/JSON.

  • A scalar ending with .xml is is parsed as DAIA/XML.

The parameter xmlns (by default set to true) can be used to disable namespace-expanding when parsing DAIA/XML.

guess ( $string )

Guess serialization format (DAIA/JSON or DAIA/XML) and return json, xml or the empty string.

is_uri ( $value )

Checks whether the value is a well-formed URI. This function is imported from Data::Validate::URI into the namespace of this package as DAIA::is_uri and can be exported into the default namespace on request.

SEE ALSO

Please report bugs and feature requests via https://rt.cpan.org/Public/Dist/Display.html?Name=DAIA. The classes of this package are implemented using DAIA::Object which is just another Perl meta-class framework.

AUTHOR

Jakob Voss <jakob.voss@gbv.de>

LICENSE

Copyright (C) 2009 by Verbundzentrale Goettingen (VZG) and Jakob Voss

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.8 or, at your option, any later version of Perl 5 you may have available.