File Coverage

blib/lib/RDF/Query/Algebra/Triple.pm
Criterion Covered Total %
statement 95 116 81.9
branch 18 28 64.2
condition 5 9 55.5
subroutine 22 24 91.6
pod 9 9 100.0
total 149 186 80.1


line stmt bran cond sub pod time code
1             # RDF::Query::Algebra::Triple
2             # -----------------------------------------------------------------------------
3              
4             =head1 NAME
5              
6             RDF::Query::Algebra::Triple - Algebra class for Triple patterns
7              
8             =head1 VERSION
9              
10             This document describes RDF::Query::Algebra::Triple version 2.918.
11              
12             =cut
13              
14             package RDF::Query::Algebra::Triple;
15              
16 36     36   130 use strict;
  36         45  
  36         852  
17 36     36   119 use warnings;
  36         45  
  36         2225  
18 36     36   150 no warnings 'redefine';
  36         40  
  36         1023  
19 36     36   127 use base qw(RDF::Query::Algebra RDF::Trine::Statement);
  36         46  
  36         2727  
20              
21 36     36   143 use Data::Dumper;
  36         44  
  36         1304  
22 36     36   145 use Log::Log4perl;
  36         46  
  36         271  
23 36     36   1289 use Scalar::Util qw(refaddr);
  36         57  
  36         1427  
24 36     36   131 use Carp qw(carp croak confess);
  36         45  
  36         1584  
25 36     36   137 use Scalar::Util qw(blessed reftype refaddr);
  36         37  
  36         1358  
26 36     36   132 use Time::HiRes qw(gettimeofday tv_interval);
  36         43  
  36         215  
27 36     36   3184 use RDF::Trine::Iterator qw(smap sgrep swatch);
  36         42  
  36         2426  
