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.916.
11              
12             =cut
13              
14             package RDF::Query::Algebra::Triple;
15              
16 36     36   182 use strict;
  36         71  
  36         994  
17 36     36   181 use warnings;
  36         68  
  36         2764  
18 36     36   187 no warnings 'redefine';
  36         71  
  36         1207  
19 36     36   173 use base qw(RDF::Query::Algebra RDF::Trine::Statement);
  36         64  
  36         3672  
20              
21 36     36   201 use Data::Dumper;
  36         62  
  36         1578  
22 36     36   192 use Log::Log4perl;
  36         81  
  36         369  
23 36     36   1606 use Scalar::Util qw(refaddr);
  36         64  
  36         1804  
24 36     36   179 use Carp qw(carp croak confess);
  36         58  
  36         2039  
25 36     36   180 use Scalar::Util qw(blessed reftype refaddr);
  36         64  
  36         1906  
26 36     36   175 use Time::HiRes qw(gettimeofday tv_interval);
  36         69  
  36         258  
27 36     36   3980 use RDF::Trine::Iterator qw(smap sgrep swatch);
  36         82  
  36         3283  
28              
29             ######################################################################
30              
31             our ($VERSION);
32             my %TRIPLE_LABELS;
33             my @node_methods = qw(subject predicate object);
34             BEGIN {
35 36     36   40364 $VERSION = '2.916';
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 6128 my $class = shift;
57 529         1091 my @nodes = @_;
58 529         1143 foreach my $i (0 .. 2) {
59 1587 50       3582 unless (defined($nodes[ $i ])) {
60 0         0 $nodes[ $i ] = RDF::Query::Node::Variable->new($node_methods[ $i ]);
61             }
62 1587 100 66     12174 if (blessed($nodes[ $i ]) and not($nodes[ $i ]->isa('RDF::Query::Node'))) {
63 6 50       23 if ($nodes[ $i ]->isa('RDF::Trine::Node')) {
    0          
64 6         23 $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         1612 return $class->_new( @nodes );
71             }
72              
73             sub _new {
74 719     719   1067 my $class = shift;
75 719         3116 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 109     109 1 179 my $self = shift;
86 109         176 my $context = shift;
87 109         157 my $indent = shift;
88            
89 109         315 my $pred = $self->predicate;
90 109 100 100     1098 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         58 $pred = 'a';
92             } else {
93 102         928 $pred = $pred->as_sparql( $context );
94             }
95            
96 109         438 my $subj = $self->subject->as_sparql( $context );
97 109         893 my $obj = $self->object->as_sparql( $context );
98 109         1373 my $string = sprintf(
99             "%s %s %s .",
100             $subj,
101             $pred,
102             $obj,
103             );
104 109         537 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 336     336 1 514 my $self = shift;
155 336         1235 my @nodes = $self->nodes;
156 336 50       1931 my @blanks = grep { Carp::confess Dumper($_) unless blessed($_); $_->isa('RDF::Trine::Node::Blank') } @nodes;
  1008         3173  
  1008         4150  
157 336         947 return map { $_->blank_identifier } @blanks;
  66         252  
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 471 my $self = shift;
168 15         23 my $pattern = shift;
169 15 50       64 return 0 unless ($pattern->isa('RDF::Trine::Statement'));
170 15         33 foreach my $method (@node_methods) {
171 38         268 my $snode = $self->$method();
172 38 100       327 next if ($snode->isa('RDF::Trine::Node::Variable'));
173 27         72 my $pnode = $pattern->$method();
174 27 100       184 next if ($snode->equal( $pnode ));
175 6         9154 return 0;
176             }
177 9         52 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 44 my $self = shift;
188 24         44 my $bf = '';
189 24         76 foreach my $n ($self->nodes) {
190 72 100       392 $bf .= ($n->isa('RDF::Query::Node::Variable'))
191             ? 'f'
192             : 'b';
193             }
194 24         217 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 432 my $self = shift;
205 284         546 my $class = ref($self);
206 284         883 my @nodes = $self->nodes;
207 284         1682 foreach my $i (0 .. $#nodes) {
208 852 100       4192 if ($nodes[$i]->isa('RDF::Query::Node::Blank')) {
209 38         139 $nodes[$i] = $nodes[$i]->make_distinguished_variable;
210             }
211             }
212 284         881 return $class->new( @nodes );
213             }
214              
215             sub _from_sse {
216 2     2   4 my $class = shift;
217 2         9 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 5 my $self = shift;
230 3         9 my $addr = refaddr($self);
231 3         4 my $label = shift;
232 3 50       9 if (@_) {
233 0         0 my $value = shift;
234 0         0 $TRIPLE_LABELS{ $addr }{ $label } = $value;
235             }
236 3 50       9 if (exists $TRIPLE_LABELS{ $addr }) {
237 0         0 return $TRIPLE_LABELS{ $addr }{ $label };
238             } else {
239 3         13 return;
240             }
241             }
242              
243             sub DESTROY {
244 744     744   19383 my $self = shift;
245 744         1690 my $addr = refaddr( $self );
246 744         3563 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