File Coverage

blib/lib/RDF/Trine/Serializer/TriG.pm
Criterion Covered Total %
statement 102 183 55.7
branch 17 46 36.9
condition 1 15 6.6
subroutine 18 27 66.6
pod 7 7 100.0
total 145 278 52.1


line stmt bran cond sub pod time code
1             # RDF::Trine::Serializer::TriG
2             # -----------------------------------------------------------------------------
3              
4             =head1 NAME
5              
6             RDF::Trine::Serializer::TriG - TriG Serializer
7              
8             =head1 VERSION
9              
10             This document describes RDF::Trine::Serializer::TriG version 1.017
11              
12             =head1 SYNOPSIS
13              
14             use RDF::Trine::Serializer::TriG;
15             my $serializer = RDF::Trine::Serializer::TriG->new();
16              
17             =head1 DESCRIPTION
18              
19             The RDF::Trine::Serializer::TriG class provides an API for serializing RDF
20             graphs to the TriG syntax.
21              
22             =head1 METHODS
23              
24             Beyond the methods documented below, this class inherits methods from the
25             L<RDF::Trine::Serializer> class.
26              
27             =over 4
28              
29             =cut
30              
31             package RDF::Trine::Serializer::TriG;
32              
33 68     68   453 use strict;
  68         150  
  68         1664  
34 68     68   324 use warnings;
  68         373  
  68         1681  
35 68     68   358 use base qw(RDF::Trine::Serializer);
  68         137  
  68         4095  
36              
37 68     68   415 use URI;
  68         152  
  68         1133  
38 68     68   311 use Carp;
  68         172  
  68         3138  
39 68     68   504 use Encode;
  68         144  
  68         5135  
40 68     68   424 use Data::Dumper;
  68         155  
  68         2688  
41 68     68   387 use Scalar::Util qw(blessed refaddr reftype);
  68         147  
  68         2820  
42              
43 68     68   376 use RDF::Trine::Node;
  68         152  
  68         1851  
44 68     68   368 use RDF::Trine::Statement;
  68         154  
  68         1372  
45 68     68   324 use RDF::Trine::Error qw(:try);
  68         152  
  68         489  
