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