# RDF::Query::Algebra::Quad # ----------------------------------------------------------------------------- =head1 NAME RDF::Query::Algebra::Quad - Algebra class for Quad patterns =head1 VERSION This document describes RDF::Query::Algebra::Quad version 2.200, released 6 August 2009. =cut package RDF::Query::Algebra::Quad; use strict; use warnings; no warnings 'redefine'; use base qw(RDF::Query::Algebra RDF::Trine::Statement::Quad); use Data::Dumper; use Carp qw(carp croak confess); use Scalar::Util qw(blessed reftype refaddr); use RDF::Trine::Iterator qw(smap sgrep swatch); ###################################################################### my %QUAD_LABELS; our ($VERSION); BEGIN { $VERSION = '2.200'; } ###################################################################### =head1 METHODS =over 4 =cut =item C<< as_sparql >> Returns the SPARQL string for this alegbra expression. =cut sub as_sparql { my $self = shift; my $context = shift || {}; my $indent = shift; my $pred = $self->predicate; if ($pred->isa('RDF::Trine::Node::Resource') and $pred->uri_value eq 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type') { $pred = 'a'; } else { $pred = $pred->as_sparql( $context ); } my $string = sprintf( "%s %s %s .", $self->subject->as_sparql( $context ), $pred, $self->object->as_sparql( $context ), ); return $string; } =item C<< referenced_blanks >> Returns a list of the blank node names used in this algebra expression. =cut sub referenced_blanks { my $self = shift; my @nodes = $self->nodes; my @blanks = grep { $_->isa('RDF::Trine::Node::Blank') } @nodes; return map { $_->blank_identifier } @blanks; } =item C<< qualify_uris ( \%namespaces, $base ) >> Returns a new algebra pattern where all referenced Resource nodes representing QNames (ns:local) are qualified using the supplied %namespaces. =cut sub qualify_uris { my $self = shift; my $class = ref($self); my $ns = shift; my $base = shift; my @nodes; foreach my $n ($self->nodes) { my $blessed = blessed($n); if ($blessed and $n->isa('RDF::Query::Node::Resource')) { my $uri = $n->uri; if (ref($uri)) { my ($n,$l) = @$uri; unless (exists($ns->{ $n })) { throw RDF::Query::Error::QuerySyntaxError -text => "Namespace $n is not defined"; } my $resolved = RDF::Query::Node::Resource->new( join('', $ns->{ $n }, $l), $base ); push(@nodes, $resolved); } else { push(@nodes, $n); } } elsif ($blessed and $n->isa('RDF::Query::Node::Literal')) { my $node = $n; my $dt = $node->literal_datatype; if (ref($dt)) { my ($n,$l) = @$dt; unless (exists($ns->{ $n })) { throw RDF::Query::Error::QuerySyntaxError -text => "Namespace $n is not defined"; } my $resolved = RDF::Query::Node::Resource->new( join('', $ns->{ $n }, $l), $base ); my $lit = RDF::Query::Node::Literal->new( $node->literal_value, undef, $resolved->uri_value ); push(@nodes, $lit); } else { push(@nodes, $node); } } else { push(@nodes, $n); } } return $class->new( @nodes ); } =item C<< bf () >> Returns a string representing the state of the nodes of the triple (bound or free). =cut sub bf { my $self = shift; my $bf = ''; foreach my $n ($self->nodes) { $bf .= ($n->isa('RDF::Query::Node::Variable')) ? 'f' : 'b'; } return $bf; } =item C<< distinguish_bnode_variables >> Returns a new Quad object with blank nodes replaced by distinguished variables. =cut sub distinguish_bnode_variables { my $self = shift; my $class = ref($self); my @nodes = $self->nodes; foreach my $i (0 .. $#nodes) { if ($nodes[$i]->isa('RDF::Query::Node::Blank')) { $nodes[$i] = $nodes[$i]->make_distinguished_variable; } } return $class->new( @nodes ); } =item C<< fixup ( $query, $bridge, $base, \%namespaces ) >> Returns a new pattern that is ready for execution using the given bridge. This method replaces generic node objects with bridge-native objects. =cut sub fixup { my $self = shift; my $class = ref($self); my $query = shift; my $bridge = shift; my $base = shift; my $ns = shift; if (my $opt = $query->algebra_fixup( $self, $bridge, $base, $ns )) { return $opt; } else { my @nodes = $self->nodes; @nodes = map { $bridge->as_native( $_, $base, $ns ) } @nodes; my $fixed = $class->new( @nodes ); return $fixed; } } =item C<< label ( $label => $value ) >> Sets the named C<< $label >> to C<< $value >> for this quad object. If no C<< $value >> is given, returns the current label value, or undef if none exists. =cut sub label { my $self = shift; my $addr = refaddr($self); my $label = shift; if (@_) { my $value = shift; $QUAD_LABELS{ $addr }{ $label } = $value; } if (exists $QUAD_LABELS{ $addr }) { return $QUAD_LABELS{ $addr }{ $label }; } else { return; } } sub DESTROY { my $self = shift; my $addr = refaddr( $self ); delete $QUAD_LABELS{ $addr }; } 1; __END__ =back =head1 AUTHOR Gregory Todd Williams =cut