1# RDF::Trine::Serializer::TSV
2# -----------------------------------------------------------------------------
3
4=head1 NAME
5
6RDF::Trine::Serializer::TSV - TSV Serializer
7
8=head1 VERSION
9
10This document describes RDF::Trine::Store version 1.019
11
12=head1 SYNOPSIS
13
14 use RDF::Trine::Serializer::TSV;
15 my $serializer	= RDF::Trine::Serializer::TSV->new();
16
17=head1 DESCRIPTION
18
19The RDF::Trine::Serializer::TSV class provides an API for serializing RDF
20graphs to the TSV syntax.
21
22=head1 METHODS
23
24Beyond the methods documented below, this class inherits methods from the
25L<RDF::Trine::Serializer> class.
26
27=over 4
28
29=cut
30
31package RDF::Trine::Serializer::TSV;
32
33use strict;
34use warnings;
35use base qw(RDF::Trine::Serializer);
36
37use URI;
38use Carp;
39use Data::Dumper;
40use Scalar::Util qw(blessed);
41
42use RDF::Trine::Node;
43use RDF::Trine::Statement;
44use RDF::Trine::Error qw(:try);
45
46######################################################################
47
48our ($VERSION);
49BEGIN {
50	$VERSION	= '1.019';
51	$RDF::Trine::Serializer::serializer_names{ 'tsv' }	= __PACKAGE__;
52	$RDF::Trine::Serializer::format_uris{ 'http://www.w3.org/ns/formats/TSV' }	= __PACKAGE__;
53	foreach my $type (qw(text/tsv)) {
54		$RDF::Trine::Serializer::media_types{ $type }	= __PACKAGE__;
55	}
56}
57
58######################################################################
59
60=item C<< new >>
61
62Returns a new TSV serializer object.
63
64=cut
65
66sub new {
67	my $class	= shift;
68	my %args	= @_;
69	my $self = bless( {}, $class);
70	return $self;
71}
72
73=item C<< serialize_model_to_file ( $fh, $model ) >>
74
75Serializes the C<$model> to TSV, printing the results to the supplied
76filehandle C<<$fh>>.
77
78=cut
79
80sub serialize_model_to_file {
81	my $self	= shift;
82	my $file	= shift;
83	my $model	= shift;
84	my $st		= RDF::Trine::Statement->new( map { RDF::Trine::Node::Variable->new($_) } qw(s p o) );
85	my $pat		= RDF::Trine::Pattern->new( $st );
86	my $stream	= $model->get_pattern( $pat, undef, orderby => [ qw(s ASC p ASC o ASC) ] );
87	my $iter	= $stream->as_statements( qw(s p o) );
88	print {$file} join("\t", qw(s p o)) . "\n";
89	while (my $st = $iter->next) {
90		print {$file} $self->statement_as_string( $st );
91	}
92}
93
94=item C<< serialize_model_to_string ( $model ) >>
95
96Serializes the C<$model> to TSV, returning the result as a string.
97
98=cut
99
100sub serialize_model_to_string {
101	my $self	= shift;
102	my $model	= shift;
103	my $st		= RDF::Trine::Statement->new( map { RDF::Trine::Node::Variable->new($_) } qw(s p o) );
104	my $pat		= RDF::Trine::Pattern->new( $st );
105	my $stream	= $model->get_pattern( $pat, undef, orderby => [ qw(s ASC p ASC o ASC) ] );
106	my $iter	= $stream->as_statements( qw(s p o) );
107
108	my $string	= join("\t", qw(s p o)) . "\n";
109	while (my $st = $iter->next) {
110		my @nodes	= $st->nodes;
111		$string		.= $self->statement_as_string( $st );
112	}
113	return $string;
114}
115
116=item C<< serialize_iterator_to_file ( $file, $iter ) >>
117
118Serializes the iterator to TSV, printing the results to the supplied
119filehandle C<<$fh>>.
120
121=cut
122
123sub serialize_iterator_to_file {
124	my $self	= shift;
125	my $file	= shift;
126	my $iter	= shift;
127	my $e		= $iter->peek;
128
129	if (defined($e) and blessed($e) and $e->isa('RDF::Trine::Statement')) {
130		print {$file} join("\t", qw(?s ?p ?o)) . "\n";
131		while (my $st = $iter->next) {
132			print {$file} $self->statement_as_string( $st );
133		}
134	} elsif (defined($e) and blessed($e) and $e->isa('RDF::Trine::VariableBindings')) {
135		my @names	= $iter->binding_names;
136		print {$file} join("\t", map { "?$_" } @names) . "\n";
137		while (my $r = $iter->next) {
138			print {$file} $self->result_as_string( $r, \@names );
139		}
140	}
141}
142
143=item C<< serialize_iterator_to_string ( $iter ) >>
144
145Serializes the iterator to TSV, returning the result as a string.
146
147=cut
148
149sub serialize_iterator_to_string {
150	my $self	= shift;
151	my $iter	= shift;
152
153	# TODO: must print the header line corresponding to the bindings in the entire iterator...
154	my $string	= '';
155	my $e		= $iter->peek;
156	if (defined($e) and blessed($e) and $e->isa('RDF::Trine::Statement')) {
157		$string	.= join("\t", qw(?s ?p ?o)) . "\n";
158		while (my $st = $iter->next) {
159			$string		.= $self->statement_as_string( $st );
160		}
161	} elsif (defined($e) and blessed($e) and $e->isa('RDF::Trine::VariableBindings')) {
162		my @names	= $iter->binding_names;
163		$string	.= join("\t", map { "?$_" } @names) . "\n";
164		while (my $r = $iter->next) {
165			$string		.= $self->result_as_string( $r, \@names );
166		}
167	}
168	return $string;
169}
170
171sub _serialize_bounded_description {
172	my $self	= shift;
173	my $model	= shift;
174	my $node	= shift;
175	my $seen	= shift || {};
176	# TODO: must print the header line, but only on the first (non-recursive) call to _serialize_bounded_description
177	return '' if ($seen->{ $node->sse }++);
178	my $iter	= $model->get_statements( $node, undef, undef );
179	my $string	= '';
180	while (my $st = $iter->next) {
181		my @nodes	= $st->nodes;
182		$string		.= $self->statement_as_string( $st );
183		if ($nodes[2]->isa('RDF::Trine::Node::Blank')) {
184			$string	.= $self->_serialize_bounded_description( $model, $nodes[2], $seen );
185		}
186	}
187	return $string;
188}
189
190=item C<< result_as_string ( $result, \@names ) >>
191
192Returns a string with the bound terms of the given RDF::Trine::VariableBindings
193corresponding to the given C<@names> serialized in N-Triples format, separated
194by tab characters.
195
196=cut
197
198sub result_as_string {
199	my $self	= shift;
200	my $r		= shift;
201	my $names	= shift;
202	my @terms	= map { $r->{ $_ } } @$names;
203	return join("\t", map { blessed($_) ? $_->as_ntriples : '' } @terms) . "\n";
204}
205
206=item C<< statement_as_string ( $st ) >>
207
208Returns a string with the nodes of the given RDF::Trine::Statement serialized
209in N-Triples format, separated by tab characters.
210
211=cut
212
213sub statement_as_string {
214	my $self	= shift;
215	my $st		= shift;
216	my @nodes	= $st->nodes;
217	return join("\t", map { $_->as_ntriples } @nodes[0..2]) . "\n";
218}
219
2201;
221
222__END__
223
224=back
225
226=head1 BUGS
227
228Please report any bugs or feature requests to through the GitHub web interface
229at L<https://github.com/kasei/perlrdf/issues>.
230
231=head1 SEE ALSO
232
233L<http://www.w3.org/TR/rdf-testcases/#ntriples>
234
235=head1 AUTHOR
236
237Gregory Todd Williams  C<< <gwilliams@cpan.org> >>
238
239=head1 COPYRIGHT
240
241Copyright (c) 2006-2012 Gregory Todd Williams. This
242program is free software; you can redistribute it and/or modify it under
243the same terms as Perl itself.
244
245=cut
246