File Coverage

blib/lib/RDF/Query/Algebra/GroupGraphPattern.pm
Criterion Covered Total %
statement 104 136 76.4
branch 14 24 58.3
condition 11 14 78.5
subroutine 23 28 82.1
pod 15 15 100.0
total 167 217 76.9


line stmt bran cond sub pod time code
1             # RDF::Query::Algebra::GroupGraphPattern
2             # -----------------------------------------------------------------------------
3              
4             =head1 NAME
5              
6             RDF::Query::Algebra::GroupGraphPattern - Algebra class for GroupGraphPattern patterns
7              
8             =head1 VERSION
9              
10             This document describes RDF::Query::Algebra::GroupGraphPattern version 2.918.
11              
12             =cut
13              
14             package RDF::Query::Algebra::GroupGraphPattern;
15              
16 36     36   138 use strict;
  36         46  
  36         870  
17 36     36   117 use warnings;
  36         47  
  36         737  
18 36     36   114 no warnings 'redefine';
  36         38  
  36         920  
19 36     36   127 use base qw(RDF::Query::Algebra);
  36         44  
  36         2180  
20              
21 36     36   172 use Log::Log4perl;
  36         43  
  36         237  
22 36     36   1341 use Scalar::Util qw(blessed refaddr);
  36         49  
  36         1481  
23 36     36   121 use Data::Dumper;
  36         49  
  36         1377  
24 36     36   151 use List::Util qw(first);
  36         42  
  36         2040  
25 36     36   160 use Carp qw(carp croak confess);
  36         50  
  36         1492  
26 36     36   147 use RDF::Query::Error qw(:try);
  36         43  
  36         198  
27 36     36   3856 use Time::HiRes qw(gettimeofday tv_interval);
  36         52  
  36         258  
28 36     36   3001 use RDF::Trine::Iterator qw(sgrep smap swatch);
  36         48  
  36         2925  
