Commits

Toby Inkster committed 2fe9051

release 0.001

Comments (0)

Files changed (14)

+############################################################################
+## Changes #################################################################
+############################################################################
+
+RDF-Everywhere
+==============
+
+Created:      2010-11-22
+Home page:    <http://search.cpan.org/dist/RDF-Everywhere/>
+Bug tracker:  <http://rt.cpan.org/Dist/Display.html?Queue=RDF-Everywhere>
+Maintainer:   Toby Inkster <mailto:tobyink@cpan.org>
+
+0.001 [2010-11-24]
+
 @prefix dcs:     <http://ontologi.es/doap-changeset#> .
 @prefix dc:      <http://purl.org/dc/terms/> .
 @prefix foaf:    <http://xmlns.com/foaf/0.1/> .
-@prefix my:      <http://purl.org/NET/cpan-uri/dist/Example-Example/> .
+@prefix my:      <http://purl.org/NET/cpan-uri/dist/RDF-Everywhere/> .
 @prefix rdfs:    <http://www.w3.org/2000/01/rdf-schema#> .
 @prefix toby:    <http://tobyinkster.co.uk/#> .
 @prefix xsd:     <http://www.w3.org/2001/XMLSchema#> .
 <>
 
 	dc:title         "Changes" ;
-	dc:description   "Revision history for Perl extension Example::Example."@en ;
+	dc:description   "Revision history for Perl extension RDF::Everywhere."@en ;
 	dc:subject       my:project ;
 	dc:creator       toby:i .
 
 #############################################################
 
-my:v_0-01
+my:v_0-001
 
 	a               :Version ;
-	dc:issued       "2000-01-01"^^xsd:date ;
-	:revision       "0.01"^^xsd:string ;
-	:file-release   <http://backpan.cpan.org/authors/id/T/TO/TOBYINK/Example-Example-0.01.tar.gz> ;
+	dc:issued       "2010-11-24"^^xsd:date ;
+	:revision       "0.001"^^xsd:string ;
+	:file-release   <http://backpan.cpan.org/authors/id/T/TO/TOBYINK/RDF-Everywhere-0.001.tar.gz> ;
 	rdfs:comment    "Original version"@en .
 
 #############################################################
 my:project
 
 	a               :Project ;
-	:name           "Example-Example" ;
-	:shortdesc      "Example Project"@en ;
+	:name           "RDF-Everywhere" ;
+	:shortdesc      "makes everything in your Perl code an RDF resource"@en ;
 	:programming-language  "Perl" ;