28              
29             ######################################################################
30              
31             our ($VERSION);
32             my %TRIPLE_LABELS;
33             my @node_methods = qw(subject predicate object);
34             BEGIN {
35 36     36   27837 $VERSION = '2.918';
36             }
37              
38             ######################################################################
39              
40             =head1 METHODS
41              
42             Beyond the methods documented below, this class inherits methods from the
43             L<RDF::Query::Algebra> class.
44              
45             =over 4
46              
47             =cut
48              
49             =item C<new ( $s, $p, $o )>
50              
51             Returns a new Triple structure.
52              
53             =cut
54              
55             sub new {
56 529     529 1 3363 my $class = shift;
57 529         668 my @nodes = @_;
58 529         752 foreach my $i (0 .. 2) {
59 1587 50       2203 unless (defined($nodes[ $i ])) {
60 0         0 $nodes[ $i ] = RDF::Query::Node::Variable->new($node_methods[ $i ]);
61             }
62 1587 100 66     7375 if (blessed($nodes[ $i ]) and not($nodes[ $i ]->isa('RDF::Query::Node'))) {
63 6 50       13 if ($nodes[ $i ]->isa('RDF::Trine::Node')) {
    0          
64 6         14 $nodes[ $i ] = RDF::Query::Node->from_trine( $nodes[ $i ] );
65             } elsif ($nodes[ $i ]->does('Attean::API::TermOrVariable')){
66 0         0 $nodes[ $i ] = RDF::Query::Node->from_attean( $nodes[ $i ] );
67             }
68             }
69             }
70 529         1033 return $class->_new( @nodes );
71             }
72              
73             sub _new {
74 721     721   750 my $class = shift;
75 721         2388 return $class->SUPER::new( @_ );
76             }
77              
78             =item C<< as_sparql >>
79              
80             Returns the SPARQL string for this algebra expression.
81              
82             =cut
83              
84             sub as_sparql {
85 111     111 1 117 my $self = shift;
86 111         108 my $context = shift;
87 111         103 my $indent = shift;
88            
89 111         230 my $pred = $self->predicate;
90 111 100 100     827 if ($pred->isa('RDF::Trine::Node::Resource') and $pred->uri_value eq 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type') {
91 7         51 $pred = 'a';
92             } else {
93 104         699 $pred = $pred->as_sparql( $context );
94             }
95            
96 111         315 my $subj = $self->subject->as_sparql( $context );
97 111         716 my $obj = $self->object->as_sparql( $context );
98 111         1073 my $string = sprintf(
99             "%s %s %s .",
100             $subj,
101             $pred,
102             $obj,
103             );
104 111         345 return $string;
105             }
106              
107             =item C<< as_hash >>
108              
109             Returns the query as a nested set of plain data structures (no objects).
110              
111             =cut
112              
113             sub as_hash {
114 0     0 1 0 my $self = shift;
115 0         0 my $context = shift;
116             return {
117             type => lc($self->type),
118 0         0 nodes => [ map { $_->as_hash } $self->nodes ],
  0         0  
119             };
120             }
121              
122             =item C<< as_spin ( $model ) >>
123              
124             Adds statements to the given model to represent this algebra object in the
125             SPARQL Inferencing Notation (L<http://www.spinrdf.org/>).
126              
127             =cut
128              
129             sub as_spin {
130 0     0 1 0 my $self = shift;
131 0         0 my $model = shift;
132 0         0 my $spin = RDF::Trine::Namespace->new('http://spinrdf.org/spin#');
133 0         0 my $t = RDF::Query::Node::Blank->new();
134 0         0 my @nodes = $self->nodes;
135 0         0 foreach (@nodes) {
136 0 0 0     0 if (blessed($_) and $_->isa('RDF::Trine::Node::Variable')) {
137 0         0 $_ = RDF::Query::Node::Blank->new( "variable_" . $_->name );
138             }
139             }
140            
141 0         0 $model->add_statement( RDF::Trine::Statement->new($t, $spin->subject, $nodes[0]) );
142 0         0 $model->add_statement( RDF::Trine::Statement->new($t, $spin->predicate, $nodes[1]) );
143 0         0 $model->add_statement( RDF::Trine::Statement->new($t, $spin->object, $nodes[2]) );
144 0         0 return $t;
145             }
146              
147             =item C<< referenced_blanks >>
148              
149             Returns a list of the blank node names used in this algebra expression.
150              
151             =cut
152              
153             sub referenced_blanks {
154 338     338 1 374 my $self = shift;
155 338         956 my @nodes = $self->nodes;
156 338 50       1286 my @blanks = grep { Carp::confess Dumper($_) unless blessed($_); $_->isa('RDF::Trine::Node::Blank') } @nodes;
  1014         2077  
  1014         2922  
157 338         620 return map { $_->blank_identifier } @blanks;
  66         172  
158             }
159              
160             =item C<< subsumes ( $pattern ) >>
161              
162             Returns true if the triple subsumes the pattern, false otherwise.
163              
164             =cut
165              
166             sub subsumes {
167 15     15 1 1110 my $self = shift;
168 15         15 my $pattern = shift;
169 15 50       37 return 0 unless ($pattern->isa('RDF::Trine::Statement'));
170 15         17 foreach my $method (@node_methods) {
171 38         179 my $snode = $self->$method();
172 38 100       181 next if ($snode->isa('RDF::Trine::Node::Variable'));
173 27         38 my $pnode = $pattern->$method();
174 27 100       117 next if ($snode->equal( $pnode ));
175 6         6128 return 0;
176             }
177 9         36 return 1;
178             }
179              
180             =item C<< bf () >>
181              
182             Returns a string representing the state of the nodes of the triple (bound or free).
183              
184             =cut
185              
186             sub bf {
187 24     24 1 28 my $self = shift;
188 24         36 my $bf = '';
189 24         58 foreach my $n ($self->nodes) {
190 72 100       251 $bf .= ($n->isa('RDF::Query::Node::Variable'))
191             ? 'f'
192             : 'b';
193             }
194 24         150 return $bf;
195             }
196              
197             =item C<< distinguish_bnode_variables >>
198              
199             Returns a new Quad object with blank nodes replaced by distinguished variables.
200              
201             =cut
202              
203             sub distinguish_bnode_variables {
204 284     284 1 296 my $self = shift;
205 284         320 my $class = ref($self);
206 284         581 my @nodes = $self->nodes;
207 284         1123 foreach my $i (0 .. $#nodes) {
208 852 100       2578 if ($nodes[$i]->isa('RDF::Query::Node::Blank')) {
209 38         91 $nodes[$i] = $nodes[$i]->make_distinguished_variable;
210             }
211             }
212 284         625 return $class->new( @nodes );
213             }
214              
215             sub _from_sse {
216 2     2   3 my $class = shift;
217 2         7 return RDF::Trine::Statement->from_sse( @_ );
218             }
219              
220             =item C<< label ( $label => $value ) >>
221              
222             Sets the named C<< $label >> to C<< $value >> for this triple object.
223             If no C<< $value >> is given, returns the current label value, or undef if none
224             exists.
225              
226             =cut
227              
228             sub label {
229 3     3 1 4 my $self = shift;
230 3         5 my $addr = refaddr($self);
231 3         3 my $label = shift;
232 3 50       6 if (@_) {
233 0         0 my $value = shift;
234 0         0 $TRIPLE_LABELS{ $addr }{ $label } = $value;
235             }
236 3 50       6 if (exists $TRIPLE_LABELS{ $addr }) {
237 0         0 return $TRIPLE_LABELS{ $addr }{ $label };
238             } else {
239 3         9 return;
240             }
241             }
242              
243             sub DESTROY {
244 746     746   12715 my $self = shift;
245 746         1169 my $addr = refaddr( $self );
246 746         2330 delete $TRIPLE_LABELS{ $addr };
247             }
248              
249             1;
250              
251             __END__
252              
253             =back
254              
255             =head1 AUTHOR
256              
257             Gregory Todd Williams <gwilliams@cpan.org>
258              
259             =cut