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