46              
47             ######################################################################
48              
49             our ($VERSION);
50             BEGIN {
51 68     68   8738 $VERSION = '1.017';
52 68         87965 $RDF::Trine::Serializer::serializer_names{ 'trig' } = __PACKAGE__;
53             # $RDF::Trine::Serializer::format_uris{ 'http://sw.deri.org/2008/07/n-quads/#n-quads' } = __PACKAGE__;
54             # foreach my $type (qw(text/x-nquads)) {
55             # $RDF::Trine::Serializer::media_types{ $type } = __PACKAGE__;
56             # }
57             }
58              
59             ######################################################################
60              
61             =item C<< new >>
62              
63             Returns a new TriG serializer object.
64              
65             =cut
66              
67             sub new {
68 5     5 1 48 my $class = shift;
69 5         10 my $ns = {};
70 5         9 my $base_uri;
71              
72 5         10 my @args = @_;
73 5         25 my $ttl = RDF::Trine::Serializer::Turtle->new(@args);
74 5 100       14 if (@_) {
75 2 50 33     8 if (scalar(@_) == 1 and reftype($_[0]) eq 'HASH') {
76 0         0 $ns = shift;
77             } else {
78 2         6 my %args = @_;
79 2 50       7 if (exists $args{ base }) {
80 0         0 $base_uri = $args{ base };
81             }
82 2 50       7 if (exists $args{ base_uri }) {
83 0         0 $base_uri = $args{ base_uri };
84             }
85 2 50       6 if (exists $args{ namespaces }) {
86 2         5 $ns = $args{ namespaces };
87             }
88             }
89             }
90            
91 5         8 my %rev;
92 5         8 while (my ($ns, $uri) = each(%{ $ns })) {
  7         23  
93 2 50       8 if (blessed($uri)) {
94 0         0 $uri = $uri->uri_value;
95 0 0       0 if (blessed($uri)) {
96 0         0 $uri = $uri->uri_value;
97             }
98             }
99 2         6 $rev{ $uri } = $ns;
100             }
101            
102 5         16 my $self = bless( {
103             ns => \%rev,
104             base_uri => $base_uri,
105             ttl => $ttl,
106             }, $class );
107            
108 5         13 return $self;
109             }
110              
111             =item C<< serialize_model_to_file ( $fh, $model ) >>
112              
113             Serializes the C<$model> to TriG, printing the results to the supplied
114             filehandle C<<$fh>>.
115              
116             =cut
117              
118             sub serialize_model_to_file {
119 0     0 1 0 my $self = shift;
120 0         0 my $file = shift;
121 0         0 my $model = shift;
122            
123 0         0 my %ns = reverse(%{ $self->{ns} });
  0         0  
124 0         0 my @nskeys = sort keys %ns;
125 0 0       0 if (@nskeys) {
126 0         0 foreach my $ns (sort @nskeys) {
127 0         0 my $uri = $ns{ $ns };
128 0         0 print $file "\@prefix $ns: <$uri> .\n";
129             }
130 0         0 print $file "\n";
131             }
132            
133 0         0 my $s = $self->{ttl};
134 0         0 my $count = $model->count_statements(undef, undef, undef, RDF::Trine::Node::Nil->new());
135 0 0       0 if ($count) {
136 0         0 my $iter = $model->get_statements(undef, undef, undef, RDF::Trine::Node::Nil->new());
137 0         0 print $file "{\n\t";
138 0         0 my $ttl = $s->serialize_iterator_to_string($iter);
139 0         0 $ttl =~ s/\n/\n\t/g;
140 0         0 print {$file} $ttl;
  0         0  
141 0         0 print $file "}\n\n";
142             }
143            
144 0         0 my $graphs = $model->get_graphs;
145 0         0 while (my $g = $graphs->next) {
146 0         0 my $iter = $model->get_statements(undef, undef, undef, $g);
147 0         0 print $file sprintf("%s {\n", $self->node_as_concise_string($g));
148 0         0 my $ttl = $s->serialize_iterator_to_string($iter);
149 0         0 $ttl =~ s/\n/\n\t/g;
150 0         0 print $file $ttl;
151 0         0 print $file "}\n\n";
152             }
153             }
154              
155             =item C<< serialize_model_to_string ( $model ) >>
156              
157             Serializes the C<$model> to TriG, returning the result as a string.
158              
159             =cut
160              
161             sub serialize_model_to_string {
162 0     0 1 0 my $self = shift;
163 0         0 my $model = shift;
164 0         0 my $iter = $model->as_stream;
165 0         0 my $data = '';
166 0         0 open(my $fh, '>:encoding(UTF-8)', \$data);
167 0         0 $self->serialize_model_to_file($fh, $model);
168 0         0 close($fh);
169 0         0 return decode('UTF-8', $data);
170             }
171              
172             =item C<< serialize_iterator_to_file ( $file, $iter ) >>
173              
174             Serializes the iterator to TriG, printing the results to the supplied
175             filehandle C<<$fh>>.
176              
177             =cut
178              
179             sub serialize_iterator_to_file {
180 5     5 1 9 my $self = shift;
181 5         9 my $file = shift;
182 5         9 my $iter = shift;
183            
184 5         9 my %ns = reverse(%{ $self->{ns} });
  5         22  
185 5         14 my @nskeys = sort keys %ns;
186 5 100       16 if (@nskeys) {
187 2         5 foreach my $ns (sort @nskeys) {
188 2         4 my $uri = $ns{ $ns };
189 2         12 print $file "\@prefix $ns: <$uri> .\n";
190             }
191 2         5 print $file "\n";
192             }
193            
194 5         10 my $g;
195 5         7 my $in_graph = 0;
196 5         9 my $s = $self->{ttl};
197 5         19 while (my $st = $iter->next) {
198 7 50       39 my $new_graph = $st->isa('RDF::Trine::Statement::Quad') ? $st->graph : RDF::Trine::Node::Nil->new();
199 7 100       22 if (not($in_graph)) {
    100          
200 5         9 $g = $new_graph;
201 5 100       22 if ($g->is_nil) {
202 4         19 print $file "{\n"
203             } else {
204 1         6 print $file sprintf("%s {\n", $s->node_as_concise_string($g));
205             }
206             } elsif (not($g->equal($new_graph))) {
207 1         2 $g = $new_graph;
208 1         5 print $file sprintf("}\n\n%s {\n", $s->node_as_concise_string($g));
209             }
210 7         15 $in_graph = 1;
211            
212 7         12 print {$file} "\t" . $self->_statement_as_string( $st );
  7         19  
213             }
214            
215 5 50       19 if ($in_graph) {
216 5         19 print $file "}\n";
217             }
218             }
219              
220             =item C<< serialize_iterator_to_string ( $iter ) >>
221              
222             Serializes the iterator to TriG, returning the result as a string.
223              
224             =cut
225              
226             sub serialize_iterator_to_string {
227 5     5 1 19 my $self = shift;
228 5         8 my $iter = shift;
229 5         8 my $data = '';
230 5     1   83 open(my $fh, '>:encoding(UTF-8)', \$data);
  1     1   6  
  1         3  
  1         7  
  1         704  
  1         2  
  1         5  
231 5         1090 $self->serialize_iterator_to_file($fh, $iter);
232 5         59 close($fh);
233 5         21 return decode('UTF-8', $data);
234             }
235              
236             sub _statement_as_string {
237 7     7   13 my $self = shift;
238 7         9 my $st = shift;
239 7         11 my @nodes;
240 7         12 my $s = $self->{ttl};
241 7         22 @nodes = ($st->nodes)[0..2];
242 7         18 return join(' ', map { $s->node_as_concise_string($_) } @nodes) . " .\n";
  21         62  
243             }
244              
245              
246             =item C<< statement_as_string ( $st ) >>
247              
248             Returns a string with the supplied RDF::Trine::Statement::Quad object serialized
249             as TriG, ending in a DOT and newline.
250              
251             =cut
252              
253             sub statement_as_string {
254 0     0 1 0 my $self = shift;
255 0         0 my $st = shift;
256 0         0 my @nodes = $st->nodes;
257 0         0 return join(' ', map { $_->as_ntriples } @nodes[0..3]) . " .\n";
  0         0  
258             }
259              
260              
261             sub _node_concise_string {
262 0     0   0 my $self = shift;
263 0         0 my $obj = shift;
264 0 0 0     0 if ($obj->is_literal and $obj->has_datatype) {
    0          
265 0         0 my $dt = $obj->literal_datatype;
266 0 0 0     0 if ($dt =~ m<^http://www.w3.org/2001/XMLSchema#(integer|double|decimal)$> and $obj->is_canonical_lexical_form) {
267 0         0 my $value = $obj->literal_value;
268 0         0 return $value;
269             } else {
270 0         0 my $dtr = iri($dt);
271 0         0 my $literal = $obj->literal_value;
272 0         0 my $qname;
273             try {
274 0     0   0 my ($ns,$local) = $dtr->qname;
275 0 0 0     0 if (blessed($self) and exists $self->{ns}{$ns}) {
276 0         0 $qname = join(':', $self->{ns}{$ns}, $local);
277 0         0 $self->{used_ns}{ $self->{ns}{$ns} }++;
278             }
279 0     0   0 } catch RDF::Trine::Error with {};
280 0 0       0 if ($qname) {
281 0         0 my $escaped = $obj->_unicode_escape( $literal );
282 0         0 return qq["$escaped"^^$qname];
283             }
284             }
285             } elsif ($obj->isa('RDF::Trine::Node::Resource')) {
286 0         0 my $value;
287             try {
288 0     0   0 my ($ns,$local) = $obj->qname;
289 0 0 0     0 if (blessed($self) and exists $self->{ns}{$ns}) {
290 0         0 $value = join(':', $self->{ns}{$ns}, $local);
291 0         0 $self->{used_ns}{ $self->{ns}{$ns} }++;
292             }
293 0     0   0 } catch RDF::Trine::Error with {} otherwise {};
294 0 0       0 if ($value) {
295 0         0 return $value;
296             }
297             }
298 0         0 return;
299             }
300              
301             =item C<< node_as_concise_string >>
302              
303             Returns a string representation using common Turtle syntax shortcuts (e.g. for numeric literals).
304              
305             =cut
306              
307             sub node_as_concise_string {
308 0     0 1 0 my $self = shift;
309 0         0 my $obj = shift;
310 0         0 my $str = $self->_node_concise_string( $obj );
311 0 0       0 if (defined($str)) {
312 0         0 return $str;
313             } else {
314 0         0 return $obj->as_ntriples;
315             }
316             }
317              
318             1;
319              
320             __END__
321              
322             =back
323              
324             =head1 BUGS
325              
326             Please report any bugs or feature requests to through the GitHub web interface
327             at L<https://github.com/kasei/perlrdf/issues>.
328              
329             =head1 SEE ALSO
330              
331             L<http://sw.deri.org/2008/07/n-quads/>
332              
333             =head1 AUTHOR
334              
335             Gregory Todd Williams C<< <gwilliams@cpan.org> >>
336              
337             =head1 COPYRIGHT
338              
339             Copyright (c) 2006-2012 Gregory Todd Williams. This
340             program is free software; you can redistribute it and/or modify it under
341             the same terms as Perl itself.
342              
343             =cut