Coverage for oc_ocdm / counter_handler / in_memory_counter_handler.py: 94%

89 statements  

« prev     ^ index     » next       coverage.py v7.13.4, created at 2026-07-06 20:05 +0000

1#!/usr/bin/python 

2 

3# SPDX-FileCopyrightText: 2020-2022 Simone Persiani <iosonopersia@gmail.com> 

4# SPDX-FileCopyrightText: 2024 Arcangelo Massari <arcangelo.massari@unibo.it> 

5# 

6# SPDX-License-Identifier: ISC 

7 

8# -*- coding: utf-8 -*- 

9from __future__ import annotations 

10 

11from typing import TYPE_CHECKING 

12 

13if TYPE_CHECKING: 

14 from typing import Dict, List 

15 

16from oc_ocdm.counter_handler.counter_handler import CounterHandler 

17 

18 

19class InMemoryCounterHandler(CounterHandler): 

20 """A concrete implementation of the ``CounterHandler`` interface that temporarily stores 

21 the counter values in the volatile system memory.""" 

22 

23 def __init__(self) -> None: 

24 """ 

25 Constructor of the ``InMemoryCounterHandler`` class. 

26 """ 

27 self.short_names: List[str] = ["an", "ar", "be", "br", "ci", "de", "id", "pl", "ra", "re", "rp"] 

28 self.prov_short_names: List[str] = ["se"] 

29 self.metadata_short_names: List[str] = ["di"] 

30 self.entity_counters: Dict[str, int] = {key: 0 for key in self.short_names} 

31 self.prov_counters: Dict[str, Dict[str, List[int]]] = { 

32 key1: {key2: [] for key2 in self.prov_short_names} for key1 in self.short_names 

33 } 

34 self.metadata_counters: Dict[str, Dict[str, int]] = {} 

35 

36 def set_counter( 

37 self, 

38 new_value: int, 

39 entity_short_name: str, 

40 prov_short_name: str = "", 

41 identifier: int = 1, 

42 supplier_prefix: str = "", 

43 ) -> None: 

44 """ 

45 It allows to set the counter value of graph and provenance entities. 

46 

47 :param new_value: The new counter value to be set 

48 :type new_value: int 

49 :param entity_short_name: The short name associated either to the type of the entity itself 

50 or, in case of a provenance entity, to the type of the relative graph entity. 

51 :type entity_short_name: str 

52 :param prov_short_name: In case of a provenance entity, the short name associated to the type 

53 of the entity itself. An empty string otherwise. 

54 :type prov_short_name: str 

55 :param identifier: In case of a provenance entity, the counter value that identifies the relative 

56 graph entity. The integer value '1' otherwise. 

57 :type identifier: int 

58 :raises ValueError: if ``new_value`` is a negative integer, ``identifier`` is less than or equal to zero, 

59 ``entity_short_name`` is not a known short name or ``prov_short_name`` is not a known provenance short name. 

60 :return: None 

61 """ 

62 if new_value < 0: 

63 raise ValueError("new_value must be a non negative integer!") 

64 

65 if entity_short_name not in self.short_names: 

66 raise ValueError("entity_short_name is not a known short name!") 

67 

68 if prov_short_name != "": 

69 if prov_short_name not in self.prov_short_names: 

70 raise ValueError("prov_short_name is not a known provenance short name!") 

71 if identifier <= 0: 

72 raise ValueError("identifier must be a positive non-zero integer number!") 

73 

74 identifier -= 1 # Internally we use zero_indexing! 

75 if prov_short_name in self.prov_short_names: 

76 # It's a provenance entity! 

77 missing_counters: int = identifier - (len(self.prov_counters[entity_short_name][prov_short_name]) - 1) 

78 if missing_counters > 0: 

79 self.prov_counters[entity_short_name][prov_short_name] += [0] * missing_counters 

80 self.prov_counters[entity_short_name][prov_short_name][identifier] = new_value 

81 else: 

82 # It's an entity! 

83 self.entity_counters[entity_short_name] = new_value 

84 

85 def read_counter( 

86 self, entity_short_name: str, prov_short_name: str = "", identifier: int = 1, supplier_prefix: str = "" 

87 ) -> int: 

88 """ 

89 It allows to read the counter value of graph and provenance entities. 

90 

91 :param entity_short_name: The short name associated either to the type of the entity itself 

92 or, in case of a provenance entity, to the type of the relative graph entity. 

93 :type entity_short_name: str 

94 :param prov_short_name: In case of a provenance entity, the short name associated to the type 

95 of the entity itself. An empty string otherwise. 

96 :type prov_short_name: str 

97 :param identifier: In case of a provenance entity, the counter value that identifies the relative 

98 graph entity. The integer value '1' otherwise. 

99 :type identifier: int 

100 :raises ValueError: if ``identifier`` is less than or equal to zero, ``entity_short_name`` 

101 is not a known short name or ``prov_short_name`` is not a known provenance short name. 

102 :return: The requested counter value. 

103 """ 

104 if entity_short_name not in self.short_names: 

105 raise ValueError("entity_short_name is not a known short name!") 

106 

107 if prov_short_name != "": 

108 if prov_short_name not in self.prov_short_names: 

109 raise ValueError("prov_short_name is not a known provenance short name!") 

110 if identifier <= 0: 

111 raise ValueError("identifier must be a positive non-zero integer number!") 

112 

113 identifier -= 1 # Internally we use zero_indexing! 

114 if prov_short_name in self.prov_short_names: 

115 # It's a provenance entity! 

116 missing_counters: int = identifier - (len(self.prov_counters[entity_short_name][prov_short_name]) - 1) 

117 if missing_counters > 0: 

118 self.prov_counters[entity_short_name][prov_short_name] += [0] * missing_counters 

