has
'stores'
=> (
is
=>
'ro'
,
isa
=> HashRef[ConsumerOf[
'Attean::API::TripleStore'
]],
required
=> 1,
default
=>
sub
{ +{} },
);
sub
size {
my
$self
=
shift
;
my
$count
= 0;
foreach
my
$store
(
values
%{
$self
->stores }) {
$count
+=
$store
->size;
}
return
$count
;
}
sub
count_quads {
my
$self
=
shift
;
my
$iter
=
$self
->get_quads(
@_
);
my
$count
= 0;
while
(
my
$r
=
$iter
->
next
) {
$count
++;
}
return
$count
;
}
sub
count_quads_estimate {
my
$self
=
shift
;
my
(
$s
,
$p
,
$o
,
$g
) =
@_
;
if
(blessed(
$g
) and
$g
->does(
'Attean::API::IRI'
)) {
if
(
my
$store
=
$self
->stores->{
$g
->value }) {
return
$store
->count_quads_estimate(
@_
);
}
else
{
return
0;
}
}
else
{
return
$self
->count_quads(
@_
);
}
}
sub
holds {
my
$self
=
shift
;
return
(
$self
->count_quads_estimate(
@_
) > 0)
}
sub
get_graphs {
my
$self
=
shift
;
my
@graphs
=
map
{ Attean::IRI->new(
$_
) }
keys
%{
$self
->stores };
return
Attean::ListIterator->new(
values
=> \
@graphs
,
item_type
=>
'Attean::API::Term'
);
}
sub
get_quads {
my
$self
=
shift
;
my
@nodes
=
@_
[0..3];
foreach
my
$i
(0..3) {
my
$t
=
$nodes
[
$i
] // Attean::Variable->new();
if
(not(
ref
(
$t
)) or reftype(
$t
) ne
'ARRAY'
) {
$nodes
[
$i
] = [
$t
];
}
}
my
@iters
;
foreach
my
$s
(@{
$nodes
[0] }) {
foreach
my
$p
(@{
$nodes
[1] }) {
foreach
my
$o
(@{
$nodes
[2] }) {
foreach
my
$g
(@{
$nodes
[3] }) {
my
$iter
=
$self
->_get_quads(
$s
,
$p
,
$o
,
$g
);
push
(
@iters
,
$iter
);
}
}
}
}
if
(
scalar
(
@iters
) <= 1) {
return
shift
(
@iters
);
}
else
{
return
Attean::IteratorSequence->new(
iterators
=> \
@iters
,
item_type
=>
$iters
[0]->item_type );
}
}
sub
_get_quads {
my
$self
=
shift
;
my
$s
=
shift
;
my
$p
=
shift
;
my
$o
=
shift
;
my
$g
=
shift
;
if
(blessed(
$g
) and
$g
->does(
'Attean::API::IRI'
)) {
if
(
my
$store
=
$self
->stores->{
$g
->value }) {
my
$iter
=
$store
->get_triples(
$s
,
$p
,
$o
);
return
$iter
->as_quads(
$g
);
}
}
elsif
(blessed(
$g
) and
$g
->does(
'Attean::API::Variable'
)) {
my
@iters
;
while
(
my
(
$g
,
$store
) =
each
%{
$self
->stores }) {
my
$iter
=
$store
->get_triples(
$s
,
$p
,
$o
);
my
$graph
= Attean::IRI->new(
$g
);
my
$quads
=
$iter
->
map
(
sub
{
$_
->as_quad(
$graph
) },
'Attean::API::Quad'
);
push
(
@iters
,
$quads
);
}
my
$iter
= Attean::IteratorSequence->new(
iterators
=> \
@iters
,
item_type
=>
$iters
[0]->item_type );
return
$iter
;
}
else
{
my
$name
= (blessed(
$g
) and
$g
->can(
'as_string'
)) ?
$g
->as_string :
"$g"
;
$self
->
log
->
warn
(
"TripleModel cannot produce quads for non-IRI graph: $name"
);
}
return
Attean::ListIterator->new(
values
=> [],
item_type
=>
'Attean::API::Quad'
);
}
sub
plans_for_algebra {
my
$self
=
shift
;
my
$algebra
=
shift
;
my
$planner
=
shift
;
my
$active_graphs
=
shift
;
my
$default_graphs
=
shift
;
my
@plans
;
if
(
scalar
(
@$active_graphs
) == 1) {
my
$graph
=
$active_graphs
->[0];
if
(
my
$store
=
$self
->stores->{
$graph
->value }) {
if
(
$store
->does(
'Attean::API::CostPlanner'
)) {
push
(
@plans
,
$store
->plans_for_algebra(
$algebra
,
$planner
,
$active_graphs
,
$default_graphs
));
}
}
}
return
@plans
;
}
sub
cost_for_plan {
my
$self
=
shift
;
my
$plan
=
shift
;
foreach
my
$store
(
values
%{
$self
->stores }) {
if
(
$store
->does(
'Attean::API::CostPlanner'
)) {
if
(
defined
(
my
$cost
=
$store
->cost_for_plan(
$plan
,
@_
))) {
return
$cost
;
}
}
}
return
;
}
}
has
'store_constructor'
=> (
is
=>
'ro'
,
isa
=> CodeRef,
required
=> 1);
sub
add_store {
my
$self
=
shift
;
my
$graph
=
shift
;
my
$iri
= blessed(
$graph
) ?
$graph
->value :
$graph
;
my
$store
=
shift
;
die
if
exists
$self
->stores->{
$iri
};
$self
->stores->{
$iri
} =
$store
;
}
sub
create_graph {
my
$self
=
shift
;
my
$graph
=
shift
;
my
$iri
=
$graph
->value;
return
if
exists
$self
->stores->{
$iri
};
my
$store
=
$self
->store_constructor->(
$graph
);
$self
->stores->{
$iri
} =
$store
;
};
sub
drop_graph {
my
$self
=
shift
;
my
$g
=
shift
;
if
(
$g
->does(
'Attean::API::IRI'
)) {
delete
$self
->stores->{
$g
->value };
}
}
}
has
'stores'
=> (
is
=>
'ro'
,
isa
=> HashRef[ConsumerOf[
'Attean::API::MutableTripleStore'
]],
required
=> 1,
default
=>
sub
{ +{} },
);
sub
add_quad {
my
$self
=
shift
;
my
$q
=
shift
;
my
$g
=
$q
->graph;
die
"Cannot add a quad whose graph is not an IRI"
unless
(
$g
->does(
'Attean::API::IRI'
));
my
$v
=
$g
->value;
if
(
my
$store
=
$self
->stores->{
$v
}) {
$store
->add_triple(
$q
->as_triple );
}
else
{
Carp::confess
"No such graph: $v"
;
}
}
sub
remove_quad {
my
$self
=
shift
;
my
$q
=
shift
;
my
$g
=
$q
->graph;
if
(
$g
->does(
'Attean::API::IRI'
)) {
my
$v
=
$g
->value;
if
(
my
$store
=
$self
->stores->{
$v
}) {
$store
->remove_triple(
$q
->as_triple );
}
}
}
sub
create_graph {
die
; }
sub
drop_graph {
my
$self
=
shift
;
my
$g
=
shift
;
if
(
$g
->does(
'Attean::API::IRI'
)) {
delete
$self
->stores->{
$g
->value };
}
}
sub
clear_graph {
my
$self
=
shift
;
my
$g
=
shift
;
$self
->drop_graph(
$g
);
$self
->create_graph(
$g
);
}
}
}
}
1;