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