-	:homepage       <http://search.cpan.org/dist/Example-Example/> ;
-	:download-page  <http://search.cpan.org/dist/Example-Example/> ;
-	:bug-database   <http://rt.cpan.org/Dist/Display.html?Queue=Example-Example> ;
-	:repository     [ a :SVNRepository ; :browse <http://goddamn.co.uk/viewvc/perlmods/Example-Example/> ] ;
+	:homepage       <http://search.cpan.org/dist/RDF-Everywhere/> ;
+	:download-page  <http://search.cpan.org/dist/RDF-Everywhere/> ;
+	:bug-database   <http://rt.cpan.org/Dist/Display.html?Queue=RDF-Everywhere> ;
+	:repository     [ a :SVNRepository ; :browse <http://goddamn.co.uk/viewvc/perlmods/RDF-Everywhere/> ] ;
 	:maintainer     toby:i ;
 	:developer      toby:i ;
 	:documenter     toby:i ;
 	:tester         toby:i ;
-	:created        "2000-01-01"^^xsd:date ;
+	:created        "2010-11-22"^^xsd:date ;
 	:license        <http://dev.perl.org/licenses/> ;
-	:release        my:v_0-01 .
+	:release        my:v_0-001 .
 
 #############################################################
 
+<?xml version="1.0" encoding="utf-8"?>
+<rdf:RDF xmlns:dbug="http://ontologi.es/doap-bugs#" xmlns:dc="http://purl.org/dc/terms/" xmlns:dcs="http://ontologi.es/doap-changeset#" xmlns:doap="http://usefulinc.com/ns/doap#" xmlns:foaf="http://xmlns.com/foaf/0.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
+<rdf:Description rdf:nodeID="r79F067EAF7A111DF8EDE9D930972E4D4r0">
+	<doap:browse rdf:resource="http://goddamn.co.uk/viewvc/perlmods/RDF-Everywhere/"/>
+	<rdf:type rdf:resource="http://usefulinc.com/ns/doap#SVNRepository"/>
+</rdf:Description>
+<rdf:Description rdf:about="file:///home/tai/src/perlmods/RDF-Everywhere/Changes.ttl">
+	<dc:creator rdf:resource="http://tobyinkster.co.uk/#i"/>
+	<dc:description xml:lang="en">Revision history for Perl extension RDF::Everywhere.</dc:description>
+	<dc:subject rdf:resource="http://purl.org/NET/cpan-uri/dist/RDF-Everywhere/project"/>
+	<dc:title>Changes</dc:title>
+</rdf:Description>
+<rdf:Description rdf:about="http://purl.org/NET/cpan-uri/dist/RDF-Everywhere/project">
+	<doap:bug-database rdf:resource="http://rt.cpan.org/Dist/Display.html?Queue=RDF-Everywhere"/>
+	<doap:created rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2010-11-22</doap:created>
+	<doap:developer rdf:resource="http://tobyinkster.co.uk/#i"/>
+	<doap:documenter rdf:resource="http://tobyinkster.co.uk/#i"/>
+	<doap:download-page rdf:resource="http://search.cpan.org/dist/RDF-Everywhere/"/>
+	<doap:homepage rdf:resource="http://search.cpan.org/dist/RDF-Everywhere/"/>
+	<doap:license rdf:resource="http://dev.perl.org/licenses/"/>
+	<doap:maintainer rdf:resource="http://tobyinkster.co.uk/#i"/>
+	<doap:name>RDF-Everywhere</doap:name>
+	<doap:programming-language>Perl</doap:programming-language>
+	<doap:release rdf:resource="http://purl.org/NET/cpan-uri/dist/RDF-Everywhere/v_0-001"/>
+	<doap:repository rdf:nodeID="r79F067EAF7A111DF8EDE9D930972E4D4r0"/>
+	<doap:shortdesc xml:lang="en">makes everything in your Perl code an RDF resource</doap:shortdesc>
+	<doap:tester rdf:resource="http://tobyinkster.co.uk/#i"/>
+	<rdf:type rdf:resource="http://usefulinc.com/ns/doap#Project"/>
+</rdf:Description>
+<rdf:Description rdf:about="http://purl.org/NET/cpan-uri/dist/RDF-Everywhere/v_0-001">
+	<dc:issued rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2010-11-24</dc:issued>
+	<doap:file-release rdf:resource="http://backpan.cpan.org/authors/id/T/TO/TOBYINK/RDF-Everywhere-0.001.tar.gz"/>
+	<doap:revision rdf:datatype="http://www.w3.org/2001/XMLSchema#string">0.001</doap:revision>
+	<rdf:type rdf:resource="http://usefulinc.com/ns/doap#Version"/>
+	<rdfs:comment xml:lang="en">Original version</rdfs:comment>
+</rdf:Description>
+<rdf:Description xmlns:ns1="http://www.w3.org/2002/07/owl#" rdf:about="http://tobyinkster.co.uk/#i">
+	<rdf:type rdf:resource="http://xmlns.com/foaf/0.1/Person"/>
+	<ns1:sameAs rdf:resource="http://purl.org/NET/cpan-uri/person/tobyink"/>
+	<foaf:homepage rdf:resource="http://tobyinkster.co.uk/"/>
+	<foaf:mbox rdf:resource="mailto:tobyink@cpan.org"/>
+	<foaf:name>Toby Inkster</foaf:name>
+	<foaf:page rdf:resource="http://search.cpan.org/~tobyink/"/>
+</rdf:Description>
+</rdf:RDF>
 META.yml
 SIGNATURE
 
+lib/RDF/Everywhere.pm
+
 t/00sig.t
 t/01basic.t
+
+inc/Module/AutoInstall.pm
+inc/Module/Install/AutoInstall.pm
+inc/Module/Install/Base.pm
+inc/Module/Install/Can.pm
+inc/Module/Install/DOAPChangeSets.pm
+inc/Module/Install/Fetch.pm
+inc/Module/Install/Include.pm
+inc/Module/Install/Makefile.pm
+inc/Module/Install/Metadata.pm
+inc/Module/Install.pm
+inc/Module/Install/ReadmeFromPod.pm
+inc/Module/Install/Win32.pm
+inc/Module/Install/WriteAll.pm
+inc/Test/Signature.pm
+---
+abstract: 'makes everything in your Perl code an RDF resource.'
+author:
+  - 'Toby Inkster <tobyink@cpan.org>'
+build_requires:
+  ExtUtils::MakeMaker: 6.42
+  Module::Signature: 0.66
+  Test::More: 0.61
+configure_requires:
+  ExtUtils::MakeMaker: 6.42
+distribution_type: module
+generated_by: 'Module::Install version 1.00'
+keywords:
+  - Perl
+  - RDF
+  - SemWeb
+  - 'Semantic Web'
+  - hashref
+  - class
+  - arrayref
+  - scalar
+  - UNIVERSAL
+license: perl
+meta-spec:
+  url: http://module-build.sourceforge.net/META-spec-v1.4.html
+  version: 1.4
+name: RDF-Everywhere
+no_index:
+  directory:
+    - inc
+    - t
+requires:
+  Data::UUID: 0
+  RDF::Trine: 0.130
+  Scalar::Util: 1.00
+  URI: 1.30
+  perl: 5.8.0
+resources:
+  bugtracker: http://rt.cpan.org/Dist/Display.html?Queue=RDF-Everywhere
+  homepage: http://search.cpan.org/dist/RDF-Everywhere/
+  license: http://dev.perl.org/licenses/
+  repository: http://goddamn.co.uk/viewvc/perlmods/RDF-Everywhere/
+version: 0.001
 
 use inc::Module::Install;
 
-my $dist = 'Example-Example';
+my $dist = 'RDF-Everywhere';
 my $fn   = "lib/$dist.pm"; $fn =~ s#-#/#g;
 
 name                $dist;
 author              'Toby Inkster <tobyink@cpan.org>';
 license             'perl';
 
+requires            'Data::UUID'         => 0;
+test_requires       'Module::Signature'  => '0.66';
+requires            'RDF::Trine'         => '0.130';
+requires            'Scalar::Util'       => '1.00';
 test_requires       'Test::More'         => '0.61';
-test_requires       'Module::Signature'  => '0.66';
-requires            'Carp'               => '1.00';
-requires            'DateTime'           => 0;
-requires            'RDF::Trine'         => '0.112';
-requires            'XML::LibXML'        => '1.60';
 requires            'URI'                => '1.30';
 
-# install_script 'fingerw';
-
 resources(
 	'homepage'   => "http://search.cpan.org/dist/$dist/",
 	'repository' => "http://goddamn.co.uk/viewvc/perlmods/$dist/",
 	'bugtracker' => "http://rt.cpan.org/Dist/Display.html?Queue=$dist",
 	);
 
-keywords("Perl");
+keywords("Perl", "RDF", "SemWeb", "Semantic Web", "hashref", "class", "arrayref", "scalar", "UNIVERSAL");
 	
 write_doap_changes;
 write_doap_changes_xml;

RDF-Everywhere-0.001.tar.gz

Binary file added.
+NAME
+    RDF::Everywhere - makes everything in your Perl code an RDF resource.
+
+SYNOPSIS
+      use RDF::Everywhere;
+  
+      # Methods are installed in UNIVERSAL, so can be called on any
+      # blessed object.
+      $headers = LWP::UserAgent->new->get('http://example.com/')->headers;
+      printf("## %s\n", $headers->rdf_node->as_ntriples);
+      print $headers->to_rdf(as => 'Turtle');
+  
+      use RDF::Everywhere qw[rdf_node to_rdf];
+  
+      # They can also be used as functions, which is useful when calling
+      # on unblessed variables.
+      print to_rdf {
+        name      => 'Toby Inkster',
+        cpanid    => 'TOBYINK',
+        page      => URI->new('http://search.cpan.org/~tobyink/'),
+        dist      => [
+            { name => 'RDF-Everywhere',     version => '0.001' },
+            { name => 'RDF-TrineShortcuts', version => '0.102' },
+          ],
+        }, as => 'RDFXML';
+
+DESCRIPTION
+    I'd been thinking of doing something like this for a while, and then
+    Nathan Rixham went and wrote a Javascript version, which spurred me to
+    do it for Perl.
+
+    The idea is that RDF's graph data model is not dissimilar to Perl's data
+    model, so all Perl objects get a "to_rdf" method which returns an RDF
+    equivalent of the object's data.
+
+  Universal Methods
+    The following methods are defined in the UNIVERSAL namespace, which
+    means they can be called on all blessed objects (like "can" and "isa").
+
+    "rdf_node"
+        Returns an RDF::Trine::Node object identifying the object. This will
+        usually be an RDF::Trine::Node::Blank but occasionally a
+        RDF::Trine::Node::Resource or even a RDF::Trine::Node::Literal.
+
+    "rdf_type"
+        Returns an RDF::Trine::Node::Resource object identifying the type of
+        object.
+
+    "to_rdf(%options)"
+        Returns an RDF::Trine::Model object containing data about the
+        object. The three options worth bothering about are:
+
+        as: instead of returning a Model, return a string formatted using
+        this serialisation. e.g. "as=>'Turtle'". Accepts the same
+        serialisations as "RDF::Trine::Serializer->new" (e.g. 'Turtle',
+        'RDFXML', 'NTriples', 'RDFJSON').
+        recurse: also include data about "child" objects. This is smart
+        enough to avoid infinite loops (or should be). Defaults to true, but
+        "recurse=>0" can be passed to force the method to avoid recursion.
+        model: an existing model to add data to. This is expected to be a
+        blessed object which has an "add_statement" method accepting an
+        RDF::Trine::Statement. An RDF::Trine::Model would be what you'd
+        normally provide.
+
+  Functions
+    The methods are also available as functions. Just export them:
+
+      use RDF::Everywhere qw[to_rdf];
+
+    And use them by passing the thing you want to convert to RDF as the
+    first parameter. This is useful in that it allows you to use
+    RDF::Everywhere's functionality with non-blessed variables.
+
+HOW IT WORKS
+    *Advanced usage information.*
+
+  How are Perl variables converted to RDF::Trine::Nodes?
+    A module can of course override rdf_node via normal Perl inheritance,
+    but the UNIVERSAL version works like this:
+
+    Firstly, @RDF::Everywhere::typed_literal_converters is checked for a
+    converter function that can handle it. This list takes the following
+    format:
+
+      (
+        [ 'Foo::Bar' => sub { my $obj = shift; ... ; return $node; } ],
+        [ 'Foo::Baz' => sub { my $obj = shift; ... ; return $node; } ],
+      );
+
+    If an entry in the list applies to the variable being converted, it is
+    use to perform the conversion.
+
+    Typed literal converters are pre-defined for <DateTime>, <URI>,
+    <Set::Array> and <RDF::Trine::Node>.
+
+    Failing that, if the variable being converted is a hashref (including
+    blessed hashrefs) with a key called '@about' then that is used as a
+    CURIE or URI to generate a RDF::Trine::Node::Resource.
+
+    Otherwise, all references are taken to be anonymous blank nodes, and
+    scalars taken to be plain literals.
+
+  How the RDF type of a Perl variable is decided?
+    A module can of course override rdf_type via normal Perl inheritance,
+    but the UNIVERSAL version works like this:
+
+    If the variable being converted is a hashref (including blessed
+    hashrefs) with a key called '@type' then that is used as a CURIE or URI
+    to generate a RDF::Trine::Node::Resource.
+
+    Otherwise, if the variable is a blessed object, the type is the URI
+    formed by concatenating "http://purl.org/NET/cpan-uri/class/" with the
+    package name the variable is blessed into.
+
+    Otherwise, it has no type.
+
+  How is RDF data for a variable generated?
+    A module can of course override to_rdf via normal Perl inheritance, but
+    the UNIVERSAL version works like this:
+
+    Firstly, @RDF::Everywhere::object_converters is checked for a converter
+    function that can handle it. This list takes the following format:
+
+      (
+        [ 'Foo::Bar' => sub { my $obj = shift; ... ; return $model; } ],
+        [ 'Foo::Baz' => sub { my $obj = shift; ... ; return $model; } ],
+      );
+
+    If an entry in the list applies to the variable being converted, it is
+    use to perform the conversion, and the result is returned.
+
+    A converter is pre-defined for <Set::Array> (treating it as an
+    rdf:List).
+
+    If nothing has been returned so far, a new model is created. A triple is
+    added to it stating the rdf:type of the object (if any).
+
+    If the variable being converted is a hashref (including blessed
+    hashrefs) it is iterated through as a set of predicate (CURIE) => object
+    pairs. If the object is an arrayref this is treated as multiple triples,
+    and not as an rdf:List (use Set::Array for rdf:Lists).
+
+  How does CURIE mapping work?
+    Tokens without a colon are looked up in %RDF::Everywhere::terms. If not
+    found, for predicates a default prefix
+    'http://wiki.ontologi.es/perl-object#' is used; for non-predicates, a
+    relative URI.
+
+    Tokens with a colon are treated as a CURIE with mappings from
+    %RDF::Everywhere::mappings. If no mapping is found, it is assumed to be
+    a URI.
+
+SEE ALSO
+    RDF::Trine, UNIVERSAL.
+
+    <http://perlrdf.org/>.
+
+BUGS
+    Please report any bugs to <http://rt.cpan.org/>.
+
+AUTHOR
+    Toby Inkster <tobyink@cpan.org>.
+
+COPYRIGHT
+    Copyright 2010 Toby Inkster
+
+    This library is free software; you can redistribute it and/or modify it
+    under the same terms as Perl itself.
+
+#!/usr/bin/perl
+
+use lib "lib";
+use RDF::Everywhere qw[rdf_node to_rdf];
+use DateTime;
+use Data::Dumper;
+use RDF::TrineShortcuts;
+use Set::Array;
+use URI;
+
+my $resp = LWP::UserAgent->new->get("http://www.example.com/");
+
+my @test;
+push @test, {};
+push @test, bless { '@about' => 'ex:Foo' , bar=>'baz', quux=>[1,2] }, 'Test::Bumbo';
+push @test, bless { xyzzy => 'x' }, 'Test::Bumbo';
+push @test, DateTime->now;
+push @test, "Hello world";
+push @test, $resp->headers;
+
+$test[1]->{who} = $test[2];
+$test[1]->{when} = $test[3];
+$test[2]->{why} = $test[1];
+
+print to_rdf({
+	'@about' => 'http://tobyinkster.co.uk/#i',
+	name => 'Toby Inkster',
+	homepage => URI->new('http://tobyinkster.co.uk/'),
+	made => \@test,
+	array => Set::Array->new(1,2,3),
+	empty => Set::Array->new(),
+	single => Set::Array->new('garb'),
+}, as=>'turtle', recurse=>1);
+
+package Test::Bumbo;
+
+1;
+#!/usr/bin/perl
+
+use lib "lib";
+use RDF::Everywhere qw[to_rdf];
+use LWP::UserAgent;
+
+print LWP::UserAgent->new->get("http://www.example.com/")->headers->to_rdf(as=>'RDFXML');
+
+print to_rdf { foo=>1, bar=>2, baz=>[3,4,5], quux=>{xyzzy=>99} }, (as => 'Turtle');

lib/RDF/Everywhere.pm

 		);
 }
 
