File Coverage

blib/lib/RDF/Trine/Model/StatementFilter.pm
Criterion Covered Total %
statement 79 99 79.8
branch 8 18 44.4
condition n/a
subroutine 19 19 100.0
pod 7 7 100.0
total 113 143 79.0


line stmt bran cond sub pod time code
1             # RDF::Trine::Model::StatementFilter
2             # -----------------------------------------------------------------------------
3              
4             =head1 NAME
5              
6             RDF::Trine::Model::StatementFilter - Model for filtering statements based on a user-specified criteria
7              
8             =head1 VERSION
9              
10             This document describes RDF::Trine::Model::StatementFilter version 1.017
11              
12             =head1 METHODS
13              
14             Beyond the methods documented below, this class inherits methods from the
15             L<RDF::Trine::Model> class.
16              
17             =over 4
18              
19             =cut
20              
21             package RDF::Trine::Model::StatementFilter;
22              
23 1     1   497 use strict;
  1         2  
  1         27  
24 1     1   6 use warnings;
  1         2  
  1         26  
25 1     1   5 no warnings 'redefine';
  1         2  
  1         28  
26 1     1   6 use Data::Dumper;
  1         2  
  1         45  
27 1     1   5 use base qw(RDF::Trine::Model);
  1         2  
  1         69  
28 1     1   10 use Scalar::Util qw(blessed reftype);
  1         2  
  1         45  
29              
30 1     1   10 use RDF::Trine::Node;
  1         2  
  1         30  
31 1     1   5 use RDF::Trine::Pattern;
  1         2  
  1         22  
32 1     1   5 use RDF::Trine::Iterator qw(sgrep);
  1         2  
  1         49  
