]> Creatis software - bbtk.git/blob - kernel/src/bbtkComplexBlackBoxDescriptor.cxx
2bc2e3ea6b67e106c6a5df7f611641aac2c6a63c
[bbtk.git] / kernel / src / bbtkComplexBlackBoxDescriptor.cxx
1 /*=========================================================================                                                                               
2   Program:   bbtk
3   Module:    $RCSfile: bbtkComplexBlackBoxDescriptor.cxx,v $
4   Language:  C++
5   Date:      $Date: 2008/10/17 08:18:12 $
6   Version:   $Revision: 1.18 $
7 =========================================================================*/
8
9 /* ---------------------------------------------------------------------
10
11 * Copyright (c) CREATIS-LRMN (Centre de Recherche en Imagerie Medicale)
12 * Authors : Eduardo Davila, Laurent Guigues, Jean-Pierre Roux
13 *
14 *  This software is governed by the CeCILL-B license under French law and 
15 *  abiding by the rules of distribution of free software. You can  use, 
16 *  modify and/ or redistribute the software under the terms of the CeCILL-B 
17 *  license as circulated by CEA, CNRS and INRIA at the following URL 
18 *  http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html 
19 *  or in the file LICENSE.txt.
20 *
21 *  As a counterpart to the access to the source code and  rights to copy,
22 *  modify and redistribute granted by the license, users are provided only
23 *  with a limited warranty  and the software's author,  the holder of the
24 *  economic rights,  and the successive licensors  have only  limited
25 *  liability. 
26 *
27 *  The fact that you are presently reading this means that you have had
28 *  knowledge of the CeCILL-B license and that you accept its terms.
29 * ------------------------------------------------------------------------ */                                                                         
30   
31
32 /**
33  *  \file 
34  *  \brief Class bbtk::ComplexBlackBoxDescriptor : describes a ComplexBlackBox (constituents, connections) and is able to create an instance of it.
35  */
36 #include "bbtkComplexBlackBoxDescriptor.h"
37 #include "bbtkComplexBlackBox.h"
38 //#include "bbtkFactory.h"
39 #include "bbtkMessageManager.h"
40 #include "bbtkUtilities.h"
41
42 namespace bbtk
43 {
44    //=======================================================================
45   /// 
46   ComplexBlackBoxDescriptor::Pointer 
47   ComplexBlackBoxDescriptor::New(const std::string& name)
48   {
49     bbtkDebugMessage("object",1,"##> ComplexBlackBoxDescriptor::New(\""<<name<<"\")"<<std::endl);
50     ComplexBlackBoxDescriptor::Pointer p = 
51       MakePointer(new ComplexBlackBoxDescriptor(name));
52     bbtkDebugMessage("object",1,"<## ComplexBlackBoxDescriptor::New(\""<<name<<"\")"<<std::endl);
53     return p;
54   }
55   //=======================================================================
56
57   //=======================================================================
58   /// Default ctor
59   ComplexBlackBoxDescriptor::ComplexBlackBoxDescriptor(const std::string& name)
60   {
61     bbtkDebugMessage("object",2,"==> ComplexBlackBoxDescriptor::ComplexBlackBoxDescriptor(\""<<name<<"\")"<<std::endl);
62     SetTypeName(name);
63     AddToCategory("complex box");
64     mPrototype = ComplexBlackBox::New(name+std::string("Prototype"),
65                                       MakePointer(this,true));
66     mPrototype->SetAsPrototype();
67     bbtkDebugMessage("object",2,"<== ComplexBlackBoxDescriptor::ComplexBlackBoxDescriptor(\""<<name<<"\")"<<std::endl);
68   }
69   //=======================================================================
70
71
72
73   //=======================================================================
74   /// Default dtor
75   ComplexBlackBoxDescriptor::~ComplexBlackBoxDescriptor()
76   {
77     bbtkDebugMessage("object",2,"==> ComplexBlackBoxDescriptor::~ComplexBlackBoxDescriptor(\""<<GetTypeName()<<"\")"<<std::endl);
78     //    mPrototype->Delete();
79     mPrototype.reset();
80     bbtkDebugMessage("object",2,"<== ComplexBlackBoxDescriptor::~ComplexBlackBoxDescriptor(\""<<GetTypeName()<<"\")"<<std::endl);
81   }
82   //=======================================================================
83
84   //=========================================================================
85   /// Check
86   void ComplexBlackBoxDescriptor::Check(bool recursive) const
87   {
88     mPrototype->Check(recursive);
89   }
90   //=========================================================================
91
92   //=======================================================================
93   /// Creates an instance of name <name> of the ComplexBlackBox of which this is the descriptor 
94   BlackBox::Pointer 
95   ComplexBlackBoxDescriptor::NewBlackBox(const std::string& name)
96   {
97     bbtkDebugMessageInc("Kernel",5,
98                         "ComplexBlackBoxDescriptor::NewBlackBox(\""
99                         <<name<<"\") ["
100                         <<GetTypeName()<<"]"<<std::endl);
101     
102     return mPrototype->bbClone(name);
103
104     bbtkDebugDecTab("Kernel",5);
105   }
106   //=======================================================================
107
108   /*
109   //=======================================================================
110   /// Release
111   void ComplexBlackBoxDescriptor::Release(bool release_package)
112   {
113   }
114   //=======================================================================
115   */
116
117   //=======================================================================
118   /// Adds a black box to the complex box
119   void ComplexBlackBoxDescriptor::Add ( const std::string& type,
120                                         const std::string& name
121                                         )
122   {
123     bbtkDebugMessageInc("Kernel",5,
124                         "ComplexBlackBoxDescriptor::Add(\""
125                         <<type<<"\",\""<<name<<"\") ["
126                         <<GetTypeName()<<"]"<<std::endl);
127     
128     // 
129     if (!GetFactory()) 
130       { 
131         bbtkError("ComplexBlackBoxDescriptor::Add : no factory set");
132       }
133     
134     // Verify that a box with the same name does not exist already
135     if ( mPrototype->bbUnsafeGetBlackBox( name ) ) 
136       {
137         bbtkError("a black box \""<<name<<"\" already exists");
138       }
139     // ok : create new one
140     mPrototype->bbAddBlackBox ( GetFactory()->NewBlackBox(type,name) );
141
142     bbtkDebugDecTab("Kernel",5);
143   }
144   //=======================================================================
145   
146   //=======================================================================
147   /// Removes a black box from the complex box
148   void ComplexBlackBoxDescriptor::Remove( const std::string& name, 
149                                           bool remove_connections)
150   {    
151     mPrototype->bbRemoveBlackBox(name,remove_connections);
152   }
153   //=======================================================================
154
155
156   //=======================================================================
157   /// Adds a black box to the execution list 
158   void ComplexBlackBoxDescriptor::AddToExecutionList ( const std::string& box)
159   {
160     bbtkDebugMessageInc("Kernel",5,
161                         "ComplexBlackBoxDescriptor::AddToExecutionList(\""
162                         <<box<<"\" ["
163                         <<GetTypeName()<<"]"<<std::endl);
164     // Verify that the box exists
165     BlackBox::Pointer b = mPrototype->bbUnsafeGetBlackBox( box ); 
166     if ( !b ) 
167       {
168         bbtkError("the black box \""<<box<<"\" does not exist");
169       }
170     // ok 
171     mPrototype->bbAddToExecutionList ( box  );
172
173     bbtkDebugDecTab("Kernel",5);
174     }
175
176
177   //=======================================================================
178   /// Connects two black boxes of the complex box
179   void ComplexBlackBoxDescriptor::Connect ( const std::string& from,
180                                             const std::string& output,
181                                             const std::string& to,
182                                             const std::string& input
183                                             )
184   {
185     bbtkDebugMessageInc("Kernel",5,
186                         "ComplexBlackBoxDescriptor::Connect(\""
187                         <<from<<"\",\""<<output<<"\",\""
188                         <<to<<"\",\""<<input
189                         <<"\") ["
190                         <<GetTypeName()<<"]"<<std::endl);
191   // 
192     if (!GetFactory()) 
193       { 
194         bbtkError("ComplexBlackBoxDescriptor::Connect : no factory set");
195       }
196     
197
198   // Verify that a box with the same name does not exist already
199     BlackBox::Pointer bbfrom = mPrototype->bbGetBlackBox( from );
200     if ( !bbfrom ) 
201       {
202         bbtkError("the black box \""<<from<<"\" does not exist");
203       }
204     BlackBox::Pointer bbto = mPrototype->bbGetBlackBox( to );
205     if ( !bbto ) 
206       {
207         bbtkError("the black box \""<<to<<"\" does not exist");
208       }
209     
210     Connection::Pointer c 
211       = GetFactory()->NewConnection( bbfrom, output, bbto, input );
212
213     mPrototype->bbAddConnection(c);
214
215     bbtkDebugDecTab("Kernel",5);
216   }
217   //=======================================================================
218
219
220   //=======================================================================
221   /// Defines an input of the complex box
222   void ComplexBlackBoxDescriptor::DefineInput ( const std::string& name,
223                                                 const std::string& box,
224                                                 const std::string& input,
225                                                 const std::string& help)
226   {
227     bbtkDebugMessageInc("Kernel",5,
228                         "ComplexBlackBoxDescriptor::DefineInput(\""
229                         <<name<<"\",\""<<box<<"\",\""
230                         <<input<<"\",\""<<help
231                         <<"\") ["
232                         <<GetTypeName()<<"]"<<std::endl);
233
234     BlackBox::Pointer bb = mPrototype->bbGetBlackBox( box );
235     if ( !bb ) 
236       {
237         bbtkError("the black box \""<<box<<"\" does not exist");
238       }
239
240     if (!bb->bbHasInput(input) )
241       {
242         bbtkError("the black box \""<<box<<"\" does not have input \""
243                   <<input<<"\"");
244       }
245     
246     const BlackBoxInputDescriptor* d = 
247       bb->bbGetDescriptor()->GetInputDescriptor(input);
248     AddInputDescriptor ( new ComplexBlackBoxInputDescriptor 
249                          ( typeid(ComplexBlackBoxDescriptor),
250                            name,
251                            help,
252                            d->GetNature(),
253                            box,
254                            input,
255                            d->GetTypeInfo()));
256     
257     
258     bbtkDebugDecTab("Kernel",5);
259   }
260   //=======================================================================
261
262   //=======================================================================
263   /// Defines an output of the complex box
264   void ComplexBlackBoxDescriptor::DefineOutput ( const std::string& name,
265                                                  const std::string& box,
266                                                  const std::string& output,
267                                                  const std::string& help)
268   {
269     bbtkDebugMessageInc("Kernel",5,
270                         "ComplexBlackBoxDescriptor::DefineOutput(\""
271                         <<name<<"\",\""<<box<<"\",\""
272                         <<output<<"\",\""<<help
273                         <<"\") ["
274                         <<GetTypeName()<<"]"<<std::endl);
275
276     BlackBox::Pointer bb = mPrototype->bbGetBlackBox( box );
277     if ( !bb ) 
278       {
279         bbtkError("the black box \""<<box<<"\" does not exist");
280       }
281
282     if (!bb->bbHasOutput(output) )
283       {
284         bbtkError("the black box \""<<box<<"\" does not have output \""
285                   <<output<<"\"");
286       }
287     
288     const BlackBoxOutputDescriptor* d = 
289       bb->bbGetDescriptor()->GetOutputDescriptor(output);
290     AddOutputDescriptor ( new ComplexBlackBoxOutputDescriptor 
291                           ( typeid(ComplexBlackBoxDescriptor),
292                             name,
293                             help,
294                             d->GetNature(),
295                             box,
296                             output,
297                             d->GetTypeInfo()));
298     
299     
300     bbtkDebugDecTab("Kernel",5);
301   }
302   //=======================================================================
303
304   //=======================================================================
305   void ComplexBlackBoxDescriptor::PrintBlackBoxes()
306   {
307     mPrototype->bbPrintBlackBoxes(); 
308   }
309   //=======================================================================
310
311
312   //=======================================================================
313   void ComplexBlackBoxDescriptor::InsertHTMLGraph( std::ofstream& s , 
314                                                    int detail, int level, 
315                                                    const std::string& output_dir, bool relative_link )   
316   {
317     this->mPrototype->bbInsertHTMLGraph( s, 
318                                          detail, level, 
319                                          false, 
320                                          output_dir,
321                                          relative_link );
322   }
323   //=======================================================================
324
325   //=========================================================================
326   void ComplexBlackBoxDescriptor::InsertHtmlHelp ( std::ofstream& s, 
327                                                    int detail, int level,
328                                                    const std::string& output_dir, bool relative_link)
329   {
330     bbtkDebugMessageInc("Kernel",9,
331                         "ComplexBlackBoxDescriptor::InsertHtmlHelp() ["
332                         <<GetTypeName()<<"]"<<std::endl);
333     
334     //-------------
335     // General info 
336     std::string name = GetTypeName();
337     Utilities::html_format(name);
338
339     //   std::ofstream* s = &s1;
340
341     (s) << "<p><hr>\n";
342     (s) << "<a name=\""<<name<<"\"></a>\n";
343     (s) << //"Top:&nbsp;
344       "<a rel=\"top\" accesskey=\"t\" href=\"#Top\">Top</a>\n";
345     // (s) << "Previous:&nbsp;<a rel="previous" accesskey="p" href="#dir">(dir)</a>,
346     // (s) << "Up:&nbsp;<a rel="up" accesskey="u" href="#dir">(dir)</a>
347     (s) << "<h2 class=\"section\">"<<name<<"</h2>\n";
348
349
350     std::string descr = GetDescription();
351     //Utilities::html_format(descr);
352     
353     std::string author = GetAuthor();
354     Utilities::html_format(author);
355     
356     std::vector<std::string> categories;
357     // Split the category string 
358     std::string delimiters = ";,";
359     Utilities::SplitString(GetCategory(),
360                            delimiters,categories);
361
362         
363     (s) << "<p><TABLE cellspacing=0  cellpadding=3>\n";
364     (s) << "<TR><TD style='vertical-align: top;'><b> Description </b></TD><TD style='vertical-align: top;'> : </TD><TD style='vertical-align: top;'> " 
365         << descr << "</TD></TR>\n";
366
367     (s) << "<TR><TD style='vertical-align: top;'><b> Author(s) </b></TD><TD style='vertical-align: top;'> : </TD><TD style='vertical-align: top;'>  " 
368         << author << "</TD></TR>\n";
369
370     (s) << "<TR><TD style='vertical-align: top;'><b> Category(s) </b></TD><TD style='vertical-align: top;'> : </TD><TD style='vertical-align: top;'>  ";
371     std::vector<std::string>::iterator ci;
372     for (ci=categories.begin(); ci!=categories.end(); ++ci)
373       {
374         s << "<a href=\"../index-category.html#"<< *ci <<"\">" << *ci 
375           << "</a>&nbsp;\n";
376       }
377     s << "</TD></TR>\n";      
378     std::string inc = GetScriptFileName();
379     if (inc.size()>0) 
380       {
381         s << "<TR><TD style='vertical-align: top;'><b> To use it </b></TD><TD style='vertical-align: top;'> : </TD><TD style='vertical-align: top;'> include ";
382         // s << inc << "&nbsp;&nbsp;<a href=\"../../../bbs/"<<inc<<"\">[source]</a>";
383         // LG TODO : USE PACKAGE BBS PATH
384         s << inc << "&nbsp;&nbsp;<a href=\""<<inc<<"\">[source]</a>";
385         s << "</TD></TR>\n";
386         
387       }
388     
389     const ComplexBlackBox::BlackBoxMapType& B = mPrototype->bbGetBlackBoxMap();
390         
391     if (B.size()) 
392     {
393            (s) << "<TR><TD style='vertical-align: top;'><b> Uses </b></TD><TD style='vertical-align: top;'> : </TD><TD style='vertical-align: top;'>  ";
394
395            std::set<BlackBoxDescriptor::Pointer> pdeps;
396            ComplexBlackBox::BlackBoxMapType::const_iterator b;
397            for ( b = B.begin(); b != B.end(); ++b ) 
398            {
399              BlackBoxDescriptor::Pointer d = b->second->bbGetDescriptor();
400               if (pdeps.find(d) != pdeps.end()) 
401             continue;
402               pdeps.insert(d);
403
404               Package::Pointer p = d->GetPackage();
405             
406               std::string name = b->second->bbGetTypeName();
407
408               std::string url;
409               if (relative_link) 
410                  url = p->GetDocRelativeURL();
411               else 
412                  url = p->GetDocURL();
413
414               s << "<a href=\"" <<url<<"#"<<name<<"\">" 
415                 << p->GetName()<<"::"<<name<<"</a>\n";
416             }   
417         
418             (s) << "</TD></TR>\n";
419
420      }
421
422      (s) << "</TABLE>\n";
423
424  
425    //-------------
426     // Graph
427     InsertHTMLGraph( s , detail,level, output_dir, relative_link);
428     
429     //-------------
430     // Inputs
431     std::string col("#CCCCFF");
432     
433     //  (s) << "<h3 class=\"subsection\">Inputs</h3>\n";
434     (s) << "<p><TABLE border=1 cellspacing=0 cellpadding=3>\n";
435     (s) << "<TR><TD colspan=3 align=center bgcolor=\""<<col
436       <<"\">Inputs</TD></TR>\n";
437     const BlackBoxDescriptor::InputDescriptorMapType& imap = 
438       GetInputDescriptorMap();
439     
440     InputDescriptorMapType::const_iterator in;
441     
442     for ( in = imap.begin();  in != imap.end(); ++in ) 
443       {
444         std::string name(in->second->GetName());
445         Utilities::html_format(name);
446         
447         std::string type("<");
448         type += in->second->GetTypeName();    
449         type += ">";
450         Utilities::html_format(type);
451         
452         std::string descr(in->second->GetDescription());
453         //Utilities::html_format(descr);
454
455         (s) << "<TR><TD style='vertical-align: top;'><B><PRE> "<<name<<" </PRE></B></TD>"
456           << "<TD style='vertical-align: top;'><I><PRE> "<<type<<" </PRE></I></TD>"
457           << "<TD style='vertical-align: top;'>"<<descr<<"</TD></TR>\n";
458         
459       }
460     //  (s) << "</TABLE>\n";
461     
462     
463     //-------------
464     // Outputs
465     //  (s) << "<h3 class=\"subsection\">Outputs</h3>\n";
466     //  (s) << "<TABLE border=1 cellspacing=0>\n";
467     (s) << "<TR><TD colspan=3 align=center bgcolor=\""<<col
468       <<"\">Outputs</TD></TR>\n";
469     
470     const BlackBoxDescriptor::OutputDescriptorMapType& omap = 
471       GetOutputDescriptorMap();
472     
473     BlackBoxDescriptor::OutputDescriptorMapType::const_iterator o;
474     
475     for ( o = omap.begin();  o != omap.end(); ++o ) 
476       {
477         std::string name(o->second->GetName());
478         Utilities::html_format(name);
479         
480         std::string type("<");
481         type += o->second->GetTypeName();    
482         type += ">";
483         Utilities::html_format(type);
484         
485         std::string descr(o->second->GetDescription());
486         //Utilities::html_format(descr);
487         
488         (s) << "<TR><TD style='vertical-align: top;'><B><PRE> "<<name<<" </PRE></B></TD>"
489           << "<TD style='vertical-align: top;'><I><PRE> "<<type<<" </PRE></I></TD>"
490           << "<TD style='vertical-align: top;'>"<<descr<<"</TD></TR>\n";
491         
492       }
493     (s) << "</TABLE>\n";
494
495     //------------
496     // End
497
498     bbtkDebugDecTab("Kernel",9);
499    }
500   //=========================================================================
501  
502
503   //=======================================================================
504   void ComplexBlackBoxDescriptor::GetHelp(bool full) const
505   {
506     if (full) bbtkMessage("Help",1,"Complex Black Box <"<<
507                           GetPackage()->GetName()<<"::"
508                           <<GetTypeName()<<">"<<std::endl);
509     bbtkMessage("Help",1," "                << GetDescription() <<std::endl);
510     bbtkMessage("Help",1," By : "           << GetAuthor()      <<std::endl);
511     bbtkMessage("Help",1," Category(s) : "  << GetCategory()     <<std::endl);    
512     if (mInput.size()) 
513       bbtkMessage("Help",1," * Inputs : "<<std::endl);
514     else 
515       bbtkMessage("Help",1," * No inputs"<<std::endl);
516     InputDescriptorMapType::const_iterator i;
517     unsigned int namelmax = 0;
518     unsigned int typelmax = 0;
519     unsigned int natlmax = 0;
520     for ( i = mInput.begin();  i != mInput.end(); ++i ) 
521     {
522            if (i->second->GetName().size()>namelmax) 
523              namelmax = i->second->GetName().size();
524            if (i->second->GetTypeName().size()>typelmax) 
525              typelmax = i->second->GetTypeName().size();
526            if (i->second->GetNature().size()>natlmax) 
527              natlmax = i->second->GetNature().size();
528     }
529     OutputDescriptorMapType::const_iterator o;
530     if (full) 
531     {
532            for ( o = mOutput.begin();  o != mOutput.end(); ++o ) 
533            {
534              if (o->second->GetName().size()>namelmax) 
535                namelmax = o->second->GetName().size();
536             if (o->second->GetTypeName().size()>typelmax) 
537                typelmax = o->second->GetTypeName().size();
538            if (o->second->GetNature().size()>natlmax) 
539              natlmax = o->second->GetNature().size();
540            }
541     }
542     //
543
544     for ( i = mInput.begin();  i != mInput.end(); ++i ) 
545     {
546            std::string name(i->second->GetName());
547            name += "'";
548            name.append(1+namelmax-name.size(),' ');
549            std::string type(i->second->GetTypeName());
550            type += ">";
551            type.append(1+typelmax-type.size(),' ');
552            std::string nature(i->second->GetNature());
553            nature += "]";
554            nature.append(1+natlmax-nature.size(),' ');
555            bbtkMessage("Help",1,
556                        "    '"<<name
557                        <<" <"<<type
558                        <<" ["<<nature
559                        <<" : "<<i->second->GetDescription()<<std::endl);
560     }
561     if (full) 
562     {
563            if (mOutput.size()) 
564              bbtkMessage("Help",1," * Outputs : "<<std::endl);
565            else 
566              bbtkMessage("Help",1," * No outputs"<<std::endl);
567            for ( o = mOutput.begin();  o != mOutput.end(); ++o ) 
568            {
569              std::string name(o->second->GetName());
570              name += "'";
571              name.append(1+namelmax-name.size(),' ');
572              std::string type(o->second->GetTypeName());
573              type += ">";
574              type.append(1+typelmax-type.size(),' ');
575              std::string nature(o->second->GetNature());
576              nature += "]";
577              nature.append(1+natlmax-nature.size(),' ');
578              bbtkMessage("Help",1,
579                        "    '"<<name
580                          <<" <"<<type
581                          <<" ["<<nature
582                          <<" : "<<o->second->GetDescription()<<std::endl);
583            }
584     }
585     if (full) 
586     {
587            const ComplexBlackBox::BlackBoxMapType& B = mPrototype->bbGetBlackBoxMap();
588         
589            if (B.size()) 
590              bbtkMessage("Help",1," * Boxes : "<<std::endl);
591            else 
592              bbtkMessage("Help",1," * No boxes"<<std::endl);
593         
594            ComplexBlackBox::BlackBoxMapType::const_iterator b;
595            for ( b = B.begin(); b != B.end(); ++b ) 
596            {
597              bbtkMessage("Help",1,"    '"<<b->second->bbGetName()<<
598                          "' <"
599                          << b->second->bbGetDescriptor()->GetPackage()->GetName() 
600                          <<"::"
601                          <<b->second->bbGetTypeName()<<">"<<std::endl);
602            }
603     }
604
605   }   
606   //=======================================================================
607
608   //==========================================================================
609   std::string ComplexBlackBoxDescriptor::GetObjectName() const
610   {
611     return std::string("ComplexBlackBoxDescriptor '")+GetFullTypeName()
612       +std::string("'");
613   }
614   //==========================================================================
615   //=======================================================================
616   std::string ComplexBlackBoxDescriptor::GetObjectInfo() const
617   {
618     std::string i;
619     return i;     
620   }
621   //=======================================================================
622  //==========================================================================
623 size_t  ComplexBlackBoxDescriptor::GetObjectSize() const 
624 {
625   size_t s = Superclass::GetObjectSize();
626   s += ComplexBlackBoxDescriptor::GetObjectInternalSize();
627   return s;
628   }
629   //==========================================================================
630   //==========================================================================
631 size_t  ComplexBlackBoxDescriptor::GetObjectInternalSize() const 
632 {
633   size_t s = sizeof(ComplexBlackBoxDescriptor);
634   return s;
635   }
636   //==========================================================================
637   //==========================================================================
638   size_t  ComplexBlackBoxDescriptor::GetObjectRecursiveSize() const 
639   {
640     size_t s = Superclass::GetObjectRecursiveSize();
641     s += ComplexBlackBoxDescriptor::GetObjectInternalSize();
642     s += mPrototype->GetObjectRecursiveSize();
643     return s;
644   }
645   //==========================================================================
646
647 }