Permalink
Browse files

added support of DAIA/RDF

  • Loading branch information...
1 parent f2a5b60 commit 9b70b63876a435e3ca70a4de022af63cb4e4395e @nichtich committed Dec 14, 2011
Showing with 98 additions and 21 deletions.
  1. +7 −0 Changes
  2. +2 −0 app.psgi
  3. +4 −1 dist.ini
  4. +57 −9 lib/Plack/App/DAIA.pm
  5. +28 −11 lib/Plack/App/DAIA/Validator.pm
View
@@ -0,0 +1,7 @@
+# Change file for Plack::App::DAIA
+
+0.2 2011-12-14
+ Added support of DAIA/RDF
+
+0.1 2011-12-08
+ First public version at CPAN
View
@@ -18,6 +18,8 @@ use Plack::App::DAIA::Validator;
my $app = MyDAIAServer->new;
builder {
+ # TODO: enable RDF::Flow middleware ( make MyDAIAServer a RDF::FLow
+ # enable 'RDF::Flow', source => $model; pass_through = 1?
mount '/validator' => Plack::App::DAIA::Validator->new;
mount '/' => $app;
};
View
@@ -1,6 +1,6 @@
name = Plack-App-DAIA
license = Perl_5
-version = 0.11
+version = 0.2
copyright_year = 2011
author = Jakob Voss
copyright_holder = Jakob Voss
@@ -10,6 +10,9 @@ copyright_holder = Jakob Voss
[PodWeaver]
[AutoPrereqs]
+[Prereqs]
+DAIA = 0.35
+
[FileFinder::ByName]
file = app.psgi
View
@@ -7,11 +7,31 @@ use parent 'Plack::Component';
use LWP::Simple qw(get);
use Encode;
use JSON;
-use DAIA '0.35';
+use DAIA;
+use Scalar::Util qw(blessed);
use Plack::Util::Accessor qw(xsd xslt warnings);
use Plack::Request;
+# we do not want depend on the following modules
+our ($TRINE_MODEL, $TRINE_SERIALIZER, $RDF_NS, $GRAPHVIZ);
+BEGIN {
+ # optionally use RDF::Trine::Serializer
+ $TRINE_MODEL = 'RDF::Trine::Model';
+ $TRINE_SERIALIZER = 'RDF::Trine::Serializer';
+ eval "use $TRINE_MODEL; use $TRINE_SERIALIZER";
+ if ($@) {
+ $TRINE_MODEL = undef;
+ $TRINE_SERIALIZER = undef;
+ }
+ # optionally use RDF::NS
+ eval "use RDF::NS";
+ $RDF_NS = eval "RDF::NS->new('any')" unless $@;
+ # optionally use RDF::Trine::Exporter::GraphViz
+ eval "use RDF::Trine::Exporter::GraphViz";
+ $GRAPHVIZ = 'RDF::Trine::Exporter::GraphViz' unless $@;
+}
+
sub prepare_app {
my $self = shift;
$self->warnings(1) unless defined $self->warnings;
@@ -26,7 +46,7 @@ sub call {
my $format = lc($req->param('format')) || "";
if (!$format) {
- # TODO: try content negotiation if DAIA/RDF is enabled
+ # TODO: guess format via content negotiation
}
my $daia = $self->retrieve( $id );
@@ -55,7 +75,25 @@ sub as_psgi {
my ($type, $content);
- if ( $format eq 'rdfjson' and $DAIA::VERSION >= 0.35 ) {
+ if ( $TRINE_SERIALIZER and $format and $format !~ /^(rdfjson|json|xml)$/ ) {
+ my %opt;
+ $opt{namespaces} = $RDF_NS if $RDF_NS and $format ne 'rdfxml'; # NOTE: RDF/XML dumps all namespaces
+ my $ser;
+ if ( $GRAPHVIZ and $TRINE_MODEL and $format =~ /^(dot|svg)$/ ) {
+ $ser = $GRAPHVIZ->new( as => $format, %opt );
+ } else {
+ $ser = eval { $TRINE_SERIALIZER->new( $format, %opt ); };
+ }
+ if ($ser) {
+ # NOTE: We could get rid of RDF::Trine::Model if hashref converted directly to iterator
+ my $model = $TRINE_MODEL->temporary_model;
+ $model->add_hashref( $daia->rdfhash );
+ ($type) = $ser->media_types( $format );
+ $content = $ser->serialize_model_to_string( $model );
+ }
+ }
+
+ if ( $format eq 'rdfjson' ) {
$type = "application/javascript; charset=utf-8";
$content = JSON->new->pretty->encode($daia->rdfhash);
# TODO: other serializations
@@ -64,10 +102,14 @@ sub as_psgi {
$content = $daia->json( $callback );
# TODO: add rdf serialization formats
- } else {
+ } elsif (!$content) {
$type = "application/xml; charset=utf-8";
- if ( $format ne 'xml' and $self->warnings ) {
- $daia->addMessage( 'en' => 'please provide an explicit parameter format=xml', 300 );
+ if ( $self->warnings ) {
+ if ( not $format ) {
+ $daia->addMessage( 'en' => 'please provide an explicit parameter format=xml', 300 );
+ } elsif ( $format ne 'xml' ) {
+ $daia->addMessage( 'en' => 'unknown or unsupported format', 300 );
+ }
}
$content = $daia->xml( ( $self->xslt ? (xslt => $self->xslt) : () ) );
}
@@ -100,7 +142,7 @@ This module implements a L<DAIA> server as PSGI application. It provides
serialization in DAIA/XML and DAIA/JSON and automatically adds some warnings
and error messages. The core functionality must be implemented by deriving
from this class and implementing the method C<retrieve>. The following
-serialization formats are supported:
+serialization formats are supported by default:
=over 4
@@ -118,6 +160,12 @@ DAIA/RDF in RDF/JSON.
=back
+In addition you get DAIA/RDF in several RDF formats (C<rdfxml>,
+C<turtle>, and C<ntriples> if L<RDF::Trine> is installed. If L<RDF::NS> is
+installed, you also get known namespace prefixes for RDF/Turtle format.
+Furthermore the output formats C<svg> and C<dot> are supported if
+L<RDF::Trine::Exporter::GraphViz> is installed to visualize RDF graphs.
+
=method new ( [%options] )
Creates a new DAIA server. Known options are
@@ -145,8 +193,8 @@ if you derive an application from Plack::App::DAIA.
=method as_psgi ( $status, $daia [, $format [, $callback ] ] )
-Serializes a L<DAIA::Response> in some DAIA serialization format (C<xml>
-by default) and returns a a PSGI response with given HTTP status code.
+Serializes a L<DAIA::Response> in some DAIA serialization format (C<xml> by
+default) and returns a a PSGI response with given HTTP status code.
=method call
@@ -9,6 +9,22 @@ use Encode;
use parent 'Plack::App::DAIA';
use Plack::Util::Accessor qw(xsd xslt warnings);
+our ($FORMATS, $GRAPHVIZ);
+BEGIN {
+ $FORMATS = { 'html'=>'HTML','json'=>'DAIA/JSON','xml'=>'DAIA/XML' };
+ # optionally add DAIA/RDF
+ eval "use RDF::Trine::Serializer";
+ my @names = eval "RDF::Trine::Serializer->serializer_names" unless $@;
+ unless ($@) {
+ $FORMATS->{$_} = "DAIA/RDF ($_)" for @names;
+ }
+ eval "use RDF::Trine::Exporter::GraphViz";
+ $GRAPHVIZ = 'RDF::Trine::Exporter::Graphviz' unless $@;
+ unless ($@) {
+ $FORMATS->{$_} = "DAIA/RDF graph ($_)" for qw(dot svg);
+ }
+}
+
sub call {
my ($self, $env) = @_;
my $req = Plack::Request->new($env);
@@ -25,7 +41,7 @@ sub call {
my $xsd = $self->xsd;
my $informat = lc($req->param('in'));
- my $outformat = lc($req->param('out')) || lc($req->param('format'));
+ my $outformat = lc($req->param('out')) || lc($req->param('format')) || 'html';
my $callback = $req->param('callback') || "";
$callback = "" unless $callback =~ /^[a-z][a-z0-9._\[\]]*$/i;
@@ -50,11 +66,11 @@ sub call {
$daia = shift @daiaobjs;
}
- if ( $outformat =~ /^(json|xml)$/ ) {
+ if ( $FORMATS->{$outformat} and $outformat ne 'html' ) {
$daia = DAIA::Response->new() unless $daia;
- $daia->addMessage(error(500,'en' => $error)) if $error;
- return $self->serialize( 200, $daia, $outformat, $req->param('callback') );
- } elsif ( $outformat and $outformat ne 'html' ) {
+ $daia->addError( 500, 'en' => $error ) if $error;
+ return $self->as_psgi( 200, $daia, $outformat, $req->param('callback') );
+ } elsif ( $outformat ne 'html' ) {
$error = "Unknown output format - using HTML instead";
}
@@ -95,8 +111,6 @@ sub call {
<form method="post" accept-charset="utf-8" action="">
HTML
- # TODO: current value of informat/outformat
-
$html .= $msg . $error .
fieldset(label('Input: ',
popup_menu('in',['','json','xml'],'',
@@ -108,13 +122,17 @@ HTML
).
fieldset(
label('Output: ',
- popup_menu('out',['html','json','xml'],'html',
- {'html'=>'HTML','json'=>'DAIA/JSON','xml'=>'DAIA/XML'})
+ popup_menu('out',
+ [ sort { $FORMATS->{$a} cmp $FORMATS->{$b} } keys %$FORMATS ],
+ $outformat, $FORMATS )
), '&#xA0;',
label('JSONP Callback: ', textfield(-name=>'callback',-value=>$callback))
).
fieldset('<input type="submit" value="Convert" class="submit" />')
;
+ if ($GRAPHVIZ && $url && !$data) {
+ $html .= "<fieldset>See RDF graph <a href=\"?url=$eurl&format=svg\">as SVG</a></fieldset>";
+ }
$html .= '</form>';
if ($daia) {
@@ -156,10 +174,9 @@ HTML
$html .= "</div>";
}
- my $VERSION = $DAIA::VERSION;
$html .= <<HTML;
<div class='footer'>
-Based on <a href='http://search.cpan.org/perldoc?Plack::App::DAIA'>Plack::App::DAIA</a> $VERSION.
+Based on <a href='http://search.cpan.org/perldoc?Plack::App::DAIA'>Plack::App::DAIA</a> ${DAIA::VERSION}.
Visit the <a href="http://github.com/gbv/daia/">DAIA project at github</a> for sources and details.
</div></body>
HTML

0 comments on commit 9b70b63

Please sign in to comment.