29              
30             ######################################################################
31              
32             our ($VERSION, $debug);
33             BEGIN {
34 36     36   62 $debug = 0;
35 36         59 $VERSION = '2.918';
36 36         32513 our %SERVICE_BLOOM_IGNORE = ('http://dbpedia.org/sparql' => 1); # by default, assume dbpedia doesn't implement k:bloom().
37             }
38              
39             ######################################################################
40              
41             =head1 METHODS
42              
43             Beyond the methods documented below, this class inherits methods from the
44             L<RDF::Query::Algebra> class.
45              
46             =over 4
47              
48             =cut
49              
50             =item C<new ( @graph_patterns )>
51              
52             Returns a new GroupGraphPattern structure.
53              
54             =cut
55              
56             sub new {
57 356     356 1 31725 my $class = shift;
58 356         560 my @patterns = @_;
59 356         723 my $self = bless( \@patterns, $class );
60 356         637 foreach my $p (@patterns) {
61 393 50       1464 unless (blessed($p)) {
62 0         0 Carp::cluck;
63 0         0 throw RDF::Query::Error::MethodInvocationError -text => "GroupGraphPattern constructor called with unblessed value";
64             }
65             }
66 356         1008 return $self;
67             }
68              
69             =item C<< construct_args >>
70              
71             Returns a list of arguments that, passed to this class' constructor,
72             will produce a clone of this algebra pattern.
73              
74             =cut
75              
76             sub construct_args {
77 1064     1064 1 938 my $self = shift;
78 1064         1617 return ($self->patterns);
79             }
80              
81             =item C<< patterns >>
82              
83             Returns a list of the graph patterns in this GGP.
84              
85             =cut
86              
87             sub patterns {
88 2143     2143 1 1778 my $self = shift;
89 2143         1651 return @{ $self };
  2143         4029  
90             }
91              
92             =item C<< add_pattern >>
93              
94             Appends a new child pattern to the GGP.
95              
96             =cut
97              
98             sub add_pattern {
99 0     0 1 0 my $self = shift;
100 0         0 my $pattern = shift;
101 0         0 push( @{ $self }, $pattern );
  0         0  
102             }
103              
104             =item C<< quads >>
105              
106             Returns a list of the quads belonging to this GGP.
107              
108             =cut
109              
110             sub quads {
111 12     12 1 17 my $self = shift;
112 12         12 my @quads;
113             my %bgps;
114 12         39 foreach my $p ($self->subpatterns_of_type('RDF::Query::Algebra::NamedGraph')) {
115 4         20 push(@quads, $p->quads);
116 4         14 foreach my $bgp ($p->subpatterns_of_type('RDF::Query::Algebra::BasicGraphPattern')) {
117 4         21 $bgps{ refaddr($bgp) }++;
118             }
119             }
120 12         27 foreach my $p ($self->subpatterns_of_type('RDF::Query::Algebra::BasicGraphPattern')) {
121 14 100       47 next if ($bgps{ refaddr($p) });
122 10         34 push(@quads, $p->quads);
123             }
124 12         37 return @quads;
125             }
126              
127             =item C<< sse >>
128              
129             Returns the SSE string for this algebra expression.
130              
131             =cut
132              
133             sub sse {
134 637     637 1 635 my $self = shift;
135 637         554 my $context = shift;
136 637   100     1481 my $prefix = shift || '';
137 637   50     1310 my $indent = ($context->{indent} ||= "\t");
138            
139 637         1019 my @patterns = $self->patterns;
140 637 100       1197 if (scalar(@patterns) == 1) {
141 563         1572 return $patterns[0]->sse( $context, $prefix );
142             } else {
143             return sprintf(
144             "(join\n${prefix}${indent}%s)",
145 74         462 join("\n${prefix}${indent}", map { $_->sse( $context, "${prefix}${indent}" ) } @patterns)
  64         2353  
146             );
147             }
148             }
149              
150             =item C<< explain >>
151              
152             Returns a string serialization of the algebra appropriate for display on the
153             command line.
154              
155             =cut
156              
157             sub explain {
158 0     0 1 0 my $self = shift;
159 0         0 my $s = shift;
160 0         0 my $count = shift;
161 0         0 my $indent = $s x $count;
162 0         0 my $string = "${indent}group graph pattern\n";
163              
164 0         0 my @patterns = $self->patterns;
165 0 0       0 if (scalar(@patterns) == 1) {
166 0         0 $string .= $patterns[0]->explain( $s, $count+1 );
167             } else {
168 0         0 foreach my $p (@patterns) {
169 0 0       0 if ($p->can('explain')) {
170 0         0 $string .= $p->explain( $s, $count+1 );
171             } else {
172 0         0 my $str = $p->sse;
173 0 0       0 $str .= "\n" unless (substr($str,-1) eq "\n");
174 0         0 $string .= $str;
175             }
176             }
177             }
178 0         0 return $string;
179             }
180              
181             =item C<< as_sparql >>
182              
183             Returns the SPARQL string for this algebra expression.
184              
185             =cut
186              
187             sub as_sparql {
188 80     80 1 93 my $self = shift;
189 80   100     201 my $context = shift || {};
190 80   100     275 my $indent = shift || '';
191 80         97 my $force = $context->{force_ggp_braces};
192 80 100       143 $force = 0 unless (defined($force));
193 80 100       153 if ($force) {
194 49         62 $context->{force_ggp_braces}--;
195             }
196            
197 80         73 my @patterns;
198 80         122 my @p = $self->patterns;
199            
200 80 50 100     345 if (scalar(@p) == 0) {
    100          
201 0         0 return "{}";
202             } elsif (scalar(@p) == 1 and not($force)) {
203 3         11 return $p[0]->as_sparql($context, $indent);
204             } else {
205 77         111 foreach my $p (@p) {
206 107         354 push(@patterns, $p->as_sparql( $context, "$indent\t" ));
207             }
208 77         180 my $patterns = join("\n${indent}\t", @patterns);
209 77         192 my $string = sprintf("{\n${indent}\t%s\n${indent}}", $patterns);
210 77         241 return $string;
211             }
212             }
213              
214             =item C<< as_hash >>
215              
216             Returns the query as a nested set of plain data structures (no objects).
217              
218             =cut
219              
220             sub as_hash {
221 0     0 1 0 my $self = shift;
222 0         0 my $context = shift;
223             return {
224             type => lc($self->type),
225 0         0 patterns => [ map { $_->as_hash } $self->patterns ],
  0         0  
226             };
227             }
228              
229             =item C<< as_spin ( $model ) >>
230              
231             Adds statements to the given model to represent this algebra object in the
232             SPARQL Inferencing Notation (L<http://www.spinrdf.org/>).
233              
234             =cut
235              
236             sub as_spin {
237 0     0 1 0 my $self = shift;
238 0         0 my $model = shift;
239 0         0 return map { $_->as_spin($model) } $self->patterns;
  0         0  
240            
241             }
242              
243             =item C<< type >>
244              
245             Returns the type of this algebra expression.
246              
247             =cut
248              
249             sub type {
250 0     0 1 0 return 'GGP';
251             }
252              
253             =item C<< referenced_variables >>
254              
255             Returns a list of the variable names used in this algebra expression.
256              
257             =cut
258              
259             sub referenced_variables {
260 88     88 1 113 my $self = shift;
261 88         139 return RDF::Query::_uniq(map { $_->referenced_variables } $self->patterns);
  88         221  
262             }
263              
264             =item C<< potentially_bound >>
265              
266             Returns a list of the variable names used in this algebra expression that will
267             bind values during execution.
268              
269             =cut
270              
271             sub potentially_bound {
272 51     51 1 66 my $self = shift;
273 51         121 return RDF::Query::_uniq(map { $_->potentially_bound } $self->patterns);
  48         162  
274             }
275              
276             =item C<< definite_variables >>
277              
278             Returns a list of the variable names that will be bound after evaluating this algebra expression.
279              
280             =cut
281              
282             sub definite_variables {
283 7     7 1 5 my $self = shift;
284 7         11 return RDF::Query::_uniq(map { $_->definite_variables } $self->patterns);
  7         22  
285             }
286              
287             =item C<< check_duplicate_blanks >>
288              
289             Returns true if blank nodes respect the SPARQL rule of no blank-label re-use
290             across BGPs, otherwise throws a RDF::Query::Error::QueryPatternError exception.
291              
292             =cut
293              
294             sub check_duplicate_blanks {
295 180     180 1 255 my $self = shift;
296 180         254 my @data;
297 180         575 foreach my $arg ($self->construct_args) {
298 174 50 33     1546 if (blessed($arg) and $arg->isa('RDF::Query::Algebra')) {
299 174         828 push(@data, $arg->_referenced_blanks());
300             }
301             }
302            
303 180         235 my %seen;
304 180         325 foreach my $d (@data) {
305 193         350 foreach my $b (@$d) {
306 30 50       100 if ($seen{ $b }++) {
307 0         0 throw RDF::Query::Error::QueryPatternError -text => "Same blank node identifier ($b) used in more than one BasicGraphPattern.";
308             }
309             }
310             }
311            
312 180         479 return 1;
313             }
314              
315             1;
316              
317             __END__
318              
319             =back
320              
321             =head1 AUTHOR
322              
323             Gregory Todd Williams <gwilliams@cpan.org>
324              
325             =cut