File Coverage

blib/lib/RDF/Trine/Exporter/RDFPatch.pm
Criterion Covered Total %
statement 106 117 90.6
branch 16 20 80.0
condition 5 6 83.3
subroutine 22 24 91.6
pod 8 8 100.0
total 157 175 89.7


line stmt bran cond sub pod time code
1             # RDF::Trine::Exporter::RDFPatch
2             # -----------------------------------------------------------------------------
3              
4             =head1 NAME
5              
6             RDF::Trine::Exporter::RDFPatch - RDF-Patch Export
7              
8             =head1 VERSION
9              
10             This document describes RDF::Trine::Exporter::RDFPatch version 1.017
11              
12             =head1 SYNOPSIS
13              
14             use RDF::Trine::Exporter::RDFPatch;
15             my $serializer = RDF::Trine::Exporter::RDFPatch->new();
16              
17             =head1 DESCRIPTION
18              
19             The RDF::Trine::Exporter::RDFPatch class provides an API for serializing RDF
20             graphs to the RDF-Patch syntax.
21              
22             =head1 METHODS
23              
24             =over 4
25              
26             =cut
27              
28             package RDF::Trine::Exporter::RDFPatch;
29              
30 68     68   15951 use strict;
  68         196  
  68         1652  
31 68     68   336 use warnings;
  68         138  
  68         1378  
32              
33 68     68   792 use URI;
  68         5424  
  68         1057  
34 68     68   314 use Carp;
  68         162  
  68         3101  
35 68     68   870 use Data::Dumper;
  68         5413  
  68         2586  
36 68     68   369 use Scalar::Util qw(blessed);
  68         153  
  68         2487  
37 68     68   355 use List::Util qw(min);
  68         147  
  68         2863  
38              
39 68     68   727 use RDF::Trine::Node;
  68         150  
  68         1848  
40 68     68   735 use RDF::Trine::Statement;
  68         161  
  68         1571  
41 68     68   340 use RDF::Trine::Error qw(:try);
  68         192  
  68         393  
