Salome HOME
Merge remote branch 'origin/V7_4_BR'
[modules/kernel.git] / src / SALOMEDSImpl / SALOMEDSImpl_Study.cxx
1 // Copyright (C) 2007-2014  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, or (at your option) any later version.
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(const std::string& theStudyVar)
945 {
946   std::string notebook = "import salome_notebook\n";
947   notebook += _GetNoteBookAccessor() + " = salome_notebook.NoteBook(" + theStudyVar + ")" ;
948   return notebook;
949 }
950
951 bool SALOMEDSImpl_Study::IsLocked()
952 {
953   _errorCode = "";
954   return GetProperties()->IsLocked();
955 }
956
957 int SALOMEDSImpl_Study::StudyId()
958 {
959   _errorCode = "";
960   return _StudyId;
961 }
962
963 void SALOMEDSImpl_Study::StudyId(int id)
964 {
965   _errorCode = "";
966   _StudyId = id;
967 }
968
969 void SALOMEDSImpl_Study::UpdateIORLabelMap(const std::string& anIOR,const std::string& anEntry)
970 {
971   _errorCode = "";
972   DF_Label aLabel = DF_Label::Label(_doc->Main(), anEntry, true);
973   std::map<std::string, DF_Label>::iterator it=myIORLabels.find(anIOR);
974   if (it != myIORLabels.end()) myIORLabels.erase(it);
975   myIORLabels[anIOR] = aLabel;
976 }
977
978 void SALOMEDSImpl_Study::DeleteIORLabelMapItem(const std::string& anIOR)
979 {
980   std::map<std::string, DF_Label>::iterator it=myIORLabels.find(anIOR);
981   if (it != myIORLabels.end())
982     {
983       //remove the ior entry and decref the genericobj (if it's one)
984       myIORLabels.erase(it);
985     }
986 }
987
988 SALOMEDSImpl_Study* SALOMEDSImpl_Study::GetStudy(const DF_Label& theLabel)
989 {
990   SALOMEDSImpl_StudyHandle* Att;
991   if ((Att=(SALOMEDSImpl_StudyHandle*)theLabel.Root().FindAttribute(SALOMEDSImpl_StudyHandle::GetID()))) {
992     return Att->Get();
993   }
994   return NULL;
995 }
996
997 SALOMEDSImpl_SObject SALOMEDSImpl_Study::SObject(const DF_Label& theLabel)
998 {
999   return GetStudy(theLabel)->GetSObject(theLabel);
1000 }
1001
1002 SALOMEDSImpl_SComponent SALOMEDSImpl_Study::SComponent(const DF_Label& theLabel)
1003 {
1004   return GetStudy(theLabel)->GetSComponent(theLabel);
1005 }
1006
1007
1008 void SALOMEDSImpl_Study::IORUpdated(const SALOMEDSImpl_AttributeIOR* theAttribute)
1009 {
1010   std::string aString = theAttribute->Label().Entry();
1011   GetStudy(theAttribute->Label())->UpdateIORLabelMap(theAttribute->Value(), aString);
1012 }
1013
1014 std::vector<SALOMEDSImpl_SObject> SALOMEDSImpl_Study::FindDependances(const SALOMEDSImpl_SObject& anObject)
1015 {
1016   _errorCode = "";
1017   std::vector<SALOMEDSImpl_SObject> aSeq;
1018
1019   SALOMEDSImpl_AttributeTarget* aTarget;
1020   if ((aTarget=(SALOMEDSImpl_AttributeTarget*)anObject.GetLabel().FindAttribute(SALOMEDSImpl_AttributeTarget::GetID()))) {
1021     return aTarget->Get();
1022   }
1023
1024   return aSeq;
1025 }
1026
1027
1028 SALOMEDSImpl_AttributeStudyProperties* SALOMEDSImpl_Study::GetProperties()
1029 {
1030   _errorCode = "";
1031   return SALOMEDSImpl_AttributeStudyProperties::Set(_doc->Main());
1032 }
1033
1034 std::string SALOMEDSImpl_Study::GetLastModificationDate()
1035 {
1036   _errorCode = "";
1037   SALOMEDSImpl_AttributeStudyProperties* aProp = GetProperties();
1038
1039   std::vector<std::string> aNames;
1040   std::vector<int> aMinutes, aHours, aDays, aMonths, aYears;
1041   aProp->GetModifications(aNames, aMinutes, aHours, aDays, aMonths, aYears);
1042
1043   int aLastIndex = aNames.size()-1;
1044   char aResult[20];
1045   sprintf(aResult, "%2.2d/%2.2d/%4.4d %2.2d:%2.2d",
1046           (int)(aDays[aLastIndex]),(int)(aMonths[aLastIndex]), (int)(aYears[aLastIndex]),
1047           (int)(aHours[aLastIndex]), (int)(aMinutes[aLastIndex]));
1048   std::string aResStr (aResult);
1049   return aResStr;
1050 }
1051
1052 std::vector<std::string> SALOMEDSImpl_Study::GetModificationsDate()
1053 {
1054   _errorCode = "";
1055   SALOMEDSImpl_AttributeStudyProperties* aProp = GetProperties();
1056
1057   std::vector<std::string> aNames;
1058   std::vector<int> aMinutes, aHours, aDays, aMonths, aYears;
1059   aProp->GetModifications(aNames, aMinutes, aHours, aDays, aMonths, aYears);
1060
1061   int anIndex, aLength = aNames.size();
1062   std::vector<std::string> aDates;
1063
1064   for (anIndex = 1; anIndex < aLength; anIndex++) {
1065     char aDate[20];
1066     sprintf(aDate, "%2.2d/%2.2d/%4.4d %2.2d:%2.2d",
1067             (int)(aDays[anIndex]), (int)(aMonths[anIndex]), (int)(aYears[anIndex]),
1068             (int)(aHours[anIndex]), (int)(aMinutes[anIndex]));
1069     aDates.push_back(aDate);
1070   }
1071   return aDates;
1072 }
1073
1074
1075
1076 //============================================================================
1077 /*! Function : GetUseCaseBuilder
1078  *  Purpose  : Returns a UseCase builder
1079  */
1080 //============================================================================
1081 SALOMEDSImpl_UseCaseBuilder* SALOMEDSImpl_Study::GetUseCaseBuilder()
1082 {
1083   _errorCode = "";
1084   return _useCaseBuilder;
1085 }
1086
1087
1088 //============================================================================
1089 /*! Function : Close
1090  *  Purpose  :
1091  */
1092 //============================================================================
1093 void SALOMEDSImpl_Study::Close()
1094 {
1095   _errorCode = "";
1096   _notifier = 0;
1097   _doc->GetApplication()->Close(_doc);
1098   _doc = NULL;
1099   _mapOfSO.clear();
1100   _mapOfSCO.clear();
1101 }
1102
1103
1104 //============================================================================
1105 /*! Function : GetSComponent
1106  *  Purpose  :
1107  */
1108 //============================================================================
1109 SALOMEDSImpl_SComponent SALOMEDSImpl_Study::GetSComponent(const std::string& theEntry)
1110 {
1111   SALOMEDSImpl_SComponent aSCO;
1112   if(_mapOfSCO.find(theEntry) != _mapOfSCO.end())
1113     aSCO = _mapOfSCO[theEntry];
1114   else {
1115     DF_Label aLabel = DF_Label::Label(_doc->Main(), theEntry);
1116     aSCO = SALOMEDSImpl_SComponent(aLabel);
1117     _mapOfSCO[theEntry] = aSCO;
1118   }
1119
1120   return aSCO;
1121 }
1122
1123 //============================================================================
1124 /*! Function : GetSComponent
1125  *  Purpose  :
1126  */
1127 //============================================================================
1128 SALOMEDSImpl_SComponent SALOMEDSImpl_Study::GetSComponent(const DF_Label& theLabel)
1129 {
1130   return SALOMEDSImpl_SComponent(theLabel);
1131 }
1132
1133 //============================================================================
1134 /*! Function : GetSObject
1135  *  Purpose  :
1136  */
1137 //============================================================================
1138 SALOMEDSImpl_SObject SALOMEDSImpl_Study::GetSObject(const std::string& theEntry)
1139 {
1140   SALOMEDSImpl_SObject aSO;
1141   std::map<std::string, SALOMEDSImpl_SObject>::iterator it=_mapOfSO.find(theEntry);
1142   if(it != _mapOfSO.end())
1143     aSO = it->second;
1144   else {
1145     DF_Label aLabel = DF_Label::Label(_doc->Main(), theEntry);
1146     aSO = SALOMEDSImpl_SObject(aLabel);
1147     _mapOfSO[theEntry] = aSO;
1148   }
1149
1150   return aSO;
1151 }
1152
1153 //============================================================================
1154 /*! Function : GetSObject
1155  *  Purpose  :
1156  */
1157 //============================================================================
1158 SALOMEDSImpl_SObject SALOMEDSImpl_Study::GetSObject(const DF_Label& theLabel)
1159 {
1160   return SALOMEDSImpl_SObject(theLabel);
1161 }
1162
1163 //============================================================================
1164 /*! Function : GetAttribute
1165  *  Purpose  :
1166  */
1167 //============================================================================
1168 DF_Attribute* SALOMEDSImpl_Study::GetAttribute(const std::string& theEntry,
1169                                                const std::string& theType)
1170 {
1171   SALOMEDSImpl_SObject aSO = GetSObject(theEntry);
1172   DF_Attribute* anAttr;
1173   aSO.FindAttribute(anAttr, theType);
1174   return anAttr;
1175 }
1176
1177 //! number of spaces for indentation in Python dump files (to replace \t symbols)
1178 static const int indent_size = 2;
1179
1180 static std::string replace_tabs( const std::string& in )
1181 {
1182   std::string out = in;
1183 #ifdef WITHOUT_TABS
1184   size_t pos = out.find( '\t' );
1185   while ( pos != std::string::npos ) {
1186     out.replace( pos, 1, indent_size, ' ' );
1187     pos = out.find( '\t' );
1188   }
1189 #endif
1190   return out;
1191 }
1192
1193 static std::string GetComponentHeader(const char* theComponentName)
1194 {
1195   std::stringstream txt;
1196   txt << "###" << std::endl;
1197   txt << "### " << theComponentName << " component" << std::endl;
1198   txt << "###" << std::endl;
1199   return txt.str();
1200 }
1201
1202 //============================================================================
1203 /*! Function : DumpStudy
1204  *  Purpose  :
1205  */
1206 //============================================================================
1207 bool SALOMEDSImpl_Study::DumpStudy(const std::string& thePath,
1208                                    const std::string& theBaseName,
1209                                    bool isPublished,
1210                                    bool isMultiFile,
1211                                    SALOMEDSImpl_DriverFactory* theFactory)
1212 {
1213   _errorCode = "";
1214
1215   if(theFactory == NULL) {
1216     _errorCode = "Null factory for creation of Engines";
1217     return false;
1218   }
1219
1220   std::vector<std::string> aSeq;
1221   std::string aCompType, aFactoryType;
1222
1223   //Build a list of all components in the Study
1224   SALOMEDSImpl_SComponentIterator itcomponent = NewComponentIterator();
1225
1226   for (; itcomponent.More(); itcomponent.Next()) {
1227     SALOMEDSImpl_SComponent sco = itcomponent.Value();
1228     aCompType = sco.ComponentDataType();
1229     //GEOM and MED are independent components
1230     if (aCompType == "GEOM" || aCompType == "MED")
1231       aSeq.insert(aSeq.begin(), aCompType);
1232     else
1233       aSeq.push_back(aCompType);
1234   }
1235
1236 #ifdef WIN32
1237   std::string aFileName =
1238     thePath + std::string("\\") + theBaseName + std::string(".py");
1239 #else
1240   std::string aFileName =
1241     thePath + std::string("/")  + theBaseName + std::string(".py");
1242 #endif
1243
1244   //Create a file that will contain a main Study script
1245   std::fstream fp;
1246   fp.open(aFileName.c_str(), std::ios::out);
1247
1248 #ifdef WIN32
1249   bool isOpened = fp.is_open();
1250 #else
1251   bool isOpened = fp.rdbuf()->is_open();
1252 #endif
1253
1254   if(!isOpened) {
1255     _errorCode = std::string("Can't create a file ")+aFileName;
1256     return false;
1257   }
1258
1259   std::stringstream sfp;
1260
1261   std::string aBatchModeScript = "salome";
1262
1263   //Output to the main Study script required Python modules import,
1264   //set sys.path and add a creation of the study.
1265
1266   // dump header
1267   sfp << GetDumpStudyComment() << std::endl;
1268
1269   // global imports
1270   sfp << "import sys" << std::endl;
1271   sfp << "import " << aBatchModeScript << std::endl << std::endl;
1272
1273   std::string aStudyVar = "salome.myStudy";
1274   // initialization function
1275   sfp << aBatchModeScript << ".salome_init()" << std::endl;
1276   if ( !isMultiFile ) {
1277     sfp << "theStudy = " << aStudyVar << std::endl << std::endl;
1278     aStudyVar = "theStudy";
1279   }
1280   // notebook initialization
1281   sfp << _GetNoteBookAccess(aStudyVar) << std::endl;
1282
1283   // extend sys.path with the directory where the script is being dumped to
1284   sfp << "sys.path.insert( 0, r\'" << thePath << "\')" << std::endl << std::endl;
1285
1286   // dump NoteBook variables
1287   sfp << _GetStudyVariablesScript();
1288
1289   // dump visual parameters if necessary
1290   bool isDumpVisuals = SALOMEDSImpl_IParameters::isDumpPython(this);
1291   int lastSavePoint = -1;
1292   if(isDumpVisuals) {
1293     lastSavePoint = SALOMEDSImpl_IParameters::getLastSavePoint(this);
1294     if(lastSavePoint > 0) {
1295       sfp << SALOMEDSImpl_IParameters::getStudyScript(this, lastSavePoint) << std::endl << std::endl;
1296     }
1297   }
1298
1299   std::vector<std::string> aSeqOfFileNames;
1300
1301   // dump all components and create the components specific scripts
1302   bool isOk = true;
1303   int aLength = aSeq.size();
1304   for(int i = 1; i <= aLength; i++) {
1305
1306     aCompType = aSeq[i-1];
1307     SALOMEDSImpl_SComponent sco = FindComponent(aCompType);
1308     SALOMEDSImpl_Driver* aDriver = NULL;
1309     // if there is an associated Engine call its method for saving
1310     std::string IOREngine;
1311     try {
1312       if (!sco.ComponentIOR(IOREngine)) {
1313         if (!aCompType.empty()) {
1314
1315           aDriver = theFactory->GetDriverByType(aCompType);
1316
1317           if (aDriver != NULL) {
1318             SALOMEDSImpl_StudyBuilder* SB = NewBuilder();
1319             if(!SB->LoadWith(sco, aDriver)) {
1320               _errorCode = SB->GetErrorCode();
1321               return false;
1322             }
1323           }
1324           else continue;
1325         }
1326       }
1327       else {
1328         aDriver = theFactory->GetDriverByIOR(IOREngine);
1329       }
1330     } catch(...) {
1331       _errorCode = "Can not restore information to dump it";
1332       return false;
1333     }
1334
1335     if(aDriver == NULL) continue;
1336
1337     bool isValidScript;
1338     long aStreamLength  = 0;
1339     SALOMEDSImpl_TMPFile* aStream = aDriver->DumpPython(this, isPublished, isMultiFile, isValidScript, aStreamLength);
1340     if ( !isValidScript )
1341       isOk = false;
1342
1343     std::stringstream sfp2;
1344     
1345     //Output the Python script generated by the component in the newly created file.
1346     if ( isMultiFile )
1347       sfp2 << GetDumpStudyComment( aCompType.c_str() ) << std::endl;
1348     else
1349       sfp2 << GetComponentHeader( aCompType.c_str() ) << std::endl;
1350     sfp2 << aStream->Data();
1351     
1352     if ( isMultiFile ) {
1353       //Create a file that will contain the component specific script
1354       std::fstream fp2;
1355 #ifdef WIN32
1356       aFileName=thePath+std::string("\\");
1357 #else
1358       aFileName=thePath+std::string("/");
1359 #endif
1360       std::string aScriptName;
1361       aScriptName += theBaseName;
1362       aScriptName += "_";
1363       aScriptName += aCompType;
1364       
1365       aFileName += aScriptName+ std::string(".py");
1366       aSeqOfFileNames.push_back(aFileName);
1367       
1368       fp2.open(aFileName.c_str(), std::ios::out);
1369       
1370 #ifdef WIN32
1371       isOpened = fp2.is_open();
1372 #else
1373       isOpened = fp2.rdbuf()->is_open();
1374 #endif
1375       
1376       if(!isOpened) {
1377         _errorCode = std::string("Can't create a file ")+aFileName;
1378         SALOMEDSImpl_Tool::RemoveTemporaryFiles(thePath, aSeqOfFileNames, false);
1379         return false;
1380       }
1381      
1382       // replace '\t' symbols
1383       fp2 << replace_tabs( sfp2.str() );
1384
1385       fp2.close();
1386
1387       //Add to the main script a call to RebuildData of the generated by the component the Python script
1388       sfp << "import " << aScriptName << std::endl;
1389       sfp << aScriptName << ".RebuildData(" << aBatchModeScript << ".myStudy)" << std::endl;
1390     }
1391     else
1392       sfp << sfp2.str();
1393
1394     if(aStream) delete aStream;
1395   }
1396
1397   sfp << std::endl;
1398   sfp << "if salome.sg.hasDesktop():" << std::endl;
1399   sfp << "\tsalome.sg.updateObjBrowser(1)" << std::endl;
1400
1401   if(isDumpVisuals) { //Output the call to Session's method restoreVisualState
1402     sfp << "\tiparameters.getSession().restoreVisualState(1)" << std::endl;
1403   }
1404
1405   // replace '\t' symbols
1406   fp << replace_tabs( sfp.str() );
1407   
1408   fp.close();
1409
1410   return isOk;
1411 }
1412
1413 //=======================================================================
1414 //function : GetDumpStudyComment
1415 //purpose  : return a header comment for a DumpStudy script
1416 //=======================================================================
1417
1418 std::string SALOMEDSImpl_Study::GetDumpStudyComment(const char* theComponentName)
1419 {
1420   std::stringstream txt;
1421   txt << "# -*- coding: utf-8 -*-" << std::endl << std::endl;
1422   txt << "###" << std::endl;
1423   txt << "### This file is generated automatically by SALOME v"
1424       << KERNEL_VERSION_STR
1425       << " with dump python functionality";
1426   if ( theComponentName )
1427     txt << " (" << theComponentName << " component)";
1428   txt << std::endl;
1429   txt << "###" << std::endl;
1430   return txt.str();
1431 }
1432
1433 void dumpSO(const SALOMEDSImpl_SObject& theSO,
1434             std::fstream& fp,
1435             const std::string& Tab,
1436             SALOMEDSImpl_Study* theStudy);
1437
1438 //============================================================================
1439 /*! Function : dump
1440  *  Purpose  :
1441  */
1442 //============================================================================
1443 void SALOMEDSImpl_Study::dump(const std::string& theFileName)
1444 {
1445   //Create a file that will contain a main Study script
1446   std::fstream fp;
1447   fp.open(theFileName.c_str(), std::ios::out);
1448
1449 #ifdef WIN32
1450   bool isOpened = fp.is_open();
1451 #else
1452   bool isOpened = fp.rdbuf()->is_open();
1453 #endif
1454
1455   if(!isOpened) {
1456     _errorCode = std::string("Can't create a file ")+theFileName;
1457     std::cout << "### SALOMEDSImpl_Study::dump Error: " << _errorCode << std::endl;
1458     return;
1459   }
1460
1461   SALOMEDSImpl_SObject aSO = FindObjectID("0:1");
1462   fp << "0:1" << std::endl;
1463   SALOMEDSImpl_ChildIterator Itr = NewChildIterator(aSO);
1464   std::string aTab("   ");
1465   for(; Itr.More(); Itr.Next()) {
1466     dumpSO(Itr.Value(), fp, aTab, this);
1467   }
1468
1469   fp.close();
1470 }
1471
1472
1473 void dumpSO(const SALOMEDSImpl_SObject& theSO,
1474             std::fstream& fp,
1475             const std::string& Tab,
1476             SALOMEDSImpl_Study* theStudy)
1477 {
1478   std::string aTab(Tab), anID(theSO.GetID());
1479   fp << aTab << anID << std::endl;
1480   std::vector<DF_Attribute*> attribs = theSO.GetLabel().GetAttributes();
1481   for(int i = 0; i<attribs.size(); i++) {
1482     SALOMEDSImpl_GenericAttribute* anAttr = dynamic_cast<SALOMEDSImpl_GenericAttribute*>(attribs[i]);
1483
1484     if(!anAttr) {
1485       continue;
1486     }
1487
1488     std::string aType = anAttr->GetClassType();
1489     fp << Tab << "  -- " << aType;
1490
1491     if(aType == std::string("AttributeReal")) {
1492       fp << " : " << dynamic_cast<SALOMEDSImpl_AttributeReal*>(anAttr)->Value();
1493     }
1494     else if(aType == std::string("AttributeInteger")) {
1495       fp << " : " << dynamic_cast<SALOMEDSImpl_AttributeInteger*>(anAttr)->Value();
1496     }
1497     else if(aType ==  std::string("AttributeName")) {
1498       fp << " : " << dynamic_cast<SALOMEDSImpl_AttributeName*>(anAttr)->Value();
1499     }
1500     else if(aType == std::string("AttributeComment")) {
1501       fp << " : " << dynamic_cast<SALOMEDSImpl_AttributeComment*>(anAttr)->Value();
1502     }
1503     else if(aType == std::string("AttributeReference")) {
1504       fp << " : " << dynamic_cast<SALOMEDSImpl_AttributeReference*>(anAttr)->Save();
1505     }
1506     fp << std::endl;
1507   }
1508
1509   SALOMEDSImpl_ChildIterator Itr = theStudy->NewChildIterator(theSO);
1510   std::string aNewTab("   ");
1511   aNewTab+=aTab;
1512   for(; Itr.More(); Itr.Next()) {
1513     dumpSO(Itr.Value(), fp, aNewTab, theStudy);
1514   }
1515
1516   return;
1517 }
1518
1519 void SALOMEDSImpl_Study::Modify()
1520 {
1521   _errorCode = "";
1522   _doc->SetModified(true);
1523 }
1524
1525 //============================================================================
1526 /*! Function :
1527  *  Purpose  :
1528  */
1529 //============================================================================
1530 SALOMEDSImpl_AttributeParameter* SALOMEDSImpl_Study::GetCommonParameters(const char* theID, int theSavePoint)
1531 {
1532   if (theSavePoint < -1) return NULL;
1533   SALOMEDSImpl_StudyBuilder* builder = NewBuilder();
1534   SALOMEDSImpl_SObject so = FindComponent((char*)theID);
1535   if (!so) so = builder->NewComponent((char*)theID);
1536   SALOMEDSImpl_AttributeParameter* attParam = NULL;
1537
1538   if (theSavePoint == -1) {
1539     int ctag = 1;
1540     DF_Label savePointLabel = so.GetLabel().FindChild( ctag, /*create=*/0 );
1541     DF_Label prevPointLabel;
1542     while ( !savePointLabel.IsNull() ) {
1543       ctag++;
1544       prevPointLabel = savePointLabel;
1545       savePointLabel = so.GetLabel().FindChild( ctag, /*create=*/0 );
1546     }
1547     if ( !prevPointLabel.IsNull() )
1548       so = GetSObject( prevPointLabel );
1549   }
1550   if (theSavePoint > 0) { // Try to find SObject that contains attribute parameter ...
1551     DF_Label savePointLabel = so.GetLabel().FindChild( theSavePoint, /*create=*/0 );
1552     if ( !savePointLabel.IsNull() )
1553       so = GetSObject( savePointLabel );
1554     else // ... if it does not exist - create a new one
1555       so = builder->NewObjectToTag( so, theSavePoint );
1556   }
1557
1558   DF_Attribute* A;
1559   if (so) {
1560     builder->FindAttribute(so, A, "AttributeParameter");
1561     if ( !A ) { // first call of GetCommonParameters on "Interface Applicative" component
1562       A = builder->FindOrCreateAttribute(so, "AttributeParameter");
1563     }
1564     attParam = dynamic_cast<SALOMEDSImpl_AttributeParameter*>( A );
1565   }
1566   return attParam;
1567 }
1568
1569 //============================================================================
1570 /*! Function :
1571  *  Purpose  :
1572  */
1573 //============================================================================
1574 SALOMEDSImpl_AttributeParameter* SALOMEDSImpl_Study::GetModuleParameters(const char* theID,
1575                                                                          const char* theModuleName,
1576                                                                          int theSavePoint)
1577 {
1578   if(theSavePoint < -1) return NULL;
1579   SALOMEDSImpl_AttributeParameter* main_ap = GetCommonParameters(theID, theSavePoint);
1580   SALOMEDSImpl_SObject main_so = main_ap->GetSObject();
1581   SALOMEDSImpl_AttributeParameter* par = NULL;
1582
1583   SALOMEDSImpl_ChildIterator it = NewChildIterator(main_so);
1584   std::string moduleName(theModuleName);
1585   for(; it.More(); it.Next()) {
1586     SALOMEDSImpl_SObject so(it.Value());
1587     if((par=(SALOMEDSImpl_AttributeParameter*)so.GetLabel().FindAttribute(SALOMEDSImpl_AttributeParameter::GetID()))) {
1588       if(!par->IsSet("AP_MODULE_NAME", (Parameter_Types)3)) continue; //3 -> PT_STRING
1589       if(par->GetString("AP_MODULE_NAME") == moduleName) return par;
1590     }
1591   }
1592
1593   SALOMEDSImpl_StudyBuilder* builder = NewBuilder();
1594   SALOMEDSImpl_SObject so = builder->NewObject(main_so);
1595   par  = dynamic_cast<SALOMEDSImpl_AttributeParameter*>(builder->FindOrCreateAttribute(so, "AttributeParameter"));
1596   par->SetString("AP_MODULE_NAME", moduleName);
1597   return par;
1598 }
1599
1600 //============================================================================
1601 /*! Function : SetStudyLock
1602  *  Purpose  :
1603  */
1604 //============================================================================
1605 void SALOMEDSImpl_Study::SetStudyLock(const char* theLockerID)
1606 {
1607   _lockers.push_back(theLockerID);
1608 }
1609
1610 //============================================================================
1611 /*! Function : IsStudyLocked
1612  *  Purpose  :
1613  */
1614 //============================================================================
1615 bool SALOMEDSImpl_Study::IsStudyLocked()
1616 {
1617   return (_lockers.size() > 0);
1618 }
1619
1620 //============================================================================
1621 /*! Function : UnLockStudy
1622  *  Purpose  :
1623  */
1624 //============================================================================
1625 void SALOMEDSImpl_Study::UnLockStudy(const char* theLockerID)
1626 {
1627   std::vector<std::string>::iterator vsI = _lockers.begin();
1628   int length = _lockers.size();
1629   bool isFound = false;
1630   std::string id(theLockerID);
1631   for(int i = 0; i<length; i++, vsI++) {
1632     if(id == _lockers[i]) {
1633       isFound = true;;
1634       break;
1635     }
1636   }
1637   if(isFound) _lockers.erase(vsI);
1638 }
1639
1640 //============================================================================
1641 /*! Function : GetLockerID
1642  *  Purpose  :
1643  */
1644 //============================================================================
1645 std::vector<std::string> SALOMEDSImpl_Study::GetLockerID()
1646 {
1647   return _lockers;
1648 }
1649
1650 //============================================================================
1651 /*! Function : SetVariable
1652  *  Purpose  :
1653  */
1654 //============================================================================
1655 void SALOMEDSImpl_Study::SetVariable(const std::string& theVarName,
1656                                      const double theValue,
1657                                      const SALOMEDSImpl_GenericVariable::VariableTypes theType)
1658 {
1659   bool modified = false;
1660   SALOMEDSImpl_GenericVariable* aGVar = GetVariable(theVarName);
1661
1662   if( aGVar == NULL ) {
1663
1664     SALOMEDSImpl_ScalarVariable* aSVar = new SALOMEDSImpl_ScalarVariable(theType, theVarName);
1665
1666     aSVar->setValue(theValue);
1667     myNoteBookVars.push_back(aSVar);
1668     modified = true;
1669   }
1670   else {
1671     if(SALOMEDSImpl_ScalarVariable* aSVar = dynamic_cast<SALOMEDSImpl_ScalarVariable*>(aGVar)) {
1672       modified = aSVar->setValue(theValue) || modified;
1673       modified = aSVar->setType(theType) || modified;
1674     }
1675   }
1676   if(modified)
1677     Modify();
1678 }
1679
1680 //============================================================================
1681 /*! Function : SetStringVariable
1682  *  Purpose  :
1683  */
1684 //============================================================================
1685 void SALOMEDSImpl_Study::SetStringVariable(const std::string& theVarName,
1686                                            const std::string& theValue,
1687                                            const SALOMEDSImpl_GenericVariable::VariableTypes theType)
1688 {
1689   bool modified = false;
1690   SALOMEDSImpl_GenericVariable* aGVar = GetVariable(theVarName);
1691
1692   if( aGVar == NULL ) {
1693
1694     SALOMEDSImpl_ScalarVariable* aSVar = new SALOMEDSImpl_ScalarVariable(theType, theVarName);
1695
1696     aSVar->setStringValue(theValue);
1697     myNoteBookVars.push_back(aSVar);
1698     modified = true;
1699   }
1700   else {
1701     if(SALOMEDSImpl_ScalarVariable* aSVar = dynamic_cast<SALOMEDSImpl_ScalarVariable*>(aGVar)) {
1702       modified = aSVar->setStringValue(theValue) || modified;
1703       modified = aSVar->setType(theType) || modified;
1704     }
1705   }
1706   if(modified)
1707     Modify();
1708 }
1709
1710 //============================================================================
1711 /*! Function : SetStringVariableAsDouble
1712  *  Purpose  :
1713  */
1714 //============================================================================
1715 void SALOMEDSImpl_Study::SetStringVariableAsDouble(const std::string& theVarName,
1716                                                    const double theValue,
1717                                                    const SALOMEDSImpl_GenericVariable::VariableTypes theType)
1718 {
1719   SALOMEDSImpl_GenericVariable* aGVar = GetVariable(theVarName);
1720   if(SALOMEDSImpl_ScalarVariable* aSVar = dynamic_cast<SALOMEDSImpl_ScalarVariable*>(aGVar))
1721     aSVar->setValue(theValue);
1722 }
1723
1724 //============================================================================
1725 /*! Function : GetReal
1726  *  Purpose  :
1727  */
1728 //============================================================================
1729 double SALOMEDSImpl_Study::GetVariableValue(const std::string& theVarName)
1730 {
1731   SALOMEDSImpl_GenericVariable* aGVar = GetVariable(theVarName);
1732
1733   if(aGVar != NULL )
1734     if(SALOMEDSImpl_ScalarVariable* aSVar = dynamic_cast<SALOMEDSImpl_ScalarVariable*>(aGVar))
1735       return aSVar->getValue();
1736
1737   return 0;
1738 }
1739
1740 //============================================================================
1741 /*! Function : GetString
1742  *  Purpose  :
1743  */
1744 //============================================================================
1745 std::string SALOMEDSImpl_Study::GetStringVariableValue(const std::string& theVarName)
1746 {
1747   SALOMEDSImpl_GenericVariable* aGVar = GetVariable(theVarName);
1748
1749   if(aGVar != NULL )
1750     if(SALOMEDSImpl_ScalarVariable* aSVar = dynamic_cast<SALOMEDSImpl_ScalarVariable*>(aGVar))
1751       return aSVar->getStringValue();
1752
1753   return 0;
1754 }
1755
1756 //============================================================================
1757 /*! Function : IsTypeOf
1758  *  Purpose  :
1759  */
1760 //============================================================================
1761 bool SALOMEDSImpl_Study::IsTypeOf(const std::string& theVarName,
1762                                   SALOMEDSImpl_GenericVariable::
1763                                   VariableTypes theType) const
1764 {
1765   SALOMEDSImpl_GenericVariable* aGVar = GetVariable(theVarName);
1766
1767   if(aGVar != NULL )
1768     return aGVar->Type() == theType;
1769
1770   return false;
1771 }
1772
1773 //============================================================================
1774 /*! Function : IsVariable
1775  *  Purpose  :
1776  */
1777 //============================================================================
1778 bool SALOMEDSImpl_Study::IsVariable(const std::string& theVarName) const
1779 {
1780   SALOMEDSImpl_GenericVariable* aGVar = GetVariable(theVarName);
1781   return (aGVar != NULL);
1782 }
1783
1784 //============================================================================
1785 /*! Function : GetVariableNames
1786  *  Purpose  :
1787  */
1788 //============================================================================
1789 std::vector<std::string> SALOMEDSImpl_Study::GetVariableNames() const
1790 {
1791   std::vector<std::string> aResult;
1792
1793   for(int i = 0; i < myNoteBookVars.size(); i++)
1794     aResult.push_back(myNoteBookVars[i]->Name());
1795
1796   return aResult;
1797 }
1798
1799 //============================================================================
1800 /*! Function : AddVariable
1801  *  Purpose  :
1802  */
1803 //============================================================================
1804 void SALOMEDSImpl_Study::AddVariable(SALOMEDSImpl_GenericVariable* theVariable)
1805 {
1806   myNoteBookVars.push_back(theVariable);
1807 }
1808
1809 //============================================================================
1810 /*! Function : AddVariable
1811  *  Purpose  :
1812  */
1813 //============================================================================
1814 SALOMEDSImpl_GenericVariable* SALOMEDSImpl_Study::GetVariable(const std::string& theName) const
1815 {
1816   SALOMEDSImpl_GenericVariable* aResult = NULL;
1817   for(int i = 0; i < myNoteBookVars.size();i++) {
1818     if(theName.compare(myNoteBookVars[i]->Name()) == 0) {
1819       aResult = myNoteBookVars[i];
1820       break;
1821     }
1822   }
1823   return aResult;
1824 }
1825
1826 //============================================================================
1827 /*! Function : RemoveVariable
1828  *  Purpose  :
1829  */
1830 //============================================================================
1831 bool SALOMEDSImpl_Study::RemoveVariable(const std::string& theVarName)
1832 {
1833   SALOMEDSImpl_GenericVariable* aVariable = GetVariable( theVarName );
1834   if( !aVariable )
1835     return false;
1836
1837   std::string aValue = aVariable->SaveToScript();
1838   ReplaceVariableAttribute( theVarName, aValue );
1839
1840   std::vector<SALOMEDSImpl_GenericVariable*>::iterator it = myNoteBookVars.begin(), itEnd = myNoteBookVars.end();
1841   for( ; it != itEnd; it++ )
1842   {
1843     SALOMEDSImpl_GenericVariable* aVariableRef = *it;
1844     if( aVariableRef && theVarName.compare( aVariableRef->Name() ) == 0 )
1845     {
1846       myNoteBookVars.erase( it );
1847       Modify();
1848       break;
1849     }
1850   }
1851
1852   return true;
1853 }
1854
1855 //============================================================================
1856 /*! Function : RenameVariable
1857  *  Purpose  :
1858  */
1859 //============================================================================
1860 bool SALOMEDSImpl_Study::RenameVariable(const std::string& theVarName, const std::string& theNewVarName)
1861 {
1862   SALOMEDSImpl_GenericVariable* aVariable = GetVariable( theVarName );
1863   if( !aVariable )
1864     return false;
1865
1866   ReplaceVariableAttribute( theVarName, theNewVarName );
1867
1868   std::vector<SALOMEDSImpl_GenericVariable*>::iterator it = myNoteBookVars.begin(), itEnd = myNoteBookVars.end();
1869   for( ; it != itEnd; it++ )
1870   {
1871     SALOMEDSImpl_GenericVariable* aVariableRef = *it;
1872     if( aVariableRef && theVarName.compare( aVariableRef->Name() ) == 0 )
1873     {
1874       aVariableRef->setName( theNewVarName );
1875       Modify();
1876       break;
1877     }
1878   }
1879
1880   return true;
1881 }
1882
1883 //============================================================================
1884 /*! Function : IsVariableUsed
1885  *  Purpose  :
1886  */
1887 //============================================================================
1888 bool SALOMEDSImpl_Study::IsVariableUsed(const std::string& theVarName)
1889 {
1890   return FindVariableAttribute( theVarName );
1891 }
1892
1893 //============================================================================
1894 /*! Function : FindVariableAttribute
1895  *  Purpose  :
1896  */
1897 //============================================================================
1898 bool SALOMEDSImpl_Study::FindVariableAttribute(SALOMEDSImpl_StudyBuilder* theStudyBuilder,
1899                                                SALOMEDSImpl_SObject theSObject,
1900                                                const std::string& theName)
1901 {
1902   SALOMEDSImpl_ChildIterator anIter = NewChildIterator( theSObject );
1903   for( ; anIter.More(); anIter.Next() )
1904     if( FindVariableAttribute( theStudyBuilder, anIter.Value(), theName ) )
1905       return true;
1906
1907   DF_Attribute* anAttr;
1908   if( theStudyBuilder->FindAttribute( theSObject, anAttr, "AttributeString" ) )
1909   {
1910     if( SALOMEDSImpl_AttributeString* aStringAttr = ( SALOMEDSImpl_AttributeString* )anAttr )
1911     {
1912       std::string aString = aStringAttr->Value();
1913
1914       std::vector< std::vector<std::string> > aSections = ParseVariables( aString );
1915       for( int i = 0, n = aSections.size(); i < n; i++ )
1916       {
1917         std::vector<std::string> aVector = aSections[i];
1918         for( int j = 0, m = aVector.size(); j < m; j++ )
1919         {
1920           std::string aStr = aVector[j];
1921           if( aStr.compare( theName ) == 0 )
1922             return true;
1923         }
1924       }
1925     }
1926   }
1927   return false;
1928 }
1929
1930 //============================================================================
1931 /*! Function : FindVariableAttribute
1932  *  Purpose  :
1933  */
1934 //============================================================================
1935 bool SALOMEDSImpl_Study::FindVariableAttribute(const std::string& theName)
1936 {
1937   SALOMEDSImpl_StudyBuilder* aStudyBuilder = NewBuilder();
1938   SALOMEDSImpl_SComponentIterator aCompIter = NewComponentIterator();
1939   for( ; aCompIter.More(); aCompIter.Next() )
1940   {
1941     SALOMEDSImpl_SObject aComp = aCompIter.Value();
1942     if( FindVariableAttribute( aStudyBuilder, aComp, theName ) )
1943       return true;
1944   }
1945   return false;
1946 }
1947
1948 //============================================================================
1949 /*! Function : ReplaceVariableAttribute
1950  *  Purpose  :
1951  */
1952 //============================================================================
1953 void SALOMEDSImpl_Study::ReplaceVariableAttribute(SALOMEDSImpl_StudyBuilder* theStudyBuilder,
1954                                                   SALOMEDSImpl_SObject theSObject,
1955                                                   const std::string& theSource,
1956                                                   const std::string& theDest)
1957 {
1958   SALOMEDSImpl_ChildIterator anIter = NewChildIterator( theSObject );
1959   for( ; anIter.More(); anIter.Next() )
1960     ReplaceVariableAttribute( theStudyBuilder, anIter.Value(), theSource, theDest );
1961
1962   DF_Attribute* anAttr;
1963   if( theStudyBuilder->FindAttribute( theSObject, anAttr, "AttributeString" ) )
1964   {
1965     if( SALOMEDSImpl_AttributeString* aStringAttr = ( SALOMEDSImpl_AttributeString* )anAttr )
1966     {
1967       bool isChanged = false;
1968       std::string aNewString, aCurrentString = aStringAttr->Value();
1969
1970       std::vector< std::vector<std::string> > aSections = ParseVariables( aCurrentString );
1971       for( int i = 0, n = aSections.size(); i < n; i++ )
1972       {
1973         std::vector<std::string> aVector = aSections[i];
1974         for( int j = 0, m = aVector.size(); j < m; j++ )
1975         {
1976           std::string aStr = aVector[j];
1977           if( aStr.compare( theSource ) == 0 )
1978           {
1979             isChanged = true;
1980             aStr = theDest;
1981           }
1982
1983           aNewString.append( aStr );
1984           if( j != m - 1 )
1985             aNewString.append( ":" );
1986         }
1987         if( i != n - 1 )
1988           aNewString.append( "|" );
1989       }
1990
1991       if( isChanged )
1992         aStringAttr->SetValue( aNewString );
1993     }
1994   }
1995 }
1996
1997 //============================================================================
1998 /*! Function : ReplaceVariableAttribute
1999  *  Purpose  :
2000  */
2001 //============================================================================
2002 void SALOMEDSImpl_Study::ReplaceVariableAttribute(const std::string& theSource, const std::string& theDest)
2003 {
2004   SALOMEDSImpl_StudyBuilder* aStudyBuilder = NewBuilder();
2005   SALOMEDSImpl_SComponentIterator aCompIter = NewComponentIterator();
2006   for( ; aCompIter.More(); aCompIter.Next() )
2007   {
2008     SALOMEDSImpl_SObject aComp = aCompIter.Value();
2009     ReplaceVariableAttribute( aStudyBuilder, aComp, theSource, theDest );
2010   }
2011 }
2012
2013 //============================================================================
2014 /*! Function : ParseVariables
2015  *  Purpose  :
2016  */
2017 //============================================================================
2018 std::vector< std::vector< std::string > > SALOMEDSImpl_Study::ParseVariables(const std::string& theVariables) const
2019 {
2020   return SALOMEDSImpl_Tool::splitStringWithEmpty( theVariables, OPERATION_SEPARATOR, VARIABLE_SEPARATOR );
2021 }
2022
2023 //============================================================================
2024 /*! Function : EnableUseCaseAutoFilling
2025  *  Purpose  :
2026  */
2027 //============================================================================
2028 void SALOMEDSImpl_Study::EnableUseCaseAutoFilling(bool isEnabled)
2029 {
2030   _errorCode = ""; _autoFill = isEnabled;
2031   if(isEnabled) {
2032     _builder->SetOnAddSObject(_cb);
2033     _builder->SetOnRemoveSObject(_cb);
2034   }
2035   else {
2036     _builder->SetOnAddSObject(NULL);
2037     _builder->SetOnRemoveSObject(NULL);
2038   }
2039 }
2040
2041 //============================================================================
2042 /*! Function : GetIORs
2043  *  Purpose  :
2044  */
2045 //============================================================================
2046 std::vector<std::string> SALOMEDSImpl_Study::GetIORs()
2047 {
2048   std::vector<std::string> anIORs;
2049   std::map<std::string, DF_Label>::const_iterator MI;
2050   for(MI = myIORLabels.begin(); MI!=myIORLabels.end(); MI++)
2051     anIORs.push_back(MI->first);
2052
2053   return anIORs;
2054 }
2055
2056 //============================================================================
2057 /*! Function : addSO_Notification
2058  *  Purpose  : This function tells all the observers that a SO has been added
2059  */
2060 //============================================================================
2061 bool SALOMEDSImpl_Study::addSO_Notification (const SALOMEDSImpl_SObject& theSObject)
2062 {
2063   if(_notifier)
2064     return _notifier->addSO_Notification(theSObject);
2065   else
2066     return false;
2067 }
2068
2069 //============================================================================
2070 /*! Function : removeSO_Notification
2071  *  Purpose  : This function tells all the observers that a SO has been removed
2072  */
2073 //============================================================================
2074 bool SALOMEDSImpl_Study::removeSO_Notification (const SALOMEDSImpl_SObject& theSObject)
2075 {
2076   if(_notifier)
2077     return _notifier->removeSO_Notification(theSObject);
2078   else
2079     return false;
2080 }
2081
2082 //============================================================================
2083 /*! Function : modifySO_Notification
2084  *  Purpose  : This function tells all the observers that a SO has been modified and
2085                pass the mofification reason
2086  */
2087 //============================================================================
2088 bool SALOMEDSImpl_Study::modifySO_Notification (const SALOMEDSImpl_SObject& theSObject, int reason) 
2089 {
2090   if(_notifier)
2091     return _notifier->modifySO_Notification(theSObject, reason);
2092   else
2093     return false;
2094 }
2095
2096 //============================================================================
2097 /*! Function : setNotifier
2098  *  Purpose  : register a notifier
2099  */
2100 //============================================================================
2101 void SALOMEDSImpl_Study::setNotifier(SALOMEDSImpl_AbstractCallback* notifier) 
2102 {
2103   _notifier=notifier;
2104 }
2105
2106 static SALOMEDSImpl_AbstractCallback* & getGenObjRegister( DF_Document* doc )
2107 {
2108   static std::vector< SALOMEDSImpl_AbstractCallback* > _genObjRegVec;
2109   if ( doc->GetDocumentID() >= (int)_genObjRegVec.size() )
2110     _genObjRegVec.resize( doc->GetDocumentID() + 1, 0 );
2111   return _genObjRegVec[ doc->GetDocumentID() ];
2112 }
2113
2114 //================================================================================
2115 /*!
2116  * \brief Stores theRegister
2117  */
2118 //================================================================================
2119
2120 void SALOMEDSImpl_Study::setGenObjRegister(SALOMEDSImpl_AbstractCallback* theRegister)
2121 {
2122   getGenObjRegister( _doc ) = theRegister;
2123 }
2124
2125 //================================================================================
2126 /*!
2127  * \brief Indirectly invokes GenericObj_i::Register()
2128  */
2129 //================================================================================
2130
2131 void SALOMEDSImpl_Study::RegisterGenObj  (const std::string& theIOR, DF_Label label)
2132 {
2133   if ( SALOMEDSImpl_AbstractCallback* goRegister = getGenObjRegister( label.GetDocument() ))
2134     goRegister->RegisterGenObj( theIOR );
2135 }
2136
2137 //================================================================================
2138 /*!
2139  * \brief Indirectly invokes GenericObj_i::UnRegister()
2140  */
2141 //================================================================================
2142
2143 void SALOMEDSImpl_Study::UnRegisterGenObj(const std::string& theIOR, DF_Label label)
2144 {
2145   if ( SALOMEDSImpl_AbstractCallback* goRegister = getGenObjRegister( label.GetDocument() ))
2146     goRegister->UnRegisterGenObj( theIOR );
2147 }