]> Creatis software - bbtk.git/blob - kernel/src/bbtkExecuter.cxx
#3203 BBTK Feature New Normal vtk7itk4wx3-mingw64
[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       }
451     else 
452       {
453       std::string v(value);
454       b->bbSetInput(input,v);
455       }
456   }
457   //=======================================================================
458
459   //=======================================================================
460   std::string Executer::Get(const std::string &box,
461                             const std::string &output)
462   {
463     BlackBox::Pointer b = GetCurrentDescriptor()->GetPrototype()->bbGetBlackBox(box);
464     // Looks for the adaptor
465     if (b->bbGetOutputType(output) != typeid(std::string)) 
466       {
467         BlackBox::Pointer a =
468           GetFactory()->NewAdaptor(
469                                    b->bbGetOutputType(output),
470                                    typeid(std::string),
471                                    "tmp");
472         if (!a) 
473           {
474             bbtkError("No <"<<
475                       TypeName(b->bbGetOutputType(output))
476                       <<"> to <std::string> found");
477           }
478         b->bbExecute();
479         
480         a->bbSetInput("In",b->bbGetOutput(output));
481         a->bbExecute();
482         std::string r = a->bbGetOutput("Out").unsafe_get<std::string>();
483         //std::string v = *((std::string*)a->bbGetOutput("Out")) ;
484         //   std::cout << a->bbGetOutput("Out").unsafe_get<std::string>() 
485         //             << std::endl;
486         //std::string v(value);
487         //b->bbSetInput(input,a->bbGetOutput("Out"));
488         //        a->bbDelete();
489         return r;
490       }
491     else
492       {
493         b->bbExecute();
494         return b->bbGetOutput(output).unsafe_get<std::string>();
495         // std::string v = *((std::string*)b->bbGetOutput(output)) ;
496         // std::cout << b->bbGetOutput("Out").unsafe_get<std::string>() 
497         //   << std::endl;
498         // b->bbSetInput(input,&v);
499       }
500   }
501   //=======================================================================
502
503   //=======================================================================
504   void Executer::Author(const std::string &authorName)
505   {
506     GetCurrentDescriptor()->AddToAuthor(authorName,GetCurrentDescriptor()==GetWorkspace());
507   }
508   //=======================================================================
509
510   //=======================================================================
511   void Executer::Category(const std::string &category)
512   {
513     GetCurrentDescriptor()->AddToCategory(category,GetCurrentDescriptor()==GetWorkspace());
514   }
515   //=======================================================================
516
517   //=======================================================================
518   void Executer::Description(const std::string &d)
519   {
520     GetCurrentDescriptor()->AddToDescription(d,GetCurrentDescriptor()==GetWorkspace());
521   }
522   //=======================================================================
523
524
525
526   //=======================================================================
527   /// prints the list of the boxes of the current descriptor
528   void Executer::PrintHelpListBoxes()
529   {
530     bbtkMessage("help",1,"The black box descriptor \""
531                 <<GetCurrentDescriptor()->GetTypeName()<<"\" contains : "<<std::endl);
532     GetCurrentDescriptor()->PrintBlackBoxes();
533  }
534   //=======================================================================
535
536   //=======================================================================
537   std::string Executer::ShowGraph(const std::string &nameblackbox, 
538                                   const std::string &detailStr, 
539                                   const std::string &levelStr,
540                                   const std::string &output_html,
541                                   const std::string &custom_header,
542                                   const std::string &custom_title,
543                                   bool system_display )
544   {
545     int detail  =       atoi(detailStr.c_str());
546     int level   =       atoi(levelStr.c_str());
547           bool relative_link = true;
548
549     Package::Pointer p;
550     try
551     {
552        p = GetFactory()->GetPackage(nameblackbox);
553     }
554     catch (Exception e)
555     {
556       p = GetUserPackage();
557     }
558           
559       std::string doc_path = bbtk::ConfigurationFile::GetInstance().Get_doc_path();
560       doc_path += bbtk::ConfigurationFile::GetInstance().Get_file_separator();
561       doc_path += "bbdoc";
562       doc_path += bbtk::ConfigurationFile::GetInstance().Get_file_separator();
563           
564           std::string pack_name(p->GetName());
565           std::string pack_path = doc_path + pack_name;
566           // Creating directory
567           if ( ! bbtk::Utilities::FileExists(pack_path) )
568           {
569                   std::string command("mkdir \"" +pack_path+ "\"");
570                   system( command.c_str() );
571           }
572           std::string pack_index(pack_path);
573           pack_index += bbtk::ConfigurationFile::GetInstance().Get_file_separator();
574           pack_index += "index.html"; 
575           
576           
577     // Generating documentation-help of workspace
578         p->SetDocURL(pack_index);
579     p->SetDocRelativeURL("index.html");
580         p->CreateHtmlPage(pack_index,"bbtk","user package",custom_header,custom_title,detail,level,relative_link);
581           
582     /*
583     try 
584     {
585        ShowGraphTypes(nameblackbox);
586     }
587     catch (bbtk::Exception a)
588     {
589        std::cout <<"EXC"<<std::endl;
590        page = ShowGraphInstances(nameblackbox,detail,level,system_display);
591     }
592     */
593     return pack_index;
594   }
595   //=======================================================================
596
597   //=======================================================================
598   /// Generate a png file with the actual pipeline (Graphviz-dot needed)
599   std::string Executer::ShowGraphInstances(const std::string &nameblackbox, int detail, int level,
600                                            bool system_display)
601   {
602
603     BlackBox::Pointer blackbox;
604     if (nameblackbox==".")
605     {
606        blackbox = GetCurrentDescriptor()->GetPrototype();
607     }
608     else
609     {
610        blackbox = GetCurrentDescriptor()->GetPrototype()->bbFindBlackBox(nameblackbox);
611     }
612     
613     std::string page;
614
615     if (blackbox)
616       {      
617         // Don't pollute the file store with  "temp_dir" directories ...
618         std::string default_doc_dir = ConfigurationFile::GetInstance().Get_default_temp_dir();
619         char c = default_doc_dir.c_str()[strlen(default_doc_dir.c_str())-1];
620
621         std::string directory = default_doc_dir; 
622         if (c != '/' && c !='\\') directory = directory + "/";
623
624         directory = directory +  "temp_dir";
625         //std::string directory("temp_dir");
626         std::string filename(directory + "/" + "bbtk_graph_pipeline");
627         std::string filename_html(filename+".html");
628         std::string command0("mkdir \""+directory + "\"");
629
630 #if defined(_WIN32)
631         std::string command2("start ");
632 #else 
633         std::string command2("gnome-open ");
634 #endif
635
636         command2=command2+filename_html;
637         page = filename_html;
638         // 1. Generate Html Diagram
639         std::ofstream s;
640         s.open(filename_html.c_str());
641         if (s.good()) 
642           {
643             s << "<html><head><title>BBtk graph diagram</title><meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\"></head>\n";
644             s << "<body bgcolor=\"#FFFFFF\" text=\"#000000\"> \n\n";
645             if ( blackbox->bbGetName()=="workspacePrototype" )
646               {
647                 s << "<center>Current workspace</center>";
648               } else {
649               s << "<center>" << blackbox->bbGetName()<< "</center>";
650             } 
651             blackbox->bbInsertHTMLGraph( s, detail, level, true, directory, false );
652             s << "</body></html>\n";
653           }
654         s.close();
655         
656         // 2. Starting Browser
657         if (system_display) system( command2.c_str() );      
658       } 
659     else 
660       {
661         bbtkMessage("help",1,"No black box: \""
662                     <<nameblackbox<<"\" " <<std::endl);
663       }
664     return page;
665   }
666   //=======================================================================
667
668   //=======================================================================
669   void Executer::PrintHelpBlackBox(const std::string &nameblackbox, 
670                                const std::string &detailStr, 
671                                const std::string &levelStr)
672   {
673     bool found=false;
674     
675     int detail = atoi(detailStr.c_str());
676     int level  = atoi(levelStr.c_str());
677     BlackBox::Pointer blackbox;
678     if (nameblackbox.compare(".")==0)
679       {
680         blackbox=GetCurrentDescriptor()->GetPrototype();
681       } 
682     else 
683       {
684         blackbox = GetCurrentDescriptor()->GetPrototype()->bbFindBlackBox(nameblackbox);
685       }
686     
687     if (blackbox)
688       {
689         found=true;
690         blackbox->bbPrintHelp(blackbox,detail,level); //,mFactory);
691       }
692     
693     if (!found) 
694       {
695         bbtkError("box with name '"  <<nameblackbox<<"' unknown");
696       }
697   }
698   //=======================================================================
699
700   //=======================================================================
701   /// sets the level of message
702   void Executer::SetMessageLevel(const std::string &kind,
703                                  int level)
704   {
705     bbtk::MessageManager::SetMessageLevel(kind,level);
706   }
707   //=======================================================================
708
709   //=======================================================================
710   /// Prints help on the messages
711   void  Executer::HelpMessages()
712   {
713     bbtk::MessageManager::PrintInfo();
714   }
715   //=======================================================================
716
717   //=======================================================================
718   ///
719   void Executer::Print(const std::string &str)
720   {  
721     if (GetNoExecMode() &&  (GetCurrentDescriptor()==GetWorkspace()) ) return;
722     if (GetCurrentDescriptor()!=GetWorkspace()) return;
723
724     bbtkDebugMessage("kernel",9,"Executer::Print(\""<<str<<"\")"<<std::endl);
725
726  // TO DO :
727  // InterpretLine ("load std")
728  // InterpretLine("new ConcatStrings _C_ ") -> trouver un nom unique : # commande 
729  // InterpretLine("new Print _P_") 
730  // InterpretLine("connect _C_.Out _P_.In")
731  // int num = 1
732  
733
734     std::vector<std::string> chains;
735     std::string delimiters("$");
736
737     // Skip delimiters at beginning.
738     std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
739     bool is_text = true;
740     if (lastPos>0) is_text = false;
741
742     // Find first delimiter.
743     std::string::size_type pos     = str.find_first_of(delimiters, lastPos);
744
745     while (std::string::npos != pos || std::string::npos != lastPos)
746     {
747        if (is_text) 
748        {
749           // Found a text token, add it to the vector.
750           chains.push_back(str.substr(lastPos, pos - lastPos));
751  // std::string token = str.substr(lastPos, pos - lastPos)
752  // InterpretLine("set _C_.In%num% %token%")
753  
754        }
755        else 
756        {
757
758        // is an output (between $$) : decode 
759          std::string tok,box,output;
760          tok = str.substr(lastPos, pos - lastPos);
761          Utilities::SplitAroundFirstDot(tok,box,output);
762          chains.push_back( Get(box,output) );
763
764 // InterpretLine("connect %tok% _C_.In%num%") 
765
766        }
767         // Skip delimiters.  Note the "not_of"
768        lastPos = str.find_first_not_of(delimiters, pos);
769         // Find next delimiter
770        pos = str.find_first_of(delimiters, lastPos);
771     //
772        is_text = !is_text;
773 // num ++;
774      }
775 // InterpretLine("exec _P_")
776 // if (IS_IN_WORKSPACE) InterpretLine("delete _C_; delete _P_");
777
778     std::vector<std::string>::iterator i;
779     for (i= chains.begin(); i!=chains.end(); ++i) 
780       {
781         Utilities::SubsBackslashN(*i);
782         bbtkMessage("output",1,*i);
783       }
784     bbtkMessage("output",1,std::endl);
785   }
786   //==========================================================================
787
788   //==========================================================================
789   std::string Executer::GetObjectName() const
790   {
791     return std::string("Executer");
792   }
793   //==========================================================================
794   
795   //==========================================================================
796   std::string  Executer::GetObjectInfo() const 
797   {
798     std::stringstream i;
799     return i.str();
800   }
801   //==========================================================================
802   //==========================================================================
803 size_t  Executer::GetObjectSize() const 
804 {
805   size_t s = Superclass::GetObjectSize();
806   s += Executer::GetObjectInternalSize();
807   return s;
808   }
809   //==========================================================================
810   //==========================================================================
811 size_t  Executer::GetObjectInternalSize() const 
812 {
813   size_t s = sizeof(Executer);
814   return s;
815   }
816   //==========================================================================
817   //==========================================================================
818   size_t  Executer::GetObjectRecursiveSize() const 
819   {
820     size_t s = Superclass::GetObjectRecursiveSize();
821     s += Executer::GetObjectInternalSize();
822     s += mFactory->GetObjectRecursiveSize();
823     return s;
824   }
825   //==========================================================================
826 }//namespace