]> Creatis software - crea.git/blob - lib/creaDevManagerLib/modelCDMLibrary.cpp
Feature #1711 CreaDevManager application implementation
[crea.git] / lib / creaDevManagerLib / modelCDMLibrary.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  * modelCDMLibrary.cpp
30  *
31  *  Created on: Nov 23, 2012
32  *      Author: Daniel Felipe Gonzalez Obando
33  */
34
35 #include "modelCDMLibrary.h"
36
37 #include <fstream>
38 #include <sstream>
39 #include <algorithm>
40 #include <boost/regex.hpp>
41
42 #include "CDMUtilities.h"
43 #include "creaWx.h"
44 #include "wx/dir.h"
45
46 modelCDMLibrary::modelCDMLibrary()
47 {
48 }
49
50 modelCDMLibrary::modelCDMLibrary(modelCDMIProjectTreeNode* parent, const std::string& path, const std::string& name, const int& level)
51 {
52   std::cout << "creating library: " + path + "\n";
53   this->parent = parent;
54   //folder name
55   this->name = name;
56   //path
57   this->path = CDMUtilities::fixPath(path);
58   //type
59   this->type = wxDIR_DIRS;
60   //level
61   this->level = level;
62
63   //open CMakeList
64   std::string pathMakeLists = path + CDMUtilities::SLASH + "CMakeLists.txt";
65
66   std::ifstream confFile;
67   confFile.open((pathMakeLists).c_str());
68
69   std::string word;
70   while(confFile.is_open() && !confFile.eof())
71     {
72       //get sets
73       std::getline(confFile,word,'(');
74       std::vector<std::string> wordBits;
75       CDMUtilities::splitter::split(wordBits,word," (\n",CDMUtilities::splitter::no_empties);
76
77       if(wordBits[wordBits.size()-1] == "SET")
78         {
79           //get library name
80           std::getline(confFile,word,')');
81           CDMUtilities::splitter::split(wordBits, word, " ", CDMUtilities::splitter::no_empties);
82           if(wordBits[0] == "LIBRARY_NAME")
83             {
84               word = wordBits[1];
85               for (int i = 2; i < (int)(wordBits.size()); i++)
86                 {
87                   word += " " + wordBits[i];
88                 }
89
90               this->nameLibrary = word;
91             }
92         }
93     }
94
95   confFile.close();
96
97   //add library contents
98
99   this->children.clear();
100   wxDir dir(crea::std2wx((this->path).c_str()));
101   if (dir.IsOpened())
102     {
103       wxString fileName;
104       //folders
105       bool cont = dir.GetFirst(&fileName, wxEmptyString, wxDIR_DIRS);
106       while (cont)
107         {
108           std::string stdfileName = crea::wx2std(fileName);
109
110           modelCDMFolder* folder = new modelCDMFolder(this, this->path + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1);
111           this->folders.push_back(folder);
112           this->children.push_back(folder);
113
114           cont = dir.GetNext(&fileName);
115         }
116       //files
117       cont = dir.GetFirst(&fileName, wxEmptyString, wxDIR_FILES);
118       while (cont)
119         {
120           std::string stdfileName = crea::wx2std(fileName);
121
122           //if CMakeLists, create CMakeLists
123           if(stdfileName == "CMakeLists.txt")
124             {
125               this->CMakeLists = new modelCDMCMakeListsFile(this, this->path + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1);
126               this->children.push_back(this->CMakeLists);
127             }
128           //if is an unknown file, create file
129           else
130             {
131               this->children.push_back(new modelCDMFile(this, this->path + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1));
132             }
133
134           cont = dir.GetNext(&fileName);
135         }
136     }
137   this->SortChildren();
138   std::sort(this->folders.begin(), this->folders.end(), CompareNodeItem);
139 }
140
141 modelCDMLibrary::~modelCDMLibrary()
142 {
143 }
144
145 const std::string& modelCDMLibrary::GetNameLibrary() const
146 {
147   return this->nameLibrary;
148 }
149
150 bool modelCDMLibrary::SetNameLibrary(const std::string& fileName, std::string*& result)
151 {
152   std::vector<std::string> words;
153   CDMUtilities::splitter::split(words, fileName, ", /\\\"", CDMUtilities::splitter::no_empties);
154   std::string fileNameReal = words[0];
155   for (int i = 1; i < (int)(words.size()); i++)
156     {
157       fileNameReal += "-" + words[i];
158     }
159
160   std::string line;
161   //opening original cmakelists
162   std::ifstream in((this->path + CDMUtilities::SLASH + "CMakeLists.txt").c_str());
163   if( !in.is_open())
164     {
165       result = new std::string("CMakeLists.txt file failed to open.");
166       return false;
167     }
168   //opening temporal cmakelists
169   std::ofstream out((this->path + CDMUtilities::SLASH + "CMakeLists.txt.tmp").c_str());
170   if( !out.is_open())
171     {
172       result = new std::string("CMakeLists.txt.tmp file failed to open.");
173       return false;
174     }
175   //copying contents from original to temporal and making changes
176   while (getline(in, line))
177     {
178       if(line.find("SET ( LIBRARY_NAME") != std::string::npos)
179         line = "SET ( LIBRARY_NAME  " + fileNameReal + "  )";
180       out << line << std::endl;
181     }
182   in.close();
183   out.close();
184   //delete old file and rename new file
185 #ifdef _WIN32
186   std::string renameCommand = "move /Y \"" + this->path + CDMUtilities::SLASH + "CMakeLists.txt.tmp\" \"" + this->path + CDMUtilities::SLASH + "CMakeLists.txt\"";
187 #else
188   std::string renameCommand = "mv \"" + this->path + CDMUtilities::SLASH + "CMakeLists.txt.tmp\" \"" + this->path + CDMUtilities::SLASH + "CMakeLists.txt\"";
189 #endif
190   if(system(renameCommand.c_str()))
191     {
192       result = new std::string("An error occurred while running '" + renameCommand + "'.");
193       return false;
194     }
195
196   this->nameLibrary = fileNameReal;
197   return true;
198 }
199
200 modelCDMFolder* modelCDMLibrary::CreateFolder(const std::string& name, std::string*& result)
201 {
202   //TODO:: mkdir depending on OS
203   std::string command = "mkdir \"" + path + CDMUtilities::SLASH + name + "\"";
204   if(system(command.c_str()))
205     {
206       result = new std::string("Error executing: " + command + ".");
207       return NULL;
208     }
209   modelCDMFolder* folder = new modelCDMFolder(this, path + CDMUtilities::SLASH + name, name, level + 1);
210   this->folders.push_back(folder);
211   this->children.push_back(folder);
212
213   return folder;
214 }
215
216 const bool modelCDMLibrary::Refresh(std::string*& result)
217 {
218   std::cout << "refreshing library: " << this->nameLibrary << std::endl;
219   //set attributes
220   this->type = wxDIR_DIRS;
221
222   //open CMakeList
223   std::string pathMakeLists = path + CDMUtilities::SLASH + "CMakeLists.txt";
224
225   std::ifstream confFile;
226   confFile.open((pathMakeLists).c_str());
227
228   std::string word;
229   while(confFile.is_open() && !confFile.eof())
230     {
231       //get sets
232       std::getline(confFile,word,'(');
233       std::vector<std::string> wordBits;
234       CDMUtilities::splitter::split(wordBits,word," (\n",CDMUtilities::splitter::no_empties);
235
236       if(wordBits[wordBits.size()-1] == "SET")
237         {
238           //get library name
239           std::getline(confFile,word,')');
240           CDMUtilities::splitter::split(wordBits, word, " ", CDMUtilities::splitter::no_empties);
241           if(wordBits[0] == "LIBRARY_NAME")
242             {
243               word = wordBits[1];
244               for (int i = 2; i < (int)(wordBits.size()); i++)
245                 {
246                   word += " " + wordBits[i];
247                 }
248
249               this->nameLibrary = word;
250             }
251         }
252     }
253
254   confFile.close();
255
256   //check children
257   std::vector<bool> checked(this->children.size(), false);
258   std::vector<bool> checkedFolders(this->folders.size(), false);
259
260   //check all folders
261   wxDir dir(crea::std2wx((this->path).c_str()));
262   if (dir.IsOpened())
263     {
264       wxString fileName;
265       bool cont = dir.GetFirst(&fileName, wxEmptyString, wxDIR_DIRS);
266       while (cont)
267         {
268           std::string stdfileName = crea::wx2std(fileName);
269           //check if they already exist
270           bool found = false;
271           for (int i = 0; !found && i < (int)(this->folders.size()); i++)
272             {
273               if (this->folders[i]->GetName() == stdfileName)
274                 {
275                   found = true;
276                   int pos = std::find(this->children.begin(), this->children.end(), this->folders[i]) - this->children.begin();
277                   checked[pos] = true;
278                   checkedFolders[i] = true;
279                   if(!this->folders[i]->Refresh(result))
280                     return false;
281                 }
282             }
283           if(!found)
284             {
285               modelCDMFolder* folder = new modelCDMFolder(this, this->path + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1);
286               this->folders.push_back(folder);
287               this->children.push_back(folder);
288             }
289           cont = dir.GetNext(&fileName);
290         }
291
292       cont = dir.GetFirst(&fileName, wxEmptyString, wxDIR_FILES);
293       while (cont)
294         {
295           std::string stdfileName = crea::wx2std(fileName);
296
297           //if CMakeLists, create CMakeLists
298           if(stdfileName == "CMakeLists.txt")
299             {
300               if (this->CMakeLists == NULL)
301                 {
302                   this->CMakeLists = new modelCDMCMakeListsFile(this, this->path + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1);
303                   this->children.push_back(this->CMakeLists);
304                 }
305               else
306                 {
307                   int pos = std::find(this->children.begin(), this->children.end(), this->CMakeLists) - this->children.begin();
308                   checked[pos] = true;
309                   if(!this->CMakeLists->Refresh(result))
310                     return false;
311                 }
312             }
313           //if is an unknown file, check if exist in children
314           else
315             {
316               bool found = false;
317               for (int i = 0; !found && i < (int)(this->children.size()); i++)
318                 {
319                   if (this->children[i]->GetName() == stdfileName)
320                     {
321                       found = true;
322                       checked[i] = true;
323                       if(!this->children[i]->Refresh(result))
324                         return false;
325                     }
326                 }
327
328               if(!found)
329                 {
330                   modelCDMFile* file = new modelCDMFile(this, this->path + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1);
331                   this->children.push_back(file);
332                 }
333             }
334
335           cont = dir.GetNext(&fileName);
336         }
337     }
338
339   for (int i = 0; i < (int)(checkedFolders.size()); i++)
340     {
341       if(!checkedFolders[i])
342         {
343           this->folders.erase(this->folders.begin()+i);
344           checkedFolders.erase(checkedFolders.begin()+i);
345           i--;
346         }
347     }
348   for (int i = 0; i < (int)(checked.size()); i++)
349     {
350       if(!checked[i])
351         {
352           delete this->children[i];
353           this->children.erase(this->children.begin()+i);
354           checked.erase(checked.begin()+i);
355           i--;
356         }
357     }
358   this->SortChildren();
359   std::sort(this->folders.begin(), this->folders.end(), CompareNodeItem);
360   return true;
361 }
362
363 void modelCDMLibrary::CheckStructure(std::map<std::string, bool>& properties)
364 {
365   //check cmake exist
366   if(this->CMakeLists != NULL)
367     {
368       //set default values
369       properties["library " + this->name + " lib ${crea_LIBRARIES}"] = false;
370       properties["library " + this->name + " lib ${WXWIDGETS_LIBRARIES}"] = false;
371       properties["library " + this->name + " lib ${KWWidgets_LIBRARIES}"] = false;
372       properties["library " + this->name + " lib ${VTK_LIBRARIES}"] = false;
373       properties["library " + this->name + " lib ${ITK_LIBRARIES}"] = false;
374       properties["library " + this->name + " lib ${GDCM_LIBRARIES}"] = false;
375       properties["library " + this->name + " lib ${BOOST_LIBRARIES}"] = false;
376
377
378       //open cmakelists
379       std::ifstream confFile;
380       confFile.open((this->CMakeLists->GetPath()).c_str());
381
382       //take everything that is not commented
383       std::string fileContent;
384
385       std::string word;
386       std::vector<std::string> words;
387       while(confFile.is_open() && !confFile.eof())
388         {
389           std::getline(confFile,word, '\n');
390           if(word[0] != '#')
391             {
392               CDMUtilities::splitter::split(words, word, "#", CDMUtilities::splitter::empties_ok);
393               if (words.size() > 0)
394                 {
395                   word = words[0];
396                   CDMUtilities::splitter::split(words, word, " ", CDMUtilities::splitter::empties_ok);
397                   for (int i = 0; i < (int)(words.size()); i++)
398                     {
399                       if(words[i].substr(0,2) == "//")
400                         break;
401                       fileContent += words[i] + " ";
402                     }
403                 }
404             }
405         }
406
407       //check every instruction
408       std::stringstream ss(fileContent);
409       while(!ss.eof())
410         {
411           std::getline(ss,word, '(');
412
413           //check instruction name
414           CDMUtilities::splitter::split(words, word, " ", CDMUtilities::splitter::no_empties);
415
416           //set instructions
417           if (words.size() > 0 && words[words.size()-1] == "SET")
418             {
419               std::getline(ss,word, ')');
420
421               CDMUtilities::splitter::split(words, word, " \t", CDMUtilities::splitter::no_empties);
422               if (words.size() > 1)
423                 {
424                   if (words[0] == "${LIBRARY_NAME}_LINK_LIBRARIES")
425                     {
426                       for (int i = 1; i < (int)(words.size()); i++)
427                         {
428                           properties["library " + this->name + " lib " + words[i]] = true;
429                         }
430                     }
431                 }
432             }
433         }
434
435     }
436 }
437
438 std::map<std::string, bool> modelCDMLibrary::Get3rdPartyLibraries()
439 {
440   std::map<std::string, std::string> correspondence;
441   correspondence["${crea_LIBRARIES}"] = "Crea";
442   correspondence["${WXWIDGETS_LIBRARIES}"] = "WxWidgets";
443   correspondence["${KWWidgets_LIBRARIES}"] = "KWWidgets";
444   correspondence["${VTK_LIBRARIES}"] = "VTK";
445   correspondence["${ITK_LIBRARIES}"] = "ITK";
446   correspondence["${GDCM_LIBRARIES}"] = "GDCM";
447   correspondence["${BOOST_LIBRARIES}"] = "Boost";
448   std::map<std::string, bool> res;
449   res["Crea"] = false;
450   res["WxWidgets"] = false;
451   res["KWWidgets"] = false;
452   res["VTK"] = false;
453   res["ITK"] = false;
454   res["GDCM"] = false;
455   res["Boost"] = false;
456
457   if (this->HasCMakeLists())
458     {
459       std::string CMfile = CDMUtilities::readFile(this->CMakeLists->GetPath().c_str());
460
461       boost::regex expression("^\\h*SET([\\s]|#[^\\n]*\\n)*\\(([\\s]|#[^\\n]*\\n)*\\$\\{LIBRARY_NAME\\}_LINK_LIBRARIES(([\\s]|#[^\\n]*\\n)+([\\$\\{\\}\\w\\d]+|\"(?:[^\"\\\\]|\\\\.)*\"))*([\\s]|#[^\\n]*\\n)*\\)");
462       std::string::const_iterator start, end;
463       start = CMfile.begin();
464       end = CMfile.end();
465       boost::match_results<std::string::const_iterator> what;
466       boost::match_flag_type flags = boost::match_default;
467       if(boost::regex_search(start, end, what, expression, flags))
468         {
469
470           expression = boost::regex("^\\h*SET([\\s]|#[^\\n]*\\n)*\\(([\\s]|#[^\\n]*\\n)*\\$\\{LIBRARY_NAME\\}_LINK_LIBRARIES");
471           std::string::const_iterator start1, end1;
472           start1 = what[0].first;
473           end1 = what[0].second;
474           boost::match_results<std::string::const_iterator> what1;
475           if(boost::regex_search(start1, end1, what1, expression, flags))
476             {
477               expression = boost::regex("(#[^\\n]*\\n|\\s*\\$\\{\\w+\\})");
478               std::string::const_iterator start2, end2;
479               start2 = what1[0].second;
480               end2 = what[0].second;
481               boost::match_results<std::string::const_iterator> what2;
482               while(boost::regex_search(start2, end2, what2, expression, flags))
483                 {
484                   if(what2.str()[0] != '#')
485                     {
486                       std::string dete = what2.str();
487                       CDMUtilities::normalizeStr(dete);
488                       if(correspondence.find(dete) != correspondence.end())
489                         res[correspondence[dete]] = true;
490                     }
491                   start2 = what2[0].second;
492                 }
493             }
494         }
495     }
496   return res;
497 }
498
499 bool modelCDMLibrary::Set3rdPartyLibrary(const std::string& library_name, const bool& toInclude)
500 {
501   std::map<std::string, std::string> correspondence;
502
503   correspondence["Crea"] = "${crea_LIBRARIES}";
504   correspondence["WxWidgets"] = "${WXWIDGETS_LIBRARIES}";
505   correspondence["KWWidgets"] = "${KWWidgets_LIBRARIES}";
506   correspondence["VTK"] = "${VTK_LIBRARIES}";
507   correspondence["ITK"] = "${ITK_LIBRARIES}";
508   correspondence["GDCM"] = "${GDCM_LIBRARIES}";
509   correspondence["Boost"] = "${BOOST_LIBRARIES}";
510
511   std::map<std::string, std::string> regexCorrespondence;
512
513   regexCorrespondence["Crea"] = "\\$\\{crea_LIBRARIES\\}";
514   regexCorrespondence["WxWidgets"] = "\\$\\{WXWIDGETS_LIBRARIES\\}";
515   regexCorrespondence["KWWidgets"] = "\\$\\{KWWidgets_LIBRARIES\\}";
516   regexCorrespondence["VTK"] = "\\$\\{VTK_LIBRARIES\\}";
517   regexCorrespondence["ITK"] = "\\$\\{ITK_LIBRARIES\\}";
518   regexCorrespondence["GDCM"] = "\\$\\{GDCM_LIBRARIES\\}";
519   regexCorrespondence["Boost"] = "\\$\\{BOOST_LIBRARIES\\}";
520
521   if (correspondence.find(library_name) != correspondence.end())
522     {
523       std::string library_command = correspondence[library_name];
524       std::string regex_command = regexCorrespondence[library_name];
525       if (this->HasCMakeLists())
526         {
527           std::string CMfile = CDMUtilities::readFile(this->CMakeLists->GetPath().c_str());
528           std::string resCMfile = "";
529
530           boost::regex expression("^\\h*SET([\\s]|#[^\\n]*\\n)*\\(([\\s]|#[^\\n]*\\n)*\\$\\{LIBRARY_NAME\\}_LINK_LIBRARIES(([\\s]|#[^\\n]*\\n)+([\\$\\{\\}\\w\\d]+|\"(?:[^\"\\\\]|\\\\.)*\"))*([\\s]|#[^\\n]*\\n)*\\)");
531           std::string::const_iterator start, end;
532           start = CMfile.begin();
533           end = CMfile.end();
534           boost::match_results<std::string::const_iterator> what;
535           boost::match_flag_type flags = boost::match_default;
536           if(boost::regex_search(start, end, what, expression, flags))
537             {
538               resCMfile += what.prefix().str();
539               bool found = false;
540               if (toInclude) {
541                 expression = "^\\h*#+\\h*" + regex_command;
542                 std::string::const_iterator start1, end1;
543                 start1 = what[0].first;
544                 end1 = what[0].second;
545                 boost::match_results<std::string::const_iterator> what1, what2;
546                 while(boost::regex_search(start1, end1, what1, expression, flags))
547                   {
548                     found = true;
549                     resCMfile += what1.prefix().str();
550                     std::string dete = what1[0].str();
551                     for (int i = 0; i < dete.size(); ++i) {
552                       if (dete[i] != '#')
553                         resCMfile.push_back(dete[i]);
554                     }
555                     what2 = what1;
556                     start1 = what1[0].second;
557                   }
558                 if (found)
559                   resCMfile += what2.suffix().str();
560                 else
561                   {
562                     expression = "^\\h*" + regex_command;
563                     if(boost::regex_search(start1, end1, what1, expression, flags))
564                       found = true;
565
566                     expression = "^\\h*SET([\\s]|#[^\\n]*\\n)*\\(([\\s]|#[^\\n]*\\n)*\\$\\{LIBRARY_NAME\\}_LINK_LIBRARIES";
567                     boost::regex_search(start1, end1, what1, expression, flags);
568
569                     resCMfile += what1.prefix().str() + what1.str();
570                     if(!found)
571                       resCMfile += "\n" + library_command + "\n";
572                     resCMfile += what1.suffix().str();
573                   }
574
575               }else{
576                 expression = "^\\h*" + regex_command;
577                 std::string::const_iterator start1, end1;
578                 start1 = what[0].first;
579                 end1 = what[0].second;
580                 boost::match_results<std::string::const_iterator> what1, what2;
581                 while(boost::regex_search(start1, end1, what1, expression, flags))
582                   {
583                     found = true;
584                     resCMfile += what1.prefix().str();
585                     resCMfile += "#" + what1.str();
586                     what2 = what1;
587                     start1 = what1[0].second;
588                   }
589                 if (found)
590                   resCMfile += what2.suffix().str();
591                 else
592                   {
593                     expression = "^\\h*SET([\\s]|#[^\\n]*\\n)*\\(([\\s]|#[^\\n]*\\n)*\\$\\{LIBRARY_NAME\\}_LINK_LIBRARIES";
594                     boost::regex_search(start1, end1, what1, expression, flags);
595
596                     resCMfile += what1.prefix().str() + what1.str() + what1.suffix().str();
597                   }
598               }
599               resCMfile += what.suffix().str();
600
601               return CDMUtilities::writeFile(this->CMakeLists->GetPath().c_str(), resCMfile);
602             }
603         }
604     }
605   return false;
606 }
607
608 std::map<std::string, bool> modelCDMLibrary::GetCustomLibraries()
609 {
610   std::map<std::string, bool> res;
611   res["Test"] = false;
612   return res;
613 }
614
615 bool modelCDMLibrary::SetCustomLibrary(const std::string& library_name, const bool& toInclude)
616 {
617   return false;
618 }