File Coverage

blib/lib/AtteanX/Plan/LDF/Triple.pm
Criterion Covered Total %
statement 26 64 40.6
branch 0 14 0.0
condition n/a
subroutine 9 14 64.2
pod 0 3 0.0
total 35 95 36.8


line stmt bran cond sub pod time code
1             =pod
2              
3             =head1 NAME
4              
5             AtteanX::Plan::LDF::Triple - Plan for evaluation of Linked Data Fragments
6              
7             =head1 SYNOPSIS
8              
9             This is typically only constructed by planning hacks deep in the code,
10             but might look like e.g.:
11              
12             use v5.14;
13             use AtteanX::Plan::LDF::Triple;
14             my $ldf_plan = AtteanX::Plan::LDF::Triple->new(subject => $subject,
15             predicate => $predicate,
16             object => $object);
17              
18              
19             =head1 DESCRIPTION
20              
21             This plan class will aid a query planner that seeks to incorporate
22             Linked Data Fragments into the query planning.
23              
24             =cut
25              
26              
27             package AtteanX::Plan::LDF::Triple;
28             # Most of the code is shamelessly stolen from Attean::API::Quad, since
29             # it has very much in common with that module. Unfortunately, this has
30             # just triple semantics, so it cannot just simply be extended. This
31             # probably implies that the quad plan should be refactored into some
32             # roles.
33              
34 1     1   47365 use v5.14;
  1         2  
35 1     1   3 use warnings;
  1         1  
  1         35  
36              
37             our $AUTHORITY = 'cpan:KJETILK';
38             our $VERSION = '0.02';
39              
40 1     1   3 use Moo;
  1         1  
  1         4  
41 1     1   560 use Class::Method::Modifiers;
  1         1027  
  1         41  
42 1     1   446 use Attean;
  1         796302  
  1         3  
43 1     1   33 use Carp;
  1         1  
  1         45  
44 1     1   5 use Scalar::Util qw(blessed reftype);
  1         0  
  1         33  
45 1     1   4 use namespace::clean;
  1         1  
  1         4  
46              
47             has 'subject' => (is => 'ro', required => 1);
48             has 'predicate' => (is => 'ro', required => 1);
49             has 'object' => (is => 'ro', required => 1);
50              
51             with 'Attean::API::BindingSubstitutionPlan', 'Attean::API::NullaryQueryTree';
52             with 'Attean::API::TriplePattern';
53              
54             around 'BUILDARGS' => sub {
55             my $orig = shift;
56             my $class = shift;
57             my $args = $orig->( $class, @_ );
58             if (exists $args->{in_scope_variables}) {
59             Carp::confess "in_scope_variables is computed automatically, and must not be specified in the $class constructor";
60             }
61            
62             my %vars;
63             foreach my $pos (qw(subject predicate object)) {
64             my $term = $args->{$pos};
65             if (blessed($term) and $term->does('Attean::API::Variable')) {
66             $vars{$term->value} = $term;
67             }
68             }
69            
70             my @vars = keys %vars;
71             $args->{in_scope_variables} = [@vars];
72            
73             return $args;
74             };
75              
76             sub plan_as_string {
77 0     0 0   my $self = shift;
78 0           my @nodes = $self->values;
79 0           my @strings;
80 0           foreach my $t (@nodes) {
81 0 0         if (ref($t) eq 'ARRAY') {
    0          
82 0           my @tstrings = map { $_->ntriples_string } @$t;
  0            
83 0 0         if (scalar(@tstrings) == 1) {
84 0           push(@strings, @tstrings);
85             } else {
86 0           push(@strings, '[' . join(', ', @tstrings) . ']');
87             }
88             } elsif ($t->does('Attean::API::TermOrVariable')) {
89 0           push(@strings, $t->ntriples_string);
90             } else {
91 1     1   348 use Data::Dumper;
  1         2  
  1         281  
92 0           die "Unrecognized node in quad pattern: " . Dumper($t);
93             }
94             }
95 0           return sprintf('LDFTriple { %s }', join(', ', @strings));
96             }
97            
98             sub substitute_impl {
99 0     0 0   my $self = shift;
100 0           my $model = shift;
101 0           my $b = shift;
102 0           my @values = $self->values;
103 0           foreach my $i (0 .. $#values) {
104 0           my $value = $values[$i];
105 0 0         if (reftype($value) eq 'ARRAY') {
    0          
106 0           my @values;
107 0           foreach my $value (@{ $value }) {
  0            
108 0           my $name = $value->value;
109 0 0         if (my $node = $b->value($name)) {
110 0           push(@values, $node);
111             } else {
112 0           push(@values, $value);
113             }
114 0           $values[$i] = \@values;
115             }
116             } elsif ($value->does('Attean::API::Variable')) {
117 0           my $name = $value->value;
118 0 0         if (my $node = $b->value($name)) {
119 0           $values[$i] = $node;
120             }
121             }
122             }
123            
124             return sub {
125 0     0     return $model->get_bindings( @values );
126             }
127 0           }
128              
129             sub impl {
130 0     0 0   my $self = shift;
131 0           my $model = shift;
132 0           my @values = $self->values;
133             return sub {
134 0     0     return $model->get_bindings( @values );
135             }
136 0           }
137              
138              
139             1;