A Graph is a collection of rdf:Statements.
This is the basic rdflib.graph.Graph with a few added capabilities:
- TODO: type and type implementation handling
- bnode closures
- handy helper methods one() and exists() and distinct_*()
- pointer to any ordf.handler in use.
This is the URI of the resource that the graph can be said to be about.
Sub-classes should set this attribute to a list of URIRef. It isn’t necessary to copy data from parent classes. The basic :class:Graph has:
Sub-classes should set this attribute to a list of inference relationships that are implicit in the nature of their rdf:type
If the instance has been obtained via ordf.handler it will have the :attr:handler set to the handler that obtained it.
Return the BNode closure(s) for triples that are matched by the given “triple”. Any additional positional or keyword arguments are passed to the constructor for the new graph.
Return one matching “triple” or “None”
Return “True” if “triple” exists, “False” otherwise
Return a graph where triple “old” is replaced with triple “new”. Any additional positional or keyword arguments are passed to the constructor for the new graph.
Return a distinct set of subjects. Arguments are as for :meth:subjects
Return a distinct set of predicates. Arguments are as for :meth:predicates
Return a distinct set of objects. Arguments are as for :meth:objects
Various RDF vocabularies benefit from specific support in Python. They are implemented as sublcasses of ordf.graph.Graph.
As well, this is a place to put data and rule fixtures for loading with ordf_load. The functions that should be implemented, rdf_data() and inference_rules(). The former takes no arguments and should return an iterable of graphs to be added to the store. The latter takes two arguments, handler and network where network is an instance of FuXi.Rete.Network.ReteNetwork and its job is to populate the network with inference rules.
An rdf_data() implementation that reads N3 files bundled with the distribution:
from ordf.graph import Graph
import os, pkg_resources
def rdf_data():
graph = Graph(identifier="http://example.org/schema")
fp = pkg_resources.resource_stream("example.vocab",
os.path.join("n3", "example.n3"))
graph.parse(fp, format="n3")
fp.close()
yield graph
An rdf_data() implementation that retrieves a vocabulary from the Internet:
from ordf.graph import Graph
def rdf_data():
graph_uri = "http://purl.org/NET/example/"
graph = Graph(identifier=graph_uri)
graph.parse(graph_uri)
yield graph
Inference rules are slightly more complicated according to whether they are inferred from description logic (e.g. an OWL Ontology) or from hand-written rules in N3. Hand-written rules follow a similar pattern as the first rdf_data() implementation above:
import os, pkg_resources
def inference_rules(handler, network):
from FuXi.Horn.HornRules import HornFromN3
rule_file = pkg_resources.resource_filename("example.vocab",
os.path.join("n3", "example-rules.n3"))
rules = HornFromN3(rule_file)
for rule in rules:
network.buildNetworkFromClause(rule)
return rules
In the case of description logic, it is usually a good idea to make sure the graph exists in the store already, and save it there if it doesn’t:
def inference_rules(handler, network):
from FuXi.DLP.DLNormalization import NormalFormReduction
onto = handler.get("http://example.org/ontology")
if len(onto) == 0:
for onto in rdf_data():
handler.put(onto)
NormalFormReduction(onto)
return network.setupDescriptionLogicProgramming(onto, addPDSemantics=False)
Note that this makes use of rdf_data() that is assumed to be defined in the same module and whose job it is to retrieve the ontology graph from whatever source.
Note also that in both these cases the import from the FuXi package is done within the scope of the function. This is so that if inferencing is not required and FuXi is not installed there will be no ImportError and any rdf_data() fixtures and concrete implementations will still be useable.