3Implements the backend to manage the content sensor keys on disk.
5\author Bertram Richter, Xiaoli Song
10from datetime
import datetime
17 Handle reading JSON files (userProperties.json and gageSegment.json) from keyfile folders located
18 in activated or deactivated directories. Also reads and updates the metadata.json file.
20 def __init__(self, activated_path, deactivated_path):
22 Initialize the FolderContent with paths for activated and deactivated keyfile directories.
23 \param activated_path (str): The path to the directory containing activated keyfiles.
24 \param deactivated_path (str): The path to the directory containing deactivated keyfiles.
31 Read the content of the userProperties.json file from the specified key's folder.
32 The method checks if the key's folder exists in the activated or deactivated directories,
33 and attempts to load the 'userProperties.json' file from within the folder.
34 \param key (str): The name of the key to locate its corresponding key file folder.
35 \return (dict or None): A dictionary containing the parsed JSON data, or None if the file does not exist.
37 keyfile_path_act = os.path.join(self.
activated_path, key,
'userProperties.json')
38 keyfile_path_deact = os.path.join(self.
deactivated_path, key,
'userProperties.json')
39 if os.path.exists(keyfile_path_act):
41 elif os.path.exists(keyfile_path_deact):
48 Read the content of the gageSegment.json file from the specified key's keyfile folder.
49 Similar to `read_user_properties`, this method checks if the key's keyfile folder exists in the activated or
50 deactivated directories and attempts to load the 'gageSegment.json' file from within the folder.
51 \param key (str): The name of the key to locate its corresponding key file folder.
52 \return (dict or None): A dictionary containing the parsed JSON data, or None if the file does not exist.
54 keyfile_path_act = os.path.join(self.
activated_path, key,
'gageSegment.json')
55 keyfile_path_deact = os.path.join(self.
deactivated_path, key,
'gageSegment.json')
56 if os.path.exists(keyfile_path_act):
58 elif os.path.exists(keyfile_path_deact):
65 Read the first line of the .od6ref file from the specified key's keyfile folder.
66 \param key (str): The name of the key to locate its corresponding folder.
67 \return (dict or None): A dictionary containing the parsed JSON data, or None if the file does not exist.
69 keyfile_path_act = os.path.join(self.
activated_path, key, f
'{key}.od6ref')
70 keyfile_path_deact = os.path.join(self.
deactivated_path, key, f
'{key}.od6ref')
71 if os.path.exists(keyfile_path_act):
73 elif os.path.exists(keyfile_path_deact):
80 Load and parse a JSON file from within a key file.
81 \param file_path (str): The path to the JSON or binary file.
82 \return (dict or None): A dictionary containing the parsed JSON data, or None if the file could not be read.
85 with open(file_path,
'rb')
as file:
88 first_line = file.readline().strip()
89 return json.loads(first_line)
90 except json.JSONDecodeError:
92 except Exception
as e:
93 print(f
"Error reading JSON from {file_path}: {e}")
98 Full-text search inside all JSON files.
99 \param search_term (str): The term to search within the JSON files.
100 \param keyfile (str or None): The specific key for keyfile to search within. If None, search in all keyfile folders.
101 \return (list of tuples): A list of (keyfile name, matching content) tuples where the search term was found.
105 if not os.path.exists(directory):
108 folder_path = os.path.join(directory, keyfile)
109 if os.path.exists(folder_path)
and os.path.isdir(folder_path):
112 results.append(result)
114 for folder_name
in os.listdir(directory):
115 folder_path = os.path.join(directory, folder_name)
116 if os.path.isdir(folder_path):
119 results.append(result)
124 Search inside a key file folder for the given search term in the JSON files.
125 \param folder_path (str): The path to the key file.
126 \param search_term (str): The term to search for.
127 \return (tuple or None): The serial number and matching content if the search term is found, None otherwise.
130 keyfile = os.path.basename(folder_path)
132 for file_name
in os.listdir(folder_path):
133 if file_name.endswith(
".json"):
134 file_path = os.path.join(folder_path, file_name)
135 with open(file_path,
'r', encoding=
'utf-8')
as file:
137 data = json.load(file)
140 all_matches.extend(result)
141 except json.JSONDecodeError:
144 return keyfile, all_matches
145 except Exception
as e:
146 print(f
"Error reading folder {folder_path}: {e}")
151 Recursively search through a JSON for the search term, case-insensitive, with partial matching.
152 \param data (dict or list): The JSON data to search through.
153 \param search_term (str): The term to search for.
154 \return (list): A list of matching key-value pairs if the search term is found, otherwise an empty list.
156 search_term_lower = search_term.lower()
158 if isinstance(data, dict):
159 for key, value
in data.items():
160 key_str = str(key).lower()
161 if search_term_lower
in key_str:
162 matches.append({key: value})
163 if isinstance(value, (str, int, float, bool)):
164 value_str = str(value).lower()
165 if search_term_lower
in value_str:
166 matches.append({key: value})
167 elif isinstance(value, (dict, list)):
169 elif isinstance(data, list):
176 Retrieve the lastEditDate from the userProperties.json file of the specified key's ZIP file.
177 \param key (str): The name of the key to locate its corresponding ZIP file.
178 \return (datetime or None): The lastEditDate as a datetime object, or None if not found or not valid.
182 last_edit_date_str = user_properties.get(
'lastEditDate')
183 if last_edit_date_str:
185 return datetime.strptime(last_edit_date_str,
"%a %b %d %Y")
186 except ValueError
as e:
187 print(f
"Error parsing date: {e}")
193 Read the userSensorName from the userProperties.json file in the specified key's folder.
194 \param key (str): The name of the key to locate its corresponding folder.
195 \return (str or None): The value of userSensorName if it exists, or None otherwise.
199 return user_properties.get(
"userSensorName",
None)
205 Edit the userSensorName for a specified key in the userProperties.json file and synchronize the lastEditDate.
206 \param key (str): The key whose userSensorName needs to be updated.
207 \param new_sensor_name (str): The new sensor name to set.
208 \return (bool): True if the update was successful, False otherwise.
210 keyfile_path_act = os.path.join(self.
activated_path, key,
'userProperties.json')
211 keyfile_path_deact = os.path.join(self.
deactivated_path, key,
'userProperties.json')
212 json_file_path = keyfile_path_act
if os.path.exists(keyfile_path_act)
else keyfile_path_deact
213 if not json_file_path:
214 print(f
"No userProperties.json found for key: {key}")
217 with open(json_file_path,
'r', encoding=
'utf-8')
as file:
218 first_line = file.readline().strip()
219 user_properties = json.loads(first_line)
220 user_properties[
"userSensorName"] = new_sensor_name
221 user_properties[
"lastEditDate"] = datetime.now().strftime(
"%a %b %d %Y")
222 with open(json_file_path,
'w', encoding=
'utf-8')
as file:
223 file.write(json.dumps(user_properties, ensure_ascii=
False))
225 except (json.JSONDecodeError, IOError)
as e:
230 Read the "sensorLength (m)" value from the .od6ref file in the specified key's folder.
231 \param key (str): The name of the key to locate its corresponding folder.
232 \return (float or None): The value of "sensorLength (m)" if it exists, or None otherwise.
236 return od6ref_data.get(
"sensorDataProcParams", {}).get(
"sensorLength (m)",
None)
242 Read the content of the metadata.json file from the specified key file.
244 \param key: The name of the key to locate its corresponding folder.
245 \return: A dictionary containing the parsed JSON data, or an empty dict if the file does not exist.
247 keyfile_path_act = os.path.join(self.
activated_path, key,
"metadata.json")
248 keyfile_path_deact = os.path.join(self.
deactivated_path, key,
"metadata.json")
250 file_path = keyfile_path_act
if os.path.exists(keyfile_path_act)
else keyfile_path_deact
251 if file_path
and os.path.exists(file_path):
253 with open(file_path,
"r", encoding=
"utf-8")
as file:
254 return json.load(file)
255 except json.JSONDecodeError:
256 print(f
"Error: Could not decode JSON in {file_path}")
262 Update the metadata.json for a given key (serial number).
264 \param key: The name of the key to locate its corresponding folder.
265 \param metadata: Dictionary to save.
267 keyfile_path_act = os.path.join(self.
activated_path, key,
"metadata.json")
268 keyfile_path_deact = os.path.join(self.
deactivated_path, key,
"metadata.json")
270 file_path = keyfile_path_act
if os.path.exists(keyfile_path_act)
else keyfile_path_deact
272 if file_path
and os.path.exists(file_path):
274 with open(file_path,
"w", encoding=
"utf-8")
as f:
275 json.dump(metadata, f, indent=4, ensure_ascii=
False)
276 except Exception
as e:
277 print(f
"Failed to save metadata for '{key}': {e}")
Handle reading JSON files (userProperties.json and gageSegment.json) from keyfile folders located in ...
read_user_properties(self, key)
Read the content of the userProperties.json file from the specified key's folder.
full_text_search(self, search_term, keyfile=None)
Full-text search inside all JSON files.
read_sensor_length_for_key(self, key)
Read the "sensorLength (m)" value from the .od6ref file in the specified key's folder.
search_in_json(self, data, search_term)
Recursively search through a JSON for the search term, case-insensitive, with partial matching.
read_od6ref_file(self, key)
Read the first line of the .od6ref file from the specified key's keyfile folder.
read_gage_segment(self, key)
Read the content of the gageSegment.json file from the specified key's keyfile folder.
get_last_edit_date(self, key)
Retrieve the lastEditDate from the userProperties.json file of the specified key's ZIP file.
search_in_folder(self, folder_path, search_term)
Search inside a key file folder for the given search term in the JSON files.
read_metadata(self, key)
Read the content of the metadata.json file from the specified key file.
edit_sensor_name_for_key(self, key, new_sensor_name)
Edit the userSensorName for a specified key in the userProperties.json file and synchronize the lastE...
update_metadata(self, key, metadata)
Update the metadata.json for a given key (serial number).
load_json(self, file_path)
Load and parse a JSON file from within a key file.
__init__(self, activated_path, deactivated_path)
Initialize the FolderContent with paths for activated and deactivated keyfile directories.
read_sensor_name_for_key(self, key)
Read the userSensorName from the userProperties.json file in the specified key's folder.