-sub rdf_node
+sub rdf_node (*;%)
 {
 	my ($self, %options) = @_;
 	
 	return RDF::Trine::Node::Literal->new("$self");
 }
 
-sub rdf_type
+sub rdf_type (*;%)
 {
 	my ($self, %options) = @_;
 	
 	return;
 }
 
-sub to_rdf
+sub to_rdf (*;%)
 {
 	my ($self, %options) = @_;
 	
 	my ($self, %options) = @_;
 	my $model = $options{model} ||= RDF::Trine::Model->new;
 	$options{visited} ||= {};
+	
+	$options{recurse} = 1
+		unless defined $options{recurse};
 		
 	my $node = rdf_node($self);
 	if ($node->is_literal)
   
   # They can also be used as functions, which is useful when calling
   # on unblessed variables.
-  print to_rdf({
+  print to_rdf {
     name      => 'Toby Inkster',
     cpanid    => 'TOBYINK',
     page      => URI->new('http://search.cpan.org/~tobyink/'),
         { name => 'RDF-Everywhere',     version => '0.001' },
         { name => 'RDF-TrineShortcuts', version => '0.102' },
       ],
-    }, as => 'RDFXML', recurse=>1);
+    }, as => 'RDFXML';
 
 =head1 DESCRIPTION
 
 =over
 
 =item B<as>: instead of returning a Model, return a string formatted using
