1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
|
Architecture
============
The BSFS stack can be coarsely divided into four parts (see the image below).
* Envelope: Essentials and utils used throughout the whole codebase.
* Front: End-user applications and APIs.
* Center: The core interfaces and functionality.
* Back: The triple store backends.
Details of these components are given in the sections below.
.. image:: _static/arch_light.png
:class: only-light
.. image:: _static/arch_dark.png
:class: only-dark
Envelope
--------
Most notably, the envelope covers the :class:`Schema <bsfs.schema.schema.Schema>` and the :mod:`Query syntax trees (AST) <bsfs.query.ast>`.
Both of them essential for all parts of the BSFS stack.
For example, the schema is specified by the user via the :func:`Migrate <bsfs.apps.migrate.main>` command, checked and extended by the :class:`Graph <bsfs.graph.graph.Graph>`, and ultimately stored by a :class:`Triple Store backend <bsfs.triple_store.base.TripleStoreBase>`.
Similarly, the Query AST may be provided by a caller and is translated to a database query by a backend.
In addition, the envelope also contains some classes to handle URIs:
:class:`URI <bsfs.utils.uri.URI>` defines the URI base class,
:class:`Namespace <bsfs.namespace.Namespace>` provides shortcuts to generate URIs, and
:mod:`UUID <bsfs.utils.uuid>` is used to generate unique URIs.
Front
-----
The front consists of exposed interfaces such as end-user applications or APIs,
and all utils needed to offer this functionality.
See :mod:`bsfs.apps` and :mod:`bsfs.front`.
Center
------
The heart of BSFS is grouped around the :mod:`bsfs.graph` module.
These classes provide the interface to navigate and manipulate the file graph
in a safe and programmer friendly manner.
Some of them are indirectly exposed through the higher-level APIs.
The two core design principles of BSFS are the focus on nodes and batch processing.
They are realized in the the Graph and Nodes classes.
The :class:`Graph class <bsfs.graph.graph.Graph>` manages the graph as a whole,
and offers methods to get a specific set of Nodes.
In turn, the :class:`Nodes class <bsfs.graph.nodes.Nodes>` represents such a set of nodes,
and performs operations on the whole node set at once.
Besides, the :mod:`bsfs.graph` module also comes with some syntactic sugar.
Example::
# Open a file graph.
from bsfs import Open, ns
graph = Open(...)
# Get all nodes of type File.
nodes = graph.all(ns.bsfs.File)
# Set the author of all nodes at once.
nodes.set(ns.bse.author, 'Myself')
# Retrieve the author of all nodes at once.
set(nodes.get(ns.bse.author, node=False))
# Same as above, but shorter.
set(nodes.comment(node=False))
Back
----
There are various graph databases (e.g., `RDFLib`_, `Blazegraph`_, `Titan`_, etc.)
and it would be foolish to replicate the work that others have done.
Instead, we use third-party stores that take care of how to store and manage the data.
The :class:`Backend base class <bsfs.triple_store.base.TripleStoreBase>` defines the
interface to integrate any such third-party store to BSFS.
Besides storing the data, a triple store backend also need to track the current schema.
.. _RDFLib: https://rdflib.readthedocs.io/en/stable/index.html
.. _Blazegraph: https://blazegraph.com/
.. _Titan: http://titan.thinkaurelius.com/
|