1 // Copyright (C) 2005 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
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.
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.
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
18 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 #pragma warning( disable:4786 )
24 #include "GEOM_Engine.hxx"
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"
33 #include "utilities.h"
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>
44 #include <TopTools_IndexedMapOfShape.hxx>
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>
53 #include <Interface_DataMapIteratorOfDataMapOfIntegerTransient.hxx>
54 #include <Resource_DataMapIteratorOfDataMapOfAsciiStringAsciiString.hxx>
60 #include <Standard_Failure.hxx>
61 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
66 #define O_SQR_BRACKET '['
67 #define C_SQR_BRACKET ']'
68 #define PY_NULL "None"
71 static int MYDEBUG = 0;
73 static int MYDEBUG = 0;
76 static GEOM_Engine* TheEngine = NULL;
80 static TCollection_AsciiString BuildIDFromObject(Handle(GEOM_Object)& theObject)
82 TCollection_AsciiString anID(theObject->GetDocID()), anEntry;
83 TDF_Tool::Entry(theObject->GetEntry(), anEntry);
84 anID+=(TCollection_AsciiString("_")+anEntry);
88 static TCollection_AsciiString BuildID(Standard_Integer theDocID, char* theEntry)
90 TCollection_AsciiString anID(theDocID);
91 anID+=(TCollection_AsciiString("_")+theEntry);
95 static Standard_Integer ExtractDocID(TCollection_AsciiString& theID)
97 TCollection_AsciiString aDocID = theID.Token("_");
98 if(aDocID.Length() < 1) return -1;
99 return aDocID.IntegerValue();
102 void ProcessFunction(Handle(GEOM_Function)& theFunction,
103 TCollection_AsciiString& theScript,
104 TVariablesList theVariables,
105 TColStd_MapOfTransient& theProcessed);
107 void ReplaceVariables(TCollection_AsciiString& theCommand,
108 TVariablesList theVariables);
112 Handle(TColStd_HSequenceOfInteger) FindEntries(TCollection_AsciiString& theString);
115 //=============================================================================
119 //=============================================================================
120 GEOM_Engine* GEOM_Engine::GetEngine() { return TheEngine; }
123 //=============================================================================
127 //=============================================================================
128 void GEOM_Engine::SetEngine(GEOM_Engine* theEngine) { TheEngine = theEngine; }
130 //=============================================================================
134 //=============================================================================
135 GEOM_Engine::GEOM_Engine()
137 TFunction_DriverTable::Get()->AddDriver(GEOM_Object::GetSubShapeID(), new GEOM_SubShapeDriver());
139 _OCAFApp = new GEOM_Application();
146 GEOM_Engine::~GEOM_Engine()
148 GEOM_DataMapIteratorOfDataMapOfAsciiStringTransient It(_objects);
149 for(; It.More(); It.Next())
151 RemoveObject(Handle(GEOM_Object)::DownCast(It.Value()));
154 //Close all documents not closed
155 for(Interface_DataMapIteratorOfDataMapOfIntegerTransient anItr(_mapIDDocument); anItr.More(); anItr.Next())
158 _mapIDDocument.Clear();
162 //=============================================================================
166 //=============================================================================
167 Handle(TDocStd_Document) GEOM_Engine::GetDocument(int theDocID)
169 Handle(TDocStd_Document) aDoc;
170 if(!_mapIDDocument.IsBound(theDocID)) {
171 _OCAFApp->NewDocument("SALOME_GEOM", aDoc);
172 aDoc->SetUndoLimit(_UndoLimit);
173 _mapIDDocument.Bind(theDocID, aDoc);
174 TDataStd_Integer::Set(aDoc->Main(), theDocID);
177 return Handle(TDocStd_Document)::DownCast(_mapIDDocument(theDocID));
180 //=============================================================================
184 //=============================================================================
185 int GEOM_Engine::GetDocID(Handle(TDocStd_Document) theDocument)
187 if(theDocument.IsNull()) return -1;
188 for(Interface_DataMapIteratorOfDataMapOfIntegerTransient anItr(_mapIDDocument); anItr.More(); anItr.Next())
189 if(anItr.Value() == theDocument) return anItr.Key();
195 //=============================================================================
199 //=============================================================================
200 Handle(GEOM_Object) GEOM_Engine::GetObject(int theDocID, char* theEntry)
202 TCollection_AsciiString anID = BuildID(theDocID, theEntry);
203 if(_objects.IsBound(anID)) return Handle(GEOM_Object)::DownCast(_objects(anID));
206 Handle(TDocStd_Document) aDoc = GetDocument(theDocID);
207 TDF_Tool::Label(aDoc->Main().Data(), theEntry, aLabel, Standard_True);
208 Handle(GEOM_Object) anObject = new GEOM_Object(aLabel);
210 _objects.Bind(anID, anObject);
215 //=============================================================================
219 //=============================================================================
220 Handle(GEOM_Object) GEOM_Engine::AddObject(int theDocID, int theType)
222 Handle(TDocStd_Document) aDoc = GetDocument(theDocID);
223 Handle(TDataStd_TreeNode) aRoot = TDataStd_TreeNode::Set(aDoc->Main());
225 // NPAL18604: use existing label to decrease memory usage,
226 // if this label has been freed (object deleted)
227 bool useExisting = false;
229 if (!_lastCleared.IsNull()) {
230 if (_lastCleared.Root() == aDoc->Main().Root()) {
232 aChild = _lastCleared;
233 _lastCleared.Nullify();
238 aChild = TDF_TagSource::NewChild(aDoc->Main());
241 Handle(GEOM_Object) anObject = new GEOM_Object(aChild, theType);
243 //Put an object in the map of created objects
244 TCollection_AsciiString anID = BuildIDFromObject(anObject);
245 if(_objects.IsBound(anID)) _objects.UnBind(anID);
246 _objects.Bind(anID, anObject);
251 //=============================================================================
255 //=============================================================================
256 Handle(GEOM_Object) GEOM_Engine::AddSubShape(Handle(GEOM_Object) theMainShape,
257 Handle(TColStd_HArray1OfInteger) theIndices,
258 bool isStandaloneOperation)
260 if(theMainShape.IsNull() || theIndices.IsNull()) return NULL;
262 Handle(TDocStd_Document) aDoc = GetDocument(theMainShape->GetDocID());
263 Handle(TDataStd_TreeNode) aRoot = TDataStd_TreeNode::Set(aDoc->Main());
265 // NPAL18604: use existing label to decrease memory usage,
266 // if this label has been freed (object deleted)
267 bool useExisting = false;
269 if (!_lastCleared.IsNull()) {
270 if (_lastCleared.Root() == aDoc->Main().Root()) {
272 aChild = _lastCleared;
273 _lastCleared.Nullify();
278 aChild = TDF_TagSource::NewChild(aDoc->Main());
281 Handle(GEOM_Function) aMainShape = theMainShape->GetLastFunction();
282 Handle(GEOM_Object) anObject = new GEOM_Object(aChild, 28); //28 is SUBSHAPE type
283 Handle(GEOM_Function) aFunction = anObject->AddFunction(GEOM_Object::GetSubShapeID(), 1);
285 GEOM_ISubShape aSSI(aFunction);
286 aSSI.SetMainShape(aMainShape);
287 aSSI.SetIndices(theIndices);
290 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
293 GEOM_Solver aSolver (GEOM_Engine::GetEngine());
294 if (!aSolver.ComputeFunction(aFunction)) {
295 MESSAGE("GEOM_Engine::AddSubShape Error: Can't build a sub shape");
299 catch (Standard_Failure) {
300 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
301 MESSAGE("GEOM_Engine::AddSubShape Error: " << aFail->GetMessageString());
305 //Put an object in the map of created objects
306 TCollection_AsciiString anID = BuildIDFromObject(anObject);
307 if(_objects.IsBound(anID)) _objects.UnBind(anID);
308 _objects.Bind(anID, anObject);
310 GEOM::TPythonDump pd (aFunction);
312 if (isStandaloneOperation) {
313 pd << anObject << " = geompy.GetSubShape(" << theMainShape << ", [";
314 Standard_Integer i = theIndices->Lower(), up = theIndices->Upper();
315 for (; i <= up - 1; i++) {
316 pd << theIndices->Value(i) << ", ";
318 pd << theIndices->Value(up) << "])";
326 //=============================================================================
330 //=============================================================================
331 bool GEOM_Engine::RemoveObject(Handle(GEOM_Object) theObject)
333 if (!theObject) return false;
335 //Remove an object from the map of available objects
336 TCollection_AsciiString anID = BuildIDFromObject(theObject);
337 if (_objects.IsBound(anID)) _objects.UnBind(anID);
339 int nb = theObject->GetNbFunctions();
340 Handle(TDataStd_TreeNode) aNode;
341 for (int i = 1; i<=nb; i++) {
342 Handle(GEOM_Function) aFunction = theObject->GetFunction(i);
343 if (aFunction->GetEntry().FindAttribute(GEOM_Function::GetFunctionTreeID(), aNode))
347 TDF_Label aLabel = theObject->GetEntry();
348 aLabel.ForgetAllAttributes(Standard_True);
349 _lastCleared = aLabel;
356 //=============================================================================
360 //=============================================================================
361 void GEOM_Engine::Undo(int theDocID)
363 GetDocument(theDocID)->Undo();
366 //=============================================================================
370 //=============================================================================
371 void GEOM_Engine::Redo(int theDocID)
373 GetDocument(theDocID)->Redo();
376 //=============================================================================
380 //=============================================================================
381 bool GEOM_Engine::Save(int theDocID, char* theFileName)
383 if(!_mapIDDocument.IsBound(theDocID)) return false;
384 Handle(TDocStd_Document) aDoc = Handle(TDocStd_Document)::DownCast(_mapIDDocument(theDocID));
386 _OCAFApp->SaveAs(aDoc, theFileName);
391 //=============================================================================
395 //=============================================================================
396 bool GEOM_Engine::Load(int theDocID, char* theFileName)
398 Handle(TDocStd_Document) aDoc;
399 if(_OCAFApp->Open(theFileName, aDoc) != CDF_RS_OK) {
403 aDoc->SetUndoLimit(_UndoLimit);
405 if(_mapIDDocument.IsBound(theDocID)) _mapIDDocument.UnBind(theDocID);
406 _mapIDDocument.Bind(theDocID, aDoc);
408 TDataStd_Integer::Set(aDoc->Main(), theDocID);
413 //=============================================================================
417 //=============================================================================
418 void GEOM_Engine::Close(int theDocID)
420 if (_mapIDDocument.IsBound(theDocID)) {
421 Handle(TDocStd_Document) aDoc = Handle(TDocStd_Document)::DownCast(_mapIDDocument(theDocID));
423 //Remove all GEOM Objects associated to the given document
424 TColStd_SequenceOfAsciiString aSeq;
425 GEOM_DataMapIteratorOfDataMapOfAsciiStringTransient It (_objects);
426 for (; It.More(); It.Next()) {
427 TCollection_AsciiString anObjID (It.Key());
428 Standard_Integer anID = ExtractDocID(anObjID);
429 if (theDocID == anID) aSeq.Append(It.Key());
431 for (Standard_Integer i=1; i<=aSeq.Length(); i++) _objects.UnBind(aSeq.Value(i));
433 _lastCleared.Nullify();
435 _mapIDDocument.UnBind(theDocID);
436 _OCAFApp->Close(aDoc);
441 //=============================================================================
445 //=============================================================================
446 TCollection_AsciiString GEOM_Engine::DumpPython(int theDocID,
447 Resource_DataMapOfAsciiStringAsciiString& theObjectNames,
448 TVariablesList theVariables,
452 TCollection_AsciiString aScript;
453 Handle(TDocStd_Document) aDoc = GetDocument(theDocID);
455 if (aDoc.IsNull()) return TCollection_AsciiString("def RebuildData(theStudy): pass\n");
457 aScript = "import geompy\n";
458 aScript += "import math\n";
459 aScript += "import SALOMEDS\n\n";
460 aScript += "def RebuildData(theStudy):";
461 aScript += "\n\tgeompy.init_geom(theStudy)";
463 Standard_Integer posToInertGlobalVars = aScript.Length() + 1;
465 Handle(TDataStd_TreeNode) aNode, aRoot;
466 Handle(GEOM_Function) aFunction;
467 TColStd_MapOfTransient aMap;
469 if (aDoc->Main().FindAttribute(GEOM_Function::GetFunctionTreeID(), aRoot)) {
470 TDataStd_ChildNodeIterator Itr(aRoot);
471 for (; Itr.More(); Itr.Next()) {
473 aFunction = GEOM_Function::GetFunction(aNode->Label());
474 if (aFunction.IsNull()) {
475 MESSAGE ( "Null function !!!!" );
478 ProcessFunction(aFunction, aScript, theVariables,aMap);
482 Resource_DataMapOfAsciiStringAsciiString aEntry2StEntry, aStEntry2Entry;
483 Resource_DataMapIteratorOfDataMapOfAsciiStringAsciiString anEntryToNameIt;
484 // build maps entry <-> studyEntry
485 for (anEntryToNameIt.Initialize( theObjectNames );
486 anEntryToNameIt.More();
487 anEntryToNameIt.Next())
489 const TCollection_AsciiString& aEntry = anEntryToNameIt.Key();
490 // look for an object by entry
492 TDF_Tool::Label( aDoc->GetData(), aEntry, L );
493 if ( L.IsNull() ) continue;
494 Handle(GEOM_Object) obj = GEOM_Object::GetObject( L );
496 if ( !obj.IsNull() ) {
497 TCollection_AsciiString aStudyEntry (obj->GetAuxData());
498 aEntry2StEntry.Bind( aEntry, aStudyEntry);
499 aStEntry2Entry.Bind( aStudyEntry, aEntry );
503 Handle(TColStd_HSequenceOfInteger) aSeq = FindEntries(aScript);
504 Standard_Integer aLen = aSeq->Length(), objectCounter = 0, aStart = 1, aScriptLength = aScript.Length();
505 Resource_DataMapOfAsciiStringAsciiString aNameToEntry, anEntryToBadName;
507 //Replace entries by the names
508 TCollection_AsciiString anUpdatedScript, anEntry, aName, aBaseName("geomObj_"),
509 allowedChars ("qwertyuioplkjhgfdsazxcvbnmQWERTYUIOPLKJHGFDSAZXCVBNM0987654321_");
510 if (aLen == 0) anUpdatedScript = aScript;
512 for (Standard_Integer i = 1; i <= aLen; i+=2) {
513 anUpdatedScript += aScript.SubString(aStart, aSeq->Value(i)-1);
514 anEntry = aScript.SubString(aSeq->Value(i), aSeq->Value(i+1));
515 if (theObjectNames.IsBound(anEntry)) {
516 aName = theObjectNames.Find(anEntry);
517 // check validity of aName
518 bool isValidName = true;
519 if ( aName.IsIntegerValue() ) { // aName must not start with a digit
520 aName.Insert( 1, 'a' );
523 int p, p2=1; // replace not allowed chars
524 while ((p = aName.FirstLocationNotInSet(allowedChars, p2, aName.Length()))) {
525 aName.SetValue(p, '_');
529 if ( aNameToEntry.IsBound( aName ) && anEntry != aNameToEntry( aName ))
530 { // diff objects have same name - make a new name by appending a digit
531 TCollection_AsciiString aName2;
532 Standard_Integer i = 0;
534 aName2 = aName + "_" + ++i;
535 } while ( aNameToEntry.IsBound( aName2 ) && anEntry != aNameToEntry( aName2 ));
539 if ( !isValidName ) {
541 anEntryToBadName.Bind( anEntry, theObjectNames.Find(anEntry) );
542 theObjectNames( anEntry ) = aName;
547 aName = aBaseName + TCollection_AsciiString(++objectCounter);
548 } while(aNameToEntry.IsBound(aName));
549 theObjectNames.Bind(anEntry, aName);
551 aNameToEntry.Bind(aName, anEntry); // to detect same name of diff objects
553 anUpdatedScript += aName;
554 aStart = aSeq->Value(i+1) + 1;
557 //Add final part of the script
558 if (aLen && aSeq->Value(aLen) < aScriptLength)
559 anUpdatedScript += aScript.SubString(aSeq->Value(aLen)+1, aScriptLength); // mkr : IPAL11865
562 for (anEntryToNameIt.Initialize( theObjectNames );
563 anEntryToNameIt.More();
564 anEntryToNameIt.Next())
566 const TCollection_AsciiString& aEntry = anEntryToNameIt.Key();
567 const TCollection_AsciiString& aName = anEntryToNameIt.Value();
570 TDF_Tool::Label( aDoc->GetData(), aEntry, L );
574 Handle(GEOM_Object) obj = GEOM_Object::GetObject( L );
578 bool anAutoColor = obj->GetAutoColor();
581 TCollection_AsciiString aCommand( "\n\t" );
582 aCommand += aName + ".SetAutoColor(1)";
583 anUpdatedScript += aCommand.ToCString();
586 SALOMEDS::Color aColor = obj->GetColor();
587 if ( aColor.R > 0 || aColor.G > 0 || aColor.B > 0 )
589 TCollection_AsciiString aCommand( "\n\t" );
590 aCommand += aName + ".SetColor(SALOMEDS.Color(" + aColor.R + "," + aColor.G + "," + aColor.B + "))";
591 anUpdatedScript += aCommand.ToCString();
595 // Make script to publish in study
598 std::map< int, std::string > anEntryToCommandMap; // sort publishing commands by object entry
599 for (anEntryToNameIt.Initialize( theObjectNames );
600 anEntryToNameIt.More();
601 anEntryToNameIt.Next())
603 const TCollection_AsciiString& aEntry = anEntryToNameIt.Key();
604 const TCollection_AsciiString& aName = anEntryToNameIt.Value();
605 if ( !aEntry2StEntry.IsBound( aEntry ))
606 continue; // was not published
607 TCollection_AsciiString aCommand("\n\tgeompy."), aFatherEntry;
609 // find a father entry
610 const TCollection_AsciiString& aStudyEntry = aEntry2StEntry( aEntry );
611 TCollection_AsciiString aFatherStudyEntry =
612 aStudyEntry.SubString( 1, aStudyEntry.SearchFromEnd(":") - 1 );
613 if ( aStEntry2Entry.IsBound( aFatherStudyEntry ))
614 aFatherEntry = aStEntry2Entry( aFatherStudyEntry );
617 if ( !aFatherEntry.IsEmpty() && theObjectNames.IsBound( aFatherEntry )) {
618 aCommand += "addToStudyInFather( ";
619 aCommand += theObjectNames( aFatherEntry ) + ", ";
622 aCommand += "addToStudy( ";
623 if ( anEntryToBadName.IsBound( aEntry ))
624 aCommand += aName + ", \"" + anEntryToBadName( aEntry ) + "\" )";
626 aCommand += aName + ", \"" + aName + "\" )";
628 // bind a command to the last digit of the entry
630 aEntry.SubString( aEntry.SearchFromEnd(":")+1, aEntry.Length() ).IntegerValue();
631 anEntryToCommandMap.insert( std::make_pair( tag, aCommand.ToCString() ));
634 // add publishing commands to the script
635 std::map< int, std::string >::iterator anEntryToCommand = anEntryToCommandMap.begin();
636 for ( ; anEntryToCommand != anEntryToCommandMap.end(); ++anEntryToCommand ) {
637 anUpdatedScript += (char*)anEntryToCommand->second.c_str();
641 //anUpdatedScript += "\n\tpass\n";
642 anUpdatedScript += "\n";
645 // fill _studyEntry2NameMap and build globalVars
646 TCollection_AsciiString globalVars;
647 _studyEntry2NameMap.Clear();
648 Resource_DataMapIteratorOfDataMapOfAsciiStringAsciiString aStEntryToEntryIt;
649 for (aStEntryToEntryIt.Initialize( aStEntry2Entry );
650 aStEntryToEntryIt.More();
651 aStEntryToEntryIt.Next() )
653 const TCollection_AsciiString & name = theObjectNames( aStEntryToEntryIt.Value() );
654 _studyEntry2NameMap.Bind (aStEntryToEntryIt.Key(), name );
655 if ( !globalVars.IsEmpty() )
659 if ( !globalVars.IsEmpty() ) {
660 globalVars.Insert( 1, "\n\tglobal " );
661 anUpdatedScript.Insert( posToInertGlobalVars, globalVars );
664 return anUpdatedScript;
667 //=======================================================================
668 //function : GetDumpName
670 //=======================================================================
672 const char* GEOM_Engine::GetDumpName (const char* theStudyEntry) const
674 if ( _studyEntry2NameMap.IsBound( (char*)theStudyEntry ))
675 return _studyEntry2NameMap( (char*)theStudyEntry ).ToCString();
680 //=======================================================================
681 //function : GetAllDumpNames
683 //=======================================================================
685 Handle(TColStd_HSequenceOfAsciiString) GEOM_Engine::GetAllDumpNames() const
687 Handle(TColStd_HSequenceOfAsciiString) aRetSeq = new TColStd_HSequenceOfAsciiString;
689 Resource_DataMapIteratorOfDataMapOfAsciiStringAsciiString it (_studyEntry2NameMap);
690 for (; it.More(); it.Next()) {
691 aRetSeq->Append(it.Value());
698 //===========================================================================
699 // Internal functions
700 //===========================================================================
701 void ProcessFunction(Handle(GEOM_Function)& theFunction,
702 TCollection_AsciiString& theScript,
703 TVariablesList theVariables,
704 TColStd_MapOfTransient& theProcessed)
706 if(theFunction.IsNull() || theProcessed.Contains(theFunction)) return;
709 TDF_LabelSequence aSeq;
710 theFunction->GetDependency(aSeq);
711 Standard_Integer aLen = aSeq.Length();
712 for(Standard_Integer i = 1; i<= aLen; i++) {
713 Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(aSeq.Value(i));
714 if(aFunction.IsNull()) continue;
715 ProcessFunction(aFunction, theScript, theProcessed);
719 TCollection_AsciiString aDescr = theFunction->GetDescription();
720 if(aDescr.Length() == 0) {
721 //cout << "Warning: the function has no description" << endl;
724 //Check if its internal function which doesn't requires dumping
725 if(aDescr == "None") return;
727 //Replace parameter by notebook variables
728 ReplaceVariables(aDescr,theVariables);
733 theProcessed.Add(theFunction);
737 //=============================================================================
739 * FindEntries: Returns a sequence of start/end positions of entries in the string
741 //=============================================================================
742 Handle(TColStd_HSequenceOfInteger) FindEntries(TCollection_AsciiString& theString)
744 Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
745 Standard_Integer aLen = theString.Length();
746 Standard_Boolean isFound = Standard_False;
748 const char* arr = theString.ToCString();
749 Standard_Integer i = 0, j;
754 if(c >= 48 && c <= 57) { //Is digit?
756 isFound = Standard_False;
757 while((j < aLen) && ((c >= 48 && c <= 57) || c == 58) ) { //Check if it is an entry
759 if(c == 58) isFound = Standard_True;
762 if(isFound && arr[j-2] != 58) { // last char should be a diggit
763 aSeq->Append(i+1); // +1 because AsciiString starts from 1
774 //=============================================================================
776 * ReplaceVariables: Replace parameters of the function by variales from
779 //=============================================================================
780 void ReplaceVariables(TCollection_AsciiString& theCommand,
781 TVariablesList theVariables)
784 cout<<"Command : "<<theCommand<<endl;
787 cout<<"All Entries:"<<endl;
788 TVariablesList::const_iterator it = theVariables.begin();
789 for(;it != theVariables.end();it++)
790 cout<<"\t'"<<(*it).first<<"'"<<endl;
793 //Additional case - multi-row commands
794 int aCommandIndex = 1;
795 while( aCommandIndex < 10 ) { // tmp check
796 TCollection_AsciiString aCommand = theCommand.Token("\n",aCommandIndex);
797 if( aCommand.Length() == 0 )
801 cout<<"Sub-command : "<<aCommand<<endl;
803 Standard_Integer aStartCommandPos = theCommand.Location(aCommand,1,theCommand.Length());
804 Standard_Integer aEndCommandPos = aStartCommandPos + aCommand.Length();
806 //Get Entry of the result object
807 TCollection_AsciiString anEntry = aCommand.Token("=",1);
809 //Remove white spaces
810 anEntry.RightAdjust();
811 anEntry.LeftAdjust();
813 cout<<"Result entry : '" <<anEntry<<"'"<<endl;
815 //Check if result is list of entries - enough to get the first entry in this case
817 if( anEntry.Value( 1 ) == O_SQR_BRACKET && anEntry.Value( anEntry.Length() ) == C_SQR_BRACKET ) {
818 while(anEntry.Location(aNbEntries,COMMA,1,anEntry.Length()))
820 TCollection_AsciiString aSeparator(COMMA);
821 anEntry = anEntry.Token(aSeparator.ToCString(),1);
822 anEntry.Remove( 1, 1 );
823 anEntry.RightAdjust();
824 anEntry.LeftAdjust();
826 cout<<"Sub-entry : '" <<anEntry<<"'"<<endl;
829 //Find variables used for object construction
830 vector<TVariable> aVariables;
831 TVariablesList::const_iterator it = theVariables.find(anEntry);
832 if( it != theVariables.end() )
833 aVariables = (*it).second;
835 if(aVariables.empty()) {
837 cout<<"Valiables list empty!!!"<<endl;
843 cout<<"Variables from SObject:"<<endl;
844 for (int i = 0; i < aVariables.size();i++)
845 cout<<"\t Variable["<<i<<"] = "<<aVariables[i].myVariable<<endl;
848 //Calculate total number of parameters
849 Standard_Integer aTotalNbParams = 1;
850 while(aCommand.Location(aTotalNbParams,COMMA,1,aCommand.Length()))
854 cout<<"aTotalNbParams = "<<aTotalNbParams<<endl;
856 Standard_Integer aFirstParam = aNbEntries;
858 //Replace parameters by variables
859 Standard_Integer aStartPos = 0;
860 Standard_Integer aEndPos = 0;
862 TCollection_AsciiString aReplasedVar, aVar;
863 for(Standard_Integer i=aFirstParam;i <= aTotalNbParams;i++) {
864 //Replace first parameter (bettwen '(' character and first ',' character)
867 aStartPos = aCommand.Location(O_BRACKET, 1, aCommand.Length()) + 1;
868 if(aTotalNbParams - aNbEntries > 0 )
869 aEndPos = aCommand.Location(aFirstParam, COMMA, 1, aCommand.Length());
871 aEndPos = aCommand.Location(C_BRACKET, 1, aCommand.Length());
873 //Replace last parameter (bettwen ',' character and ')' character)
874 else if(i == aTotalNbParams)
876 aStartPos = aCommand.Location(i-1, COMMA, 1, aCommand.Length()) + 2;
877 aEndPos = aCommand.Location(C_BRACKET, 1, aCommand.Length());
879 //Replace other parameters (bettwen two ',' characters)
880 else if(i != aFirstParam && i != aTotalNbParams )
882 aStartPos = aCommand.Location(i-1, COMMA, 1, aCommand.Length()) + 2;
883 aEndPos = aCommand.Location(i, COMMA, 1, aCommand.Length());
886 if( aCommand.Value( aStartPos ) == O_SQR_BRACKET )
888 if( aCommand.Value( aEndPos-1 ) == C_SQR_BRACKET )
892 cout<<"aStartPos = "<<aStartPos<<", aEndPos = "<<aEndPos<<endl;
894 aVar = aCommand.SubString(aStartPos, aEndPos-1);
899 cout<<"Variable: '"<< aVar <<"'"<<endl;
901 //If parameter is entry or 'None', skip it
902 if(theVariables.find(aVar) != theVariables.end() || aVar == PY_NULL)
905 if(iVar >= aVariables.size())
908 aReplasedVar = aVariables[iVar].myVariable;
910 if(aReplasedVar.IsEmpty()) {
915 if(aVariables[iVar].isVariable) {
916 aReplasedVar.InsertBefore(1,"\"");
917 aReplasedVar.InsertAfter(aReplasedVar.Length(),"\"");
920 aCommand.Remove(aStartPos, aEndPos - aStartPos);
921 aCommand.Insert(aStartPos, aReplasedVar);
925 theCommand.Remove(aStartCommandPos, aEndCommandPos - aStartCommandPos);
926 theCommand.Insert(aStartCommandPos, aCommand);
932 cout<<"Command : "<<theCommand<<endl;