Coverage for rdflib_ocdm / counter_handler / filesystem_counter_handler.py: 100%
61 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-03-21 12:35 +0000
« prev ^ index » next coverage.py v7.13.5, created at 2026-03-21 12:35 +0000
1#!/usr/bin/python
3# SPDX-FileCopyrightText: 2016 Silvio Peroni <essepuntato@gmail.com>
4# SPDX-FileCopyrightText: 2023 Arcangelo Massari <arcangelo.massari@unibo.it>
5#
6# SPDX-License-Identifier: ISC
7from __future__ import annotations
9import json
10import os
12from rdflib_ocdm.counter_handler.counter_handler import CounterHandler
13from rdflib_ocdm.support import is_string_empty
16class FilesystemCounterHandler(CounterHandler):
17 """A concrete implementation of the ``CounterHandler`` interface that persistently stores
18 the counter values within the filesystem."""
20 def __init__(self, info_dir: str) -> None:
21 """
22 Constructor of the ``FilesystemCounterHandler`` class.
24 :param info_dir: The path to the folder that does/will contain the counter values.
25 :type info_dir: str
26 :raises ValueError: if ``info_dir`` is None or an empty string.
27 """
28 if info_dir is None or is_string_empty(info_dir):
29 raise ValueError("info_dir parameter is required!")
31 if info_dir[-1] != os.sep:
32 info_dir += os.sep
34 self.info_dir: str = info_dir
35 self.prov_files = dict()
36 self.provenance_index_filename = 'provenance_index.json'
38 def set_counter(self, new_value: int, entity_name: str) -> None:
39 """
40 It allows to set the counter value of provenance entities.
42 :param new_value: The new counter value to be set
43 :type new_value: int
44 :param entity_name: The entity name
45 :type entity_name: str
46 :raises ValueError: if ``new_value`` is a negative integer.
47 :return: None
48 """
49 entity_name = str(entity_name)
50 if new_value < 0:
51 raise ValueError("new_value must be a non negative integer!")
52 file_path: str = self._get_prov_path()
53 self.__initialize_file_if_not_existing(file_path, entity_name)
54 with open(file_path, 'r', encoding='utf8') as file:
55 data = json.load(file)
56 with open(file_path, 'w', encoding='utf8') as outfile:
57 data[entity_name] = new_value
58 json.dump(obj=data, fp=outfile, ensure_ascii=False, indent=False)
60 def read_counter(self, entity_name: str) -> int:
61 """
62 It allows to read the counter value of provenance entities.
64 :param entity_name: The entity name
65 :type entity_name: str
66 :return: The requested counter value.
67 """
68 entity_name = str(entity_name)
69 file_path: str = self._get_prov_path()
70 return self._read_number(file_path, entity_name)
72 def increment_counter(self, entity_name: str) -> int:
73 """
74 It allows to increment the counter value of provenance entities by one unit.
76 :param entity_name: The entity name
77 :type entity_name: str
78 :return: The newly-updated (already incremented) counter value.
79 """
80 entity_name = str(entity_name)
81 file_path: str = self._get_prov_path()
82 return self._add_number(file_path, entity_name)
84 def _get_prov_path(self) -> str:
85 return os.path.join(self.info_dir, self.provenance_index_filename)
87 def __initialize_file_if_not_existing(self, file_path: str, entity_name: str):
88 entity_name = str(entity_name)
89 if not os.path.exists(os.path.dirname(file_path)):
90 os.makedirs(os.path.dirname(file_path))
91 if not os.path.isfile(file_path):
92 with open(file_path, 'w', encoding='utf8') as outfile:
93 json.dump({entity_name: 0}, ensure_ascii=False, indent=None, fp=outfile)
95 def _read_number(self, file_path: str, entity_name: str) -> int:
96 self.__initialize_file_if_not_existing(file_path, entity_name)
97 with open(file_path, 'r', encoding='utf8') as file:
98 data = json.load(file)
99 if entity_name in data:
100 self.prov_files[entity_name] = data[entity_name]
101 else:
102 self.prov_files[entity_name] = 0
103 return self.prov_files[entity_name]
105 def _add_number(self, file_path: str, entity_name: str) -> int:
106 self.__initialize_file_if_not_existing(file_path, entity_name)
107 cur_number = self._read_number(file_path, entity_name)
108 cur_number += 1
109 with open(file_path, 'r', encoding='utf8') as file:
110 data = json.load(file)
111 with open(file_path, 'w', encoding='utf8') as outfile:
112 data[entity_name] = cur_number
113 json_object = json.dumps(data, ensure_ascii=False, indent=None)
114 outfile.write(json_object)
115 return cur_number