Skip to content

Commit

Permalink
is_restored
Browse files Browse the repository at this point in the history
  • Loading branch information
arcangelo7 committed Nov 30, 2024
1 parent f3bb089 commit e8c9581
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 9 deletions.
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "rdflib-ocdm"
version = "0.3.12"
version = "0.4.0"
description = ""
authors = ["arcangelo7 <[email protected]>"]
license = "ISC"
Expand Down
27 changes: 21 additions & 6 deletions rdflib_ocdm/ocdm_graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def __init__(self, counter_handler: CounterHandler):
def preexisting_finished(self: Graph|ConjunctiveGraph|OCDMGraphCommons, resp_agent: str = None, primary_source: str = None, c_time: str = None):
self.preexisting_graph = deepcopy(self)
for subject in self.subjects(unique=True):
self.entity_index[subject] = {'to_be_deleted': False, 'resp_agent': resp_agent, 'source': primary_source}
self.entity_index[subject] = {'to_be_deleted': False, 'is_restored': False, 'resp_agent': resp_agent, 'source': primary_source}
self.all_entities.add(subject)
count = self.provenance.counter_handler.read_counter(subject)
if count == 0:
Expand All @@ -79,6 +79,21 @@ def merge(self: Graph|ConjunctiveGraph|OCDMGraphCommons, res: URIRef, other: URI
def mark_as_deleted(self, res: URIRef) -> None:
self.entity_index[res]['to_be_deleted'] = True

def mark_as_restored(self, res: URIRef) -> None:
"""
Marks an entity as being restored after deletion.
This will:
1. Set is_restored flag to True in the entity_index
2. Set to_be_deleted flag to False
:param res: The URI reference of the entity to restore
:type res: URIRef
:return: None
"""
if res in self.entity_index:
self.entity_index[res]['is_restored'] = True
self.entity_index[res]['to_be_deleted'] = False

@property
def merge_index(self) -> dict:
return self.__merge_index
Expand All @@ -90,7 +105,7 @@ def entity_index(self) -> dict:
def generate_provenance(self, c_time: float = None) -> None:
return self.provenance.generate_provenance(c_time)

def get_entity(self, res: str) -> Optional[ProvEntity]:
def get_entity(self, res: str) -> Optional[SnapshotEntity]:
return self.provenance.get_entity(res)

def commit_changes(self):
Expand Down Expand Up @@ -124,7 +139,7 @@ def add(self, triple: "_TripleType", resp_agent = None, primary_source = None):
self.all_entities.add(s)

if s not in self.entity_index:
self.entity_index[s] = {'to_be_deleted': False, 'resp_agent': resp_agent, 'source': primary_source}
self.entity_index[s] = {'to_be_deleted': False, 'is_restored': True, 'resp_agent': resp_agent, 'source': primary_source}

return self

Expand Down Expand Up @@ -268,7 +283,7 @@ def parse(
self.all_entities.add(subject)

if subject not in self.entity_index:
self.entity_index[subject] = {'to_be_deleted': False, 'resp_agent': resp_agent, 'source': primary_source}
self.entity_index[subject] = {'to_be_deleted': False, 'is_restored': True, 'resp_agent': resp_agent, 'source': primary_source}

return self

Expand Down Expand Up @@ -305,7 +320,7 @@ def add(
self.all_entities.add(s)

if s not in self.entity_index:
self.entity_index[s] = {'to_be_deleted': False, 'resp_agent': resp_agent, 'source': primary_source}
self.entity_index[s] = {'to_be_deleted': False, 'is_restored': True, 'resp_agent': resp_agent, 'source': primary_source}

return self

Expand Down Expand Up @@ -378,7 +393,7 @@ def parse(
self.all_entities.add(subject)

if subject not in self.entity_index:
self.entity_index[subject] = {'to_be_deleted': False, 'resp_agent': resp_agent, 'source': primary_source}
self.entity_index[subject] = {'to_be_deleted': False, 'is_restored': True, 'resp_agent': resp_agent, 'source': primary_source}

return context

Expand Down
12 changes: 12 additions & 0 deletions rdflib_ocdm/prov/provenance.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,18 @@ def generate_provenance(self, c_time: float = None) -> None:
cur_snapshot.has_invalidation_time(cur_time)
cur_snapshot.has_description(f"The entity '{str(cur_subj)}' has been deleted.")
cur_snapshot.has_update_action(update_query)
elif cur_subj_metadata['is_restored']:
# RESTORATION SNAPSHOT
last_snapshot: SnapshotEntity = self.add_se(prov_subject=cur_subj, res=last_snapshot_res)
# Non settiamo l'invalidation time per il precedente snapshot in caso di restore

cur_snapshot: SnapshotEntity = self._create_snapshot(cur_subj, cur_time)
cur_snapshot.derives_from(last_snapshot)
cur_snapshot.has_description(f"The entity '{str(cur_subj)}' has been restored.")

update_query: str = get_update_query(self.prov_g, cur_subj)[0]
if update_query:
cur_snapshot.has_update_action(update_query)
else:
if last_snapshot_res is None:
# CREATION SNAPSHOT
Expand Down
41 changes: 40 additions & 1 deletion test/provenance_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ def test_generate_provenance_creation_no_snapshot_modification_ocdm_graph(self):
result = ocdm_graph.generate_provenance(c_time=self.cur_time)
self.assertIsNone(result)
se_a: SnapshotEntity = ocdm_graph.get_entity(f'{self.subject}/prov/se/1')
print(ocdm_graph.get_entity(f'{self.subject}/prov/se/1'))
self.assertIsNotNone(se_a)
self.assertIsInstance(se_a, SnapshotEntity)
self.assertEqual(URIRef(self.subject), se_a.get_is_snapshot_of())
Expand Down Expand Up @@ -124,5 +123,45 @@ def test_generate_provenance_after_merge(self):
self.assertEqual(se_id_0636064270_2.get_description(), "The entity 'https://w3id.org/oc/meta/id/0636064270' has been deleted.")
self.assertEqual(se_id_0636064270_2.get_update_action(), "DELETE DATA { GRAPH <https://w3id.org/oc/meta/id/> { <https://w3id.org/oc/meta/id/0636064270> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://purl.org/spar/datacite/Identifier> . } }")

def test_restore_deleted_entity(self):
# Setup grafo e entità iniziale
ocdm_graph = OCDMGraph()
subject_uri = URIRef(self.subject)
ocdm_graph.add((subject_uri, URIRef('http://purl.org/dc/terms/title'), Literal('Test Title')))
ocdm_graph.preexisting_finished(c_time=self.cur_time)

# Prima otteniamo lo snapshot di creazione
initial_snapshot: SnapshotEntity = ocdm_graph.get_entity(f'{self.subject}/prov/se/1')
self.assertIsNotNone(initial_snapshot)
self.assertEqual(initial_snapshot.get_description(), f"The entity '{self.subject}' has been created.")

# Cancelliamo l'entità e generiamo la provenance
ocdm_graph.mark_as_deleted(subject_uri)
deletion_time = '2020-12-08T21:17:34+00:00'
ocdm_graph.generate_provenance(c_time=1607462254.846196)

# Verifichiamo lo snapshot di cancellazione
deletion_snapshot: SnapshotEntity = ocdm_graph.get_entity(f'{self.subject}/prov/se/2')
self.assertEqual(deletion_snapshot.get_generation_time(), deletion_time)
self.assertEqual(deletion_snapshot.get_invalidation_time(), deletion_time)
self.assertEqual(deletion_snapshot.get_description(), f"The entity '{self.subject}' has been deleted.")

# Ripristiniamo l'entità e aggiungiamo una modifica
ocdm_graph.mark_as_restored(subject_uri)
ocdm_graph.add((subject_uri, URIRef('http://purl.org/dc/terms/title'), Literal('Restored Title')))

# Generiamo la provenance dopo il ripristino
restore_time = '2020-12-09T21:17:34+00:00'
ocdm_graph.generate_provenance(c_time=1607548654.846196)

# Verifichiamo lo snapshot di ripristino
restore_snapshot = ocdm_graph.get_entity(f'{self.subject}/prov/se/3')
self.assertIsNotNone(restore_snapshot)
self.assertEqual(restore_snapshot.get_generation_time(), restore_time)
self.assertIsNone(restore_snapshot.get_invalidation_time())
self.assertEqual(restore_snapshot.get_description(), f"The entity '{self.subject}' has been restored.")
self.assertEqual(restore_snapshot.get_derives_from()[0].res, deletion_snapshot.res)
self.assertIsNotNone(restore_snapshot.get_update_action())

if __name__ == '__main__':
unittest.main()
1 change: 0 additions & 1 deletion test/storer_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,6 @@ def test_upload_all_provenance(self):
self.ts.setQuery(query)
results = self.ts.queryAndConvert()
results = {(result['g']['value'], result['s']['value'], result['p']['value'], result['o']['value']) for result in results['results']['bindings']}
print(results)
expected_result = {
('https://w3id.org/oc/meta/br/0605/prov/', 'https://w3id.org/oc/meta/br/0605/prov/se/2', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type', 'http://www.w3.org/ns/prov#Entity'),
('https://w3id.org/oc/meta/br/0636066666/prov/', 'https://w3id.org/oc/meta/br/0636066666/prov/se/1', 'http://www.w3.org/ns/prov#generatedAtTime', '2020-12-07T21:17:34Z'),
Expand Down

0 comments on commit e8c9581

Please sign in to comment.