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 21 23 91.3
pod 8 8 100.0
total 156 174 89.6


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.018
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     72   14702 use strict;
  68         150  
  68         1593  
31 68     68   353 use warnings;
  68         141  
  68         1301  
32              
33 68     68   741 use URI;
  68         5327  
  68         997  
34 68     68   305 use Carp;
  68         137  
  68         2993  
35 68     68   883 use Data::Dumper;
  68         5340  
  68         2428  
36 68     68   370 use Scalar::Util qw(blessed);
  68         139  
  68         2464  
37 68     68   372 use List::Util qw(min);
  68         143  
  68         2912  
38              
39 68     68   704 use RDF::Trine::Node;
  68         145  
  68         1840  
40 68     68   744 use RDF::Trine::Statement;
  68         172  
  68         1396  
41 68     68   329 use RDF::Trine::Error qw(:try);
  68         152  
  68         438  
42              
43             ######################################################################
44              
45             our ($VERSION);
46             BEGIN {
47 68     68   59220 $VERSION = '1.018';
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 16 my $class = shift;
60 3         7 my $ns = {};
61              
62 3         12 my %args = @_;
63 3 100       11 if (exists $args{ namespaces }) {
64 2         6 $ns = $args{ namespaces };
65             }
66            
67 3         7 my $sink = $args{sink};
68            
69 3         6 my %rev;
70 3         7 while (my ($ns, $uri) = each(%{ $ns })) {
  7         24  
71 4 50       17 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         12 $rev{ $uri } = $ns;
78             }
79            
80 3         16 my $self = bless( {
81             first => 1,
82             ns => \%rev,
83             last => [],
84             sink => $sink,
85             }, $class );
86 3         10 return $self;
87             }
88              
89             sub _sink {
90 101     101   148 my $self = shift;
91 101         261 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         3 my $c = shift;
103 2         8 $c =~ s/\n/\n# /g;
104 2         6 $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 20 my $self = shift;
116 12         21 my $op = shift;
117 12         25 my @args = @_;
118 12         28 $self->_sink->emit($op);
119 12         25 foreach my $arg (@args) {
120 36         68 $self->_sink->emit(' ');
121 36         68 $self->_sink->emit($arg);
122             }
123 12         27 $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 20 my $self = shift;
134 11         16 my $st = shift;
135 11 100       29 if ($self->{first}) {
136 3         23 my $header = $self->_header();
137 3         9 $self->_sink->emit($header);
138 3         9 $self->{first} = 0;
139             }
140 11         34 my @list = $self->terms_as_string_list( $st->nodes );
141 11         34 $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       4 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         4 $self->emit_operation( 'D', @list );
160             }
161              
162             sub _header {
163 3     3   8 my $self = shift;
164 3         7 my %ns = reverse(%{ $self->{ns} });
  3         14  
165 3         19 my @nskeys = sort keys %ns;
166 3         7 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         15 $header .= "\@prefix $ns: <$uri> .\n";
171             }
172 2         5 $header .= "\n";
173             }
174 3         9 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 21 my $self = shift;
199 12         31 my @nodes = @_;
200 12         25 my @str_nodes = map { $self->node_as_concise_string($_) } @nodes;
  36         77  
201 12         24 if (1) {
202 12         24 foreach my $i (0 .. min(scalar(@nodes), scalar(@{$self->{'last'}}))) {
  12         60  
203 39 100 100     157 if (defined($self->{'last'}[$i]) and $nodes[$i]->equal( $self->{'last'}[$i])) {
204 6         15 $str_nodes[$i] = 'R';
205             }
206             }
207 12         25 @{ $self->{'last'} } = @nodes;
  12         33  
208             }
209 12         38 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 58 my $self = shift;
220 36         53 my $obj = shift;
221 36 100       133 if ($obj->isa('RDF::Trine::Node::Resource')) {
222 24         38 my $value;
223             try {
224 24     24   903 my ($ns,$local) = $obj->qname;
225 19 100 66     144 if (blessed($self) and exists $self->{ns}{$ns}) {
226 13         40 $value = join(':', $self->{ns}{$ns}, $local);
227 13         39 $self->{used_ns}{ $self->{ns}{$ns} }++;
228             }
229 24     0   161 } catch RDF::Trine::Error with {} otherwise {};
230 24 100       416 if ($value) {
231 13         42 return $value;
232             }
233             }
234 23         75 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