Salome HOME
Fix for the bug IPAL22164: Fatal error during save/load a SMESH study
[modules/kernel.git] / src / SALOMEDSImpl / SALOMEDSImpl_Study.cxx
1 //  Copyright (C) 2007-2010  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 //  Copyright (C) 2003-2007  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.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 //  File   : SALOMEDSImpl_Study.cxx
24 //  Author : Sergey RUIN
25 //  Module : SALOME
26 //
27 #include "SALOMEDSImpl_Study.hxx"
28 #include <string.h>
29
30 #include <KERNEL_version.h>
31 #include <Basics_Utils.hxx>
32
33 #include "DF_Application.hxx"
34 #include "DF_ChildIterator.hxx"
35
36 #include "SALOMEDSImpl_ChildNodeIterator.hxx"
37 #include "SALOMEDSImpl_Attributes.hxx"
38 #include "SALOMEDSImpl_UseCaseIterator.hxx"
39 #include "SALOMEDSImpl_AttributeReference.hxx"
40 #include "SALOMEDSImpl_StudyHandle.hxx"
41 #include "SALOMEDSImpl_Tool.hxx"
42 #include "SALOMEDSImpl_IParameters.hxx"
43 #include "SALOMEDSImpl_ScalarVariable.hxx"
44
45 #include <fstream>
46 #include <sstream>
47
48 #define DIRECTORYID       16661
49 #define FILELOCALID       26662
50 #define FILEID            "FILE: "
51 #define VARIABLE_SEPARATOR  ':'
52 #define OPERATION_SEPARATOR '|'
53
54 //============================================================================
55 /*! Function : SALOMEDSImpl_Study
56  *  Purpose  : SALOMEDSImpl_Study constructor
57  */
58 //============================================================================
59 SALOMEDSImpl_Study::SALOMEDSImpl_Study(const DF_Document* doc,
60                                        const std::string& study_name)
61 {
62   _name = study_name;
63   _doc = (DF_Document*)doc;
64   _Saved = false ;
65   _URL = "";
66   _StudyId = -1;
67   _autoFill = false;
68   _errorCode = "";
69   _useCaseBuilder = new SALOMEDSImpl_UseCaseBuilder(_doc);
70   _builder = new SALOMEDSImpl_StudyBuilder(this);
71   _cb = new SALOMEDSImpl_Callback(_useCaseBuilder);
72   _notifier=0;
73   //Put on the root label a StudyHandle attribute to store the address of this object
74   //It will be used to retrieve the study object by DF_Label that belongs to the study
75   SALOMEDSImpl_StudyHandle::Set(_doc->Main().Root(), this);
76 }
77
78
79 //============================================================================
80 /*! Function : ~SALOMEDSImpl_Study
81  *  Purpose  : SALOMEDSImpl_Study destructor
82  */
83 //============================================================================
84 SALOMEDSImpl_Study::~SALOMEDSImpl_Study()
85 {
86   delete _builder;
87   delete _cb;
88   delete _useCaseBuilder;
89 }
90
91 //============================================================================
92 /*! Function : GetPersistentReference
93  *  Purpose  : Get persistent reference of study (idem URL())
94  */
95 //============================================================================
96 std::string SALOMEDSImpl_Study::GetPersistentReference()
97 {
98   _errorCode = "";
99   return URL();
100 }
101 //============================================================================
102 /*! Function : GetTransientReference
103  *  Purpose  : Get IOR of the Study (registred in Document in doc->Root)
104  */
105 //============================================================================
106 std::string SALOMEDSImpl_Study::GetTransientReference()
107 {
108   _errorCode = "";
109   std::string IOR = "";
110
111   SALOMEDSImpl_AttributeIOR* Att;
112   DF_Label _lab = _doc->Root();
113   if ((Att=(SALOMEDSImpl_AttributeIOR*)_lab.FindAttribute(SALOMEDSImpl_AttributeIOR::GetID()))) {
114     IOR = Att->Value();
115   }
116   else {
117     _errorCode = "IOR is empty";
118   }
119
120   return IOR;
121 }
122
123 void SALOMEDSImpl_Study::SetTransientReference(const std::string& theIOR)
124 {
125   _errorCode = "";
126
127   SALOMEDSImpl_AttributeStudyProperties* aProp = GetProperties();
128   int aLocked = aProp->IsLocked();
129   if (aLocked) aProp->SetLocked(false);
130
131   // Assign the value of the IOR in the study->root
132   SALOMEDSImpl_AttributeIOR::Set(_doc->Main().Root(), theIOR);
133
134   if (aLocked) aProp->SetLocked(true);
135 }
136
137 //============================================================================
138 /*! Function : IsEmpty
139  *  Purpose  : Detect if study is empty
140  */
141 //============================================================================
142 bool SALOMEDSImpl_Study::IsEmpty()
143 {
144   _errorCode = "";
145   if (!_doc) return true;
146   return _doc->IsEmpty();
147 }
148
149 //============================================================================
150 /*! Function : FindComponent
151  *  Purpose  : Find a Component with ComponentDataType = aComponentName
152  */
153 //============================================================================
154 SALOMEDSImpl_SComponent SALOMEDSImpl_Study::FindComponent (const std::string& aComponentName)
155 {
156   _errorCode = "";
157   bool _find = false;
158   std::string name;
159   SALOMEDSImpl_SComponentIterator itcomp = NewComponentIterator();
160   SALOMEDSImpl_SComponent compo;
161
162   for (; itcomp.More(); itcomp.Next()) {
163     SALOMEDSImpl_SComponent SC = itcomp.Value();
164     name = SC.ComponentDataType();
165     if(aComponentName == name) {
166       _find = true;
167       return SC;
168     }
169   }
170
171   if(!_find)
172     {
173       _errorCode = "No component was found";
174       return compo;
175     }
176   return compo;
177 }
178
179 //============================================================================
180 /*! Function : FindComponentID
181  *  Purpose  : Find a Component from it's ID
182  */
183 //============================================================================
184 SALOMEDSImpl_SComponent SALOMEDSImpl_Study::FindComponentID(const std::string& aComponentID)
185 {
186   _errorCode = "";
187
188   // Iterate on each components defined in the study
189   // Get the component ID and compare with aComponentID
190   bool _find = false;
191   std::string ID;
192   SALOMEDSImpl_SComponent compo;
193
194   SALOMEDSImpl_SComponentIterator itcomp = NewComponentIterator();
195   for (; itcomp.More(); itcomp.Next()) {
196     SALOMEDSImpl_SComponent SC = itcomp.Value();
197     ID = SC.GetID();
198     if(aComponentID == ID)
199       {
200         // ComponentID found
201         _find = true;
202         compo = SC;
203       }
204   }
205   if(!_find)
206     {
207       _errorCode = "No component was found";
208       compo = compo;
209     }
210
211   return compo;
212 }
213
214 //============================================================================
215 /*! Function : FindObject
216  *  Purpose  : Find an Object with SALOMEDSImpl_Name = anObjectName
217  */
218 //============================================================================
219 SALOMEDSImpl_SObject SALOMEDSImpl_Study::FindObject(const std::string& anObjectName)
220 {
221   _errorCode = "";
222
223   // Iterate to all components defined in the study
224   // After testing the component name, iterate in all objects defined under
225   // components (function _FindObject)
226   bool _find = false;
227   SALOMEDSImpl_SObject RefSO;
228
229   SALOMEDSImpl_SComponentIterator it = NewComponentIterator();
230   for (; it.More();it.Next()){
231     if(!_find)
232       {
233         SALOMEDSImpl_SComponent SC = it.Value();
234         if (SC.GetName() == anObjectName)
235         {
236             _find = true;
237             RefSO = SC;
238
239         }
240         if (!_find) RefSO =  _FindObject(SC, anObjectName, _find);
241       }
242   }
243   if(!RefSO) _errorCode = "No object was found";
244   return RefSO;
245 }
246
247 //============================================================================
248 /*! Function : FindObjectID
249  *  Purpose  : Find an Object with ID = anObjectID
250  */
251 //============================================================================
252 SALOMEDSImpl_SObject SALOMEDSImpl_Study::FindObjectID(const std::string& anObjectID)
253 {
254   _errorCode = "";
255   SALOMEDSImpl_SObject so;
256
257   // Convert aSO->GetID in DF_Label.
258   DF_Label Lab = DF_Label::Label(_doc->Main(), anObjectID, false);
259
260   if (Lab.IsNull()) {
261     _errorCode = "No label was found by ID";
262     return so;
263   }
264   return GetSObject(Lab);
265
266 }
267
268 //============================================================================
269 /*! Function : CreateObjectID
270  *  Purpose  : Creates an Object with ID = anObjectID
271  */
272 //============================================================================
273 SALOMEDSImpl_SObject SALOMEDSImpl_Study::CreateObjectID(const std::string& anObjectID)
274 {
275   _errorCode = "";
276   SALOMEDSImpl_SObject so;
277
278   // Convert aSO->GetID in DF_Label.
279   DF_Label Lab = DF_Label::Label(_doc->Main(), anObjectID, true);
280
281   if (Lab.IsNull()) {
282     _errorCode = "Can not create a label";
283     return so;
284   }
285   return GetSObject(Lab);
286
287 }
288
289 //============================================================================
290 /*! Function : FindObjectByName
291  *  Purpose  : Find Objects with SALOMEDSImpl_Name = anObjectName in a Component
292  *           : with ComponentDataType = aComponentName
293  */
294 //============================================================================
295 std::vector<SALOMEDSImpl_SObject> SALOMEDSImpl_Study::FindObjectByName(const std::string& anObjectName,
296                                                                        const std::string& aComponentName)
297 {
298   _errorCode = "";
299
300   std::vector<SALOMEDSImpl_SObject> listSO;
301
302   SALOMEDSImpl_SComponent compo = FindComponent(aComponentName) ;
303   if ( !compo ) {
304     _errorCode = "Can not find the component";
305     return listSO;
306   }
307
308   // Iterate on each object and subobject of the component
309   // If objectName is found add it to the list of SObjects
310   std::string childName ;
311
312   std::string compoId = compo.GetID();
313   SALOMEDSImpl_ChildIterator it = NewChildIterator(compo);
314   for ( ; it.More(); it.Next() ) {
315
316     SALOMEDSImpl_SObject CSO = it.Value();
317     if ( CSO.GetName() == anObjectName ) {
318         /* add to list */
319         listSO.push_back(CSO) ;
320     }
321
322     /* looks also for eventual children */
323     bool found = false ;
324     CSO = _FindObject( CSO, anObjectName, found ) ;
325     if( found) {
326       listSO.push_back(CSO) ;
327     }
328   }
329
330   return listSO;
331 }
332
333
334
335 //============================================================================
336 /*! Function : FindObjectIOR
337  *  Purpose  : Find an Object with IOR = anObjectIOR
338  */
339 //============================================================================
340 SALOMEDSImpl_SObject SALOMEDSImpl_Study::FindObjectIOR(const std::string& anObjectIOR)
341 {
342   _errorCode = "";
343
344   SALOMEDSImpl_SObject aResult ;
345
346   // searching in the datamap for optimization
347   std::map<std::string, DF_Label>::iterator it=myIORLabels.find(anObjectIOR);
348   if (it != myIORLabels.end()) {
349     aResult = GetSObject(it->second);
350     // 11 oct 2002: forbidden attributes must be checked here
351     if (!aResult.GetLabel().IsAttribute(SALOMEDSImpl_AttributeIOR::GetID())) {
352       myIORLabels.erase(anObjectIOR);
353       aResult = SALOMEDSImpl_SObject();
354     }
355   }
356
357   if(!aResult) _errorCode = "No object was found";
358   return aResult;
359 }
360
361 //============================================================================
362 /*! Function : FindObjectByPath
363  *  Purpose  : Find an Object by its path = thePath
364  */
365 //============================================================================
366 SALOMEDSImpl_SObject SALOMEDSImpl_Study::FindObjectByPath(const std::string& thePath)
367 {
368   _errorCode = "";
369
370   std::string aPath(thePath), aToken;
371   SALOMEDSImpl_SObject aSO;
372   int aLength = aPath.size();
373   bool isRelative = false;
374
375   if(aLength == 0) {  //Empty path - return the current context
376     return GetSObject(_current);
377   }
378
379   if(aPath[0] != '/')  //Relative path
380     isRelative = true;
381
382   DF_ChildIterator anIterator;
383   DF_Label aLabel;
384   SALOMEDSImpl_AttributeName* anAttr;
385
386   if(isRelative) {
387     if(_current.IsNull()) return aSO;
388     anIterator.Init(_current, false);
389   }
390   else {
391     if(aPath.size() == 1 && aPath[0] == '/') {    //Root
392       return GetSObject(_doc->Main());
393     }
394     anIterator.Init(_doc->Main(), false);
395   }
396
397   std::vector<std::string> vs = SALOMEDSImpl_Tool::splitString(aPath, '/');
398   for(int i = 0, len = vs.size(); i<len; i++) {
399
400     aToken = vs[i];
401     if(aToken.size() == 0) break;
402
403     for ( ; anIterator.More(); anIterator.Next() ) {
404       aLabel = anIterator.Value();
405       if((anAttr=(SALOMEDSImpl_AttributeName*)aLabel.FindAttribute(SALOMEDSImpl_AttributeName::GetID()))) {
406         if(anAttr->Value() == aToken) {
407           if(i == (len-1)) {  //The searched label is found (no part of the path is left)
408               return GetSObject(aLabel);
409           }
410
411           anIterator.Init(aLabel, false);
412           break;
413         }
414       }
415     }
416
417   }
418
419   if(!aSO) _errorCode = "No object was found";
420   return aSO;
421 }
422
423 //============================================================================
424 /*! Function : GetObjectPath
425  *  Purpose  :
426  */
427 //============================================================================
428 std::string SALOMEDSImpl_Study::GetObjectPath(const SALOMEDSImpl_SObject& theObject)
429 {
430   _errorCode = "";
431
432   std::string aPath("");
433   if(!theObject) {
434     _errorCode = "Null object";
435     return aPath;
436   }
437
438   std::string aName = theObject.GetName();
439   if(!aName.empty() && aName != "" ) {
440     std::string aValue("/");
441     aValue+=aName;
442     aValue += aPath;
443     aPath = aValue;
444     SALOMEDSImpl_SObject aFather = theObject.GetFather();
445     if(aFather) {
446        aName = aFather.GetName();
447        if(!aName.empty() && aName != "") {
448            aValue = GetObjectPath(aFather);
449           aPath = aValue + aPath;
450        }
451     }
452   }
453
454   return aPath;
455 }
456
457
458 //============================================================================
459 /*! Function : GetObjectPathByIOR
460  *  Purpose  :
461  */
462 //============================================================================
463 std::string SALOMEDSImpl_Study::GetObjectPathByIOR(const std::string& theIOR)
464 {
465   _errorCode = "";
466
467   std::string aPath;
468   SALOMEDSImpl_SObject so = FindObjectIOR(theIOR);
469   if(!so) {
470     _errorCode = "No SObject was found by IOR";
471     return aPath;
472   }
473
474   return GetObjectPath(so);
475 }
476
477
478 //============================================================================
479 /*! Function : SetContext
480  *  Purpose  : Sets the current context
481  */
482 //============================================================================
483 bool SALOMEDSImpl_Study::SetContext(const std::string& thePath)
484 {
485   _errorCode = "";
486   if(thePath.empty()) {
487     _errorCode = "InvalidPath";
488     return false;
489   }
490
491   std::string aPath(thePath), aContext("");
492   bool isInvalid = false;
493   SALOMEDSImpl_SObject aSO;
494
495   if(aPath[0] != '/') { //Relative path
496     aContext = GetContext();
497     aContext += '/';
498     aContext += aPath;
499   }
500   else
501     aContext = aPath;
502
503   try {
504     aSO = FindObjectByPath(aContext);
505   }
506   catch( ... ) {
507     isInvalid = true;
508   }
509
510   if(isInvalid || !aSO) {
511     _errorCode = "InvalidContext";
512     return false;
513   }
514
515   DF_Label aLabel = aSO.GetLabel();
516   if(aLabel.IsNull()) {
517     _errorCode = "InvalidContext";
518     return false;
519   }
520   else
521     _current = aLabel;  //Set the current context
522
523   return true;
524 }
525
526 //============================================================================
527 /*! Function : GetContext
528  *  Purpose  : Gets the current context
529  */
530 //============================================================================
531 std::string SALOMEDSImpl_Study::GetContext()
532 {
533   _errorCode = "";
534
535   if(_current.IsNull()) {
536     _errorCode = "InvaidContext";
537     return "";
538   }
539   SALOMEDSImpl_SObject so = GetSObject(_current);
540   return GetObjectPath(so);
541 }
542
543 //============================================================================
544 /*! Function : GetObjectNames
545  *  Purpose  : method to get all object names in the given context (or in the current context, if 'theContext' is empty)
546  */
547 //============================================================================
548 std::vector<std::string> SALOMEDSImpl_Study::GetObjectNames(const std::string& theContext)
549 {
550   _errorCode = "";
551
552   std::vector<std::string> aResultSeq;
553   DF_Label aLabel;
554   if (theContext.empty()) {
555     aLabel = _current;
556   } else {
557     DF_Label aTmp = _current;
558     SetContext(theContext);
559     aLabel = _current;
560     _current = aTmp;
561   }
562   if (aLabel.IsNull()) {
563     _errorCode = "InvalidContext";
564     return aResultSeq;
565   }
566
567   DF_ChildIterator anIter (aLabel, true); // iterate all subchildren at all sublevels
568   for (; anIter.More(); anIter.Next()) {
569     DF_Label aLabel = anIter.Value();
570     SALOMEDSImpl_AttributeName* aName;
571     if ((aName=(SALOMEDSImpl_AttributeName*)aLabel.FindAttribute(SALOMEDSImpl_AttributeName::GetID())))
572       aResultSeq.push_back(aName->Value());
573   }
574
575   return aResultSeq;
576 }
577
578 //============================================================================
579 /*! Function : GetDirectoryNames
580  *  Purpose  : method to get all directory names in the given context (or in the current context, if 'theContext' is empty)
581  */
582 //============================================================================
583 std::vector<std::string> SALOMEDSImpl_Study::GetDirectoryNames(const std::string& theContext)
584 {
585   _errorCode = "";
586
587   std::vector<std::string> aResultSeq;
588   DF_Label aLabel;
589   if (theContext.empty()) {
590     aLabel = _current;
591   } else {
592     DF_Label aTmp = _current;
593     SetContext(theContext);
594     aLabel = _current;
595     _current = aTmp;
596   }
597   if (aLabel.IsNull()) {
598     _errorCode = "InvalidContext";
599     return aResultSeq;
600   }
601
602   DF_ChildIterator anIter (aLabel, true); // iterate first-level children at all sublevels
603   for (; anIter.More(); anIter.Next()) {
604     DF_Label aLabel = anIter.Value();
605     SALOMEDSImpl_AttributeLocalID* anID;
606     if ((anID=(SALOMEDSImpl_AttributeLocalID*)aLabel.FindAttribute(SALOMEDSImpl_AttributeLocalID::GetID()))) {
607       if (anID->Value() == DIRECTORYID) {
608         SALOMEDSImpl_AttributeName* aName;
609         if ((aName=(SALOMEDSImpl_AttributeName*)aLabel.FindAttribute(SALOMEDSImpl_AttributeName::GetID()))) {
610           aResultSeq.push_back(aName->Value());
611         }
612       }
613     }
614   }
615
616   return aResultSeq;
617 }
618
619 //============================================================================
620 /*! Function : GetFileNames
621  *  Purpose  : method to get all file names in the given context (or in the current context, if 'theContext' is empty)
622  */
623 //============================================================================
624 std::vector<std::string> SALOMEDSImpl_Study::GetFileNames(const std::string& theContext)
625 {
626   _errorCode = "";
627
628   std::vector<std::string> aResultSeq;
629   DF_Label aLabel;
630   if (theContext.empty()) {
631     aLabel = _current;
632   } else {
633     DF_Label aTmp = _current;
634     SetContext(theContext);
635     aLabel = _current;
636     _current = aTmp;
637   }
638   if (aLabel.IsNull()) {
639     _errorCode = "InvalidContext";
640     return aResultSeq;
641   }
642
643   DF_ChildIterator anIter (aLabel, true); // iterate all subchildren at all sublevels
644   for (; anIter.More(); anIter.Next()) {
645     DF_Label aLabel = anIter.Value();
646     SALOMEDSImpl_AttributeLocalID* anID;
647     if ((anID=(SALOMEDSImpl_AttributeLocalID*)aLabel.FindAttribute(SALOMEDSImpl_AttributeLocalID::GetID()))) {
648       if (anID->Value() == FILELOCALID) {
649         SALOMEDSImpl_AttributePersistentRef* aName;
650         if ((aName=(SALOMEDSImpl_AttributePersistentRef*)aLabel.FindAttribute(SALOMEDSImpl_AttributePersistentRef::GetID()))) {
651           std::string aFileName = aName->Value();
652           if (aFileName.size() > 0)
653             aResultSeq.push_back(aFileName.substr(strlen(FILEID), aFileName.size()));
654         }
655       }
656     }
657   }
658
659   return aResultSeq;
660 }
661
662 //============================================================================
663 /*! Function : GetComponentNames
664  *  Purpose  : method to get all components names
665  */
666 //============================================================================
667 std::vector<std::string> SALOMEDSImpl_Study::GetComponentNames(const std::string& theContext)
668 {
669   _errorCode = "";
670
671   std::vector<std::string> aResultSeq;
672   DF_ChildIterator anIter(_doc->Main(), false); // iterate all subchildren at first level
673   for(; anIter.More(); anIter.Next()) {
674     DF_Label aLabel = anIter.Value();
675     SALOMEDSImpl_AttributeName* aName;
676     if ((aName=(SALOMEDSImpl_AttributeName*)aLabel.FindAttribute(SALOMEDSImpl_AttributeName::GetID())))
677       aResultSeq.push_back(aName->Value());
678   }
679
680   return aResultSeq;
681 }
682
683 //============================================================================
684 /*! Function : NewChildIterator
685  *  Purpose  : Create a ChildIterator from an SObject
686  */
687 //============================================================================
688 SALOMEDSImpl_ChildIterator SALOMEDSImpl_Study::NewChildIterator(const SALOMEDSImpl_SObject& aSO)
689 {
690   _errorCode = "";
691   return SALOMEDSImpl_ChildIterator(aSO);
692 }
693
694
695 //============================================================================
696 /*! Function : NewComponentIterator
697  *  Purpose  : Create a SComponentIterator
698  */
699 //============================================================================
700 SALOMEDSImpl_SComponentIterator SALOMEDSImpl_Study::NewComponentIterator()
701 {
702   _errorCode = "";
703   return SALOMEDSImpl_SComponentIterator(_doc);
704 }
705
706
707 //============================================================================
708 /*! Function : NewBuilder
709  *  Purpose  : Create a StudyBuilder
710  */
711 //============================================================================
712 SALOMEDSImpl_StudyBuilder* SALOMEDSImpl_Study::NewBuilder()
713 {
714   _errorCode = "";
715   if(_autoFill) {
716     _builder->SetOnAddSObject(_cb);
717     _builder->SetOnRemoveSObject(_cb);
718   }
719   return _builder;
720
721 }
722
723 //============================================================================
724 /*! Function : Name
725  *  Purpose  : get study name
726  */
727 //============================================================================
728 std::string SALOMEDSImpl_Study::Name()
729 {
730   _errorCode = "";
731   return _name;
732 }
733
734 //============================================================================
735 /*! Function : Name
736  *  Purpose  : set study name
737  */
738 //============================================================================
739 void SALOMEDSImpl_Study::Name(const std::string& name)
740 {
741   _errorCode = "";
742   _name = name;
743 }
744
745 //============================================================================
746 /*! Function : IsSaved
747  *  Purpose  : get if study has been saved
748  */
749 //============================================================================
750 bool SALOMEDSImpl_Study::IsSaved()
751 {
752   _errorCode = "";
753   return _Saved;
754 }
755
756 //============================================================================
757 /*! Function : IsSaved
758  *  Purpose  : set if study has been saved
759  */
760 //============================================================================
761 void SALOMEDSImpl_Study::IsSaved(bool save)
762 {
763   _errorCode = "";
764   _Saved = save;
765   if(save) _doc->SetModified(false);
766 }
767
768 //============================================================================
769 /*! Function : IsModified
770  *  Purpose  : Detect if a Study has been modified since it has been saved
771  */
772 //============================================================================
773 bool SALOMEDSImpl_Study::IsModified()
774 {
775   _errorCode = "";
776
777   // True if is modified
778   if (_doc && _doc->IsModified()) return true;
779
780   return false;
781 }
782
783 //============================================================================
784 /*! Function : URL
785  *  Purpose  : get URL of the study (persistent reference of the study)
786  */
787 //============================================================================
788 std::string SALOMEDSImpl_Study::URL()
789 {
790   _errorCode = "";
791   return _URL;
792 }
793
794 //============================================================================
795 /*! Function : URL
796  *  Purpose  : set URL of the study (persistent reference of the study)
797  */
798 //============================================================================
799 void SALOMEDSImpl_Study::URL(const std::string& url)
800 {
801   _errorCode = "";
802   _URL = url;
803
804   /*jfa: Now name of SALOMEDS study will correspond to name of SalomeApp study
805   std::string tmp(_URL);
806
807   char *aName = (char*)tmp.ToCString();
808   char *adr = strtok(aName, "/");
809   while (adr)
810     {
811       aName = adr;
812       adr = strtok(NULL, "/");
813     }
814   Name(aName);*/
815   Name(url);
816 }
817
818
819 //============================================================================
820 /*! Function : _FindObject
821  *  Purpose  : Find an Object with SALOMEDSImpl_Name = anObjectName
822  */
823 //============================================================================
824 SALOMEDSImpl_SObject SALOMEDSImpl_Study::_FindObject(const SALOMEDSImpl_SObject& SO,
825                                                      const std::string& theObjectName,
826                                                      bool& _find)
827 {
828   SALOMEDSImpl_SObject RefSO;
829   if(!SO) return RefSO;
830
831   // Iterate on each objects and subobjects of the component
832   // If objectName find, stop the loop and get the object reference
833   SALOMEDSImpl_AttributeName* anAttr;
834
835   std::string soid = SO.GetID();
836   DF_ChildIterator it(SO.GetLabel());
837   for (; it.More(); it.Next()){
838     if(!_find)
839       {
840         if ((anAttr=(SALOMEDSImpl_AttributeName*)it.Value().FindAttribute(SALOMEDSImpl_AttributeName::GetID())))
841         {
842           std::string Val(anAttr->Value());
843           if (Val == theObjectName)
844             {
845               RefSO = GetSObject(it.Value());
846               _find = true;
847             }
848         }
849         if (!_find) RefSO = _FindObject(GetSObject(it.Value()), theObjectName, _find);
850       }
851   }
852   return RefSO;
853 }
854
855 //============================================================================
856 /*! Function : _FindObjectIOR
857  *  Purpose  : Find an Object with SALOMEDSImpl_IOR = anObjectIOR
858  */
859 //============================================================================
860 SALOMEDSImpl_SObject
861 SALOMEDSImpl_Study::_FindObjectIOR(const SALOMEDSImpl_SObject& SO,
862                                    const std::string& theObjectIOR,
863                                    bool& _find)
864 {
865   SALOMEDSImpl_SObject RefSO, aSO;
866   if(!SO) return RefSO;
867
868   // Iterate on each objects and subobjects of the component
869   // If objectName find, stop the loop and get the object reference
870   SALOMEDSImpl_AttributeIOR* anAttr;
871
872   DF_ChildIterator it(SO.GetLabel());
873   for (; it.More();it.Next()){
874     if(!_find)
875       {
876         if ((anAttr=(SALOMEDSImpl_AttributeIOR*)it.Value().FindAttribute(SALOMEDSImpl_AttributeIOR::GetID())))
877         {
878           std::string Val(anAttr->Value());
879           if (Val == theObjectIOR)
880             {
881               RefSO = GetSObject(it.Value());
882               _find = true;
883             }
884         }
885         aSO = GetSObject(it.Value());
886         if (!_find) RefSO =  _FindObjectIOR(aSO, theObjectIOR, _find);
887       }
888   }
889   return RefSO;
890 }
891
892 //============================================================================
893 /*! Function : _GetNoteBookAccessor
894  *  Purpose  : Find an Object with SALOMEDSImpl_IOR = anObjectIOR
895  */
896 //============================================================================
897 std::string SALOMEDSImpl_Study::_GetNoteBookAccessor(){
898   return std::string("notebook");
899 }
900
901 //============================================================================
902 /*! Function : _GetStudyVariablesScript
903  *  Purpose  :
904  */
905 //============================================================================
906 std::string SALOMEDSImpl_Study::_GetStudyVariablesScript()
907 {
908   std::string dump("");
909
910   if(myNoteBookVars.empty())
911     return dump;
912
913   Kernel_Utils::Localizer loc;
914
915   dump += "####################################################\n";
916   dump += "##       Begin of NoteBook variables section      ##\n";
917   dump += "####################################################\n";
918
919   std::string set_method = _GetNoteBookAccessor()+".set(";
920   std::string varName;
921   std::string varValue;
922   for(int i = 0 ; i < myNoteBookVars.size();i++ ) {
923     varName = myNoteBookVars[i]->Name();
924     varValue = myNoteBookVars[i]->SaveToScript();
925     dump+=set_method+"\""+varName+"\", "+varValue+")\n";
926   }
927
928   dump += "####################################################\n";
929   dump += "##        End of NoteBook variables section       ##\n";
930   dump += "####################################################\n";
931
932   return dump;
933 }
934
935 //============================================================================
936 /*! Function : _GetNoteBookAccess
937  *  Purpose  :
938  */
939 //============================================================================
940 std::string SALOMEDSImpl_Study::_GetNoteBookAccess()
941 {
942   std::string accessor = _GetNoteBookAccessor();
943   std::string notebook = "import salome_notebook\n";
944   notebook += accessor+" = salome_notebook."+accessor + "\n";
945   return notebook;
946 }
947
948 bool SALOMEDSImpl_Study::IsLocked()
949 {
950   _errorCode = "";
951   return GetProperties()->IsLocked();
952 }
953
954 int SALOMEDSImpl_Study::StudyId()
955 {
956   _errorCode = "";
957   return _StudyId;
958 }
959
960 void SALOMEDSImpl_Study::StudyId(int id)
961 {
962   _errorCode = "";
963   _StudyId = id;
964 }
965
966 void SALOMEDSImpl_Study::UpdateIORLabelMap(const std::string& anIOR,const std::string& anEntry)
967 {
968   _errorCode = "";
969   DF_Label aLabel = DF_Label::Label(_doc->Main(), anEntry, true);
970   std::map<std::string, DF_Label>::iterator it=myIORLabels.find(anIOR);
971   if (it != myIORLabels.end()) myIORLabels.erase(it);
972   myIORLabels[anIOR] = aLabel;
973 }
974
975 void SALOMEDSImpl_Study::DeleteIORLabelMapItem(const std::string& anIOR)
976 {
977   std::map<std::string, DF_Label>::iterator it=myIORLabels.find(anIOR);
978   if (it != myIORLabels.end())
979     {
980       //remove the ior entry and decref the genericobj (if it's one)
981       myIORLabels.erase(it);
982     }
983 }
984
985 SALOMEDSImpl_Study* SALOMEDSImpl_Study::GetStudy(const DF_Label& theLabel)
986 {
987   SALOMEDSImpl_StudyHandle* Att;
988   if ((Att=(SALOMEDSImpl_StudyHandle*)theLabel.Root().FindAttribute(SALOMEDSImpl_StudyHandle::GetID()))) {
989     return Att->Get();
990   }
991   return NULL;
992 }
993
994 SALOMEDSImpl_SObject SALOMEDSImpl_Study::SObject(const DF_Label& theLabel)
995 {
996   return GetStudy(theLabel)->GetSObject(theLabel);
997 }
998
999 SALOMEDSImpl_SComponent SALOMEDSImpl_Study::SComponent(const DF_Label& theLabel)
1000 {
1001   return GetStudy(theLabel)->GetSComponent(theLabel);
1002 }
1003
1004
1005 void SALOMEDSImpl_Study::IORUpdated(const SALOMEDSImpl_AttributeIOR* theAttribute)
1006 {
1007   std::string aString = theAttribute->Label().Entry();
1008   GetStudy(theAttribute->Label())->UpdateIORLabelMap(theAttribute->Value(), aString);
1009 }
1010
1011 std::vector<SALOMEDSImpl_SObject> SALOMEDSImpl_Study::FindDependances(const SALOMEDSImpl_SObject& anObject)
1012 {
1013   _errorCode = "";
1014   std::vector<SALOMEDSImpl_SObject> aSeq;
1015
1016   SALOMEDSImpl_AttributeTarget* aTarget;
1017   if ((aTarget=(SALOMEDSImpl_AttributeTarget*)anObject.GetLabel().FindAttribute(SALOMEDSImpl_AttributeTarget::GetID()))) {
1018     return aTarget->Get();
1019   }
1020
1021   return aSeq;
1022 }
1023
1024
1025 SALOMEDSImpl_AttributeStudyProperties* SALOMEDSImpl_Study::GetProperties()
1026 {
1027   _errorCode = "";
1028   return SALOMEDSImpl_AttributeStudyProperties::Set(_doc->Main());
1029 }
1030
1031 std::string SALOMEDSImpl_Study::GetLastModificationDate()
1032 {
1033   _errorCode = "";
1034   SALOMEDSImpl_AttributeStudyProperties* aProp = GetProperties();
1035
1036   std::vector<std::string> aNames;
1037   std::vector<int> aMinutes, aHours, aDays, aMonths, aYears;
1038   aProp->GetModifications(aNames, aMinutes, aHours, aDays, aMonths, aYears);
1039
1040   int aLastIndex = aNames.size()-1;
1041   char aResult[20];
1042   sprintf(aResult, "%2.2d/%2.2d/%4.4d %2.2d:%2.2d",
1043           (int)(aDays[aLastIndex]),(int)(aMonths[aLastIndex]), (int)(aYears[aLastIndex]),
1044           (int)(aHours[aLastIndex]), (int)(aMinutes[aLastIndex]));
1045   std::string aResStr (aResult);
1046   return aResStr;
1047 }
1048
1049 std::vector<std::string> SALOMEDSImpl_Study::GetModificationsDate()
1050 {
1051   _errorCode = "";
1052   SALOMEDSImpl_AttributeStudyProperties* aProp = GetProperties();
1053
1054   std::vector<std::string> aNames;
1055   std::vector<int> aMinutes, aHours, aDays, aMonths, aYears;
1056   aProp->GetModifications(aNames, aMinutes, aHours, aDays, aMonths, aYears);
1057
1058   int anIndex, aLength = aNames.size();
1059   std::vector<std::string> aDates;
1060
1061   for (anIndex = 1; anIndex < aLength; anIndex++) {
1062     char aDate[20];
1063     sprintf(aDate, "%2.2d/%2.2d/%4.4d %2.2d:%2.2d",
1064             (int)(aDays[anIndex]), (int)(aMonths[anIndex]), (int)(aYears[anIndex]),
1065             (int)(aHours[anIndex]), (int)(aMinutes[anIndex]));
1066     aDates.push_back(aDate);
1067   }
1068   return aDates;
1069 }
1070
1071
1072
1073 //============================================================================
1074 /*! Function : GetUseCaseBuilder
1075  *  Purpose  : Returns a UseCase builder
1076  */
1077 //============================================================================
1078 SALOMEDSImpl_UseCaseBuilder* SALOMEDSImpl_Study::GetUseCaseBuilder()
1079 {
1080   _errorCode = "";
1081   return _useCaseBuilder;
1082 }
1083
1084
1085 //============================================================================
1086 /*! Function : Close
1087  *  Purpose  :
1088  */
1089 //============================================================================
1090 void SALOMEDSImpl_Study::Close()
1091 {
1092   _errorCode = "";
1093   _doc->GetApplication()->Close(_doc);
1094   _doc = NULL;
1095   _mapOfSO.clear();
1096   _mapOfSCO.clear();
1097 }
1098
1099
1100 //============================================================================
1101 /*! Function : GetSComponent
1102  *  Purpose  :
1103  */
1104 //============================================================================
1105 SALOMEDSImpl_SComponent SALOMEDSImpl_Study::GetSComponent(const std::string& theEntry)
1106 {
1107   SALOMEDSImpl_SComponent aSCO;
1108   if(_mapOfSCO.find(theEntry) != _mapOfSCO.end())
1109     aSCO = _mapOfSCO[theEntry];
1110   else {
1111     DF_Label aLabel = DF_Label::Label(_doc->Main(), theEntry);
1112     aSCO = SALOMEDSImpl_SComponent(aLabel);
1113     _mapOfSCO[theEntry] = aSCO;
1114   }
1115
1116   return aSCO;
1117 }
1118
1119 //============================================================================
1120 /*! Function : GetSComponent
1121  *  Purpose  :
1122  */
1123 //============================================================================
1124 SALOMEDSImpl_SComponent SALOMEDSImpl_Study::GetSComponent(const DF_Label& theLabel)
1125 {
1126   return SALOMEDSImpl_SComponent(theLabel);
1127 }
1128
1129 //============================================================================
1130 /*! Function : GetSObject
1131  *  Purpose  :
1132  */
1133 //============================================================================
1134 SALOMEDSImpl_SObject SALOMEDSImpl_Study::GetSObject(const std::string& theEntry)
1135 {
1136   SALOMEDSImpl_SObject aSO;
1137   std::map<std::string, SALOMEDSImpl_SObject>::iterator it=_mapOfSO.find(theEntry);
1138   if(it != _mapOfSO.end())
1139     aSO = it->second;
1140   else {
1141     DF_Label aLabel = DF_Label::Label(_doc->Main(), theEntry);
1142     aSO = SALOMEDSImpl_SObject(aLabel);
1143     _mapOfSO[theEntry] = aSO;
1144   }
1145
1146   return aSO;
1147 }
1148
1149 //============================================================================
1150 /*! Function : GetSObject
1151  *  Purpose  :
1152  */
1153 //============================================================================
1154 SALOMEDSImpl_SObject SALOMEDSImpl_Study::GetSObject(const DF_Label& theLabel)
1155 {
1156   return SALOMEDSImpl_SObject(theLabel);
1157 }
1158
1159 //============================================================================
1160 /*! Function : GetAttribute
1161  *  Purpose  :
1162  */
1163 //============================================================================
1164 DF_Attribute* SALOMEDSImpl_Study::GetAttribute(const std::string& theEntry,
1165                                                const std::string& theType)
1166 {
1167   SALOMEDSImpl_SObject aSO = GetSObject(theEntry);
1168   DF_Attribute* anAttr;
1169   aSO.FindAttribute(anAttr, theType);
1170   return anAttr;
1171 }
1172
1173 //============================================================================
1174 /*! Function : DumpStudy
1175  *  Purpose  :
1176  */
1177 //============================================================================
1178 bool SALOMEDSImpl_Study::DumpStudy(const std::string& thePath,
1179                                    const std::string& theBaseName,
1180                                    bool isPublished,
1181                                    SALOMEDSImpl_DriverFactory* theFactory)
1182 {
1183   _errorCode = "";
1184
1185   if(theFactory == NULL) {
1186     _errorCode = "Null factory for creation of Engines";
1187     return false;
1188   }
1189
1190   std::vector<std::string> aSeq;
1191   std::string aCompType, aFactoryType;
1192
1193   //Build a list of all components in the Study
1194   SALOMEDSImpl_SComponentIterator itcomponent = NewComponentIterator();
1195
1196   for (; itcomponent.More(); itcomponent.Next()) {
1197     SALOMEDSImpl_SComponent sco = itcomponent.Value();
1198     aCompType = sco.ComponentDataType();
1199     //GEOM and MED are independent components
1200     if (aCompType == "GEOM" || aCompType == "MED")
1201       aSeq.insert(aSeq.begin(), aCompType);
1202     else
1203       aSeq.push_back(aCompType);
1204   }
1205
1206 #ifdef WIN32
1207   std::string aFileName =
1208     thePath + std::string("\\") + theBaseName + std::string(".py");
1209 #else
1210   std::string aFileName =
1211     thePath + std::string("/")  + theBaseName + std::string(".py");
1212 #endif
1213
1214   //Create a file that will contain a main Study script
1215   std::fstream fp;
1216   fp.open(aFileName.c_str(), std::ios::out);
1217
1218 #ifdef WIN32
1219   bool isOpened = fp.is_open();
1220 #else
1221   bool isOpened = fp.rdbuf()->is_open();
1222 #endif
1223
1224   if(!isOpened) {
1225     _errorCode = std::string("Can't create a file ")+aFileName;
1226     return false;
1227   }
1228
1229   std::string aBatchModeScript = "salome";
1230
1231   //Output to the main Study script required Python modules import,
1232   //set sys.path and add a creation of the study.
1233
1234   // dump header
1235   fp << GetDumpStudyComment() << std::endl;
1236
1237   // global imports
1238   fp << "import sys" << std::endl;
1239   fp << "import " << aBatchModeScript << std::endl << std::endl;
1240
1241   // initialization function
1242   fp << aBatchModeScript << ".salome_init()" << std::endl << std::endl;
1243
1244   // notebook initialization
1245   fp << _GetNoteBookAccess();
1246
1247   // extend sys.path with the directory where the script is being dumped to
1248   fp << "sys.path.insert( 0, r\'" << thePath << "\')" << std::endl << std::endl;
1249
1250   // dump NoteBook variables
1251   fp << _GetStudyVariablesScript();
1252
1253   // dump visual parameters if necessary
1254   bool isDumpVisuals = SALOMEDSImpl_IParameters::isDumpPython(this);
1255   int lastSavePoint = -1;
1256   if(isDumpVisuals) {
1257     lastSavePoint = SALOMEDSImpl_IParameters::getLastSavePoint(this);
1258     if(lastSavePoint > 0) {
1259       fp << SALOMEDSImpl_IParameters::getStudyScript(this, lastSavePoint) << std::endl << std::endl;
1260     }
1261   }
1262
1263   std::vector<std::string> aSeqOfFileNames;
1264
1265   // dump all components and create the components specific scripts
1266   bool isOk = true;
1267   int aLength = aSeq.size();
1268   for(int i = 1; i <= aLength; i++) {
1269
1270     aCompType = aSeq[i-1];
1271     SALOMEDSImpl_SComponent sco = FindComponent(aCompType);
1272     SALOMEDSImpl_Driver* aDriver = NULL;
1273     // if there is an associated Engine call its method for saving
1274     std::string IOREngine;
1275     try {
1276       if (!sco.ComponentIOR(IOREngine)) {
1277         if (!aCompType.empty()) {
1278
1279           aDriver = theFactory->GetDriverByType(aCompType);
1280
1281           if (aDriver != NULL) {
1282             SALOMEDSImpl_StudyBuilder* SB = NewBuilder();
1283             if(!SB->LoadWith(sco, aDriver)) {
1284               _errorCode = SB->GetErrorCode();
1285               return false;
1286             }
1287           }
1288           else continue;
1289         }
1290       }
1291       else {
1292         aDriver = theFactory->GetDriverByIOR(IOREngine);
1293       }
1294     } catch(...) {
1295       _errorCode = "Can not restore information to dump it";
1296       return false;
1297     }
1298
1299     if(aDriver == NULL) continue;
1300
1301     bool isValidScript;
1302     long aStreamLength  = 0;
1303     SALOMEDSImpl_TMPFile* aStream = aDriver->DumpPython(this, isPublished, isValidScript, aStreamLength);
1304     if ( !isValidScript )
1305       isOk = false;
1306
1307     //Create a file that will contain the component specific script
1308     std::fstream fp2;
1309 #ifdef WIN32
1310     aFileName=thePath+std::string("\\");
1311 #else
1312     aFileName=thePath+std::string("/");
1313 #endif
1314     std::string aScriptName;
1315     aScriptName += theBaseName;
1316     aScriptName += "_";
1317     aScriptName += aCompType;
1318
1319     aFileName += aScriptName+ std::string(".py");
1320     aSeqOfFileNames.push_back(aFileName);
1321
1322     fp2.open(aFileName.c_str(), std::ios::out);
1323
1324 #ifdef WIN32
1325     isOpened = fp2.is_open();
1326 #else
1327     isOpened = fp2.rdbuf()->is_open();
1328 #endif
1329
1330     if(!isOpened) {
1331       _errorCode = std::string("Can't create a file ")+aFileName;
1332       SALOMEDSImpl_Tool::RemoveTemporaryFiles(thePath, aSeqOfFileNames, false);
1333       return false;
1334     }
1335
1336     //Output the Python script generated by the component in the newly created file.
1337     fp2 << GetDumpStudyComment( aCompType.c_str() ) << std::endl;
1338     fp2 << aStream->Data();
1339     fp2.close();
1340
1341     if(aStream) delete aStream;
1342
1343     //Add to the main script a call to RebuildData of the generated by the component the Python script
1344     fp << "import " << aScriptName << std::endl;
1345     fp << aScriptName << ".RebuildData(" << aBatchModeScript << ".myStudy)" << std::endl;
1346   }
1347
1348   fp << std::endl;
1349   fp << "if salome.sg.hasDesktop():" << std::endl;
1350   fp << "\tsalome.sg.updateObjBrowser(1)" << std::endl;
1351
1352   if(isDumpVisuals) { //Output the call to Session's method restoreVisualState
1353     fp << "\tiparameters.getSession().restoreVisualState(1)" << std::endl;
1354   }
1355
1356
1357   fp.close();
1358   return isOk;
1359 }
1360
1361 //=======================================================================
1362 //function : GetDumpStudyComment
1363 //purpose  : return a header comment for a DumpStudy script
1364 //=======================================================================
1365
1366 std::string SALOMEDSImpl_Study::GetDumpStudyComment(const char* theComponentName)
1367 {
1368   std::stringstream txt;
1369   txt << "# -*- coding: iso-8859-1 -*-" << std::endl << std::endl;
1370   txt << "###" << std::endl;
1371   txt << "### This file is generated automatically by SALOME v"
1372       << KERNEL_VERSION_STR
1373       << " with dump python functionality";
1374   if ( theComponentName )
1375     txt << " (" << theComponentName << " component)";
1376   txt << std::endl;
1377   txt << "###" << std::endl;
1378   return txt.str();
1379 }
1380
1381 void dumpSO(const SALOMEDSImpl_SObject& theSO,
1382             std::fstream& fp,
1383             const std::string& Tab,
1384             SALOMEDSImpl_Study* theStudy);
1385
1386 //============================================================================
1387 /*! Function : dump
1388  *  Purpose  :
1389  */
1390 //============================================================================
1391 void SALOMEDSImpl_Study::dump(const std::string& theFileName)
1392 {
1393   //Create a file that will contain a main Study script
1394   std::fstream fp;
1395   fp.open(theFileName.c_str(), std::ios::out);
1396
1397 #ifdef WIN32
1398   bool isOpened = fp.is_open();
1399 #else
1400   bool isOpened = fp.rdbuf()->is_open();
1401 #endif
1402
1403   if(!isOpened) {
1404     _errorCode = std::string("Can't create a file ")+theFileName;
1405     std::cout << "### SALOMEDSImpl_Study::dump Error: " << _errorCode << std::endl;
1406     return;
1407   }
1408
1409   SALOMEDSImpl_SObject aSO = FindObjectID("0:1");
1410   fp << "0:1" << std::endl;
1411   SALOMEDSImpl_ChildIterator Itr = NewChildIterator(aSO);
1412   std::string aTab("   ");
1413   for(; Itr.More(); Itr.Next()) {
1414     dumpSO(Itr.Value(), fp, aTab, this);
1415   }
1416
1417   fp.close();
1418 }
1419
1420
1421 void dumpSO(const SALOMEDSImpl_SObject& theSO,
1422             std::fstream& fp,
1423             const std::string& Tab,
1424             SALOMEDSImpl_Study* theStudy)
1425 {
1426   std::string aTab(Tab), anID(theSO.GetID());
1427   fp << aTab << anID << std::endl;
1428   std::vector<DF_Attribute*> attribs = theSO.GetLabel().GetAttributes();
1429   for(int i = 0; i<attribs.size(); i++) {
1430     SALOMEDSImpl_GenericAttribute* anAttr = dynamic_cast<SALOMEDSImpl_GenericAttribute*>(attribs[i]);
1431
1432     if(!anAttr) {
1433       continue;
1434     }
1435
1436     std::string aType = anAttr->GetClassType();
1437     fp << Tab << "  -- " << aType;
1438
1439     if(aType == std::string("AttributeReal")) {
1440       fp << " : " << dynamic_cast<SALOMEDSImpl_AttributeReal*>(anAttr)->Value();
1441     }
1442     else if(aType == std::string("AttributeInteger")) {
1443       fp << " : " << dynamic_cast<SALOMEDSImpl_AttributeInteger*>(anAttr)->Value();
1444     }
1445     else if(aType ==  std::string("AttributeName")) {
1446       fp << " : " << dynamic_cast<SALOMEDSImpl_AttributeName*>(anAttr)->Value();
1447     }
1448     else if(aType == std::string("AttributeComment")) {
1449       fp << " : " << dynamic_cast<SALOMEDSImpl_AttributeComment*>(anAttr)->Value();
1450     }
1451     else if(aType == std::string("AttributeReference")) {
1452       fp << " : " << dynamic_cast<SALOMEDSImpl_AttributeReference*>(anAttr)->Save();
1453     }
1454     fp << std::endl;
1455   }
1456
1457   SALOMEDSImpl_ChildIterator Itr = theStudy->NewChildIterator(theSO);
1458   std::string aNewTab("   ");
1459   aNewTab+=aTab;
1460   for(; Itr.More(); Itr.Next()) {
1461     dumpSO(Itr.Value(), fp, aNewTab, theStudy);
1462   }
1463
1464   return;
1465 }
1466
1467 void SALOMEDSImpl_Study::Modify()
1468 {
1469   _errorCode = "";
1470   _doc->SetModified(true);
1471 }
1472
1473 //============================================================================
1474 /*! Function :
1475  *  Purpose  :
1476  */
1477 //============================================================================
1478 SALOMEDSImpl_AttributeParameter* SALOMEDSImpl_Study::GetCommonParameters(const char* theID, int theSavePoint)
1479 {
1480   if (theSavePoint < 0) return NULL;
1481   SALOMEDSImpl_StudyBuilder* builder = NewBuilder();
1482   SALOMEDSImpl_SObject so = FindComponent((char*)theID);
1483   if (!so) so = builder->NewComponent((char*)theID);
1484   SALOMEDSImpl_AttributeParameter* attParam = NULL;
1485
1486   if (theSavePoint > 0) { // Try to find SObject that contains attribute parameter ...
1487     DF_Label savePointLabel = so.GetLabel().FindChild( theSavePoint, /*create=*/0 );
1488     if ( !savePointLabel.IsNull() )
1489       so = GetSObject( savePointLabel );
1490     else // ... if it does not exist - create a new one
1491       so = builder->NewObjectToTag( so, theSavePoint );
1492   }
1493
1494   DF_Attribute* A;
1495   if (so) {
1496     builder->FindAttribute(so, A, "AttributeParameter");
1497     if ( !A ) { // first call of GetCommonParameters on "Interface Applicative" component
1498       A = builder->FindOrCreateAttribute(so, "AttributeParameter");
1499     }
1500     attParam = dynamic_cast<SALOMEDSImpl_AttributeParameter*>( A );
1501   }
1502   return attParam;
1503 }
1504
1505 //============================================================================
1506 /*! Function :
1507  *  Purpose  :
1508  */
1509 //============================================================================
1510 SALOMEDSImpl_AttributeParameter* SALOMEDSImpl_Study::GetModuleParameters(const char* theID,
1511                                                                          const char* theModuleName,
1512                                                                          int theSavePoint)
1513 {
1514   if(theSavePoint <= 0) return NULL;
1515   SALOMEDSImpl_AttributeParameter* main_ap = GetCommonParameters(theID, theSavePoint);
1516   SALOMEDSImpl_SObject main_so = main_ap->GetSObject();
1517   SALOMEDSImpl_AttributeParameter* par = NULL;
1518
1519   SALOMEDSImpl_ChildIterator it = NewChildIterator(main_so);
1520   std::string moduleName(theModuleName);
1521   for(; it.More(); it.Next()) {
1522     SALOMEDSImpl_SObject so(it.Value());
1523     if((par=(SALOMEDSImpl_AttributeParameter*)so.GetLabel().FindAttribute(SALOMEDSImpl_AttributeParameter::GetID()))) {
1524       if(!par->IsSet("AP_MODULE_NAME", (Parameter_Types)3)) continue; //3 -> PT_STRING
1525       if(par->GetString("AP_MODULE_NAME") == moduleName) return par;
1526     }
1527   }
1528
1529   SALOMEDSImpl_StudyBuilder* builder = NewBuilder();
1530   SALOMEDSImpl_SObject so = builder->NewObject(main_so);
1531   par  = dynamic_cast<SALOMEDSImpl_AttributeParameter*>(builder->FindOrCreateAttribute(so, "AttributeParameter"));
1532   par->SetString("AP_MODULE_NAME", moduleName);
1533   return par;
1534 }
1535
1536 //============================================================================
1537 /*! Function : SetStudyLock
1538  *  Purpose  :
1539  */
1540 //============================================================================
1541 void SALOMEDSImpl_Study::SetStudyLock(const char* theLockerID)
1542 {
1543   _lockers.push_back(theLockerID);
1544 }
1545
1546 //============================================================================
1547 /*! Function : IsStudyLocked
1548  *  Purpose  :
1549  */
1550 //============================================================================
1551 bool SALOMEDSImpl_Study::IsStudyLocked()
1552 {
1553   return (_lockers.size() > 0);
1554 }
1555
1556 //============================================================================
1557 /*! Function : UnLockStudy
1558  *  Purpose  :
1559  */
1560 //============================================================================
1561 void SALOMEDSImpl_Study::UnLockStudy(const char* theLockerID)
1562 {
1563   std::vector<std::string>::iterator vsI = _lockers.begin();
1564   int length = _lockers.size();
1565   bool isFound = false;
1566   std::string id(theLockerID);
1567   for(int i = 0; i<length; i++, vsI++) {
1568     if(id == _lockers[i]) {
1569       isFound = true;;
1570       break;
1571     }
1572   }
1573   if(isFound) _lockers.erase(vsI);
1574 }
1575
1576 //============================================================================
1577 /*! Function : GetLockerID
1578  *  Purpose  :
1579  */
1580 //============================================================================
1581 std::vector<std::string> SALOMEDSImpl_Study::GetLockerID()
1582 {
1583   return _lockers;
1584 }
1585
1586 //============================================================================
1587 /*! Function : SetVariable
1588  *  Purpose  :
1589  */
1590 //============================================================================
1591 void SALOMEDSImpl_Study::SetVariable(const std::string& theVarName,
1592                                      const double theValue,
1593                                      const SALOMEDSImpl_GenericVariable::VariableTypes theType)
1594 {
1595   bool modified = false;
1596   SALOMEDSImpl_GenericVariable* aGVar = GetVariable(theVarName);
1597
1598   if( aGVar == NULL ) {
1599
1600     SALOMEDSImpl_ScalarVariable* aSVar = new SALOMEDSImpl_ScalarVariable(theType, theVarName);
1601
1602     aSVar->setValue(theValue);
1603     myNoteBookVars.push_back(aSVar);
1604     modified = true;
1605   }
1606   else {
1607     if(SALOMEDSImpl_ScalarVariable* aSVar = dynamic_cast<SALOMEDSImpl_ScalarVariable*>(aGVar)) {
1608       modified = aSVar->setValue(theValue) || modified;
1609       modified = aSVar->setType(theType) || modified;
1610     }
1611   }
1612   if(modified)
1613     Modify();
1614 }
1615
1616 //============================================================================
1617 /*! Function : SetStringVariable
1618  *  Purpose  :
1619  */
1620 //============================================================================
1621 void SALOMEDSImpl_Study::SetStringVariable(const std::string& theVarName,
1622                                            const std::string& theValue,
1623                                            const SALOMEDSImpl_GenericVariable::VariableTypes theType)
1624 {
1625   bool modified = false;
1626   SALOMEDSImpl_GenericVariable* aGVar = GetVariable(theVarName);
1627
1628   if( aGVar == NULL ) {
1629
1630     SALOMEDSImpl_ScalarVariable* aSVar = new SALOMEDSImpl_ScalarVariable(theType, theVarName);
1631
1632     aSVar->setStringValue(theValue);
1633     myNoteBookVars.push_back(aSVar);
1634     modified = true;
1635   }
1636   else {
1637     if(SALOMEDSImpl_ScalarVariable* aSVar = dynamic_cast<SALOMEDSImpl_ScalarVariable*>(aGVar)) {
1638       modified = aSVar->setStringValue(theValue) || modified;
1639       modified = aSVar->setType(theType) || modified;
1640     }
1641   }
1642   if(modified)
1643     Modify();
1644 }
1645
1646 //============================================================================
1647 /*! Function : SetStringVariableAsDouble
1648  *  Purpose  :
1649  */
1650 //============================================================================
1651 void SALOMEDSImpl_Study::SetStringVariableAsDouble(const std::string& theVarName,
1652                                                    const double theValue,
1653                                                    const SALOMEDSImpl_GenericVariable::VariableTypes theType)
1654 {
1655   SALOMEDSImpl_GenericVariable* aGVar = GetVariable(theVarName);
1656   if(SALOMEDSImpl_ScalarVariable* aSVar = dynamic_cast<SALOMEDSImpl_ScalarVariable*>(aGVar))
1657     aSVar->setValue(theValue);
1658 }
1659
1660 //============================================================================
1661 /*! Function : GetReal
1662  *  Purpose  :
1663  */
1664 //============================================================================
1665 double SALOMEDSImpl_Study::GetVariableValue(const std::string& theVarName)
1666 {
1667   SALOMEDSImpl_GenericVariable* aGVar = GetVariable(theVarName);
1668
1669   if(aGVar != NULL )
1670     if(SALOMEDSImpl_ScalarVariable* aSVar = dynamic_cast<SALOMEDSImpl_ScalarVariable*>(aGVar))
1671       return aSVar->getValue();
1672
1673   return 0;
1674 }
1675
1676 //============================================================================
1677 /*! Function : GetString
1678  *  Purpose  :
1679  */
1680 //============================================================================
1681 std::string SALOMEDSImpl_Study::GetStringVariableValue(const std::string& theVarName)
1682 {
1683   SALOMEDSImpl_GenericVariable* aGVar = GetVariable(theVarName);
1684
1685   if(aGVar != NULL )
1686     if(SALOMEDSImpl_ScalarVariable* aSVar = dynamic_cast<SALOMEDSImpl_ScalarVariable*>(aGVar))
1687       return aSVar->getStringValue();
1688
1689   return 0;
1690 }
1691
1692 //============================================================================
1693 /*! Function : IsTypeOf
1694  *  Purpose  :
1695  */
1696 //============================================================================
1697 bool SALOMEDSImpl_Study::IsTypeOf(const std::string& theVarName,
1698                                   SALOMEDSImpl_GenericVariable::
1699                                   VariableTypes theType) const
1700 {
1701   SALOMEDSImpl_GenericVariable* aGVar = GetVariable(theVarName);
1702
1703   if(aGVar != NULL )
1704     return aGVar->Type() == theType;
1705
1706   return false;
1707 }
1708
1709 //============================================================================
1710 /*! Function : IsVariable
1711  *  Purpose  :
1712  */
1713 //============================================================================
1714 bool SALOMEDSImpl_Study::IsVariable(const std::string& theVarName) const
1715 {
1716   SALOMEDSImpl_GenericVariable* aGVar = GetVariable(theVarName);
1717   return (aGVar != NULL);
1718 }
1719
1720 //============================================================================
1721 /*! Function : GetVariableNames
1722  *  Purpose  :
1723  */
1724 //============================================================================
1725 std::vector<std::string> SALOMEDSImpl_Study::GetVariableNames() const
1726 {
1727   std::vector<std::string> aResult;
1728
1729   for(int i = 0; i < myNoteBookVars.size(); i++)
1730     aResult.push_back(myNoteBookVars[i]->Name());
1731
1732   return aResult;
1733 }
1734
1735 //============================================================================
1736 /*! Function : AddVariable
1737  *  Purpose  :
1738  */
1739 //============================================================================
1740 void SALOMEDSImpl_Study::AddVariable(SALOMEDSImpl_GenericVariable* theVariable)
1741 {
1742   myNoteBookVars.push_back(theVariable);
1743 }
1744
1745 //============================================================================
1746 /*! Function : AddVariable
1747  *  Purpose  :
1748  */
1749 //============================================================================
1750 SALOMEDSImpl_GenericVariable* SALOMEDSImpl_Study::GetVariable(const std::string& theName) const
1751 {
1752   SALOMEDSImpl_GenericVariable* aResult = NULL;
1753   for(int i = 0; i < myNoteBookVars.size();i++) {
1754     if(theName.compare(myNoteBookVars[i]->Name()) == 0) {
1755       aResult = myNoteBookVars[i];
1756       break;
1757     }
1758   }
1759   return aResult;
1760 }
1761
1762 //============================================================================
1763 /*! Function : RemoveVariable
1764  *  Purpose  :
1765  */
1766 //============================================================================
1767 bool SALOMEDSImpl_Study::RemoveVariable(const std::string& theVarName)
1768 {
1769   SALOMEDSImpl_GenericVariable* aVariable = GetVariable( theVarName );
1770   if( !aVariable )
1771     return false;
1772
1773   std::string aValue = aVariable->SaveToScript();
1774   ReplaceVariableAttribute( theVarName, aValue );
1775
1776   std::vector<SALOMEDSImpl_GenericVariable*>::iterator it = myNoteBookVars.begin(), itEnd = myNoteBookVars.end();
1777   for( ; it != itEnd; it++ )
1778   {
1779     SALOMEDSImpl_GenericVariable* aVariableRef = *it;
1780     if( aVariableRef && theVarName.compare( aVariableRef->Name() ) == 0 )
1781     {
1782       myNoteBookVars.erase( it );
1783       Modify();
1784       break;
1785     }
1786   }
1787
1788   return true;
1789 }
1790
1791 //============================================================================
1792 /*! Function : RenameVariable
1793  *  Purpose  :
1794  */
1795 //============================================================================
1796 bool SALOMEDSImpl_Study::RenameVariable(const std::string& theVarName, const std::string& theNewVarName)
1797 {
1798   SALOMEDSImpl_GenericVariable* aVariable = GetVariable( theVarName );
1799   if( !aVariable )
1800     return false;
1801
1802   ReplaceVariableAttribute( theVarName, theNewVarName );
1803
1804   std::vector<SALOMEDSImpl_GenericVariable*>::iterator it = myNoteBookVars.begin(), itEnd = myNoteBookVars.end();
1805   for( ; it != itEnd; it++ )
1806   {
1807     SALOMEDSImpl_GenericVariable* aVariableRef = *it;
1808     if( aVariableRef && theVarName.compare( aVariableRef->Name() ) == 0 )
1809     {
1810       aVariableRef->setName( theNewVarName );
1811       Modify();
1812       break;
1813     }
1814   }
1815
1816   return true;
1817 }
1818
1819 //============================================================================
1820 /*! Function : IsVariableUsed
1821  *  Purpose  :
1822  */
1823 //============================================================================
1824 bool SALOMEDSImpl_Study::IsVariableUsed(const std::string& theVarName)
1825 {
1826   return FindVariableAttribute( theVarName );
1827 }
1828
1829 //============================================================================
1830 /*! Function : FindVariableAttribute
1831  *  Purpose  :
1832  */
1833 //============================================================================
1834 bool SALOMEDSImpl_Study::FindVariableAttribute(SALOMEDSImpl_StudyBuilder* theStudyBuilder,
1835                                                SALOMEDSImpl_SObject theSObject,
1836                                                const std::string& theName)
1837 {
1838   SALOMEDSImpl_ChildIterator anIter = NewChildIterator( theSObject );
1839   for( ; anIter.More(); anIter.Next() )
1840     if( FindVariableAttribute( theStudyBuilder, anIter.Value(), theName ) )
1841       return true;
1842
1843   DF_Attribute* anAttr;
1844   if( theStudyBuilder->FindAttribute( theSObject, anAttr, "AttributeString" ) )
1845   {
1846     if( SALOMEDSImpl_AttributeString* aStringAttr = ( SALOMEDSImpl_AttributeString* )anAttr )
1847     {
1848       std::string aString = aStringAttr->Value();
1849
1850       std::vector< std::vector<std::string> > aSections = ParseVariables( aString );
1851       for( int i = 0, n = aSections.size(); i < n; i++ )
1852       {
1853         std::vector<std::string> aVector = aSections[i];
1854         for( int j = 0, m = aVector.size(); j < m; j++ )
1855         {
1856           std::string aStr = aVector[j];
1857           if( aStr.compare( theName ) == 0 )
1858             return true;
1859         }
1860       }
1861     }
1862   }
1863   return false;
1864 }
1865
1866 //============================================================================
1867 /*! Function : FindVariableAttribute
1868  *  Purpose  :
1869  */
1870 //============================================================================
1871 bool SALOMEDSImpl_Study::FindVariableAttribute(const std::string& theName)
1872 {
1873   SALOMEDSImpl_StudyBuilder* aStudyBuilder = NewBuilder();
1874   SALOMEDSImpl_SComponentIterator aCompIter = NewComponentIterator();
1875   for( ; aCompIter.More(); aCompIter.Next() )
1876   {
1877     SALOMEDSImpl_SObject aComp = aCompIter.Value();
1878     if( FindVariableAttribute( aStudyBuilder, aComp, theName ) )
1879       return true;
1880   }
1881   return false;
1882 }
1883
1884 //============================================================================
1885 /*! Function : ReplaceVariableAttribute
1886  *  Purpose  :
1887  */
1888 //============================================================================
1889 void SALOMEDSImpl_Study::ReplaceVariableAttribute(SALOMEDSImpl_StudyBuilder* theStudyBuilder,
1890                                                   SALOMEDSImpl_SObject theSObject,
1891                                                   const std::string& theSource,
1892                                                   const std::string& theDest)
1893 {
1894   SALOMEDSImpl_ChildIterator anIter = NewChildIterator( theSObject );
1895   for( ; anIter.More(); anIter.Next() )
1896     ReplaceVariableAttribute( theStudyBuilder, anIter.Value(), theSource, theDest );
1897
1898   DF_Attribute* anAttr;
1899   if( theStudyBuilder->FindAttribute( theSObject, anAttr, "AttributeString" ) )
1900   {
1901     if( SALOMEDSImpl_AttributeString* aStringAttr = ( SALOMEDSImpl_AttributeString* )anAttr )
1902     {
1903       bool isChanged = false;
1904       std::string aNewString, aCurrentString = aStringAttr->Value();
1905
1906       std::vector< std::vector<std::string> > aSections = ParseVariables( aCurrentString );
1907       for( int i = 0, n = aSections.size(); i < n; i++ )
1908       {
1909         std::vector<std::string> aVector = aSections[i];
1910         for( int j = 0, m = aVector.size(); j < m; j++ )
1911         {
1912           std::string aStr = aVector[j];
1913           if( aStr.compare( theSource ) == 0 )
1914           {
1915             isChanged = true;
1916             aStr = theDest;
1917           }
1918
1919           aNewString.append( aStr );
1920           if( j != m - 1 )
1921             aNewString.append( ":" );
1922         }
1923         if( i != n - 1 )
1924           aNewString.append( "|" );
1925       }
1926
1927       if( isChanged )
1928         aStringAttr->SetValue( aNewString );
1929     }
1930   }
1931 }
1932
1933 //============================================================================
1934 /*! Function : ReplaceVariableAttribute
1935  *  Purpose  :
1936  */
1937 //============================================================================
1938 void SALOMEDSImpl_Study::ReplaceVariableAttribute(const std::string& theSource, const std::string& theDest)
1939 {
1940   SALOMEDSImpl_StudyBuilder* aStudyBuilder = NewBuilder();
1941   SALOMEDSImpl_SComponentIterator aCompIter = NewComponentIterator();
1942   for( ; aCompIter.More(); aCompIter.Next() )
1943   {
1944     SALOMEDSImpl_SObject aComp = aCompIter.Value();
1945     ReplaceVariableAttribute( aStudyBuilder, aComp, theSource, theDest );
1946   }
1947 }
1948
1949 //============================================================================
1950 /*! Function : ParseVariables
1951  *  Purpose  :
1952  */
1953 //============================================================================
1954 std::vector< std::vector< std::string > > SALOMEDSImpl_Study::ParseVariables(const std::string& theVariables) const
1955 {
1956   return SALOMEDSImpl_Tool::splitStringWithEmpty( theVariables, OPERATION_SEPARATOR, VARIABLE_SEPARATOR );
1957 }
1958
1959 //============================================================================
1960 /*! Function : EnableUseCaseAutoFilling
1961  *  Purpose  :
1962  */
1963 //============================================================================
1964 void SALOMEDSImpl_Study::EnableUseCaseAutoFilling(bool isEnabled)
1965 {
1966   _errorCode = ""; _autoFill = isEnabled;
1967   if(isEnabled) {
1968     _builder->SetOnAddSObject(_cb);
1969     _builder->SetOnRemoveSObject(_cb);
1970   }
1971   else {
1972     _builder->SetOnAddSObject(NULL);
1973     _builder->SetOnRemoveSObject(NULL);
1974   }
1975 }
1976
1977 //============================================================================
1978 /*! Function : GetIORs
1979  *  Purpose  :
1980  */
1981 //============================================================================
1982 std::vector<std::string> SALOMEDSImpl_Study::GetIORs()
1983 {
1984   std::vector<std::string> anIORs;
1985   std::map<std::string, DF_Label>::const_iterator MI;
1986   for(MI = myIORLabels.begin(); MI!=myIORLabels.end(); MI++)
1987     anIORs.push_back(MI->first);
1988
1989   return anIORs;
1990 }
1991
1992 //============================================================================
1993 /*! Function : addSO_Notification
1994  *  Purpose  : This function tells all the observers that a SO has been added
1995  */
1996 //============================================================================
1997 bool SALOMEDSImpl_Study::addSO_Notification (const SALOMEDSImpl_SObject& theSObject)
1998 {
1999   if(_notifier)
2000     return _notifier->addSO_Notification(theSObject);
2001   else
2002     return false;
2003 }
2004
2005 //============================================================================
2006 /*! Function : removeSO_Notification
2007  *  Purpose  : This function tells all the observers that a SO has been removed
2008  */
2009 //============================================================================
2010 bool SALOMEDSImpl_Study::removeSO_Notification (const SALOMEDSImpl_SObject& theSObject)
2011 {
2012   if(_notifier)
2013     return _notifier->removeSO_Notification(theSObject);
2014   else
2015     return false;
2016 }
2017
2018 //============================================================================
2019 /*! Function : modifySO_Notification
2020  *  Purpose  : This function tells all the observers that a SO has been modified
2021  */
2022 //============================================================================
2023 bool SALOMEDSImpl_Study::modifySO_Notification (const SALOMEDSImpl_SObject& theSObject) 
2024 {
2025   if(_notifier)
2026     return _notifier->modifySO_Notification(theSObject);
2027   else
2028     return false;
2029 }
2030
2031 //============================================================================
2032 /*! Function : setNotifier
2033  *  Purpose  : register a notifier
2034  */
2035 //============================================================================
2036 void SALOMEDSImpl_Study::setNotifier(SALOMEDSImpl_AbstractCallback* notifier) 
2037 {
2038   _notifier=notifier;
2039 }