OdbDesignLib
OdbDesign ODB++ Parsing Library
MiscInfoFile.cpp
1 #include "MiscInfoFile.h"
2 #include "MiscInfoFile.h"
3 //
4 // Created by nmill on 10/13/2023.
5 //
6 
7 #include <fstream>
8 #include "MiscInfoFile.h"
9 #include <string>
10 #include <sstream>
11 #include "str_utils.h"
12 #include "../../Constants.h"
13 #include "timestamp.h"
14 #include "Logger.h"
15 #include "../parse_error.h"
16 #include "../invalid_odb_error.h"
17 
18 using namespace std::chrono;
19 
20 namespace Odb::Lib::FileModel::Design
21 {
22  bool MiscInfoFile::Parse(std::filesystem::path path)
23  {
24  std::ifstream infoFile;
25  int lineNumber = 0;
26  std::string line;
27 
28  try
29  {
30  if (!OdbFile::Parse(path))
31  {
32  auto message = "\"misc\" directory does not exist: [" + path.string() + "]";
33  throw invalid_odb_error(message);
34  }
35 
36  auto infoFilePath = path / "info";
37  if (!std::filesystem::exists(infoFilePath))
38  {
39  auto message = "misc/info file does not exist: [" + infoFilePath.string() + "]";
40  throw invalid_odb_error(message);
41  }
42 
43  infoFile.open(infoFilePath, std::ios::in);
44  if (!infoFile.is_open())
45  {
46  auto message = "unable to open misc/info file: [" + infoFilePath.string() + "]";
47  throw invalid_odb_error(message);
48  }
49 
50  while (std::getline(infoFile, line))
51  {
52  lineNumber++;
53 
54  // trim whitespace from beginning and end of line
55  Utils::str_trim(line);
56  if (!line.empty())
57  {
58  std::stringstream lineStream(line);
59  if (line.find(Constants::COMMENT_TOKEN) == 0)
60  {
61  // comment line
62  }
63  else
64  {
65  // attribute line
66  std::string attribute;
67  std::string value;
68 
69  if (!std::getline(lineStream, attribute, '=')) return false;
70  // attribute value may be blank?
71 
72  if (!std::getline(lineStream, value))
73  {
74  if (!attributeValueIsOptional(attribute))
75  {
76  logwarn("misc/info file: no value for non-optional attribute: " + attribute);
77  }
78  }
79 
80  Utils::str_trim(attribute);
81  Utils::str_trim(value);
82 
83  if (attribute == "PRODUCT_MODEL_NAME" ||
84  attribute == "product_model_name")
85  {
86  m_productModelName = value;
87  }
88  else if (attribute == "JOB_NAME" ||
89  attribute == "job_name")
90  {
91  m_jobName = value;
92  }
93  else if (attribute == "odb_version_major" ||
94  attribute == "ODB_VERSION_MAJOR")
95  {
96  m_odbVersionMajor = value;
97  }
98  else if (attribute == "odb_version_minor" ||
99  attribute == "ODB_VERSION_MINOR")
100  {
101  m_odbVersionMinor = value;
102  }
103  else if (attribute == "odb_source" ||
104  attribute == "ODB_SOURCE")
105  {
106  m_odbSource = value;
107  }
108  else if (attribute == "creation_date" ||
109  attribute == "CREATION_DATE")
110  {
111  //std::istringstream iss(value);
113  //iss >> std::chrono::parse("%Y%m%d.%H%M%S", m_creationDateDate);
114  m_creationDateDate = Utils::parse_timestamp(value, "%Y%m%d.%H%M%S");
115 
116 #if defined(_DEBUG)
117 
118  auto createdDate = Utils::make_timestamp(m_creationDateDate);
119  std::stringstream ss;
120  ss << "value: " << value << ", parsed createdDate: " << createdDate;
121  loginfo(ss.str());
122 #endif // _DEBUG
123  }
124  else if (attribute == "save_date" ||
125  attribute == "SAVE_DATE")
126  {
128  //std::istringstream(value) >> std::chrono::parse("%Y%m%d.%H%M%S", m_saveDate);
129  m_saveDate = Utils::parse_timestamp(value, "%Y%m%d.%H%M%S");
130 #if defined(_DEBUG)
131  auto saveDate = Utils::make_timestamp(m_saveDate);
132 
133  std::stringstream ss;
134  ss << "value: " << value << ", parsed saveDate: " << saveDate;
135  loginfo(ss.str());
136 #endif // _DEBUG
137  }
138  else if (attribute == "save_app" ||
139  attribute == "SAVE_APP")
140  {
141  m_saveApp = value;
142  }
143  else if (attribute == "save_user" ||
144  attribute == "SAVE_USER")
145  {
146  m_saveUser = value;
147  }
148  else if (attribute == "units" ||
149  attribute == "UNITS")
150  {
151  m_units = value;
152  }
153  else if (attribute == "max_uid" ||
154  attribute == "MAX_UID")
155  {
156  m_maxUniqueId = std::stoi(value);
157  }
158  else
159  {
160  // unknown attribute
161 
162  // DO NOT fail parsing on unknown attributes- log instead
163  //return false;
164 
165  parse_info pi(m_path, line, attribute, lineNumber);
166  logwarn(pi.toString("unrecognized line in misc/info file:"));
167  }
168  }
169  }
170  }
171 
172  infoFile.close();
173  }
174  catch (invalid_odb_error& ioe)
175  {
176  parse_info pi(m_path, line, lineNumber);
177  const auto m = pi.toString();
178  logexception_msg(ioe, m);
179  // cleanup file
180  infoFile.close();
181  throw ioe;
182  }
183  catch (std::exception& e)
184  {
185  parse_info pi(m_path, line, lineNumber);
186  const auto m = pi.toString();
187  logexception_msg(e, m);
188  // cleanup file
189  infoFile.close();
190  throw e;
191  }
192 
193  return true;
194  }
195 
196  bool MiscInfoFile::Save(std::ostream& os)
197  {
198  os << PRODUCT_MODEL_NAME_KEY << "=" << m_productModelName << std::endl;
199  os << JOB_NAME_KEY << "=" << m_jobName << std::endl;
200  os << ODB_VERSION_MAJOR_KEY << "=" << m_odbVersionMajor << std::endl;
201  os << ODB_VERSION_MINOR_KEY << "=" << m_odbVersionMinor << std::endl;
202  os << ODB_SOURCE_KEY << "=" << m_odbSource << std::endl;
203  os << CREATION_DATE_KEY << "=" << Utils::make_timestamp(m_creationDateDate) << std::endl;
204  os << SAVE_DATE_KEY << "=" << Utils::make_timestamp(m_saveDate) << std::endl;
205  os << SAVE_APP_KEY << "=" << m_saveApp << std::endl;
206  os << SAVE_USER_KEY << "=" << m_saveUser << std::endl;
207  os << UNITS_KEY << "=" << m_units << std::endl;
208  os << MAX_UID_KEY << "=" << m_maxUniqueId << std::endl;
209 
210  return true;
211  }
212 
213  /*static*/ inline bool MiscInfoFile::attributeValueIsOptional(const std::string& attribute)
214  {
215  for (const auto& optionalAttribute : OPTIONAL_ATTRIBUTES)
216  {
217  if (attribute == optionalAttribute)
218  {
219  return true;
220  }
221  }
222  return false;
223  }
224 
225  std::unique_ptr<Odb::Lib::Protobuf::MiscInfoFile> MiscInfoFile::to_protobuf() const
226  {
227  std::unique_ptr<Odb::Lib::Protobuf::MiscInfoFile> pMiscInfoFileMessage(new Odb::Lib::Protobuf::MiscInfoFile);
228  pMiscInfoFileMessage->set_jobname(m_jobName);
229  pMiscInfoFileMessage->set_productmodelname(m_productModelName);
230  pMiscInfoFileMessage->set_odbversionmajor(m_odbVersionMajor);
231  pMiscInfoFileMessage->set_odbversionminor(m_odbVersionMinor);
232  pMiscInfoFileMessage->set_odbsource(m_odbSource);
233  auto seconds = std::chrono::duration_cast<std::chrono::seconds>(m_creationDateDate.time_since_epoch()).count();
234  pMiscInfoFileMessage->mutable_creationdatedate()->set_seconds(seconds);
235  pMiscInfoFileMessage->mutable_creationdatedate()->set_nanos(0);
236  seconds = std::chrono::duration_cast<std::chrono::seconds>(m_saveDate.time_since_epoch()).count();
237  pMiscInfoFileMessage->mutable_savedate()->set_seconds(seconds);
238  pMiscInfoFileMessage->mutable_savedate()->set_nanos(0);
239  pMiscInfoFileMessage->set_saveapp(m_saveApp);
240  pMiscInfoFileMessage->set_saveuser(m_saveUser);
241  pMiscInfoFileMessage->set_units(m_units);
242  pMiscInfoFileMessage->set_maxuniqueid(m_maxUniqueId);
243  return pMiscInfoFileMessage;
244  }
245 
246  void MiscInfoFile::from_protobuf(const Odb::Lib::Protobuf::MiscInfoFile& message)
247  {
248  m_jobName = message.jobname();
249  m_productModelName = message.productmodelname();
250  m_odbVersionMajor = message.odbversionmajor();
251  m_odbVersionMinor = message.odbversionminor();
252  m_odbSource = message.odbsource();
253  //m_creationDateDate = system_clock::from_time_t(message.creationdatedate().seconds());
254  m_creationDateDate = std::chrono::system_clock::time_point(std::chrono::seconds(message.creationdatedate().seconds()));
255  m_saveDate = std::chrono::system_clock::time_point(std::chrono::seconds(message.savedate().seconds()));
256  m_saveApp = message.saveapp();
257  m_saveUser = message.saveuser();
258  m_units = message.units();
259  m_maxUniqueId = message.maxuniqueid();
260  }
261 
262  MiscInfoFile::MiscInfoFile()
263  : m_maxUniqueId((unsigned int)-1)
264  {
265  }
266 
267  std::string MiscInfoFile::GetProductModelName() const
268  {
269  return m_productModelName;
270  }
271 
272  std::string MiscInfoFile::GetJobName() const
273  {
274  return m_jobName;
275  }
276 
277  std::string MiscInfoFile::GetOdbVersionMajor() const
278  {
279  return m_odbVersionMajor;
280  }
281 
282  std::string MiscInfoFile::GetOdbVersionMinor() const
283  {
284  return m_odbVersionMinor;
285  }
286 
287  std::string MiscInfoFile::GetOdbSource() const
288  {
289  return m_odbSource;
290  }
291 
292  system_clock::time_point MiscInfoFile::GetCreationDate() const
293  {
294  return m_creationDateDate;
295  }
296 
297  system_clock::time_point MiscInfoFile::GetSaveDate() const
298  {
299  return m_saveDate;
300  }
301 
302  std::string MiscInfoFile::GetSaveApp() const
303  {
304  return m_saveApp;
305  }
306 
307  std::string MiscInfoFile::GetSaveUser() const
308  {
309  return m_saveUser;
310  }
311 
312  std::string MiscInfoFile::GetUnits() const
313  {
314  return m_units;
315  }
316 
317  unsigned int MiscInfoFile::GetMaxUniqueId() const
318  {
319  return m_maxUniqueId;
320  }
321 }