File Coverage

blib/lib/RDF/Query/Algebra/Extend.pm
Criterion Covered Total %
statement 66 116 56.9
branch 5 22 22.7
condition 5 9 55.5
subroutine 18 23 78.2
pod 12 12 100.0
total 106 182 58.2


line stmt bran cond sub pod time code
1             # RDF::Query::Algebra::Extend
2             # -----------------------------------------------------------------------------
3              
4             =head1 NAME
5              
6             RDF::Query::Algebra::Extend - Algebra class for extending the variable projection
7              
8             =head1 VERSION
9              
10             This document describes RDF::Query::Algebra::Extend version 2.915_01.
11              
12             =cut
13              
14             package RDF::Query::Algebra::Extend;
15              
16 36     36   185 use strict;
  36         71  
  36         918  
17 36     36   184 use warnings;
  36         68  
  36         1033  
18 36     36   181 no warnings 'redefine';
  36         72  
  36         1175  
19 36     36   180 use base qw(RDF::Query::Algebra);
  36         63  
  36         2566  
20              
21 36     36   301 use Data::Dumper;
  36         70  
  36         1643  
22 36     36   184 use Set::Scalar;
  36         67  
  36         1331  
23 36     36   180 use Scalar::Util qw(reftype blessed);
  36         66  
  36         1913  
24 36     36   190 use Carp qw(carp croak confess);
  36         76  
  36         2032  
25 36     36   217 use RDF::Trine::Iterator qw(sgrep);
  36         68  
  36         2198  
