File Coverage

blib/lib/RDF/Trine/Serializer.pm
Criterion Covered Total %
statement 142 151 94.0
branch 20 20 100.0
condition 10 14 71.4
subroutine 32 34 94.1
pod 7 7 100.0
total 211 226 93.3


line stmt bran cond sub pod time code
1             # RDF::Trine::Serializer
2             # -----------------------------------------------------------------------------
3              
4             =head1 NAME
5              
6             RDF::Trine::Serializer - RDF Serializer class
7              
8             =head1 VERSION
9              
10             This document describes RDF::Trine::Serializer version 1.018
11              
12             =head1 SYNOPSIS
13              
14             use RDF::Trine::Serializer;
15              
16             =head1 DESCRIPTION
17              
18             The RDF::Trine::Serializer class provides an API for serializing RDF graphs
19             (via both model objects and graph iterators) to strings and files.
20              
21             =cut
22              
23             package RDF::Trine::Serializer;
24              
25 68     68   464 use strict;
  68         137  
  68         1556  
26 68     68   303 use warnings;
  68         151  
  68         1484  
27 68     68   302 no warnings 'redefine';
  68         152  
  68         1593  
28              
29 68     68   1894 use Data::Dumper;
  68         20398  
  68         2895  
30 68     68   121768 use HTTP::Negotiate qw(choose);
  68         24004  
  68         5762  
31              
32             our ($VERSION);
33             our %serializer_names;
34             our %format_uris;
35             our %media_types;
36             BEGIN {
37 68     68   1260 $VERSION = '1.018';
38             }
39              
40 68     68   22856 use RDF::Trine::Serializer::NQuads;
  68         183  
  68         1696  
41 68     68   23187 use RDF::Trine::Serializer::NTriples;
  68         173  
  68         1746  
42 68     68   24309 use RDF::Trine::Serializer::NTriples::Canonical;
  68         182  
  68         2096  
43 68     68   24584 use RDF::Trine::Serializer::RDFXML;
  68         184  
  68         2002  
44 68     68   23260 use RDF::Trine::Serializer::RDFJSON;
  68         178  
  68         1783  
45 68     68   416 use RDF::Trine::Serializer::Turtle;
  68         137  
  68         1304  
46 68     68   23395 use RDF::Trine::Serializer::TriG;
  68         181  
  68         2024  
47 68     68   22930 use RDF::Trine::Serializer::RDFPatch;
  68         188  
  68         46360  
