]> Creatis software - crea.git/blob - lib/creaDevManagerLib/modelCDMProject.cpp
Feature #1711 CreaDevManager application implementation
[crea.git] / lib / creaDevManagerLib / modelCDMProject.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  * modelCDMProject.cpp
30  *
31  *  Created on: 13/11/2012
32  *      Author: Daniel Felipe Gonzalez Obando
33  */
34
35 #include "modelCDMProject.h"
36
37 #include <iostream>
38 #include <sstream>
39 #include <vector>
40 #include <algorithm>
41 #include <fstream>
42 #include <ctime>
43 #include <boost/regex.hpp>
44
45 #include "CDMUtilities.h"
46 #include "creaWx.h"
47 #include "wx/dir.h"
48 #include <wx/config.h>
49
50 modelCDMProject::modelCDMProject()
51 {
52   std::cout << "in constructor1" << std::endl;
53   this->appli = NULL;
54   this->lib = NULL;
55   this->CMakeLists = NULL;
56 }
57
58 modelCDMProject::modelCDMProject(
59     modelCDMIProjectTreeNode* parent,
60     const std::string& path,
61     const std::string& name,
62     const std::string& buildPath
63 )
64 {
65   std::cout << "creating project: " + name + " in " + path + "\n";
66   this->parent = parent;
67   this->path = CDMUtilities::fixPath(path);
68   //open makelists file
69   std::string pathFixed(CDMUtilities::fixPath(path));
70
71   std::string pathMakeLists = pathFixed + CDMUtilities::SLASH + "CMakeLists.txt";
72
73   std::ifstream confFile;
74   confFile.open((pathMakeLists).c_str());
75
76   std::string word;
77   while(confFile.is_open() && !confFile.eof())
78     {
79       //std::cout << "leyendo " << word << std::endl;
80       //get project name
81       std::getline(confFile,word,'(');
82       std::vector<std::string> wordBits;
83       CDMUtilities::splitter::split(wordBits,word," (\n",CDMUtilities::splitter::no_empties);
84
85       if(wordBits[wordBits.size()-1] == "PROJECT")
86         {
87           std::getline(confFile,word,')');
88           std::vector<std::string> nameBits;
89           CDMUtilities::splitter::split(nameBits, word, " ", CDMUtilities::splitter::no_empties);
90
91           this->name = this->nameProject = "";
92           for (int i = 0; i < (int)(nameBits.size()); i++)
93             {
94               if(i != 0)
95                 this->name += " ";
96               this->name += nameBits[i];
97             }
98           this->nameProject = this->name;
99
100         }
101
102
103       if(wordBits[wordBits.size()-1] == "SET")
104         {
105           //get project version
106           std::getline(confFile,word,')');
107           CDMUtilities::splitter::split(wordBits, word, " ", CDMUtilities::splitter::no_empties);
108           if(wordBits[0] == "PROJECT_MAJOR_VERSION")
109             {
110               version = wordBits[1];
111             }
112           if(wordBits[0] == "PROJECT_MINOR_VERSION")
113             {
114               version += "." + wordBits[1];
115             }
116           if(wordBits[0] == "PROJECT_BUILD_VERSION")
117             {
118               version += "." + wordBits[1];
119             }
120
121           //get project versionDate
122           if(wordBits[0] == "PROJECT_VERSION_DATE")
123             {
124               std::vector<std::string> versionBits;
125               CDMUtilities::splitter::split(versionBits, wordBits[1], "\"", CDMUtilities::splitter::no_empties);
126               versionDate = versionBits[0];
127             }
128           //get project buildPath
129
130           if (buildPath != "")
131             {
132               this->buildPath = buildPath;
133             }
134           else
135             {
136               this->buildPath = this->path + "Bin";
137             }
138         }
139     }
140   confFile.close();
141
142   this->type = wxDIR_DIRS;
143   this->level = 0;
144
145   this->children.clear();
146   this->appli = NULL;
147   this->lib = NULL;
148   this->packages.clear();
149
150
151   //check all folders
152   wxDir dir(crea::std2wx((pathFixed).c_str()));
153   if (dir.IsOpened())
154     {
155       wxString fileName;
156       bool cont = dir.GetFirst(&fileName, wxEmptyString, wxDIR_DIRS);
157       while (cont)
158         {
159           std::string stdfileName = crea::wx2std(fileName);
160
161           //if appli, create appli
162           if(stdfileName == "appli")
163             {
164               this->appli = new modelCDMAppli(this, pathFixed + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1);
165               this->children.push_back(this->appli);
166             }
167           //if lib, create lib
168           else if(stdfileName == "lib")
169             {
170               this->lib = new modelCDMLib(this, pathFixed + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1);
171               this->children.push_back(this->lib);
172             }
173           //if package , create package
174           else if(stdfileName.size() > 9 && stdfileName.substr(0,5) == "bbtk_" && stdfileName.substr(stdfileName.size()-4,4) == "_PKG")
175             {
176               modelCDMPackage* package = new modelCDMPackage(this, pathFixed + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1);
177               this->packages.push_back(package);
178               this->children.push_back(package);
179             }
180           //if is an unknown folder, create folder
181           else
182             {
183               this->children.push_back(new modelCDMFolder(this, pathFixed + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1));
184             }
185
186           cont = dir.GetNext(&fileName);
187         }
188
189       cont = dir.GetFirst(&fileName, wxEmptyString, wxDIR_FILES);
190       while (cont)
191         {
192           std::string stdfileName = crea::wx2std(fileName);
193           std::size_t fileTypePos = stdfileName.find_last_of(".");
194           std::string fileType = stdfileName.substr(fileTypePos);
195
196           //if CMakeLists, create CMakeLists
197           if(stdfileName == "CMakeLists.txt")
198             {
199               this->CMakeLists = new modelCDMCMakeListsFile(this, pathFixed + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1);
200               this->children.push_back(this->CMakeLists);
201             }
202           //if is a code file, create modelCDMCodeFile
203           else if(
204               fileType == ".c" ||
205               fileType == ".cxx" ||
206               fileType == ".h" ||
207               fileType == ".cpp" ||
208               fileType == ".txx" ||
209               fileType == ".cmake" )
210             {
211               this->children.push_back(new modelCDMCodeFile(this, pathFixed + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1));
212             }
213           //if is an unknown file, create file
214           else
215             {
216               this->children.push_back(new modelCDMFile(this, pathFixed + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1));
217             }
218
219           cont = dir.GetNext(&fileName);
220         }
221     }
222
223   this->SortChildren();
224   std::sort(this->packages.begin(), this->packages.end(), CompareNodeItem);
225
226 }
227
228 modelCDMProject::~modelCDMProject()
229 {
230 }
231
232 const std::string& modelCDMProject::GetNameProject() const
233 {
234   return this->nameProject;
235 }
236
237 const std::string& modelCDMProject::GetVersion() const
238 {
239   return this->version;
240 }
241
242 const std::string& modelCDMProject::GetVersionDate() const
243 {
244   return this->versionDate;
245 }
246
247 const std::string& modelCDMProject::GetBuildPath() const
248 {
249   return this->buildPath;
250 }
251
252 const std::vector<modelCDMPackage*>& modelCDMProject::GetPackages() const
253 {
254   return this->packages;
255 }
256
257 modelCDMAppli* modelCDMProject::GetAppli() const
258 {
259   return this->appli;
260 }
261
262 modelCDMLib* modelCDMProject::GetLib() const
263 {
264   return this->lib;
265 }
266
267 std::string modelCDMProject::GetBuildInstruction() const
268 {
269   wxConfigBase* pConfig =  wxConfigBase::Get();
270   std::string commandline = crea::wx2std(pConfig->Read(wxT("BUILD_COMMAND"), crea::std2wx(CDMUtilities::BUILD_COMMAND)));
271
272
273   std::string makeComm = "cd \"" + this->buildPath + "\";" + commandline;// -C \"" + this->buildPath + "\""; /*> \"" + this->buildPath + CDMUtilities::SLASH + "building.log\" 2>&1";*/
274   return makeComm;
275 }
276
277 bool modelCDMProject::SetVersion(const std::string& version, std::string*& result)
278 {
279
280   std::vector<std::string> vers;
281   CDMUtilities::splitter::split(vers, version, " .", CDMUtilities::splitter::no_empties);
282
283   time_t now = time(0);
284
285   tm ltm;
286 #ifdef _WIN32
287   localtime_s(&ltm, &now);
288 #else
289   ltm = *(localtime(&now));
290 #endif
291
292   std::stringstream date;
293   date << ltm.tm_mday << "/" << 1 + ltm.tm_mon << "/" << 1900 + ltm.tm_year;
294
295   //set name of library in CMakeLists inside copied folder
296   std::string line;
297   std::ifstream in((this->path + CDMUtilities::SLASH + "CMakeLists.txt").c_str());
298   if( !in.is_open())
299     {
300       result = new std::string("CMakeLists.txt file failed to open.");
301       return false;
302     }
303   std::ofstream out((this->path + CDMUtilities::SLASH + "CMakeLists.txt.tmp").c_str());
304   if( !out.is_open())
305     {
306       result = new std::string("CMakeLists.txt.tmp file failed to open.");
307       return false;
308     }
309   while (getline(in, line))
310     {
311       if(line.find("SET(PROJECT_MAJOR_VERSION") != std::string::npos)
312         line = "SET(PROJECT_MAJOR_VERSION " + vers[0] + ")";
313       else if(line.find("SET(PROJECT_MINOR_VERSION") != std::string::npos)
314         line = "SET(PROJECT_MINOR_VERSION " + vers[1] + ")";
315       else if(line.find("SET(PROJECT_BUILD_VERSION") != std::string::npos)
316         line = "SET(PROJECT_BUILD_VERSION " + vers[2] + ")";
317       else if(line.find("SET(PROJECT_VERSION_DATE") != std::string::npos)
318         line = "SET(PROJECT_VERSION_DATE \"" + date.str() + "\")";
319       out << line << std::endl;
320     }
321   in.close();
322   out.close();
323   //delete old file and rename new file
324 #ifdef _WIN32
325   std::string renameCommand = "move /Y \"" + this->path + CDMUtilities::SLASH + "CMakeLists.txt.tmp\" \"" + this->path + CDMUtilities::SLASH + "CMakeLists.txt\"";
326 #else
327   std::string renameCommand = "mv \"" + this->path + CDMUtilities::SLASH + "CMakeLists.txt.tmp\" \"" + this->path + CDMUtilities::SLASH + "CMakeLists.txt\"";
328 #endif
329   if(system(renameCommand.c_str()))
330     {
331       result = new std::string("An error occurred while running '" + renameCommand + "'.");
332       return false;
333     }
334
335   this->version = vers[0] + "." + vers[1] + "." + vers[2];
336   this->versionDate = date.str();
337   return true;
338 }
339
340 bool modelCDMProject::SetBuildPath(const std::string& path, std::string*& result)
341 {
342   if(path == "")
343     {
344       result = new std::string("The path cannot be empty");
345       return false;
346     }
347   if(path == this->path)
348     {
349       result = new std::string("The path cannot be same as the project sources");
350       return false;
351     }
352   this->buildPath = path;
353   return true;
354 }
355
356 modelCDMIProjectTreeNode* modelCDMProject::CreatePackage(
357     const std::string& name,
358     std::string*& result,
359     const std::string& authors,
360     const std::string& authorsEmail,
361     const std::string& description,
362     const std::string& version
363 )
364 {
365   //fixing input parameters
366   std::vector<std::string> words;
367
368   CDMUtilities::splitter::split(words,name," '/\"\\,.",CDMUtilities::splitter::no_empties);
369   std::string nameFixed = "";
370   for (int i = 0; i < (int)(words.size()); i++)
371     {
372       nameFixed += words[i];
373     }
374
375   words.clear();
376   CDMUtilities::splitter::split(words,authors," '/\"\\,.",CDMUtilities::splitter::no_empties);
377   std::string authorFixed;
378   for (int i = 0; i < (int)(words.size()); i++)
379     {
380       authorFixed += words[i];
381     }
382
383   words.clear();
384   std::string descriptionFixed;
385   CDMUtilities::splitter::split(words,authorsEmail," '/\"\\,",CDMUtilities::splitter::no_empties);
386   for (int i = 0; i < (int)(words.size()); i++)
387     {
388       descriptionFixed += words[i] + "/";
389     }
390   words.clear();
391   CDMUtilities::splitter::split(words,description," '\"",CDMUtilities::splitter::no_empties);
392   for (int i = 0; i < (int)(words.size()); i++)
393     {
394       descriptionFixed += "_" + words[i];
395     }
396
397   //call project to create package : use bbCreatePackage <path> <name> [author] [description]
398   std::string creationCommand = "bbCreatePackage \"" + this->path + "\" \"" + nameFixed + "\" \"" + authorFixed + "\" \"" + descriptionFixed + "\"";
399   //TODO: bbCreatePackage script always returning 0. It should return 1 or greater if any error
400   bool resultCommand = 0 != system(creationCommand.c_str());
401 #ifdef _WIN32
402   resultCommand = false;
403 #endif
404   if(resultCommand)
405     {
406       result = new std::string("An error occurred while running '" + creationCommand + "'.");
407       return NULL;
408     }
409
410   //add library to project CMakeLists
411   std::fstream out1((this->path + CDMUtilities::SLASH + "CMakeLists.txt").c_str(), std::fstream::in | std::fstream::out | std::fstream::app);
412   if (out1.is_open())
413     {
414       out1 << "ADD_SUBDIRECTORY(bbtk_" << nameFixed << "_PKG)" << std::endl;
415       out1.close();
416     }
417
418   //add library to model
419   modelCDMPackage* package = new modelCDMPackage(this, this->path + CDMUtilities::SLASH + "bbtk_" + nameFixed + "_PKG", "bbtk_" + nameFixed + "_PKG", this->level + 1);
420   this->packages.push_back(package);
421   this->children.push_back(package);
422
423   //TODO: set package version
424
425   this->SortChildren();
426
427   result = new std::string(this->path + CDMUtilities::SLASH + name);
428   return package;
429 }
430
431 modelCDMIProjectTreeNode* modelCDMProject::CreateLibrary(
432     const std::string& name,
433     std::string*& result,
434     const std::string& path
435 )
436 {
437   if(this->lib != NULL)
438     {
439       return this->lib->CreateLibrary(name, result);
440     }
441   result = new std::string("there is no lib folder in this project.");
442   return NULL;
443 }
444
445 modelCDMIProjectTreeNode* modelCDMProject::CreateApplication(
446     const std::string& name,
447     const int& type,
448     std::string*& result,
449     const std::string& path
450 )
451 {
452   if(this->appli != NULL)
453     {
454       return this->appli->CreateApplication(name, type, result);
455     }
456   result = new std::string("there is no appli folder in this project.");
457   return NULL;
458 }
459
460 modelCDMIProjectTreeNode* modelCDMProject::CreateBlackBox(
461     const std::string& name,
462     const std::string& package,
463     const std::string& authors,
464     const std::string& authorsEmail,
465     const std::string& categories,
466     const std::string& description
467 )
468 {
469   //TODO: implement method
470   return NULL;
471 }
472
473 bool modelCDMProject::OpenCMakeListsFile(std::string*& result)
474 {
475   if (!CDMUtilities::openTextEditor(this->CMakeLists->GetPath()))
476     return true;
477   else
478     {
479       result = new std::string("Couldn't open CMakeLists file.");
480       return false;
481     }
482 }
483
484 const bool modelCDMProject::Refresh(std::string*& result)
485 {
486   std::cout << "refreshing project" << std::endl;
487   //open makelists file
488   std::string pathMakeLists = this->path + CDMUtilities::SLASH + "CMakeLists.txt";
489
490   std::ifstream confFile;
491   confFile.open((pathMakeLists).c_str());
492
493   std::string word;
494   while(confFile.is_open() && !confFile.eof())
495     {
496       //std::cout << "leyendo " << word << std::endl;
497       //get project name
498       std::getline(confFile,word,'(');
499       std::vector<std::string> wordBits;
500       CDMUtilities::splitter::split(wordBits,word," (\n",CDMUtilities::splitter::no_empties);
501
502       if(wordBits[wordBits.size()-1] == "PROJECT")
503         {
504           std::getline(confFile,word,')');
505           std::vector<std::string> nameBits;
506           CDMUtilities::splitter::split(nameBits, word, " ", CDMUtilities::splitter::no_empties);
507
508           this->name = this->nameProject = "";
509           for (int i = 0; i < (int)(nameBits.size()); i++)
510             {
511               if(i != 0)
512                 this->name += " ";
513               this->name += nameBits[i];
514             }
515           this->nameProject = this->name;
516
517         }
518
519
520       if(wordBits[wordBits.size()-1] == "SET")
521         {
522           //get project version
523           std::getline(confFile,word,')');
524           CDMUtilities::splitter::split(wordBits, word, " ", CDMUtilities::splitter::no_empties);
525           if(wordBits[0] == "PROJECT_MAJOR_VERSION")
526             {
527               version = wordBits[1];
528             }
529           if(wordBits[0] == "PROJECT_MINOR_VERSION")
530             {
531               version += "." + wordBits[1];
532             }
533           if(wordBits[0] == "PROJECT_BUILD_VERSION")
534             {
535               version += "." + wordBits[1];
536             }
537
538           //get project versionDate
539           if(wordBits[0] == "PROJECT_VERSION_DATE")
540             {
541               std::vector<std::string> versionBits;
542               CDMUtilities::splitter::split(versionBits, wordBits[1], "\"", CDMUtilities::splitter::no_empties);
543               versionDate = versionBits[0];
544             }
545         }
546     }
547   confFile.close();
548
549   this->type = wxDIR_DIRS;
550   this->level = 0;
551
552   std::vector<bool> checked(this->children.size(), false);
553   std::vector<bool> checkedPackages(this->packages.size(), false);
554
555   //check all folders
556   wxDir dir(crea::std2wx((this->path).c_str()));
557   if (dir.IsOpened())
558     {
559       wxString fileName;
560       bool cont = dir.GetFirst(&fileName, wxEmptyString, wxDIR_DIRS);
561       while (cont)
562         {
563           std::string stdfileName = crea::wx2std(fileName);
564
565           //if appli, create appli
566           if(stdfileName == "appli")
567             {
568               if (this->appli == NULL)
569                 {
570                   this->appli = new modelCDMAppli(this, this->path + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1);
571                   this->children.push_back(this->appli);
572                 }
573               else
574                 {
575                   int pos = std::find(this->children.begin(), this->children.end(), this->appli) - this->children.begin();
576                   checked[pos] = true;
577                   if(!this->appli->Refresh(result))
578                     return false;
579                 }
580             }
581           //if lib, create lib
582           else if(stdfileName == "lib")
583             {
584               if (this->lib == NULL)
585                 {
586                   this->lib = new modelCDMLib(this, this->path + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1);
587                   this->children.push_back(this->lib);
588                 }
589               else
590                 {
591                   int pos = std::find(this->children.begin(), this->children.end(), this->lib) - this->children.begin();
592                   checked[pos] = true;
593                   if(!this->lib->Refresh(result))
594                     return false;
595                 }
596
597             }
598           //if package , create package
599           else if(stdfileName.size() > 9 && stdfileName.substr(0,5) == "bbtk_" && stdfileName.substr(stdfileName.size()-4,4) == "_PKG")
600             {
601               bool found = false;
602               for (int i = 0; !found && i < (int)(this->packages.size()); i++)
603                 {
604                   if (this->packages[i]->GetName() == stdfileName)
605                     {
606                       found = true;
607                       int pos = std::find(this->children.begin(), this->children.end(), this->packages[i]) - this->children.begin();
608                       checked[pos] = true;
609                       checkedPackages[i] = true;
610                       if(!this->packages[i]->Refresh(result))
611                         return false;
612                     }
613                 }
614               if(!found)
615                 {
616                   modelCDMPackage* package = new modelCDMPackage(this, this->path + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1);
617                   this->packages.push_back(package);
618                   this->children.push_back(package);
619                 }
620
621             }
622           //if is an unknown folder, create folder
623           else
624             {
625               bool found = false;
626               for (int i = 0; !found && i < (int)(this->children.size()); i++)
627                 {
628                   if (this->children[i]->GetName() == stdfileName)
629                     {
630                       found = true;
631                       checked[i] = true;
632                       if(!this->children[i]->Refresh(result))
633                         return false;
634                     }
635                 }
636
637               if(!found)
638                 {
639                   modelCDMFolder* folder = new modelCDMFolder(this, this->path + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1);
640                   this->children.push_back(folder);
641                 }
642             }
643
644           cont = dir.GetNext(&fileName);
645         }
646
647       cont = dir.GetFirst(&fileName, wxEmptyString, wxDIR_FILES);
648       while (cont)
649         {
650           std::string stdfileName = crea::wx2std(fileName);
651           std::size_t fileTypePos = stdfileName.find_last_of(".");
652           std::string fileType = stdfileName.substr(fileTypePos);
653
654           //if CMakeLists, create CMakeLists
655           if(stdfileName == "CMakeLists.txt")
656             {
657               if (this->CMakeLists == NULL)
658                 {
659                   this->CMakeLists = new modelCDMCMakeListsFile(this, this->path + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1);
660                   this->children.push_back(this->CMakeLists);
661                 }
662               else
663                 {
664                   int pos = std::find(this->children.begin(), this->children.end(), this->CMakeLists) - this->children.begin();
665                   checked[pos] = true;
666                   if(!this->CMakeLists->Refresh(result))
667                     return false;
668                 }
669             }
670           //if is a code file, create modelCDMCodeFile
671           //if is an unknown file, create file
672           else
673             {
674               bool found = false;
675               for (int i = 0; !found && i < (int)(this->children.size()); i++)
676                 {
677                   if (this->children[i]->GetName() == stdfileName)
678                     {
679                       found = true;
680                       checked[i] = true;
681                       if(!this->children[i]->Refresh(result))
682                         return false;
683                     }
684                 }
685
686               if(!found)
687                 {
688                   if(
689                     fileType == ".c" ||
690                     fileType == ".cxx" ||
691                     fileType == ".h" ||
692                     fileType == ".cpp" ||
693                     fileType == ".txx" ||
694                     fileType == ".cmake" )
695                     {
696                       this->children.push_back(new modelCDMCodeFile(this, this->path + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1));
697                     }
698                   else
699                     {
700                       modelCDMFile* file = new modelCDMFile(this, this->path + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1);
701                       this->children.push_back(file);
702                     }
703                 }
704             }
705
706           cont = dir.GetNext(&fileName);
707         }
708     }
709
710   for (int i = 0; i < (int)(checkedPackages.size()); i++)
711     {
712       if(!checkedPackages[i])
713         {
714           this->packages.erase(this->packages.begin()+i);
715           checkedPackages.erase(checkedPackages.begin()+i);
716           i--;
717         }
718     }
719   for (int i = 0; i < (int)(checked.size()); i++)
720     {
721       if(!checked[i])
722         {
723           delete this->children[i];
724           this->children.erase(this->children.begin()+i);
725           checked.erase(checked.begin()+i);
726           i--;
727         }
728     }
729
730   this->SortChildren();
731   std::sort(this->packages.begin(), this->packages.end(), CompareNodeItem);
732   return true;
733 }
734
735 bool modelCDMProject::ConfigureBuild(std::string*& result)
736 {
737   //TODO: adjust for windows and mac
738 #ifdef _WIN32
739   // ------ Windows
740   if(0 == system("cmake-gui"))
741     return true;
742   else
743     {
744           result = new std::string("There was an error opening cmake-gui. Please make sure it's installed and that cmake's bin folder is in the system path.");
745       return false;
746     }
747 #elif __APPLE__
748   // ------ Apple
749 #else
750   // ------ Linux
751   //open binary folder
752   wxDir dir(crea::std2wx((this->buildPath).c_str()));
753
754   //if folder doesn't exist then create it
755   if (!dir.IsOpened())
756     {
757       //create command line to create folder
758       std::string createComm = "mkdir \"" + this->buildPath + "\"";
759       //execute creation command
760       if (system(createComm.c_str()))
761         {
762           //if there was an error then report it
763           result = new std::string("There was an error creating the build path: \"" + this->buildPath + "\"");
764           return false;
765         }
766     }
767   //create command line to execute ccmake
768   //TODO:: adjust for different Linux distributions
769   std::string confComm = "gnome-terminal --tab --working-directory=\"" + this->buildPath + "\" -e \"ccmake '" + this->path + "'\"";
770   //execute command
771   if(CDMUtilities::openTerminal(confComm))
772     {
773       //if there was an error then report it
774       result = new std::string("There was an error opening the configuration tool in the desired place.");
775       return false;
776     }
777 #endif
778   return true;
779 }
780
781 bool modelCDMProject::Build(std::string*& result, const std::string& line)
782 {
783   //TODO: adjust for windows and mac
784 #ifdef _WIN32
785   // ------ Windows
786         std::string command = "start \"\" \"" + this->buildPath + CDMUtilities::SLASH + this->nameProject + ".sln\"";
787   //wxMessageBox(crea::std2wx(command), wxT("Project Compilation - Check!"));
788         if(0 == system(command.c_str()))
789     return true;
790   else
791     {
792       result = new std::string("An error has happened running: \"" + command + "\". Please make sure to have visual c++ installed.");
793           return false;
794     }
795 #elif __APPLE__
796   // ------ Apple
797 #else
798   // ------ Linux
799   //open binary folder
800   wxDir dir(crea::std2wx((this->buildPath).c_str()));
801
802   //if binary folder can't be opened then return false
803   if (!dir.IsOpened())
804     {
805       result = new std::string("The build path could not be opened. Make sure to configure the project before compiling it");
806       return false;
807     }
808   //create make command
809   std::string makeComm = "gnome-terminal -e \"bash -c \\\"";
810   for (int i = 0; i < line.size(); i++)
811     {
812       if(line[i] == '"')
813         {
814           makeComm+="\\\\\\\"";
815         }
816       else if(line[i] == '\\')
817         {
818           makeComm+="\\\\\\\\";
819         }
820       else
821         {
822           makeComm.push_back(line[i]);
823         }
824     }
825   makeComm += "; echo -e '\\a'; bash";
826   makeComm += "\\\"\"";
827
828   std::cout << "executing '" << makeComm << "'" << std::endl;
829   //execute make command
830   if(system(makeComm.c_str()))
831     {
832       //if there was an error then report it
833       result = new std::string("There was an error compiling the project, please check the \"building.log\" file located in the build folder to read more about the problem.");
834       return false;
835     }
836 #endif
837   return true;
838 }
839
840 bool modelCDMProject::Connect(std::string*& result, const std::string& folder)
841 {
842   //TODO: adjust for mac
843 #ifdef _WIN32
844   // ------ Windows
845   //open binary folder
846   wxDir dir(crea::std2wx(folder));
847
848   //if binary folder can't be opened then return false
849   if (!dir.IsOpened())
850     {
851       result = new std::string("The path could not be opened. Make sure the folder exists and contains a bbtkPackage file.");
852       return false;
853     }
854   //create plug command
855   std::string plugComm = "bbPlugPackage \"" + folder + "\"";
856   std::cout << "executing '" << plugComm << "'" << std::endl;
857   //execute plug command
858   if(system(std::string("start cmd.exe /k \"" + plugComm + "\"").c_str()))
859     {
860       //if there was an error then report it
861       result = new std::string("There was an error plugging the packages of the project, please check the console to read more about the problem.");
862       return false;
863     }
864 #elif __APPLE__
865   // ------ Apple
866 #else
867   // ------ Linux
868   //open binary folder
869   wxDir dir(crea::std2wx(folder));
870
871   //if binary folder can't be opened then return false
872   if (!dir.IsOpened())
873     {
874       result = new std::string("The path could not be opened. Make sure the folder exists and contains a bbtkPackage file.");
875       return false;
876     }
877   //create plug command
878   std::string plugComm = "bbPlugPackage \"" + this->buildPath + "\"";
879
880   std::string Comm = "gnome-terminal -e \"bash -c \\\"";
881     for (int i = 0; i < plugComm.size(); i++)
882       {
883         if(plugComm[i] == '"')
884           {
885             Comm+="\\\\\\\"";
886           }
887         else if(plugComm[i] == '\\')
888           {
889             Comm+="\\\\\\\\";
890           }
891         else
892           {
893             Comm.push_back(plugComm[i]);
894           }
895       }
896     Comm += "; echo -e '\\a'; bash";
897     Comm += "\\\"\"";
898
899
900   std::cout << "executing '" << Comm << "'" << std::endl;
901   //execute plug command
902   if(system(Comm.c_str()))
903     {
904       //if there was an error then report it
905       result = new std::string("There was an error plugging the packages of the project, please check the console to read more about the problem.");
906       return false;
907     }
908 #endif
909   return true;
910 }
911
912 void modelCDMProject::CheckStructure(std::map<std::string, bool>& properties)
913 {
914   //check cmake exist
915   if(this->CMakeLists != NULL)
916     {
917       //set properties parameters based on model
918       properties["project add appli"] = this->appli != NULL;
919       properties["project add lib"] = this->lib != NULL;
920       for (int i = 0; i < (int)(this->packages.size()); i++)
921         properties["project add " + packages[i]->GetName()] = false;
922
923       //open cmakelists
924       std::ifstream confFile;
925       confFile.open((this->CMakeLists->GetPath()).c_str());
926
927       //take everything that is not commented
928       std::string fileContent;
929
930       std::string word;
931       std::vector<std::string> words;
932       while(confFile.is_open() && !confFile.eof())
933         {
934           std::getline(confFile,word, '\n');
935           if(word[0] != '#')
936             {
937               CDMUtilities::splitter::split(words, word, "#", CDMUtilities::splitter::empties_ok);
938               if (words.size() > 0)
939                 {
940                   word = words[0];
941                   CDMUtilities::splitter::split(words, word, " ", CDMUtilities::splitter::empties_ok);
942                   for (int i = 0; i < (int)(words.size()); i++)
943                     {
944                       if(words[i].substr(0,2) == "//")
945                         break;
946                       fileContent += words[i] + " ";
947                     }
948                 }
949
950             }
951         }
952
953       //check every instruction
954       std::stringstream ss(fileContent);
955       while(!ss.eof())
956         {
957           std::getline(ss,word, '(');
958
959           //check instruction name
960           CDMUtilities::splitter::split(words, word, " ", CDMUtilities::splitter::no_empties);
961
962           //set instructions
963           if (words.size() > 0 && words[words.size()-1] == "SET")
964             {
965               std::getline(ss,word, ')');
966
967               CDMUtilities::splitter::split(words, word, " ", CDMUtilities::splitter::no_empties);
968               if (words.size() > 1)
969                 {
970                   if (words[0] == "USE_CREA" && words[1] == "ON")
971                     {
972                       properties["project set USE_CREA"] = true;
973                     }
974                   else if (words[0] == "USE_GDCM" && words[1] == "ON")
975                     {
976                       properties["project set USE_GDCM"] = true;
977                     }
978                   else if (words[0] == "USE_GDCM_VTK" && words[1] == "ON")
979                     {
980                       properties["project set USE_GDCM_VTK"] = true;
981                     }
982                   else if (words[0] == "USE_GDCM2" && words[1] == "ON")
983                     {
984                       properties["project set USE_GDCM2"] = true;
985                     }
986                   else if (words[0] == "USE_WXWIDGETS" && words[1] == "ON")
987                     {
988                       properties["project set USE_WXWIDGETS"] = true;
989                     }
990                   else if (words[0] == "USE_KWWIDGETS" && words[1] == "ON")
991                     {
992                       properties["project set USE_KWWIDGETS"] = true;
993                     }
994                   else if (words[0] == "USE_VTK" && words[1] == "ON")
995                     {
996                       properties["project set USE_VTK"] = true;
997                     }
998                   else if (words[0] == "USE_ITK" && words[1] == "ON")
999                     {
1000                       properties["project set USE_ITK"] = true;
1001                     }
1002                   else if (words[0] == "USE_BOOST" && words[1] == "ON")
1003                     {
1004                       properties["project set USE_BOOST"] = true;
1005                     }
1006                 }
1007             }
1008           //add instructions
1009           else if (words.size() > 0 && words[words.size()-1] == "ADD_SUBDIRECTORY")
1010             {
1011               std::getline(ss,word, ')');
1012               //std::cout << word << std::endl;
1013               CDMUtilities::splitter::split(words, word, " ", CDMUtilities::splitter::no_empties);
1014
1015               if (words.size() > 0)
1016                 {
1017                   if(words[0] == "appli")
1018                     {
1019                       properties["project add "+words[0]] = this->appli != NULL;
1020                     }
1021                   else if(words[0] == "lib")
1022                     {
1023                       properties["project add "+words[0]] = this->lib != NULL;
1024                     }
1025                   else
1026                     {
1027                       properties["project add "+words[0]] = true;
1028                     }
1029                 }
1030             }
1031         }
1032
1033     }
1034
1035   //check appli's structure
1036   this->appli->CheckStructure(properties);
1037   //check lib's structure
1038   this->lib->CheckStructure(properties);
1039   //check packages' structure
1040   for (int i = 0; i < (int)(this->packages.size()); i++)
1041     {
1042       properties["package " + this->packages[i]->GetName()] = true;
1043       this->packages[i]->CheckStructure(properties);
1044     }
1045 }
1046
1047 bool modelCDMProject::IsPackageIncluded(const std::string& package_name)
1048 {
1049   if (this->HasCMakeLists())
1050     {
1051       CDMUtilities::CMLFile cmlFile = CDMUtilities::readCMLFile(this->CMakeLists->GetPath().c_str());
1052       for (int i = 0; i < cmlFile.size(); ++i)
1053         {
1054           if (cmlFile[i].first=="command" && cmlFile[i].second[0] == "ADD_SUBDIRECTORY")
1055             {
1056               int pos = 1;
1057               while (pos < cmlFile[i].second.size())
1058                 {
1059                   if (!isspace(cmlFile[i].second[pos][0]) && cmlFile[i].second[pos][0] != '(' && cmlFile[i].second[pos][0] != '#')
1060                     {
1061                       if (package_name == cmlFile[i].second[pos])
1062                         return true;
1063                       break;
1064                     }
1065                   pos++;
1066                 }
1067             }
1068         }
1069     }
1070   return false;
1071
1072 }
1073
1074 bool modelCDMProject::SetPackageInclude(const std::string& package_name, const bool& toInclude)
1075 {
1076   if (this->HasCMakeLists())
1077     {
1078       CDMUtilities::CMLFile cmlFile = CDMUtilities::readCMLFile(this->CMakeLists->GetPath().c_str());
1079
1080       bool found = false;
1081
1082       for (int i = 0; i < cmlFile.size(); ++i)
1083         {
1084           if(toInclude && cmlFile[i].first == "comment")
1085             {
1086               std::vector<std::string> segments;
1087               std::string line = cmlFile[i].second[0];
1088               while(line[0] == '#')
1089                 line.erase(0,1);
1090
1091               CDMUtilities::splitter::split(segments, line, " ()", CDMUtilities::splitter::no_empties);
1092               if (segments.size() > 1 && segments[0] == "ADD_SUBDIRECTORY" && segments[1] == package_name)
1093                 {
1094                   found = true;
1095                   while(cmlFile[i].second[0][0] == '#')
1096                     cmlFile[i].second[0].erase(0,1);
1097                 }
1098             }
1099           else if(cmlFile[i].first == "command" && cmlFile[i].second[0] == "ADD_SUBDIRECTORY")
1100             {
1101               int pos = 1;
1102               while (pos < cmlFile[i].second.size())
1103                 {
1104                   if (!isspace(cmlFile[i].second[pos][0]) && cmlFile[i].second[pos][0] != '(' && cmlFile[i].second[pos][0] != '#')
1105                     {
1106                       if (package_name == cmlFile[i].second[pos])
1107                         {
1108                           found = true;
1109                           if (!toInclude)
1110                             {
1111                               cmlFile[i].first = "comment";
1112                               cmlFile[i].second[0] = "#" + cmlFile[i].second[0];
1113                               while (cmlFile[i].second.size() > 1)
1114                                 {
1115                                   cmlFile[i].second[0] += cmlFile[i].second[1];
1116                                   cmlFile[i].second.erase(cmlFile[i].second.begin()+1);
1117                                 }
1118
1119                             }
1120                         }
1121                       break;
1122                     }
1123                   pos++;
1124                 }
1125             }
1126         }
1127       if (!found && toInclude)
1128         {
1129           CDMUtilities::syntaxElement element;
1130           element.first = "command";
1131           element.second.push_back("ADD_SUBDIRECTORY(" + package_name + ")");
1132           cmlFile.push_back(element);
1133         }
1134
1135       return CDMUtilities::writeCMLFile(this->CMakeLists->GetPath().c_str(),cmlFile);
1136     }
1137   return false;
1138 }
1139
1140 std::map<std::string, bool> modelCDMProject::Get3rdPartyLibraries()
1141 {
1142   std::map<std::string, std::string> correspondence;
1143   correspondence["USE_CREA"] = "Crea";
1144   correspondence["USE_GDCM"] = "GDCM";
1145   correspondence["USE_GDCM_VTK"] = "GDCM_VTK";
1146   correspondence["USE_GDCM2"] = "GDCM2";
1147   correspondence["USE_WXWIDGETS"] = "WxWidgets";
1148   correspondence["USE_KWWIDGETS"] = "KWWidgets";
1149   correspondence["USE_VTK"] = "VTK";
1150   correspondence["USE_ITK"] = "ITK";
1151   correspondence["USE_BOOST"] = "Boost";
1152
1153   std::map<std::string, bool> res;
1154   res["Crea"] = false;
1155   res["GDCM"] = false;
1156   res["GDCM_VTK"] = false;
1157   res["GDCM2"] = false;
1158   res["WxWidgets"] = false;
1159   res["KWWidgets"] = false;
1160   res["VTK"] = false;
1161   res["ITK"] = false;
1162   res["Boost"] = false;
1163
1164   if (this->HasCMakeLists())
1165     {
1166       std::string CMfile = CDMUtilities::readFile(this->CMakeLists->GetPath().c_str());
1167
1168       boost::regex expression("^\\h*SET([\\s]|#[^\\n]*\\n)*\\(([\\s]|#[^\\n]*\\n)*USE_\\w+\\s+ON");
1169       std::string::const_iterator start, end;
1170       start = CMfile.begin();
1171       end = CMfile.end();
1172       boost::match_results<std::string::const_iterator> what;
1173       boost::match_flag_type flags = boost::match_default;
1174       while(boost::regex_search(start, end, what, expression, flags))
1175         {
1176           //std::cout << what[0].str() << std::endl;
1177           boost::regex expression1 = boost::regex("USE_\\w+");
1178           std::string::const_iterator start1, end1;
1179           start1 = what[0].first;
1180           end1 = what[0].second;
1181           boost::match_results<std::string::const_iterator> what1;
1182           if(boost::regex_search(start1, end1, what1, expression1, flags))
1183             {
1184               std::string dete = what1.str();
1185               CDMUtilities::normalizeStr(dete);
1186               //std::cout << dete << std::endl;
1187               if(correspondence.find(dete) != correspondence.end())
1188                 res[correspondence[dete]] = true;
1189             }
1190           start = what[0].second;
1191         }
1192     }
1193
1194   return res;
1195 }
1196
1197 bool modelCDMProject::Set3rdPartyLibrary(const std::string& library_name,
1198     const bool& toInclude)
1199 {
1200   std::map<std::string, std::string> correspondence;
1201   correspondence["Crea"] = "USE_CREA";
1202   correspondence["GDCM"] = "USE_GDCM";
1203   correspondence["GDCM_VTK"] = "USE_GDCM_VTK";
1204   correspondence["GDCM2"] = "USE_GDCM2";
1205   correspondence["WxWidgets"] = "USE_WXWIDGETS";
1206   correspondence["KWWidgets"] = "USE_KWWIDGETS";
1207   correspondence["VTK"] = "USE_VTK";
1208   correspondence["ITK"] = "USE_ITK";
1209   correspondence["Boost"] = "USE_BOOST";
1210
1211   if (correspondence.find(library_name) != correspondence.end())
1212     {
1213       std::string library_command = correspondence[library_name];
1214
1215       if (this->HasCMakeLists())
1216         {
1217           std::string CMfile = CDMUtilities::readFile(this->CMakeLists->GetPath().c_str());
1218           std::string resCMfile = "";
1219
1220           std::string::const_iterator start, end;
1221           boost::match_results<std::string::const_iterator> what, tmp;
1222           boost::match_flag_type flags = boost::match_default;
1223           bool found = false;
1224
1225           start = CMfile.begin();
1226           end = CMfile.end();
1227
1228           //search for existing inclusions
1229           boost::regex expression("^\\h*SET([\\s]|#[^\\n]*\\n)*\\(([\\s]|#[^\\n]*\\n)*" + library_command + "\\s+ON\\s*\\)");
1230           while(boost::regex_search(start, end, what, expression, flags))
1231             {
1232               found = true;
1233               resCMfile += what.prefix().str();
1234               if(!toInclude)
1235                 {
1236                   std::string dete = what.str();
1237                   int pos = dete.find("ON",0);
1238                   dete.replace(pos, 2, "OFF");
1239                   resCMfile += dete;
1240                 }
1241               else
1242                 resCMfile += what.str();
1243               tmp = what;
1244               start = what[0].second;
1245             }
1246
1247           if (found)
1248             resCMfile += tmp.suffix().str();
1249           else
1250             {
1251               start = CMfile.begin();
1252               end = CMfile.end();
1253
1254               //search for existing exclusions
1255               boost::regex expression("^\\h*SET([\\s]|#[^\\n]*\\n)*\\(([\\s]|#[^\\n]*\\n)*" + library_command + "\\s+OFF\\s*\\)");
1256               while(boost::regex_search(start, end, what, expression, flags))
1257                 {
1258                   found = true;
1259                   resCMfile += what.prefix().str();
1260                   if(toInclude)
1261                     {
1262                       std::string dete = what.str();
1263                       int pos = dete.find("OFF",0);
1264                       dete.replace(pos, 3, "ON");
1265                       resCMfile += dete;
1266                     }
1267                   else
1268                     resCMfile += what.str();
1269                   tmp = what;
1270                   start = what[0].second;
1271                 }
1272
1273               if (found)
1274                 resCMfile += tmp.suffix().str();
1275               else
1276                 {
1277                   start = CMfile.begin();
1278                   end = CMfile.end();
1279
1280                   //search for existing commented inclusions
1281                   expression = boost::regex("^\\h*#+\\h*SET([\\s]|#[^\\n]*\\n)*\\(([\\s]|#[^\\n]*\\n)*" + library_command + "\\s+ON\\s*\\)");
1282                   while(boost::regex_search(start, end, what, expression, flags))
1283                     {
1284                       found = true;
1285                       resCMfile += what.prefix().str();
1286                       if(toInclude)
1287                         {
1288                           std::string dete = what.str();
1289                           for (int i = 0; i < dete.size(); ++i) {
1290                             if(dete[i] == '#')
1291                               {
1292                                 dete.erase(i,1);
1293                                 i--;
1294                               }
1295                           }
1296                           resCMfile += dete;
1297                         }
1298                       else
1299                         resCMfile += what.str();
1300
1301                       tmp = what;
1302                       start = what[0].second;
1303                     }
1304
1305                   if (found)
1306                     resCMfile += tmp.suffix().str();
1307                   else
1308                     {
1309                       if(toInclude)
1310                         {
1311                           start = CMfile.begin();
1312                           end = CMfile.end();
1313
1314                           //search for position to insert
1315                           expression = boost::regex("^\\h*#\\h*Libraries\\/tools used\\h*$");
1316                           if(boost::regex_search(start, end, what, expression, flags))
1317                             {
1318                               found = true;
1319                               resCMfile += what.prefix().str();
1320                               resCMfile += what.str();
1321                               resCMfile += "\nSET(" + library_command + " ON)";
1322                               resCMfile += what.suffix().str();
1323                             }
1324                         }
1325                       else
1326                         {
1327                           found = true;
1328                         }
1329                     }
1330                 }
1331             }
1332           if (!found) {
1333             return false;
1334           }
1335           else
1336             return CDMUtilities::writeFile(this->CMakeLists->GetPath().c_str(), resCMfile);
1337         }
1338     }
1339
1340   return false;
1341 }