OdbDesignLib
OdbDesign ODB++ Parsing Library
FileArchive.cpp
1 #include "FileArchive.h"
2 #include <filesystem>
3 #include "ArchiveExtractor.h"
4 #include "MiscInfoFile.h"
5 #include <iostream>
6 #include "Logger.h"
7 #include "StopWatch.h"
8 
9 using namespace Utils;
10 using namespace std::filesystem;
11 
12 namespace Odb::Lib::FileModel::Design
13 {
14 
15  FileArchive::FileArchive(std::string path)
16  : m_filePath(path)
17  {
18  }
19 
20  FileArchive::~FileArchive()
21  {
22  m_stepsByName.clear();
23  m_symbolsDirectoriesByName.clear();
24  }
25 
26  std::string FileArchive::GetRootDir() const
27  {
28  return m_rootDir;
29  }
30 
31  std::string FileArchive::GetProductName() const
32  {
33  return m_productName;
34  }
35 
36  std::string FileArchive::GetFilePath() const
37  {
38  return m_filePath;
39  }
40 
41  std::string FileArchive::GetFilename() const
42  {
43  //return m_filename;
44  return path(m_filePath).filename().string();
45  }
46 
47  const StepDirectory::StringMap& FileArchive::GetStepsByName() const
48  {
49  return m_stepsByName;
50  }
51 
52  const SymbolsDirectory::StringMap& FileArchive::GetSymbolsDirectoriesByName() const
53  {
54  return m_symbolsDirectoriesByName;
55  }
56 
57  bool FileArchive::ParseFileModel()
58  {
59  //try
60  {
61  StopWatch timer(true);
62 
63  if (!exists(m_filePath)) return false;
64 
65  if (is_regular_file(m_filePath))
66  {
67  std::filesystem::path extractedPath;
68  if (!ExtractDesignArchive(m_filePath, extractedPath))
69  {
70  logerror("failed to extract archive: (" + m_filePath + ")");
71  return false;
72  }
73 
74  m_rootDir = findRootDir(extractedPath);
75  }
76 
77  if (is_directory(m_rootDir))
78  {
79  loginfo("Parsing... ");
80 
81  if (ParseDesignDirectory(m_rootDir))
82  {
83  timer.stop();
84  auto s = timer.getElapsedSecondsString();
85  loginfo("Successfully parsed. (" + s + "s)");
86 
87  return true;
88  }
89  else
90  {
91  logerror("Parsing failed.");
92  throw std::runtime_error("Parsing failed.");
93  }
94  }
95  else
96  {
97  logerror("Failed to find root directory");
98  }
99  }
100  //catch (std::exception& e)
101  //{
102  // logexception(e);
103  // throw e;
104  //}
105 
106  return false;
107  }
108 
109  bool FileArchive::ExtractDesignArchive(const std::filesystem::path& path, std::filesystem::path& extractedPath)
110  {
111  loginfo("Extracting... ");
112 
113  if (!Utils::ArchiveExtractor::IsArchiveTypeSupported(path))
114  {
115  logerror("Unsupported archive type: (" + path.string() + ")");
116  return false;
117  }
118 
119  Utils::ArchiveExtractor extractor(path.string());
120  if (!extractor.Extract()) return false;
121 
122  auto extracted = std::filesystem::path(extractor.GetExtractionDirectory());
123  if (!exists(extracted)) return false;
124 
125  extractedPath = extracted;
126 
127  loginfo("Successfully extracted.");
128 
129  return true;
130 
131  }
132 
133  /*static*/ std::string FileArchive::findRootDir(const path& extractedPath)
134  {
135  if (pathContainsTopLevelDesignDirs(extractedPath))
136  {
137  return extractedPath.string();
138  }
139  else
140  {
141  for (const auto& p : directory_iterator(extractedPath))
142  {
143  if (is_directory(p))
144  {
145  if (pathContainsTopLevelDesignDirs(p.path()))
146  {
147  return p.path().string();
148  }
149  }
150  }
151 
152  return "";
153  }
154  }
155 
156  /*static*/ bool FileArchive::pathContainsTopLevelDesignDirs(const std::filesystem::path& path)
157  {
158  for (const auto& topLevelRootDirName : TOPLEVEL_DESIGN_DIR_NAMES)
159  {
160  auto rootLevelDirPath = path / topLevelRootDirName;
161  if (!exists(rootLevelDirPath)) return false;
162  }
163  return true;
164  }
165 
166  std::unique_ptr<Odb::Lib::Protobuf::FileArchive> FileArchive::to_protobuf() const
167  {
168  std::unique_ptr<Odb::Lib::Protobuf::FileArchive> pFileArchiveMessage(new Odb::Lib::Protobuf::FileArchive);
169  pFileArchiveMessage->set_productname(m_productName);
170  pFileArchiveMessage->set_filename(m_filename);
171  pFileArchiveMessage->mutable_matrixfile()->CopyFrom(*m_matrixFile.to_protobuf());
172  pFileArchiveMessage->mutable_miscinfofile()->CopyFrom(*m_miscInfoFile.to_protobuf());
173  pFileArchiveMessage->mutable_standardfontsfile()->CopyFrom(*m_standardFontsFile.to_protobuf());
174  pFileArchiveMessage->mutable_miscattrlistfile()->CopyFrom(*m_miscAttrListFile.to_protobuf());
175 
176  for (const auto& kvStepDirectoryRecord : m_stepsByName)
177  {
178  (*pFileArchiveMessage->mutable_stepsbyname())[kvStepDirectoryRecord.first] = *kvStepDirectoryRecord.second->to_protobuf();
179  }
180 
181  for (const auto& kvSymbolsDirectory : m_symbolsDirectoriesByName)
182  {
183  (*pFileArchiveMessage->mutable_symbolsdirectoriesbyname())[kvSymbolsDirectory.first] = *kvSymbolsDirectory.second->to_protobuf();
184  }
185 
186  return pFileArchiveMessage;
187  }
188 
189  void FileArchive::from_protobuf(const Odb::Lib::Protobuf::FileArchive& message)
190  {
191  m_productName = message.productname();
192  m_filename = message.filename();
193  m_matrixFile.from_protobuf(message.matrixfile());
194  m_miscInfoFile.from_protobuf(message.miscinfofile());
195  m_standardFontsFile.from_protobuf(message.standardfontsfile());
196  m_miscAttrListFile.from_protobuf(message.miscattrlistfile());
197 
198  for (const auto& kvStepDirectoryRecord : message.stepsbyname())
199  {
200  auto pStepDirectory = std::make_shared<StepDirectory>("");
201  pStepDirectory->from_protobuf(kvStepDirectoryRecord.second);
202  m_stepsByName[kvStepDirectoryRecord.first] = pStepDirectory;
203  }
204 
205  for (const auto& kvSymbolsDirectory : message.symbolsdirectoriesbyname())
206  {
207  auto pSymbolsDirectory = std::make_shared<SymbolsDirectory>("");
208  pSymbolsDirectory->from_protobuf(kvSymbolsDirectory.second);
209  m_symbolsDirectoriesByName[kvSymbolsDirectory.first] = pSymbolsDirectory;
210  }
211  }
212 
213  bool FileArchive::ParseDesignDirectory(const std::filesystem::path& path)
214  {
215  if (!exists(path)) return false;
216  else if (!is_directory(path)) return false;
217 
218  m_productName = path.stem().string();
219 
220  if (! ParseStepDirectories(path)) return false;
221  if (! ParseMiscInfoFile(path)) return false;
222  if (! ParseMatrixFile(path)) return false;
223  if (! ParseStandardFontsFile(path)) return false;
224  if (! ParseSymbolsDirectories(path)) return false;
225  if (! ParseMiscAttrListFile(path)) return false;
226 
227  return true;
228  }
229 
230  bool FileArchive::ParseStepDirectories(const std::filesystem::path& path)
231  {
232  loginfo("Parsing steps...");
233 
234  auto stepsPath = path / "steps";
235  for (auto& d : directory_iterator(stepsPath))
236  {
237  if (is_directory(d))
238  {
239  auto pStep = std::make_shared<StepDirectory>(d.path());
240  if (pStep->Parse())
241  {
242  m_stepsByName[pStep->GetName()] = pStep;
243  }
244  else
245  {
246  logwarn("Failed to parse step: " + pStep->GetName());
247  //return false;
248  }
249  }
250  }
251 
252  loginfo("Parsing steps complete");
253 
254  return true;
255  }
256 
257  bool FileArchive::ParseMiscInfoFile(const path& path)
258  {
259  loginfo("Parsing misc/info file...");
260 
261  auto miscDirectory = path / "misc";
262  if (!exists(miscDirectory)) return false;
263  if (!is_directory(miscDirectory)) return false;
264 
265  if (!m_miscInfoFile.Parse(miscDirectory)) return false;
266 
267  loginfo("Parsing misc/info file complete");
268 
269  return true;
270  }
271 
272  bool FileArchive::ParseMiscAttrListFile(const std::filesystem::path& path)
273  {
274  loginfo("Parsing misc/attrlist file...");
275 
276  auto miscDirectory = path / "misc";
277  if (!exists(miscDirectory)) return false;
278  if (!is_directory(miscDirectory)) return false;
279 
280  if (!m_miscAttrListFile.Parse(miscDirectory)) return false;
281 
282  loginfo("Parsing misc/attrlist file complete");
283 
284  return true;
285  }
286 
287  bool FileArchive::ParseMatrixFile(const std::filesystem::path& path)
288  {
289  loginfo("Parsing matrix/matrix file...");
290 
291  auto matrixDir = path / "matrix";
292  if (!exists(matrixDir)) return false;
293  if (!is_directory(matrixDir)) return false;
294 
295  if (!m_matrixFile.Parse(matrixDir)) return false;
296 
297  loginfo("Parsing matrix/matrix file complete");
298 
299  return true;
300  }
301  bool FileArchive::ParseStandardFontsFile(const std::filesystem::path& path)
302  {
303  loginfo("Parsing fonts/standard file...");
304 
305  auto fontsDir = path / "fonts";
306  if (!exists(fontsDir)) return false;
307  if (!is_directory(fontsDir)) return false;
308 
309  if (!m_standardFontsFile.Parse(fontsDir)) return false;
310 
311  loginfo("Parsing fonts/standard file complete");
312 
313  return true;
314  }
315 
316  bool FileArchive::ParseSymbolsDirectories(const std::filesystem::path& path)
317  {
318  loginfo("Parsing symbols root directory...");
319 
320  auto symbolsDirectory = path / "symbols";
321 
322  if (!std::filesystem::exists(symbolsDirectory))
323  {
324  logwarn("symbols root directory does not exist (" + symbolsDirectory.string() + ")");
325  return true;
326  }
327  else if (!std::filesystem::is_directory(symbolsDirectory))
328  {
329  logerror("symbols root directory exists but is a regular file/not a directory (" + symbolsDirectory.string() + ")");
330  return false;
331  }
332 
333  for (auto& d : std::filesystem::directory_iterator(symbolsDirectory))
334  {
335  if (std::filesystem::is_directory(d))
336  {
337  auto pSymbolsDirectory = std::make_shared<SymbolsDirectory>(d.path());
338  if (pSymbolsDirectory->Parse())
339  {
340  //loginfo("Parsing symbols directory: " + pSymbolsDirectory->GetName() + " complete");
341 
342  m_symbolsDirectoriesByName[pSymbolsDirectory->GetName()] = pSymbolsDirectory;
343  }
344  else
345  {
346  logerror("Parsing symbol directory: " + pSymbolsDirectory->GetName() + " failed");
347  return false;
348  }
349  }
350  }
351 
352  loginfo("Parsing symbols root directory complete");
353 
354  return true;
355  }
356 
357  const MiscInfoFile &FileArchive::GetMiscInfoFile() const
358  {
359  return m_miscInfoFile;
360  }
361 
362  const MatrixFile& FileArchive::GetMatrixFile() const
363  {
364  return m_matrixFile;
365  }
366 
367  const StandardFontsFile& FileArchive::GetStandardFontsFile() const
368  {
369  return m_standardFontsFile;
370  }
371 
372  const AttrListFile& FileArchive::GetMiscAttrListFile() const
373  {
374  return m_miscAttrListFile;
375  }
376 
377  std::shared_ptr<StepDirectory> FileArchive::GetStepDirectory(const std::string& stepName /*= ""*/) const
378  {
379  std::shared_ptr<FileModel::Design::StepDirectory> pStepDirectory;
380 
381  const auto& steps = GetStepsByName();
382  if (!steps.empty())
383  {
384  if (stepName.empty())
385  {
386  // return first step
387  pStepDirectory = steps.begin()->second;
388  }
389  else
390  {
391  auto findIt = steps.find(stepName);
392  if (findIt != steps.end())
393  {
394  pStepDirectory = findIt->second;
395  }
396  }
397  }
398 
399  return pStepDirectory;
400  }
401 }