OdbDesignLib
OdbDesign ODB++ Parsing Library
AttrListFile.cpp
1 //
2 // Created by nmill on 10/13/2023.
3 //
4 
5 #include "AttrListFile.h"
6 #include <string>
7 #include <fstream>
8 #include "../parse_error.h"
9 #include "../invalid_odb_error.h"
10 #include "Logger.h"
11 #include "str_utils.h"
12 #include "../../Constants.h"
13 #include <ArchiveExtractor.h>
14 
15 namespace Odb::Lib::FileModel::Design
16 {
17  AttrListFile::AttrListFile()
18  : m_directory("")
19  , m_path("")
20  , m_units("")
21  {
22  }
23 
24  std::string AttrListFile::GetUnits() const
25  {
26  return m_units;
27  }
28 
29  const AttrListFile::AttributeMap& AttrListFile::GetAttributes() const
30  {
31  return m_attributesByName;
32  }
33 
34  bool Lib::FileModel::Design::AttrListFile::Parse(std::filesystem::path directory)
35  {
36  std::ifstream attrListFile;
37  int lineNumber = 0;
38  std::string line;
39 
40  try
41  {
42  m_directory = directory;
43 
44  loginfo("checking for extraction...");
45 
46  std::filesystem::path attrListFilePath;
47  for (const std::string attrListFilename : ATTRLIST_FILENAMES)
48  {
49  loginfo("trying attrlist file: [" + attrListFilename + "]...");
50 
51  attrListFilePath = Utils::ArchiveExtractor::getUncompressedFilePath(m_directory, attrListFilename);
52  if (exists(attrListFilePath) && is_regular_file(attrListFilePath))
53  {
54  loginfo("found attrlist file: [" + attrListFilePath.string() + "]");
55  break;
56  }
57  }
58 
59  m_path = attrListFilePath;
60 
61  loginfo("any extraction complete, parsing data...");
62 
63  if (!std::filesystem::exists(m_path))
64  {
65  auto message = "attrlist file does not exist: [" + m_directory.string() + "]";
66  logwarn(message);
67  return true;
68  //throw invalid_odb_error(message.c_str());
69  }
70  else if (!std::filesystem::is_regular_file(m_path))
71  {
72  auto message = "attrlist is not a file: [" + m_path.string() + "]";
73  throw invalid_odb_error(message.c_str());
74  }
75 
76  attrListFile.open(m_path.string(), std::ios::in);
77  if (!attrListFile.is_open())
78  {
79  auto message = "unable to open attrlist file: [" + m_path.string() + "]";
80  throw invalid_odb_error(message.c_str());
81  }
82 
83  while (std::getline(attrListFile, line))
84  {
85  lineNumber++;
86 
87  // trim whitespace from beginning and end of line
88  Utils::str_trim(line);
89  if (!line.empty())
90  {
91  std::stringstream lineStream(line);
92  //char firstChar = line[0];
93 
94  if (line.find(Constants::COMMENT_TOKEN) == 0)
95  {
96  // comment line
97  }
98  else if (line.find(Constants::UNITS_TOKEN) == 0)
99  {
100  // units line
101  std::string token;
102  if (!std::getline(lineStream, token, '='))
103  {
104  throw_parse_error(m_path, line, token, lineNumber);
105  }
106  else if (!std::getline(lineStream, token, '='))
107  {
108  throw_parse_error(m_path, line, token, lineNumber);
109  }
110 
111  m_units = token;
112  }
113  else
114  {
115  // attribute line
116  std::string attribute;
117  std::string value;
118 
119  if (!std::getline(lineStream, attribute, '='))
120  {
121  throw_parse_error(m_path, line, "", lineNumber);
122  }
123 
124  if (!std::getline(lineStream, value))
125  {
126  if (!attributeValueIsOptional(attribute))
127  {
128  logwarn("attrlist file: no value for non-optional attribute: " + attribute);
129  }
130 
131  }
132 
133  Utils::str_trim(attribute);
134  Utils::str_trim(value);
135 
136  m_attributesByName[attribute] = value;
137  }
138  }
139  }
140 
141  attrListFile.close();
142  }
143  catch (parse_error& pe)
144  {
145  auto m = pe.toString("Parse Error:");
146  logerror(m);
147  attrListFile.close();
148  throw pe;
149  }
150  catch (std::exception& e)
151  {
152  parse_info pi(m_path, line, lineNumber);
153  const auto m = pi.toString();
154  logexception_msg(e, m);
155  attrListFile.close();
156  throw e;
157  }
158 
159  return true;
160  }
161 
162  std::unique_ptr<Odb::Lib::Protobuf::AttrListFile> Lib::FileModel::Design::AttrListFile::to_protobuf() const
163  {
164  auto message = std::make_unique<Odb::Lib::Protobuf::AttrListFile>();
165 
166  message->set_directory(m_directory.string());
167  message->set_path(m_path.string());
168  message->set_units(m_units);
169 
170  for (const auto& kvAttribute : m_attributesByName)
171  {
172  (*message->mutable_attributesbyname())[kvAttribute.first] = kvAttribute.second;
173  }
174 
175  return message;
176 
177  }
178 
179  void Lib::FileModel::Design::AttrListFile::from_protobuf(const Odb::Lib::Protobuf::AttrListFile& message)
180  {
181  m_directory = message.directory();
182  m_path = message.path();
183  m_units = message.units();
184 
185  for (const auto& kvAttribute : message.attributesbyname())
186  {
187  m_attributesByName[kvAttribute.first] = kvAttribute.second;
188  }
189  }
190 
191  bool Lib::FileModel::Design::AttrListFile::attributeValueIsOptional(const std::string& attributeName) const
192  {
193  //for (const auto& optionalAttribute : OPTIONAL_ATTRIBUTES)
194  //{
195  // if (attributeName == optionalAttribute)
196  // {
197  // return true;
198  // }
199  //}
200  //return false;
201 
202  // all atrributes are "optional", i.e. value is not required
203  return true;
204  }
205 
206  bool AttrListFile::Save(std::ostream& os)
207  {
208  os << Constants::UNITS_TOKEN << " = " << m_units << std::endl;
209  for (const auto& kvAttribute : m_attributesByName)
210  {
211  os << kvAttribute.first << " = " << kvAttribute.second << std::endl;
212  }
213 
214  return true;
215  }
216 } // namespace Odb::Lib::FileModel::Design