File Coverage

blib/lib/RDF/aREF.pm
Criterion Covered Total %
statement 50 64 78.1
branch 17 32 53.1
condition 8 17 47.0
subroutine 13 13 100.0
pod 4 4 100.0
total 92 130 70.7


line stmt bran cond sub pod time code
1             package RDF::aREF;
2 6     6   129131 use strict;
  6         12  
  6         275  
3 6     6   27 use warnings;
  6         10  
  6         183  
4 6     6   66 use v5.10;
  6         20  
  6         344  
5              
6             our $VERSION = '0.25';
7              
8 6     6   2536 use RDF::aREF::Query;
  6         16  
  6         228  
9 6     6   42 use RDF::aREF::Decoder;
  6         11  
  6         242  
10 6     6   3319 use RDF::aREF::Encoder;
  6         16  
  6         295  
11 6     6   50 use Scalar::Util qw(blessed reftype);
  6         12  
  6         401  
12 6     6   32 use Carp qw(croak);
  6         9  
  6         272  
13              
14 6     6   33 use parent 'Exporter';
  6         7  
  6         40  
15             our @EXPORT = qw(decode_aref encode_aref aref_query aref_query_map);
16             our %EXPORT_TAGS = (all => [@EXPORT]);
17              
18             our @CARP_NOT = qw(RDF::aREF::Query RDF::aREF::Decoder RDF::aREF::Encoder);
19              
20             sub decode_aref(@) { ## no critic
21 18     18 1 22228 my ($aref, %options) = @_;
22 18         187 RDF::aREF::Decoder->new(%options)->decode($aref);
23             }
24              
25             sub encode_aref(@) { ## no critic
26 5     5 1 1512 my ($source, %options) = @_;
27 5         42 my $encoder = RDF::aREF::Encoder->new(%options);
28 5   100     37 my $aref = $options{to} // {};
29              
30 5 50 33     102 if (blessed $source and $source->isa('RDF::Trine::Iterator')) {
    50 33        
    50 33        
    50 33        
    100 66        
    50          
31 0         0 $encoder->add_iterator( $source, $aref );
32             } elsif (blessed $source and $source->DOES('Attean::API::TripleIterator')) {
33 0         0 $encoder->add_iterator( $source, $aref );
34             } elsif (blessed $source and $source->isa('RDF::Trine::Model')) {
35 0         0 $encoder->add_iterator( $source->as_stream, $aref );
36             } elsif (blessed $source and $source->DOES('Attean::API::TripleStore')) {
37 0         0 $encoder->add_iterator( $source->get_triples, $aref );
38             } elsif (ref $source and reftype $source eq 'HASH') {
39 4         13 $encoder->add_hashref( $source, $aref );
40             } elsif (!ref $source) {
41 1         2 eval { require RDF::Trine::Model; require RDF::Trine::Parser };
  1         309  
  0         0  
42 1 50       1845 croak "RDF::Trine missing: encoding aREF from URL or file not supported!" if $@;
43 0         0 my $model = RDF::Trine::Model->new;
44             # TODO: directly use iterator
45 0 0       0 if ($source =~ qr{^https?://}) {
    0          
46 0         0 RDF::Trine::Parser->parse_url_into_model($source, $model);
47             } elsif (-f $source) {
48 0         0 my $parser = RDF::Trine::Parser->guess_parser_by_filename($source);
49 0         0 $parser->parse_file_into_model("file://$source", $source, $model)
50             } else {
51 0         0 croak 'invalid RDF graph, given as string';
52             }
53 0         0 $encoder->add_iterator( $model->as_stream, $aref );
54             }
55            
56 4         1076 return $aref;
57             }
58              
59             sub aref_query(@) { ## no critic
60 26 100   26 1 8142 my ($graph, $origin, @queries) = @_ < 3 ? ($_[0], undef, $_[1]) : @_;
61 26         236 RDF::aREF::Query->new( query => join '|', @queries )->apply($graph, $origin);
62             }
63              
64             sub aref_query_map(@) { ## no critic
65 1 50   1 1 11 my ($graph, $origin, $map) = @_ < 3 ? ($_[0], undef, $_[1]) : @_;
66              
67 1         2 my %record;
68            
69 1         7 while (my ($query, $field) = each %$map) {
70 2 50       10 my @values = aref_query( $origin ? ($graph, $origin, $query)
71             : ($graph, $query) );
72 2 50       526 if (@values) {
73 2 100       9 if ($record{$field}) {
74 1 50       8 if (ref $record{$field}) {
75 0         0 push @{$record{$field}}, @values;
  0         0  
76             } else {
77 1         8 $record{$field} = [ $record{$field}, @values ];
78             }
79             } else {
80 1 50       10 $record{$field} = @values > 1 ? \@values : $values[0];
81             }
82             }
83             }
84              
85 1         4 \%record;
86             }
87              
88             1;
89             __END__
90              
91             =head1 NAME
92              
93             RDF::aREF - Another RDF Encoding Form
94              
95             =begin markdown
96              
97             # STATUS
98              
99             [![Build Status](https://travis-ci.org/nichtich/RDF-aREF.png)](https://travis-ci.org/nichtich/RDF-aREF)
100             [![Coverage Status](https://coveralls.io/repos/nichtich/RDF-aREF/badge.png)](https://coveralls.io/r/nichtich/RDF-aREF)
101             [![Kwalitee Score](http://cpants.cpanauthors.org/dist/RDF-aREF.png)](http://cpants.cpanauthors.org/dist/RDF-aREF)
102              
103             =end markdown
104              
105             =head1 SYNOPSIS
106              
107             use RDF::aREF;
108              
109             my $rdf = {
110             _id => 'http://example.com/people#alice',
111             foaf_name => 'Alice Smith',
112             foaf_age => '42^xsd_integer',
113             foaf_homepage => [
114             {
115             _id => 'http://personal.example.org/',
116             dct_modified => '2010-05-29^xsd_date',
117             },
118             'http://work.example.com/asmith/',
119             ],
120             foaf_knows => {
121             dct_description => 'a nice guy@en',
122             },
123             };
124              
125             decode_aref( $rdf,
126             callback => sub {
127             my ($subject, $predicate, $object, $language, $datatype) = @_;
128             ...
129             }
130             );
131            
132             my @lastmod = aref_query $rdf, 'foaf_homepage.dct_modified^';
133              
134             my $model = RDF::Trine::Model->new;
135             decode_aref( $rdf, callback => $model );
136             print RDF::Trine::Serializer->new('Turtle')->serialize_model_to_string($model);
137              
138             my $model = RDF::Trine::Model->new;
139             RDF::Trine::Parser->parse_url_into_model($url, $model);
140             my $aref = encode_aref $model;
141              
142             =head1 DESCRIPTION
143              
144             B<aREF> (L<another RDF Encoding Form|http://gbv.github.io/aREF/>) is an
145             encoding of RDF graphs in form of arrays, hashes, and Unicode strings. This
146             module provides methods for decoding from aREF data to RDF triples
147             (L<RDF::aREF::Decoder>), for encoding RDF data in aREF (L<RDF::aREF::Encoder>),
148             and for querying parts of an RDF graph (L<RDF::aREF::Query>).
149              
150             =head1 EXPORTED FUNCTIONS
151              
152             The following functions are exported by default.
153              
154             =head2 decode_aref $aref [, %options ]
155              
156             Decodes an aREF document given as hash reference with L<RDF::aREF::Decoder>.
157             Equivalent to C<< RDF::aREF::Decoder->new(%options)->decode($aref) >>.
158              
159             =head2 encode_aref $graph [, %options ]
160              
161             Construct an aREF subject mapfrom an RDF graph. The L<RDF::aREF::Encoder> for
162             possible options. The C<$graph> can be supplied as:
163              
164             =over
165              
166             =item
167              
168             instance of L<RDF::Trine::Model>
169              
170             =item
171              
172             instance of L<RDF::Trine::Model::Iterator>
173              
174             =item
175              
176             an URL or a filename (only if L<RDF::Trine> is installed)
177              
178             =item
179              
180             instance of L<Attean::API::TripleIterator> (experimental)
181              
182             =item
183              
184             instance of L<Attean::API::TripleStore> (experimental)
185              
186             =item
187              
188             hash reference with L<RDF/JSON|http://www.w3.org/TR/rdf-json/> format (as
189             returned by method C<as_hashref> in L<RDF::Trine::Model>)
190              
191             =back
192              
193             =head2 aref_query $graph, [ $origin ], @queries
194              
195             Query parts of an aREF data structure by L<aREF query
196             expressions|http://gbv.github.io/aREF/aREF.html#aref-query> and return a list.
197             See L<RDF::aREF::Query> for details.
198              
199             =head2 aref_query_map( $graph, [ $origin ], $query_map )
200              
201             Map parts of an aREF data structure to a flat key-value structure.
202              
203             =head1 SEE ALSO
204              
205             =over
206              
207             =item
208              
209             aREF is specified at L<http://github.com/gbv/aREF>.
210              
211             =item
212              
213             See L<Catmandu::RDF> for an application of this module.
214              
215             =item
216              
217             Usee L<RDF::Trine> for more elaborated handling of RDF data in Perl.
218              
219             =item
220              
221             See L<RDF::YAML> for a similar (outdated) RDF encoding in YAML.
222              
223             =back
224              
225             =head1 COPYRIGHT AND LICENSE
226              
227             Copyright Jakob Voss, 2014-
228              
229             This library is free software; you can redistribute it and/or modify it under
230             the same terms as Perl itself.
231              
232             =cut