Skip to content

Commit 4f934ee

Browse files
committed
fix is_node_available
1 parent ca03792 commit 4f934ee

File tree

1 file changed

+36
-29
lines changed

1 file changed

+36
-29
lines changed

stix2/datastore/neo4j/neo4j.py

Lines changed: 36 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -180,8 +180,8 @@ def _insert_sdo_sco_smo(self, obj, type_name):
180180
self.sgraph.create(node)
181181
# check to see if the addition of this node makes it possible to create a relationship
182182
for rel in self.relationships_to_recheck:
183-
self._insert_sro(obj, True)
184-
self._insert_embedded_relationships(obj)
183+
self._insert_sro(rel, True)
184+
self._insert_embedded_relationships(obj, obj["id"])
185185
self._insert_external_references(external_references, node)
186186
self._insert_extensions(extension_relationships, node)
187187
self._insert_sub_objects(self.sub_object_relationships, node)
@@ -190,25 +190,27 @@ def _insert_sub_object(self, sub_prop, sub_obj, parent_node):
190190
node_contents = dict()
191191
node_contents["type"] = sub_prop
192192
for key, value in sub_obj.items():
193-
if isinstance(value, list):
194-
if isinstance(value[0], str):
195-
node_contents[key] = ",".join(value)
196-
elif isinstance(value[0], dict):
197-
for v in value:
198-
self.sub_object_relationships.append((key, v))
199-
elif key == "hashes":
200-
node_contents[key] = hash_dict_as_string(value)
201-
elif not isinstance(value, dict):
202-
node_contents[key] = value
203-
else:
204-
self.sub_object_relationships.append((key, value))
193+
if not key.endswith("ref") and not key.endswith("refs"):
194+
if isinstance(value, list):
195+
if isinstance(value[0], str):
196+
node_contents[key] = ",".join(value)
197+
elif isinstance(value[0], dict):
198+
for v in value:
199+
self.sub_object_relationships.append((key, v))
200+
elif key == "hashes":
201+
node_contents[key] = hash_dict_as_string(value)
202+
elif not isinstance(value, dict):
203+
node_contents[key] = value
204+
else:
205+
self.sub_object_relationships.append((key, value))
205206
node = Node(sub_prop,
206207
name=sub_prop + "_" + self.next_id(),
207208
# bundlesource=self.bundlename,
208209
**node_contents)
209210
self.sgraph.create(node)
210211
relationship = Relationship(parent_node, sub_prop, node)
211212
self.sgraph.create(relationship)
213+
self._insert_embedded_relationships(sub_obj, parent_node["id"])
212214

213215
def _insert_sub_objects(self, sub_objects, parent_node):
214216
for sub in sub_objects:
@@ -238,26 +240,29 @@ def _insert_extensions(self, extensions, parent_node):
238240
type_name = ext.__class__.__name__
239241
node_contents["type"] = type_name
240242
for key, value in ext.items():
241-
if isinstance(value, list):
242-
if isinstance(value[0], str):
243-
node_contents[key] = ",".join(value)
243+
if not key.endswith("ref") and not key.endswith("refs"):
244+
if isinstance(value, list):
245+
if isinstance(value[0], str):
246+
node_contents[key] = ",".join(value)
247+
else:
248+
for v in value:
249+
self.sub_object_relationships.append((key, v))
250+
elif key == "hashes":
251+
node_contents[key] = hash_dict_as_string(value)
244252
else:
245-
for v in value:
246-
self.sub_object_relationships.append((key, v))
247-
elif key == "hashes":
248-
node_contents[key] = hash_dict_as_string(value)
249-
else:
250-
node_contents[key] = value
253+
node_contents[key] = value
251254
node = Node(type_name,
252255
name=type_name + "_" + self.next_id(),
253256
# bundlesource=self.bundlename,
254257
**node_contents)
255258
relationship = Relationship(parent_node, type_name, node)
256259
self.sgraph.create(relationship)
260+
self._insert_embedded_relationships(ext, parent_node["id"])
257261

258262
def _is_node_available(self, id,):
259-
cypher_string = f'OPTIONAL MATCH (a) WHERE a.id="{str(id)}" RETURN a'
260-
return self.sgraph.run(cypher_string)
263+
cypher_string = f'OPTIONAL MATCH (a) WHERE a.id="{str(id)}" UNWIND [a] AS list_rows RETURN list_rows'
264+
cursor = self.sgraph.run(cypher_string).data()
265+
return cursor[0]["list_rows"]
261266

262267
def _insert_sro(self, obj, recheck=False):
263268
reltype = str(obj['relationship_type'])
@@ -270,13 +275,14 @@ def _insert_sro(self, obj, recheck=False):
270275
if self._is_node_available(obj["source_ref"]) and self._is_node_available(obj["target_ref"]):
271276
cypher_string = f'MATCH (a),(b) WHERE a.id="{str(obj["source_ref"])}" AND b.id="{str(obj["target_ref"])}" CREATE (a)-[r:{reltype}]->(b) RETURN a,b'
272277
self.sgraph.run(cypher_string)
278+
print(f'Created {str(obj["source_ref"])} {reltype} {obj["target_ref"]}')
273279
if recheck:
274280
remove_sro_from_list(obj, self.relationships_to_recheck)
275281
else:
276282
if not recheck:
277283
self.relationships_to_recheck.append(obj)
278284

279-
def _insert_embedded_relationships(self, obj, recheck=False):
285+
def _insert_embedded_relationships(self, obj, id, recheck=False):
280286
for k in obj.keys():
281287
k_tokens = k.split("_")
282288
# find refs, but ignore external_references since they aren't objects
@@ -291,15 +297,16 @@ def _insert_embedded_relationships(self, obj, recheck=False):
291297
for ref in ref_list:
292298
if self._is_node_available(ref):
293299
# The "b to a" relationship is reversed in this cypher query to ensure the correct relationship direction in the graph
294-
cypher_string = f'MATCH (a),(b) WHERE a.id="{str(ref)}" AND b.id="{str(obj["id"])}" CREATE (b)-[r:{rel_type}]->(a) RETURN a,b'
300+
cypher_string = f'MATCH (a),(b) WHERE a.id="{str(ref)}" AND b.id="{str(id)}" CREATE (b)-[r:{k}]->(a) RETURN a,b'
295301
self.sgraph.run(cypher_string)
302+
print(f'Created * {str(id)} {k} {str(ref)}')
296303
if recheck:
297304
remove_sro_from_list(obj, self.relationships_to_recheck)
298305
else:
299306
if not recheck:
300-
embedded_relationship = {"source_ref": obj["id"],
307+
embedded_relationship = {"source_ref": id,
301308
"target_ref": ref,
302-
"relationship_type": rel_type}
309+
"relationship_type": k}
303310
self.relationships_to_recheck.append(embedded_relationship)
304311

305312

0 commit comments

Comments
 (0)