]> Creatis software - crea.git/blob - lib/creaDevManagerLib/modelCDMLib.cpp
Feature #1711 CreaDevManager application implementation
[crea.git] / lib / creaDevManagerLib / modelCDMLib.cpp
1 /*
2 # ---------------------------------------------------------------------
3 #
4 # Copyright (c) CREATIS (Centre de Recherche en Acquisition et Traitement de l'Image
5 #                        pour la Sant�)
6 # Authors : Eduardo Davila, Frederic Cervenansky, Claire Mouton
7 # Previous Authors : Laurent Guigues, Jean-Pierre Roux
8 # CreaTools website : www.creatis.insa-lyon.fr/site/fr/creatools_accueil
9 #
10 #  This software is governed by the CeCILL-B license under French law and
11 #  abiding by the rules of distribution of free software. You can  use,
12 #  modify and/ or redistribute the software under the terms of the CeCILL-B
13 #  license as circulated by CEA, CNRS and INRIA at the following URL
14 #  http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
15 #  or in the file LICENSE.txt.
16 #
17 #  As a counterpart to the access to the source code and  rights to copy,
18 #  modify and redistribute granted by the license, users are provided only
19 #  with a limited warranty  and the software's author,  the holder of the
20 #  economic rights,  and the successive licensors  have only  limited
21 #  liability.
22 #
23 #  The fact that you are presently reading this means that you have had
24 #  knowledge of the CeCILL-B license and that you accept its terms.
25 # ------------------------------------------------------------------------
26  */
27
28 /*
29  * modelCDMLib.cpp
30  *
31  *  Created on: Nov 23, 2012
32  *      Author: Daniel Felipe Gonzalez Obando
33  */
34
35 #include "modelCDMLib.h"
36
37 #include <fstream>
38 #include <sstream>
39 #include <algorithm>
40
41 #include "CDMUtilities.h"
42 #include "creaWx.h"
43 #include "wx/dir.h"
44
45 modelCDMLib::modelCDMLib()
46 {
47 }
48
49 modelCDMLib::modelCDMLib(modelCDMIProjectTreeNode* parent, const std::string& path, const std::string& name, const int& level)
50 {
51   std::cout << "creating lib\n";
52   this->parent = parent;
53   this->type = wxDIR_DIRS;
54   this->name = name;
55   this->level = level;
56   this->path = path;
57
58
59
60   this->path = CDMUtilities::fixPath(path);
61   //open makelists file
62   std::string pathFixed(CDMUtilities::fixPath(path));
63
64   this->libraries.clear();
65   wxDir dir(crea::std2wx((pathFixed).c_str()));
66   if (dir.IsOpened())
67     {
68       wxString fileName;
69       //folders
70       bool cont = dir.GetFirst(&fileName, wxEmptyString, wxDIR_DIRS);
71       while (cont)
72         {
73           std::string stdfileName = crea::wx2std(fileName);
74
75           if(stdfileName != "template_lib")
76             {
77               modelCDMLibrary* library = new modelCDMLibrary(this, pathFixed + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1);
78               this->libraries.push_back(library);
79               this->children.push_back(library);
80             }
81           else
82             {
83               modelCDMFolder* folder = new modelCDMFolder(this, pathFixed + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1);
84               this->children.push_back(folder);
85             }
86
87           cont = dir.GetNext(&fileName);
88         }
89       //files
90       cont = dir.GetFirst(&fileName, wxEmptyString, wxDIR_FILES);
91       while (cont)
92         {
93           std::string stdfileName = crea::wx2std(fileName);
94           std::size_t fileTypePos = stdfileName.find_last_of(".");
95           std::string fileType = stdfileName.substr(fileTypePos);
96
97           //if CMakeLists, create CMakeLists
98           if(stdfileName == "CMakeLists.txt")
99             {
100               this->CMakeLists = new modelCDMCMakeListsFile(this, pathFixed + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1);
101               this->children.push_back(this->CMakeLists);
102             }
103           //if is a code file, create modelCDMCodeFile
104           else if(
105               fileType == ".c" ||
106               fileType == ".cxx" ||
107               fileType == ".h" ||
108               fileType == ".cpp" ||
109               fileType == ".txx" ||
110               fileType == ".cmake" )
111             {
112               this->children.push_back(new modelCDMCodeFile(this, pathFixed + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1));
113             }
114           //if is an unknown file, create file
115           else
116             {
117               this->children.push_back(new modelCDMFile(this, pathFixed + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1));
118             }
119
120           cont = dir.GetNext(&fileName);
121         }
122     }
123   this->SortChildren();
124   std::sort(this->libraries.begin(), this->libraries.end(), CompareNodeItem);
125 }
126
127 modelCDMLib::~modelCDMLib()
128 {
129 }
130
131 const std::vector<modelCDMLibrary*>& modelCDMLib::GetLibraries() const
132 {
133   return this->libraries;
134 }
135
136 modelCDMLibrary* modelCDMLib::CreateLibrary(
137     const std::string& namein,
138     std::string*& result
139 )
140 {
141   std::vector<std::string> words;
142   CDMUtilities::splitter::split(words,namein," '/\\*\"%",CDMUtilities::splitter::no_empties);
143   std::string name;
144   for (int i = 0; i < (int)(words.size()); i++)
145     {
146           name += words[i];
147     }
148   if (name == "")
149     {
150       result = new std::string("The given name is not valid:  '/\\*\"% are forbidden.");
151           return NULL;
152     }
153   //copy template library folder with new name
154 #ifdef _WIN32
155         std::string copyCommand = "xcopy \"" + this->path + CDMUtilities::SLASH + "template_lib\" \"" + this->path + CDMUtilities::SLASH + name + CDMUtilities::SLASH + "\" /Y";
156 #else
157   std::string copyCommand = "cp -r \"" + this->path + CDMUtilities::SLASH + "template_lib\" \"" + this->path + CDMUtilities::SLASH + name + "\"";
158 #endif
159   if(system(copyCommand.c_str()))
160     {
161       result = new std::string("An error occurred while running '" + copyCommand + "'.");
162       return NULL;
163     }
164   //set name of library in CMakeLists inside copied folder
165   std::string line;
166   std::ifstream in((this->path + CDMUtilities::SLASH + name + CDMUtilities::SLASH + "CMakeLists.txt").c_str());
167   if( !in.is_open())
168     {
169       result = new std::string("CMakeLists.txt file failed to open.");
170       return NULL;
171     }
172   std::ofstream out((this->path + CDMUtilities::SLASH + name + CDMUtilities::SLASH + "CMakeLists.txt.tmp").c_str());
173   while (getline(in, line))
174     {
175       if(line == "SET ( LIBRARY_NAME   MyLib  )")
176         line = "SET ( LIBRARY_NAME   " + name + "  )";
177       out << line << std::endl;
178     }
179   in.close();
180   out.close();
181   //delete old file and rename new file
182 #ifdef _WIN32
183   std::string renameCommand = "move /Y \"" + this->path + CDMUtilities::SLASH + name + CDMUtilities::SLASH + "CMakeLists.txt.tmp\" \"" + this->path + CDMUtilities::SLASH + name + CDMUtilities::SLASH + "CMakeLists.txt\"";
184 #else
185   std::string renameCommand = "mv \"" + this->path + CDMUtilities::SLASH + name + CDMUtilities::SLASH + "CMakeLists.txt.tmp\" \"" + this->path + CDMUtilities::SLASH + name + CDMUtilities::SLASH + "CMakeLists.txt\"";
186 #endif
187   if(system(renameCommand.c_str()))
188     {
189       result = new std::string("An error occurred while running '" + renameCommand + "'.");
190       return NULL;
191     }
192
193   //add library to lib CMakeLists
194   std::fstream out1((this->path + CDMUtilities::SLASH + "CMakeLists.txt").c_str(), std::fstream::in | std::fstream::out | std::fstream::app);
195   if (out1.is_open())
196     {
197       out1 << "ADD_SUBDIRECTORY(" << name << ")" << std::endl;
198       out1.close();
199     }
200
201
202   //add library to model
203   modelCDMLibrary* library = new modelCDMLibrary(this, this->path + CDMUtilities::SLASH + name, name, this->level + 1);
204   this->libraries.push_back(library);
205   this->children.push_back(library);
206
207   this->SortChildren();
208
209   result = new std::string(this->path + CDMUtilities::SLASH + name);
210   return library;
211 }
212
213 const bool modelCDMLib::Refresh(std::string*& result)
214 {
215   std::cout << "refreshing lib" << std::endl;
216   this->type = wxDIR_DIRS;
217
218
219
220   std::vector<bool> checked(this->children.size(), false);
221   std::vector<bool> checkedLibraries(this->libraries.size(), false);
222
223   //check all folders
224   wxDir dir(crea::std2wx((this->path).c_str()));
225   if (dir.IsOpened())
226     {
227       wxString fileName;
228       bool cont = dir.GetFirst(&fileName, wxEmptyString, wxDIR_DIRS);
229       while (cont)
230         {
231           std::string stdfileName = crea::wx2std(fileName);
232
233           if(stdfileName != "template_lib")
234             {
235               std::string libraryName = stdfileName;
236               //check if library already exist
237               bool found = false;
238               for (int i = 0; !found && i < (int)(this->libraries.size()); i++)
239                 {
240                   if (this->libraries[i]->GetName() == libraryName)
241                     {
242                       found = true;
243                       int pos = std::find(this->children.begin(), this->children.end(), this->libraries[i]) - this->children.begin();
244                       checked[pos] = true;
245                       checkedLibraries[i] = true;
246                       if(!this->libraries[i]->Refresh(result))
247                         return false;
248                     }
249                 }
250               if(!found)
251                 {
252                   modelCDMLibrary* library = new modelCDMLibrary(this, this->path + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1);
253                   this->libraries.push_back(library);
254                   this->children.push_back(library);
255                 }
256             }
257           else
258             {
259               //check if folder already exist
260               bool found = false;
261               for (int i = 0; !found && i < (int)(this->children.size()); i++)
262                 {
263                   if (this->children[i]->GetName() == stdfileName)
264                     {
265                       found = true;
266                       checked[i] = true;
267                       if(!this->children[i]->Refresh(result))
268                         return false;
269                     }
270                 }
271               if(!found)
272                 {
273                   modelCDMFolder* folder= new modelCDMFolder(this, this->path + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1);
274                   this->children.push_back(folder);
275                 }
276             }
277           cont = dir.GetNext(&fileName);
278         }
279
280       cont = dir.GetFirst(&fileName, wxEmptyString, wxDIR_FILES);
281       while (cont)
282         {
283           std::string stdfileName = crea::wx2std(fileName);
284           std::size_t fileTypePos = stdfileName.find_last_of(".");
285           std::string fileType = stdfileName.substr(fileTypePos);
286
287
288           //if CMakeLists, create CMakeLists
289           if(stdfileName == "CMakeLists.txt")
290             {
291               if (this->CMakeLists == NULL)
292                 {
293                   this->CMakeLists = new modelCDMCMakeListsFile(this, this->path + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1);
294                   this->children.push_back(this->CMakeLists);
295                 }
296               else
297                 {
298                   int pos = std::find(this->children.begin(), this->children.end(), this->CMakeLists) - this->children.begin();
299                   checked[pos] = true;
300                   if(!this->CMakeLists->Refresh(result))
301                     return false;
302                 }
303             }
304           //if is an unknown file, create file
305           else
306             {
307               bool found = false;
308               for (int i = 0; !found && i < (int)(this->children.size()); i++)
309                 {
310                   if (this->children[i]->GetName() == stdfileName)
311                     {
312                       found = true;
313                       checked[i] = true;
314                       if(!this->children[i]->Refresh(result))
315                         return false;
316                     }
317                 }
318
319               if(!found)
320                 {
321                   //if is a code file, create modelCDMCodeFile
322                   if(
323                       fileType == ".c" ||
324                       fileType == ".cxx" ||
325                       fileType == ".h" ||
326                       fileType == ".cpp" ||
327                       fileType == ".txx" ||
328                       fileType == ".cmake" )
329                     {
330                       this->children.push_back(new modelCDMCodeFile(this, this->path + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1));
331                     }
332                   else
333                     {
334                       modelCDMFile* file = new modelCDMFile(this, this->path + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1);
335                       this->children.push_back(file);
336                     }
337                 }
338             }
339
340           cont = dir.GetNext(&fileName);
341         }
342     }
343
344   for (int i = 0; i < (int)(checkedLibraries.size()); i++)
345     {
346       if(!checkedLibraries[i])
347         {
348           this->libraries.erase(this->libraries.begin()+i);
349           checkedLibraries.erase(checkedLibraries.begin()+i);
350           i--;
351         }
352     }
353   for (int i = 0; i < (int)(checked.size()); i++)
354     {
355       if(!checked[i])
356         {
357           delete this->children[i];
358           this->children.erase(this->children.begin()+i);
359           checked.erase(checked.begin()+i);
360           i--;
361         }
362     }
363   this->SortChildren();
364   std::sort(this->libraries.begin(), this->libraries.end(), CompareNodeItem);
365   return true;
366 }
367
368 void modelCDMLib::CheckStructure(std::map<std::string, bool>& properties)
369 {
370   //check cmake exist
371   if(this->CMakeLists != NULL)
372     {
373       //set properties parameters based on model
374       for (int i = 0; i < (int)(this->libraries.size()); i++)
375         properties["lib add " + libraries[i]->GetName()] = false;
376
377       //open cmakelists
378       std::ifstream confFile;
379       confFile.open((this->CMakeLists->GetPath()).c_str());
380
381       //take everything that is not commented
382       std::string fileContent;
383
384       std::string word;
385       std::vector<std::string> words;
386       while(confFile.is_open() && !confFile.eof())
387         {
388           std::getline(confFile,word, '\n');
389           if(word[0] != '#')
390             {
391               CDMUtilities::splitter::split(words, word, "#", CDMUtilities::splitter::empties_ok);
392               if (words.size() > 0)
393                 {
394                   word = words[0];
395                   CDMUtilities::splitter::split(words, word, " ", CDMUtilities::splitter::empties_ok);
396                   for (int i = 0; i < (int)(words.size()); i++)
397                     {
398                       if(words[i].substr(0,2) == "//")
399                         break;
400                       fileContent += words[i] + " ";
401                     }
402                 }
403             }
404         }
405
406       //check every instruction
407       std::stringstream ss(fileContent);
408       while(!ss.eof())
409         {
410           std::getline(ss,word, '(');
411
412           //check instruction name
413           CDMUtilities::splitter::split(words, word, " ", CDMUtilities::splitter::no_empties);
414
415           //add instructions
416           if (words.size() > 0 && words[words.size()-1] == "ADD_SUBDIRECTORY")
417             {
418               std::getline(ss,word, ')');
419               //std::cout << word << std::endl;
420               CDMUtilities::splitter::split(words, word, " ", CDMUtilities::splitter::no_empties);
421
422               if (words.size() > 0)
423                 {
424                   {
425                     properties["lib add " + words[0]] = true;
426                   }
427                 }
428             }
429         }
430
431     }
432
433   //check libraries' structure
434   for (int i = 0; i < (int)(this->libraries.size()); i++)
435     {
436       properties["library " + this->libraries[i]->GetName()] = true;
437       this->libraries[i]->CheckStructure(properties);
438     }
439 }
440
441 bool modelCDMLib::IsLibraryIncluded(const std::string& library_name)
442 {
443   if (this->HasCMakeLists())
444     {
445       CDMUtilities::CMLFile cmlFile = CDMUtilities::readCMLFile(this->CMakeLists->GetPath().c_str());
446       for (int i = 0; i < cmlFile.size(); ++i)
447         {
448           if (cmlFile[i].first=="command" && cmlFile[i].second[0] == "ADD_SUBDIRECTORY")
449             {
450               int pos = 1;
451               while (pos < cmlFile[i].second.size())
452                 {
453                   if (!isspace(cmlFile[i].second[pos][0]) && cmlFile[i].second[pos][0] != '(' && cmlFile[i].second[pos][0] != '#')
454                     {
455                       if (library_name == cmlFile[i].second[pos])
456                         return true;
457                       break;
458                     }
459                   pos++;
460                 }
461             }
462         }
463     }
464   return false;
465 }
466
467 bool modelCDMLib::SetLibraryInclude(const std::string& library_name, const bool& toInclude)
468 {
469   if (this->HasCMakeLists())
470     {
471       CDMUtilities::CMLFile cmlFile = CDMUtilities::readCMLFile(this->CMakeLists->GetPath().c_str());
472
473       bool found = false;
474
475       for (int i = 0; i < cmlFile.size(); ++i)
476         {
477           if(toInclude && cmlFile[i].first == "comment")
478             {
479               std::vector<std::string> segments;
480               std::string line = cmlFile[i].second[0];
481               while(line[0] == '#')
482                 line.erase(0,1);
483
484               CDMUtilities::splitter::split(segments, line, " ()", CDMUtilities::splitter::no_empties);
485               if (segments.size() > 1 && segments[0] == "ADD_SUBDIRECTORY" && segments[1] == library_name)
486                 {
487                   found = true;
488                   while(cmlFile[i].second[0][0] == '#')
489                     cmlFile[i].second[0].erase(0,1);
490                 }
491             }
492           else if(cmlFile[i].first == "command" && cmlFile[i].second[0] == "ADD_SUBDIRECTORY")
493             {
494               int pos = 1;
495               while (pos < cmlFile[i].second.size())
496                 {
497                   if (!isspace(cmlFile[i].second[pos][0]) && cmlFile[i].second[pos][0] != '(' && cmlFile[i].second[pos][0] != '#')
498                     {
499                       if (library_name == cmlFile[i].second[pos])
500                         {
501                           found = true;
502                           if (!toInclude)
503                             {
504                               cmlFile[i].first = "comment";
505                               cmlFile[i].second[0] = "#" + cmlFile[i].second[0];
506                               while (cmlFile[i].second.size() > 1)
507                                 {
508                                   cmlFile[i].second[0] += cmlFile[i].second[1];
509                                   cmlFile[i].second.erase(cmlFile[i].second.begin()+1);
510                                 }
511
512                             }
513                         }
514                       break;
515                     }
516                   pos++;
517                 }
518             }
519         }
520       if (!found && toInclude)
521         {
522           CDMUtilities::syntaxElement element;
523           element.first = "command";
524           element.second.push_back("ADD_SUBDIRECTORY(" + library_name + ")");
525           cmlFile.push_back(element);
526         }
527
528       return CDMUtilities::writeCMLFile(this->CMakeLists->GetPath().c_str(),cmlFile);
529     }
530   return false;
531 }