48              
49              
50             =head1 METHODS
51              
52             =over 4
53              
54             =item C<< serializer_names >>
55              
56             Returns a list of valid serializer names for use as arguments to the serializer constructor.
57              
58             =cut
59              
60             sub serializer_names {
61 0     0 1 0 return keys %serializer_names;
62             }
63              
64             =item C<< new ( $serializer_name, %options ) >>
65              
66             Returns a new RDF::Trine::Serializer object for the serializer with the
67             specified name (e.g. "rdfxml" or "turtle"). If no serializer with the specified
68             name is found, throws a RDF::Trine::Error::SerializationError exception.
69              
70             The valid key-values used in C<< %options >> are specific to a particular
71             serializer implementation. For serializers that support namespace declarations
72             (to allow more concise serialization), use C<< namespaces => \%namespaces >> in
73             C<< %options >>, where the keys of C<< %namespaces >> are namespace names and
74             the values are (partial) URIs. For serializers that support base URI declarations,
75             use C<< base_uri => $base_uri >> .
76              
77             =cut
78              
79             sub new {
80 9     9 1 4218 my $class = shift;
81 9         17 my $name = shift;
82 9         21 my $key = lc($name);
83 9         27 $key =~ s/[^-a-z]//g;
84            
85 9 100       35 if (my $class = $serializer_names{ $key }) {
86 8         62 return $class->new( @_ );
87             } else {
88 1         17 throw RDF::Trine::Error::SerializationError -text => "No serializer known named $name";
89             }
90             }
91              
92             =item C<< negotiate ( request_headers => $request_headers, %options ) >>
93              
94             Returns a two-element list containing an appropriate media type and
95             RDF::Trine::Serializer object as decided by L<HTTP::Negotiate>. If
96             the C<< 'request_headers' >> key-value is supplied, the C<<
97             $request_headers >> is passed to C<< HTTP::Negotiate::choose >>. The
98             option C<< 'restrict' >>, set to a list of serializer names, can be
99             used to limit the serializers to choose from. Finally, an C<<'extend' >>
100             option can be set to a hashref that contains MIME-types
101             as keys and a custom variant as value. This will enable the user to
102             use this negotiator to return a type that isn't supported by any
103             serializers. The subsequent code will have to find out how to return a
104             representation. The rest of C<< %options >> is passed through to the
105             serializer constructor.
106              
107             =cut
108              
109             sub negotiate {
110 14     14 1 12516 my $class = shift;
111 14         39 my %options = @_;
112 14         32 my $headers = delete $options{ 'request_headers' };
113 14         26 my $restrict = delete $options{ 'restrict' };
114 14   100     85 my $extend = delete $options{ 'extend' } || {};
115 14         26 my %sclasses;
116 14 100 66     50 if (ref($restrict) && ref($restrict) eq 'ARRAY') {
117 3         13 $sclasses{ $serializer_names{$_} } = 1 for @$restrict;
118             } else {
119 11         69 %sclasses = reverse %serializer_names;
120             }
121 14         28 my @default_variants;
122 14         50 while (my($type, $sclass) = each(%media_types)) {
123 140 100       327 next unless $sclasses{$sclass};
124 124         166 my $qv;
125             # slightly prefer turtle as a readable format to others
126             # try hard to avoid using ntriples as 'text/plain' isn't very useful for conneg
127 124 100       262 if ($type eq 'text/turtle') {
    100          
128 14         24 $qv = 1.0;
129             } elsif ($type eq 'text/plain') {
130 11         16 $qv = 0.2;
131             } else {
132 99         132 $qv = 0.99;
133             }
134 124 100       287 $qv -= 0.01 if ($type =~ m#/x-#); # prefer non experimental media types
135 124 100       322 $qv -= 0.01 if ($type =~ m#^application/(?!rdf[+]xml)#); # prefer standard rdf/xml to other application/* formats
136 124         433 push(@default_variants, [$type, $qv, $type]);
137             }
138            
139 14         25 my %custom_thunks;
140             my @custom_variants;
141 14         44 while (my($type,$thunk) = each(%$extend)) {
142 3         8 push(@custom_variants, [$thunk, 1.0, $type]);
143 3         13 $custom_thunks{ $thunk } = [$type, $thunk];
144             }
145            
146             # remove variants with media types that are in custom_variants from @variants
147 14         30 my @variants = grep { not exists $extend->{ $_->[2] } } @default_variants;
  124         240  
148 14         23 push(@variants, @custom_variants);
149            
150 14         48 my $stype = choose( \@variants, $headers );
151 14 100 100     8377 if (defined($stype) and $custom_thunks{ $stype }) {
152 2         5 my $thunk = $stype;
153 2         5 my $type = $custom_thunks{ $stype }[0];
154 2         14 return ($type, $thunk);
155             }
156            
157 12 100 66     56 if (defined($stype) and my $sclass = $media_types{ $stype }) {
158 10         53 return ($stype, $sclass->new( %options ));
159             } else {
160 2         13 throw RDF::Trine::Error::SerializationError -text => "No appropriate serializer found for content-negotiation";
161             }
162             }
163              
164             =item C<< media_types >>
165              
166             Returns a list of media types appropriate for the format of the serializer.
167              
168             =cut
169              
170             sub media_types {
171 6     6 1 2822 my $self = shift;
172 6   33     26 my $class = ref($self) || $self;
173 6         10 my @list;
174 6         27 while (my($type, $sclass) = each(%media_types)) {
175 60 100       209 push(@list, $type) if ($sclass eq $class);
176             }
177 6         19 my @types = sort @list;
178 6         21 return @types;
179             }
180              
181             =item C<< serialize_model_to_file ( $fh, $model ) >>
182              
183             Serializes the C<< $model >>, printing the results to the supplied filehandle
184             C<<$fh>>.
185              
186             =item C<< serialize_model_to_string ( $model ) >>
187              
188             Serializes the C<< $model >>, returning the result as a string.
189              
190             =cut
191              
192             sub serialize_model_to_string {
193 13     13 1 175 my $self = shift;
194 13         22 my $model = shift;
195 13         26 my $string = '';
196 13     1   275 open( my $fh, '>:encoding(UTF-8)', \$string );
  1     1   9  
  1         4  
  1         8  
  1         813  
  1         3  
  1         5  
197 13         1625 $self->serialize_model_to_file( $fh, $model );
198 11         129 close($fh);
199 11         53 return $string;
200             }
201              
202             =item C<< serialize_iterator_to_file ( $file, $iterator ) >>
203              
204             Serializes the statement objects produced by C<< $iterator >>, printing the
205             results to the supplied filehandle C<<$fh>>.
206              
207             Note that some serializers may not support the use of this method, or may
208             require the full materialization of the iterator in order to serialize it.
209             If materialization is required, available memeory may constrain the iterators
210             that can be serialized.
211              
212             =cut
213              
214             sub serialize_iterator_to_file {
215 0     0 1 0 my $self = shift;
216 0         0 my $fh = shift;
217 0         0 my $iter = shift;
218 0         0 my %args = @_;
219 0         0 my $model = RDF::Trine::Model->temporary_model;
220 0         0 while (my $st = $iter->next) {
221 0         0 $model->add_statement( $st );
222             }
223 0         0 return $self->serialize_model_to_file( $fh, $model );
224             }
225              
226              
227             =item C<< serialize_iterator_to_string ( $iterator ) >>
228              
229             Serializes the statement objects produced by C<< $iterator >>, returning the
230             result as a string. Note that the same constraints apply to this method as to
231             C<< serialize_iterator_to_file >>.
232              
233             =cut
234              
235             sub serialize_iterator_to_string {
236 7     7 1 41 my $self = shift;
237 7         12 my $iter = shift;
238 7         14 my $string = '';
239 7         85 open( my $fh, '>', \$string );
240 7         34 $self->serialize_iterator_to_file( $fh, $iter );
241 7         24 close($fh);
242 7         35 return $string;
243             }
244              
245              
246              
247              
248             =back
249              
250             =cut
251              
252             package RDF::Trine::Serializer::FileSink;
253              
254 68     68   534 use strict;
  68         147  
  68         1372  
255 68     68   309 use warnings;
  68         155  
  68         5524  
256              
257             =begin private
258              
259             =head1 NAME
260              
261             RDF::Trine::Serializer::FileSink
262              
263             =head1 METHODS
264              
265             =over 4
266              
267             =cut
268              
269             =item C<< new ( $fh ) >>
270              
271             Returns a new serializer sink object backed by a filehandle.
272              
273             =cut
274              
275             sub new {
276 1     1   3 my $class = shift;
277 1         2 my $fh = shift;
278 1         4 return bless([$fh],$class);
279             }
280              
281             =item C<< emit ( $data ) >>
282              
283             Write the C<< $data >> to the sink.
284              
285             =cut
286              
287             sub emit {
288 16     16   25 my $self = shift;
289 16         25 my $data = shift;
290 16         20 print {$self->[0]} $data;
  16         54  
291             }
292              
293             =back
294              
295             =cut
296              
297             package RDF::Trine::Serializer::StringSink;
298              
299 68     68   381 use strict;
  68         147  
  68         1206  
300 68     68   293 use warnings;
  68         151  
  68         1475  
301 68     68   316 use Encode;
  68         163  
  68         11112  
302              
303             =head1 NAME
304              
305             RDF::Trine::Serializer::StringSink
306              
307             =head1 METHODS
308              
309             =over 4
310              
311             =cut
312              
313             =item C<< new () >>
314              
315             Returns a new serializer sink object backed by a string.
316              
317             =cut
318              
319             sub new {
320 42     42   100 my $class = shift;
321 42         166 my $string = decode_utf8("");
322 42         1229 return bless(\$string,$class);
323             }
324              
325             =item C<< emit ( $data ) >>
326              
327             Write the C<< $data >> to the sink.
328              
329             =cut
330              
331             sub emit {
332 767     767   1227 my $self = shift;
333 767         1187 my $data = shift;
334 767         1986 $$self .= $data;
335             }
336              
337             =item C<< prepend ( $data ) >>
338              
339             Prepend the C<< $data >> to the underlying string.
340              
341             =cut
342              
343             sub prepend {
344 10     10   18 my $self = shift;
345 10         16 my $data = shift;
346 10         63 $$self = $data . $$self;
347             }
348              
349             =item C<< string () >>
350              
351             Returns the string value of all data written to the sink.
352              
353             =cut
354              
355             sub string {
356 47     47   88 my $self = shift;
357 47         588 return $$self;
358             }
359              
360             =back
361              
362             =end private
363              
364             =cut
365              
366             1;
367              
368             __END__
369              
370             =head1 BUGS
371              
372             Please report any bugs or feature requests to through the GitHub web interface
373             at L<https://github.com/kasei/perlrdf/issues>.
374              
375             =head1 AUTHOR
376              
377             Gregory Todd Williams C<< <gwilliams@cpan.org> >>
378              
379             =head1 COPYRIGHT
380              
381             Copyright (c) 2006-2012 Gregory Todd Williams. This
382             program is free software; you can redistribute it and/or modify it under
383             the same terms as Perl itself.
384              
385             =cut