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.915_01.
11              
12             =cut
13              
14             package RDF::Query::Algebra::GroupGraphPattern;
15              
16 36     36   184 use strict;
  36         66  
  36         901  
17 36     36   179 use warnings;
  36         67  
  36         1023  
18 36     36   175 no warnings 'redefine';
  36         67  
  36         1274  
19 36     36   189 use base qw(RDF::Query::Algebra);
  36         71  
  36         2784  
20              
21 36     36   206 use Log::Log4perl;
  36         79  
  36         297  
22 36     36   1729 use Scalar::Util qw(blessed refaddr);
  36         67  
  36         1865  
23 36     36   184 use Data::Dumper;
  36         74  
  36         1711  
24 36     36   199 use List::Util qw(first);
  36         77  
  36         2436  
25 36     36   179 use Carp qw(carp croak confess);
  36         76  
  36         1945  
26 36     36   196 use RDF::Query::Error qw(:try);
  36         65  
  36         251  
27 36     36   4826 use Time::HiRes qw(gettimeofday tv_interval);
  36         69  
  36         277  
28 36     36   3786 use RDF::Trine::Iterator qw(sgrep smap swatch);
  36         60  
  36         4065  
29              
30             ######################################################################
31              
32             our ($VERSION, $debug);
33             BEGIN {
34 36     36   85 $debug = 0;
35 36         75 $VERSION = '2.915_01';
36 36         46242 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 49154 my $class = shift;
58 354         776 my @patterns = @_;
59 354         832 my $self = bless( \@patterns, $class );
60 354         768 foreach my $p (@patterns) {
61 391 50       1874 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         1462 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 1434 my $self = shift;
78 1058         2357 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 2745 my $self = shift;
89 2129         2491 return @{ $self };
  2129         6051  
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         18 my @quads;
113             my %bgps;
114 12         51 foreach my $p ($self->subpatterns_of_type('RDF::Query::Algebra::NamedGraph')) {
115 4         17 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         41 foreach my $p ($self->subpatterns_of_type('RDF::Query::Algebra::BasicGraphPattern')) {
121 14 100       63 next if ($bgps{ refaddr($p) });
122 10         36 push(@quads, $p->quads);
123             }
124 12         48 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 905 my $self = shift;
135 637         864 my $context = shift;
136 637   100     1920 my $prefix = shift || '';
137 637   50     1775 my $indent = ($context->{indent} ||= "\t");
138            
139 637         1420 my @patterns = $self->patterns;
140 637 100       1568 if (scalar(@patterns) == 1) {
141 563         2106 return $patterns[0]->sse( $context, $prefix );
142             } else {
143             return sprintf(
144             "(join\n${prefix}${indent}%s)",
145 74         484 join("\n${prefix}${indent}", map { $_->sse( $context, "${prefix}${indent}" ) } @patterns)
  64         3356  
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 121 my $self = shift;
189 78   100     246 my $context = shift || {};
190 78   100     293 my $indent = shift || '';
191 78         138 my $force = $context->{force_ggp_braces};
192 78 100       179 $force = 0 unless (defined($force));
193 78 100       225 if ($force) {
194 47         79 $context->{force_ggp_braces}--;
195             }
196            
197 78         102 my @patterns;
198 78         172 my @p = $self->patterns;
199            
200 78 50 100     436 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         140 foreach my $p (@p) {
206 105         453 push(@patterns, $p->as_sparql( $context, "$indent\t" ));
207             }
208 75         209 my $patterns = join("\n${indent}\t", @patterns);
209 75         230 my $string = sprintf("{\n${indent}\t%s\n${indent}}", $patterns);
210 75         339 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 132 my $self = shift;
261 84         190 return RDF::Query::_uniq(map { $_->referenced_variables } $self->patterns);
  84         298  
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 85 my $self = shift;
273 49         128 return RDF::Query::_uniq(map { $_->potentially_bound } $self->patterns);
  46         186  
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 11 my $self = shift;
284 7         14 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 344 my $self = shift;
296 178         272 my @data;
297 178         555 foreach my $arg ($self->construct_args) {
298 172 50 33     1756 if (blessed($arg) and $arg->isa('RDF::Query::Algebra')) {
299 172         967 push(@data, $arg->_referenced_blanks());
300             }
301             }
302            
303 178         316 my %seen;
304 178         369 foreach my $d (@data) {
305 191         505 foreach my $b (@$d) {
306 30 50       139 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         654 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