Salome HOME
Dump Python extension.
[modules/geom.git] / src / GEOM / GEOM_Engine.cxx
1 // Copyright (C) 2005  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
3 // 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either 
7 // version 2.1 of the License.
8 // 
9 // This library is distributed in the hope that it will be useful 
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
12 // Lesser General Public License for more details.
13 //
14 // You should have received a copy of the GNU Lesser General Public  
15 // License along with this library; if not, write to the Free Software 
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17 //
18 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 //
20 #ifdef WNT
21 #pragma warning( disable:4786 )
22 #endif
23
24 #include "GEOM_Engine.hxx"
25
26 #include "GEOM_Solver.hxx"
27 #include "GEOM_Function.hxx"
28 #include "GEOM_ISubShape.hxx"
29 #include "GEOM_SubShapeDriver.hxx"
30 #include "GEOM_DataMapIteratorOfDataMapOfAsciiStringTransient.hxx"
31 #include "GEOM_PythonDump.hxx"
32
33 #include "utilities.h"
34
35 #include <TDF_Tool.hxx>
36 #include <TDF_Data.hxx>
37 #include <TDF_LabelSequence.hxx>
38 #include <TDataStd_Integer.hxx>
39 #include <TDataStd_ChildNodeIterator.hxx>
40 #include <TFunction_Driver.hxx>
41 #include <TFunction_DriverTable.hxx>
42
43 #include <TopExp.hxx>
44 #include <TopTools_IndexedMapOfShape.hxx>
45
46 #include <TCollection_AsciiString.hxx>
47 #include <TCollection_ExtendedString.hxx>
48 #include <TColStd_SequenceOfAsciiString.hxx>
49 #include <TColStd_MapOfTransient.hxx>
50 #include <TColStd_HSequenceOfInteger.hxx>
51
52
53 #include <Interface_DataMapIteratorOfDataMapOfIntegerTransient.hxx>
54 #include <Resource_DataMapIteratorOfDataMapOfAsciiStringAsciiString.hxx>
55
56 #include <map>
57 #include <string>
58
59 #include <Standard_Failure.hxx>
60 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
61
62 #define COMMA ','
63 #define O_BRACKET '('
64 #define C_BRACKET ')'
65
66 #ifdef _DEBUG_
67 static int MYDEBUG = 0;
68 #else
69 static int MYDEBUG = 0;
70 #endif
71
72 static GEOM_Engine* TheEngine = NULL;
73
74 static TCollection_AsciiString BuildIDFromObject(Handle(GEOM_Object)& theObject)
75 {
76   TCollection_AsciiString anID(theObject->GetDocID()), anEntry;
77   TDF_Tool::Entry(theObject->GetEntry(), anEntry);
78   anID+=(TCollection_AsciiString("_")+anEntry);
79   return anID;
80 }
81
82 static TCollection_AsciiString BuildID(Standard_Integer theDocID, char* theEntry)
83 {
84   TCollection_AsciiString anID(theDocID);
85   anID+=(TCollection_AsciiString("_")+theEntry);
86   return anID;
87 }
88
89 static Standard_Integer ExtractDocID(TCollection_AsciiString& theID)
90 {
91   TCollection_AsciiString aDocID = theID.Token("_");
92   if(aDocID.Length() < 1) return -1;
93   return aDocID.IntegerValue();
94 }
95
96 void ProcessFunction(Handle(GEOM_Function)& theFunction, 
97                      TCollection_AsciiString& theScript,
98                      Resource_DataMapOfAsciiStringAsciiString& theVariableNames,
99                      TColStd_HSequenceOfAsciiString& theStudyVariables,
100                      TColStd_MapOfTransient& theProcessed);
101
102 void ReplaceVariables(TCollection_AsciiString& theCommand, 
103                       Resource_DataMapOfAsciiStringAsciiString& theVariableNames,
104                       TColStd_HSequenceOfAsciiString& theStudyVariables);
105
106
107
108 Handle(TColStd_HSequenceOfInteger) FindEntries(TCollection_AsciiString& theString);
109
110
111 //=============================================================================
112 /*!
113  *  GetEngine
114  */
115 //=============================================================================
116 GEOM_Engine* GEOM_Engine::GetEngine() { return TheEngine; }
117
118
119 //=============================================================================
120 /*!
121  *  SetEngine
122  */
123 //=============================================================================
124 void GEOM_Engine::SetEngine(GEOM_Engine* theEngine) { TheEngine = theEngine; }
125
126 //=============================================================================
127 /*!
128  *  Constructor
129  */
130 //=============================================================================
131 GEOM_Engine::GEOM_Engine()
132 {
133   TFunction_DriverTable::Get()->AddDriver(GEOM_Object::GetSubShapeID(), new GEOM_SubShapeDriver());
134
135   _OCAFApp = new GEOM_Application();
136   _UndoLimit = 10;
137 }
138
139 /*!
140  *  Destructor
141  */
142 GEOM_Engine::~GEOM_Engine()
143
144   GEOM_DataMapIteratorOfDataMapOfAsciiStringTransient It(_objects);
145   for(; It.More(); It.Next()) 
146     {
147       RemoveObject(Handle(GEOM_Object)::DownCast(It.Value()));
148     }
149
150   //Close all documents not closed
151   for(Interface_DataMapIteratorOfDataMapOfIntegerTransient anItr(_mapIDDocument); anItr.More(); anItr.Next())
152     Close(anItr.Key());
153
154   _mapIDDocument.Clear();
155   _objects.Clear();
156 }
157
158 //=============================================================================
159 /*!
160  *  GetDocument
161  */
162 //=============================================================================
163 Handle(TDocStd_Document) GEOM_Engine::GetDocument(int theDocID)
164 {
165   Handle(TDocStd_Document) aDoc;
166   if(!_mapIDDocument.IsBound(theDocID)) {
167     _OCAFApp->NewDocument("SALOME_GEOM", aDoc);
168     aDoc->SetUndoLimit(_UndoLimit);
169     _mapIDDocument.Bind(theDocID, aDoc);
170     TDataStd_Integer::Set(aDoc->Main(), theDocID);
171   }
172
173   return Handle(TDocStd_Document)::DownCast(_mapIDDocument(theDocID));
174 }
175
176 //=============================================================================
177 /*!
178  *  GetDocID
179  */
180 //=============================================================================
181 int GEOM_Engine::GetDocID(Handle(TDocStd_Document) theDocument)
182 {
183   if(theDocument.IsNull()) return -1;
184   for(Interface_DataMapIteratorOfDataMapOfIntegerTransient anItr(_mapIDDocument); anItr.More(); anItr.Next())
185     if(anItr.Value() == theDocument) return anItr.Key();
186
187   return -1;
188
189 }
190
191 //=============================================================================
192 /*!
193  *  GetObject
194  */
195 //=============================================================================
196 Handle(GEOM_Object) GEOM_Engine::GetObject(int theDocID, char* theEntry)
197 {
198   TCollection_AsciiString anID = BuildID(theDocID, theEntry);
199   if(_objects.IsBound(anID)) return Handle(GEOM_Object)::DownCast(_objects(anID));
200
201   TDF_Label aLabel;
202   Handle(TDocStd_Document) aDoc = GetDocument(theDocID);
203   TDF_Tool::Label(aDoc->Main().Data(), theEntry, aLabel, Standard_True);
204   Handle(GEOM_Object) anObject = new GEOM_Object(aLabel);
205
206   _objects.Bind(anID, anObject);
207
208   return anObject;
209 }
210
211 //=============================================================================
212 /*!
213  *  AddObject
214  */
215 //=============================================================================
216 Handle(GEOM_Object) GEOM_Engine::AddObject(int theDocID, int theType)
217 {
218   Handle(TDocStd_Document) aDoc = GetDocument(theDocID);
219   Handle(TDataStd_TreeNode) aRoot = TDataStd_TreeNode::Set(aDoc->Main());
220
221   // NPAL18604: use existing label to decrease memory usage,
222   //            if this label has been freed (object deleted)
223   bool useExisting = false;
224   TDF_Label aChild;
225   if (!_lastCleared.IsNull()) {
226     if (_lastCleared.Root() == aDoc->Main().Root()) {
227       useExisting = true;
228       aChild = _lastCleared;
229       _lastCleared.Nullify();
230     }
231   }
232   if (!useExisting) {
233     // create new label
234     aChild = TDF_TagSource::NewChild(aDoc->Main());
235   }
236
237   Handle(GEOM_Object) anObject = new GEOM_Object(aChild, theType);
238
239   //Put an object in the map of created objects
240   TCollection_AsciiString anID = BuildIDFromObject(anObject);
241   if(_objects.IsBound(anID)) _objects.UnBind(anID);
242   _objects.Bind(anID, anObject);
243
244   return anObject;
245 }
246
247 //=============================================================================
248 /*!
249  *  AddSubShape
250  */
251 //=============================================================================
252 Handle(GEOM_Object) GEOM_Engine::AddSubShape(Handle(GEOM_Object) theMainShape, 
253                                              Handle(TColStd_HArray1OfInteger) theIndices,
254                                              bool isStandaloneOperation)
255 {
256   if(theMainShape.IsNull() || theIndices.IsNull()) return NULL;
257
258   Handle(TDocStd_Document) aDoc = GetDocument(theMainShape->GetDocID());
259   Handle(TDataStd_TreeNode) aRoot = TDataStd_TreeNode::Set(aDoc->Main());
260
261   // NPAL18604: use existing label to decrease memory usage,
262   //            if this label has been freed (object deleted)
263   bool useExisting = false;
264   TDF_Label aChild;
265   if (!_lastCleared.IsNull()) {
266     if (_lastCleared.Root() == aDoc->Main().Root()) {
267       useExisting = true;
268       aChild = _lastCleared;
269       _lastCleared.Nullify();
270     }
271   }
272   if (!useExisting) {
273     // create new label
274     aChild = TDF_TagSource::NewChild(aDoc->Main());
275   }
276
277   Handle(GEOM_Function) aMainShape = theMainShape->GetLastFunction();
278   Handle(GEOM_Object) anObject = new GEOM_Object(aChild, 28); //28 is SUBSHAPE type
279   Handle(GEOM_Function) aFunction = anObject->AddFunction(GEOM_Object::GetSubShapeID(), 1);
280
281   GEOM_ISubShape aSSI(aFunction);
282   aSSI.SetMainShape(aMainShape);
283   aSSI.SetIndices(theIndices);
284
285   try {
286 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
287     OCC_CATCH_SIGNALS;
288 #endif
289     GEOM_Solver aSolver (GEOM_Engine::GetEngine());
290     if (!aSolver.ComputeFunction(aFunction)) {
291       MESSAGE("GEOM_Engine::AddSubShape Error: Can't build a sub shape");
292       return NULL;
293     }
294   }
295   catch (Standard_Failure) {
296     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
297     MESSAGE("GEOM_Engine::AddSubShape Error: " << aFail->GetMessageString());
298     return NULL;
299   }
300
301   //Put an object in the map of created objects
302   TCollection_AsciiString anID = BuildIDFromObject(anObject);
303   if(_objects.IsBound(anID)) _objects.UnBind(anID);
304   _objects.Bind(anID, anObject);
305
306   GEOM::TPythonDump pd (aFunction);
307  
308   if (isStandaloneOperation) {
309     pd << anObject << " = geompy.GetSubShape(" << theMainShape << ", [";
310     Standard_Integer i = theIndices->Lower(), up = theIndices->Upper();
311     for (; i <= up - 1; i++) {
312       pd << theIndices->Value(i) << ", ";
313     }
314     pd << theIndices->Value(up) << "])";
315   }
316   else
317     pd << "None";
318
319   return anObject;
320 }
321
322 //=============================================================================
323 /*!
324  *  RemoveObject
325  */
326 //=============================================================================
327 bool GEOM_Engine::RemoveObject(Handle(GEOM_Object) theObject)
328 {
329   if (!theObject) return false;
330
331   //Remove an object from the map of available objects
332   TCollection_AsciiString anID = BuildIDFromObject(theObject);
333   if (_objects.IsBound(anID)) _objects.UnBind(anID);
334
335   int nb = theObject->GetNbFunctions();
336   Handle(TDataStd_TreeNode) aNode;
337   for (int i = 1; i<=nb; i++) {
338     Handle(GEOM_Function) aFunction = theObject->GetFunction(i);
339     if (aFunction->GetEntry().FindAttribute(GEOM_Function::GetFunctionTreeID(), aNode)) 
340       aNode->Remove();
341   }
342
343   TDF_Label aLabel = theObject->GetEntry();
344   aLabel.ForgetAllAttributes(Standard_True);
345   _lastCleared = aLabel;
346
347   theObject.Nullify();
348
349   return true;
350 }
351
352 //=============================================================================
353 /*!
354  *  Undo
355  */
356 //=============================================================================
357 void GEOM_Engine::Undo(int theDocID)
358 {
359   GetDocument(theDocID)->Undo();
360 }
361
362 //=============================================================================
363 /*!
364  *  Redo
365  */
366 //=============================================================================
367 void GEOM_Engine::Redo(int theDocID)
368 {
369   GetDocument(theDocID)->Redo();
370 }
371
372 //=============================================================================
373 /*!
374  *  Save
375  */
376 //=============================================================================
377 bool GEOM_Engine::Save(int theDocID, char* theFileName)
378 {
379   if(!_mapIDDocument.IsBound(theDocID)) return false;
380   Handle(TDocStd_Document) aDoc = Handle(TDocStd_Document)::DownCast(_mapIDDocument(theDocID));
381
382   _OCAFApp->SaveAs(aDoc, theFileName);
383
384   return true;
385 }
386
387 //=============================================================================
388 /*!
389  *  Load
390  */
391 //=============================================================================
392 bool GEOM_Engine::Load(int theDocID, char* theFileName)
393 {
394   Handle(TDocStd_Document) aDoc;
395   if(_OCAFApp->Open(theFileName, aDoc) != CDF_RS_OK) {
396     return false;
397   }
398
399   aDoc->SetUndoLimit(_UndoLimit);
400
401   if(_mapIDDocument.IsBound(theDocID)) _mapIDDocument.UnBind(theDocID);
402   _mapIDDocument.Bind(theDocID, aDoc);
403
404   TDataStd_Integer::Set(aDoc->Main(), theDocID);
405
406   return true;
407 }
408
409 //=============================================================================
410 /*!
411  *  Close
412  */
413 //=============================================================================
414 void GEOM_Engine::Close(int theDocID)
415 {
416   if (_mapIDDocument.IsBound(theDocID)) {
417     Handle(TDocStd_Document) aDoc = Handle(TDocStd_Document)::DownCast(_mapIDDocument(theDocID));
418
419     //Remove all GEOM Objects associated to the given document
420     TColStd_SequenceOfAsciiString aSeq;
421     GEOM_DataMapIteratorOfDataMapOfAsciiStringTransient It (_objects);
422     for (; It.More(); It.Next()) {
423       TCollection_AsciiString anObjID (It.Key());
424       Standard_Integer anID = ExtractDocID(anObjID);
425       if (theDocID == anID) aSeq.Append(It.Key());
426     }
427     for (Standard_Integer i=1; i<=aSeq.Length(); i++) _objects.UnBind(aSeq.Value(i));
428
429     _lastCleared.Nullify();
430
431     _mapIDDocument.UnBind(theDocID);
432     _OCAFApp->Close(aDoc);
433     aDoc.Nullify();
434   }
435 }
436
437 //=============================================================================
438 /*!
439  *  DumpPython
440  */
441 //=============================================================================
442 TCollection_AsciiString GEOM_Engine::DumpPython(int theDocID,
443                                                 Resource_DataMapOfAsciiStringAsciiString& theObjectNames,
444                                                 Resource_DataMapOfAsciiStringAsciiString& theVariableNames,
445                                                 TColStd_HSequenceOfAsciiString& theStudyVariables,
446                                                 bool isPublished,
447                                                 bool& aValidScript)
448 {
449   TCollection_AsciiString aScript;
450   Handle(TDocStd_Document) aDoc = GetDocument(theDocID);
451
452   if (aDoc.IsNull()) return TCollection_AsciiString("def RebuildData(theStudy): pass\n");
453
454   aScript = "import geompy\n";
455   aScript += "import math\n";
456   aScript += "import SALOMEDS\n\n";
457   aScript += "def RebuildData(theStudy):";
458   aScript += "\n\tgeompy.init_geom(theStudy)";
459
460   Standard_Integer posToInertGlobalVars = aScript.Length() + 1;
461
462   Handle(TDataStd_TreeNode) aNode, aRoot;
463   Handle(GEOM_Function) aFunction;
464   TColStd_MapOfTransient aMap;
465
466   if (aDoc->Main().FindAttribute(GEOM_Function::GetFunctionTreeID(), aRoot)) {
467     TDataStd_ChildNodeIterator Itr(aRoot);
468     for (; Itr.More(); Itr.Next()) {
469       aNode = Itr.Value();
470       aFunction = GEOM_Function::GetFunction(aNode->Label());
471       if (aFunction.IsNull()) {
472         MESSAGE ( "Null function !!!!" );
473         continue;
474       }
475       ProcessFunction(aFunction, aScript, theVariableNames, theStudyVariables ,aMap);
476     }
477   }
478
479   Resource_DataMapOfAsciiStringAsciiString aEntry2StEntry, aStEntry2Entry;
480   Resource_DataMapIteratorOfDataMapOfAsciiStringAsciiString anEntryToNameIt;
481   // build maps entry <-> studyEntry
482   for (anEntryToNameIt.Initialize( theObjectNames );
483        anEntryToNameIt.More();
484        anEntryToNameIt.Next())
485   {
486     const TCollection_AsciiString& aEntry = anEntryToNameIt.Key();
487     // look for an object by entry
488     TDF_Label L;
489     TDF_Tool::Label( aDoc->GetData(), aEntry, L );
490     if ( L.IsNull() ) continue;
491     Handle(GEOM_Object) obj = GEOM_Object::GetObject( L );
492     // fill maps
493     if ( !obj.IsNull() ) {
494       TCollection_AsciiString aStudyEntry (obj->GetAuxData());
495       aEntry2StEntry.Bind( aEntry,  aStudyEntry);
496       aStEntry2Entry.Bind( aStudyEntry, aEntry );
497     }
498   }
499
500   Handle(TColStd_HSequenceOfInteger) aSeq = FindEntries(aScript);
501   Standard_Integer aLen = aSeq->Length(), objectCounter = 0, aStart = 1, aScriptLength = aScript.Length();
502   Resource_DataMapOfAsciiStringAsciiString aNameToEntry, anEntryToBadName;
503
504   //Replace entries by the names
505   TCollection_AsciiString anUpdatedScript, anEntry, aName, aBaseName("geomObj_"),
506     allowedChars ("qwertyuioplkjhgfdsazxcvbnmQWERTYUIOPLKJHGFDSAZXCVBNM0987654321_");
507   if (aLen == 0) anUpdatedScript = aScript;
508
509   for (Standard_Integer i = 1; i <= aLen; i+=2) {
510     anUpdatedScript += aScript.SubString(aStart, aSeq->Value(i)-1);
511     anEntry = aScript.SubString(aSeq->Value(i), aSeq->Value(i+1));
512     if (theObjectNames.IsBound(anEntry)) {
513       aName = theObjectNames.Find(anEntry);
514       // check validity of aName
515       bool isValidName = true;
516       if ( aName.IsIntegerValue() ) { // aName must not start with a digit
517         aName.Insert( 1, 'a' );
518         isValidName = false;
519       }
520       int p, p2=1; // replace not allowed chars
521       while ((p = aName.FirstLocationNotInSet(allowedChars, p2, aName.Length()))) {
522         aName.SetValue(p, '_');
523         p2=p;
524         isValidName = false;
525       }
526       if ( aNameToEntry.IsBound( aName ) && anEntry != aNameToEntry( aName ))
527       {  // diff objects have same name - make a new name by appending a digit
528         TCollection_AsciiString aName2;
529         Standard_Integer i = 0;
530         do {
531           aName2 = aName + "_" + ++i;
532         } while ( aNameToEntry.IsBound( aName2 ) && anEntry != aNameToEntry( aName2 ));
533         aName = aName2;
534         isValidName = false;
535       }
536       if ( !isValidName ) {
537         if ( isPublished )
538           anEntryToBadName.Bind( anEntry, theObjectNames.Find(anEntry) );
539         theObjectNames( anEntry ) = aName;
540       }
541     }
542     else {
543       do {
544         aName = aBaseName + TCollection_AsciiString(++objectCounter);
545       } while(aNameToEntry.IsBound(aName));
546       theObjectNames.Bind(anEntry, aName);
547     }
548     aNameToEntry.Bind(aName, anEntry); // to detect same name of diff objects
549
550     anUpdatedScript += aName;
551     aStart = aSeq->Value(i+1) + 1;
552   }
553
554   //Add final part of the script
555   if (aLen && aSeq->Value(aLen) < aScriptLength)
556     anUpdatedScript += aScript.SubString(aSeq->Value(aLen)+1, aScriptLength); // mkr : IPAL11865
557
558   // ouv : NPAL12872
559   for (anEntryToNameIt.Initialize( theObjectNames );
560        anEntryToNameIt.More();
561        anEntryToNameIt.Next())
562   {
563     const TCollection_AsciiString& aEntry = anEntryToNameIt.Key();
564     const TCollection_AsciiString& aName = anEntryToNameIt.Value();
565
566     TDF_Label L;
567     TDF_Tool::Label( aDoc->GetData(), aEntry, L );
568     if ( L.IsNull() )
569       continue;
570
571     Handle(GEOM_Object) obj = GEOM_Object::GetObject( L );
572     if ( obj.IsNull() )
573       continue;
574
575     bool anAutoColor = obj->GetAutoColor();
576     if ( anAutoColor )
577     {
578       TCollection_AsciiString aCommand( "\n\t" );
579       aCommand += aName + ".SetAutoColor(1)";
580       anUpdatedScript += aCommand.ToCString();
581     }
582
583     SALOMEDS::Color aColor = obj->GetColor();
584     if ( aColor.R > 0 || aColor.G > 0 || aColor.B > 0 )
585     {
586       TCollection_AsciiString aCommand( "\n\t" );
587       aCommand += aName + ".SetColor(SALOMEDS.Color(" + aColor.R + "," + aColor.G + "," + aColor.B + "))";
588       anUpdatedScript += aCommand.ToCString();
589     }
590   }
591
592   // Make script to publish in study
593   if ( isPublished )
594   {
595     std::map< int, std::string > anEntryToCommandMap; // sort publishing commands by object entry
596     for (anEntryToNameIt.Initialize( theObjectNames );
597          anEntryToNameIt.More();
598          anEntryToNameIt.Next())
599     {
600       const TCollection_AsciiString& aEntry = anEntryToNameIt.Key();
601       const TCollection_AsciiString& aName = anEntryToNameIt.Value();
602       if ( !aEntry2StEntry.IsBound( aEntry ))
603         continue; // was not published
604       TCollection_AsciiString aCommand("\n\tgeompy."), aFatherEntry;
605
606       // find a father entry
607       const TCollection_AsciiString& aStudyEntry = aEntry2StEntry( aEntry );
608       TCollection_AsciiString aFatherStudyEntry =
609         aStudyEntry.SubString( 1, aStudyEntry.SearchFromEnd(":") - 1 );
610       if ( aStEntry2Entry.IsBound( aFatherStudyEntry ))
611         aFatherEntry = aStEntry2Entry( aFatherStudyEntry );
612
613       // make a command
614       if ( !aFatherEntry.IsEmpty() && theObjectNames.IsBound( aFatherEntry )) {
615         aCommand += "addToStudyInFather( ";
616         aCommand += theObjectNames( aFatherEntry ) + ", ";
617       }
618       else
619         aCommand += "addToStudy( ";
620       if ( anEntryToBadName.IsBound( aEntry ))
621         aCommand += aName + ", \"" + anEntryToBadName( aEntry ) + "\" )";
622       else 
623         aCommand += aName + ", \"" + aName + "\" )";
624
625       // bind a command to the last digit of the entry
626       int tag =
627         aEntry.SubString( aEntry.SearchFromEnd(":")+1, aEntry.Length() ).IntegerValue();
628       anEntryToCommandMap.insert( std::make_pair( tag, aCommand.ToCString() ));
629     }
630
631     // add publishing commands to the script
632     std::map< int, std::string >::iterator anEntryToCommand = anEntryToCommandMap.begin();
633     for ( ; anEntryToCommand != anEntryToCommandMap.end(); ++anEntryToCommand ) {
634       anUpdatedScript += (char*)anEntryToCommand->second.c_str();
635     }
636   }
637
638   //anUpdatedScript += "\n\tpass\n";
639   anUpdatedScript += "\n";
640   aValidScript = true;
641
642   // fill _studyEntry2NameMap and build globalVars
643   TCollection_AsciiString globalVars;
644   _studyEntry2NameMap.Clear();
645   Resource_DataMapIteratorOfDataMapOfAsciiStringAsciiString aStEntryToEntryIt;
646   for (aStEntryToEntryIt.Initialize( aStEntry2Entry );
647        aStEntryToEntryIt.More();
648        aStEntryToEntryIt.Next() )
649   {
650     const TCollection_AsciiString & name = theObjectNames( aStEntryToEntryIt.Value() );
651     _studyEntry2NameMap.Bind (aStEntryToEntryIt.Key(), name );
652     if ( !globalVars.IsEmpty() )
653       globalVars += ", ";
654     globalVars += name;
655   }
656   if ( !globalVars.IsEmpty() ) {
657     globalVars.Insert( 1, "\n\tglobal " );
658     anUpdatedScript.Insert( posToInertGlobalVars, globalVars );
659   }
660
661   return anUpdatedScript;
662 }
663
664 //=======================================================================
665 //function : GetDumpName
666 //purpose  : 
667 //=======================================================================
668
669 const char* GEOM_Engine::GetDumpName (const char* theStudyEntry) const
670 {
671   if ( _studyEntry2NameMap.IsBound( (char*)theStudyEntry ))
672     return _studyEntry2NameMap( (char*)theStudyEntry ).ToCString();
673
674   return NULL;
675 }
676
677 //=======================================================================
678 //function : GetAllDumpNames
679 //purpose  : 
680 //=======================================================================
681
682 Handle(TColStd_HSequenceOfAsciiString) GEOM_Engine::GetAllDumpNames() const
683 {
684   Handle(TColStd_HSequenceOfAsciiString) aRetSeq = new TColStd_HSequenceOfAsciiString;
685
686   Resource_DataMapIteratorOfDataMapOfAsciiStringAsciiString it (_studyEntry2NameMap);
687   for (; it.More(); it.Next()) {
688     aRetSeq->Append(it.Value());
689   }
690
691   return aRetSeq;
692 }
693
694
695 //===========================================================================
696 //                     Internal functions
697 //===========================================================================
698 void ProcessFunction(Handle(GEOM_Function)& theFunction, 
699                      TCollection_AsciiString& theScript,
700                      Resource_DataMapOfAsciiStringAsciiString& theVariableNames,
701                      TColStd_HSequenceOfAsciiString& theStudyVariables,
702                      TColStd_MapOfTransient& theProcessed)
703 {
704   if(theFunction.IsNull() || theProcessed.Contains(theFunction)) return;
705
706 /*
707   TDF_LabelSequence aSeq;
708   theFunction->GetDependency(aSeq);
709   Standard_Integer aLen = aSeq.Length();
710   for(Standard_Integer i = 1; i<= aLen; i++) {
711     Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(aSeq.Value(i));
712     if(aFunction.IsNull()) continue;
713     ProcessFunction(aFunction, theScript, theProcessed);
714   }
715 */
716
717   TCollection_AsciiString aDescr = theFunction->GetDescription();
718   if(aDescr.Length() == 0) {
719     //cout << "Warning: the function has no description" << endl;
720     return;
721   }
722   //Check if its internal function which doesn't requires dumping
723   if(aDescr == "None") return;
724
725   //Replace parameter by notebook variables
726   ReplaceVariables(aDescr,theVariableNames,theStudyVariables);
727   theScript += "\n\t";
728   theScript += aDescr;
729
730  
731   theProcessed.Add(theFunction);
732   return;
733 }
734
735 //=============================================================================
736 /*!
737  *  FindEntries: Returns a sequence of start/end positions of entries in the string
738  */
739 //=============================================================================
740 Handle(TColStd_HSequenceOfInteger) FindEntries(TCollection_AsciiString& theString)
741 {
742   Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
743   Standard_Integer aLen = theString.Length();
744   Standard_Boolean isFound = Standard_False;
745
746   const char* arr = theString.ToCString();
747   Standard_Integer i = 0, j;
748
749   while(i < aLen) {
750     int c = (int)arr[i];
751     j = i+1;
752     if(c >= 48 && c <= 57) { //Is digit?
753  
754       isFound = Standard_False;
755       while((j < aLen) && ((c >= 48 && c <= 57) || c == 58) ) { //Check if it is an entry
756         c = (int)arr[j++];  
757         if(c == 58) isFound = Standard_True;
758       }
759       
760       if(isFound && arr[j-2] != 58) { // last char should be a diggit
761         aSeq->Append(i+1); // +1 because AsciiString starts from 1
762         aSeq->Append(j-1);
763       }
764     }
765      
766     i = j;
767   }
768
769   return aSeq;
770 }
771
772 //=============================================================================
773 /*!
774  *  ReplaceVariables: Replace parameters of the function by variales from 
775  *                    Notebook if need
776  */
777 //=============================================================================
778 void ReplaceVariables(TCollection_AsciiString& theCommand, 
779                       Resource_DataMapOfAsciiStringAsciiString& theVariableNames,
780                       TColStd_HSequenceOfAsciiString& theStudyVariables)
781 {
782   //Get Entry of the result object
783   TCollection_AsciiString anEntry = theCommand.Token("=",1);
784
785   //Remove white spaces
786   anEntry.RightAdjust();
787   anEntry.LeftAdjust();
788   if(MYDEBUG)
789     cout<<"Result entry : '" <<anEntry<<"'"<<endl;
790     
791   //Find variables used for object construction
792   TCollection_AsciiString aVariables;
793   if(theVariableNames.IsBound(anEntry)) 
794     aVariables = theVariableNames.Find(anEntry);
795
796   if(aVariables.IsEmpty()) {
797     if(MYDEBUG)
798       cout<<"Valiables list empty!!!"<<endl;
799     return;
800   }
801
802   if(MYDEBUG)
803     cout<<"Variables : '" <<aVariables<<"'"<<endl;
804
805   //Calculate number of variables, that mast be replaced
806   Standard_Integer aNbReplacedParams = 1,aPos;
807   TColStd_HSequenceOfInteger aPositions;
808   while(aPos = aVariables.Location(aNbReplacedParams,':',1,aVariables.Length())) {
809     aPositions.Append(aPos);
810     aNbReplacedParams++;
811   }
812
813   if(MYDEBUG)
814     cout<<"Number of replaced variables : " <<aNbReplacedParams<<endl;
815
816   if(MYDEBUG)
817     {
818       for(Standard_Integer i = 1;i<=aPositions.Length();i++)
819         cout<<"Positions ["<<i<<"] = "<<aPositions.Value(i)<<endl;
820     }
821
822   //Calculate total number of parameter
823   Standard_Integer aTotalNbParams = 1;
824   while(theCommand.Location(aTotalNbParams,COMMA,1,theCommand.Length()))
825     aTotalNbParams++;
826
827
828   if(MYDEBUG)
829     cout<<"Total Number of parameters : " <<aTotalNbParams<<endl;
830
831   //Get Variables names 
832   TColStd_SequenceOfAsciiString aVarSeq;
833   TCollection_AsciiString aVar;
834   Standard_Integer i = 1;
835   while(i <= aNbReplacedParams){
836     
837     if(i == 1)
838       aVar = (aPositions.Value(i) == 1) ? TCollection_AsciiString() : aVariables.SubString(1, aPositions.Value(i)-1);
839     else if(i == aNbReplacedParams) {
840       Standard_Integer aLen = aVariables.Length();
841       Standard_Integer aPos = aPositions.Value(i-1);
842       aVar = (aPos == aLen) ? TCollection_AsciiString() : aVariables.SubString(aPos+1, aLen);
843     }
844     else {
845       Standard_Integer aPrevPos = aPositions.Value(i-1);
846       Standard_Integer aCurrentPos = aPositions.Value(i);
847       aVar = (aCurrentPos - aPrevPos == 1) ? TCollection_AsciiString() : aVariables.SubString(aPrevPos+1, aCurrentPos-1);
848     }
849     if(MYDEBUG)
850       cout<<"Variable ["<<i<<"] = '"<<aVar<<"'"<<endl;
851     
852     //Add current varibale
853     aVarSeq.Append(aVar);
854     i++;
855   }
856
857   //Replace parameters by variables
858   Standard_Integer aStartPos = 0;
859   Standard_Integer aEndPos = 0;
860   Standard_Integer iVar = 1;
861   for(Standard_Integer i=1;i <= aTotalNbParams;i++) {
862         
863     //Replace first parameter (bettwen '(' character and first ',' character)
864     if(i == 1) 
865       {
866         aStartPos = theCommand.Location(O_BRACKET, 1, theCommand.Length()) + 1;
867         aEndPos = theCommand.Location(COMMA, 1, theCommand.Length());
868       }
869     //Replace last parameter (bettwen ',' character and ')' character)
870     else if(i == aVarSeq.Length())
871       {
872         aStartPos = theCommand.Location(i-1, COMMA, 1, theCommand.Length()) + 2;
873         aEndPos = theCommand.Location(C_BRACKET, 1, theCommand.Length());
874       }
875     //Replace other parameters (bettwen two ',' characters)
876     else if(i != 1 && i != aVarSeq.Length())
877       {
878         aStartPos = theCommand.Location(i-1, COMMA, 1, theCommand.Length()) + 2;
879         aEndPos = theCommand.Location(i, COMMA, 1, theCommand.Length());
880       }
881
882     aVar = aVarSeq.Value(iVar);
883     
884     //If parameter is entry, skip it
885     aVar.RightAdjust();
886     aVar.LeftAdjust();
887     if(theVariableNames.IsBound(aVar))
888       continue;
889
890       
891     if(aVar.IsEmpty()) {
892       iVar++;
893       continue;
894     }
895
896     bool isVar = false;
897     for(Standard_Integer i = 1; i <= theStudyVariables.Length();i++)
898       if(theStudyVariables.Value(i).IsEqual(aVar)) {
899         isVar = true;
900         break;
901       }
902     if(isVar) {
903       aVar.InsertBefore(1,"\"");
904       aVar.InsertAfter(aVar.Length(),"\"");
905     }
906
907     theCommand.Remove(aStartPos, aEndPos - aStartPos);
908     theCommand.Insert(aStartPos,aVar);    
909     iVar++;
910   }
911 }