33              
34             our ($VERSION);
35             BEGIN {
36 1     1   218 $VERSION = '1.017';
37             }
38              
39             ################################################################################
40              
41             =item C<< new ( $store ) >>
42              
43             Returns a new statement-filter model.
44              
45             =cut
46              
47             sub new {
48 1     1 1 17 my $class = shift;
49 1         14 my $self = $class->SUPER::new( @_ );
50 1         8 $self->{rules} = [];
51 1         4 return $self;
52             }
53              
54             =item C<< count_statements ($subject, $predicate, $object) >>
55              
56             Returns a count of all the statements matching the specified subject,
57             predicate and objects. Any of the arguments may be undef to match any value.
58              
59             =cut
60              
61             sub count_statements {
62 8     8 1 1339 my $self = shift;
63 8         20 my $s = shift;
64 8         18 my $p = shift;
65 8         15 my $o = shift;
66 8         15 my $c = shift;
67            
68 8         16 my $count = 0;
69 8         33 my $i = $self->get_statements( $s, $p, $o, $c );
70 8         37 while (my $s = $i->next) {
71 24         67 $count++;
72             }
73 8         80 return $count;
74             }
75              
76             =item C<< get_statements ($subject, $predicate, $object [, $context] ) >>
77              
78             Returns a stream object of all statements matching the specified subject,
79             predicate and objects from all of the rdf stores. Any of the arguments may be
80             undef to match any value.
81              
82             =cut
83              
84             sub get_statements {
85 14     14 1 24 my $self = shift;
86 14         28 my $s = shift;
87 14         32 my $p = shift;
88 14         25 my $o = shift;
89 14         26 my $c = shift;
90            
91 14     31   118 my $stream = sgrep { $self->apply_rules($_) } $self->SUPER::get_statements( $s, $p, $o, $c );
  31         99  
92 14         41 return $stream;
93             }
94              
95             =item C<< get_pattern ( $bgp [, $context] ) >>
96              
97             Returns a stream object of all bindings matching the specified graph pattern.
98              
99             =cut
100              
101             sub get_pattern {
102 10     10 1 3152 my $self = shift;
103 10         20 my $bgp = shift;
104 10         22 my $context = shift;
105 10         28 my %args = @_;
106            
107 10 100       38 if (my $o = $args{ orderby }) {
108 5         20 my @ordering = @$o;
109 5         20 while (my ($col, $dir) = splice( @ordering, 0, 2, () )) {
110 1     1   6 no warnings 'uninitialized';
  1         3  
  1         409  
111 7 100       48 unless ($dir =~ /^(ASC|DESC)$/) {
112 1         23 throw RDF::Trine::Error -text => 'Direction must be ASC or DESC in get_pattern call';
113             }
114             }
115             }
116            
117 9         31 my @rules = $self->rules;
118 9 50       30 if (@rules) {
119 0 0       0 my (@triples) = ($bgp->isa('RDF::Trine::Statement')) ? $bgp : $bgp->triples;
120 0 0       0 unless (@triples) {
121 0         0 throw RDF::Trine::Error::CompilationError -text => 'Cannot call get_pattern() with empty pattern';
122             }
123            
124 0         0 my @streams;
125 0         0 foreach my $triple (@triples) {
126 0         0 my @vars = map { $_->name } grep { $_->isa('RDF::Trine::Node::Variable') } $triple->nodes;
  0         0  
  0         0  
127 0 0       0 Carp::confess "not a statement object: " . Dumper($triple) unless ($triple->isa('RDF::Trine::Statement'));
128 0         0 my $stream = $self->get_statements( $triple->nodes, $context );
129 0         0 my $binds = $stream->as_bindings( $triple->nodes )->project( @vars );
130 0         0 push(@streams, $binds);
131             }
132 0 0       0 if (@streams) {
133 0         0 while (@streams > 1) {
134 0         0 my $a = shift(@streams);
135 0         0 my $b = shift(@streams);
136 0         0 unshift(@streams, RDF::Trine::Iterator::Bindings->join_streams( $a, $b ));
137             }
138             } else {
139 0         0 push(@streams, RDF::Trine::Iterator::Bindings->new([{}], []));
140             }
141 0         0 my $stream = shift(@streams);
142 0         0 return $stream;
143             } else {
144 9         58 return $self->SUPER::get_pattern( $bgp, $context, %args );
145             }
146             }
147              
148             =item C<< apply_rules ( $statement ) >>
149              
150             =cut
151              
152             sub apply_rules {
153 31     31 1 54 my $self = shift;
154 31         55 my $st = shift;
155 31         76 my @rules = $self->rules;
156 31         57 foreach my $rule (@rules) {
157 2 100       9 return 0 unless ($rule->( $st ));
158             }
159 30         78 return 1;
160             }
161              
162             =item C<< rules >>
163              
164             Returns a list of all rules in the inferencing model.
165              
166             =cut
167              
168             sub rules {
169 40     40 1 67 my $self = shift;
170 40         61 return @{ $self->{rules} };
  40         103  
171             }
172              
173             =item C<< add_rule ( \&rule ) >>
174              
175             Adds a rule to the inferencing model. The rule should be a CODE reference that,
176             when passed a statement object, will return true if the statement should be
177             allowed in the model, false if it should be filtered out.
178              
179             =cut
180              
181             sub add_rule {
182 1     1 1 3 my $self = shift;
183 1         3 my $rule = shift;
184 1 50       7 throw RDF::Trine::Error -text => "Filter must be a CODE reference" unless (reftype($rule) eq 'CODE');
185 1         3 push( @{ $self->{rules} }, $rule );
  1         4  
186             }
187              
188             1;
189              
190             __END__
191              
192             =back
193              
194             =head1 BUGS
195              
196             Please report any bugs or feature requests to through the GitHub web interface
197             at L<https://github.com/kasei/perlrdf/issues>.
198              
199             =head1 AUTHOR
200              
201             Gregory Todd Williams C<< <gwilliams@cpan.org> >>
202              
203             =head1 COPYRIGHT
204              
205             Copyright (c) 2006-2012 Gregory Todd Williams. This
206             program is free software; you can redistribute it and/or modify it under
207             the same terms as Perl itself.
208              
209             =cut