Salome HOME
35dd6c43d74cded378f36dad52118ebd55e5dc85
[modules/smesh.git] / src / SMESH_I / SMESH_2smeshpy.cxx
1 //  SMESH SMESH_I : idl implementation based on 'SMESH' unit's calsses
2 //
3 //  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
5 // 
6 //  This library is free software; you can redistribute it and/or 
7 //  modify it under the terms of the GNU Lesser General Public 
8 //  License as published by the Free Software Foundation; either 
9 //  version 2.1 of the License. 
10 // 
11 //  This library is distributed in the hope that it will be useful, 
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of 
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
14 //  Lesser General Public License for more details. 
15 // 
16 //  You should have received a copy of the GNU Lesser General Public 
17 //  License along with this library; if not, write to the Free Software 
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
19 // 
20 //  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
21 //
22 //
23 //
24 //  File   : SMESH_2D_Algo_i.hxx
25 //  Author : Paul RASCLE, EDF
26 //  Module : SMESH
27 //  $Header$
28
29 // File      : SMESH_2smeshpy.cxx
30 // Created   : Fri Nov 18 13:20:10 2005
31 // Author    : Edward AGAPOV (eap)
32
33 #include "SMESH_2smeshpy.hxx"
34
35 #include "SMESH_Gen_i.hxx"
36 #include "utilities.h"
37 #include "SMESH_PythonDump.hxx"
38 #include "Resource_DataMapOfAsciiStringAsciiString.hxx"
39
40 IMPLEMENT_STANDARD_HANDLE (_pyObject          ,Standard_Transient);
41 IMPLEMENT_STANDARD_HANDLE (_pyCommand         ,Standard_Transient);
42 IMPLEMENT_STANDARD_HANDLE (_pyGen             ,_pyObject);
43 IMPLEMENT_STANDARD_HANDLE (_pyMesh            ,_pyObject);
44 IMPLEMENT_STANDARD_HANDLE (_pyHypothesis      ,_pyObject);
45 IMPLEMENT_STANDARD_HANDLE (_pyAlgorithm       ,_pyHypothesis);
46 IMPLEMENT_STANDARD_HANDLE (_pyComplexParamHypo,_pyHypothesis);
47 IMPLEMENT_STANDARD_HANDLE (_pyNumberOfSegmentsHyp,_pyHypothesis);
48
49 IMPLEMENT_STANDARD_RTTIEXT(_pyObject          ,Standard_Transient);
50 IMPLEMENT_STANDARD_RTTIEXT(_pyCommand         ,Standard_Transient);
51 IMPLEMENT_STANDARD_RTTIEXT(_pyGen             ,_pyObject);
52 IMPLEMENT_STANDARD_RTTIEXT(_pyMesh            ,_pyObject);
53 IMPLEMENT_STANDARD_RTTIEXT(_pyHypothesis      ,_pyObject);
54 IMPLEMENT_STANDARD_RTTIEXT(_pyAlgorithm       ,_pyHypothesis);
55 IMPLEMENT_STANDARD_RTTIEXT(_pyComplexParamHypo,_pyHypothesis);
56 IMPLEMENT_STANDARD_RTTIEXT(_pyNumberOfSegmentsHyp,_pyHypothesis);
57
58 using namespace std;
59 using SMESH::TPythonDump;
60
61 /*!
62  * \brief Container of commands into which the initial script is split.
63  *        It also contains data coresponding to SMESH_Gen contents
64  */
65 static Handle(_pyGen) theGen;
66
67 static TCollection_AsciiString theEmptyString;
68
69 //#define DUMP_CONVERSION
70
71 #if !defined(_DEBUG_) && defined(DUMP_CONVERSION)
72 #undef DUMP_CONVERSION
73 #endif
74
75 //================================================================================
76 /*!
77  * \brief Convert python script using commands of smesh.py
78   * \param theScript - Input script
79   * \retval TCollection_AsciiString - Convertion result
80  */
81 //================================================================================
82
83 TCollection_AsciiString
84 SMESH_2smeshpy::ConvertScript(const TCollection_AsciiString& theScript,
85                               Resource_DataMapOfAsciiStringAsciiString& theEntry2AccessorMethod)
86 {
87   theGen = new _pyGen( theEntry2AccessorMethod );
88
89   // split theScript into separate commands
90   int from = 1, end = theScript.Length(), to;
91   while ( from < end && ( to = theScript.Location( "\n", from, end )))
92   {
93     if ( to != from )
94       // cut out and store a command
95       theGen->AddCommand( theScript.SubString( from, to - 1 ));
96     from = to + 1;
97   }
98   // finish conversion
99   theGen->Flush();
100 #ifdef DUMP_CONVERSION
101   cout << endl << " ######## RESULT ######## " << endl<< endl;
102 #endif
103   // reorder commands after conversion
104   list< Handle(_pyCommand) >::iterator cmd;
105   bool orderChanges;
106   do {
107     orderChanges = false;
108     for ( cmd = theGen->GetCommands().begin(); cmd != theGen->GetCommands().end(); ++cmd )
109       if ( (*cmd)->SetDependentCmdsAfter() )
110         orderChanges = true;
111   } while ( orderChanges );
112   
113   // concat commands back into a script
114   TCollection_AsciiString aScript;
115   for ( cmd = theGen->GetCommands().begin(); cmd != theGen->GetCommands().end(); ++cmd )
116   {
117 #ifdef DUMP_CONVERSION
118     cout << "## COM " << (*cmd)->GetOrderNb() << ": "<< (*cmd)->GetString() << endl;
119 #endif
120     if ( !(*cmd)->IsEmpty() ) {
121       aScript += "\n";
122       aScript += (*cmd)->GetString();
123     }
124   }
125   aScript += "\n";
126
127   theGen.Nullify();
128
129   return aScript;
130 }
131
132 //================================================================================
133 /*!
134  * \brief _pyGen constructor
135  */
136 //================================================================================
137
138 _pyGen::_pyGen(Resource_DataMapOfAsciiStringAsciiString& theEntry2AccessorMethod)
139   : _pyObject( new _pyCommand( TPythonDump::SMESHGenName(), 0 )),
140     myID2AccessorMethod( theEntry2AccessorMethod )
141 {
142   myNbCommands = 0;
143   myHasPattern = false;
144   // make that GetID() to return TPythonDump::SMESHGenName()
145   GetCreationCmd()->GetString() += "=";
146 }
147
148 //================================================================================
149 /*!
150  * \brief Convert a command using a specific converter
151   * \param theCommand - the command to convert
152  */
153 //================================================================================
154
155 void _pyGen::AddCommand( const TCollection_AsciiString& theCommand)
156 {
157   // store theCommand in the sequence
158   myCommands.push_back( new _pyCommand( theCommand, ++myNbCommands ));
159
160   Handle(_pyCommand) aCommand = myCommands.back();
161 #ifdef DUMP_CONVERSION
162   cout << "## COM " << myNbCommands << ": "<< aCommand->GetString() << endl;
163 #endif
164
165   _pyID objID = aCommand->GetObject();
166
167   if ( objID.IsEmpty() )
168     return;
169
170   // SMESH_Gen method?
171   if ( objID == this->GetID() ) {
172     this->Process( aCommand );
173     return;
174   }
175   // SMESH_Mesh method?
176   map< _pyID, Handle(_pyMesh) >::iterator id_mesh = myMeshes.find( objID );
177   if ( id_mesh != myMeshes.end() ) {
178     id_mesh->second->Process( aCommand );
179     return;
180   }
181   // SMESH_Hypothesis method?
182   list< Handle(_pyHypothesis) >::iterator hyp = myHypos.begin();
183   for ( ; hyp != myHypos.end(); ++hyp )
184     if ( !(*hyp)->IsAlgo() && objID == (*hyp)->GetID() ) {
185       (*hyp)->Process( aCommand );
186       return;
187     }
188
189   // Add access to a wrapped mesh
190   for ( id_mesh = myMeshes.begin(); id_mesh != myMeshes.end(); ++id_mesh ) {
191     if ( aCommand->AddAccessorMethod( id_mesh->first, id_mesh->second->AccessorMethod() ))
192       break;
193   }
194
195   // Add access to a wrapped algorithm
196   for ( hyp = myHypos.begin(); hyp != myHypos.end(); ++hyp ) {
197     if ( (*hyp)->IsAlgo() &&
198          aCommand->AddAccessorMethod( (*hyp)->GetID(), (*hyp)->AccessorMethod() ))
199       break;
200   }
201 }
202
203 //================================================================================
204 /*!
205  * \brief Convert the command or remember it for later conversion 
206   * \param theCommand - The python command calling a method of SMESH_Gen
207  */
208 //================================================================================
209
210 void _pyGen::Process( const Handle(_pyCommand)& theCommand )
211 {
212   // there are methods to convert:
213   // CreateMesh( shape )
214   // CreateHypothesis( theHypType, theLibName )
215   // Compute( mesh, geom )
216
217   if ( theCommand->GetMethod() == "CreateMesh" )
218   {
219     Handle(_pyMesh) mesh = new _pyMesh( theCommand );
220     myMeshes.insert( make_pair( mesh->GetID(), mesh ));
221     return;
222   }
223
224   // CreateHypothesis()
225   if ( theCommand->GetMethod() == "CreateHypothesis" )
226   {
227     myHypos.push_back( _pyHypothesis::NewHypothesis( theCommand ));
228     return;
229   }
230
231   // smeshgen.Compute( mesh, geom ) --> mesh.Compute()
232   if ( theCommand->GetMethod() == "Compute" )
233   {
234     const _pyID& meshID = theCommand->GetArg( 1 );
235     map< _pyID, Handle(_pyMesh) >::iterator id_mesh = myMeshes.find( meshID );
236     if ( id_mesh != myMeshes.end() ) {
237       theCommand->SetObject( meshID );
238       theCommand->RemoveArgs();
239       id_mesh->second->Flush();
240       return;
241     }
242   }
243
244   // leave only one smeshgen.GetPattern() in the script
245   if ( theCommand->GetMethod() == "GetPattern" ) {
246     if ( myHasPattern ) {
247       theCommand->Clear();
248       return;
249     }
250     myHasPattern = true;
251   }
252
253   // smeshgen.Method() --> smesh.smesh.Method()
254   theCommand->SetObject( SMESH_2smeshpy::GenName() );
255 }
256
257 //================================================================================
258 /*!
259  * \brief Convert the remembered commands
260  */
261 //================================================================================
262
263 void _pyGen::Flush()
264 {
265   map< _pyID, Handle(_pyMesh) >::iterator id_mesh = myMeshes.begin();
266   for ( ; id_mesh != myMeshes.end(); ++id_mesh )
267     if ( ! id_mesh->second.IsNull() )
268       id_mesh->second->Flush();
269
270   list< Handle(_pyHypothesis) >::iterator hyp = myHypos.begin();
271   for ( ; hyp != myHypos.end(); ++hyp )
272     if ( !hyp->IsNull() ) {
273       (*hyp)->Flush();
274       // smeshgen.CreateHypothesis() --> smesh.smesh.CreateHypothesis()
275       if ( !(*hyp)->IsWrapped() )
276         (*hyp)->GetCreationCmd()->SetObject( SMESH_2smeshpy::GenName() );
277     }
278 }
279
280 //================================================================================
281 /*!
282  * \brief Find hypothesis by ID (entry)
283   * \param theHypID - The hypothesis ID
284   * \retval Handle(_pyHypothesis) - The found hypothesis
285  */
286 //================================================================================
287
288 Handle(_pyHypothesis) _pyGen::FindHyp( const _pyID& theHypID )
289 {
290   list< Handle(_pyHypothesis) >::iterator hyp = myHypos.begin();
291   for ( ; hyp != myHypos.end(); ++hyp )
292     if ( !hyp->IsNull() && theHypID == (*hyp)->GetID() )
293       return *hyp;
294   return Handle(_pyHypothesis)();
295 }
296
297 //================================================================================
298 /*!
299  * \brief Find algorithm the created algorithm
300   * \param theGeom - The shape ID the algorithm was created on
301   * \param theMesh - The mesh ID that created the algorithm
302   * \param dim - The algo dimension
303   * \retval Handle(_pyHypothesis) - The found algo
304  */
305 //================================================================================
306
307 Handle(_pyHypothesis) _pyGen::FindAlgo( const _pyID& theGeom, const _pyID& theMesh,
308                                       const TCollection_AsciiString& theAlgoType )
309 {
310   list< Handle(_pyHypothesis) >::iterator hyp = myHypos.begin();
311   for ( ; hyp != myHypos.end(); ++hyp )
312     if ( !hyp->IsNull() &&
313          (*hyp)->IsAlgo() &&
314          (*hyp)->GetType() == theAlgoType &&
315          (*hyp)->GetGeom() == theGeom &&
316          (*hyp)->GetMesh() == theMesh )
317       return *hyp;
318   return 0;
319 }
320
321 //================================================================================
322 /*!
323  * \brief Change order of commands in the script
324   * \param theCmd1 - One command
325   * \param theCmd2 - Another command
326  */
327 //================================================================================
328
329 void _pyGen::ExchangeCommands( Handle(_pyCommand) theCmd1, Handle(_pyCommand) theCmd2 )
330 {
331   list< Handle(_pyCommand) >::iterator pos1, pos2;
332   pos1 = find( myCommands.begin(), myCommands.end(), theCmd1 );
333   pos2 = find( myCommands.begin(), myCommands.end(), theCmd2 );
334   myCommands.insert( pos1, theCmd2 );
335   myCommands.insert( pos2, theCmd1 );
336   myCommands.erase( pos1 );
337   myCommands.erase( pos2 );
338
339   int nb1 = theCmd1->GetOrderNb();
340   theCmd1->SetOrderNb( theCmd2->GetOrderNb() );
341   theCmd2->SetOrderNb( nb1 );
342 //   cout << "BECOME " << theCmd1->GetOrderNb() << "\t" << theCmd1->GetString() << endl
343 //        << "BECOME " << theCmd2->GetOrderNb() << "\t" << theCmd2->GetString() << endl << endl;
344 }
345
346 //================================================================================
347 /*!
348  * \brief Set one command after the other
349   * \param theCmd - Command to move
350   * \param theAfterCmd - Command ater which to insert the first one
351  */
352 //================================================================================
353
354 void _pyGen::SetCommandAfter( Handle(_pyCommand) theCmd, Handle(_pyCommand) theAfterCmd )
355 {
356 //   cout << "SET\t" << theCmd->GetString() << endl << "AFTER\t" << theAfterCmd->GetString() << endl << endl;
357   list< Handle(_pyCommand) >::iterator pos;
358   pos = find( myCommands.begin(), myCommands.end(), theCmd );
359   myCommands.erase( pos );
360   pos = find( myCommands.begin(), myCommands.end(), theAfterCmd );
361   myCommands.insert( ++pos, theCmd );
362
363   int i = 1;
364   for ( pos = myCommands.begin(); pos != myCommands.end(); ++pos)
365     (*pos)->SetOrderNb( i++ );
366 }
367
368 //================================================================================
369 /*!
370  * \brief Set method to access to object wrapped with python class
371   * \param theID - The wrapped object entry
372   * \param theMethod - The accessor method
373  */
374 //================================================================================
375
376 void _pyGen::SetAccessorMethod(const _pyID& theID, const char* theMethod )
377 {
378   myID2AccessorMethod.Bind( theID, (char*) theMethod );
379 }
380
381 //================================================================================
382 /*!
383  * \brief Find out type of geom group
384   * \param grpID - The geom group entry
385   * \retval int - The type
386  */
387 //================================================================================
388
389 static bool sameGroupType( const _pyID&                   grpID,
390                            const TCollection_AsciiString& theType)
391 {
392   // define group type as smesh.Mesh.Group() does
393   int type = -1;
394   SALOMEDS::Study_var study = SMESH_Gen_i::GetSMESHGen()->GetCurrentStudy();
395   SALOMEDS::SObject_var aSObj = study->FindObjectID( grpID.ToCString() );
396   if ( !aSObj->_is_nil() ) {
397     GEOM::GEOM_Object_var aGeomObj = GEOM::GEOM_Object::_narrow( aSObj->GetObject() );
398     if ( !aGeomObj->_is_nil() ) {
399       switch ( aGeomObj->GetShapeType() ) {
400       case GEOM::VERTEX: type = SMESH::NODE; break;
401       case GEOM::EDGE:   type = SMESH::EDGE; break;
402       case GEOM::FACE:   type = SMESH::FACE; break;
403       case GEOM::SOLID:
404       case GEOM::SHELL:  type = SMESH::VOLUME; break;
405       case GEOM::COMPOUND: {
406         GEOM::GEOM_Gen_var aGeomGen = SMESH_Gen_i::GetSMESHGen()->GetGeomEngine();
407         if ( !aGeomGen->_is_nil() ) {
408           GEOM::GEOM_IGroupOperations_var aGrpOp =
409             aGeomGen->GetIGroupOperations( study->StudyId() );
410           if ( !aGrpOp->_is_nil() ) {
411             switch ( aGrpOp->GetType( aGeomObj )) {
412             case TopAbs_VERTEX: type = SMESH::NODE; break;
413             case TopAbs_EDGE:   type = SMESH::EDGE; break;
414             case TopAbs_FACE:   type = SMESH::FACE; break;
415             case TopAbs_SOLID:  type = SMESH::VOLUME; break;
416             default:;
417             }
418           }
419         }
420       }
421       default:;
422       }
423     }
424   }
425   if ( type < 0 ) {
426     MESSAGE("Type of the group " << grpID << " not found");
427     return false;
428   }
429   if ( theType.IsIntegerValue() )
430     return type == theType.IntegerValue();
431
432   switch ( type ) {
433   case SMESH::NODE:   return theType.Location( "NODE", 1, theType.Length() );
434   case SMESH::EDGE:   return theType.Location( "EDGE", 1, theType.Length() );
435   case SMESH::FACE:   return theType.Location( "FACE", 1, theType.Length() );
436   case SMESH::VOLUME: return theType.Location( "VOLUME", 1, theType.Length() );
437   default:;
438   }
439   return false;
440 }
441
442 //================================================================================
443 /*!
444  * \brief 
445   * \param theCreationCmd - 
446  */
447 //================================================================================
448
449 _pyMesh::_pyMesh(const Handle(_pyCommand) theCreationCmd):
450   _pyObject(theCreationCmd), myHasEditor(false)
451 {
452   // convert my creation command
453   Handle(_pyCommand) creationCmd = GetCreationCmd();
454   creationCmd->SetObject( SMESH_2smeshpy::SmeshpyName() );
455   creationCmd->SetMethod( "Mesh" );
456
457   theGen->SetAccessorMethod( GetID(), "GetMesh()" );
458 }
459
460 //================================================================================
461 /*!
462  * \brief Convert a IDL API command of SMESH::Mesh to a method call of python Mesh
463   * \param theCommand - Engine method called for this mesh
464  */
465 //================================================================================
466
467 void _pyMesh::Process( const Handle(_pyCommand)& theCommand )
468 {
469   // smesh.py wraps the following methods:
470   //
471   // 1. GetSubMesh(geom, name) + AddHypothesis(geom, algo)
472   //     --> in Mesh_Algorithm.Create(mesh, geom, hypo, so)
473   // 2. AddHypothesis(geom, hyp)
474   //     --> in Mesh_Algorithm.Hypothesis(hyp, args, so)
475   // 3. CreateGroupFromGEOM(type, name, grp)
476   //     --> in Mesh.Group(grp, name="")
477   // 4. ExportToMED(f, opt, version)
478   //     --> in Mesh.ExportToMED( f, version, opt=0 )
479   // 5. ExportMED(f, opt)
480   //     --> in Mesh.ExportMED( f,opt=0 )
481   // 6. ExportDAT(f)
482   //     --> in Mesh.ExportDAT( f )
483   // 7. ExportUNV(f)
484   //     --> in Mesh.ExportUNV(f)
485   // 8. ExportSTL(f, ascii)
486   //     --> in Mesh.ExportSTL(f, ascii=1)
487
488   const TCollection_AsciiString method = theCommand->GetMethod();
489   if ( method == "GetSubMesh" ) {
490     mySubmeshes.push_back( theCommand );
491   }
492   else if ( method == "AddHypothesis" ) { // mesh.AddHypothesis(geom, HYPO )
493     myAddHypCmds.push_back( theCommand );
494     // set mesh to hypo
495     const _pyID& hypID = theCommand->GetArg( 2 );
496     Handle(_pyHypothesis) hyp = theGen->FindHyp( hypID );
497     if ( !hyp.IsNull() ) {
498       myHypos.push_back( hyp );
499       if ( hyp->GetMesh().IsEmpty() )
500         hyp->SetMesh( this->GetID() );
501     }
502   }
503   else if ( method == "CreateGroupFromGEOM" ) {// (type, name, grp)
504     _pyID grp = theCommand->GetArg( 3 );
505     if ( sameGroupType( grp, theCommand->GetArg( 1 )) ) { // --> Group(grp)
506       theCommand->SetMethod( "Group" );
507       theCommand->RemoveArgs();
508       theCommand->SetArg( 1, grp );
509     }
510     else {
511       AddMeshAccess( theCommand );
512     }
513   }
514   else if ( method == "ExportToMED" ) {//(f, opt, version)
515     // --> (f, version, opt)
516     _pyID opt = theCommand->GetArg( 2 );
517     _pyID ver = theCommand->GetArg( 3 );
518     theCommand->SetArg( 2, ver );
519     theCommand->SetArg( 3, opt );
520   }
521   else if ( method == "RemoveHypothesis" ) // (geom, hyp)
522   {
523     const _pyID & hypID = theCommand->GetArg( 2 );
524
525     // check if this mesh still has corresponding addition command
526     bool hasAddCmd = false;
527     list< Handle(_pyCommand) >::iterator cmd = myAddHypCmds.begin();
528     while ( cmd != myAddHypCmds.end() )
529     {
530       // AddHypothesis(geom, hyp)
531       if ( hypID == (*cmd)->GetArg( 2 )) { // erase both (add and remove) commands
532         theCommand->Clear();
533         (*cmd)->Clear();
534         cmd = myAddHypCmds.erase( cmd );
535         hasAddCmd = true;
536       }
537       else {
538         ++cmd;
539       }
540     }
541     Handle(_pyHypothesis) hyp = theGen->FindHyp( hypID );
542     if ( ! hasAddCmd ) { // hypo addition already wrapped
543       // access to wrapped mesh
544       AddMeshAccess( theCommand );
545       // access to wrapped algo
546       if ( !hyp.IsNull() && hyp->IsAlgo() && hyp->IsWrapped() )
547         theCommand->SetArg( 2, theCommand->GetArg( 2 ) + ".GetAlgorithm()" );
548     }
549     // remove hyp from myHypos
550     myHypos.remove( hyp );
551   }
552
553   // leave only one "  mesh_editor_<nb> = mesh.GetMeshEditor()"
554   else if ( theCommand->GetMethod() == "GetMeshEditor")
555   {
556     if ( myHasEditor )
557       theCommand->Clear();
558     else
559       AddMeshAccess( theCommand );
560     myHasEditor = true;
561   }
562
563   // apply theCommand to the mesh wrapped by smeshpy mesh
564   else
565   {
566     AddMeshAccess( theCommand );
567   }
568 }
569
570 //================================================================================
571 /*!
572  * \brief Convert creation and addition of all algos and hypos
573  */
574 //================================================================================
575
576 void _pyMesh::Flush()
577 {
578   list < Handle(_pyCommand) >::iterator cmd, cmd2;
579
580   // try to convert algo addition like this:
581   // mesh.AddHypothesis(geom, ALGO ) --> ALGO = mesh.Algo()
582   for ( cmd = myAddHypCmds.begin(); cmd != myAddHypCmds.end(); ++cmd )
583   {
584     Handle(_pyCommand) addCmd = *cmd;
585     const _pyID& algoID = addCmd->GetArg( 2 );
586     Handle(_pyHypothesis) algo = theGen->FindHyp( algoID );
587     if ( algo.IsNull() || !algo->IsAlgo() )
588       continue;
589     // try to convert
590     _pyID geom = addCmd->GetArg( 1 );
591     if ( algo->Addition2Creation( addCmd, this->GetID() )) // OK
592     {
593       // wrapped algo is created atfer mesh creation
594       GetCreationCmd()->AddDependantCmd( addCmd );
595
596       if ( geom != GetGeom() ) // local algo
597       {
598         // mesh.AddHypothesis(geom, ALGO ) --> mesh.AlgoMethod(geom)
599         addCmd->SetArg( addCmd->GetNbArgs() + 1,
600                         TCollection_AsciiString( "geom=" ) + geom );
601         // sm = mesh.GetSubMesh(geom, name) --> sm = ALGO.GetSubMesh()
602         for ( cmd2 = mySubmeshes.begin(); cmd2 != mySubmeshes.end(); ++cmd2 ) {
603           Handle(_pyCommand) subCmd = *cmd2;
604           if ( geom == subCmd->GetArg( 1 )) {
605             subCmd->SetObject( algo->GetID() );
606             subCmd->RemoveArgs();
607             addCmd->AddDependantCmd( subCmd );
608           }
609         }
610       }
611     }
612     else // ALGO was already created
613     {
614       // mesh.AddHypothesis(geom, ALGO ) --> mesh.GetMesh().AddHypothesis(geom, ALGO )
615       AddMeshAccess( addCmd );
616       // mesh.GetMesh().AddHypothesis(geom, ALGO ) ->
617       // mesh.GetMesh().AddHypothesis(geom, ALGO.GetAlgorithm() )
618       addCmd->SetArg( 2, addCmd->GetArg( 2 ) + ".GetAlgorithm()" );
619     }
620   }
621
622   // try to convert hypo addition like this:
623   // mesh.AddHypothesis(geom, HYPO ) --> HYPO = algo.Hypo()
624   for ( cmd = myAddHypCmds.begin(); cmd != myAddHypCmds.end(); ++cmd )
625   {
626     Handle(_pyCommand) addCmd = *cmd;
627     const _pyID& hypID = addCmd->GetArg( 2 );
628     Handle(_pyHypothesis) hyp = theGen->FindHyp( hypID );
629     if ( hyp.IsNull() || hyp->IsAlgo() )
630       continue;
631     const _pyID& geom = addCmd->GetArg( 1 );
632     // find algo created on <geom> for this mesh
633     Handle(_pyHypothesis) algo = theGen->FindAlgo( geom, this->GetID(), hyp->GetType() );
634     //_pyID algoID = algo.IsNull() ? "" : algo->GetID();
635     if ( !algo.IsNull() && hyp->Addition2Creation( addCmd, this->GetID() )) // OK
636     {
637       addCmd->SetObject( algo->GetID() );
638       algo->GetCreationCmd()->AddDependantCmd( addCmd );
639     }
640     else
641     {
642       AddMeshAccess( addCmd );
643     }
644   }
645
646   // sm = mesh.GetSubMesh(geom, name) --> sm = mesh.GetMesh().GetSubMesh(geom, name)
647   for ( cmd = mySubmeshes.begin(); cmd != mySubmeshes.end(); ++cmd ) {
648     Handle(_pyCommand) subCmd = *cmd;
649     if ( subCmd->GetNbArgs() > 0 )
650       AddMeshAccess( subCmd );
651   }
652   myAddHypCmds.clear();
653   mySubmeshes.clear();
654
655   // flush hypotheses
656   list< Handle(_pyHypothesis) >::iterator hyp = myHypos.begin();
657   for ( ; hyp != myHypos.end(); ++hyp )
658     (*hyp)->Flush();
659 }
660
661 //================================================================================
662 /*!
663  * \brief _pyHypothesis constructor
664   * \param theCreationCmd - 
665  */
666 //================================================================================
667
668 _pyHypothesis::_pyHypothesis(const Handle(_pyCommand)& theCreationCmd):
669   _pyObject( theCreationCmd )
670 {
671   myDim = myIsAlgo = /*myIsLocal = */myIsWrapped = myIsConverted = false;
672 }
673
674 //================================================================================
675 /*!
676  * \brief Creates algorithm or hypothesis
677   * \param theCreationCmd - The engine command creating a hypothesis
678   * \retval Handle(_pyHypothesis) - Result _pyHypothesis
679  */
680 //================================================================================
681
682 Handle(_pyHypothesis) _pyHypothesis::NewHypothesis( const Handle(_pyCommand)& theCreationCmd)
683 {
684   // theCreationCmd: CreateHypothesis( "theHypType", "theLibName" )
685   ASSERT (( theCreationCmd->GetMethod() == "CreateHypothesis"));
686
687   Handle(_pyHypothesis) hyp, algo;
688
689   // "theHypType"
690   const TCollection_AsciiString & hypTypeWithQuotes = theCreationCmd->GetArg( 1 );
691   if ( hypTypeWithQuotes.IsEmpty() )
692     return hyp;
693   // theHypType
694   TCollection_AsciiString  hypType =
695     hypTypeWithQuotes.SubString( 2, hypTypeWithQuotes.Length() - 1 );
696
697   algo = new _pyAlgorithm( theCreationCmd );
698   hyp  = new _pyHypothesis( theCreationCmd );
699
700   // 1D Regular_1D ----------
701   if ( hypType == "Regular_1D" ) {
702     algo->myDim = 1;
703     algo->myCreationMethod = "Segment";
704   }
705   else if ( hypType == "LocalLength" ) {
706     hyp->myDim = 1;
707     hyp->myCreationMethod = "LocalLength";
708     hyp->myType = "Regular_1D";
709     hyp->myArgMethods.Append( "SetLength" );
710   }
711   else if ( hypType == "NumberOfSegments" ) {
712     hyp = new _pyNumberOfSegmentsHyp( theCreationCmd );
713     hyp->myDim = 1;
714     hyp->myCreationMethod = "NumberOfSegments";
715     hyp->myType = "Regular_1D";
716     hyp->myArgMethods.Append( "SetNumberOfSegments" );
717     hyp->myArgMethods.Append( "SetScaleFactor" );
718   }
719   else if ( hypType == "Arithmetic1D" ) {
720     hyp = new _pyComplexParamHypo( theCreationCmd );
721     hyp->myDim = 1;
722     hyp->myCreationMethod = "Arithmetic1D";
723     hyp->myType = "Regular_1D";
724   }
725   else if ( hypType == "StartEndLength" ) {
726     hyp = new _pyComplexParamHypo( theCreationCmd );
727     hyp->myDim = 1;
728     hyp->myCreationMethod = "StartEndLength";
729     hyp->myType = "Regular_1D";
730   }
731   else if ( hypType == "Deflection1D" ) {
732     hyp->myDim = 1;
733     hyp->myCreationMethod = "Deflection1D";
734     hyp->myArgMethods.Append( "SetDeflection" );
735     hyp->myType = "Regular_1D";
736   }
737   else if ( hypType == "Propagation" ) {
738     hyp->myDim = 1;
739     hyp->myCreationMethod = "Propagation";
740     hyp->myType = "Regular_1D";
741   }
742   else if ( hypType == "QuadraticMesh" ) {
743     hyp->myDim = 1;
744     hyp->myCreationMethod = "QuadraticMesh";
745     hyp->myType = "Regular_1D";
746   }
747   else if ( hypType == "AutomaticLength" ) {
748     hyp->myDim = 1;
749     hyp->myCreationMethod = "AutomaticLength";
750     hyp->myType = "Regular_1D";
751     hyp->myArgMethods.Append( "SetFineness");
752   }
753   // 1D Python_1D ----------
754   else if ( hypType == "Python_1D" ) {
755     algo->myDim = 1;
756     algo->myCreationMethod = "Segment";
757     algo->myArgs.Append( "algo=smesh.PYTHON");
758   }
759   else if ( hypType == "PythonSplit1D" ) {
760     hyp->myDim = 1;
761     hyp->myCreationMethod = "PythonSplit1D";
762     hyp->myType = "Python_1D";
763     hyp->myArgMethods.Append( "SetNumberOfSegments");
764     hyp->myArgMethods.Append( "SetPythonLog10RatioFunction");
765   }
766   // 2D ----------
767   else if ( hypType == "MEFISTO_2D" ) {
768     algo->myDim = 2;
769     algo->myCreationMethod = "Triangle";
770   }
771   else if ( hypType == "MaxElementArea" ) {
772     hyp->myDim = 2;
773     hyp->myCreationMethod = "MaxElementArea";
774     hyp->myType = "MEFISTO_2D";
775     hyp->myArgMethods.Append( "SetMaxElementArea");
776   }
777   else if ( hypType == "LengthFromEdges" ) {
778     hyp->myDim = 2;
779     hyp->myCreationMethod = "LengthFromEdges";
780     hyp->myType = "MEFISTO_2D";
781   }
782   else if ( hypType == "Quadrangle_2D" ) {
783     algo->myDim = 2;
784     algo->myCreationMethod = "Quadrangle";
785   }
786   else if ( hypType == "QuadranglePreference" ) {
787     hyp->myDim = 2;
788     hyp->myCreationMethod = "QuadranglePreference";
789     hyp->myType = "Quadrangle_2D";
790   }
791   // 3D ----------
792   else if ( hypType == "NETGEN_3D") {
793     algo->myDim = 3;
794     algo->myCreationMethod = "Tetrahedron";
795     algo->myArgs.Append( "algo=smesh.NETGEN" );
796   }
797   else if ( hypType == "MaxElementVolume") {
798     hyp->myDim = 3;
799     hyp->myCreationMethod = "MaxElementVolume";
800     hyp->myType = "NETGEN_3D";
801     hyp->myArgMethods.Append( "SetMaxElementVolume" );
802   }
803   else if ( hypType == "GHS3D_3D" ) {
804     algo->myDim = 3;
805     algo->myCreationMethod = "Tetrahedron";
806     algo->myArgs.Append( "algo=smesh.GHS3D" );
807   }
808   else if ( hypType == "Hexa_3D" ) {
809     algo->myDim = 3;
810     algo->myCreationMethod = "Hexahedron";
811   }
812
813   if ( algo->GetDim() ) {
814     algo->myType = hypType;
815     return algo;
816   }
817   return hyp;
818 }
819
820 //================================================================================
821 /*!
822  * \brief Convert the command adding a hypothesis to mesh into a smesh command
823   * \param theCmd - The command like mesh.AddHypothesis( geom, hypo )
824   * \param theAlgo - The algo that can create this hypo
825   * \retval bool - false if the command cant be converted
826  */
827 //================================================================================
828
829 bool _pyHypothesis::Addition2Creation( const Handle(_pyCommand)& theCmd,
830                                        const _pyID&              theMesh)
831 {
832   ASSERT(( theCmd->GetMethod() == "AddHypothesis" ));
833
834   if ( !IsWrappable( theMesh ))
835     return false;
836
837   myIsWrapped = true;
838
839   if ( myIsWrapped )
840   {
841     // mesh.AddHypothesis(geom,hyp) --> hyp = theMesh.myCreationMethod(args)
842     theCmd->SetResultValue( GetID() );
843     theCmd->SetObject( theMesh );
844     theCmd->SetMethod( myCreationMethod );
845     // set args
846     theCmd->RemoveArgs();
847     for ( int i = 1; i <= myArgs.Length(); ++i ) {
848       if ( !myArgs( i ).IsEmpty() )
849         theCmd->SetArg( i, myArgs( i ));
850       else
851         theCmd->SetArg( i, "[]");
852     }
853     // set a new creation command
854     GetCreationCmd()->Clear();
855     SetCreationCmd( theCmd );
856
857     // clear commands setting arg values
858     list < Handle(_pyCommand) >::iterator argCmd = myArgCommands.begin();
859     for ( ; argCmd != myArgCommands.end(); ++argCmd )
860       (*argCmd)->Clear();
861   }
862   else
863   {
864 //     // set arg commands after hypo creation
865 //     list<Handle(_pyCommand)>::iterator argCmd = myArgCommands.begin();
866 //     for ( ; argCmd != myArgCommands.end(); ++argCmd )
867 //       if ( !(*argCmd)->IsEmpty() && GetCommandNb() > (*argCmd)->GetOrderNb() )
868 //         theGen->ExchangeCommands( GetCreationCmd(), *argCmd );
869   }
870
871   // set unknown arg commands after hypo creation
872   Handle(_pyCommand) afterCmd = myIsWrapped ? theCmd : GetCreationCmd();
873   list<Handle(_pyCommand)>::iterator cmd = myUnknownCommands.begin();
874   for ( ; cmd != myUnknownCommands.end(); ++cmd ) {
875     afterCmd->AddDependantCmd( *cmd );
876   }
877
878   return myIsWrapped;
879 }
880
881 //================================================================================
882 /*!
883  * \brief Remember hypothesis parameter values
884  * \param theCommand - The called hypothesis method
885  */
886 //================================================================================
887
888 void _pyHypothesis::Process( const Handle(_pyCommand)& theCommand)
889 {
890   ASSERT( !myIsAlgo );
891   // set args
892   for ( int i = 1; i <= myArgMethods.Length(); ++i ) {
893     if ( myArgMethods( i ) == theCommand->GetMethod() ) {
894       while ( myArgs.Length() < i )
895         myArgs.Append( "[]" );
896       myArgs( i ) = theCommand->GetArg( 1 ); // arg value
897       myArgCommands.push_back( theCommand );
898       return;
899     }
900   }
901   myUnknownCommands.push_back( theCommand );
902 }
903
904 //================================================================================
905 /*!
906  * \brief Finish conversion
907  */
908 //================================================================================
909
910 void _pyHypothesis::Flush()
911 {
912   if ( IsWrapped() ) {
913     // forget previous hypothesis modifications
914     myArgCommands.clear();
915     myUnknownCommands.clear();
916   }
917 }
918
919 //================================================================================
920 /*!
921  * \brief Remember hypothesis parameter values
922   * \param theCommand - The called hypothesis method
923  */
924 //================================================================================
925
926 void _pyComplexParamHypo::Process( const Handle(_pyCommand)& theCommand)
927 {
928   // ex: hyp.SetLength(start, 1)
929   //     hyp.SetLength(end,   0)
930   ASSERT(( theCommand->GetMethod() == "SetLength" ));
931   ASSERT(( theCommand->GetArg( 2 ).IsIntegerValue() ));
932   int i = 2 - theCommand->GetArg( 2 ).IntegerValue();
933   while ( myArgs.Length() < i )
934     myArgs.Append( "[]" );
935   myArgs( i ) = theCommand->GetArg( 1 ); // arg value
936   myArgCommands.push_back( theCommand );
937 }
938
939 //================================================================================
940 /*!
941  * \brief additionally to Addition2Creation, clears SetDistrType() command
942   * \param theCmd - AddHypothesis() command
943   * \param theMesh - mesh to which a hypothesis is added
944   * \retval bool - convertion result
945  */
946 //================================================================================
947
948 bool _pyNumberOfSegmentsHyp::Addition2Creation( const Handle(_pyCommand)& theCmd,
949                                                 const _pyID&              theMesh)
950 {
951   if ( IsWrappable( theMesh ) && myArgs.Length() > 1 ) {
952     // scale factor (2-nd arg) is provided: clear SetDistrType(1) command
953     bool scaleDistrType = false;
954     list<Handle(_pyCommand)>::reverse_iterator cmd = myUnknownCommands.rbegin();
955     for ( ; cmd != myUnknownCommands.rend(); ++cmd ) {
956       if ( (*cmd)->GetMethod() == "SetDistrType" ) {
957         if ( (*cmd)->GetArg( 1 ) == "1" ) {
958           scaleDistrType = true;
959           (*cmd)->Clear();
960         }
961         else if ( !scaleDistrType ) {
962           // distribution type changed: remove scale factor from args
963           myArgs.Remove( 2, myArgs.Length() );
964           break;
965         }
966       }
967     }
968   }
969   return _pyHypothesis::Addition2Creation( theCmd, theMesh );
970 }
971
972 //================================================================================
973 /*!
974  * \brief remove repeated commands defining distribution
975  */
976 //================================================================================
977
978 void _pyNumberOfSegmentsHyp::Flush()
979 {
980   const int nbCmdLists = 2;
981   list<Handle(_pyCommand)> * cmds[nbCmdLists] = { &myArgCommands, &myUnknownCommands };
982   for ( int i = 0; i < nbCmdLists; ++i ) {
983     set<TCollection_AsciiString> uniqueMethods;
984     list<Handle(_pyCommand)> & cmdList = *cmds[i];
985     list<Handle(_pyCommand)>::reverse_iterator cmd = cmdList.rbegin();
986     for ( ; cmd != cmdList.rend(); ++cmd ) {
987       bool isNewInSet = uniqueMethods.insert( (*cmd)->GetMethod() ).second;
988       if ( ! isNewInSet )
989         (*cmd)->Clear();
990     }
991     cmdList.clear();
992   }
993 }
994
995 //================================================================================
996 /*!
997  * \brief _pyAlgorithm constructor
998  * \param theCreationCmd - The command like "algo = smeshgen.CreateHypothesis(type,lib)"
999  */
1000 //================================================================================
1001
1002 _pyAlgorithm::_pyAlgorithm(const Handle(_pyCommand)& theCreationCmd)
1003   : _pyHypothesis( theCreationCmd )
1004 {
1005   myIsAlgo = true;
1006 }
1007
1008 //================================================================================
1009 /*!
1010  * \brief Convert the command adding an algorithm to mesh
1011   * \param theCmd - The command like mesh.AddHypothesis( geom, algo )
1012   * \param theMesh - The mesh needing this algo 
1013   * \retval bool - false if the command cant be converted
1014  */
1015 //================================================================================
1016   
1017 bool _pyAlgorithm::Addition2Creation( const Handle(_pyCommand)& theCmd,
1018                                       const _pyID&              theMeshID)
1019 {
1020   if ( IsWrappable( theMeshID )) {
1021
1022     myGeom = theCmd->GetArg( 1 );
1023
1024     // mesh.AddHypothesis(geom,algo) --> theMeshID.myCreationMethod()
1025     if ( _pyHypothesis::Addition2Creation( theCmd, theMeshID )) {
1026       theGen->SetAccessorMethod( GetID(), "GetAlgorithm()" );
1027       return true;
1028     }
1029   }
1030   return false;
1031 }
1032
1033 //================================================================================
1034 /*!
1035  * \brief Return starting position of a part of python command
1036   * \param thePartIndex - The index of command part
1037   * \retval int - Part position
1038  */
1039 //================================================================================
1040
1041 int _pyCommand::GetBegPos( int thePartIndex )
1042 {
1043   if ( IsEmpty() )
1044     return EMPTY;
1045   if ( myBegPos.Length() < thePartIndex )
1046     return UNKNOWN;
1047   return myBegPos( thePartIndex );
1048 }
1049
1050 //================================================================================
1051 /*!
1052  * \brief Store starting position of a part of python command
1053   * \param thePartIndex - The index of command part
1054   * \param thePosition - Part position
1055  */
1056 //================================================================================
1057
1058 void _pyCommand::SetBegPos( int thePartIndex, int thePosition )
1059 {
1060   while ( myBegPos.Length() < thePartIndex )
1061     myBegPos.Append( UNKNOWN );
1062   myBegPos( thePartIndex ) = thePosition;
1063 }
1064
1065 //================================================================================
1066 /*!
1067  * \brief Return substring of python command looking like ResultValue = Obj.Meth()
1068   * \retval const TCollection_AsciiString & - ResultValue substring
1069  */
1070 //================================================================================
1071
1072 const TCollection_AsciiString & _pyCommand::GetResultValue()
1073 {
1074   if ( GetBegPos( RESULT_IND ) == UNKNOWN )
1075   {
1076     int begPos = myString.Location( "=", 1, Length() );
1077     if ( begPos )
1078       myRes = GetWord( myString, begPos, false );
1079     else
1080       begPos = EMPTY;
1081     SetBegPos( RESULT_IND, begPos );
1082   }
1083   return myRes;
1084 }
1085
1086 //================================================================================
1087 /*!
1088  * \brief Return substring of python command looking like ResVal = Object.Meth()
1089   * \retval const TCollection_AsciiString & - Object substring
1090  */
1091 //================================================================================
1092
1093 const TCollection_AsciiString & _pyCommand::GetObject()
1094 {
1095   if ( GetBegPos( OBJECT_IND ) == UNKNOWN )
1096   {
1097     // beginning
1098     int begPos = GetBegPos( RESULT_IND ) + myRes.Length();
1099     if ( begPos < 1 )
1100       begPos = myString.Location( "=", 1, Length() ) + 1;
1101     // store
1102     myObj = GetWord( myString, begPos, true );
1103     SetBegPos( OBJECT_IND, begPos );
1104   }
1105   //SCRUTE(myObj);
1106   return myObj;
1107 }
1108
1109 //================================================================================
1110 /*!
1111  * \brief Return substring of python command looking like ResVal = Obj.Method()
1112   * \retval const TCollection_AsciiString & - Method substring
1113  */
1114 //================================================================================
1115
1116 const TCollection_AsciiString & _pyCommand::GetMethod()
1117 {
1118   if ( GetBegPos( METHOD_IND ) == UNKNOWN )
1119   {
1120     // beginning
1121     int begPos = GetBegPos( OBJECT_IND ) + myObj.Length();
1122     bool forward = true;
1123     if ( begPos < 1 ) {
1124       begPos = myString.Location( "(", 1, Length() ) - 1;
1125       forward = false;
1126     }
1127     // store
1128     myMeth = GetWord( myString, begPos, forward );
1129     SetBegPos( METHOD_IND, begPos );
1130   }
1131   //SCRUTE(myMeth);
1132   return myMeth;
1133 }
1134
1135 //================================================================================
1136 /*!
1137  * \brief Return substring of python command looking like ResVal = Obj.Meth(Arg1,...)
1138   * \retval const TCollection_AsciiString & - Arg<index> substring
1139  */
1140 //================================================================================
1141
1142 const TCollection_AsciiString & _pyCommand::GetArg( int index )
1143 {
1144   if ( GetBegPos( ARG1_IND ) == UNKNOWN )
1145   {
1146     // find all args
1147     int begPos = GetBegPos( METHOD_IND ) + myMeth.Length();
1148     if ( begPos < 1 )
1149       begPos = myString.Location( "(", 1, Length() ) + 1;
1150
1151     int i = 0, prevLen = 0;
1152     while ( begPos != EMPTY ) {
1153       begPos += prevLen;
1154       // check if we are looking at the closing parenthesis
1155       while ( begPos <= Length() && isspace( myString.Value( begPos )))
1156         ++begPos;
1157       if ( begPos > Length() || myString.Value( begPos ) == ')' )
1158         break;
1159       myArgs.Append( GetWord( myString, begPos, true, true ));
1160       SetBegPos( ARG1_IND + i, begPos );
1161       prevLen = myArgs.Last().Length();
1162       if ( prevLen == 0 )
1163         myArgs.Remove( myArgs.Length() ); // no more args
1164       i++;
1165     }
1166   }
1167   if ( myArgs.Length() < index )
1168     return theEmptyString;
1169   return myArgs( index );
1170 }
1171
1172 //================================================================================
1173 /*!
1174  * \brief Check if char is a word part
1175   * \param c - The character to check
1176   * \retval bool - The check result
1177  */
1178 //================================================================================
1179
1180 static inline bool isWord(const char c, const bool dotIsWord)
1181 {
1182   return
1183     !isspace(c) && c != ',' && c != '=' && c != ')' && c != '(' && ( dotIsWord || c != '.');
1184 }
1185
1186 //================================================================================
1187 /*!
1188  * \brief Looks for a word in the string and returns word's beginning
1189   * \param theString - The input string
1190   * \param theStartPos - The position to start the search, returning word's beginning
1191   * \param theForward - The search direction
1192   * \retval TCollection_AsciiString - The found word
1193  */
1194 //================================================================================
1195
1196 TCollection_AsciiString _pyCommand::GetWord( const TCollection_AsciiString & theString,
1197                                             int &      theStartPos,
1198                                             const bool theForward,
1199                                             const bool dotIsWord )
1200 {
1201   int beg = theStartPos, end = theStartPos;
1202   theStartPos = EMPTY;
1203   if ( beg < 1 || beg > theString.Length() )
1204     return theEmptyString;
1205
1206   if ( theForward ) { // search forward
1207     // beg
1208     while ( beg <= theString.Length() && !isWord( theString.Value( beg ), dotIsWord))
1209       ++beg;
1210     if ( beg > theString.Length() )
1211       return theEmptyString; // no word found
1212     // end
1213     end = beg + 1;
1214     while ( end <= theString.Length() && isWord( theString.Value( end ), dotIsWord))
1215       ++end;
1216     --end;
1217   }
1218   else {  // search backward
1219     // end
1220     while ( end > 0 && !isWord( theString.Value( end ), dotIsWord))
1221       --end;
1222     if ( end == 0 )
1223       return theEmptyString; // no word found
1224     beg = end - 1;
1225     while ( beg > 0 && isWord( theString.Value( beg ), dotIsWord))
1226       --beg;
1227     ++beg;
1228   }
1229   theStartPos = beg;
1230   //cout << theString << " ---- " << beg << " - " << end << endl;
1231   return theString.SubString( beg, end );
1232 }
1233
1234 //================================================================================
1235 /*!
1236  * \brief Look for position where not space char is
1237   * \param theString - The string 
1238   * \param thePos - The position to search from and which returns result
1239   * \retval bool - false if there are only space after thePos in theString
1240  * 
1241  * 
1242  */
1243 //================================================================================
1244
1245 bool _pyCommand::SkipSpaces( const TCollection_AsciiString & theString, int & thePos )
1246 {
1247   if ( thePos < 1 || thePos > theString.Length() )
1248     return false;
1249
1250   while ( thePos <= theString.Length() && isspace( theString.Value( thePos )))
1251     ++thePos;
1252
1253   return thePos <= theString.Length();
1254 }
1255
1256 //================================================================================
1257 /*!
1258  * \brief Modify a part of the command
1259   * \param thePartIndex - The index of the part
1260   * \param thePart - The new part string
1261   * \param theOldPart - The old part
1262  */
1263 //================================================================================
1264
1265 void _pyCommand::SetPart(int thePartIndex, const TCollection_AsciiString& thePart,
1266                         TCollection_AsciiString& theOldPart)
1267 {
1268   int pos = GetBegPos( thePartIndex );
1269   if ( pos <= Length() && theOldPart != thePart)
1270   {
1271     TCollection_AsciiString seperator;
1272     if ( pos < 1 ) {
1273       pos = GetBegPos( thePartIndex + 1 );
1274       if ( pos < 1 ) return;
1275       switch ( thePartIndex ) {
1276       case RESULT_IND: seperator = " = "; break;
1277       case OBJECT_IND: seperator = "."; break;
1278       case METHOD_IND: seperator = "()"; break;
1279       default:;
1280       }
1281     }      
1282     myString.Remove( pos, theOldPart.Length() );
1283     if ( !seperator.IsEmpty() )
1284       myString.Insert( pos , seperator );
1285     myString.Insert( pos, thePart );
1286     // update starting positions of the following parts
1287     int posDelta = thePart.Length() + seperator.Length() - theOldPart.Length();
1288     for ( int i = thePartIndex + 1; i <= myBegPos.Length(); ++i ) {
1289       if ( myBegPos( i ) > 0 )
1290         myBegPos( i ) += posDelta;
1291     }
1292     theOldPart = thePart;
1293   }
1294 }
1295
1296 //================================================================================
1297 /*!
1298  * \brief Set agrument
1299   * \param index - The argument index, it counts from 1
1300   * \param theArg - The argument string
1301  */
1302 //================================================================================
1303
1304 void _pyCommand::SetArg( int index, const TCollection_AsciiString& theArg)
1305 {
1306   FindAllArgs();
1307   int argInd = ARG1_IND + index - 1;
1308   int pos = GetBegPos( argInd );
1309   if ( pos < 1 ) // no index-th arg exist, append inexistent args
1310   {
1311     // find a closing parenthesis
1312     pos = Length();
1313     while ( pos > 0 && myString.Value( pos ) != ')' )
1314       --pos;
1315     if ( pos == 0 ) { // no parentheses at all
1316       myString += "()";
1317       pos = Length();
1318     }
1319     while ( myArgs.Length() < index ) {
1320       if ( myArgs.Length() )
1321         myString.Insert( pos++, "," );
1322       myArgs.Append("None");
1323       myString.Insert( pos, myArgs.Last() );
1324       SetBegPos( ARG1_IND + myArgs.Length() - 1, pos );
1325       pos += myArgs.Last().Length();
1326     }
1327   }
1328   SetPart( argInd, theArg, myArgs( index ));
1329 }
1330
1331 //================================================================================
1332 /*!
1333  * \brief Empty arg list
1334  */
1335 //================================================================================
1336
1337 void _pyCommand::RemoveArgs()
1338 {
1339   if ( int pos = myString.Location( '(', 1, Length() ))
1340     myString.Trunc( pos );
1341   myString += ")";
1342   myArgs.Clear();
1343   if ( myBegPos.Length() >= ARG1_IND )
1344     myBegPos.Remove( ARG1_IND, myBegPos.Length() );
1345 }
1346
1347 //================================================================================
1348 /*!
1349  * \brief Set dependent commands after this one
1350  */
1351 //================================================================================
1352
1353 bool _pyCommand::SetDependentCmdsAfter() const
1354 {
1355   bool orderChanged = false;
1356   list< Handle(_pyCommand)>::const_reverse_iterator cmd = myDependentCmds.rbegin();
1357   for ( ; cmd != myDependentCmds.rend(); ++cmd ) {
1358     if ( (*cmd)->GetOrderNb() < GetOrderNb() ) {
1359       orderChanged = true;
1360       theGen->SetCommandAfter( *cmd, this );
1361       (*cmd)->SetDependentCmdsAfter();
1362     }
1363   }
1364   return orderChanged;
1365 }
1366 //================================================================================
1367 /*!
1368  * \brief Insert accessor method after theObjectID
1369   * \param theObjectID - id of the accessed object
1370   * \param theAcsMethod - name of the method giving access to the object
1371   * \retval bool - false if theObjectID is not found in the command string
1372  */
1373 //================================================================================
1374
1375 bool _pyCommand::AddAccessorMethod( _pyID theObjectID, const char* theAcsMethod )
1376 {
1377   if ( !theAcsMethod )
1378     return false;
1379   // start object search from the object, i.e. ignore result
1380   GetObject();
1381   int beg = GetBegPos( OBJECT_IND );
1382   if ( beg < 1 || beg > Length() )
1383     return false;
1384   while (( beg = myString.Location( theObjectID, beg, Length() )))
1385   {
1386     // check that theObjectID is not just a part of a longer ID
1387     int afterEnd = beg + theObjectID.Length();
1388     Standard_Character c = myString.Value( afterEnd );
1389     if ( !isalnum( c ) && c != ':' ) {
1390       // insertion
1391       int oldLen = Length();
1392       myString.Insert( afterEnd, (char*) theAcsMethod );
1393       myString.Insert( afterEnd, "." );
1394       // update starting positions of the parts following the modified one
1395       int posDelta = Length() - oldLen;
1396       for ( int i = 1; i <= myBegPos.Length(); ++i ) {
1397         if ( myBegPos( i ) > afterEnd )
1398           myBegPos( i ) += posDelta;
1399       }
1400       return true;
1401     }
1402     beg = afterEnd; // is a part - next search
1403   }
1404   return false;
1405 }
1406
1407 //================================================================================
1408 /*!
1409  * \brief Return method name giving access to an interaface object wrapped by python class
1410   * \retval const char* - method name
1411  */
1412 //================================================================================
1413
1414 const char* _pyObject::AccessorMethod() const
1415 {
1416   return 0;
1417 }