Salome HOME
Fix configuration / compilation problems in KERNEL with libBatch (caused by wrong...
[modules/kernel.git] / src / SALOMEDSImpl / SALOMEDSImpl_Study.cxx
1 //  Copyright (C) 2007-2010  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 //  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 //  This library is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU Lesser General Public
8 //  License as published by the Free Software Foundation; either
9 //  version 2.1 of the License.
10 //
11 //  This library is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 //  Lesser General Public License for more details.
15 //
16 //  You should have received a copy of the GNU Lesser General Public
17 //  License along with this library; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 //  File   : SALOMEDSImpl_Study.cxx
24 //  Author : Sergey RUIN
25 //  Module : SALOME
26 //
27 #include "SALOMEDSImpl_Study.hxx"
28 #include <string.h>
29
30 #include <KERNEL_version.h>
31 #include <Basics_Utils.hxx>
32
33 #include "DF_Application.hxx"
34 #include "DF_ChildIterator.hxx"
35
36 #include "SALOMEDSImpl_ChildNodeIterator.hxx"
37 #include "SALOMEDSImpl_Attributes.hxx"
38 #include "SALOMEDSImpl_UseCaseIterator.hxx"
39 #include "SALOMEDSImpl_AttributeReference.hxx"
40 #include "SALOMEDSImpl_StudyHandle.hxx"
41 #include "SALOMEDSImpl_Tool.hxx"
42 #include "SALOMEDSImpl_IParameters.hxx"
43 #include "SALOMEDSImpl_ScalarVariable.hxx"
44
45 #include <fstream>
46 #include <sstream>
47
48 // 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 << std::endl;
1274
1275   // notebook initialization
1276   sfp << _GetNoteBookAccess();
1277
1278   // extend sys.path with the directory where the script is being dumped to
1279   sfp << "sys.path.insert( 0, r\'" << thePath << "\')" << std::endl << std::endl;
1280
1281   // dump NoteBook variables
1282   sfp << _GetStudyVariablesScript();
1283
1284   // dump visual parameters if necessary
1285   bool isDumpVisuals = SALOMEDSImpl_IParameters::isDumpPython(this);
1286   int lastSavePoint = -1;
1287   if(isDumpVisuals) {
1288     lastSavePoint = SALOMEDSImpl_IParameters::getLastSavePoint(this);
1289     if(lastSavePoint > 0) {
1290       sfp << SALOMEDSImpl_IParameters::getStudyScript(this, lastSavePoint) << std::endl << std::endl;
1291     }
1292   }
1293
1294   std::vector<std::string> aSeqOfFileNames;
1295
1296   // dump all components and create the components specific scripts
1297   bool isOk = true;
1298   int aLength = aSeq.size();
1299   for(int i = 1; i <= aLength; i++) {
1300
1301     aCompType = aSeq[i-1];
1302     SALOMEDSImpl_SComponent sco = FindComponent(aCompType);
1303     SALOMEDSImpl_Driver* aDriver = NULL;
1304     // if there is an associated Engine call its method for saving
1305     std::string IOREngine;
1306     try {
1307       if (!sco.ComponentIOR(IOREngine)) {
1308         if (!aCompType.empty()) {
1309
1310           aDriver = theFactory->GetDriverByType(aCompType);
1311
1312           if (aDriver != NULL) {
1313             SALOMEDSImpl_StudyBuilder* SB = NewBuilder();
1314             if(!SB->LoadWith(sco, aDriver)) {
1315               _errorCode = SB->GetErrorCode();
1316               return false;
1317             }
1318           }
1319           else continue;
1320         }
1321       }
1322       else {
1323         aDriver = theFactory->GetDriverByIOR(IOREngine);
1324       }
1325     } catch(...) {
1326       _errorCode = "Can not restore information to dump it";
1327       return false;
1328     }
1329
1330     if(aDriver == NULL) continue;
1331
1332     bool isValidScript;
1333     long aStreamLength  = 0;
1334     SALOMEDSImpl_TMPFile* aStream = aDriver->DumpPython(this, isPublished, isMultiFile, isValidScript, aStreamLength);
1335     if ( !isValidScript )
1336       isOk = false;
1337
1338     std::stringstream sfp2;
1339     
1340     //Output the Python script generated by the component in the newly created file.
1341     if ( isMultiFile )
1342       sfp2 << GetDumpStudyComment( aCompType.c_str() ) << std::endl;
1343     else
1344       sfp2 << GetComponentHeader( aCompType.c_str() ) << std::endl;
1345     sfp2 << aStream->Data();
1346     
1347     if ( isMultiFile ) {
1348       //Create a file that will contain the component specific script
1349       std::fstream fp2;
1350 #ifdef WIN32
1351       aFileName=thePath+std::string("\\");
1352 #else
1353       aFileName=thePath+std::string("/");
1354 #endif
1355       std::string aScriptName;
1356       aScriptName += theBaseName;
1357       aScriptName += "_";
1358       aScriptName += aCompType;
1359       
1360       aFileName += aScriptName+ std::string(".py");
1361       aSeqOfFileNames.push_back(aFileName);
1362       
1363       fp2.open(aFileName.c_str(), std::ios::out);
1364       
1365 #ifdef WIN32
1366       isOpened = fp2.is_open();
1367 #else
1368       isOpened = fp2.rdbuf()->is_open();
1369 #endif
1370       
1371       if(!isOpened) {
1372         _errorCode = std::string("Can't create a file ")+aFileName;
1373         SALOMEDSImpl_Tool::RemoveTemporaryFiles(thePath, aSeqOfFileNames, false);
1374         return false;
1375       }
1376      
1377       // replace '\t' symbols
1378       fp2 << replace_tabs( sfp2.str() );
1379
1380       fp2.close();
1381
1382       //Add to the main script a call to RebuildData of the generated by the component the Python script
1383       sfp << "import " << aScriptName << std::endl;
1384       sfp << aScriptName << ".RebuildData(" << aBatchModeScript << ".myStudy)" << std::endl;
1385     }
1386     else
1387       sfp << sfp2.str();
1388
1389     if(aStream) delete aStream;
1390   }
1391
1392   sfp << std::endl;
1393   sfp << "if salome.sg.hasDesktop():" << std::endl;
1394   sfp << "\tsalome.sg.updateObjBrowser(1)" << std::endl;
1395
1396   if(isDumpVisuals) { //Output the call to Session's method restoreVisualState
1397     sfp << "\tiparameters.getSession().restoreVisualState(1)" << std::endl;
1398   }
1399
1400   // replace '\t' symbols
1401   fp << replace_tabs( sfp.str() );
1402   
1403   fp.close();
1404
1405   return isOk;
1406 }
1407
1408 //=======================================================================
1409 //function : GetDumpStudyComment
1410 //purpose  : return a header comment for a DumpStudy script
1411 //=======================================================================
1412
1413 std::string SALOMEDSImpl_Study::GetDumpStudyComment(const char* theComponentName)
1414 {
1415   std::stringstream txt;
1416   txt << "# -*- coding: iso-8859-1 -*-" << std::endl << std::endl;
1417   txt << "###" << std::endl;
1418   txt << "### This file is generated automatically by SALOME v"
1419       << KERNEL_VERSION_STR
1420       << " with dump python functionality";
1421   if ( theComponentName )
1422     txt << " (" << theComponentName << " component)";
1423   txt << std::endl;
1424   txt << "###" << std::endl;
1425   return txt.str();
1426 }
1427
1428 void dumpSO(const SALOMEDSImpl_SObject& theSO,
1429             std::fstream& fp,
1430             const std::string& Tab,
1431             SALOMEDSImpl_Study* theStudy);
1432
1433 //============================================================================
1434 /*! Function : dump
1435  *  Purpose  :
1436  */
1437 //============================================================================
1438 void SALOMEDSImpl_Study::dump(const std::string& theFileName)
1439 {
1440   //Create a file that will contain a main Study script
1441   std::fstream fp;
1442   fp.open(theFileName.c_str(), std::ios::out);
1443
1444 #ifdef WIN32
1445   bool isOpened = fp.is_open();
1446 #else
1447   bool isOpened = fp.rdbuf()->is_open();
1448 #endif
1449
1450   if(!isOpened) {
1451     _errorCode = std::string("Can't create a file ")+theFileName;
1452     std::cout << "### SALOMEDSImpl_Study::dump Error: " << _errorCode << std::endl;
1453     return;
1454   }
1455
1456   SALOMEDSImpl_SObject aSO = FindObjectID("0:1");
1457   fp << "0:1" << std::endl;
1458   SALOMEDSImpl_ChildIterator Itr = NewChildIterator(aSO);
1459   std::string aTab("   ");
1460   for(; Itr.More(); Itr.Next()) {
1461     dumpSO(Itr.Value(), fp, aTab, this);
1462   }
1463
1464   fp.close();
1465 }
1466
1467
1468 void dumpSO(const SALOMEDSImpl_SObject& theSO,
1469             std::fstream& fp,
1470             const std::string& Tab,
1471             SALOMEDSImpl_Study* theStudy)
1472 {
1473   std::string aTab(Tab), anID(theSO.GetID());
1474   fp << aTab << anID << std::endl;
1475   std::vector<DF_Attribute*> attribs = theSO.GetLabel().GetAttributes();
1476   for(int i = 0; i<attribs.size(); i++) {
1477     SALOMEDSImpl_GenericAttribute* anAttr = dynamic_cast<SALOMEDSImpl_GenericAttribute*>(attribs[i]);
1478
1479     if(!anAttr) {
1480       continue;
1481     }
1482
1483     std::string aType = anAttr->GetClassType();
1484     fp << Tab << "  -- " << aType;
1485
1486     if(aType == std::string("AttributeReal")) {
1487       fp << " : " << dynamic_cast<SALOMEDSImpl_AttributeReal*>(anAttr)->Value();
1488     }
1489     else if(aType == std::string("AttributeInteger")) {
1490       fp << " : " << dynamic_cast<SALOMEDSImpl_AttributeInteger*>(anAttr)->Value();
1491     }
1492     else if(aType ==  std::string("AttributeName")) {
1493       fp << " : " << dynamic_cast<SALOMEDSImpl_AttributeName*>(anAttr)->Value();
1494     }
1495     else if(aType == std::string("AttributeComment")) {
1496       fp << " : " << dynamic_cast<SALOMEDSImpl_AttributeComment*>(anAttr)->Value();
1497     }
1498     else if(aType == std::string("AttributeReference")) {
1499       fp << " : " << dynamic_cast<SALOMEDSImpl_AttributeReference*>(anAttr)->Save();
1500     }
1501     fp << std::endl;
1502   }
1503
1504   SALOMEDSImpl_ChildIterator Itr = theStudy->NewChildIterator(theSO);
1505   std::string aNewTab("   ");
1506   aNewTab+=aTab;
1507   for(; Itr.More(); Itr.Next()) {
1508     dumpSO(Itr.Value(), fp, aNewTab, theStudy);
1509   }
1510
1511   return;
1512 }
1513
1514 void SALOMEDSImpl_Study::Modify()
1515 {
1516   _errorCode = "";
1517   _doc->SetModified(true);
1518 }
1519
1520 //============================================================================
1521 /*! Function :
1522  *  Purpose  :
1523  */
1524 //============================================================================
1525 SALOMEDSImpl_AttributeParameter* SALOMEDSImpl_Study::GetCommonParameters(const char* theID, int theSavePoint)
1526 {
1527   if (theSavePoint < 0) return NULL;
1528   SALOMEDSImpl_StudyBuilder* builder = NewBuilder();
1529   SALOMEDSImpl_SObject so = FindComponent((char*)theID);
1530   if (!so) so = builder->NewComponent((char*)theID);
1531   SALOMEDSImpl_AttributeParameter* attParam = NULL;
1532
1533   if (theSavePoint > 0) { // Try to find SObject that contains attribute parameter ...
1534     DF_Label savePointLabel = so.GetLabel().FindChild( theSavePoint, /*create=*/0 );
1535     if ( !savePointLabel.IsNull() )
1536       so = GetSObject( savePointLabel );
1537     else // ... if it does not exist - create a new one
1538       so = builder->NewObjectToTag( so, theSavePoint );
1539   }
1540
1541   DF_Attribute* A;
1542   if (so) {
1543     builder->FindAttribute(so, A, "AttributeParameter");
1544     if ( !A ) { // first call of GetCommonParameters on "Interface Applicative" component
1545       A = builder->FindOrCreateAttribute(so, "AttributeParameter");
1546     }
1547     attParam = dynamic_cast<SALOMEDSImpl_AttributeParameter*>( A );
1548   }
1549   return attParam;
1550 }
1551
1552 //============================================================================
1553 /*! Function :
1554  *  Purpose  :
1555  */
1556 //============================================================================
1557 SALOMEDSImpl_AttributeParameter* SALOMEDSImpl_Study::GetModuleParameters(const char* theID,
1558                                                                          const char* theModuleName,
1559                                                                          int theSavePoint)
1560 {
1561   if(theSavePoint <= 0) return NULL;
1562   SALOMEDSImpl_AttributeParameter* main_ap = GetCommonParameters(theID, theSavePoint);
1563   SALOMEDSImpl_SObject main_so = main_ap->GetSObject();
1564   SALOMEDSImpl_AttributeParameter* par = NULL;
1565
1566   SALOMEDSImpl_ChildIterator it = NewChildIterator(main_so);
1567   std::string moduleName(theModuleName);
1568   for(; it.More(); it.Next()) {
1569     SALOMEDSImpl_SObject so(it.Value());
1570     if((par=(SALOMEDSImpl_AttributeParameter*)so.GetLabel().FindAttribute(SALOMEDSImpl_AttributeParameter::GetID()))) {
1571       if(!par->IsSet("AP_MODULE_NAME", (Parameter_Types)3)) continue; //3 -> PT_STRING
1572       if(par->GetString("AP_MODULE_NAME") == moduleName) return par;
1573     }
1574   }
1575
1576   SALOMEDSImpl_StudyBuilder* builder = NewBuilder();
1577   SALOMEDSImpl_SObject so = builder->NewObject(main_so);
1578   par  = dynamic_cast<SALOMEDSImpl_AttributeParameter*>(builder->FindOrCreateAttribute(so, "AttributeParameter"));
1579   par->SetString("AP_MODULE_NAME", moduleName);
1580   return par;
1581 }
1582
1583 //============================================================================
1584 /*! Function : SetStudyLock
1585  *  Purpose  :
1586  */
1587 //============================================================================
1588 void SALOMEDSImpl_Study::SetStudyLock(const char* theLockerID)
1589 {
1590   _lockers.push_back(theLockerID);
1591 }
1592
1593 //============================================================================
1594 /*! Function : IsStudyLocked
1595  *  Purpose  :
1596  */
1597 //============================================================================
1598 bool SALOMEDSImpl_Study::IsStudyLocked()
1599 {
1600   return (_lockers.size() > 0);
1601 }
1602
1603 //============================================================================
1604 /*! Function : UnLockStudy
1605  *  Purpose  :
1606  */
1607 //============================================================================
1608 void SALOMEDSImpl_Study::UnLockStudy(const char* theLockerID)
1609 {
1610   std::vector<std::string>::iterator vsI = _lockers.begin();
1611   int length = _lockers.size();
1612   bool isFound = false;
1613   std::string id(theLockerID);
1614   for(int i = 0; i<length; i++, vsI++) {
1615     if(id == _lockers[i]) {
1616       isFound = true;;
1617       break;
1618     }
1619   }
1620   if(isFound) _lockers.erase(vsI);
1621 }
1622
1623 //============================================================================
1624 /*! Function : GetLockerID
1625  *  Purpose  :
1626  */
1627 //============================================================================
1628 std::vector<std::string> SALOMEDSImpl_Study::GetLockerID()
1629 {
1630   return _lockers;
1631 }
1632
1633 //============================================================================
1634 /*! Function : SetVariable
1635  *  Purpose  :
1636  */
1637 //============================================================================
1638 void SALOMEDSImpl_Study::SetVariable(const std::string& theVarName,
1639                                      const double theValue,
1640                                      const SALOMEDSImpl_GenericVariable::VariableTypes theType)
1641 {
1642   bool modified = false;
1643   SALOMEDSImpl_GenericVariable* aGVar = GetVariable(theVarName);
1644
1645   if( aGVar == NULL ) {
1646
1647     SALOMEDSImpl_ScalarVariable* aSVar = new SALOMEDSImpl_ScalarVariable(theType, theVarName);
1648
1649     aSVar->setValue(theValue);
1650     myNoteBookVars.push_back(aSVar);
1651     modified = true;
1652   }
1653   else {
1654     if(SALOMEDSImpl_ScalarVariable* aSVar = dynamic_cast<SALOMEDSImpl_ScalarVariable*>(aGVar)) {
1655       modified = aSVar->setValue(theValue) || modified;
1656       modified = aSVar->setType(theType) || modified;
1657     }
1658   }
1659   if(modified)
1660     Modify();
1661 }
1662
1663 //============================================================================
1664 /*! Function : SetStringVariable
1665  *  Purpose  :
1666  */
1667 //============================================================================
1668 void SALOMEDSImpl_Study::SetStringVariable(const std::string& theVarName,
1669                                            const std::string& theValue,
1670                                            const SALOMEDSImpl_GenericVariable::VariableTypes theType)
1671 {
1672   bool modified = false;
1673   SALOMEDSImpl_GenericVariable* aGVar = GetVariable(theVarName);
1674
1675   if( aGVar == NULL ) {
1676
1677     SALOMEDSImpl_ScalarVariable* aSVar = new SALOMEDSImpl_ScalarVariable(theType, theVarName);
1678
1679     aSVar->setStringValue(theValue);
1680     myNoteBookVars.push_back(aSVar);
1681     modified = true;
1682   }
1683   else {
1684     if(SALOMEDSImpl_ScalarVariable* aSVar = dynamic_cast<SALOMEDSImpl_ScalarVariable*>(aGVar)) {
1685       modified = aSVar->setStringValue(theValue) || modified;
1686       modified = aSVar->setType(theType) || modified;
1687     }
1688   }
1689   if(modified)
1690     Modify();
1691 }
1692
1693 //============================================================================
1694 /*! Function : SetStringVariableAsDouble
1695  *  Purpose  :
1696  */
1697 //============================================================================
1698 void SALOMEDSImpl_Study::SetStringVariableAsDouble(const std::string& theVarName,
1699                                                    const double theValue,
1700                                                    const SALOMEDSImpl_GenericVariable::VariableTypes theType)
1701 {
1702   SALOMEDSImpl_GenericVariable* aGVar = GetVariable(theVarName);
1703   if(SALOMEDSImpl_ScalarVariable* aSVar = dynamic_cast<SALOMEDSImpl_ScalarVariable*>(aGVar))
1704     aSVar->setValue(theValue);
1705 }
1706
1707 //============================================================================
1708 /*! Function : GetReal
1709  *  Purpose  :
1710  */
1711 //============================================================================
1712 double SALOMEDSImpl_Study::GetVariableValue(const std::string& theVarName)
1713 {
1714   SALOMEDSImpl_GenericVariable* aGVar = GetVariable(theVarName);
1715
1716   if(aGVar != NULL )
1717     if(SALOMEDSImpl_ScalarVariable* aSVar = dynamic_cast<SALOMEDSImpl_ScalarVariable*>(aGVar))
1718       return aSVar->getValue();
1719
1720   return 0;
1721 }
1722
1723 //============================================================================
1724 /*! Function : GetString
1725  *  Purpose  :
1726  */
1727 //============================================================================
1728 std::string SALOMEDSImpl_Study::GetStringVariableValue(const std::string& theVarName)
1729 {
1730   SALOMEDSImpl_GenericVariable* aGVar = GetVariable(theVarName);
1731
1732   if(aGVar != NULL )
1733     if(SALOMEDSImpl_ScalarVariable* aSVar = dynamic_cast<SALOMEDSImpl_ScalarVariable*>(aGVar))
1734       return aSVar->getStringValue();
1735
1736   return 0;
1737 }
1738
1739 //============================================================================
1740 /*! Function : IsTypeOf
1741  *  Purpose  :
1742  */
1743 //============================================================================
1744 bool SALOMEDSImpl_Study::IsTypeOf(const std::string& theVarName,
1745                                   SALOMEDSImpl_GenericVariable::
1746                                   VariableTypes theType) const
1747 {
1748   SALOMEDSImpl_GenericVariable* aGVar = GetVariable(theVarName);
1749
1750   if(aGVar != NULL )
1751     return aGVar->Type() == theType;
1752
1753   return false;
1754 }
1755
1756 //============================================================================
1757 /*! Function : IsVariable
1758  *  Purpose  :
1759  */
1760 //============================================================================
1761 bool SALOMEDSImpl_Study::IsVariable(const std::string& theVarName) const
1762 {
1763   SALOMEDSImpl_GenericVariable* aGVar = GetVariable(theVarName);
1764   return (aGVar != NULL);
1765 }
1766
1767 //============================================================================
1768 /*! Function : GetVariableNames
1769  *  Purpose  :
1770  */
1771 //============================================================================
1772 std::vector<std::string> SALOMEDSImpl_Study::GetVariableNames() const
1773 {
1774   std::vector<std::string> aResult;
1775
1776   for(int i = 0; i < myNoteBookVars.size(); i++)
1777     aResult.push_back(myNoteBookVars[i]->Name());
1778
1779   return aResult;
1780 }
1781
1782 //============================================================================
1783 /*! Function : AddVariable
1784  *  Purpose  :
1785  */
1786 //============================================================================
1787 void SALOMEDSImpl_Study::AddVariable(SALOMEDSImpl_GenericVariable* theVariable)
1788 {
1789   myNoteBookVars.push_back(theVariable);
1790 }
1791
1792 //============================================================================
1793 /*! Function : AddVariable
1794  *  Purpose  :
1795  */
1796 //============================================================================
1797 SALOMEDSImpl_GenericVariable* SALOMEDSImpl_Study::GetVariable(const std::string& theName) const
1798 {
1799   SALOMEDSImpl_GenericVariable* aResult = NULL;
1800   for(int i = 0; i < myNoteBookVars.size();i++) {
1801     if(theName.compare(myNoteBookVars[i]->Name()) == 0) {
1802       aResult = myNoteBookVars[i];
1803       break;
1804     }
1805   }
1806   return aResult;
1807 }
1808
1809 //============================================================================
1810 /*! Function : RemoveVariable
1811  *  Purpose  :
1812  */
1813 //============================================================================
1814 bool SALOMEDSImpl_Study::RemoveVariable(const std::string& theVarName)
1815 {
1816   SALOMEDSImpl_GenericVariable* aVariable = GetVariable( theVarName );
1817   if( !aVariable )
1818     return false;
1819
1820   std::string aValue = aVariable->SaveToScript();
1821   ReplaceVariableAttribute( theVarName, aValue );
1822
1823   std::vector<SALOMEDSImpl_GenericVariable*>::iterator it = myNoteBookVars.begin(), itEnd = myNoteBookVars.end();
1824   for( ; it != itEnd; it++ )
1825   {
1826     SALOMEDSImpl_GenericVariable* aVariableRef = *it;
1827     if( aVariableRef && theVarName.compare( aVariableRef->Name() ) == 0 )
1828     {
1829       myNoteBookVars.erase( it );
1830       Modify();
1831       break;
1832     }
1833   }
1834
1835   return true;
1836 }
1837
1838 //============================================================================
1839 /*! Function : RenameVariable
1840  *  Purpose  :
1841  */
1842 //============================================================================
1843 bool SALOMEDSImpl_Study::RenameVariable(const std::string& theVarName, const std::string& theNewVarName)
1844 {
1845   SALOMEDSImpl_GenericVariable* aVariable = GetVariable( theVarName );
1846   if( !aVariable )
1847     return false;
1848
1849   ReplaceVariableAttribute( theVarName, theNewVarName );
1850
1851   std::vector<SALOMEDSImpl_GenericVariable*>::iterator it = myNoteBookVars.begin(), itEnd = myNoteBookVars.end();
1852   for( ; it != itEnd; it++ )
1853   {
1854     SALOMEDSImpl_GenericVariable* aVariableRef = *it;
1855     if( aVariableRef && theVarName.compare( aVariableRef->Name() ) == 0 )
1856     {
1857       aVariableRef->setName( theNewVarName );
1858       Modify();
1859       break;
1860     }
1861   }
1862
1863   return true;
1864 }
1865
1866 //============================================================================
1867 /*! Function : IsVariableUsed
1868  *  Purpose  :
1869  */
1870 //============================================================================
1871 bool SALOMEDSImpl_Study::IsVariableUsed(const std::string& theVarName)
1872 {
1873   return FindVariableAttribute( theVarName );
1874 }
1875
1876 //============================================================================
1877 /*! Function : FindVariableAttribute
1878  *  Purpose  :
1879  */
1880 //============================================================================
1881 bool SALOMEDSImpl_Study::FindVariableAttribute(SALOMEDSImpl_StudyBuilder* theStudyBuilder,
1882                                                SALOMEDSImpl_SObject theSObject,
1883                                                const std::string& theName)
1884 {
1885   SALOMEDSImpl_ChildIterator anIter = NewChildIterator( theSObject );
1886   for( ; anIter.More(); anIter.Next() )
1887     if( FindVariableAttribute( theStudyBuilder, anIter.Value(), theName ) )
1888       return true;
1889
1890   DF_Attribute* anAttr;
1891   if( theStudyBuilder->FindAttribute( theSObject, anAttr, "AttributeString" ) )
1892   {
1893     if( SALOMEDSImpl_AttributeString* aStringAttr = ( SALOMEDSImpl_AttributeString* )anAttr )
1894     {
1895       std::string aString = aStringAttr->Value();
1896
1897       std::vector< std::vector<std::string> > aSections = ParseVariables( aString );
1898       for( int i = 0, n = aSections.size(); i < n; i++ )
1899       {
1900         std::vector<std::string> aVector = aSections[i];
1901         for( int j = 0, m = aVector.size(); j < m; j++ )
1902         {
1903           std::string aStr = aVector[j];
1904           if( aStr.compare( theName ) == 0 )
1905             return true;
1906         }
1907       }
1908     }
1909   }
1910   return false;
1911 }
1912
1913 //============================================================================
1914 /*! Function : FindVariableAttribute
1915  *  Purpose  :
1916  */
1917 //============================================================================
1918 bool SALOMEDSImpl_Study::FindVariableAttribute(const std::string& theName)
1919 {
1920   SALOMEDSImpl_StudyBuilder* aStudyBuilder = NewBuilder();
1921   SALOMEDSImpl_SComponentIterator aCompIter = NewComponentIterator();
1922   for( ; aCompIter.More(); aCompIter.Next() )
1923   {
1924     SALOMEDSImpl_SObject aComp = aCompIter.Value();
1925     if( FindVariableAttribute( aStudyBuilder, aComp, theName ) )
1926       return true;
1927   }
1928   return false;
1929 }
1930
1931 //============================================================================
1932 /*! Function : ReplaceVariableAttribute
1933  *  Purpose  :
1934  */
1935 //============================================================================
1936 void SALOMEDSImpl_Study::ReplaceVariableAttribute(SALOMEDSImpl_StudyBuilder* theStudyBuilder,
1937                                                   SALOMEDSImpl_SObject theSObject,
1938                                                   const std::string& theSource,
1939                                                   const std::string& theDest)
1940 {
1941   SALOMEDSImpl_ChildIterator anIter = NewChildIterator( theSObject );
1942   for( ; anIter.More(); anIter.Next() )
1943     ReplaceVariableAttribute( theStudyBuilder, anIter.Value(), theSource, theDest );
1944
1945   DF_Attribute* anAttr;
1946   if( theStudyBuilder->FindAttribute( theSObject, anAttr, "AttributeString" ) )
1947   {
1948     if( SALOMEDSImpl_AttributeString* aStringAttr = ( SALOMEDSImpl_AttributeString* )anAttr )
1949     {
1950       bool isChanged = false;
1951       std::string aNewString, aCurrentString = aStringAttr->Value();
1952
1953       std::vector< std::vector<std::string> > aSections = ParseVariables( aCurrentString );
1954       for( int i = 0, n = aSections.size(); i < n; i++ )
1955       {
1956         std::vector<std::string> aVector = aSections[i];
1957         for( int j = 0, m = aVector.size(); j < m; j++ )
1958         {
1959           std::string aStr = aVector[j];
1960           if( aStr.compare( theSource ) == 0 )
1961           {
1962             isChanged = true;
1963             aStr = theDest;
1964           }
1965
1966           aNewString.append( aStr );
1967           if( j != m - 1 )
1968             aNewString.append( ":" );
1969         }
1970         if( i != n - 1 )
1971           aNewString.append( "|" );
1972       }
1973
1974       if( isChanged )
1975         aStringAttr->SetValue( aNewString );
1976     }
1977   }
1978 }
1979
1980 //============================================================================
1981 /*! Function : ReplaceVariableAttribute
1982  *  Purpose  :
1983  */
1984 //============================================================================
1985 void SALOMEDSImpl_Study::ReplaceVariableAttribute(const std::string& theSource, const std::string& theDest)
1986 {
1987   SALOMEDSImpl_StudyBuilder* aStudyBuilder = NewBuilder();
1988   SALOMEDSImpl_SComponentIterator aCompIter = NewComponentIterator();
1989   for( ; aCompIter.More(); aCompIter.Next() )
1990   {
1991     SALOMEDSImpl_SObject aComp = aCompIter.Value();
1992     ReplaceVariableAttribute( aStudyBuilder, aComp, theSource, theDest );
1993   }
1994 }
1995
1996 //============================================================================
1997 /*! Function : ParseVariables
1998  *  Purpose  :
1999  */
2000 //============================================================================
2001 std::vector< std::vector< std::string > > SALOMEDSImpl_Study::ParseVariables(const std::string& theVariables) const
2002 {
2003   return SALOMEDSImpl_Tool::splitStringWithEmpty( theVariables, OPERATION_SEPARATOR, VARIABLE_SEPARATOR );
2004 }
2005
2006 //============================================================================
2007 /*! Function : EnableUseCaseAutoFilling
2008  *  Purpose  :
2009  */
2010 //============================================================================
2011 void SALOMEDSImpl_Study::EnableUseCaseAutoFilling(bool isEnabled)
2012 {
2013   _errorCode = ""; _autoFill = isEnabled;
2014   if(isEnabled) {
2015     _builder->SetOnAddSObject(_cb);
2016     _builder->SetOnRemoveSObject(_cb);
2017   }
2018   else {
2019     _builder->SetOnAddSObject(NULL);
2020     _builder->SetOnRemoveSObject(NULL);
2021   }
2022 }
2023
2024 //============================================================================
2025 /*! Function : GetIORs
2026  *  Purpose  :
2027  */
2028 //============================================================================
2029 std::vector<std::string> SALOMEDSImpl_Study::GetIORs()
2030 {
2031   std::vector<std::string> anIORs;
2032   std::map<std::string, DF_Label>::const_iterator MI;
2033   for(MI = myIORLabels.begin(); MI!=myIORLabels.end(); MI++)
2034     anIORs.push_back(MI->first);
2035
2036   return anIORs;
2037 }
2038
2039 //============================================================================
2040 /*! Function : addSO_Notification
2041  *  Purpose  : This function tells all the observers that a SO has been added
2042  */
2043 //============================================================================
2044 bool SALOMEDSImpl_Study::addSO_Notification (const SALOMEDSImpl_SObject& theSObject)
2045 {
2046   if(_notifier)
2047     return _notifier->addSO_Notification(theSObject);
2048   else
2049     return false;
2050 }
2051
2052 //============================================================================
2053 /*! Function : removeSO_Notification
2054  *  Purpose  : This function tells all the observers that a SO has been removed
2055  */
2056 //============================================================================
2057 bool SALOMEDSImpl_Study::removeSO_Notification (const SALOMEDSImpl_SObject& theSObject)
2058 {
2059   if(_notifier)
2060     return _notifier->removeSO_Notification(theSObject);
2061   else
2062     return false;
2063 }
2064
2065 //============================================================================
2066 /*! Function : modifySO_Notification
2067  *  Purpose  : This function tells all the observers that a SO has been modified and
2068                pass the mofification reason
2069  */
2070 //============================================================================
2071 bool SALOMEDSImpl_Study::modifySO_Notification (const SALOMEDSImpl_SObject& theSObject, int reason) 
2072 {
2073   if(_notifier)
2074     return _notifier->modifySO_Notification(theSObject, reason);
2075   else
2076     return false;
2077 }
2078
2079 //============================================================================
2080 /*! Function : setNotifier
2081  *  Purpose  : register a notifier
2082  */
2083 //============================================================================
2084 void SALOMEDSImpl_Study::setNotifier(SALOMEDSImpl_AbstractCallback* notifier) 
2085 {
2086   _notifier=notifier;
2087 }