-this serialisation. e.g. C<< as=>'Turtle' >>.
+this serialisation. e.g. C<< as=>'Turtle' >>. Accepts the same serialisations
+as C<< RDF::Trine::Serializer->new >> (e.g. 'Turtle', 'RDFXML', 'NTriples', 'RDFJSON').
 
 =item B<recurse>: also include data about "child" objects. This is smart
-enough to avoid infinite loops (or should be).
+enough to avoid infinite loops (or should be). Defaults to true, but
+C<< recurse=>0 >> can be passed to force the method to avoid recursion.
 
-=item B<model>: an existing model to add data to.
+=item B<model>: an existing model to add data to. This is expected to be a
+blessed object which has an C<add_statement> method accepting an
+RDF::Trine::Statement. An RDF::Trine::Model would be what you'd normally
+provide.
 
 =back
 
 
 =head1 SEE ALSO
 
-L<RDF::Trine>.
+L<RDF::Trine>, L<UNIVERSAL>.
 
 L<http://perlrdf.org/>.
 
-use Test::More tests => 1;
-BEGIN { use_ok('Example::Example') };
+use Test::More tests => 5;
+BEGIN { use_ok('RDF::Everywhere') };
 
+my $test = bless {}, QuuxFooBarBaz::Example::RE;
+
+ok($test->can('rdf_node'), "Objects can rdf_node.");
+ok($test->can('rdf_type'), "Objects can rdf_type.");
+ok($test->can('to_rdf'), "Objects can to_rdf.");
+ok($test->rdf_node->is_blank, "Our example object is a blank node.");
+
+package QuuxFooBarBaz::Example::RE;
+1;