119 return self.prov_counters[entity_short_name][prov_short_name][identifier] 

120 else: 

121 # It's an entity! 

122 return self.entity_counters[entity_short_name] 

123 

124 def increment_counter( 

125 self, entity_short_name: str, prov_short_name: str = "", identifier: int = 1, supplier_prefix: str = "" 

126 ) -> int: 

127 """ 

128 It allows to increment the counter value of graph and provenance entities by one unit. 

129 

130 :param entity_short_name: The short name associated either to the type of the entity itself 

131 or, in case of a provenance entity, to the type of the relative graph entity. 

132 :type entity_short_name: str 

133 :param prov_short_name: In case of a provenance entity, the short name associated to the type 

134 of the entity itself. An empty string otherwise. 

135 :type prov_short_name: str 

136 :param identifier: In case of a provenance entity, the counter value that identifies the relative 

137 graph entity. The integer value '1' otherwise. 

138 :type identifier: int 

139 :raises ValueError: if ``identifier`` is less than or equal to zero, ``entity_short_name`` 

140 is not a known short name or ``prov_short_name`` is not a known provenance short name. 

141 :return: The newly-updated (already incremented) counter value. 

142 """ 

143 if entity_short_name not in self.short_names: 

144 raise ValueError("entity_short_name is not a known short name!") 

145 

146 if prov_short_name != "": 

147 if prov_short_name not in self.prov_short_names: 

148 raise ValueError("prov_short_name is not a known provenance short name!") 

149 if identifier <= 0: 

150 raise ValueError("identifier must be a positive non-zero integer number!") 

151 

152 identifier -= 1 # Internally we use zero_indexing! 

153 if prov_short_name in self.prov_short_names: 

154 # It's a provenance entity! 

155 missing_counters: int = identifier - (len(self.prov_counters[entity_short_name][prov_short_name]) - 1) 

156 if missing_counters > 0: 

157 self.prov_counters[entity_short_name][prov_short_name] += [0] * missing_counters 

158 self.prov_counters[entity_short_name][prov_short_name][identifier] += 1 

159 return self.prov_counters[entity_short_name][prov_short_name][identifier] 

160 else: 

161 # It's an entity! 

162 self.entity_counters[entity_short_name] += 1 

163 return self.entity_counters[entity_short_name] 

164 

165 def set_metadata_counter(self, new_value: int, entity_short_name: str, dataset_name: str | None) -> None: 

166 """ 

167 It allows to set the counter value of metadata entities. 

168 

169 :param new_value: The new counter value to be set 

170 :type new_value: int 

171 :param entity_short_name: The short name associated either to the type of the entity itself. 

172 :type entity_short_name: str 

173 :param dataset_name: In case of a ``Dataset``, its name. Otherwise, the name of the relative dataset. 

174 :type dataset_name: str 

175 :raises ValueError: if ``new_value`` is a negative integer, ``dataset_name`` is None or 

176 ``entity_short_name`` is not a known metadata short name. 

177 :return: None 

178 """ 

179 if new_value < 0: 

180 raise ValueError("new_value must be a non negative integer!") 

181 

182 if dataset_name is None: 

183 raise ValueError("dataset_name must be provided!") 

184 

185 if entity_short_name not in self.metadata_short_names: 

186 raise ValueError("entity_short_name is not a known metadata short name!") 

187 

188 if dataset_name not in self.metadata_counters: 

189 self.metadata_counters[dataset_name] = {key: 0 for key in self.metadata_short_names} 

190 

191 self.metadata_counters[dataset_name][entity_short_name] = new_value 

192 

193 def read_metadata_counter(self, entity_short_name: str, dataset_name: str | None) -> int: 

194 """ 

195 It allows to read the counter value of metadata entities. 

196 

197 :param entity_short_name: The short name associated either to the type of the entity itself. 

198 :type entity_short_name: str 

199 :param dataset_name: In case of a ``Dataset``, its name. Otherwise, the name of the relative dataset. 

200 :type dataset_name: str 

201 :raises ValueError: if ``dataset_name`` is None or ``entity_short_name`` is not a known metadata short name. 

202 :return: The requested counter value. 

203 """ 

204 if dataset_name is None: 

205 raise ValueError("dataset_name must be provided!") 

206 

207 if entity_short_name not in self.metadata_short_names: 

208 raise ValueError("entity_short_name is not a known metadata short name!") 

209 

210 if dataset_name not in self.metadata_counters: 

211 return 0 

212 else: 

213 if entity_short_name not in self.metadata_counters[dataset_name]: 

214 return 0 

215 else: 

216 return self.metadata_counters[dataset_name][entity_short_name] 

217 

218 def increment_metadata_counter(self, entity_short_name: str, dataset_name: str | None) -> int: 

219 """ 

220 It allows to increment the counter value of metadata entities by one unit. 

221 

222 :param entity_short_name: The short name associated either to the type of the entity itself. 

223 :type entity_short_name: str 

224 :param dataset_name: In case of a ``Dataset``, its name. Otherwise, the name of the relative dataset. 

225 :type dataset_name: str 

226 :raises ValueError: if ``dataset_name`` is None or ``entity_short_name`` is not a known metadata short name. 

227 :return: The newly-updated (already incremented) counter value. 

228 """ 

229 if dataset_name is None: 

230 raise ValueError("dataset_name must be provided!") 

231 

232 if entity_short_name not in self.metadata_short_names: 

233 raise ValueError("entity_short_name is not a known metadata short name!") 

234 

235 if dataset_name not in self.metadata_counters: 

236 self.metadata_counters[dataset_name] = {key: 0 for key in self.metadata_short_names} 

237 

238 self.metadata_counters[dataset_name][entity_short_name] += 1 

239 return self.metadata_counters[dataset_name][entity_short_name]