Commits

Toby Inkster committed 748be52

Initial API work.

Comments (0)

Files changed (34)

+#############################################################
+
+@prefix :        <http://usefulinc.com/ns/doap#> .
+@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 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:subject       my:project ;
+	dc:creator       toby:i .
+
+#############################################################
+
+my:v_0-01
+
+	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> ;
+	rdfs:comment    "Original version"@en .
+
+#############################################################
+
+my:project
+
+	a               :Project ;
+	:name           "Example-Example" ;
+	:shortdesc      "Example Project"@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/> ] ;
+	:maintainer     toby:i ;
+	:developer      toby:i ;
+	:documenter     toby:i ;
+	:tester         toby:i ;
+	:created        "2000-01-01"^^xsd:date ;
+	:license        <http://dev.perl.org/licenses/> ;
+	:release        my:v_0-01 .
+
+#############################################################
+
+toby:i
+
+	a               foaf:Person ;
+	foaf:name       "Toby Inkster" ;
+	foaf:homepage   <http://tobyinkster.co.uk/> ;
+	foaf:page       <http://search.cpan.org/~tobyink/> ;
+	foaf:mbox       <mailto:tobyink@cpan.org> ;
+	<http://www.w3.org/2002/07/owl#sameAs> <http://purl.org/NET/cpan-uri/person/tobyink> .
+
+#############################################################
+Changes
+Changes.ttl
+Changes.xml
+Makefile.PL
+MANIFEST
+MANIFEST.SKIP
+README
+META.yml
+SIGNATURE
+
+t/00sig.t
+t/01basic.t
+^Makefile$
+^blib/
+^pm_to_blib
+^blibdirs
+\.svn
+^example.*\.pl$
+^[^/]+\.(tar\.gz|tar\.bz2|tgz|tbz2|tbz|zip|tar)$
+^MYMETA.yml
+use strict;
+use warnings;
+
+use inc::Module::Install;
+
+my $dist = 'Example-Example';
+my $fn   = "lib/$dist.pm"; $fn =~ s#-#/#g;
+
+name                $dist;
+perl_version_from   $fn;
+version_from        $fn;
+abstract_from       $fn;
+readme_from         $fn;
+author              'Toby Inkster <tobyink@cpan.org>';
+license             'perl';
+
+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");
+	
+write_doap_changes;
+write_doap_changes_xml;
+
+include 'Test::Signature';
+auto_install;
+WriteAll(
+	'meta' => 1,
+	'sign' => 1,
+	);
+use lib "lib";
+
+use Data::Dumper;
+use RDF::RDFa::API;
+
+my $C     = RDF::RDFa::API::DataContext->new;
+my $plain = RDF::RDFa::API::PlainLiteral->construct("Hello World", "en");
+my $typed = RDF::RDFa::API::TypedLiteral->construct("Hello World", "xsd:string", dataContext => $C);
+my $iri   = RDF::RDFa::API::IRI->construct("http://example.com/doc");
+my $bnode = RDF::RDFa::API::BlankNode->construct("_:foobar");
+my $st    = RDF::RDFa::API::RDFTriple->construct($bnode, $iri, $plain);
+
+print Dumper(
+{
+	plain  => $plain,
+	typed  => $typed,
+	iri    => $iri,
+	bnode  => $bnode,
+	st     => $st,
+	C      => $C,
+}
+);
+
+print Dumper(\%RDF::RDFa::API::DataContext::DefaultConverters);
+
+print "
+{
+	plain  => $plain,
+	typed  => $typed,
+	iri    => $iri,
+	bnode  => $bnode,
+	st     => $st,
+}
+";

lib/RDF/RDFa/API.pm

+package RDF::RDFa::API;
+
+use RDF::Trine '0.130';
+use RDF::RDFa::Parser '1.093';
+
+use RDF::RDFa::API::RDFNode;
+use RDF::RDFa::API::RDFResource;
+use RDF::RDFa::API::IRI;
+use RDF::RDFa::API::BlankNode;
+use RDF::RDFa::API::PlainLiteral;
+use RDF::RDFa::API::TypedLiteral;
+
+use RDF::RDFa::API::RDFTriple;
+
+use RDF::RDFa::API::DataContext;
+use RDF::RDFa::API::TypedLiteralConverter;
+
+use RDF::RDFa::API::DataStore;
+use RDF::RDFa::API::DataStore::Memory;
+
+1;
+
+__END__
+
+=head1 NAME
+
+RDF::RDFa::API - Implementation of the W3C RDFa API.
+
+=head1 DESCRIPTION
+
+This is an implementation of the 23 September 2010 working draft
+L<http://www.w3.org/TR/2010/WD-rdfa-api-20100923/>.
+
+=head1 SEE ALSO
+
+L<http://www.w3.org/TR/rdfa-api/>.
+
+L<http://www.perlrdf.org/>.
+
+=head1 BUGS
+
+Please report any bugs to L<http://rt.cpan.org/>.
+
+=head1 AUTHOR
+
+Toby Inkster E<lt>tobyink@cpan.orgE<gt>.
+
+=head1 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.