test.pl

-#!/usr/bin/perl
-
-use lib "lib";
-use RDF::Everywhere qw[rdf_node to_rdf];
-use DateTime;
-use Data::Dumper;
-use RDF::TrineShortcuts;
-use Set::Array;
-use URI;
-
-my $resp = LWP::UserAgent->new->get("http://www.example.com/");
-
-my @test;
-push @test, {};
-push @test, bless { '@about' => 'ex:Foo' , bar=>'baz', quux=>[1,2] }, 'Test::Bumbo';
-push @test, bless { xyzzy => 'x' }, 'Test::Bumbo';
-push @test, DateTime->now;
-push @test, "Hello world";
-push @test, $resp->headers;
-
-$test[1]->{who} = $test[2];
-$test[1]->{when} = $test[3];
-$test[2]->{why} = $test[1];
-
-print to_rdf({
-	'@about' => 'http://tobyinkster.co.uk/#i',
-	name => 'Toby Inkster',
-	homepage => URI->new('http://tobyinkster.co.uk/'),
-	made => \@test,
-	array => Set::Array->new(1,2,3),
-	empty => Set::Array->new(),
-	single => Set::Array->new('garb'),
-}, as=>'turtle', recurse=>1);
-
-package Test::Bumbo;
-
-1;

test2.pl

-#!/usr/bin/perl
-
-use lib "lib";
-use RDF::Everywhere;
-use LWP::UserAgent;
-
-print LWP::UserAgent->new->get("http://www.example.com/")->headers->to_rdf(as=>'RDFXML');