]> SALOME platform Git repositories - modules/geom.git/blob - src/GEOM/GEOM_Engine.cxx
Salome HOME
Improve variables dump.
[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 #include <vector>
59
60 #include <Standard_Failure.hxx>
61 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
62
63 #define COMMA ','
64 #define O_BRACKET '('
65 #define C_BRACKET ')'
66 #define PY_NULL "None"
67
68 #ifdef _DEBUG_
69 static int MYDEBUG = 0;
70 #else
71 static int MYDEBUG = 0;
72 #endif
73
74 static GEOM_Engine* TheEngine = NULL;
75
76 using namespace std;
77
78 static TCollection_AsciiString BuildIDFromObject(Handle(GEOM_Object)& theObject)
79 {
80   TCollection_AsciiString anID(theObject->GetDocID()), anEntry;
81   TDF_Tool::Entry(theObject->GetEntry(), anEntry);
82   anID+=(TCollection_AsciiString("_")+anEntry);
83   return anID;
84 }
85
86 static TCollection_AsciiString BuildID(Standard_Integer theDocID, char* theEntry)
87 {
88   TCollection_AsciiString anID(theDocID);
89   anID+=(TCollection_AsciiString("_")+theEntry);
90   return anID;
91 }
92
93 static Standard_Integer ExtractDocID(TCollection_AsciiString& theID)
94 {
95   TCollection_AsciiString aDocID = theID.Token("_");
96   if(aDocID.Length() < 1) return -1;
97   return aDocID.IntegerValue();
98 }
99
100 void ProcessFunction(Handle(GEOM_Function)& theFunction, 
101                      TCollection_AsciiString& theScript,
102                      TVariablesList theVariables,
103                      TColStd_MapOfTransient& theProcessed);
104
105 void ReplaceVariables(TCollection_AsciiString& theCommand, 
106                       TVariablesList theVariables);
107
108
109
110 Handle(TColStd_HSequenceOfInteger) FindEntries(TCollection_AsciiString& theString);
111
112
113 //=============================================================================
114 /*!
115  *  GetEngine
116  */
117 //=============================================================================
118 GEOM_Engine* GEOM_Engine::GetEngine() { return TheEngine; }
119
120
121 //=============================================================================
122 /*!
123  *  SetEngine
124  */
125 //=============================================================================
126 void GEOM_Engine::SetEngine(GEOM_Engine* theEngine) { TheEngine = theEngine; }
127
128 //=============================================================================
129 /*!
130  *  Constructor
131  */
132 //=============================================================================
133 GEOM_Engine::GEOM_Engine()
134 {
135   TFunction_DriverTable::Get()->AddDriver(GEOM_Object::GetSubShapeID(), new GEOM_SubShapeDriver());
136
137   _OCAFApp = new GEOM_Application();
138   _UndoLimit = 10;
139 }
140
141 /*!
142  *  Destructor
143  */
144 GEOM_Engine::~GEOM_Engine()
145
146   GEOM_DataMapIteratorOfDataMapOfAsciiStringTransient It(_objects);
147   for(; It.More(); It.Next()) 
148     {
149       RemoveObject(Handle(GEOM_Object)::DownCast(It.Value()));
150     }
151
152   //Close all documents not closed
153   for(Interface_DataMapIteratorOfDataMapOfIntegerTransient anItr(_mapIDDocument); anItr.More(); anItr.Next())
154     Close(anItr.Key());
155
156   _mapIDDocument.Clear();
157   _objects.Clear();
158 }
159
160 //=============================================================================
161 /*!
162  *  GetDocument
163  */
164 //=============================================================================
165 Handle(TDocStd_Document) GEOM_Engine::GetDocument(int theDocID)
166 {
167   Handle(TDocStd_Document) aDoc;
168   if(!_mapIDDocument.IsBound(theDocID)) {
169     _OCAFApp->NewDocument("SALOME_GEOM", aDoc);
170     aDoc->SetUndoLimit(_UndoLimit);
171     _mapIDDocument.Bind(theDocID, aDoc);
172     TDataStd_Integer::Set(aDoc->Main(), theDocID);
173   }
174
175   return Handle(TDocStd_Document)::DownCast(_mapIDDocument(theDocID));
176 }
177
178 //=============================================================================
179 /*!
180  *  GetDocID
181  */
182 //=============================================================================
183 int GEOM_Engine::GetDocID(Handle(TDocStd_Document) theDocument)
184 {
185   if(theDocument.IsNull()) return -1;
186   for(Interface_DataMapIteratorOfDataMapOfIntegerTransient anItr(_mapIDDocument); anItr.More(); anItr.Next())
187     if(anItr.Value() == theDocument) return anItr.Key();
188
189   return -1;
190
191 }
192
193 //=============================================================================
194 /*!
195  *  GetObject
196  */
197 //=============================================================================
198 Handle(GEOM_Object) GEOM_Engine::GetObject(int theDocID, char* theEntry)
199 {
200   TCollection_AsciiString anID = BuildID(theDocID, theEntry);
201   if(_objects.IsBound(anID)) return Handle(GEOM_Object)::DownCast(_objects(anID));
202
203   TDF_Label aLabel;
204   Handle(TDocStd_Document) aDoc = GetDocument(theDocID);
205   TDF_Tool::Label(aDoc->Main().Data(), theEntry, aLabel, Standard_True);
206   Handle(GEOM_Object) anObject = new GEOM_Object(aLabel);
207
208   _objects.Bind(anID, anObject);
209
210   return anObject;
211 }
212
213 //=============================================================================
214 /*!
215  *  AddObject
216  */
217 //=============================================================================
218 Handle(GEOM_Object) GEOM_Engine::AddObject(int theDocID, int theType)
219 {
220   Handle(TDocStd_Document) aDoc = GetDocument(theDocID);
221   Handle(TDataStd_TreeNode) aRoot = TDataStd_TreeNode::Set(aDoc->Main());
222
223   // NPAL18604: use existing label to decrease memory usage,
224   //            if this label has been freed (object deleted)
225   bool useExisting = false;
226   TDF_Label aChild;
227   if (!_lastCleared.IsNull()) {
228     if (_lastCleared.Root() == aDoc->Main().Root()) {
229       useExisting = true;
230       aChild = _lastCleared;
231       _lastCleared.Nullify();
232     }
233   }
234   if (!useExisting) {
235     // create new label
236     aChild = TDF_TagSource::NewChild(aDoc->Main());
237   }
238
239   Handle(GEOM_Object) anObject = new GEOM_Object(aChild, theType);
240
241   //Put an object in the map of created objects
242   TCollection_AsciiString anID = BuildIDFromObject(anObject);
243   if(_objects.IsBound(anID)) _objects.UnBind(anID);
244   _objects.Bind(anID, anObject);
245
246   return anObject;
247 }
248
249 //=============================================================================
250 /*!
251  *  AddSubShape
252  */
253 //=============================================================================
254 Handle(GEOM_Object) GEOM_Engine::AddSubShape(Handle(GEOM_Object) theMainShape, 
255                                              Handle(TColStd_HArray1OfInteger) theIndices,
256                                              bool isStandaloneOperation)
257 {
258   if(theMainShape.IsNull() || theIndices.IsNull()) return NULL;
259
260   Handle(TDocStd_Document) aDoc = GetDocument(theMainShape->GetDocID());
261   Handle(TDataStd_TreeNode) aRoot = TDataStd_TreeNode::Set(aDoc->Main());
262
263   // NPAL18604: use existing label to decrease memory usage,
264   //            if this label has been freed (object deleted)
265   bool useExisting = false;
266   TDF_Label aChild;
267   if (!_lastCleared.IsNull()) {
268     if (_lastCleared.Root() == aDoc->Main().Root()) {
269       useExisting = true;
270       aChild = _lastCleared;
271       _lastCleared.Nullify();
272     }
273   }
274   if (!useExisting) {
275     // create new label
276     aChild = TDF_TagSource::NewChild(aDoc->Main());
277   }
278
279   Handle(GEOM_Function) aMainShape = theMainShape->GetLastFunction();
280   Handle(GEOM_Object) anObject = new GEOM_Object(aChild, 28); //28 is SUBSHAPE type
281   Handle(GEOM_Function) aFunction = anObject->AddFunction(GEOM_Object::GetSubShapeID(), 1);
282
283   GEOM_ISubShape aSSI(aFunction);
284   aSSI.SetMainShape(aMainShape);
285   aSSI.SetIndices(theIndices);
286
287   try {
288 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
289     OCC_CATCH_SIGNALS;
290 #endif
291     GEOM_Solver aSolver (GEOM_Engine::GetEngine());
292     if (!aSolver.ComputeFunction(aFunction)) {
293       MESSAGE("GEOM_Engine::AddSubShape Error: Can't build a sub shape");
294       return NULL;
295     }
296   }
297   catch (Standard_Failure) {
298     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
299     MESSAGE("GEOM_Engine::AddSubShape Error: " << aFail->GetMessageString());
300     return NULL;
301   }
302
303   //Put an object in the map of created objects
304   TCollection_AsciiString anID = BuildIDFromObject(anObject);
305   if(_objects.IsBound(anID)) _objects.UnBind(anID);
306   _objects.Bind(anID, anObject);
307
308   GEOM::TPythonDump pd (aFunction);
309  
310   if (isStandaloneOperation) {
311     pd << anObject << " = geompy.GetSubShape(" << theMainShape << ", [";
312     Standard_Integer i = theIndices->Lower(), up = theIndices->Upper();
313     for (; i <= up - 1; i++) {
314       pd << theIndices->Value(i) << ", ";
315     }
316     pd << theIndices->Value(up) << "])";
317   }
318   else
319     pd << "None";
320
321   return anObject;
322 }
323
324 //=============================================================================
325 /*!
326  *  RemoveObject
327  */
328 //=============================================================================
329 bool GEOM_Engine::RemoveObject(Handle(GEOM_Object) theObject)
330 {
331   if (!theObject) return false;
332
333   //Remove an object from the map of available objects
334   TCollection_AsciiString anID = BuildIDFromObject(theObject);
335   if (_objects.IsBound(anID)) _objects.UnBind(anID);
336
337   int nb = theObject->GetNbFunctions();
338   Handle(TDataStd_TreeNode) aNode;
339   for (int i = 1; i<=nb; i++) {
340     Handle(GEOM_Function) aFunction = theObject->GetFunction(i);
341     if (aFunction->GetEntry().FindAttribute(GEOM_Function::GetFunctionTreeID(), aNode)) 
342       aNode->Remove();
343   }
344
345   TDF_Label aLabel = theObject->GetEntry();
346   aLabel.ForgetAllAttributes(Standard_True);
347   _lastCleared = aLabel;
348
349   theObject.Nullify();
350
351   return true;
352 }
353
354 //=============================================================================
355 /*!
356  *  Undo
357  */
358 //=============================================================================
359 void GEOM_Engine::Undo(int theDocID)
360 {
361   GetDocument(theDocID)->Undo();
362 }
363
364 //=============================================================================
365 /*!
366  *  Redo
367  */
368 //=============================================================================
369 void GEOM_Engine::Redo(int theDocID)
370 {
371   GetDocument(theDocID)->Redo();
372 }
373
374 //=============================================================================
375 /*!
376  *  Save
377  */
378 //=============================================================================
379 bool GEOM_Engine::Save(int theDocID, char* theFileName)
380 {
381   if(!_mapIDDocument.IsBound(theDocID)) return false;
382   Handle(TDocStd_Document) aDoc = Handle(TDocStd_Document)::DownCast(_mapIDDocument(theDocID));
383
384   _OCAFApp->SaveAs(aDoc, theFileName);
385
386   return true;
387 }
388
389 //=============================================================================
390 /*!
391  *  Load
392  */
393 //=============================================================================
394 bool GEOM_Engine::Load(int theDocID, char* theFileName)
395 {
396   Handle(TDocStd_Document) aDoc;
397   if(_OCAFApp->Open(theFileName, aDoc) != CDF_RS_OK) {
398     return false;
399   }
400
401   aDoc->SetUndoLimit(_UndoLimit);
402
403   if(_mapIDDocument.IsBound(theDocID)) _mapIDDocument.UnBind(theDocID);
404   _mapIDDocument.Bind(theDocID, aDoc);
405
406   TDataStd_Integer::Set(aDoc->Main(), theDocID);
407
408   return true;
409 }
410
411 //=============================================================================
412 /*!
413  *  Close
414  */
415 //=============================================================================
416 void GEOM_Engine::Close(int theDocID)
417 {
418   if (_mapIDDocument.IsBound(theDocID)) {
419     Handle(TDocStd_Document) aDoc = Handle(TDocStd_Document)::DownCast(_mapIDDocument(theDocID));
420
421     //Remove all GEOM Objects associated to the given document
422     TColStd_SequenceOfAsciiString aSeq;
423     GEOM_DataMapIteratorOfDataMapOfAsciiStringTransient It (_objects);
424     for (; It.More(); It.Next()) {
425       TCollection_AsciiString anObjID (It.Key());
426       Standard_Integer anID = ExtractDocID(anObjID);
427       if (theDocID == anID) aSeq.Append(It.Key());
428     }
429     for (Standard_Integer i=1; i<=aSeq.Length(); i++) _objects.UnBind(aSeq.Value(i));
430
431     _lastCleared.Nullify();
432
433     _mapIDDocument.UnBind(theDocID);
434     _OCAFApp->Close(aDoc);
435     aDoc.Nullify();
436   }
437 }
438
439 //=============================================================================
440 /*!
441  *  DumpPython
442  */
443 //=============================================================================
444 TCollection_AsciiString GEOM_Engine::DumpPython(int theDocID,
445                                                 Resource_DataMapOfAsciiStringAsciiString& theObjectNames,
446                                                 TVariablesList theVariables,
447                                                 bool isPublished,
448                                                 bool& aValidScript)
449 {
450   TCollection_AsciiString aScript;
451   Handle(TDocStd_Document) aDoc = GetDocument(theDocID);
452
453   if (aDoc.IsNull()) return TCollection_AsciiString("def RebuildData(theStudy): pass\n");
454
455   aScript = "import geompy\n";
456   aScript += "import math\n";
457   aScript += "import SALOMEDS\n\n";
458   aScript += "def RebuildData(theStudy):";
459   aScript += "\n\tgeompy.init_geom(theStudy)";
460
461   Standard_Integer posToInertGlobalVars = aScript.Length() + 1;
462
463   Handle(TDataStd_TreeNode) aNode, aRoot;
464   Handle(GEOM_Function) aFunction;
465   TColStd_MapOfTransient aMap;
466
467   if (aDoc->Main().FindAttribute(GEOM_Function::GetFunctionTreeID(), aRoot)) {
468     TDataStd_ChildNodeIterator Itr(aRoot);
469     for (; Itr.More(); Itr.Next()) {
470       aNode = Itr.Value();
471       aFunction = GEOM_Function::GetFunction(aNode->Label());
472       if (aFunction.IsNull()) {
473         MESSAGE ( "Null function !!!!" );
474         continue;
475       }
476       ProcessFunction(aFunction, aScript, theVariables,aMap);
477     }
478   }
479
480   Resource_DataMapOfAsciiStringAsciiString aEntry2StEntry, aStEntry2Entry;
481   Resource_DataMapIteratorOfDataMapOfAsciiStringAsciiString anEntryToNameIt;
482   // build maps entry <-> studyEntry
483   for (anEntryToNameIt.Initialize( theObjectNames );
484        anEntryToNameIt.More();
485        anEntryToNameIt.Next())
486   {
487     const TCollection_AsciiString& aEntry = anEntryToNameIt.Key();
488     // look for an object by entry
489     TDF_Label L;
490     TDF_Tool::Label( aDoc->GetData(), aEntry, L );
491     if ( L.IsNull() ) continue;
492     Handle(GEOM_Object) obj = GEOM_Object::GetObject( L );
493     // fill maps
494     if ( !obj.IsNull() ) {
495       TCollection_AsciiString aStudyEntry (obj->GetAuxData());
496       aEntry2StEntry.Bind( aEntry,  aStudyEntry);
497       aStEntry2Entry.Bind( aStudyEntry, aEntry );
498     }
499   }
500
501   Handle(TColStd_HSequenceOfInteger) aSeq = FindEntries(aScript);
502   Standard_Integer aLen = aSeq->Length(), objectCounter = 0, aStart = 1, aScriptLength = aScript.Length();
503   Resource_DataMapOfAsciiStringAsciiString aNameToEntry, anEntryToBadName;
504
505   //Replace entries by the names
506   TCollection_AsciiString anUpdatedScript, anEntry, aName, aBaseName("geomObj_"),
507     allowedChars ("qwertyuioplkjhgfdsazxcvbnmQWERTYUIOPLKJHGFDSAZXCVBNM0987654321_");
508   if (aLen == 0) anUpdatedScript = aScript;
509
510   for (Standard_Integer i = 1; i <= aLen; i+=2) {
511     anUpdatedScript += aScript.SubString(aStart, aSeq->Value(i)-1);
512     anEntry = aScript.SubString(aSeq->Value(i), aSeq->Value(i+1));
513     if (theObjectNames.IsBound(anEntry)) {
514       aName = theObjectNames.Find(anEntry);
515       // check validity of aName
516       bool isValidName = true;
517       if ( aName.IsIntegerValue() ) { // aName must not start with a digit
518         aName.Insert( 1, 'a' );
519         isValidName = false;
520       }
521       int p, p2=1; // replace not allowed chars
522       while ((p = aName.FirstLocationNotInSet(allowedChars, p2, aName.Length()))) {
523         aName.SetValue(p, '_');
524         p2=p;
525         isValidName = false;
526       }
527       if ( aNameToEntry.IsBound( aName ) && anEntry != aNameToEntry( aName ))
528       {  // diff objects have same name - make a new name by appending a digit
529         TCollection_AsciiString aName2;
530         Standard_Integer i = 0;
531         do {
532           aName2 = aName + "_" + ++i;
533         } while ( aNameToEntry.IsBound( aName2 ) && anEntry != aNameToEntry( aName2 ));
534         aName = aName2;
535         isValidName = false;
536       }
537       if ( !isValidName ) {
538         if ( isPublished )
539           anEntryToBadName.Bind( anEntry, theObjectNames.Find(anEntry) );
540         theObjectNames( anEntry ) = aName;
541       }
542     }
543     else {
544       do {
545         aName = aBaseName + TCollection_AsciiString(++objectCounter);
546       } while(aNameToEntry.IsBound(aName));
547       theObjectNames.Bind(anEntry, aName);
548     }
549     aNameToEntry.Bind(aName, anEntry); // to detect same name of diff objects
550
551     anUpdatedScript += aName;
552     aStart = aSeq->Value(i+1) + 1;
553   }
554
555   //Add final part of the script
556   if (aLen && aSeq->Value(aLen) < aScriptLength)
557     anUpdatedScript += aScript.SubString(aSeq->Value(aLen)+1, aScriptLength); // mkr : IPAL11865
558
559   // ouv : NPAL12872
560   for (anEntryToNameIt.Initialize( theObjectNames );
561        anEntryToNameIt.More();
562        anEntryToNameIt.Next())
563   {
564     const TCollection_AsciiString& aEntry = anEntryToNameIt.Key();
565     const TCollection_AsciiString& aName = anEntryToNameIt.Value();
566
567     TDF_Label L;
568     TDF_Tool::Label( aDoc->GetData(), aEntry, L );
569     if ( L.IsNull() )
570       continue;
571
572     Handle(GEOM_Object) obj = GEOM_Object::GetObject( L );
573     if ( obj.IsNull() )
574       continue;
575
576     bool anAutoColor = obj->GetAutoColor();
577     if ( anAutoColor )
578     {
579       TCollection_AsciiString aCommand( "\n\t" );
580       aCommand += aName + ".SetAutoColor(1)";
581       anUpdatedScript += aCommand.ToCString();
582     }
583
584     SALOMEDS::Color aColor = obj->GetColor();
585     if ( aColor.R > 0 || aColor.G > 0 || aColor.B > 0 )
586     {
587       TCollection_AsciiString aCommand( "\n\t" );
588       aCommand += aName + ".SetColor(SALOMEDS.Color(" + aColor.R + "," + aColor.G + "," + aColor.B + "))";
589       anUpdatedScript += aCommand.ToCString();
590     }
591   }
592
593   // Make script to publish in study
594   if ( isPublished )
595   {
596     std::map< int, std::string > anEntryToCommandMap; // sort publishing commands by object entry
597     for (anEntryToNameIt.Initialize( theObjectNames );
598          anEntryToNameIt.More();
599          anEntryToNameIt.Next())
600     {
601       const TCollection_AsciiString& aEntry = anEntryToNameIt.Key();
602       const TCollection_AsciiString& aName = anEntryToNameIt.Value();
603       if ( !aEntry2StEntry.IsBound( aEntry ))
604         continue; // was not published
605       TCollection_AsciiString aCommand("\n\tgeompy."), aFatherEntry;
606
607       // find a father entry
608       const TCollection_AsciiString& aStudyEntry = aEntry2StEntry( aEntry );
609       TCollection_AsciiString aFatherStudyEntry =
610         aStudyEntry.SubString( 1, aStudyEntry.SearchFromEnd(":") - 1 );
611       if ( aStEntry2Entry.IsBound( aFatherStudyEntry ))
612         aFatherEntry = aStEntry2Entry( aFatherStudyEntry );
613
614       // make a command
615       if ( !aFatherEntry.IsEmpty() && theObjectNames.IsBound( aFatherEntry )) {
616         aCommand += "addToStudyInFather( ";
617         aCommand += theObjectNames( aFatherEntry ) + ", ";
618       }
619       else
620         aCommand += "addToStudy( ";
621       if ( anEntryToBadName.IsBound( aEntry ))
622         aCommand += aName + ", \"" + anEntryToBadName( aEntry ) + "\" )";
623       else 
624         aCommand += aName + ", \"" + aName + "\" )";
625
626       // bind a command to the last digit of the entry
627       int tag =
628         aEntry.SubString( aEntry.SearchFromEnd(":")+1, aEntry.Length() ).IntegerValue();
629       anEntryToCommandMap.insert( std::make_pair( tag, aCommand.ToCString() ));
630     }
631
632     // add publishing commands to the script
633     std::map< int, std::string >::iterator anEntryToCommand = anEntryToCommandMap.begin();
634     for ( ; anEntryToCommand != anEntryToCommandMap.end(); ++anEntryToCommand ) {
635       anUpdatedScript += (char*)anEntryToCommand->second.c_str();
636     }
637   }
638
639   //anUpdatedScript += "\n\tpass\n";
640   anUpdatedScript += "\n";
641   aValidScript = true;
642
643   // fill _studyEntry2NameMap and build globalVars
644   TCollection_AsciiString globalVars;
645   _studyEntry2NameMap.Clear();
646   Resource_DataMapIteratorOfDataMapOfAsciiStringAsciiString aStEntryToEntryIt;
647   for (aStEntryToEntryIt.Initialize( aStEntry2Entry );
648        aStEntryToEntryIt.More();
649        aStEntryToEntryIt.Next() )
650   {
651     const TCollection_AsciiString & name = theObjectNames( aStEntryToEntryIt.Value() );
652     _studyEntry2NameMap.Bind (aStEntryToEntryIt.Key(), name );
653     if ( !globalVars.IsEmpty() )
654       globalVars += ", ";
655     globalVars += name;
656   }
657   if ( !globalVars.IsEmpty() ) {
658     globalVars.Insert( 1, "\n\tglobal " );
659     anUpdatedScript.Insert( posToInertGlobalVars, globalVars );
660   }
661
662   return anUpdatedScript;
663 }
664
665 //=======================================================================
666 //function : GetDumpName
667 //purpose  : 
668 //=======================================================================
669
670 const char* GEOM_Engine::GetDumpName (const char* theStudyEntry) const
671 {
672   if ( _studyEntry2NameMap.IsBound( (char*)theStudyEntry ))
673     return _studyEntry2NameMap( (char*)theStudyEntry ).ToCString();
674
675   return NULL;
676 }
677
678 //=======================================================================
679 //function : GetAllDumpNames
680 //purpose  : 
681 //=======================================================================
682
683 Handle(TColStd_HSequenceOfAsciiString) GEOM_Engine::GetAllDumpNames() const
684 {
685   Handle(TColStd_HSequenceOfAsciiString) aRetSeq = new TColStd_HSequenceOfAsciiString;
686
687   Resource_DataMapIteratorOfDataMapOfAsciiStringAsciiString it (_studyEntry2NameMap);
688   for (; it.More(); it.Next()) {
689     aRetSeq->Append(it.Value());
690   }
691
692   return aRetSeq;
693 }
694
695
696 //===========================================================================
697 //                     Internal functions
698 //===========================================================================
699 void ProcessFunction(Handle(GEOM_Function)& theFunction, 
700                      TCollection_AsciiString& theScript,
701                      TVariablesList theVariables,
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,theVariables);
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                       TVariablesList theVariables)
780 {
781   //Get Entry of the result object
782   TCollection_AsciiString anEntry = theCommand.Token("=",1);
783
784   if (MYDEBUG) {
785     cout<<"All Entries:"<<endl;
786     TVariablesList::const_iterator it = theVariables.begin();
787     for(;it != theVariables.end();it++)
788       cout<<"\t'"<<(*it).first<<"'"<<endl;
789   }
790   
791   //Remove white spaces
792   anEntry.RightAdjust();
793   anEntry.LeftAdjust();
794   if(MYDEBUG)
795     cout<<"Result entry : '" <<anEntry<<"'"<<endl;
796     
797   //Find variables used for object construction
798   vector<TVariable> aVariables;
799   TVariablesList::const_iterator it = theVariables.find(anEntry);
800   if( it != theVariables.end() ) 
801     aVariables = (*it).second;
802
803   if(aVariables.empty()) {
804     if(MYDEBUG)
805       cout<<"Valiables list empty!!!"<<endl;
806     return;
807   }
808   
809   if(MYDEBUG) {
810     cout<<"Variables from SObject:"<<endl;
811     for (int i = 0; i < aVariables.size();i++)
812       cout<<"\t Variable["<<i<<"]"<<aVariables[i].myVariable<<endl;
813   }
814
815   //Calculate total number of parameter
816   Standard_Integer aTotalNbParams = 1;
817   while(theCommand.Location(aTotalNbParams,COMMA,1,theCommand.Length()))
818     aTotalNbParams++;
819   
820   //Replace parameters by variables
821   Standard_Integer aStartPos = 0;
822   Standard_Integer aEndPos = 0;
823   int iVar = 0;
824   TCollection_AsciiString aReplasedVar, aVar;
825   for(Standard_Integer i=1;i <= aTotalNbParams;i++) {
826         
827     //Replace first parameter (bettwen '(' character and first ',' character)
828     if(i == 1)
829       {
830         aStartPos = theCommand.Location(O_BRACKET, 1, theCommand.Length()) + 1;
831         aEndPos = theCommand.Location(COMMA, 1, theCommand.Length());
832       }
833     //Replace last parameter (bettwen ',' character and ')' character)
834     else if(i == aTotalNbParams)
835       {
836         aStartPos = theCommand.Location(i-1, COMMA, 1, theCommand.Length()) + 2;
837         aEndPos = theCommand.Location(C_BRACKET, 1, theCommand.Length());
838       }
839     //Replace other parameters (bettwen two ',' characters)
840     else if(i != 1 && i != aTotalNbParams )
841       {
842         aStartPos = theCommand.Location(i-1, COMMA, 1, theCommand.Length()) + 2;
843         aEndPos = theCommand.Location(i, COMMA, 1, theCommand.Length());
844       }
845     aVar = theCommand.SubString(aStartPos, aEndPos-1);
846     if(MYDEBUG) 
847       cout<<"Current variable 1: '"<< aVar <<"'"<<endl;
848
849     aVar.RightAdjust();
850     aVar.LeftAdjust();
851     
852     if(MYDEBUG) 
853       cout<<"Current variable 2: '"<< aVar <<"'"<<endl;
854     
855     //If parameter is entry or 'None', skip it
856     if(theVariables.find(aVar) != theVariables.end() || aVar == PY_NULL)
857       continue;
858     
859     aReplasedVar = aVariables[iVar].myVariable;
860     
861     
862     if(aReplasedVar.IsEmpty()) {
863       iVar++;
864       continue;
865     }
866
867     if(aVariables[iVar].isVariable) {
868       aReplasedVar.InsertBefore(1,"\"");
869       aReplasedVar.InsertAfter(aReplasedVar.Length(),"\"");
870     }
871
872     theCommand.Remove(aStartPos, aEndPos - aStartPos);
873     theCommand.Insert(aStartPos,aReplasedVar);
874     iVar++;
875   }
876 }