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