42              
43             ######################################################################
44              
45             our ($VERSION);
46             BEGIN {
47 68     68   60872 $VERSION = '1.017';
48             }
49              
50             ######################################################################
51              
52             =item C<< new ( sink => $sink ) >>
53              
54             Returns a new RDF-Patch exporter object.
55              
56             =cut
57              
58             sub new {
59 3     3 1 18 my $class = shift;
60 3         7 my $ns = {};
61              
62 3         12 my %args = @_;
63 3 100       12 if (exists $args{ namespaces }) {
64 2         6 $ns = $args{ namespaces };
65             }
66            
67 3         7 my $sink = $args{sink};
68            
69 3         7 my %rev;
70 3         6 while (my ($ns, $uri) = each(%{ $ns })) {
  7         27  
71 4 50       16 if (blessed($uri)) {
72 0         0 $uri = $uri->uri_value;
73 0 0       0 if (blessed($uri)) {
74 0         0 $uri = $uri->uri_value;
75             }
76             }
77 4         14 $rev{ $uri } = $ns;
78             }
79            
80 3         18 my $self = bless( {
81             first => 1,
82             ns => \%rev,
83             last => [],
84             sink => $sink,
85             }, $class );
86 3         13 return $self;
87             }
88              
89             sub _sink {
90 101     101   152 my $self = shift;
91 101         286 return $self->{sink};
92             }
93              
94             =item C<< comment ( $c ) >>
95              
96             Serializes a comment with the given string.
97              
98             =cut
99              
100             sub comment {
101 2     2 1 6 my $self = shift;
102 2         5 my $c = shift;
103 2         9 $c =~ s/\n/\n# /g;
104 2         9 $self->_sink->emit("# $c\n");
105             }
106              
107             =item C<< emit_operation ( $op, @operands ) >>
108              
109             Serializes an operation identified by the character C<< $op >>, followed by C<< @operands >>
110             (separated by a single space) and a trailing DOT and newline.
111              
112             =cut
113              
114             sub emit_operation {
115 12     12 1 23 my $self = shift;
116 12         20 my $op = shift;
117 12         30 my @args = @_;
118 12         27 $self->_sink->emit($op);
119 12         29 foreach my $arg (@args) {
120 36         71 $self->_sink->emit(' ');
121 36         72 $self->_sink->emit($arg);
122             }
123 12         28 $self->_sink->emit(" .\n");
124             }
125              
126             =item C<< add ( $st ) >>
127              
128             Serializes an add/insert operation for the given statement object.
129              
130             =cut
131              
132             sub add {
133 11     11 1 23 my $self = shift;
134 11         15 my $st = shift;
135 11 100       31 if ($self->{first}) {
136 3         11 my $header = $self->_header();
137 3         10 $self->_sink->emit($header);
138 3         9 $self->{first} = 0;
139             }
140 11         35 my @list = $self->terms_as_string_list( $st->nodes );
141 11         35 $self->emit_operation( 'A', @list );
142             }
143              
144             =item C<< delete ( $st ) >>
145              
146             Serializes a delete operation for the given statement object.
147              
148             =cut
149              
150             sub delete {
151 1     1 1 2 my $self = shift;
152 1         2 my $st = shift;
153 1 50       5 if ($self->{first}) {
154 0         0 my $header = $self->_header();
155 0         0 $self->_sink->emit($header);
156 0         0 $self->{first} = 0;
157             }
158 1         4 my @list = $self->terms_as_string_list( $st->nodes );
159 1         5 $self->emit_operation( 'D', @list );
160             }
161              
162             sub _header {
163 3     3   6 my $self = shift;
164 3         6 my %ns = reverse(%{ $self->{ns} });
  3         15  
165 3         17 my @nskeys = sort keys %ns;
166 3         6 my $header = '';
167 3 100       11 if (@nskeys) {
168 2         8 foreach my $ns (sort @nskeys) {
169 4         9 my $uri = $ns{ $ns };
170 4         14 $header .= "\@prefix $ns: <$uri> .\n";
171             }
172 2         4 $header .= "\n";
173             }
174 3         11 return $header;
175             }
176              
177             =item C<< statement_as_string ( $st ) >>
178              
179             Returns a string with the supplied RDF::Trine::Statement object serialized as an RDF-Patch string.
180              
181             =cut
182              
183             sub statement_as_string {
184 0     0 1 0 my $self = shift;
185 0         0 my $st = shift;
186 0         0 my @nodes = $st->nodes;
187 0         0 my @str_nodes = $self->terms_as_string_list( @nodes );
188 0         0 return join(' ', @str_nodes);
189             }
190              
191             =item C<< terms_as_string_list ( @terms ) >>
192              
193             Returns a list with each supplied term serialized as RDF-Patch strings.
194              
195             =cut
196              
197             sub terms_as_string_list {
198 12     12 1 22 my $self = shift;
199 12         27 my @nodes = @_;
200 12         27 my @str_nodes = map { $self->node_as_concise_string($_) } @nodes;
  36         83  
201 12         26 if (1) {
202 12         21 foreach my $i (0 .. min(scalar(@nodes), scalar(@{$self->{'last'}}))) {
  12         69  
203 39 100 100     180 if (defined($self->{'last'}[$i]) and $nodes[$i]->equal( $self->{'last'}[$i])) {
204 6         22 $str_nodes[$i] = 'R';
205             }
206             }
207 12         26 @{ $self->{'last'} } = @nodes;
  12         34  
208             }
209 12         42 return @str_nodes;
210             }
211              
212             =item C<< node_as_concise_string >>
213              
214             Returns a string representation using RDF-Patch syntax shortcuts (e.g. PrefixNames).
215              
216             =cut
217              
218             sub node_as_concise_string {
219 36     36 1 56 my $self = shift;
220 36         53 my $obj = shift;
221 36 100       136 if ($obj->isa('RDF::Trine::Node::Resource')) {
222 24         37 my $value;
223             try {
224 24     24   963 my ($ns,$local) = $obj->qname;
225 19 100 66     152 if (blessed($self) and exists $self->{ns}{$ns}) {
226 13         46 $value = join(':', $self->{ns}{$ns}, $local);
227 13         43 $self->{used_ns}{ $self->{ns}{$ns} }++;
228             }
229 24     4   190 } catch RDF::Trine::Error with {} otherwise {};
        0      
230 24 100       426 if ($value) {
231 13         43 return $value;
232             }
233             }
234 23         79 return $obj->as_ntriples;
235             }
236              
237             1;
238              
239             __END__
240              
241             =back
242              
243             =head1 NOTES
244              
245             As described in L<RDF::Trine::Node::Resource/as_ntriples>, serialization will
246             decode any L<punycode|http://www.ietf.org/rfc/rfc3492.txt> that is included in the IRI,
247             and serialize it using unicode codepoint escapes.
248              
249             =head1 BUGS
250              
251             Please report any bugs or feature requests to through the GitHub web interface
252             at L<https://github.com/kasei/perlrdf/issues>.
253              
254             =head1 SEE ALSO
255              
256             L<http://afs.github.io/rdf-patch/>
257              
258             =head1 AUTHOR
259              
260             Gregory Todd Williams C<< <gwilliams@cpan.org> >>
261              
262             =head1 COPYRIGHT
263              
264             Copyright (c) 2006-2012 Gregory Todd Williams. This
265             program is free software; you can redistribute it and/or modify it under
266             the same terms as Perl itself.
267              
268             =cut