]> 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;
96           if(fileTypePos != std::string::npos)
97             fileType = stdfileName.substr(fileTypePos);
98           else
99             fileType = "";
100
101           //if CMakeLists, create CMakeLists
102           if(stdfileName == "CMakeLists.txt")
103             {
104               this->CMakeLists = new modelCDMCMakeListsFile(this, pathFixed + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1);
105               this->children.push_back(this->CMakeLists);
106             }
107           //if is a code file, create modelCDMCodeFile
108           else if(
109               fileType == ".c" ||
110               fileType == ".cxx" ||
111               fileType == ".h" ||
112               fileType == ".cpp" ||
113               fileType == ".txx" ||
114               fileType == ".cmake" )
115             {
116               this->children.push_back(new modelCDMCodeFile(this, pathFixed + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1));
117             }
118           //if is an unknown file, create file
119           else
120             {
121               this->children.push_back(new modelCDMFile(this, pathFixed + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1));
122             }
123
124           cont = dir.GetNext(&fileName);
125         }
126     }
127   this->SortChildren();
128   std::sort(this->libraries.begin(), this->libraries.end(), CompareNodeItem);
129 }
130
131 modelCDMLib::~modelCDMLib()
132 {
133 }
134
135 const std::vector<modelCDMLibrary*>& modelCDMLib::GetLibraries() const
136 {
137   return this->libraries;
138 }
139
140 modelCDMLibrary* modelCDMLib::CreateLibrary(
141     const std::string& namein,
142     std::string*& result
143 )
144 {
145   std::vector<std::string> words;
146   CDMUtilities::splitter::split(words,namein," '/\\*\"%",CDMUtilities::splitter::no_empties);
147   std::string name;
148   for (int i = 0; i < (int)(words.size()); i++)
149     {
150           name += words[i];
151     }
152   if (name == "")
153     {
154       result = new std::string("The given name is not valid:  '/\\*\"% are forbidden.");
155           return NULL;
156     }
157   //copy template library folder with new name
158 #ifdef _WIN32
159         std::string copyCommand = "xcopy \"" + this->path + CDMUtilities::SLASH + "template_lib\" \"" + this->path + CDMUtilities::SLASH + name + CDMUtilities::SLASH + "\" /Y";
160 #else
161   std::string copyCommand = "cp -r \"" + this->path + CDMUtilities::SLASH + "template_lib\" \"" + this->path + CDMUtilities::SLASH + name + "\"";
162 #endif
163   if(system(copyCommand.c_str()))
164     {
165       result = new std::string("An error occurred while running '" + copyCommand + "'.");
166       return NULL;
167     }
168   //set name of library in CMakeLists inside copied folder
169   std::string line;
170   std::ifstream in((this->path + CDMUtilities::SLASH + name + CDMUtilities::SLASH + "CMakeLists.txt").c_str());
171   if( !in.is_open())
172     {
173       result = new std::string("CMakeLists.txt file failed to open.");
174       return NULL;
175     }
176   std::ofstream out((this->path + CDMUtilities::SLASH + name + CDMUtilities::SLASH + "CMakeLists.txt.tmp").c_str());
177   while (getline(in, line))
178     {
179       if(line == "SET ( LIBRARY_NAME   MyLib  )")
180         line = "SET ( LIBRARY_NAME   " + name + "  )";
181       out << line << std::endl;
182     }
183   in.close();
184   out.close();
185   //delete old file and rename new file
186 #ifdef _WIN32
187   std::string renameCommand = "move /Y \"" + this->path + CDMUtilities::SLASH + name + CDMUtilities::SLASH + "CMakeLists.txt.tmp\" \"" + this->path + CDMUtilities::SLASH + name + CDMUtilities::SLASH + "CMakeLists.txt\"";
188 #else
189   std::string renameCommand = "mv \"" + this->path + CDMUtilities::SLASH + name + CDMUtilities::SLASH + "CMakeLists.txt.tmp\" \"" + this->path + CDMUtilities::SLASH + name + CDMUtilities::SLASH + "CMakeLists.txt\"";
190 #endif
191   if(system(renameCommand.c_str()))
192     {
193       result = new std::string("An error occurred while running '" + renameCommand + "'.");
194       return NULL;
195     }
196
197   //add library to lib CMakeLists
198   std::fstream out1((this->path + CDMUtilities::SLASH + "CMakeLists.txt").c_str(), std::fstream::in | std::fstream::out | std::fstream::app);
199   if (out1.is_open())
200     {
201       out1 << "ADD_SUBDIRECTORY(" << name << ")" << std::endl;
202       out1.close();
203     }
204
205
206   //add library to model
207   modelCDMLibrary* library = new modelCDMLibrary(this, this->path + CDMUtilities::SLASH + name, name, this->level + 1);
208   this->libraries.push_back(library);
209   this->children.push_back(library);
210
211   this->SortChildren();
212
213   result = new std::string(this->path + CDMUtilities::SLASH + name);
214   return library;
215 }
216
217 const bool modelCDMLib::Refresh(std::string*& result)
218 {
219   std::cout << "refreshing lib" << std::endl;
220   this->type = wxDIR_DIRS;
221
222
223
224   std::vector<bool> checked(this->children.size(), false);
225   std::vector<bool> checkedLibraries(this->libraries.size(), false);
226
227   //check all folders
228   wxDir dir(crea::std2wx((this->path).c_str()));
229   if (dir.IsOpened())
230     {
231       wxString fileName;
232       bool cont = dir.GetFirst(&fileName, wxEmptyString, wxDIR_DIRS);
233       while (cont)
234         {
235           std::string stdfileName = crea::wx2std(fileName);
236
237           if(stdfileName != "template_lib")
238             {
239               std::string libraryName = stdfileName;
240               //check if library already exist
241               bool found = false;
242               for (int i = 0; !found && i < (int)(this->libraries.size()); i++)
243                 {
244                   if (this->libraries[i]->GetName() == libraryName)
245                     {
246                       found = true;
247                       int pos = std::find(this->children.begin(), this->children.end(), this->libraries[i]) - this->children.begin();
248                       checked[pos] = true;
249                       checkedLibraries[i] = true;
250                       if(!this->libraries[i]->Refresh(result))
251                         return false;
252                     }
253                 }
254               if(!found)
255                 {
256                   modelCDMLibrary* library = new modelCDMLibrary(this, this->path + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1);
257                   this->libraries.push_back(library);
258                   this->children.push_back(library);
259                 }
260             }
261           else
262             {
263               //check if folder already exist
264               bool found = false;
265               for (int i = 0; !found && i < (int)(this->children.size()); i++)
266                 {
267                   if (this->children[i]->GetName() == stdfileName)
268                     {
269                       found = true;
270                       checked[i] = true;
271                       if(!this->children[i]->Refresh(result))
272                         return false;
273                     }
274                 }
275               if(!found)
276                 {
277                   modelCDMFolder* folder= new modelCDMFolder(this, this->path + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1);
278                   this->children.push_back(folder);
279                 }
280             }
281           cont = dir.GetNext(&fileName);
282         }
283
284       cont = dir.GetFirst(&fileName, wxEmptyString, wxDIR_FILES);
285       while (cont)
286         {
287           std::string stdfileName = crea::wx2std(fileName);
288           std::size_t fileTypePos = stdfileName.find_last_of(".");
289           std::string fileType;
290           if(fileTypePos != std::string::npos)
291             fileType = stdfileName.substr(fileTypePos);
292           else
293             fileType = "";
294
295
296           //if CMakeLists, create CMakeLists
297           if(stdfileName == "CMakeLists.txt")
298             {
299               if (this->CMakeLists == NULL)
300                 {
301                   this->CMakeLists = new modelCDMCMakeListsFile(this, this->path + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1);
302                   this->children.push_back(this->CMakeLists);
303                 }
304               else
305                 {
306                   int pos = std::find(this->children.begin(), this->children.end(), this->CMakeLists) - this->children.begin();
307                   checked[pos] = true;
308                   if(!this->CMakeLists->Refresh(result))
309                     return false;
310                 }
311             }
312           //if is an unknown file, create file
313           else
314             {
315               bool found = false;
316               for (int i = 0; !found && i < (int)(this->children.size()); i++)
317                 {
318                   if (this->children[i]->GetName() == stdfileName)
319                     {
320                       found = true;
321                       checked[i] = true;
322                       if(!this->children[i]->Refresh(result))
323                         return false;
324                     }
325                 }
326
327               if(!found)
328                 {
329                   //if is a code file, create modelCDMCodeFile
330                   if(
331                       fileType == ".c" ||
332                       fileType == ".cxx" ||
333                       fileType == ".h" ||
334                       fileType == ".cpp" ||
335                       fileType == ".txx" ||
336                       fileType == ".cmake" )
337                     {
338                       this->children.push_back(new modelCDMCodeFile(this, this->path + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1));
339                     }
340                   else
341                     {
342                       modelCDMFile* file = new modelCDMFile(this, this->path + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1);
343                       this->children.push_back(file);
344                     }
345                 }
346             }
347
348           cont = dir.GetNext(&fileName);
349         }
350     }
351
352   for (int i = 0; i < (int)(checkedLibraries.size()); i++)
353     {
354       if(!checkedLibraries[i])
355         {
356           this->libraries.erase(this->libraries.begin()+i);
357           checkedLibraries.erase(checkedLibraries.begin()+i);
358           i--;
359         }
360     }
361   for (int i = 0; i < (int)(checked.size()); i++)
362     {
363       if(!checked[i])
364         {
365           delete this->children[i];
366           this->children.erase(this->children.begin()+i);
367           checked.erase(checked.begin()+i);
368           i--;
369         }
370     }
371   this->SortChildren();
372   std::sort(this->libraries.begin(), this->libraries.end(), CompareNodeItem);
373   return true;
374 }
375
376 void modelCDMLib::CheckStructure(std::map<std::string, bool>& properties)
377 {
378   //check cmake exist
379   if(this->CMakeLists != NULL)
380     {
381       //set properties parameters based on model
382       for (int i = 0; i < (int)(this->libraries.size()); i++)
383         properties["lib add " + libraries[i]->GetName()] = false;
384
385       //open cmakelists
386       std::ifstream confFile;
387       confFile.open((this->CMakeLists->GetPath()).c_str());
388
389       //take everything that is not commented
390       std::string fileContent;
391
392       std::string word;
393       std::vector<std::string> words;
394       while(confFile.is_open() && !confFile.eof())
395         {
396           std::getline(confFile,word, '\n');
397           if(word[0] != '#')
398             {
399               CDMUtilities::splitter::split(words, word, "#", CDMUtilities::splitter::empties_ok);
400               if (words.size() > 0)
401                 {
402                   word = words[0];
403                   CDMUtilities::splitter::split(words, word, " ", CDMUtilities::splitter::empties_ok);
404                   for (int i = 0; i < (int)(words.size()); i++)
405                     {
406                       if(words[i].substr(0,2) == "//")
407                         break;
408                       fileContent += words[i] + " ";
409                     }
410                 }
411             }
412         }
413
414       //check every instruction
415       std::stringstream ss(fileContent);
416       while(!ss.eof())
417         {
418           std::getline(ss,word, '(');
419
420           //check instruction name
421           CDMUtilities::splitter::split(words, word, " ", CDMUtilities::splitter::no_empties);
422
423           //add instructions
424           if (words.size() > 0 && words[words.size()-1] == "ADD_SUBDIRECTORY")
425             {
426               std::getline(ss,word, ')');
427               //std::cout << word << std::endl;
428               CDMUtilities::splitter::split(words, word, " ", CDMUtilities::splitter::no_empties);
429
430               if (words.size() > 0)
431                 {
432                   {
433                     properties["lib add " + words[0]] = true;
434                   }
435                 }
436             }
437         }
438
439     }
440
441   //check libraries' structure
442   for (int i = 0; i < (int)(this->libraries.size()); i++)
443     {
444       properties["library " + this->libraries[i]->GetName()] = true;
445       this->libraries[i]->CheckStructure(properties);
446     }
447 }
448
449 bool modelCDMLib::IsLibraryIncluded(const std::string& library_name)
450 {
451   if (this->HasCMakeLists())
452     {
453       CDMUtilities::CMLFile cmlFile = CDMUtilities::readCMLFile(this->CMakeLists->GetPath().c_str());
454       for (int i = 0; i < cmlFile.size(); ++i)
455         {
456           if (cmlFile[i].first=="command" && cmlFile[i].second[0] == "ADD_SUBDIRECTORY")
457             {
458               int pos = 1;
459               while (pos < cmlFile[i].second.size())
460                 {
461                   if (!isspace(cmlFile[i].second[pos][0]) && cmlFile[i].second[pos][0] != '(' && cmlFile[i].second[pos][0] != '#')
462                     {
463                       if (library_name == cmlFile[i].second[pos])
464                         return true;
465                       break;
466                     }
467                   pos++;
468                 }
469             }
470         }
471     }
472   return false;
473 }
474
475 bool modelCDMLib::SetLibraryInclude(const std::string& library_name, const bool& toInclude)
476 {
477   if (this->HasCMakeLists())
478     {
479       CDMUtilities::CMLFile cmlFile = CDMUtilities::readCMLFile(this->CMakeLists->GetPath().c_str());
480
481       bool found = false;
482
483       for (int i = 0; i < cmlFile.size(); ++i)
484         {
485           if(toInclude && cmlFile[i].first == "comment")
486             {
487               std::vector<std::string> segments;
488               std::string line = cmlFile[i].second[0];
489               while(line[0] == '#')
490                 line.erase(0,1);
491
492               CDMUtilities::splitter::split(segments, line, " ()", CDMUtilities::splitter::no_empties);
493               if (segments.size() > 1 && segments[0] == "ADD_SUBDIRECTORY" && segments[1] == library_name)
494                 {
495                   found = true;
496                   while(cmlFile[i].second[0][0] == '#')
497                     cmlFile[i].second[0].erase(0,1);
498                 }
499             }
500           else if(cmlFile[i].first == "command" && cmlFile[i].second[0] == "ADD_SUBDIRECTORY")
501             {
502               int pos = 1;
503               while (pos < cmlFile[i].second.size())
504                 {
505                   if (!isspace(cmlFile[i].second[pos][0]) && cmlFile[i].second[pos][0] != '(' && cmlFile[i].second[pos][0] != '#')
506                     {
507                       if (library_name == cmlFile[i].second[pos])
508                         {
509                           found = true;
510                           if (!toInclude)
511                             {
512                               cmlFile[i].first = "comment";
513                               cmlFile[i].second[0] = "#" + cmlFile[i].second[0];
514                               while (cmlFile[i].second.size() > 1)
515                                 {
516                                   cmlFile[i].second[0] += cmlFile[i].second[1];
517                                   cmlFile[i].second.erase(cmlFile[i].second.begin()+1);
518                                 }
519
520                             }
521                         }
522                       break;
523                     }
524                   pos++;
525                 }
526             }
527         }
528       if (!found && toInclude)
529         {
530           CDMUtilities::syntaxElement element;
531           element.first = "command";
532           element.second.push_back("ADD_SUBDIRECTORY(" + library_name + ")");
533           cmlFile.push_back(element);
534         }
535
536       return CDMUtilities::writeCMLFile(this->CMakeLists->GetPath().c_str(),cmlFile);
537     }
538   return false;
539 }