]> Creatis software - bbtk.git/blob - kernel/src/bbtkExecuter.cxx
Allow user to always forget .bbs
[bbtk.git] / kernel / src / bbtkExecuter.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   bbtk
4   Module:    $RCSfile: bbtkExecuter.cxx,v $ $
5   Language:  C++
6   Date:      $Date: 2008/01/22 15:02:00 $
7   Version:   $Revision: 1.1 $
8                                                                                 
9   Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
10   l'Image). All rights reserved. See Doc/License.txt or
11   http://www.creatis.insa-lyon.fr/Public/bbtk/License.html for details.
12                                                                                 
13      This software is distributed WITHOUT ANY WARRANTY; without even
14      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15      PURPOSE.  See the above copyright notices for more information.
16                                                                                 
17 =========================================================================*/
18 /**
19  *  \file 
20  *  \brief class Executer: level 0 of script execution (code)
21  */
22
23 #include "bbtkExecuter.h" 
24 #include "bbtkMessageManager.h"
25 #include "bbtkFactory.h"
26 #include "bbtkUtilities.h"
27
28 #include <fstream>
29
30 #ifdef _USE_WXWIDGETS_
31 #include <wx/textdlg.h>
32 #endif
33
34 #include "bbtkWxBlackBox.h"
35
36 #include "bbtkConfigurationFile.h"
37
38 namespace bbtk
39 {  
40 /**
41  *  
42  */
43   Executer::Executer() 
44     : mPackage(0),
45       mRoot(0),
46       mNoExecMode(false),
47       mDialogMode(NoDialog)
48   {
49     //VirtualExec();
50     
51     bbtkDebugMessageInc("Core",9,"Executer::Executer()" <<std::endl);
52     Reset();
53     bbtkDebugDecTab("Core",9);
54   } 
55   
56 /**
57  *  
58  */
59   Executer::~Executer()
60   {
61      bbtkDebugMessageInc("Core",9,"Executer::~Executer()" <<std::endl);
62      if (mRoot) 
63      {
64         mPackage->UnRegisterBlackBox("workspace");
65         delete mRoot;    
66      }
67      if (mPackage) 
68      {
69         GetGlobalFactory()->UnLoadPackage("user");
70      }
71      bbtkDebugDecTab("Core",9);
72   }
73   
74
75 /**
76  *  
77  */
78   void Executer::Reset()
79   {
80     bbtkDebugMessageInc("Core",9,"Executer::Reset()" <<std::endl);
81
82     // The 'user' package must be closed before all other 
83     // because box destructors must not be unloaded when bb are deleted!
84     // Similarly, the 'workspace' CBB must be destroyed before 
85     // all user defined CBB otherwise any instance 
86     // of a user CBB that is in the 'workspace' would try to 
87     // access a user CBB descriptor which has been previously freed
88     if (mRoot) 
89     {
90        mPackage->UnRegisterBlackBox(mRoot->GetTypeName());
91        delete mRoot;    
92     }
93     if (mPackage) 
94     {
95        GetGlobalFactory()->UnLoadPackage("user");
96     }
97     GetGlobalFactory()->Reset();
98     // Create user package
99     mPackage = new Package("user","internal to bbi",
100                            "User defined black boxes",
101                            "",
102                            BBTK_STRINGIFY_SYMBOL(BBTK_VERSION));
103     // Create user workspace
104     mRoot = new ComplexBlackBoxDescriptor("workspace"); //,f);
105     mRoot->AddToAuthor("bbi (internal)");
106     mRoot->AddToDescription("User's workspace");
107     mCurrent.push_back(CBBDefinition(mRoot,"user"));
108     // Register it into the user package
109     mPackage->RegisterBlackBox(mRoot);
110     // Insert the user package in the factory
111     InsertPackage(mPackage);
112
113     bbtkDebugDecTab("Core",9);
114   }
115   
116   /// changes the workspace name
117   void Executer::SetWorkspaceName( const std::string& n )
118   {
119     mPackage->ChangeBlackBoxName( mRoot->GetTypeName(), n );
120   }
121   
122
123   void Executer::Define (const std::string &name,
124                          const std::string &pack,
125                          const std::string &scriptfilename)
126   {
127     bbtkDebugMessageInc("Core",9,"Executer::Define(\""<<name<<
128                         ","<<pack<<"\")" 
129                         <<std::endl);
130
131     ComplexBlackBoxDescriptor* b = new ComplexBlackBoxDescriptor(name);
132     b->SetScriptFileName(scriptfilename);
133     mCurrent.push_back( CBBDefinition( b, pack ) );
134     
135     bbtkDebugDecTab("Core",9);
136   }
137
138   void Executer::EndDefine ()
139   {
140     bbtkDebugMessageInc("Core",9,"Executer::EndDefine(\""
141                         <<Current()->GetTypeName()<<"\")" 
142                         <<std::endl);
143     // Does current package exist ?
144     std::string pname(mCurrent.back().package);
145     Package* p;
146     try 
147       {
148         p = GetGlobalFactory()->GetPackage(pname);
149       }
150     catch (Exception e)
151       {
152         p = new Package(pname,
153                         "",
154                         "",
155                         "",
156                         BBTK_STRINGIFY_SYMBOL(BBTK_VERSION));
157         InsertPackage(p);
158       }
159
160     p->RegisterBlackBox(Current());
161     
162     mCurrent.pop_back();
163   }
164
165
166   void Executer::Create ( const std::string& nodeType, 
167                           const std::string& nodeName)
168   {
169      Current()->Add(nodeType,nodeName);
170   }
171   
172
173   /*
174     void Executer::Remove (const std::string &nodeName)
175   { 
176     // Current()->RemoveBlackBox(nodeName);
177   }
178   */    
179
180 /**
181  *  
182  */
183   void Executer::Connect (const std::string &nodeFrom, 
184                           const std::string &outputLabel, 
185                           const std::string &nodeTo, 
186                           const std::string &inputLabel)
187   {
188     Current()->Connect(nodeFrom, outputLabel, nodeTo, inputLabel); 
189   }
190    
191  /**
192  *  
193  */ 
194   void Executer::Update (const std::string &nodeName) // would 'Execute' be more meaningfull ?
195   {
196  // if in root
197      if (Current()==mRoot) 
198      {
199         if (!mNoExecMode) 
200         {
201            Current()->GetPrototype()->bbGetBlackBox(nodeName)->bbExecute(true);
202         }
203      }
204      else 
205      {
206         Current()->AddToExecutionList(nodeName) ;
207      }
208   }
209     
210 /**
211  *  
212  */
213   void Executer::DefineInput ( const std::string &name,
214                                const std::string &box,
215                                const std::string &input,
216                                const std::string& help)
217   {
218     // If the input is defined in the Root box
219     if (Current()==mRoot) 
220       {
221       // If the dialog mode is set to NoDialog
222       // and the user passed the name in the Inputs map 
223       // then the associated value is set to the box.input
224       // This is the way command line parameters are passed to the Root box
225          if (mDialogMode == NoDialog) 
226          {
227          // find if name is in mInputs
228             std::map<std::string,std::string>::iterator i;
229             i = mInputs.find(name);
230             if (i!=mInputs.end()) {
231                Set(box,input,(*i).second);
232             }
233          }
234         // If the dialog mode is set to TextDialog
235         // The user is prompted for the value
236         else if (mDialogMode == TextDialog) 
237         {
238            std::cout << name << "=";
239            std::string ans;
240            std::cin >> ans;
241            Set(box,input,ans);
242         }
243        #ifdef _USE_WXWIDGETS_
244        // If the dialog mode is set to GraphicalDialog
245        // A dialog box is pop up
246        else if (mDialogMode == GraphicalDialog) 
247        {
248           std::string mess("Enter the value of '");
249           mess += name;
250           mess += "' (";
251           mess += help;
252           mess += ")";
253           std::string title(name);
254           title += " ?";
255     
256           std::string ans = wx2std ( wxGetTextFromUser( std2wx (mess), std2wx(title)));
257           Set(box,input,ans); 
258        }
259 #endif
260     }
261     
262     Current()->DefineInput(name,box,input,help);
263         
264   }
265   
266  /**
267  *  
268  */ 
269    void Executer::DefineOutput ( const std::string &name,
270                                  const std::string &box,
271                                  const std::string &output,
272                                  const std::string& help)
273   {
274     Current()->DefineOutput(name,box,output,help);
275   }
276   
277   /**
278    *  
279    */ 
280   void Executer::Set (const std::string &box,
281                       const std::string &input,
282                       const std::string &value)
283   {
284     BlackBox* b = Current()->GetPrototype()->bbGetBlackBox(box);
285     // Looks for the adaptor
286
287     if ( b->bbGetInputType(input) !=  typeid(std::string) ) 
288       {
289          BlackBox* a = /*mFactory->*/
290          NewAdaptor(typeid(std::string),
291                     b->bbGetInputType(input),
292                     "tmp");
293          if (!a) 
294          {
295             bbtkError("No <"<<
296                       TypeName(b->bbGetInputType(input))
297                       <<"> to <std::string> found");
298          }
299          std::string v(value);
300          a->bbSetInput("In",v);
301          a->bbExecute();
302          b->bbSetInput(input,a->bbGetOutput("Out"));
303          a->bbDelete();
304       }
305     else 
306       {
307       std::string v(value);
308       b->bbSetInput(input,v);
309       }
310   }
311
312   
313   /**
314    *  
315    */ 
316   std::string Executer::Get(const std::string &box,
317                             const std::string &output)
318   {
319     BlackBox* b = Current()->GetPrototype()->bbGetBlackBox(box);
320     // Looks for the adaptor
321     if (b->bbGetOutputType(output) != typeid(std::string)) 
322       {
323       BlackBox* a = /*mFactory->*/
324           NewAdaptor(
325              b->bbGetOutputType(output),
326              typeid(std::string),
327              "tmp");
328       if (!a) 
329         {
330         bbtkError("No <"<<
331                    TypeName(b->bbGetOutputType(output))
332                    <<"> to <std::string> found");
333         }
334         b->bbExecute();
335
336         a->bbSetInput("In",b->bbGetOutput(output));
337         a->bbExecute();
338         std::string r = a->bbGetOutput("Out").unsafe_get<std::string>();
339        //std::string v = *((std::string*)a->bbGetOutput("Out")) ;
340        //   std::cout << a->bbGetOutput("Out").unsafe_get<std::string>() 
341        //             << std::endl;
342        //std::string v(value);
343        //b->bbSetInput(input,a->bbGetOutput("Out"));
344         a->bbDelete();
345         return r;
346       }
347     else 
348       {
349        b->bbExecute();
350        return b->bbGetOutput(output).unsafe_get<std::string>();
351        // std::string v = *((std::string*)b->bbGetOutput(output)) ;
352        // std::cout << b->bbGetOutput("Out").unsafe_get<std::string>() 
353        //   << std::endl;
354        // b->bbSetInput(input,&v);
355       }
356   }
357
358
359   void Executer::Author(const std::string &authorName)
360   {
361     Current()->AddToAuthor(authorName,Current()==mRoot);
362   }
363
364
365
366   void Executer::Description(const std::string &d)
367   {
368      Current()->AddToDescription(d,Current()==mRoot);
369   }
370
371
372   /// prints the list of the boxes of the current descriptor
373   void Executer::PrintBoxes()
374   {  
375     bbtkMessageInc("Help",1,"The black box descriptor \""
376                    <<Current()->GetTypeName()<<"\" contains : "<<std::endl);
377     Current()->PrintBlackBoxes();
378     bbtkDecTab("Help",1);
379  }
380
381
382   std::string Executer::ShowGraph(const std::string &nameblackbox, 
383                                   const std::string &detailStr, 
384                                   const std::string &levelStr,
385                                   const std::string &output_html,
386                                   const std::string &custom_header,
387                                   const std::string &custom_title,
388                                   bool system_display )
389   {
390
391     int detail  =       atoi(detailStr.c_str());
392     int level   =       atoi(levelStr.c_str());
393
394     std::string filename_rootHtml (output_html) ;
395     std::string simplefilename_rootHtml ( Utilities::get_file_name(output_html));
396
397     bool relative_link = true;
398
399     // No output provided : automatic generation
400     if (output_html.length() == 0)
401       {
402         // Don't pollute the file store with  "doc_tmp" directories ...    
403         std::string default_doc_dir = ConfigurationFile::GetInstance().Get_default_doc_tmp();
404         
405         char c = default_doc_dir.c_str()[strlen(default_doc_dir.c_str())-1];
406         
407         std::string directory = default_doc_dir; 
408         if (c != '/' && c !='\\') directory = directory + "/";
409         directory = directory +  "doc_tmp";    
410         
411         filename_rootHtml = directory + "/" + "User.html";
412         simplefilename_rootHtml = "User.html" ;
413
414         // Creating directory
415         std::string command0("mkdir \"" +directory + "\"");
416         system( command0.c_str() );      
417
418         relative_link = false;
419       }
420
421     // Generating documentation-help of workspace
422     mPackage->SetDocURL(filename_rootHtml);
423     mPackage->SetDocRelativeURL(simplefilename_rootHtml);
424
425     mPackage->CreateHtmlPage(filename_rootHtml,"bbi","user package",custom_header,custom_title,detail,level,relative_link);
426     
427     std::string page = filename_rootHtml;
428     /*
429     try 
430       {
431         ShowGraphTypes(nameblackbox);
432       }
433     catch (bbtk::Exception a) 
434       {
435         std::cout <<"EXC"<<std::endl;
436         page = ShowGraphInstances(nameblackbox,detail,level,system_display);
437       }
438     */
439     return page;
440   }
441
442   /// Generate a png file with the actual pipeline (Graphviz-dot needed)
443   std::string Executer::ShowGraphInstances(const std::string &nameblackbox, int detail, int level,
444                                     bool system_display)
445   {
446
447     BlackBox* blackbox=NULL;
448     if (nameblackbox==".")
449       {
450         blackbox=Current()->GetPrototype();
451       } 
452     else 
453       {
454         blackbox = Current()->GetPrototype()->bbFindBlackBox(nameblackbox);
455       }
456     
457     std::string page;
458
459     if (blackbox)
460       {      
461         // Don't pollute the file store with  "doc_tmp" directories ...    
462         std::string default_doc_dir = ConfigurationFile::GetInstance().Get_default_doc_tmp();
463         char c = default_doc_dir.c_str()[strlen(default_doc_dir.c_str())-1];
464         
465         std::string directory = default_doc_dir; 
466         if (c != '/' && c !='\\') directory = directory + "/";
467
468         directory = directory +  "doc_tmp"; 
469         
470         //std::string directory("doc_tmp");
471         std::string filename(directory + "/" + "bbtk_graph_pipeline");
472         std::string filename_html(filename+".html");
473         std::string command0("mkdir \""+directory + "\"");
474
475 #if defined(_WIN32)  
476         std::string command2("start ");
477 #else 
478         std::string command2("gnome-open ");
479 #endif
480
481         command2=command2+filename_html;
482         page = filename_html;
483         // 1. Generate Html Diagram
484         std::ofstream s;
485         s.open(filename_html.c_str());
486         if (s.good()) 
487           {
488             s << "<html><head><title>BBtk graph diagram</title><meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\"></head>\n";
489             s << "<body bgcolor=\"#FFFFFF\" text=\"#000000\"> \n\n";
490             if ( blackbox->bbGetName()=="workspacePrototype" )
491               {
492                 s << "<center>Current workspace</center>";
493               } else {
494               s << "<center>" << blackbox->bbGetName()<< "</center>";
495             } 
496
497             blackbox->bbInsertHTMLGraph( s, detail, level, true, directory, false );
498             s << "</body></html>\n";      
499           }
500         s.close();
501         
502         // 2. Starting Browser
503         if (system_display) system( command2.c_str() );      
504       } 
505     else 
506       {
507         bbtkMessageInc("Help",1,"No black box: \""
508                        <<nameblackbox<<"\" " <<std::endl);
509         
510       }
511     return page;
512   }
513   
514
515 void Executer::ShowRelations(const std::string &nameblackbox, const std::string &detailStr, const std::string &levelStr)
516   {
517        bool found=false;
518
519        int detail = atoi(detailStr.c_str());
520        int level  = atoi(levelStr.c_str());
521        BlackBox* blackbox=NULL;
522        if (nameblackbox.compare(".")==0)
523        {
524           blackbox=Current()->GetPrototype();
525        } else {
526           blackbox = Current()->GetPrototype()->bbFindBlackBox(nameblackbox);
527        }
528
529        if (blackbox)
530        {
531           found=true;
532           blackbox->bbShowRelations(blackbox,detail,level); //,mFactory);
533        }
534
535        if (!found) 
536        {
537           bbtkError("Blackbox Name not found.. <"  <<nameblackbox<<">");
538        }
539   }
540
541   /*
542   /// sets the level of message
543   void Executer::Message(const std::string &category, 
544                          const std::string& level)
545   {
546     int l;
547     sscanf(level.c_str(),"%d",&l);
548     bbtk::MessageManager::SetMessageLevel(category,l);
549   }
550   */
551
552
553 }//namespace