]> Creatis software - bbtk.git/blob - kernel/src/bbtkExecuter.cxx
79380c4271072db6ca5671156e5cecdfae5ca706
[bbtk.git] / kernel / src / bbtkExecuter.cxx
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   Program:   bbtk
30   Module:    $RCSfile: bbtkExecuter.cxx,v $
31   Language:  C++
32   Date:      $Date: 2012/11/16 08:49:01 $
33   Version:   $Revision: 1.34 $
34 =========================================================================*/
35
36                                                                       
37
38 /**
39  *  \file 
40  *  \brief class Executer: level 0 of script execution (code)
41  */
42
43 #include "bbtkExecuter.h"
44 #include "bbtkMessageManager.h"
45 #include "bbtkFactory.h"
46 #include "bbtkUtilities.h"
47 //#include "bbtkWx.h"
48 #include <fstream>
49
50 #ifdef USE_WXWIDGETS
51 #include <wx/textdlg.h>
52 #endif
53
54 #include "bbtkWxBlackBox.h"
55
56 #include "bbtkConfigurationFile.h"
57
58 namespace bbtk
59 {
60   //=======================================================================
61   Executer::Pointer Executer::New()
62   {
63     bbtkDebugMessage("object",9,"Executer::New()"<<std::endl);
64     return MakePointer(new Executer());
65   }
66   //=======================================================================
67
68   //=======================================================================
69   Executer::Executer()
70     : 
71     mFactory(),
72     mRootPackage(),
73     mRootCBB(),
74     mNoExecMode(false),
75     mDialogMode(NoDialog),
76     mNoErrorMode(false)
77   {
78     bbtkDebugMessage("object",2,"==> Executer()" <<std::endl);
79     mFactory = Factory::New();
80     // The smart pointer on this is not made yet (is made by New) 
81     // -> create it to pass it to the factory
82     // We have to "lock" the smart pointer because the factory
83     // only keeps a weak pointer on the executer
84     // -> this would auto-destroy !!
85         
86     mFactory->SetExecuter(MakePointer(this,true));
87
88     Reset();
89     bbtkDebugMessage("object",2,"<== Executer()" <<std::endl);
90   }
91   //=======================================================================
92
93   //=======================================================================
94   Executer::~Executer()
95   {
96      bbtkDebugMessage("object",2,"==> ~Executer()" <<std::endl);
97      mOpenDefinition.clear();
98      mOpenPackage.clear();
99      mFactory->Reset();
100      mFactory.reset();
101      bbtkDebugMessage("object",2,"<== ~Executer()" <<std::endl);
102   }
103   //=======================================================================
104
105   //=======================================================================
106    /// Loads a package
107     void Executer::LoadPackage(const std::string &name )
108    {
109      GetFactory()->LoadPackage(name);
110    }
111   //=======================================================================
112
113   //=======================================================================
114     /// Unloads a package
115     void Executer::UnLoadPackage(const std::string &name )
116     {
117       GetFactory()->UnLoadPackage(name);
118     }
119   //=======================================================================
120
121   //=======================================================================
122   void Executer::Reset()
123   {
124     bbtkDebugMessage("kernel",9,"==> Executer::Reset()" <<std::endl);
125
126     //    GetFactory()->Check();
127  
128     mOpenDefinition.clear();
129     mOpenPackage.clear();
130
131     //  Wx::DestroyTopWindow();
132
133     GetFactory()->Reset();
134 #if(USE_WXWIDGETS)
135     Wx::ProcessPendingEvents();
136 #endif
137
138  
139     // Create user package
140     Package::Pointer p =
141       Package::New("user","internal","User defined black boxes","");
142     // Insert the user package in the factory
143     GetFactory()->InsertPackage(p);
144     // And in the list of open packages
145     mOpenPackage.push_back(p);
146     mRootPackage = p;
147
148     // Create user workspace
149     ComplexBlackBoxDescriptor::Pointer r = 
150       ComplexBlackBoxDescriptor::New("workspace"); 
151     //    mRootCBB->Reference();
152     r->SetFactory(GetFactory());
153     r->AddToAuthor("bbtk");
154     r->AddToDescription("User's workspace");
155     mOpenDefinition.push_back(CBBDefinition(r,"user"));
156     // Register it into the user package
157     p->Register(r);
158     mRootCBB = r;
159
160     //    Object::PrintObjectListInfo();
161     //  GetFactory()->CheckPackages();
162     bbtkDebugMessage("kernel",9,"<== Executer::Reset()" <<std::endl);
163   }
164   //=======================================================================
165
166
167   //=======================================================================
168   /// changes the workspace name
169   void Executer::SetWorkspaceName( const std::string& n )
170   {
171     GetUserPackage()->ChangeDescriptorName( GetWorkspace()->GetTypeName(), n );
172   }
173   //=======================================================================
174
175   //=======================================================================
176   void Executer::BeginPackage (const std::string &name)
177   {
178      bbtkDebugMessage("kernel",9,"==> Executer::BeginPackage(\""<<name<<"\")"
179                         <<std::endl);
180      Package::Pointer p;
181      try 
182       {
183          p = GetFactory()->GetPackage(name);
184       }
185     catch (Exception e)
186       {
187         p = Package::New(name,"","","");
188         GetFactory()->InsertPackage(p);
189       }
190      mOpenPackage.push_back(p);
191
192      bbtkDebugMessage("kernel",9,"<== Executer::BeginPackage(\""<<name<<"\")"
193                       <<std::endl);
194   }
195   //=======================================================================
196
197   //=======================================================================
198   void Executer::EndPackage()
199   {
200     if (mOpenPackage.size()>1) mOpenPackage.pop_back();
201   }
202   //=======================================================================
203
204   //=======================================================================
205   void Executer::Define (const std::string &name,
206                          const std::string &pack,
207                          const std::string &scriptfilename)
208   {
209     bbtkDebugMessage("kernel",9,"==> Executer::Define(\""<<name<<
210                      ","<<pack<<"\")"
211                      <<std::endl);
212
213     ComplexBlackBoxDescriptor::Pointer b 
214       = ComplexBlackBoxDescriptor::New(name);
215     b->SetFactory(GetFactory());
216     b->SetScriptFileName(scriptfilename);
217     mOpenDefinition.push_back( CBBDefinition( b, pack ) );
218     
219     bbtkDebugMessage("kernel",9,"<== Executer::Define(\""<<name<<
220                      ","<<pack<<"\")"
221                      <<std::endl);
222   }
223   //=======================================================================
224
225   //=======================================================================
226   /// Sets the file name to use for the current definition
227   /// (Used to set it after the Define command)
228   void Executer::SetCurrentFileName (const std::string &name )
229   {
230     mOpenDefinition.back().box->SetScriptFileName(name);
231   }
232   //=======================================================================
233
234         void Executer::SetTypeOfScript_Application ()
235         {
236                 mOpenDefinition.back().box->SetTypeOfScript_Application();
237         }
238         
239         
240         
241   //=======================================================================
242   void Executer::Clear()
243   {
244     bbtkDebugMessage("kernel",9,"==> Executer::Clear()" <<std::endl);
245     GetCurrentDescriptor()->GetPrototype()->Clear();
246     bbtkDebugMessage("kernel",9,"<== Executer::Clear()" <<std::endl);
247   }
248   //=======================================================================
249
250   //=======================================================================
251   void Executer::EndDefine ()
252   {
253     bbtkDebugMessage("kernel",9,"==> Executer::EndDefine(\""
254                      <<GetCurrentDescriptor()->GetTypeName()<<"\")" 
255                      <<std::endl);
256     // Does current package exist ?
257     Package::Pointer p;
258     std::string pname(mOpenDefinition.back().package);
259     if (pname.size()>0)
260       {
261         try
262           {
263             p = GetFactory()->GetPackage(pname);
264           }
265         catch (Exception e)
266           {
267             p = Package::New(pname,"","","");
268             GetFactory()->InsertPackage(p);
269           }
270       }
271     else
272       {
273         p = mOpenPackage.back().lock();
274       }
275     // Register the descriptor in the current package
276     p->Register(GetCurrentDescriptor());
277     
278     bbtkDebugMessage("kernel",9,"<== Executer::EndDefine(\""
279                      <<GetCurrentDescriptor()->GetTypeName()<<"\")" 
280                      <<std::endl);
281     mOpenDefinition.pop_back();
282   }
283   //======================================================================= 
284
285   //=======================================================================  
286   void Executer::Kind(const std::string& kind)
287   {
288     if (kind=="ADAPTOR")
289       {
290         GetCurrentDescriptor()->AddToCategory("adaptor");
291         GetCurrentDescriptor()->SetKind(bbtk::BlackBoxDescriptor::ADAPTOR);
292       }
293     else if (kind=="DEFAULT_ADAPTOR")
294       {
295         GetCurrentDescriptor()->AddToCategory("adaptor");
296         GetCurrentDescriptor()->SetKind(bbtk::BlackBoxDescriptor::DEFAULT_ADAPTOR);
297       }
298     if (kind=="GUI")
299       {
300         GetCurrentDescriptor()->AddToCategory("gui");
301         GetCurrentDescriptor()->SetKind(bbtk::BlackBoxDescriptor::GUI);
302       }
303     else if (kind=="DEFAULT_GUI")
304       {
305         GetCurrentDescriptor()->AddToCategory("gui");
306         GetCurrentDescriptor()->SetKind(bbtk::BlackBoxDescriptor::DEFAULT_GUI);
307       }
308     else
309       {
310         bbtkError("Unknown box kind : '"<<kind<<"'. "
311                   <<"Valid kinds are 'ADAPTOR','DEFAULT_ADAPTOR',"
312                   <<"'GUI','DEFAULT_GUI'");
313       }
314   }
315   //=======================================================================
316
317   //=======================================================================
318   void Executer::Create ( const std::string& nodeType, 
319                           const std::string& nodeName)
320   {
321      GetCurrentDescriptor()->Add(nodeType,nodeName);
322   }
323   //=======================================================================
324
325   //=======================================================================
326   void Executer::Destroy(const std::string &boxName)
327   {
328     GetCurrentDescriptor()->Remove(boxName,true);
329   }
330   //=======================================================================
331
332   //=======================================================================
333   void Executer::Connect (const std::string &nodeFrom,
334                           const std::string &outputLabel,
335                           const std::string &nodeTo, 
336                           const std::string &inputLabel)
337   {
338     GetCurrentDescriptor()->Connect(nodeFrom, outputLabel, nodeTo, inputLabel);
339   }
340   //=======================================================================
341
342   //=======================================================================
343   void Executer::Execute (const std::string &nodeName) 
344   {
345     // if in root
346     if (GetCurrentDescriptor()==GetWorkspace()) 
347      {
348         if (!mNoExecMode) 
349         {
350            GetCurrentDescriptor()->GetPrototype()->bbGetBlackBox(nodeName)->bbExecute(true);
351         }
352      }
353      else 
354      {
355         GetCurrentDescriptor()->AddToExecutionList(nodeName) ;
356      }
357   }
358   //=======================================================================
359
360   //=======================================================================
361   void Executer::DefineInput ( const std::string &name,
362                                const std::string &box,
363                                const std::string &input,
364                                const std::string& help)
365   {
366     // If the input is defined in the Root box
367     if (GetCurrentDescriptor()==GetWorkspace()) 
368       {
369       // If the dialog mode is set to NoDialog
370       // and the user passed the name in the Inputs map 
371       // then the associated value is set to the box.input
372       // This is the way command line parameters are passed to the Root box
373          if (mDialogMode == NoDialog) 
374          {
375          // find if name is in mInputs
376             std::map<std::string,std::string>::iterator i;
377             i = mInputs.find(name);
378             if (i!=mInputs.end()) {
379                Set(box,input,(*i).second);
380             }
381          }
382         // If the dialog mode is set to TextDialog
383         // The user is prompted for the value
384         else if (mDialogMode == TextDialog) 
385         {
386            std::cout << name << "=";
387            std::string ans;
388            std::cin >> ans;
389            Set(box,input,ans);
390         }
391 #ifdef USE_WXWIDGETS
392        // If the dialog mode is set to GraphicalDialog
393        // A dialog box is pop up
394        else if (mDialogMode == GraphicalDialog) 
395        {
396           std::string mess("Enter the value of '");
397           mess += name;
398           mess += "' (";
399           mess += help;
400           mess += ")";
401           std::string title(name);
402           title += " ?";
403           std::string ans = wx2std ( wxGetTextFromUser( std2wx (mess), std2wx(title)));
404           Set(box,input,ans); 
405        }
406 #endif
407     }
408
409     GetCurrentDescriptor()->DefineInput(name,box,input,help);
410
411   }
412   //=======================================================================
413
414   //=======================================================================
415    void Executer::DefineOutput ( const std::string &name,
416                                  const std::string &box,
417                                  const std::string &output,
418                                  const std::string& help)
419   {
420     GetCurrentDescriptor()->DefineOutput(name,box,output,help);
421   }
422   //=======================================================================
423
424   //=======================================================================
425   void Executer::Set (const std::string &box,
426                       const std::string &input,
427                       const std::string &value)
428   {
429       BlackBox::Pointer b = GetCurrentDescriptor()->GetPrototype()->bbGetBlackBox(box);
430     // Looks for the adaptor
431
432     if ( ( b->bbGetInputType(input) != typeid(bbtk::any<bbtk::thing>) )&&
433          ( b->bbGetInputType(input) != typeid(std::string) ) )
434       {
435         BlackBox::Pointer a =
436            GetFactory()->NewAdaptor(typeid(std::string),
437                                     b->bbGetInputType(input),
438                                     "tmp");
439          if (!a) 
440            {
441              bbtkError("No <"<<
442                        TypeName(b->bbGetInputType(input))
443                        <<"> to <std::string> found");
444            }
445          std::string v(value);
446          a->bbSetInput("In",v);
447          a->bbExecute();
448          b->bbSetInput(input,a->bbGetOutput("Out"));
449          //         a->Delete();
450       } else {
451       std::string v(value);
452       b->bbSetInput(input,v);
453       }
454   }
455   //=======================================================================
456
457   //=======================================================================
458   std::string Executer::Get(const std::string &box,
459                             const std::string &output)
460   {
461     BlackBox::Pointer b = GetCurrentDescriptor()->GetPrototype()->bbGetBlackBox(box);
462     // Looks for the adaptor
463     if (b->bbGetOutputType(output) != typeid(std::string)) 
464       {
465         BlackBox::Pointer a =
466           GetFactory()->NewAdaptor(
467                                    b->bbGetOutputType(output),
468                                    typeid(std::string),
469                                    "tmp");
470         if (!a) 
471           {
472             bbtkError("No <"<<
473                       TypeName(b->bbGetOutputType(output))
474                       <<"> to <std::string> found");
475           }
476         b->bbExecute();
477         
478         a->bbSetInput("In",b->bbGetOutput(output));
479         a->bbExecute();
480         std::string r = a->bbGetOutput("Out").unsafe_get<std::string>();
481         //std::string v = *((std::string*)a->bbGetOutput("Out")) ;
482         //   std::cout << a->bbGetOutput("Out").unsafe_get<std::string>() 
483         //             << std::endl;
484         //std::string v(value);
485         //b->bbSetInput(input,a->bbGetOutput("Out"));
486         //        a->bbDelete();
487         return r;
488       } else  {
489         b->bbExecute();
490         return b->bbGetOutput(output).unsafe_get<std::string>();
491         // std::string v = *((std::string*)b->bbGetOutput(output)) ;
492         // std::cout << b->bbGetOutput("Out").unsafe_get<std::string>() 
493         //   << std::endl;
494         // b->bbSetInput(input,&v);
495       }
496   }
497   //=======================================================================
498
499   //=======================================================================
500   void Executer::Author(const std::string &authorName)
501   {
502     GetCurrentDescriptor()->AddToAuthor(authorName,GetCurrentDescriptor()==GetWorkspace());
503   }
504   //=======================================================================
505
506   //=======================================================================
507   void Executer::Category(const std::string &category)
508   {
509     GetCurrentDescriptor()->AddToCategory(category,GetCurrentDescriptor()==GetWorkspace());
510   }
511   //=======================================================================
512
513   //=======================================================================
514   void Executer::Description(const std::string &d)
515   {
516     GetCurrentDescriptor()->AddToDescription(d,GetCurrentDescriptor()==GetWorkspace());
517   }
518   //=======================================================================
519
520
521
522   //=======================================================================
523   /// prints the list of the boxes of the current descriptor
524   void Executer::PrintHelpListBoxes()
525   {
526     bbtkMessage("help",1,"The black box descriptor \""
527                 <<GetCurrentDescriptor()->GetTypeName()<<"\" contains : "<<std::endl);
528     GetCurrentDescriptor()->PrintBlackBoxes();
529  }
530   //=======================================================================
531
532   //=======================================================================
533   std::string Executer::ShowGraph(const std::string &nameblackbox, 
534                                   const std::string &detailStr, 
535                                   const std::string &levelStr,
536                                   const std::string &output_html,
537                                   const std::string &custom_header,
538                                   const std::string &custom_title,
539                                   bool system_display )
540   {
541     int detail  =       atoi(detailStr.c_str());
542     int level   =       atoi(levelStr.c_str());
543           bool relative_link = true;
544
545     Package::Pointer p;
546     try
547     {
548        p = GetFactory()->GetPackage(nameblackbox);
549     }
550     catch (Exception e)
551     {
552       p = GetUserPackage();
553     }
554           
555       std::string doc_path = bbtk::ConfigurationFile::GetInstance().Get_doc_path();
556       doc_path += bbtk::ConfigurationFile::GetInstance().Get_file_separator();
557       doc_path += "bbdoc";
558       doc_path += bbtk::ConfigurationFile::GetInstance().Get_file_separator();
559           
560           std::string pack_name(p->GetName());
561           std::string pack_path = doc_path + pack_name;
562           // Creating directory
563           if ( ! bbtk::Utilities::FileExists(pack_path) )
564           {
565                   std::string command("mkdir \"" +pack_path+ "\"");
566                   system( command.c_str() );
567           }
568           std::string pack_index(pack_path);
569           pack_index += bbtk::ConfigurationFile::GetInstance().Get_file_separator();
570           pack_index += "index.html"; 
571           
572           
573     // Generating documentation-help of workspace
574         p->SetDocURL(pack_index);
575     p->SetDocRelativeURL("index.html");
576         p->CreateHtmlPage(pack_index,"bbtk","user package",custom_header,custom_title,detail,level,relative_link);
577           
578     /*
579     try 
580     {
581        ShowGraphTypes(nameblackbox);
582     }
583     catch (bbtk::Exception a)
584     {
585        std::cout <<"EXC"<<std::endl;
586        page = ShowGraphInstances(nameblackbox,detail,level,system_display);
587     }
588     */
589     return pack_index;
590   }
591   //=======================================================================
592
593   //=======================================================================
594   /// Generate a png file with the actual pipeline (Graphviz-dot needed)
595   std::string Executer::ShowGraphInstances(const std::string &nameblackbox, int detail, int level,
596                                            bool system_display)
597   {
598
599     BlackBox::Pointer blackbox;
600     if (nameblackbox==".")
601     {
602        blackbox = GetCurrentDescriptor()->GetPrototype();
603     }
604     else
605     {
606        blackbox = GetCurrentDescriptor()->GetPrototype()->bbFindBlackBox(nameblackbox);
607     }
608     
609     std::string page;
610
611     if (blackbox)
612       {      
613         // Don't pollute the file store with  "temp_dir" directories ...
614         std::string default_doc_dir = ConfigurationFile::GetInstance().Get_default_temp_dir();
615         char c = default_doc_dir.c_str()[strlen(default_doc_dir.c_str())-1];
616
617         std::string directory = default_doc_dir; 
618         if (c != '/' && c !='\\') directory = directory + "/";
619
620         directory = directory +  "temp_dir";
621         //std::string directory("temp_dir");
622         std::string filename(directory + "/" + "bbtk_graph_pipeline");
623         std::string filename_html(filename+".html");
624         std::string command0("mkdir \""+directory + "\"");
625
626 #if defined(_WIN32)
627         std::string command2("start ");
628 #else 
629         std::string command2("gnome-open ");
630 #endif
631
632         command2=command2+filename_html;
633         page = filename_html;
634         // 1. Generate Html Diagram
635         std::ofstream s;
636         s.open(filename_html.c_str());
637         if (s.good()) 
638           {
639             s << "<html><head><title>BBtk graph diagram</title><meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\"></head>\n";
640             s << "<body bgcolor=\"#FFFFFF\" text=\"#000000\"> \n\n";
641             if ( blackbox->bbGetName()=="workspacePrototype" )
642               {
643                 s << "<center>Current workspace</center>";
644               } else {
645               s << "<center>" << blackbox->bbGetName()<< "</center>";
646             } 
647             blackbox->bbInsertHTMLGraph( s, detail, level, true, directory, false );
648             s << "</body></html>\n";
649           }
650         s.close();
651         
652         // 2. Starting Browser
653         if (system_display) system( command2.c_str() );      
654       } 
655     else 
656       {
657         bbtkMessage("help",1,"No black box: \""
658                     <<nameblackbox<<"\" " <<std::endl);
659       }
660     return page;
661   }
662   //=======================================================================
663
664   //=======================================================================
665   void Executer::PrintHelpBlackBox(const std::string &nameblackbox, 
666                                const std::string &detailStr, 
667                                const std::string &levelStr)
668   {
669     bool found=false;
670     
671     int detail = atoi(detailStr.c_str());
672     int level  = atoi(levelStr.c_str());
673     BlackBox::Pointer blackbox;
674     if (nameblackbox.compare(".")==0)
675       {
676         blackbox=GetCurrentDescriptor()->GetPrototype();
677       } 
678     else 
679       {
680         blackbox = GetCurrentDescriptor()->GetPrototype()->bbFindBlackBox(nameblackbox);
681       }
682     
683     if (blackbox)
684       {
685         found=true;
686         blackbox->bbPrintHelp(blackbox,detail,level); //,mFactory);
687       }
688     
689     if (!found) 
690       {
691         bbtkError("box with name '"  <<nameblackbox<<"' unknown");
692       }
693   }
694   //=======================================================================
695
696   //=======================================================================
697   /// sets the level of message
698   void Executer::SetMessageLevel(const std::string &kind,
699                                  int level)
700   {
701     bbtk::MessageManager::SetMessageLevel(kind,level);
702   }
703   //=======================================================================
704
705   //=======================================================================
706   /// Prints help on the messages
707   void  Executer::HelpMessages()
708   {
709     bbtk::MessageManager::PrintInfo();
710   }
711   //=======================================================================
712
713   //=======================================================================
714   ///
715   void Executer::Print(const std::string &str)
716   {  
717     if (GetNoExecMode() &&  (GetCurrentDescriptor()==GetWorkspace()) ) return;
718     if (GetCurrentDescriptor()!=GetWorkspace()) return;
719
720     bbtkDebugMessage("kernel",9,"Executer::Print(\""<<str<<"\")"<<std::endl);
721
722  // TO DO :
723  // InterpretLine ("load std")
724  // InterpretLine("new ConcatStrings _C_ ") -> trouver un nom unique : # commande 
725  // InterpretLine("new Print _P_") 
726  // InterpretLine("connect _C_.Out _P_.In")
727  // int num = 1
728  
729
730     std::vector<std::string> chains;
731     std::string delimiters("$");
732
733     // Skip delimiters at beginning.
734     std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
735     bool is_text = true;
736     if (lastPos>0) is_text = false;
737
738     // Find first delimiter.
739     std::string::size_type pos     = str.find_first_of(delimiters, lastPos);
740
741     while (std::string::npos != pos || std::string::npos != lastPos)
742     {
743        if (is_text) 
744        {
745           // Found a text token, add it to the vector.
746           chains.push_back(str.substr(lastPos, pos - lastPos));
747  // std::string token = str.substr(lastPos, pos - lastPos)
748  // InterpretLine("set _C_.In%num% %token%")
749  
750        }
751        else 
752        {
753
754        // is an output (between $$) : decode 
755          std::string tok,box,output;
756          tok = str.substr(lastPos, pos - lastPos);
757          Utilities::SplitAroundFirstDot(tok,box,output);
758          chains.push_back( Get(box,output) );
759
760 // InterpretLine("connect %tok% _C_.In%num%") 
761
762        }
763         // Skip delimiters.  Note the "not_of"
764        lastPos = str.find_first_not_of(delimiters, pos);
765         // Find next delimiter
766        pos = str.find_first_of(delimiters, lastPos);
767     //
768        is_text = !is_text;
769 // num ++;
770      }
771 // InterpretLine("exec _P_")
772 // if (IS_IN_WORKSPACE) InterpretLine("delete _C_; delete _P_");
773
774     std::vector<std::string>::iterator i;
775     for (i= chains.begin(); i!=chains.end(); ++i) 
776       {
777         Utilities::SubsBackslashN(*i);
778         bbtkMessage("output",1,*i);
779       }
780     bbtkMessage("output",1,std::endl);
781   }
782   //==========================================================================
783
784   //==========================================================================
785   std::string Executer::GetObjectName() const
786   {
787     return std::string("Executer");
788   }
789   //==========================================================================
790   
791   //==========================================================================
792   std::string  Executer::GetObjectInfo() const 
793   {
794     std::stringstream i;
795     return i.str();
796   }
797   //==========================================================================
798   //==========================================================================
799 size_t  Executer::GetObjectSize() const 
800 {
801   size_t s = Superclass::GetObjectSize();
802   s += Executer::GetObjectInternalSize();
803   return s;
804   }
805   //==========================================================================
806   //==========================================================================
807 size_t  Executer::GetObjectInternalSize() const 
808 {
809   size_t s = sizeof(Executer);
810   return s;
811   }
812   //==========================================================================
813   //==========================================================================
814   size_t  Executer::GetObjectRecursiveSize() const 
815   {
816     size_t s = Superclass::GetObjectRecursiveSize();
817     s += Executer::GetObjectInternalSize();
818     s += mFactory->GetObjectRecursiveSize();
819     return s;
820   }
821   //==========================================================================
822 }//namespace