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.916.
11              
12             =cut
13              
14             package RDF::Query::Algebra::GroupGraphPattern;
15              
16 36     36   183 use strict;
  36         69  
  36         1000  
17 36     36   188 use warnings;
  36         66  
  36         1005  
18 36     36   177 no warnings 'redefine';
  36         65  
  36         1225  
19 36     36   186 use base qw(RDF::Query::Algebra);
  36         79  
  36         2848  
20              
21 36     36   198 use Log::Log4perl;
  36         77  
  36         287  
22 36     36   1709 use Scalar::Util qw(blessed refaddr);
  36         68  
  36         2163  
23 36     36   206 use Data::Dumper;
  36         74  
  36         1895  
24 36     36   192 use List::Util qw(first);
  36         76  
  36         2506  
25 36     36   190 use Carp qw(carp croak confess);
  36         67  
  36         2041  
26 36     36   187 use RDF::Query::Error qw(:try);
  36         73  
  36         311  
27 36     36   4854 use Time::HiRes qw(gettimeofday tv_interval);
  36         65  
  36         267  
28 36     36   3606 use RDF::Trine::Iterator qw(sgrep smap swatch);
  36         60  
  36         3976  
29              
30             ######################################################################
31              
32             our ($VERSION, $debug);
33             BEGIN {
34 36     36   87 $debug = 0;
35 36         78 $VERSION = '2.916';
36 36         46685 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 354     354 1 49529 my $class = shift;
58 354         789 my @patterns = @_;
59 354         842 my $self = bless( \@patterns, $class );
60 354         877 foreach my $p (@patterns) {
61 391 50       1937 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 354         1499 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 1058     1058 1 1494 my $self = shift;
78 1058         2405 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 2129     2129 1 2771 my $self = shift;
89 2129         2645 return @{ $self };
  2129         6174  
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 21 my $self = shift;
112 12         19 my @quads;
113             my %bgps;
114 12         45 foreach my $p ($self->subpatterns_of_type('RDF::Query::Algebra::NamedGraph')) {
115 4         15 push(@quads, $p->quads);
116 4         16 foreach my $bgp ($p->subpatterns_of_type('RDF::Query::Algebra::BasicGraphPattern')) {
117 4         21 $bgps{ refaddr($bgp) }++;
118             }
119             }
120 12         38 foreach my $p ($self->subpatterns_of_type('RDF::Query::Algebra::BasicGraphPattern')) {
121 14 100       57 next if ($bgps{ refaddr($p) });
122 10         65 push(@quads, $p->quads);
123             }
124 12         50 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 949 my $self = shift;
135 637         864 my $context = shift;
136 637   100     2025 my $prefix = shift || '';
137 637   50     1743 my $indent = ($context->{indent} ||= "\t");
138            
139 637         1431 my @patterns = $self->patterns;
140 637 100       1675 if (scalar(@patterns) == 1) {
141 563         2227 return $patterns[0]->sse( $context, $prefix );
142             } else {
143             return sprintf(
144             "(join\n${prefix}${indent}%s)",
145 74         544 join("\n${prefix}${indent}", map { $_->sse( $context, "${prefix}${indent}" ) } @patterns)
  64         3315  
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 78     78 1 120 my $self = shift;
189 78   100     258 my $context = shift || {};
190 78   100     327 my $indent = shift || '';
191 78         136 my $force = $context->{force_ggp_braces};
192 78 100       190 $force = 0 unless (defined($force));
193 78 100       194 if ($force) {
194 47         81 $context->{force_ggp_braces}--;
195             }
196            
197 78         96 my @patterns;
198 78         178 my @p = $self->patterns;
199            
200 78 50 100     464 if (scalar(@p) == 0) {
    100          
201 0         0 return "{}";
202             } elsif (scalar(@p) == 1 and not($force)) {
203 3         16 return $p[0]->as_sparql($context, $indent);
204             } else {
205 75         149 foreach my $p (@p) {
206 105         452 push(@patterns, $p->as_sparql( $context, "$indent\t" ));
207             }
208 75         211 my $patterns = join("\n${indent}\t", @patterns);
209 75         234 my $string = sprintf("{\n${indent}\t%s\n${indent}}", $patterns);
210 75         323 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 84     84 1 115 my $self = shift;
261 84         188 return RDF::Query::_uniq(map { $_->referenced_variables } $self->patterns);
  84         285  
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 49     49 1 77 my $self = shift;
273 49         146 return RDF::Query::_uniq(map { $_->potentially_bound } $self->patterns);
  46         202  
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 8 my $self = shift;
284 7         15 return RDF::Query::_uniq(map { $_->definite_variables } $self->patterns);
  7         27  
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 178     178 1 312 my $self = shift;
296 178         282 my @data;
297 178         622 foreach my $arg ($self->construct_args) {
298 172 50 33     1841 if (blessed($arg) and $arg->isa('RDF::Query::Algebra')) {
299 172         968 push(@data, $arg->_referenced_blanks());
300             }
301             }
302            
303 178         314 my %seen;
304 178         395 foreach my $d (@data) {
305 191         484 foreach my $b (@$d) {
306 30 50       133 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 178         672 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