aboutsummaryrefslogtreecommitdiffstats
path: root/bsfs/triple_store/sparql/sparql.py
diff options
context:
space:
mode:
Diffstat (limited to 'bsfs/triple_store/sparql/sparql.py')
-rw-r--r--bsfs/triple_store/sparql/sparql.py51
1 files changed, 46 insertions, 5 deletions
diff --git a/bsfs/triple_store/sparql/sparql.py b/bsfs/triple_store/sparql/sparql.py
index 7172f34..c3cbff6 100644
--- a/bsfs/triple_store/sparql/sparql.py
+++ b/bsfs/triple_store/sparql/sparql.py
@@ -15,6 +15,7 @@ from bsfs.query import ast
from bsfs.utils import errors, URI
# inner-module imports
+from . import parse_filter
from .. import base
@@ -86,11 +87,15 @@ class SparqlStore(base.TripleStoreBase):
# The local schema.
_schema: bsc.Schema
+ # Filter parser
+ _filter_parser: parse_filter.Filter
+
def __init__(self):
super().__init__(None)
self._graph = rdflib.Graph()
self._transaction = _Transaction(self._graph)
self._schema = bsc.Schema.Empty()
+ self._filter_parser = parse_filter.Filter(self._schema)
# NOTE: mypy and pylint complain about the **kwargs not being listed (contrasting super)
# However, not having it here is clearer since it's explicit that there are no arguments.
@@ -127,10 +132,17 @@ class SparqlStore(base.TripleStoreBase):
# get deleted classes
sub = self.schema - schema
- # remove predicate instances
for pred in sub.predicates:
+ # remove predicate instances
for src, trg in self._graph.subject_objects(rdflib.URIRef(pred.uri)):
self._transaction.remove((src, rdflib.URIRef(pred.uri), trg))
+ # remove predicate definition
+ if pred.parent is not None:
+ self._transaction.remove((
+ rdflib.URIRef(pred.uri),
+ rdflib.RDFS.subClassOf,
+ rdflib.URIRef(pred.parent.uri),
+ ))
# remove node instances
for node in sub.nodes:
@@ -144,17 +156,46 @@ class SparqlStore(base.TripleStoreBase):
self._transaction.remove((inst, pred, trg))
# remove instance
self._transaction.remove((inst, rdflib.RDF.type, rdflib.URIRef(node.uri)))
-
- # NOTE: Nothing to do for literals
+ # remove node definition
+ if node.parent is not None:
+ self._transaction.remove((
+ rdflib.URIRef(node.uri),
+ rdflib.RDFS.subClassOf,
+ rdflib.URIRef(node.parent.uri),
+ ))
+
+ for lit in sub.literals:
+ # remove literal definition
+ if lit.parent is not None:
+ self._transaction.remove((
+ rdflib.URIRef(lit.uri),
+ rdflib.RDFS.subClassOf,
+ rdflib.URIRef(lit.parent.uri),
+ ))
+
+ # add predicate, node, and literal hierarchies to the graph
+ for itm in itertools.chain(schema.predicates(), schema.nodes(), schema.literals()):
+ if itm.parent is not None:
+ self._transaction.add((rdflib.URIRef(itm.uri), rdflib.RDFS.subClassOf, rdflib.URIRef(itm.parent.uri)))
# commit instance changes
self.commit()
# migrate schema
self._schema = schema
+ self._filter_parser.schema = schema
- def get(self, node_type: bsc.Node, query: ast.filter.FilterExpression) -> typing.Iterator[URI]:
- raise NotImplementedError()
+ def get(
+ self,
+ node_type: bsc.Node,
+ query: typing.Optional[ast.filter.FilterExpression] = None,
+ ) -> typing.Iterator[URI]:
+ if node_type not in self.schema.nodes():
+ raise errors.ConsistencyError(f'{node_type} is not defined in the schema')
+ if not isinstance(query, ast.filter.FilterExpression):
+ raise TypeError(query)
+ for guid, in self._graph.query(self._filter_parser(node_type, query)):
+ yield URI(guid)
def _has_type(self, subject: URI, node_type: bsc.Node) -> bool:
"""Return True if *subject* is a node of class *node_type* or a subclass thereof."""