File Coverage

blib/lib/AtteanX/Serializer/Turtle.pm
Criterion Covered Total %
statement 51 51 100.0
branch 3 4 75.0
condition n/a
subroutine 18 18 100.0
pod 4 5 80.0
total 76 78 97.4


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             AtteanX::Serializer::Turtle - Turtle Serializer
4              
5             =head1 VERSION
6              
7             This document describes AtteanX::Serializer::Turtle version 0.032
8              
9             =head1 SYNOPSIS
10              
11             use Attean;
12             my $serializer = Attean->get_serializer('Turtle')->new();
13             $serializer->serialize_iter_to_io( $io, $fh );
14              
15             =head1 DESCRIPTION
16              
17             ...
18              
19             =head1 ATTRIBUTES
20              
21             =over 4
22              
23             =item C<< canonical_media_type >>
24              
25             =item C<< media_types >>
26              
27             =item C<< handled_type >>
28              
29             =item C<< file_extensions >>
30              
31             =back
32              
33             =head1 METHODS
34              
35             =over 4
36              
37             =cut
38              
39 3     3   10397 use v5.14;
  3         15  
40 3     3   15 use warnings;
  3         15  
  3         115  
41              
42             use Moo;
43 3     3   18 use Data::Dumper;
  3         6  
  3         20  
44 3     3   1047 use Encode qw(encode);
  3         9  
  3         205  
45 3     3   17 use Attean::ListIterator;
  3         7  
  3         149  
46 3     3   21 use List::MoreUtils qw(any);
  3         5  
  3         79  
47 3     3   23 use AtteanX::Parser::Turtle::Constants;
  3         16  
  3         36  
48 3     3   2247 use AtteanX::Parser::Turtle::Token;
  3         8  
  3         483  
49 3     3   20 use AtteanX::Serializer::TurtleTokens;
  3         8  
  3         103  
50 3     3   1259 use Types::Standard qw(InstanceOf HashRef ArrayRef Bool Str);
  3         8  
  3         100  
51 3     3   21 use namespace::clean;
  3         10  
  3         20  
52 3     3   2680 with 'Attean::API::AbbreviatingSerializer';
  3         9  
  3         16  
53             with 'Attean::API::AppendableSerializer';
54             with 'Attean::API::TripleSerializer';
55            
56              
57 1     1 1 1125 return [qw(text/turtle)];
58             }
59            
60 10     10 1 24 state $ITEM_TYPE = Type::Tiny::Role->new(role => 'Attean::API::Triple');
61             return $ITEM_TYPE;
62             }
63              
64 4     4 1 394 =item C<< file_extensions >>
65 4         117  
66             Returns a list of file extensions associated with the serialized format.
67              
68             =cut
69              
70              
71             has 'serializer' => (is => 'rw', isa => InstanceOf['AtteanX::Serializer::TurtleTokens']);
72            
73             my $self = shift;
74 3     3 1 1124 my $s = $self->serializer;
75             unless ($s) {
76             my @args;
77             if (my $map = $self->namespaces) {
78             push(@args, namespaces => $map);
79 8     8 0 3180 }
80 8         149 $s = AtteanX::Serializer::TurtleTokens->new( @args );
81 8 50       74 $self->serializer($s);
82 8         16 }
83 8 100       33 }
84 4         12
85             =item C<< serialize_iter_to_io( $fh, $iterator ) >>
86 8         128  
87 8         2570 Serializes the Turtle token objects from C<< $iterator >> to the
88             L<IO::Handle> object C<< $fh >>.
89              
90             =cut
91              
92             my $self = shift;
93             my $io = shift;
94             my $iter = shift;
95             my @buffer;
96            
97             # TODO: look for shared subject-predicate in repeated triples, and emit COMMA syntax
98             # TODO: look for shared subject in repeated triples, and emit SEMICOLON syntax
99            
100             my $dot = AtteanX::Parser::Turtle::Token->dot;
101             my $comma = AtteanX::Parser::Turtle::Token->comma;
102             my $semi = AtteanX::Parser::Turtle::Token->semicolon;
103             if (my $map = $self->namespaces) {
104             my $prefix = AtteanX::Parser::Turtle::Token->prefix;
105             foreach my $ns (sort $map->list_prefixes) {
106             my $uri = Attean::IRI->new( value => $map->namespace_uri($ns)->as_string );
107             my $name = AtteanX::Parser::Turtle::Token->fast_constructor( PREFIXNAME, -1, -1, -1, -1, ["${ns}:"] );
108             my $iri = AtteanX::Parser::Turtle::Token->fast_constructor( IRI, -1, -1, -1, -1, [$uri->value] );
109             push(@buffer, $prefix);
110             push(@buffer, $name);
111             push(@buffer, $iri);
112             push(@buffer, $dot);
113             }
114             }
115            
116             my $last_subj;
117             my $last_pred;
118             my $sub = sub {
119             if (scalar(@buffer)) {
120             return shift(@buffer);
121             }
122             if (my $t = $iter->next) {
123             my ($subj, $pred, $obj) = $t->values;
124             if (defined($last_subj) and $subj->equals($last_subj)) {
125             if (defined($last_pred) and $pred->equals($last_pred)) {
126             push(@buffer, $comma);
127             push(@buffer, $obj->sparql_tokens->elements);
128             } else {
129             push(@buffer, $semi);
130             push(@buffer, $pred->sparql_tokens->elements);
131             push(@buffer, $obj->sparql_tokens->elements);
132             }
133             } else {
134             if (defined($last_pred)) {
135             push(@buffer, $dot);
136             }
137             foreach my $term ($subj, $pred, $obj) {
138             push(@buffer, $term->sparql_tokens->elements);
139             }
140             }
141            
142             $last_subj = $subj;
143             $last_pred = $pred;
144             return shift(@buffer);
145             }
146              
147             if (defined($last_subj)) {
148             push(@buffer, $dot);
149             $last_subj = undef;
150             $last_pred = undef;
151             return shift(@buffer);
152             }
153            
154             return;
155             };
156            
157             my $titer = Attean::CodeIterator->new( generator => $sub, item_type => 'AtteanX::Parser::Turtle::Token' );
158             return $self->serializer->serialize_iter_to_io($io, $titer);
159             }
160            
161             =item C<< serialize_iter_to_bytes( $iterator ) >>
162              
163             Serializes the Turtle token objects from C<< $iterator >>
164             and returns the serialization as a UTF-8 encoded byte string.
165              
166             =cut
167              
168             my $self = shift;
169             my $iter = shift;
170             my $data = encode('UTF-8', '');
171             open(my $fh, '>', \$data);
172             $self->serialize_iter_to_io($fh, $iter);
173             close($fh);
174             return $data;
175             }
176             }
177              
178             1;
179 1     1   8  
  1         2  
  1         6  
180              
181             =back
182              
183             =head1 BUGS
184              
185             Please report any bugs or feature requests to through the GitHub web interface
186             at L<https://github.com/kasei/perlrdf/issues>.
187              
188             =head1 AUTHOR
189              
190             Gregory Todd Williams C<< <gwilliams@cpan.org> >>
191              
192             =head1 COPYRIGHT
193              
194             Copyright (c) 2014--2022 Gregory Todd Williams. This
195             program is free software; you can redistribute it and/or modify it under
196             the same terms as Perl itself.
197              
198             =cut