lib/RDF/RDFa/API/BlankNode.pm

+package RDF::RDFa::API::BlankNode;
+
+use 5.010;
+use Moose;
+use namespace::clean -except => 'meta';
+use common::sense;
+
+extends 'RDF::RDFa::API::RDFResource';
+
+has trineNode => (is => 'ro', required => 1, isa => 'RDF::Trine::Node::Blank');
+
+sub construct
+{
+	my ($class, $ident, %args) = @_;
+	
+	$ident =~ s/^_://g;
+	
+	return $class->new(
+		%args,
+		trineNode => RDF::Trine::Node::Blank->new("$ident"),
+		);
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+RDF::RDFa::API::BlankNode- An RDF resource that does not have a corresponding IRI reference, as defined in [RDF-CONCEPTS].
+
+=head1 WEBIDL
+
+	[NoInterfaceObject]
+	interface BlankNode : RDFResource {
+		 readonly attribute stringifier DOMString value;
+	};
+
+=head1 SEE ALSO
+
+L<RDF::RDFa::API>.
+
+RDF-CONCEPTS: L<http://www.w3.org/TR/2004/REC-rdf-concepts-20040210>.
+
+=head1 BUGS
+
+Please report any bugs to L<http://rt.cpan.org/>.
+
+=head1 AUTHOR
+
+Toby Inkster E<lt>tobyink@cpan.orgE<gt>.
+
+=head1 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.

lib/RDF/RDFa/API/DOMImplementation.pm

Empty file added.

lib/RDF/RDFa/API/DataContext.pm

+package RDF::RDFa::API::DataContext;
+
+use 5.010;
+use Moose;
+use namespace::clean -except => 'meta';
+use common::sense;
+
+our %DefaultMappings = (
+	rdf => 'http://www.w3.org/1999/02/22-rdf-syntax-ns#',
+	xsd => 'http://www.w3.org/2001/XMLSchema#',
+	);
+
+our %DefaultConverters;
+#~ 'http://www.w3.org/2001/XMLSchema#string'    => 'RDF::RDFa::API::TypedLiteralConverter::String',
+#~ 'http://www.w3.org/2001/XMLSchema#boolean'   => 'RDF::RDFa::API::TypedLiteralConverter::Boolean',
+#~ 'http://www.w3.org/2001/XMLSchema#float'     => 'RDF::RDFa::API::TypedLiteralConverter::Numeric',
+#~ 'http://www.w3.org/2001/XMLSchema#double'    => 'RDF::RDFa::API::TypedLiteralConverter::Numeric',
+#~ 'http://www.w3.org/2001/XMLSchema#integer'   => 'RDF::RDFa::API::TypedLiteralConverter::Numeric',
+#~ 'http://www.w3.org/2001/XMLSchema#long'      => 'RDF::RDFa::API::TypedLiteralConverter::Numeric',
+#~ 'http://www.w3.org/2001/XMLSchema#date'      => 'RDF::RDFa::API::TypedLiteralConverter::Date',
+#~ 'http://www.w3.org/2001/XMLSchema#time'      => 'RDF::RDFa::API::TypedLiteralConverter::Time',
+#~ 'http://www.w3.org/2001/XMLSchema#dateTime'  => 'RDF::RDFa::API::TypedLiteralConverter::DateTime',
+
+has mappings     => (is => 'rw', isa => 'HashRef', default => sub { my %x = %DefaultMappings; \%x;});
+has converters   => (is => 'rw', isa => 'HashRef', default => sub { my %x = %DefaultConverters; \%x; });
+
+sub setMapping
+{
+	my ($self, $prefix, $iri) = @_;
+	
+	my $old = delete $self->mappings->{lc $prefix};
+	$self->mappings->{lc $prefix} = $iri if $iri;
+	
+	return $old;
+}
+
+sub resolveCurieToString
+{
+	my ($self, $curie) = @_;
+	
+	my ($pfx, $sfx) = split /:/, $curie, 2;
+	
+	if (defined $self->mappings->{lc $pfx})
+	{
+		return $self->mappings->{lc $pfx} . $sfx;
+	}
+
+	return $curie;
+}
+
+sub resolveCurie
+{
+	my ($self, $curie) = @_;
+	
+	return RDF::RDFa::API::IRI->construct(
+		$self->resolveCurieToString($curie),
+		dataContext => $self,
+		);
+}
+
+sub registerTypeConversion
+{
+	my ($self, $type_iri, $converter) = @_;
+	$type_iri = $self->resolveCurie($type_iri);
+	
+	my $old = delete $self->converters->{$type_iri};
+	if ($converter)
+	{
+		$self->converters->{$type_iri} = $converter;
+	}
+	
+	return $old;
+}
+
+sub convertType
+{
+	my ($self, $value, $inputType, $modifier) = @_;
+	$inputType = $self->resolveCurie($inputType);
+	
+	if (blessed($self->converters->{$inputType})
+	and $self->converters->{$inputType}->can('does')
+	and $self->converters->{$inputType}->does('RDF::RDFa::API::TypedLiteralConverter'))
+	{
+		my $conv = $self->converters->{$inputType};
+		return $conv->convert($value, $inputType, $modifier);
+	}
+	elsif (ref $self->converters->{$inputType} eq 'CODE')
+	{
+		my $coderef = $self->converters->{$inputType};
+		return $coderef->($value, $inputType, $modifier);
+	}
+	elsif ($self->converters->{$inputType}
+	and $self->converters->{$inputType}->can('new'))
+	{
+		my $conv = $self->converters->{$inputType}->new;
+		return $conv->convert($value, $inputType, $modifier);
+	}
+	elsif (defined $self->converters->{$inputType})
+	{
+		die "Converter for input type $inputType set to something odd.\n";
+	}
+	else
+	{
+		return $value;
+	}
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+RDF::RDFa::API::DataContext - Greatly reduces the amount of code a developer must write to express IRIs and convert data.
+
+=head1 WEBIDL
+
+	interface DataContext {
+		 void setMapping (in DOMString prefix, in DOMString iri);
+		 void registerTypeConversion (in DOMString iri, in TypedLiteralConverter converter);
+		 IRI  resolveCurie (in DOMString curie);
+		 any  convertType (in DOMString value, in optional DOMString inputType, in optional DOMString modifier);
+	};
+
+=head1 PERL SPECIFICS
+
+=over
+
+=item * C<setMapping> and C<registerTypeConverter> return value
+
+Rather than returning void (there's not really such a thing in Perl),
+this method returns the previous value of the CURIE mapping or type
+mapping (if any).
+
+=item * C<registerTypeConverter> I<converter> parameter
+
+May be an object that isa RDF::RDFa::API::TypedLiteralConverter, or a string
+representing a subclass of that, or a coderef.
+
+=item * C<convertType> I<modifier> parameter
+
+Rather than just allowing a string, any scalar is allowed.
+
+=back
+
+=head1 ADDITIONS
+
+In addition to the standard RDFa API interface, this module supports the
+following methods:
+
+=over
+
+=item * C<mappings>
+
+Gets/sets the context's CURIE mappings as a hashref. Keys are the CURIE
+prefix; values, the IRI prefix. Only lower-cased keys are honoured.
+
+Be careful - it's usually better to use C<setMapping>.
+
+=item * C<converters>
+
+Gets/sets the context's type converters as a hashref. Keys are datatype
+URIs; values, suitable for C<registerTypedConverter>.
+
+Be careful - it's usually better to use C<registerTypedConverter>.
+
+=item * C<resolveCurieToString>
+
+Equivalent to C<< $context->resolveCurie($curie)->toString >> but faster
+as it doesn't create an intervening C<RDF::RDFa::API::IRI> object.
+
+=back
+
+=head1 SEE ALSO
+
+L<RDF::RDFa::API>.
+
+=head1 BUGS
+
+Please report any bugs to L<http://rt.cpan.org/>.
+
+=head1 AUTHOR
+
+Toby Inkster E<lt>tobyink@cpan.orgE<gt>.
+
+=head1 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.

lib/RDF/RDFa/API/DataParser.pm

+package RDF::RDFa::API::DataParser;
+
+use 5.010;
+use Moose::Role;
+use namespace::clean -except => 'meta';
+use common::sense;
+
+requires 'parse';
+requires 'iterate';
+
+has store => (is => 'ro', isa => 'RDF::RDFa::API::DataStore');
+
+1;

lib/RDF/RDFa/API/DataParser/RDFa_11.pm

+package RDF::RDFa::API::DataParser::RDFa_11;
+
+use 5.010;
+use Moose;
+use namespace::clean -except => 'meta';
+use common::sense;
+
+with 'RDF::RDFa::API::DataParser';
+
+sub parse
+{
+	my ($self, $domElement, $base) = @_;
+	
+	my $parser = RDF::RDFa::Parser->new(
+		$domElement->ownerDocument,
+		$domElement->ownerDocument->documentElement->baseURI,
+		RDF::RDFa::Parser::Config->new('xhtml', '1.1'),
+		);
+	$parser->set_callbacks({
+		ontriple => sub {
+			my ($parser_again, $elements, $triple) = @_;
+			next unless 1; # next unless $elements->{current} is a descendent or equal to $domElement
+			
+			my $api_triple = RDF::RDFa::API::RDFTriple->fromTrine($triple, $elements);
+			$api_triple->dataContext($store->dataContext);
+			$self->store->add($api_triple);
+		}
+	});
+	$parser->consume;
+}
+
+sub iterate
+{
+	die "Not implemented yet.\n";
+}
+
+1;

lib/RDF/RDFa/API/DataQuery.pm

Empty file added.

lib/RDF/RDFa/API/DataStore.pm

+package RDF::RDFa::API::DataStore;
+
+use 5.010;
+use Moose;
+use namespace::clean -except => ['meta'];
+use common::sense;
+
+has triples          => (is => 'ro', isa => 'Arrayref', default => sub {[]});
+has model            => (is => 'ro', isa => 'RDF::Trine::Model', default => sub { RDF::Trine::Model->temporary_model; });
+has dataContext      => (is => 'rw', isa => 'RDF::RDFa::API::DataContext');
+
+sub size
+{
+	my ($self) = @_;
+	return scalar @{ $self->triples };
+}
+
+sub get
+{
+	my ($self, $index) = @_;
+	return $self->triples->[$index];
+}
+
+sub contains
+{
+	my ($self, $triple) = @_;	
+	return grep { $triple eq $_ } @{ $self->triples };
+}
+
+sub add
+{
+	my ($self, $triple) = @_;
+	
+	my @already = $self->contains($triple);
+	return @already
+		if @already;
+
+	push @{ $self->triples }, $triple;
+	$self->model->add_statement( $triple->trineStatement );
+	return 1;
+}
+
+sub createIRI
+{
+	my ($self, $iri, $node) = @_;
+	return RDF::RDFa::API::IRI->construct($iri, dataContext => $self->dataContext);
+}
+
+sub createBlankNode
+{
+	my ($self, $name) = @_;
+	return RDF::RDFa::API::BlankNode->construct($name, dataContext => $self->dataContext);
+}
+
+sub createPlainLiteral
+{
+	my ($self, $value, $lang) = @_;
+	return RDF::RDFa::API::PlainLiteral->construct($value, $lang, dataContext => $self->dataContext);
+}
+
+sub createTypedLiteral
+{
+	my ($self, $value, $dt) = @_;
+	return RDF::RDFa::API::TypedLiteral->construct($value, $dt, dataContext => $self->dataContext);
+}
+
+sub createTriple
+{
+	my ($self, $s, $p, $o) = @_;
+	return RDF::RDFa::API::RDFTriple->construct($s, $p, $o, dataContext => $self->dataContext);
+}
+
+sub clear
+{
+	my ($self) = @_;
+	my $rv = $self->size;
+	$self->{triples} = [];
+	$self->model->remove_statements(undef, undef, undef);
+	return $rv;
+}
+
+sub merge
+{
+	die "Not implemented yet.\n";
+}
+
+sub forEach
+{
+	die "Not implemented yet.\n";
+}
+
+sub filter
+{
+	die "Not implemented yet.\n";
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+RDF::RDFa::API::DataStore - The DataStore is a set of RDFTriple objects.
+
+=head1 WEBIDL
+
+	[NoInterfaceObject]
+	interface DataStore {
+		 readonly attribute unsigned long size;
+		 getter RDFTriple get (in unsigned long index);
+		 boolean          add (in RDFTriple triple);
+		 IRI              createIRI (in DOMString iri, in optional Node node);
+		 PlainLiteral     createPlainLiteral (in DOMString value, in optional DOMString? language);
+		 TypedLiteral     createTypedLiteral (in DOMString value, in DOMString type);
+		 BlankNode        createBlankNode (in optional DOMString name);
+		 RDFTriple        createTriple (in RDFResource subject, in IRI property, in RDFNode object);
+		 [Null=Null]
+		 DataStore        filter (in optional Object? pattern, in optional Element? element, in optional RDFTripleFilter filter);
+		 void             clear ();
+		 void             forEach (in DataStoreIterator iterator);
+		 boolean          merge (in DataStore store);
+	};
+
+=head1 PERL SPECIFICS
+
+...
+
+* clear: return value
+* add: return value
+
+=head1 ADDITIONS
+
+...
+
+* triples
+* contains
+
+=head1 SEE ALSO
+
+L<RDF::RDFa::API>.
+
+=head1 BUGS
+
+Please report any bugs to L<http://rt.cpan.org/>.
+
+=head1 AUTHOR
+
+Toby Inkster E<lt>tobyink@cpan.orgE<gt>.
+
+=head1 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.

lib/RDF/RDFa/API/DataStore/Memory.pm

+package RDF::RDFa::API::DataStore::Memory;
+
+use 5.010;
+use Moose;
+use namespace::clean -except => ['meta'];
+use common::sense;
+
+with 'RDF::RDFa::API::DataStore';
+
+
+1;

lib/RDF/RDFa/API/DataStoreIterator.pm

Empty file added.

lib/RDF/RDFa/API/DocumentData.pm

Empty file added.

lib/RDF/RDFa/API/IRI.pm

+package RDF::RDFa::API::IRI;
+
+use 5.010;
+use Moose;
+use namespace::clean -except => 'meta';
+use common::sense;
+
+extends 'RDF::RDFa::API::RDFResource';
+
+has trineNode => (is => 'ro', required => 1, isa => 'RDF::Trine::Node::Resource');
+
+sub construct
+{
+	my ($class, $iri_string, %args) = @_;
+
+	return $class->new(
+		%args,
+		trineNode => RDF::Trine::Node::Resource->new("$iri_string"),
+		);
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+RDF::RDFa::API::IRI - An IRI Reference in the RDFa API points to a resource and is further defined in [IRI].
+
+=head1 WEBIDL
+
+	[NoInterfaceObject]
+	interface IRI : RDFResource {
+	};
+
+=head1 SEE ALSO
+
+L<RDF::RDFa::API>.
+
+IRI: L<http://www.ietf.org/rfc/rfc3987.txt>.
+
+=head1 BUGS
+
+Please report any bugs to L<http://rt.cpan.org/>.
+
+=head1 AUTHOR
+
+Toby Inkster E<lt>tobyink@cpan.orgE<gt>.
+
+=head1 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.

lib/RDF/RDFa/API/PlainLiteral.pm

+package RDF::RDFa::API::PlainLiteral;
+
+use 5.010;
+use Moose;
+use namespace::clean -except => 'meta';
+use common::sense;
+
+extends 'RDF::RDFa::API::RDFNode';
+
+has trineNode => (is => 'ro', required => 1, isa => 'RDF::Trine::Node::Literal');
+
+sub construct
+{
+	my ($class, $value, $lang, %args) = @_;
+	
+	return $class->new(
+		%args,
+		trineNode => RDF::Trine::Node::Literal->new("$value", $lang),
+		);
+}
+
+sub language
+{
+	my ($self) = @_;
+	return $self->trineNode->literal_value_language;
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+RDF::RDFa::API::PlainLiteral - PlainLiterals have a string value and may specify a language.
+
+=head1 WEBIDL
+
+	[NoInterfaceObject]
+	interface PlainLiteral : RDFNode {
+	    readonly attribute stringifier DOMString value;
+	    readonly attribute DOMString             language;
+	};
+
+=head1 SEE ALSO
+
+L<RDF::RDFa::API>.
+
+=head1 BUGS
+
+Please report any bugs to L<http://rt.cpan.org/>.
+
+=head1 AUTHOR
+
+Toby Inkster E<lt>tobyink@cpan.orgE<gt>.
+
+=head1 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.

lib/RDF/RDFa/API/PropertyGroup.pm

Empty file added.

lib/RDF/RDFa/API/RDFNode.pm

+package RDF::RDFa::API::RDFNode;
+
+use 5.010;
+use Moose;
+use namespace::clean -except => 'meta';
+use common::sense;
+
+has trineNode   => (is => 'ro', required => 1, isa => 'RDF::Trine::Node');
+has dataContext => (is => 'rw', isa => 'RDF::RDFa::API::DataContext');
+
+use overload '""'  => \&toString;
+use overload 'eq'  => \&isEqual;
+
+sub value
+{
+	my ($self) = @_;
+	
+	return undef
+		unless blessed($self->trineNode);
+	
+	return $self->trineNode->uri
+		if $self->trineNode->is_resource;
+	
+	return $self->trineNode->literal_value
+		if $self->trineNode->is_literal;
+	
+	return $self->trineNode->blank_identifier
+		if $self->trineNode->is_blank;
+	
+	return undef;
+}
+
+sub toString
+{
+	my ($self) = @_;
+	
+	return undef
+		unless blessed($self->trineNode);
+	
+	return $self->trineNode->uri
+		if $self->trineNode->is_resource;
+	
+	return $self->trineNode->literal_value
+		if $self->trineNode->is_literal;
+	
+	return '_:' . $self->trineNode->blank_identifier
+		if $self->trineNode->is_blank;
+	
+	return undef;
+}
+
+sub isEqual
+{
+	my ($this, $that) = @_;
+	
+	if (blessed($that) && $that->isa('RDF::RDFa::API::RDFNode'))
+	{
+		return $this->trineNode->as_ntriples eq $that->trineNode->as_ntriples;
+	}
+	return $this->trineNode eq "$that";
+}
+
+sub fromTrine
+{
+	my ($class, $node) = @_;
+	
+	if ($node->is_resource)
+	{
+		return RDF::RDFa::API::IRI->construct($node->uri);
+	}
+	elsif ($node->is_blank)
+	{
+		return RDF::RDFa::API::IRI->construct($node->blank_identifier);
+	}
+	elsif ($node->is_literal && $node->has_datatype)
+	{
+		return RDF::RDFa::API::TypedLiteral->construct($node->literal_value, $node->literal_datatype);
+	}
+	elsif ($node->is_literal)
+	{
+		return RDF::RDFa::API::PlainLiteral->construct($node->literal_value, $node->literal_value_language);
+	}
+	
+	die "Could not build RDF::RDFa::API::RDFNode.\n";
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+RDF::RDFa::API::RDFNode - An RDFNode is anything that can be an object of an RDFTriple.
+
+=head1 WEBIDL
+
+	[NoInterfaceObject]
+	interface RDFNode {
+		 readonly attribute stringifier DOMString value;
+	};
+
+=head1 PERL SPECIFICS
+
+Stringification ('""') and equality ('eq') are overloaded, so stuff like
+C<< $a eq $b >> should "just work".
+
+=head1 ADDITIONS
+
+In addition to the standard RDFa API interface, this module supports the
+following methods:
+
+=over
+
+=item * C<trineNode>
+
+Returns the node as an RDF::Trine::Node.
+
+=item * C<isEqual>
+
+Returns true iff the nodes are equivalent (same value, type, language, etc).
+
+=back
+
+=head1 SEE ALSO
+
+L<RDF::RDFa::API>.
+
+=head1 BUGS
+
+Please report any bugs to L<http://rt.cpan.org/>.
+
+=head1 AUTHOR
+
+Toby Inkster E<lt>tobyink@cpan.orgE<gt>.
+
+=head1 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.

lib/RDF/RDFa/API/RDFResource.pm

+package RDF::RDFa::API::RDFResource;
+
+use 5.010;
+use Moose;
+use namespace::clean -except => 'meta';
+use common::sense;
+
+extends 'RDF::RDFa::API::RDFNode';
+
+1;
+
+__END__
+
+=head1 NAME
+
+RDF::RDFa::API::RDFResource - An RDFResource is anything that can be an subject of an RDFTriple.
+
+=head1 WEBIDL
+
+	[NoInterfaceObject]
+	interface RDFResource : RDFNode {
+		 readonly attribute stringifier DOMString value;
+	};
+
+=head1 SEE ALSO
+
+L<RDF::RDFa::API>.
+
+=head1 BUGS
+
+Please report any bugs to L<http://rt.cpan.org/>.
+
+=head1 AUTHOR
+
+Toby Inkster E<lt>tobyink@cpan.orgE<gt>.
+
+=head1 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.

lib/RDF/RDFa/API/RDFTriple.pm

+package RDF::RDFa::API::RDFTriple;
+
+use 5.010;
+use Moose;
+use namespace::clean -except => 'meta';
+use common::sense;
+
+use overload '""'  => \&toString;
+use overload '@{}' => \&toArray;
+use overload 'eq'  => \&isEqual;
+use constant size => 3;
+
+has subject          => (is => 'ro', required => 1, isa => 'RDF::RDFa::API::RDFResource');
+has property         => (is => 'ro', required => 1, isa => 'RDF::RDFa::API::IRI');
+has object           => (is => 'ro', required => 1, isa => 'RDF::RDFa::API::RDFNode');
+has subjectOrigin    => (is => 'ro');
+has propertyOrigin   => (is => 'ro');
+has objectOrigin     => (is => 'ro');
+has tripleOrigin     => (is => 'ro');
+has trineStatement   => (is => 'ro', isa => 'RDF::Trine::Statement');
+has dataContext      => (is => 'rw', isa => 'RDF::RDFa::API::DataContext');
+
+sub construct
+{
+	my ($class, $s, $p, $o, %args) = @_;
+	
+	return $class->new(
+		%args,
+		subject    => $s,
+		property   => $p,
+		object     => $o,
+		);
+}
+
+sub fromTrine
+{
+	my ($class, $triple, $prov) = @_;
+	$prov ||= {};
+		
+	my $self = {
+		subject     => RDF::RDFa::API::RDFNode->fromTrine($triple->subject),
+		property    => RDF::RDFa::API::RDFNode->fromTrine($triple->predicate),
+		object      => RDF::RDFa::API::RDFNode->fromTrine($triple->object),
+		};
+	
+	$self->{subjectOrigin}  = $prov->{subject}   if $prov->{subject};
+	$self->{propertyOrigin} = $prov->{predicate} if $prov->{predicate};
+	$self->{objectOrigin}   = $prov->{object}    if $prov->{object};
+	$self->{tripleOrigin}   = $prov->{current}   if $prov->{current};
+	
+	bless $self, $class;
+}
+
+sub get
+{
+	my ($self, $index) = @_;
+	
+	$index == 0 and return $self->subject;
+	$index == 1 and return $self->property;
+	$index == 2 and return $self->object;
+	
+	die "Index must be 0, 1 or 2.\n";
+}
+
+sub toString
+{
+	my ($self) = @_;
+	
+	return sprintf("%s %s %s .\n",
+		map { $_->trineNode->as_ntriples } @$self
+		);
+}
+
+sub toArray
+{
+	my ($self) = @_;
+	
+	my @array = map { $self->get($_) } 0 .. ($self->size - 1);
+	
+	return wantarray ? @array : \@array;
+}
+
+sub isEqual
+{
+	my ($this, $that) = @_;
+	return $this->object eq $that->object
+		&& $this->property eq $that->property
+		&& $this->subject eq $that->subject;
+}
+
+before trineStatement => sub
+{
+	my ($self) = @_;
+
+	unless (defined $self->{trine_statement})
+	{
+		$self->{trine_statement} = RDF::Trine::Statement->new(map { $_->trine_node } @$self);
+	}
+};
+
+1;
+
+__END__
+
+=head1 NAME
+
+RDF::RDFa::API::RDFTriple - Represents an RDF triple as specified in [RDF-CONCEPTS].
+
+=head1 WEBIDL
+
+	[NoInterfaceObject, Null=Null]
+	interface RDFTriple {
+		 const unsigned long size = 3;
+		 readonly attribute RDFResource subject;
+		 readonly attribute IRI         property;
+		 readonly attribute RDFNode     object;
+		 getter RDFNode        get (in unsigned long index);
+		 stringifier DOMString toString ();
+	};
+
+=head1 PERL SPECIFICS
+
+While internally implemented as a blessed hashref, this module
+overloads '@{}' allowing it to be used as an S-P-O arrayref. For
+example:
+
+  my ($subject, $property, $object) = @$triple;
+
+=head1 ADDITIONS
+
+=over
+
+=item * C<toArray>
+
+Returns the triple as an S-P-O arrayref, or if called in list context,
+an S-P-O list.
+
+=item * C<subjectOrigin>, C<propertyOrigin>, C<objectOrigin>
+
+If this triple was parsed from RDFa, these reference the
+XML::LibXML::Elements where the subject, property and object of
+the triple were found in the RDFa source.
+
+For non-RDFa parsers, these may be something slightly different
+(e.g. an N-Triples parser might provide line/column numbers).
+
+=item * C<tripleOrigin>
+
+This will usually be the same as C<subjectOrigin> or C<objectOrigin>.
+The element that was "current" in the RDFa parsing algorithm when
+the triple was generated.
+
+=item * <isEqual>
+
+Returns true iff both triples are equal from an RDF perspective.
+
+=back
+
+=head1 SEE ALSO
+
+L<RDF::RDFa::API>.
+
+RDF-CONCEPTS: L<http://www.w3.org/TR/2004/REC-rdf-concepts-20040210>.
+
+=head1 BUGS
+
+Please report any bugs to L<http://rt.cpan.org/>.
+
+=head1 AUTHOR
+
+Toby Inkster E<lt>tobyink@cpan.orgE<gt>.
+
+=head1 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.

lib/RDF/RDFa/API/RDFTripleFilter.pm

Empty file added.

lib/RDF/RDFa/API/RDFaDocument.pm

Empty file added.

lib/RDF/RDFa/API/TypedLiteral.pm

+package RDF::RDFa::API::TypedLiteral;
+
+use 5.010;
+use Moose;
+use namespace::clean -except => 'meta';
+use common::sense;
+
+extends 'RDF::RDFa::API::RDFNode';
+
+has trineNode => (is => 'ro', isa => 'RDF::Trine::Node::Literal');
+
+sub construct
+{
+	my ($class, $value, $dt, %args) = @_;
+	
+	if ($dt && $args{dataContext})
+	{
+		$dt = $args{dataContext}->resolveCurieToString($dt);
+	}
+	
+	return $class->new(
+		%args,
+		trineNode => RDF::Trine::Node::Literal->new("$value", undef, $dt),
+		);
+}
+
+sub type
+{
+	my ($self) = @_;
+	
+	return undef
+		unless $self->trineNode->has_datatype;
+		
+	return RDF::RDFa::API::IRI->construct($self->trineNode->literal_datatype);
+}
+
+sub valueOf
+{
+	my ($self) = @_;
+	
+	if ($self->dataContext)
+	{
+		return $self->dataContext->convertType($self->value, $self->type);
+	}
+	
+	return $self->value;
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+RDF::RDFa::API::TypedLiteral - A TypedLiteral has a string value and a datatype specified as an IRI Reference.
+
+=head1 WEBIDL
+
+	[NoInterfaceObject]
+	interface TypedLiteral : RDFNode {
+		 readonly attribute stringifier DOMString value;
+		 readonly attribute IRI                   type;
+		 any valueOf ();
+	};
+
+=head1 SEE ALSO
+
+L<RDF::RDFa::API>.
+
+=head1 BUGS
+
+Please report any bugs to L<http://rt.cpan.org/>.
+
+=head1 AUTHOR
+
+Toby Inkster E<lt>tobyink@cpan.orgE<gt>.
+
+=head1 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.

lib/RDF/RDFa/API/TypedLiteralConverter.pm

+package RDF::RDFa::API::TypedLiteralConverter;
+
+use Module::Pluggable
+	search_path   => ['RDF::RDFa::API::TypedLiteralConverter'],
+	sub_name      => 'converters',
+	require       => 1,
+	instantiate   => 1;
+
+use 5.010;
+use Moose::Role;
+use namespace::clean -except => ['meta', 'converters'];
+use common::sense;
+
+requires 'convert';
+
+BEGIN
+{
+	foreach my $converter (__PACKAGE__->converters)
+	{
+		next unless $converter->can('does') && $converter->does(__PACKAGE__);
+		
+		foreach my $type ($converter->defaults)
+		{
+			$RDF::RDFa::API::DataContext::DefaultConverters{$type} = $converter;
+		}
+	}
+}
+
+sub handles
+{
+	return;
+}
+
+sub defaults
+{
+	return;
+}
+
+1;

lib/RDF/RDFa/API/TypedLiteralConverter/Boolean.pm

+package RDF::RDFa::API::TypedLiteralConverter::Boolean;
+
+use 5.010;
+use Moose;
+use namespace::clean -except => ['meta'];
+use common::sense;
+
+with 'RDF::RDFa::API::TypedLiteralConverter';
+
+sub handles
+{
+	return ('http://www.w3.org/2001/XMLSchema#boolean');
+}
+
+sub defaults
+{
+	return ('http://www.w3.org/2001/XMLSchema#boolean');
+}
+
+sub convert
+{
+	my ($self, $value, $dt, $modifier) = @_;
+	
+	warn "This module was not designed to work with datatype <$dt>"
+		unless grep { $_ eq $dt } $self->handles;
+	
+	return $modifier || 1
+		if $value =~ /[ty]/i;
+	return;
+}
+
+1;

lib/RDF/RDFa/API/TypedLiteralConverter/Date.todo

Empty file added.

lib/RDF/RDFa/API/TypedLiteralConverter/DateTime.todo

Empty file added.

lib/RDF/RDFa/API/TypedLiteralConverter/Numeric.pm

+package RDF::RDFa::API::TypedLiteralConverter::Numeric;
+
+use 5.010;
+use Moose;
+use namespace::clean -except => ['meta'];
+use common::sense;
+
+with 'RDF::RDFa::API::TypedLiteralConverter';
+
+sub handles
+{
+	return (
+		'http://www.w3.org/2001/XMLSchema#float',
+		'http://www.w3.org/2001/XMLSchema#double',
+		'http://www.w3.org/2001/XMLSchema#integer',
+		'http://www.w3.org/2001/XMLSchema#long',
+		'http://www.w3.org/2001/XMLSchema#decimal',
+		'http://www.w3.org/2001/XMLSchema#nonPositiveInteger',
+		'http://www.w3.org/2001/XMLSchema#negativeInteger',
+		'http://www.w3.org/2001/XMLSchema#int',
+		'http://www.w3.org/2001/XMLSchema#short',
+		'http://www.w3.org/2001/XMLSchema#byte',
+		'http://www.w3.org/2001/XMLSchema#nonNegativeInteger',
+		'http://www.w3.org/2001/XMLSchema#unsignedLong',
+		'http://www.w3.org/2001/XMLSchema#unsignedInt',
+		'http://www.w3.org/2001/XMLSchema#unsignedShort',
+		'http://www.w3.org/2001/XMLSchema#unsignedByte',
+		'http://www.w3.org/2001/XMLSchema#positiveInteger',
+		);
+}
+
+sub defaults
+{
+	return (
+		'http://www.w3.org/2001/XMLSchema#float',
+		'http://www.w3.org/2001/XMLSchema#double',
+		'http://www.w3.org/2001/XMLSchema#integer',
+		'http://www.w3.org/2001/XMLSchema#long',
+		);
+}
+
+sub convert
+{
+	my ($self, $value, $dt, $modifier) = @_;
+	
+	warn "This module was not designed to work with datatype <$dt>"
+		unless grep { $_ eq $dt } $self->handles;
+	
+	return (0 + $value);
+}
+
+1;

lib/RDF/RDFa/API/TypedLiteralConverter/String.pm

+package RDF::RDFa::API::TypedLiteralConverter::String;
+
+use 5.010;
+use Moose;
+use namespace::clean -except => ['meta'];
+use common::sense;
+
+with 'RDF::RDFa::API::TypedLiteralConverter';
+
+sub handles
+{
+	return ('http://www.w3.org/2001/XMLSchema#string');
+}
+
+sub defaults
+{
+	return ('http://www.w3.org/2001/XMLSchema#string');
+}
+
+sub convert
+{
+	my ($self, $value, $dt, $modifier) = @_;
+	
+	warn "This module was not designed to work with datatype <$dt>"
+		unless grep { $_ eq $dt } $self->handles;
+	
+	return $value;
+}
+
+1;

lib/RDF/RDFa/API/TypedLiteralConverter/Time.todo

Empty file added.
+use lib 'inc';
+use Test::More tests => 1;
+use Test::Signature;
+signature_ok();
+use Test::More tests => 1;
+BEGIN { use_ok('Example::Example') };
+