f403744cb954a48d0ce83515ac525d5951602df9
[nit.git] / lib / neo4j / graph / graph.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # This file is free software, which comes along with NIT. This software is
4 # distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
5 # without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
6 # PARTICULAR PURPOSE. You can modify it is you want, provided this header
7 # is kept unaltered, and a notification of the changes is added.
8 # You are allowed to redistribute it and sell it, alone or is a part of
9 # another product.
10
11 # Provides an interface for services on a Neo4j graphs.
12 module neo4j::graph::graph
13
14 import neo4j
15 import progression
16
17 # A Neo4j graph with a local identification scheme for its nodes.
18 #
19 # An identification scheme can be defined by subclassing `NeoNodeCollection`.
20 #
21 # `GraphStore` can be subclassed to add ways to save or load a graph. The
22 # storing mechanisms may use `nodes.id_of` to identify the nodes in the graph
23 # while encoding the relationships.
24 class NeoGraph
25 # All the nodes in the graph.
26 var nodes: NeoNodeCollection
27
28 # All the relationships in the graph.
29 var edges: SimpleCollection[NeoEdge] = new Array[NeoEdge]
30
31 # Add a new node to the graph and return it.
32 #
33 # Set the local ID of the node before returning it.
34 #
35 # SEE: `NeoNodeCollection.add`
36 # SEE: `NeoNodeCollection.create_node`
37 # SEE: `NeoNodeCollection.register`
38 fun create_node: NeoNode do return nodes.create_node
39 end
40
41 # All the nodes in a `NeoGraph`.
42 #
43 # An identification scheme can be defined throught the `register` and `add`
44 # methods. The `id_property` attribute defines where the local ID (that is the
45 # ID managed by the collection) is stored in each node.
46 abstract class NeoNodeCollection
47 super SimpleCollection[NeoNode]
48
49 # The type of the local IDs.
50 type ID_TYPE: Jsonable
51
52 # The property of the nodes that hold the local ID.
53 var id_property: String
54
55 # Retrieve the node that has the specified local id.
56 #
57 # Note: The default implementation uses `get_or_null`.
58 fun [](id: ID_TYPE): NeoNode do
59 var n = get_or_null(id)
60 assert n isa NeoNode
61 return n
62 end
63
64 # Retrieve the node that has the specified local id, or return `null`.
65 #
66 # Note: The default implementation uses `iterator`.
67 fun get_or_null(id: ID_TYPE): nullable NeoNode do
68 for n in self do
69 if id_of(n) == id then return n
70 end
71 return null
72 end
73
74 # There is a node that has the specified local id?
75 #
76 # Note: The default implementation uses `get_or_null`.
77 fun has_id(id: ID_TYPE): Bool do return get_or_null(id) isa NeoNode
78
79 # Return the local ID of the node.
80 fun id_of(node: NeoNode): ID_TYPE do return node[id_property].as(ID_TYPE)
81
82 # Set the local ID of the specified node.
83 #
84 # Just update the property at `property_id`. Do not check anything.
85 protected fun id_of=(node: NeoNode, id: ID_TYPE) do
86 node[id_property] = id
87 end
88
89 # Add the specified node to the graph and set its local ID.
90 #
91 # SEE: `add`
92 # SEE: `create_node`
93 fun register(node: NeoNode) is abstract
94
95 # Add the specified node to the graph assuming that its local ID is already set.
96 #
97 # SEE: `create_node`
98 # SEE: `register`
99 redef fun add(node: NeoNode) is abstract
100
101 # Add a new node to the graph and return it.
102 #
103 # Set the local ID of the node before returning it.
104 #
105 # SEE: `add`
106 # SEE: `register`
107 fun create_node: NeoNode do
108 var node = new NeoNode
109 register(node)
110 return node
111 end
112
113 # Remove the node with the specified local ID.
114 fun remove_at(id: ID_TYPE) is abstract
115
116 # Remove the specified node.
117 #
118 # The local ID is used instead of `==` to seek the node.
119 fun remove_node(node: NeoNode) do
120 remove_at(id_of(node))
121 end
122
123 redef fun clear do
124 for node in self do remove_node(node)
125 end
126
127 redef fun remove(node: NeoNode) do
128 for n in self do
129 if node == n then
130 remove_node(n)
131 return
132 end
133 end
134 end
135
136 redef fun remove_all(node: NeoNode) do
137 for n in self do
138 if node == n then remove_node(n)
139 end
140 end
141 end
142
143 # A mean to save and load a Neo4j graph.
144 abstract class GraphStore
145 super Trackable
146
147 # The graph to save or load.
148 var graph: NeoGraph
149
150 # Can we save the graph without conflict?
151 fun isolated_save: Bool is abstract
152
153 # Load the graph (or a part of it).
154 #
155 # Do not reset the graph.
156 fun load is abstract
157
158 # Save the graph.
159 fun save do save_part(graph.nodes, graph.edges)
160
161 # Save the specified part of the graph.
162 #
163 # Assume that for each relationship specified, both ends are already saved
164 # or are specified in the same call to this method.
165 fun save_part(nodes: Collection[NeoNode],
166 edges: Collection[NeoEdge]) is abstract
167 end