RDF-aREF/lib/RDF/aREF.pm
package RDF::aREF;
use strict;
use warnings;
use v5.10;
our $VERSION = '0.28';
use RDF::aREF::Query;
use RDF::aREF::Decoder;
use RDF::aREF::Encoder;
use Scalar::Util qw(blessed reftype);
use Carp qw(croak);
use parent 'Exporter';
our @EXPORT = qw(decode_aref encode_aref aref_query aref_query_map);
our %EXPORT_TAGS = ( all => [@EXPORT] );
our @CARP_NOT = qw(RDF::aREF::Query RDF::aREF::Decoder RDF::aREF::Encoder);
sub decode_aref(@) { ## no critic
my ( $aref, %options ) = @_;
RDF::aREF::Decoder->new(%options)->decode($aref);
}
sub encode_aref(@) { ## no critic
my ( $source, %options ) = @_;
my $encoder = RDF::aREF::Encoder->new(%options);
my $aref = $options{to} // {};
if ( blessed $source and $source->isa('RDF::Trine::Iterator') ) {
$encoder->add_iterator( $source, $aref );
}
elsif ( blessed $source and $source->DOES('Attean::API::TripleIterator') ) {
$encoder->add_iterator( $source, $aref );
}
elsif ( blessed $source and $source->isa('RDF::Trine::Model') ) {
$encoder->add_iterator( $source->as_stream, $aref );
}
elsif ( blessed $source and $source->DOES('Attean::API::TripleStore') ) {
$encoder->add_iterator( $source->get_triples, $aref );
}
elsif ( ref $source and reftype $source eq 'HASH' ) {
$encoder->add_hashref( $source, $aref );
}
elsif ( !ref $source ) {
eval { require RDF::Trine::Model; require RDF::Trine::Parser };
croak
"RDF::Trine missing: encoding aREF from URL or file not supported!"
if $@;
my $model = RDF::Trine::Model->new;
# TODO: directly use iterator
if ( $source =~ qr{^https?://} ) {
RDF::Trine::Parser->parse_url_into_model( $source, $model );
}
elsif ( -f $source ) {
my $parser = RDF::Trine::Parser->guess_parser_by_filename($source);
$parser->parse_file_into_model( "file://$source", $source, $model );
}
else {
croak 'invalid RDF graph, given as string';
}
$encoder->add_iterator( $model->as_stream, $aref );
}
return $aref;
}
sub aref_query(@) { ## no critic
my ( $graph, $origin, @queries ) = @_ < 3 ? ( $_[0], undef, $_[1] ) : @_;
RDF::aREF::Query->new( query => join '|', @queries )
->apply( $graph, $origin );
}
sub aref_query_map(@) { ## no critic
my ( $graph, $origin, $map ) = @_ < 3 ? ( $_[0], undef, $_[1] ) : @_;
my %record;
while ( my ( $query, $field ) = each %$map ) {
my @values = aref_query(
$origin
? ( $graph, $origin, $query )
: ( $graph, $query )
);
if (@values) {
if ( $record{$field} ) {
if ( ref $record{$field} ) {
push @{ $record{$field} }, @values;
}
else {
$record{$field} = [ $record{$field}, @values ];
}
}
else {
$record{$field} = @values > 1 ? \@values : $values[0];
}
}
}
\%record;
}
1;
__END__
=head1 NAME
RDF::aREF - Another RDF Encoding Form
=begin markdown
# STATUS
[](https://travis-ci.org/nichtich/RDF-aREF)
[](https://coveralls.io/r/nichtich/RDF-aREF)
[](http://cpants.cpanauthors.org/dist/RDF-aREF)
=end markdown
=head1 SYNOPSIS
use RDF::aREF;
my $rdf = {
_id => 'http://example.com/people#alice',
foaf_name => 'Alice Smith',
foaf_age => '42^xsd_integer',
foaf_homepage => [
{
_id => 'http://personal.example.org/',
dct_modified => '2010-05-29^xsd_date',
},
'http://work.example.com/asmith/',
],
foaf_knows => {
dct_description => 'a nice guy@en',
},
};
decode_aref( $rdf,
callback => sub {
my ($subject, $predicate, $object, $language, $datatype) = @_;
...
}
);
my @lastmod = aref_query $rdf, 'foaf_homepage.dct_modified^';
my $model = RDF::Trine::Model->new;
decode_aref( $rdf, callback => $model );
print RDF::Trine::Serializer->new('Turtle')->serialize_model_to_string($model);
my $model = RDF::Trine::Model->new;
RDF::Trine::Parser->parse_url_into_model($url, $model);
my $aref = encode_aref $model;
=head1 DESCRIPTION
B<aREF> (L<another RDF Encoding Form|http://gbv.github.io/aREF/>) is an
encoding of RDF graphs in form of arrays, hashes, and Unicode strings. This
module provides methods for decoding from aREF data to RDF triples
(L<RDF::aREF::Decoder>), for encoding RDF data in aREF (L<RDF::aREF::Encoder>),
and for querying parts of an RDF graph (L<RDF::aREF::Query>).
=head1 WARNING
B<aREF> has been an attempt to solve problems that meanwhile have largely been
solved by L<JSON-LD|https://json-ld.org/>. Despite aRef having its own
benefits, please consider using a more established technology (JSON-LD)
instead!
=head1 EXPORTED FUNCTIONS
The following functions are exported by default.
=head2 decode_aref $aref [, %options ]
Decodes an aREF document given as hash reference with L<RDF::aREF::Decoder>.
Equivalent to C<< RDF::aREF::Decoder->new(%options)->decode($aref) >>.
=head2 encode_aref $graph [, %options ]
Construct an aREF subject mapfrom an RDF graph. The L<RDF::aREF::Encoder> for
possible options. The C<$graph> can be supplied as:
=over
=item
instance of L<RDF::Trine::Model>
=item
instance of L<RDF::Trine::Model::Iterator>
=item
an URL or a filename (only if L<RDF::Trine> is installed)
=item
instance of L<Attean::API::TripleIterator> (experimental)
=item
instance of L<Attean::API::TripleStore> (experimental)
=item
hash reference with L<RDF/JSON|http://www.w3.org/TR/rdf-json/> format (as
returned by method C<as_hashref> in L<RDF::Trine::Model>)
=back
=head2 aref_query $graph, [ $origin ], @queries
Query parts of an aREF data structure by L<aREF query
expressions|http://gbv.github.io/aREF/aREF.html#aref-query> and return a list.
See L<RDF::aREF::Query> for details.
=head2 aref_query_map( $graph, [ $origin ], $query_map )
Map parts of an aREF data structure to a flat key-value structure.
=head1 SEE ALSO
=over
=item
aREF is specified at L<http://github.com/gbv/aREF>.
=item
See L<Catmandu::RDF> for an application of this module.
=item
Usee L<RDF::Trine> for more elaborated handling of RDF data in Perl.
=item
See L<RDF::YAML> for a similar (outdated) RDF encoding in YAML.
=back
=head1 COPYRIGHT AND LICENSE
Copyright Jakob Voss, 2014-
This library is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.
=cut