#!/usr/bin/perl -w # # redzip-serialise-0.3 - A script for serialising one or all contexts in a # persistent Redland model to an archive. # # Usage: ./redzip-serialise --redland [ --context ] # [ --output (rdfxml|turtle|ntriples) ] # # Example: ./redzip-serialise --redland mysql://user:password@mysql/db/model # # URL: http://www.wasab.dk/morten/blog/archives/2005/01/04/exchange-of-named-rdf-graphs # # Changelog # --------- # Version 0.3 - 2005.04.25: # - Added support for multiple models (morten@mfd-consult.dk). # - Order of contexts sorted (morten@mfd-consult.dk). # Version 0.2 - 2005.01.06: # - Added basic statistics in rdfs:comment (morten@mfd-consult.dk). # Version 0.1 - 2005.01.04: # - First release (morten@mfd-consult.dk). # # Copyright (c) 2005 MFD Consult, Morten Frederiksen # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # use strict; use Getopt::Long; use Pod::Usage; use URI; use RDF::Redland; use Archive::Zip qw( :ERROR_CODES :CONSTANTS ); # Command line variables. my $redland=''; my $context=''; my $output='ntriples'; my $verbose=-1; my $help=0; my %extensions=('turtle'=>'ttl', 'rdfxml'=>'rdf', 'ntriples'=>'nt'); # Parse command line. GetOptions( 'redland=s'=>\$redland, 'context=s'=>\$context, 'output=s'=>\$output, 'verbose:i'=>\$verbose, 'help|h'=>\$help) || pod2usage(2); pod2usage(-exitval=>1,-verbose=>2) if ($help || !$redland || !$extensions{$output}); # Validate/fix parameters. $verbose++ if ($verbose<=0); print STDERR "$0: initialising\n" if ($verbose); # Parse Redland URI: ://[[:]@]// my %redland=('user'=>'default','password'=>'default','database'=>'redland','model'=>'redland'); $redland=URI->new($redland); $redland{'type'}=$redland->scheme; $redland->scheme('http'); $redland{'hash-type'}=$redland{'host'}=$redland->host; ($redland{'user'},$redland{'password'})=split(':',$redland->userinfo) if ($redland->userinfo); ($redland{'dummy'},$redland{'database'},$redland{'model'})=$redland->path_segments if ($redland->path_segments); $redland{'dir'}=$redland{'database'}; # Create Redland objects... my $storage=new RDF::Redland::Storage($redland{'type'}, $redland{'model'},"host='".$redland{'host'}."',database='". $redland{'database'}."',user='".$redland{'user'}."',password='". $redland{'password'}."',contexts='yes',hash-type='". $redland{'hash-type'}."',dir='".$redland{'dir'}."'") or die ($0.': unable to create RDF::Redland::Storage'); my $model=new RDF::Redland::Model($storage,'') or die ($0.': unable to create RDF::Redland::Model'); my $serialiser=new RDF::Redland::Serializer($output) or die ($0.': unable to create RDF::Redland::Serializer'); # Build list of contexts to serialise. my @contexts; @contexts=new RDF::Redland::Node->new_from_uri($context) if ($context); @contexts=$model->contexts if (!$context); # Create archive. my $zip=Archive::Zip->new(); # Create temporary model to hold map of names. my $ms=new RDF::Redland::Storage('hashes', 'dummy', "new='yes',hash-type='memory'") or die $0.': unable to create temporary RDF::Redland::Storage'; my $mm=new RDF::Redland::Model($ms,'') or die $0.': unable to create temporary RDF::Redland::Model'; # Iterate through contexts, building map in model on the way. my $triplecount=0; my $filenum=0; my @tempfiles=(); foreach my $context (sort { $a->as_string cmp $b ->as_string } @contexts) { print STDERR "$0: serialising context ".$context->as_string."\n" if ($verbose); # Create temporary storage to hold statements before serialisation. my $cs=new RDF::Redland::Storage('hashes', 'dummy', "new='yes',hash-type='memory'") or die $0.': unable to create temporary RDF::Redland::Storage'; my $cm=new RDF::Redland::Model($cs,'') or die $0.': unable to create temporary RDF::Redland::Model'; # Add statements from context to temporary model. $cm->add_statements($model->as_stream($context)); $triplecount+=$cm->size; # Create temporary file and serialise temporary model. my ($tfh, $tfn)=Archive::Zip::tempFile(); !$serialiser->serialize_model_to_file($tfn, new RDF::Redland::URI(''), $cm) or die $0.': unable to serialise temporary model'; # Add contents of temporary file to archive. my $graph='graph'.++$filenum.'.'.$extensions{$output}; $zip->addFile($tfn, $graph); # Add graph name and statistics to map. $mm->add(new RDF::Redland::URI($graph), new RDF::Redland::URI('http://www.w3.org/2000/01/rdf-schema#label'), $context); $mm->add(new RDF::Redland::URI($graph), new RDF::Redland::URI('http://www.w3.org/2000/01/rdf-schema#comment'), new RDF::Redland::Node($cm->size.' statements')); $mm->add(new RDF::Redland::URI('META-INF/rdf-manifest.'.$extensions{$output}), new RDF::Redland::URI('http://www.w3.org/2000/01/rdf-schema#seeAlso'), new RDF::Redland::URI($graph)); # Clean up after context. push(@tempfiles, $tfn); $cm=undef; $cs=undef; } $filenum or die $0.': no context(s) found to serialise?'; $mm->add(new RDF::Redland::URI('META-INF/rdf-manifest.'.$extensions{$output}), new RDF::Redland::URI('http://www.w3.org/2000/01/rdf-schema#comment'), new RDF::Redland::Node($filenum.' graphs, '.$triplecount.' statements')); # Add map to archive. print STDERR "$0: creating map\n" if ($verbose); my ($tfh, $tfn)=Archive::Zip::tempFile(); !$serialiser->serialize_model_to_file($tfn, new RDF::Redland::URI(''), $mm) or die $0.': unable to serialise map model'; $zip->addFile($tfn, 'META-INF/rdf-manifest.'.$extensions{$output}); push(@tempfiles, $tfn); # "Serialise" archive. my $fh=IO::Handle->new_from_fd(fileno(STDOUT), 'w'); $zip->writeToFileHandle($fh, 0) == AZ_OK or die $0.': unable to create archive'; # Clean up... print STDERR "$0: cleaning up\n" if ($verbose); foreach my $tfn (@tempfiles) { unlink($tfn); } $mm=undef; $ms=undef; $serialiser=undef; $model=undef; $storage=undef; print STDERR $0.': done.'."\n" if ($verbose); __END__ =head1 NAME redzip-serialise - A script for serialising one or all contexts in a persistent Redland model to an archive. =head1 SYNOPSIS B B<--redland> I [ B<--context> I ] [ B<--output> I ] [ B<--verbose> [ I ] ] [ B<--help> ] =head1 DESCRIPTION I generates a .zip-archive containing a document for each context (or only the requested context) in the persistent Redland storage. =head1 OPTIONS AND ARGUMENTS =over 4 =item B<--redland> I URI for Redland model: ://[[:]@]// Examples: mysql://user:password@mysql/db/model hashes://bdb/./test =item B<--context> I URI of single context to serialise. =item B<--output> I Serialization format, I, I or I. Default is I. =item B<--verbose> I Output progress on STDERR. =item B<--help> | B<--?> Output manual page with usage instructions on stdout and exit. =back =head1 BUGS Temporary files are currently left as is when die'ing during execution. =head1 AUTHOR MFD Consult, Morten Frederiksen Emorten@mfd-consult.dkE URL: http://www.wasab.dk/morten/blog/archives/2005/01/04/exchange-of-named-rdf-graphs =cut