26              
27             ######################################################################
28              
29             our ($VERSION);
30             BEGIN {
31 36     36   46965 $VERSION = '2.915_01';
32             }
33              
34             ######################################################################
35              
36             =head1 METHODS
37              
38             Beyond the methods documented below, this class inherits methods from the
39             L<RDF::Query::Algebra> class.
40              
41             =over 4
42              
43             =cut
44              
45             =item C<< new ( $pattern, \@vars_and_exprs ) >>
46              
47             Returns a new Extend structure.
48              
49             =cut
50              
51             sub new {
52 25     25 1 40 my $class = shift;
53 25         43 my $pattern = shift;
54 25         49 my $vars = shift;
55 25 50 33     243 unless (reftype($vars) eq 'ARRAY' and not(blessed($vars))) {
56 0         0 throw RDF::Query::Error::MethodInvocationError -text => "Variable list in RDF::Query::Algebra::Extend constructor must be an ARRAY reference";
57             }
58 25         58 my @vars = grep { $_->isa('RDF::Query::Expression::Alias') } @$vars;
  39         158  
59 25         119 return bless( [ $pattern, \@vars ], $class );
60             }
61              
62             =item C<< construct_args >>
63              
64             Returns a list of arguments that, passed to this class' constructor,
65             will produce a clone of this algebra pattern.
66              
67             =cut
68              
69             sub construct_args {
70 130     130 1 198 my $self = shift;
71 130         269 my $pattern = $self->pattern;
72 130         276 my $vars = $self->vars;
73 130         333 return ($pattern, $vars);
74             }
75              
76             =item C<< pattern >>
77              
78             Returns the pattern to be sorted.
79              
80             =cut
81              
82             sub pattern {
83 239     239 1 291 my $self = shift;
84 239 50       510 if (@_) {
85 0         0 $self->[0] = shift;
86             }
87 239         629 return $self->[0];
88             }
89              
90             =item C<< vars >>
91              
92             Returns the vars to be extended.
93              
94             =cut
95              
96             sub vars {
97 213     213 1 260 my $self = shift;
98 213         409 return $self->[1];
99             }
100              
101             =item C<< sse >>
102              
103             Returns the SSE string for this algebra expression.
104              
105             =cut
106              
107             sub sse {
108 56     56 1 90 my $self = shift;
109 56         75 my $context = shift;
110 56   100     223 my $prefix = shift || '';
111 56   50     144 my $indent = $context->{indent} || ' ';
112            
113             my $vars = join(' ',
114             map {
115 64 50       603 ($_->isa('RDF::Query::Node::Variable')) ? '?' . $_->name : $_->sse( $context )
116 56         77 } @{ $self->vars }
  56         117  
117             );
118 56         1022 return sprintf(
119             "(extend (%s)\n${prefix}${indent}%s\n${prefix})",
120             $vars,
121             $self->pattern->sse( $context, "${prefix}${indent}" ),
122             );
123             }
124              
125             sub _from_sse {
126 0     0   0 my $class = shift;
127 0         0 my $context = $_[1];
128 0         0 for ($_[0]) {
129 0 0       0 if (m/^[(]extend\s+[(]\s*/) {
130 0         0 my @nodes;
131 0         0 s/^[(]extend\s+[(]\s*//;
132 0         0 do {
133 0         0 push(@nodes, RDF::Trine::Node->from_sse( $_[0], $context ));
134             } until (m/\s*[)]/);
135 0 0       0 if (m/^\s*[)]/) {
136 0         0 s/^\s*[)]\s*//;
137             } else {
138 0         0 throw RDF::Trine::Error -text => "Cannot parse end-of-extend-vars from SSE string: >>$_<<";
139             }
140            
141 0         0 my ($pattern) = RDF::Query::Algebra->from_sse( $context, $_[0] );
142            
143 0 0       0 if (m/^\s*[)]/) {
144 0         0 s/^\s*[)]\s*//;
145 0         0 return RDF::Query::Algebra::Extend->new( $pattern, \@nodes );
146             } else {
147 0         0 throw RDF::Trine::Error -text => "Cannot parse end-of-extend from SSE string: >>$_<<";
148             }
149             } else {
150 0         0 throw RDF::Trine::Error -text => "Cannot parse extend from SSE string: >>$_<<";
151             }
152             }
153             }
154              
155             =item C<< as_sparql >>
156              
157             Returns the SPARQL string for this algebra expression.
158              
159             =cut
160              
161             sub as_sparql {
162 1     1 1 2 my $self = shift;
163 1   50     4 my $context = shift || {};
164 1         2 my $indent = shift;
165            
166 1 50       4 if ($context->{ skip_extend }) {
167 1         2 $context->{ skip_extend }--;
168 1         4 return $self->pattern->as_sparql( $context, $indent );
169             }
170            
171 0         0 my $pattern = $self->pattern;
172 0         0 my $vlist = $self->vars;
173 0         0 my (@vars);
174 0         0 foreach my $k (@$vlist) {
175 0 0       0 if ($k->isa('RDF::Query::Expression')) {
    0          
176 0         0 push(@vars, $k->as_sparql({}, ''));
177             } elsif ($k->isa('RDF::Query::Node::Variable')) {
178 0         0 push(@vars, '?' . $k->name);
179             } else {
180 0         0 push(@vars, $k);
181             }
182             }
183            
184 0         0 my $ggp = $pattern->as_sparql( $context, $indent );
185 0         0 my $sparql = $ggp;
186 0         0 foreach my $v (@vars) {
187 0         0 $sparql .= "\n${indent}BIND" . $v;
188             }
189 0         0 return $sparql;
190             }
191              
192             =item C<< as_hash >>
193              
194             Returns the query as a nested set of plain data structures (no objects).
195              
196             =cut
197              
198             sub as_hash {
199 0     0 1 0 my $self = shift;
200 0         0 my $context = shift;
201             return {
202             type => lc($self->type),
203             pattern => $self->pattern->as_hash,
204 0         0 vars => [ map { $_->as_hash } @{ $self->vars } ],
  0         0  
  0         0  
205             };
206             }
207              
208             =item C<< type >>
209              
210             Returns the type of this algebra expression.
211              
212             =cut
213              
214             sub type {
215 0     0 1 0 return 'PROJECT';
216             }
217              
218             =item C<< referenced_variables >>
219              
220             Returns a list of the variable names used in this algebra expression.
221              
222             =cut
223              
224             sub referenced_variables {
225 2     2 1 5 my $self = shift;
226 2         6 my @vars = $self->pattern->referenced_variables;
227 2         6 foreach my $v (@{ $self->vars }) {
  2         6  
228 2 50       11 if ($v->isa('RDF::Query::Node::Variable')) {
229 0         0 push(@vars, $v->name);
230             } else {
231 2         13 push(@vars, $v->referenced_variables);
232             }
233             }
234 2         7 return RDF::Query::_uniq(@vars);
235             }
236              
237             =item C<< potentially_bound >>
238              
239             Returns a list of the variable names used in this algebra expression that will
240             bind values during execution.
241              
242             =cut
243              
244             sub potentially_bound {
245 0     0 1 0 my $self = shift;
246 0         0 my @vars;
247 0         0 push(@vars, $self->pattern->potentially_bound);
248 0         0 foreach my $v (@{ $self->vars }) {
  0         0  
249 0 0       0 if ($v->isa('RDF::Query::Node::Variable')) {
250 0         0 push(@vars, $v->name);
251             } else {
252 0         0 push(@vars, $v->potentially_bound);
253             }
254             }
255 0         0 return RDF::Query::_uniq(@vars);
256             }
257              
258             =item C<< definite_variables >>
259              
260             Returns a list of the variable names that will be bound after evaluating this algebra expression.
261              
262             =cut
263              
264             sub definite_variables {
265 0     0 1 0 my $self = shift;
266 0         0 return $self->pattern->definite_variables;
267             }
268              
269             =item C<< is_solution_modifier >>
270              
271             Returns true if this node is a solution modifier.
272              
273             =cut
274              
275             sub is_solution_modifier {
276 24     24 1 117 return 1;
277             }
278              
279              
280             1;
281              
282             __END__
283              
284             =back
285              
286             =head1 AUTHOR
287              
288             Gregory Todd Williams <gwilliams@cpan.org>
289              
290             =cut