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