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.915_01.
11              
12             =cut
13              
14             package RDF::Query::Algebra::Triple;
15              
16 36     36   178 use strict;
  36         72  
  36         894  
17 36     36   176 use warnings;
  36         65  
  36         2745  
18 36     36   191 no warnings 'redefine';
  36         68  
  36         1223  
19 36     36   249 use base qw(RDF::Query::Algebra RDF::Trine::Statement);
  36         70  
  36         3636  
20              
21 36     36   185 use Data::Dumper;
  36         66  
  36         1697  
22 36     36   180 use Log::Log4perl;
  36         57  
  36         343  
23 36     36   1626 use Scalar::Util qw(refaddr);
  36         60  
  36         1841  
24 36     36   204 use Carp qw(carp croak confess);
  36         70  
  36         1988  
25 36     36   177 use Scalar::Util qw(blessed reftype refaddr);
  36         68  
  36         1944  
26 36     36   186 use Time::HiRes qw(gettimeofday tv_interval);
  36         67  
  36         239  
27 36     36   3785 use RDF::Trine::Iterator qw(smap sgrep swatch);
  36         75  
  36         3363  
28              
29             ######################################################################
30              
31             our ($VERSION);
32             my %TRIPLE_LABELS;
33             my @node_methods = qw(subject predicate object);
34             BEGIN {
35 36     36   39696 $VERSION = '2.915_01';
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 5598 my $class = shift;
57 529         1085 my @nodes = @_;
58 529         1096 foreach my $i (0 .. 2) {
59 1587 50       3461 unless (defined($nodes[ $i ])) {
60 0         0 $nodes[ $i ] = RDF::Query::Node::Variable->new($node_methods[ $i ]);
61             }
62 1587 100 66     11928 if (blessed($nodes[ $i ]) and not($nodes[ $i ]->isa('RDF::Query::Node'))) {
63 6 50       18 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         1572 return $class->_new( @nodes );
71             }
72              
73             sub _new {
74 719     719   1068 my $class = shift;
75 719         3097 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 168 my $self = shift;
86 109         144 my $context = shift;
87 109         157 my $indent = shift;
88            
89 109         328 my $pred = $self->predicate;
90 109 100 100     1092 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         63 $pred = 'a';
92             } else {
93 102         820 $pred = $pred->as_sparql( $context );
94             }
95            
96 109         422 my $subj = $self->subject->as_sparql( $context );
97 109         966 my $obj = $self->object->as_sparql( $context );
98 109         1429 my $string = sprintf(
99             "%s %s %s .",
100             $subj,
101             $pred,
102             $obj,
103             );
104 109         437 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 498 my $self = shift;
155 336         1217 my @nodes = $self->nodes;
156 336 50       1812 my @blanks = grep { Carp::confess Dumper($_) unless blessed($_); $_->isa('RDF::Trine::Node::Blank') } @nodes;
  1008         3179  
  1008         4109  
157 336         942 return map { $_->blank_identifier } @blanks;
  66         246  
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 444 my $self = shift;
168 15         20 my $pattern = shift;
169 15 50       56 return 0 unless ($pattern->isa('RDF::Trine::Statement'));
170 15         25 foreach my $method (@node_methods) {
171 38         262 my $snode = $self->$method();
172 38 100       315 next if ($snode->isa('RDF::Trine::Node::Variable'));
173 27         71 my $pnode = $pattern->$method();
174 27 100       167 next if ($snode->equal( $pnode ));
175 6         9018 return 0;
176             }
177 9         47 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 39 my $self = shift;
188 24         46 my $bf = '';
189 24         77 foreach my $n ($self->nodes) {
190 72 100       400 $bf .= ($n->isa('RDF::Query::Node::Variable'))
191             ? 'f'
192             : 'b';
193             }
194 24         202 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 465 my $self = shift;
205 284         476 my $class = ref($self);
206 284         827 my @nodes = $self->nodes;
207 284         1629 foreach my $i (0 .. $#nodes) {
208 852 100       3994 if ($nodes[$i]->isa('RDF::Query::Node::Blank')) {
209 38         143 $nodes[$i] = $nodes[$i]->make_distinguished_variable;
210             }
211             }
212 284         897 return $class->new( @nodes );
213             }
214              
215             sub _from_sse {
216 2     2   3 my $class = shift;
217 2         11 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         8 my $addr = refaddr($self);
231 3         4 my $label = shift;
232 3 50       8 if (@_) {
233 0         0 my $value = shift;
234 0         0 $TRIPLE_LABELS{ $addr }{ $label } = $value;
235             }
236 3 50       12 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   18836 my $self = shift;
245 744         1729 my $addr = refaddr( $self );
246 744         3517 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