Salome HOME
cbe8fc71ea52ed81c9e57558f479f907f1a54a27
[modules/yacs.git] / src / SALOMEDSImpl / SALOMEDSImpl_Study.cxx
1 // Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 //  File   : SALOMEDSImpl_Study.cxx
24 //  Author : Sergey RUIN
25 //  Module : SALOME
26 //
27 #include "SALOMEDSImpl_Study.hxx"
28 #include <string.h>
29
30 #include <KERNEL_version.h>
31 #include <Basics_Utils.hxx>
32 #include <Basics_DirUtils.hxx>
33
34 #include "HDFexplorer.hxx"
35
36 #include "DF_Application.hxx"
37 #include "DF_ChildIterator.hxx"
38
39 #include "SALOMEDSImpl_ChildNodeIterator.hxx"
40 #include "SALOMEDSImpl_Attributes.hxx"
41 #include "SALOMEDSImpl_UseCaseIterator.hxx"
42 #include "SALOMEDSImpl_AttributeReference.hxx"
43 #include "SALOMEDSImpl_StudyHandle.hxx"
44 #include "SALOMEDSImpl_Tool.hxx"
45 #include "SALOMEDSImpl_IParameters.hxx"
46 #include "SALOMEDSImpl_ScalarVariable.hxx"
47 #include "SALOMEDSImpl_SComponent.hxx"
48
49 #include "HDFOI.hxx"
50 #include <fstream>
51 #include <sstream>
52 #include <algorithm>
53
54 // comment out the following define to enable \t symbols in in the python dump files
55 #define WITHOUT_TABS
56
57 #define DIRECTORYID       16661
58 #define FILELOCALID       26662
59 #define FILEID            "FILE: "
60 #define VARIABLE_SEPARATOR  ':'
61 #define OPERATION_SEPARATOR '|'
62 #define USE_CASE_LABEL_ID "0:2"
63
64 static void SaveAttributes(const SALOMEDSImpl_SObject& SO, HDFgroup *hdf_group_sobject);
65 static void ReadAttributes(SALOMEDSImpl_Study*, const SALOMEDSImpl_SObject&, HDFdataset* );
66 static void BuildTree (SALOMEDSImpl_Study*, HDFgroup*);
67 static void Translate_IOR_to_persistentID (const SALOMEDSImpl_SObject&,
68                                            SALOMEDSImpl_Driver*, bool isMultiFile, bool isASCII);
69 static void ReadNoteBookVariables(SALOMEDSImpl_Study* theStudy, HDFgroup* theGroup);
70
71 namespace {
72   class StudyUnlocker
73   {
74   public:
75     StudyUnlocker( SALOMEDSImpl_Study* study ): myStudy( study ), myLocked( false )
76     {
77       myPrevLocked = myStudy->GetProperties()->IsLocked();
78       resume();
79     }
80     ~StudyUnlocker()
81     {
82       suspend();
83     }
84     void suspend()
85     {
86       if (myLocked) {
87             myStudy->GetProperties()->SetLocked(true);
88             myPrevLocked = myLocked;
89             myLocked = false;
90       }
91     }
92     void resume()
93     {
94       if (myPrevLocked) {
95             myStudy->GetProperties()->SetLocked(false);
96             myLocked = myPrevLocked;
97             myPrevLocked = false;
98       }
99     }
100   private:
101     SALOMEDSImpl_Study* myStudy;
102     bool myLocked;
103     bool myPrevLocked;
104   };
105 }
106
107 //============================================================================
108 /*! Function : SALOMEDSImpl_Study
109  *  Purpose  : SALOMEDSImpl_Study constructor
110  */
111 //============================================================================
112 SALOMEDSImpl_Study::SALOMEDSImpl_Study()
113 {
114   _appli = new DF_Application();
115   _clipboard = _appli->NewDocument("SALOME_STUDY");
116
117   Init();
118 }
119
120 //============================================================================
121 /*! Function : ~SALOMEDSImpl_Study
122  *  Purpose  : SALOMEDSImpl_Study destructor
123  */
124 //============================================================================
125 SALOMEDSImpl_Study::~SALOMEDSImpl_Study()
126 {
127   Clear();
128   _appli->Close(_clipboard);
129   // Destroy application
130   delete _appli;
131 }
132
133 //============================================================================
134 /*! Function : Init
135  *  Purpose  : Initialize study components
136  */
137 //============================================================================
138 void SALOMEDSImpl_Study::Init()
139 {
140   static int _id = 0;
141   _name = "Study" + std::to_string(++_id);
142   _doc = _appli->NewDocument("SALOME_STUDY");
143   _Saved = false ;
144   _URL = "";
145   _autoFill = false;
146   _errorCode = "";
147   _useCaseBuilder = new SALOMEDSImpl_UseCaseBuilder(_doc);
148   _builder = new SALOMEDSImpl_StudyBuilder(this);
149   _cb = new SALOMEDSImpl_Callback(_useCaseBuilder);
150   _notifier=0;
151   //Put on the root label a StudyHandle attribute to store the address of this object
152   //It will be used to retrieve the study object by DF_Label that belongs to the study
153   SALOMEDSImpl_StudyHandle::Set(_doc->Main().Root(), this);
154
155   // set Study properties
156   SALOMEDSImpl_AttributeStudyProperties* aProp = GetProperties();
157
158   int month=0,day=0,year=0,hh=0,mn=0,ss=0;
159   SALOMEDSImpl_Tool::GetSystemDate(year, month, day, hh, mn, ss);
160   aProp->SetModification(SALOMEDSImpl_Tool::GetUserName(),
161                          mn, hh, day, month, year);
162   aProp->SetCreationMode(1);  //"from scratch"
163 }
164
165 //============================================================================
166 /*! Function : Clear
167  *  Purpose  : Clear study components
168  */
169 //============================================================================
170 void SALOMEDSImpl_Study::Clear()
171 {
172   delete _builder;
173   delete _cb;
174   delete _useCaseBuilder;
175   _appli->Close(_doc);
176   _doc = NULL;
177   _mapOfSO.clear();
178   _mapOfSCO.clear();
179 }
180
181 //============================================================================
182 /*! Function : Open
183  *  Purpose  : Open a Study from it's persistent reference
184  */
185 //============================================================================
186 bool SALOMEDSImpl_Study::Open(const std::string& aUrl)
187 {
188   Clear();
189   Init();
190   // Set "C" locale temporarily to avoid possible localization problems
191   Kernel_Utils::Localizer loc;
192
193   _errorCode = "";
194
195   // open the HDFFile
196   HDFfile *hdf_file =0;
197   HDFgroup *hdf_group_study_structure =0;
198   HDFgroup *hdf_notebook_vars = 0;
199
200   char* aC_HDFUrl;
201   std::string aHDFUrl;
202   bool isASCII = false;
203   if (HDFascii::isASCII(aUrl.c_str())) {
204     isASCII = true;
205     char* aResultPath = HDFascii::ConvertFromASCIIToHDF(aUrl.c_str());
206     if ( !aResultPath )
207       return NULL;
208     aC_HDFUrl = new char[strlen(aResultPath) + 19];
209     sprintf(aC_HDFUrl, "%shdf_from_ascii.hdf", aResultPath);
210     delete [] (aResultPath);
211     aHDFUrl = aC_HDFUrl;
212     delete [] aC_HDFUrl;
213   }
214   else {
215     aHDFUrl = aUrl;
216   }
217
218   hdf_file = new HDFfile((char*)aHDFUrl.c_str());
219   try {
220     hdf_file->OpenOnDisk(HDF_RDONLY);// mpv: was RDWR, but opened file can be write-protected too
221   }
222   catch (HDFexception)
223   {
224     char *eStr;
225     eStr = new char[strlen(aUrl.c_str())+17];
226     sprintf(eStr,"Can't open file %s",aUrl.c_str());
227     delete [] eStr;
228     _errorCode = std::string(eStr);
229     return NULL;
230   }
231
232   // Assign the value of the URL in the study object
233   URL(aUrl);
234
235   SALOMEDSImpl_AttributePersistentRef::Set(_doc->Main(), aUrl);
236
237   if (!hdf_file->ExistInternalObject("STUDY_STRUCTURE")) {
238      _errorCode = "Study is empty";
239     return false;
240   }
241
242   //Create  the Structure of the Document
243   hdf_group_study_structure = new HDFgroup("STUDY_STRUCTURE",hdf_file);
244
245   try {
246     BuildTree (this, hdf_group_study_structure);
247   }
248   catch (HDFexception)
249   {
250     char *eStr = new char [strlen(aUrl.c_str())+17];
251     sprintf(eStr,"Can't open file %s", aUrl.c_str());
252     _errorCode = std::string(eStr);
253     return false;
254   }
255
256   //Read and create notebook variables
257   if(hdf_file->ExistInternalObject("NOTEBOOK_VARIABLES")) {
258     hdf_notebook_vars  = new HDFgroup("NOTEBOOK_VARIABLES",hdf_file);
259     ReadNoteBookVariables(this, hdf_notebook_vars);
260     hdf_notebook_vars =0; //will be deleted by hdf_sco_group destructor
261   }
262
263   hdf_file->CloseOnDisk();
264   hdf_group_study_structure = new HDFgroup("STUDY_STRUCTURE",hdf_file);
265
266   if (isASCII) {
267     std::vector<std::string> aFilesToRemove;
268     aFilesToRemove.push_back("hdf_from_ascii.hdf");
269     SALOMEDSImpl_Tool::RemoveTemporaryFiles(SALOMEDSImpl_Tool::GetDirFromPath(aHDFUrl), aFilesToRemove, true);
270   }
271
272   delete hdf_file; // all related hdf objects will be deleted
273
274   // unlock study if it is locked, to set components versions
275   StudyUnlocker unlock(this);
276
277   //For old studies we have to add "unknown" version tag for all stored components
278   SALOMEDSImpl_SComponentIterator itcomponent = NewComponentIterator();
279   for (; itcomponent.More(); itcomponent.Next())
280   {
281     SALOMEDSImpl_SComponent sco = itcomponent.Value();
282     std::string aCompType = sco.GetComment();
283     if ( aCompType == SALOMEDSImpl_IParameters::getDefaultVisualComponent() ) continue;
284     if ( GetProperties()->GetComponentVersions( aCompType ).empty() )
285       GetProperties()->SetComponentVersion( aCompType, "" ); // empty version means "unknown"
286   }
287
288   return true;
289 }
290
291 //============================================================================
292 /*! Function : Save
293  *  Purpose  : Save a Study to it's persistent reference
294  */
295 //============================================================================
296 bool SALOMEDSImpl_Study::Save(SALOMEDSImpl_DriverFactory* aFactory,
297                               bool theMultiFile)
298 {
299   _errorCode = "";
300
301   std::string url = URL();
302   if (url.empty()) {
303     _errorCode = "No path specified to save the study. Nothing done";
304     return false;
305   }
306   else {
307     return Impl_SaveAs(url, aFactory, theMultiFile, false);
308   }
309
310   return false;
311 }
312
313 bool SALOMEDSImpl_Study::SaveASCII(SALOMEDSImpl_DriverFactory* aFactory,
314                                    bool theMultiFile)
315 {
316   _errorCode = "";
317
318   std::string url = URL();
319   if (url.empty()) {
320     _errorCode = "No path specified to save the study. Nothing done";
321     return false;
322   }
323   else {
324     return Impl_SaveAs(url, aFactory, theMultiFile, true);
325   }
326
327   return false;
328 }
329
330 //=============================================================================
331 /*! Function : SaveAs
332  *  Purpose  : Save a study to the persistent reference aUrl
333  */
334 //============================================================================
335 bool SALOMEDSImpl_Study::SaveAs(const std::string& aUrl,
336                                 SALOMEDSImpl_DriverFactory* aFactory,
337                                 bool theMultiFile)
338 {
339   _errorCode = "";
340   return Impl_SaveAs(aUrl, aFactory, theMultiFile, false);
341 }
342
343 bool SALOMEDSImpl_Study::SaveAsASCII(const std::string& aUrl,
344                                      SALOMEDSImpl_DriverFactory* aFactory,
345                                      bool theMultiFile)
346 {
347   _errorCode = "";
348   return Impl_SaveAs(aUrl, aFactory, theMultiFile, true);
349 }
350
351 //=============================================================================
352 /*! Function : _SaveProperties
353  *  Purpose  : save the study properties in HDF file
354  */
355 //============================================================================
356 bool SALOMEDSImpl_Study::Impl_SaveProperties(HDFgroup *hdf_group)
357 {
358   _errorCode = "";
359
360   HDFdataset *hdf_dataset = 0;
361   hdf_size size[1];
362   hdf_int32 name_len;
363
364   // add modifications list (user and date of save)
365   SALOMEDSImpl_AttributeStudyProperties* aProp = GetProperties();
366
367   // unlock study if it is locked, to set modification date
368   StudyUnlocker unlock(this);
369
370   int month=0,day=0,year=0,hh=0,mn=0,ss=0;
371   SALOMEDSImpl_Tool::GetSystemDate(year, month, day, hh, mn, ss);
372   aProp->SetModification(SALOMEDSImpl_Tool::GetUserName(),
373                                      mn, hh, day, month, year);
374
375   // lock study back if it was locked initially, to write correct value of Locked flag
376   unlock.suspend();
377
378   std::vector<std::string> aNames;
379   std::vector<int> aMinutes, aHours, aDays, aMonths, aYears;
380
381   aProp->GetModifications(aNames, aMinutes, aHours, aDays, aMonths, aYears);
382
383   std::string units = aProp->GetUnits();
384   std::string comment = aProp->GetComment();
385
386   std::map< std::string, std::vector<std::string> > allVersions = aProp->GetComponentsVersions();
387   std::map<std::string, std::string> versions;
388
389   int aLength = 0, aLength1 = 0, anIndex, i, unitsSize = 0, commentSize = 0;
390
391   for(i=1; i<=aNames.size(); i++)
392     aLength += aNames[i-1].size() + 1;
393
394   std::map< std::string, std::vector<std::string> >::const_iterator it;
395   for (it = allVersions.begin(); it != allVersions.end(); ++it ) {
396     std::string vlist = "";
397     std::vector<std::string> vl = it->second;
398     std::vector<std::string>::const_iterator vlit;
399     for ( vlit = vl.begin(); vlit != vl.end(); ++vlit ) {
400       if ( vlist != "" ) vlist += ";";
401       vlist += *vlit;
402     }
403     versions[ it->first ] = vlist;
404     aLength1 += it->first.size() + vlist.size() + 2;
405   }
406
407   unitsSize = units.size();
408   commentSize = comment.size();
409
410   //string format:
411   //locked flag, modified flag,
412   //minutes, hours, day, months, year, user name, char(1),
413   //minutes, hours, day, months, year, user name, char(1),
414   //.....................................................,
415   //.....................................................,
416   //.....................................................,
417   //minutes, hours, day, months, year, user name, char(1), char(30) <- !!!! used to define end of section with modifications !!!!
418   //units, char(1), comment, char(30) <- !!!! used to define start of section with components' versions !!!!
419   //component=versions, char(1),
420   //component=versions, char(1),
421   //...........................,
422   //component=versions, char(1), char(0)
423
424   //string length: 1 byte = locked flag, 1 byte = modified flag, (12 + name length + 1) for each name and date, 1 byte (char(30) section delimeter)
425   // unit length + 1, comment length, "zero" byte
426
427   char* aProperty = new char[3 + aLength + 12 * aNames.size() + 1 + unitsSize + 1 + commentSize + 1 + aLength1 ];
428
429   sprintf(aProperty,"%c%c", (char)aProp->GetCreationMode(),  (aProp->IsLocked())?'l':'u');
430
431   aLength = aNames.size();
432   int a = 2;
433   for(anIndex = 0; anIndex<aLength; anIndex++) {
434     sprintf(&(aProperty[a]),"%2d%2d%2d%2d%4d%s",
435             (int)(aMinutes[anIndex]),
436             (int)(aHours[anIndex]),
437             (int)(aDays[anIndex]),
438             (int)(aMonths[anIndex]),
439             (int)(aYears[anIndex]),
440             aNames[anIndex].c_str());
441     a = strlen(aProperty);
442     aProperty[a++] = 1;
443   }
444
445   //Write delimeter of the section to define end of the modifications section
446   aProperty[a++] = 30;
447
448   //Write units if need
449   if(units.size() > 0) {
450     sprintf(&(aProperty[a]),"%s",units.c_str());
451     a = strlen(aProperty);
452   }
453
454   aProperty[a++] = 1;
455
456   //Write comments if need
457   if(comment.size() > 0) {
458     sprintf(&(aProperty[a]),"%s",comment.c_str());
459     a = strlen(aProperty);
460   }
461
462   aProperty[a++] = 30; //delimeter of the component versions
463
464   std::map<std::string, std::string>::const_iterator versionsIt;
465   for ( versionsIt = versions.begin(); versionsIt != versions.end(); ++versionsIt ) {
466     sprintf(&(aProperty[a]),"%s=%s",
467             (char*)(versionsIt->first.c_str()),
468             (char*)(versionsIt->second.c_str()));
469     a = a + versionsIt->first.size() + versionsIt->second.size() + 1;
470     aProperty[a++] = 1;
471   }
472
473   aProperty[a] = 0;
474
475   name_len = (hdf_int32) a;
476   size[0] = name_len + 1 ;
477   hdf_dataset = new HDFdataset("AttributeStudyProperties",hdf_group,HDF_STRING,size,1);
478   hdf_dataset->CreateOnDisk();
479   hdf_dataset->WriteOnDisk(aProperty);
480   hdf_dataset->CloseOnDisk();
481   hdf_dataset=0; //will be deleted by hdf_sco_group destructor
482   delete [] aProperty;
483
484   aProp->SetModified(0);
485   return true;
486 }
487
488 //=============================================================================
489 /*! Function : _SaveAs
490  *  Purpose  : save the study in HDF file
491  */
492 //============================================================================
493 bool SALOMEDSImpl_Study::Impl_SaveAs(const std::string& aStudyUrl,
494                                      SALOMEDSImpl_DriverFactory* aFactory,
495                                      bool theMultiFile,
496                                      bool theASCII)
497 {
498   // Set "C" locale temporarily to avoid possible localization problems
499   Kernel_Utils::Localizer loc;
500
501   // HDF File will be composed of differents part :
502   // * For each ComponentDataType, all data created by the component
503   //   Informations in data group hdf_group_datacomponent
504   // * Study Structure -> Exactly what is contained in Document
505   //   Informations in data group hdf_group_study_structure
506
507   _errorCode = "";
508
509   HDFfile *hdf_file=0;
510   HDFgroup *hdf_group_study_structure =0;
511   HDFgroup *hdf_sco_group =0;
512   HDFgroup *hdf_sco_group2 =0;
513   HDFgroup *hdf_notebook_vars =0;
514   HDFgroup *hdf_notebook_var  = 0;
515
516   HDFgroup *hdf_group_datacomponent =0;
517   HDFdataset *hdf_dataset =0;
518   hdf_size size[1];
519   hdf_int32 name_len = 0;
520   std::string component_name;
521
522   // Store previous URL
523   std::string anOldName = Name();
524
525   // Map to store components' versions
526   std::map<std::string, std::string> componentVersions;
527
528   //Create a temporary url to which the study is saved
529   std::string aUrl = SALOMEDSImpl_Tool::GetTmpDir() + SALOMEDSImpl_Tool::GetNameFromPath(aStudyUrl);
530
531   // unlock study if it is locked, as some attributes need to be modified
532   StudyUnlocker unlock(this);
533
534   SALOMEDSImpl_StudyBuilder* SB= NewBuilder();
535   std::map<std::string, SALOMEDSImpl_Driver*> aMapTypeDriver;
536
537   try {
538     // mpv 15.12.2003: for saving components we have to load all data from all modules
539     SALOMEDSImpl_SComponentIterator itcomponent = NewComponentIterator();
540     for (; itcomponent.More(); itcomponent.Next()) {
541       SALOMEDSImpl_SComponent sco = itcomponent.Value();
542       // if there is an associated Engine call its method for saving
543       std::string IOREngine;
544       try {
545         SALOMEDSImpl_Driver* aDriver = NULL;
546         std::string aCompType = sco.GetComment();
547         if (!sco.ComponentIOR(IOREngine)) {
548           if (!aCompType.empty()) {
549             aDriver = aFactory->GetDriverByType(aCompType);
550             if (aDriver != NULL) {
551               if (!SB->LoadWith(sco, aDriver)) {
552                 _errorCode = SB->GetErrorCode();
553                 return false;
554               }
555             }
556           }
557         }
558             else {
559               aDriver = aFactory->GetDriverByIOR(IOREngine);
560             }
561             aMapTypeDriver[aCompType] = aDriver;
562       }
563       catch(...) {
564         _errorCode = "Can not restore information to resave it";
565         return false;
566       }
567     }
568
569     // VSR: set URL to new file name
570     // VSR: remember to set previous name if save operation fails
571     URL(aStudyUrl);
572
573     // To change for Save
574     // Do not have to do a new file but just a Open??? Rewrite all informations after erasing evrything??
575     hdf_file = new HDFfile((char*)aUrl.c_str());
576     hdf_file->CreateOnDisk();
577
578     //-----------------------------------------------------------------------
579     // 1 - Create a groupe for each SComponent and Update the PersistanceRef
580     //-----------------------------------------------------------------------
581     hdf_group_datacomponent = new HDFgroup("DATACOMPONENT",hdf_file);
582     hdf_group_datacomponent->CreateOnDisk();
583
584     for (itcomponent.Init(); itcomponent.More(); itcomponent.Next()) {
585       SALOMEDSImpl_SComponent sco = itcomponent.Value();
586
587       std::string scoid = sco.GetID();
588       hdf_sco_group = new HDFgroup((char*)scoid.c_str(), hdf_group_datacomponent);
589       hdf_sco_group->CreateOnDisk();
590
591       std::string componentDataType = sco.ComponentDataType();
592       std::string IOREngine;
593       if (sco.ComponentIOR(IOREngine)) {
594         // Engine should be already in the map as it was to added before
595         SALOMEDSImpl_Driver* Engine = aMapTypeDriver[componentDataType];
596         if (Engine != NULL) {
597           SALOMEDSImpl_TMPFile* aStream = NULL;
598           long length = 0;
599
600           componentVersions[ componentDataType ] = Engine->Version();
601
602           if (theASCII) aStream = Engine->SaveASCII(sco,
603                                                     SALOMEDSImpl_Tool::GetDirFromPath(aUrl),
604                                                     length,
605                                                     theMultiFile);
606           else aStream = Engine->Save(sco,
607                                       SALOMEDSImpl_Tool::GetDirFromPath(aUrl),
608                                       length,
609                                       theMultiFile);
610           HDFdataset *hdf_dataset;
611           hdf_size aHDFSize[1];
612           if (length > 0) {  //The component saved some auxiliary files, then put them into HDF file
613             aHDFSize[0] = length;
614
615             HDFdataset *hdf_dataset = new HDFdataset("FILE_STREAM", hdf_sco_group, HDF_STRING, aHDFSize, 1);
616             hdf_dataset->CreateOnDisk();
617             hdf_dataset->WriteOnDisk(aStream->Data());  //Save the stream in the HDF file
618             hdf_dataset->CloseOnDisk();
619           }
620
621           if (aStream) delete aStream;
622
623           // store multifile state
624           aHDFSize[0] = 2;
625           hdf_dataset = new HDFdataset("MULTIFILE_STATE", hdf_sco_group, HDF_STRING, aHDFSize, 1);
626           hdf_dataset->CreateOnDisk();
627           hdf_dataset->WriteOnDisk((void*)(theMultiFile?"M":"S")); // save: multi or single
628           hdf_dataset->CloseOnDisk();
629           hdf_dataset=0; //will be deleted by hdf_sco_AuxFiles destructor
630           // store ASCII state
631           aHDFSize[0] = 2;
632           hdf_dataset = new HDFdataset("ASCII_STATE", hdf_sco_group, HDF_STRING, aHDFSize, 1);
633           hdf_dataset->CreateOnDisk();
634           hdf_dataset->WriteOnDisk((void*)(theASCII?"A":"B")); // save: ASCII or BINARY
635           hdf_dataset->CloseOnDisk();
636           hdf_dataset=0; //will be deleted by hdf_sco_AuxFiles destructor
637           // Creation of the persistance reference  attribute
638           Translate_IOR_to_persistentID (sco, Engine, theMultiFile, theASCII);
639         }
640       }
641       hdf_sco_group->CloseOnDisk();
642       hdf_sco_group=0; // will be deleted by hdf_group_datacomponent destructor
643     }
644     hdf_group_datacomponent->CloseOnDisk();
645     hdf_group_datacomponent =0;  // will be deleted by hdf_file destructor
646
647     //-----------------------------------------------------------------------
648     //3 - Write the Study Structure
649     //-----------------------------------------------------------------------
650     hdf_group_study_structure = new HDFgroup("STUDY_STRUCTURE",hdf_file);
651     hdf_group_study_structure->CreateOnDisk();
652     // save component attributes
653     for (itcomponent.Init(); itcomponent.More(); itcomponent.Next()) {
654       SALOMEDSImpl_SComponent SC = itcomponent.Value();
655       std::string scid = SC.GetID();
656       hdf_sco_group2 = new HDFgroup((char*)scid.c_str(), hdf_group_study_structure);
657       hdf_sco_group2->CreateOnDisk();
658       SaveAttributes(SC, hdf_sco_group2);
659       // ComponentDataType treatment
660       component_name = SC.ComponentDataType();
661       name_len = (hdf_int32)component_name.length();
662       size[0] = name_len +1 ;
663       hdf_dataset = new HDFdataset("COMPONENTDATATYPE",hdf_sco_group2,HDF_STRING,size,1);
664       hdf_dataset->CreateOnDisk();
665       hdf_dataset->WriteOnDisk((char*)component_name.c_str());
666       hdf_dataset->CloseOnDisk();
667       hdf_dataset=0; //will be deleted by hdf_sco_group destructor
668       Impl_SaveObject(SC, hdf_sco_group2);
669       hdf_sco_group2->CloseOnDisk();
670       hdf_sco_group2=0; // will be deleted by hdf_group_study_structure destructor
671     }
672     //-----------------------------------------------------------------------
673     //4 - Write the Study UseCases Structure
674     //-----------------------------------------------------------------------
675     SALOMEDSImpl_SObject aSO = FindObjectID(USE_CASE_LABEL_ID);
676     if (aSO) {
677       HDFgroup *hdf_soo_group = new HDFgroup(USE_CASE_LABEL_ID,hdf_group_study_structure);
678       hdf_soo_group->CreateOnDisk();
679       SaveAttributes(aSO, hdf_soo_group);
680       Impl_SaveObject(aSO, hdf_soo_group);
681       hdf_soo_group->CloseOnDisk();
682       hdf_soo_group=0; // will be deleted by hdf_group_study_structure destructor
683     }
684     //-----------------------------------------------------------------------
685     //5 - Write the NoteBook Variables
686     //-----------------------------------------------------------------------
687
688     //5.1 Create group to store all note book variables
689     hdf_notebook_vars = new HDFgroup("NOTEBOOK_VARIABLES",hdf_file);
690     hdf_notebook_vars->CreateOnDisk();
691
692     std::string varValue;
693     std::string varType;
694     std::string varIndex;
695
696     for (int i=0 ;i < myNoteBookVars.size(); i++ ) {
697       // For each variable create HDF group
698       hdf_notebook_var = new HDFgroup((char*)myNoteBookVars[i]->Name().c_str(),hdf_notebook_vars);
699       hdf_notebook_var->CreateOnDisk();
700
701       // Save Variable type
702       varType = myNoteBookVars[i]->SaveType();
703       name_len = (hdf_int32) varType.length();
704       size[0] = name_len +1 ;
705       hdf_dataset = new HDFdataset("VARIABLE_TYPE",hdf_notebook_var,HDF_STRING,size,1);
706       hdf_dataset->CreateOnDisk();
707       hdf_dataset->WriteOnDisk((char*)varType.c_str());
708       hdf_dataset->CloseOnDisk();
709       hdf_dataset=0; //will be deleted by hdf_sco_group destructor
710
711       char buffer[256];
712       sprintf(buffer,"%d",i);
713       varIndex= std::string(buffer);
714       name_len = (hdf_int32) varIndex.length();
715       size[0] = name_len +1 ;
716       hdf_dataset = new HDFdataset("VARIABLE_INDEX",hdf_notebook_var,HDF_STRING,size,1);
717       hdf_dataset->CreateOnDisk();
718       hdf_dataset->WriteOnDisk((char*)varIndex.c_str());
719       hdf_dataset->CloseOnDisk();
720       hdf_dataset=0; //will be deleted by hdf_sco_group destructor
721
722       // Save Variable value
723       varValue = myNoteBookVars[i]->Save();
724       name_len = (hdf_int32) varValue.length();
725       size[0] = name_len +1 ;
726       hdf_dataset = new HDFdataset("VARIABLE_VALUE",hdf_notebook_var,HDF_STRING,size,1);
727       hdf_dataset->CreateOnDisk();
728       hdf_dataset->WriteOnDisk((char*)varValue.c_str());
729       hdf_dataset->CloseOnDisk();
730       hdf_dataset=0; //will be deleted by hdf_sco_group destructor
731       hdf_notebook_var->CloseOnDisk();
732       hdf_notebook_var = 0; //will be deleted by hdf_sco_group destructor
733     }
734     hdf_notebook_vars->CloseOnDisk();
735     hdf_notebook_vars = 0; //will be deleted by hdf_sco_group destructor
736
737     // record component versions
738     std::map<std::string, std::string>::const_iterator itVersions;
739     for ( itVersions = componentVersions.begin(); itVersions != componentVersions.end(); ++itVersions )
740       GetProperties()->SetComponentVersion( itVersions->first, itVersions->second );
741
742     // lock study back if it was locked initially, to write correct value of Locked flag
743     unlock.suspend();
744
745     //-----------------------------------------------------------------------
746     //6 - Write the Study Properties
747     //-----------------------------------------------------------------------
748     std::string study_name = Name();
749     name_len = (hdf_int32) study_name.size();
750     size[0] = name_len +1 ;
751     hdf_dataset = new HDFdataset("STUDY_NAME",hdf_group_study_structure,HDF_STRING,size,1);
752     hdf_dataset->CreateOnDisk();
753     hdf_dataset->WriteOnDisk((char*)study_name.c_str());
754     hdf_dataset->CloseOnDisk();
755     hdf_dataset=0; // will be deleted by hdf_group_study_structure destructor
756
757     Impl_SaveProperties(hdf_group_study_structure);
758     hdf_group_study_structure->CloseOnDisk();
759     hdf_file->CloseOnDisk();
760
761     hdf_group_study_structure =0; // will be deleted by hdf_file destructor
762     delete hdf_file; // recursively deletes all hdf objects...
763   }
764   catch (HDFexception) {
765     _errorCode = "HDFexception ! ";
766     URL( anOldName ); // VSR: restore previous url if operation is failed
767     return false;
768   }
769   catch (std::exception& exc) {
770     _errorCode = const_cast<char*>(exc.what());
771     URL( anOldName ); // VSR: restore previous url if operation is failed
772     return false;
773   }
774   catch (...) {
775     _errorCode = "Unknown exception ! ";
776     URL( anOldName ); // VSR: restore previous url if operation is failed
777     return false;
778   }
779   if (theASCII) { // save file in ASCII format
780     HDFascii::ConvertFromHDFToASCII(aUrl.c_str(), true);
781   }
782
783   // Now it's necessary to copy files from the temporary directory to the user defined directory.
784   // The easiest way to get a list of file in the temporary directory
785
786   std::string aCmd, aTmpFileDir = SALOMEDSImpl_Tool::GetTmpDir();
787   std::string aTmpFile = aTmpFileDir +"files";
788   std::string aStudyTmpDir = SALOMEDSImpl_Tool::GetDirFromPath(aUrl);
789
790 #ifdef WIN32
791   aCmd = "dir /B \"" + aStudyTmpDir +"\" > " + aTmpFile;
792 #else
793   aCmd ="ls -1 \"" + aStudyTmpDir +"\" > " + aTmpFile;
794 #endif
795   system(aCmd.c_str());
796
797   // Iterate and move files in the temporary directory
798   FILE* fp = fopen(aTmpFile.c_str(), "rb");
799   if (!fp) {
800     URL( anOldName ); // VSR: restore previous url if operation is failed
801     return false;
802   }
803   char* buffer = new char[2047];
804   int errors = 0;
805   while (!feof(fp) && !errors) {
806     if ((fgets(buffer, 2046, fp)) == NULL) break;
807     size_t aLen = strlen(buffer);
808     if (buffer[aLen-1] == '\n') buffer[aLen-1] = char(0);
809 #ifdef WIN32
810     aCmd = "move /Y \"" + aStudyTmpDir + std::string(buffer) + "\" \"" + SALOMEDSImpl_Tool::GetDirFromPath(aStudyUrl) +"\"";
811 #else
812     aCmd = "mv -f \"" + aStudyTmpDir + std::string(buffer) + "\" \"" + SALOMEDSImpl_Tool::GetDirFromPath(aStudyUrl)+"\"";
813 #endif
814     errors = system(aCmd.c_str());
815   }
816
817   delete []buffer;
818   fclose(fp);
819
820   // Perform cleanup
821 #ifdef WIN32
822   DeleteFileA(aTmpFile.c_str());
823 #else
824   unlink(aTmpFile.c_str());
825 #endif
826
827 #ifdef WIN32
828   RemoveDirectoryA(aTmpFileDir.c_str());
829   RemoveDirectoryA(aStudyTmpDir.c_str());
830 #else
831   rmdir(aTmpFileDir.c_str());
832   rmdir(aStudyTmpDir.c_str());
833 #endif
834
835   if ( !errors ) {
836     // VSR: finally, if all is done without errors, mark study as Saved
837     IsSaved(true);
838   }
839
840   return !errors;
841 }
842
843 //============================================================================
844 /*! Function : Impl_SaveObject
845  *  Purpose  :
846  */
847 //============================================================================
848 bool SALOMEDSImpl_Study::Impl_SaveObject(const SALOMEDSImpl_SObject& SC,
849                                          HDFgroup *hdf_group_datatype)
850 {
851   _errorCode = "";
852
853   // Write in group hdf_group_datatype all informations of SObject SC
854   // Iterative function to parse all SObjects under a SComponent
855
856   HDFgroup *hdf_group_sobject = 0;
857
858   DF_ChildIterator itchild(SC.GetLabel());
859   for (; itchild.More(); itchild.Next()) {
860     // mpv: don't save empty labels
861     std::vector<DF_Attribute*> attr = itchild.Value().GetAttributes();
862     if (attr.size() == 0) {  //No attributes on the label
863       DF_ChildIterator subchild(itchild.Value());
864       if (!subchild.More()) {
865         continue;
866       }
867       subchild.Init(itchild.Value(), true);
868       bool anEmpty = true;
869       for (; subchild.More() && anEmpty; subchild.Next()) {
870         std::vector<DF_Attribute*> attr2 = subchild.Value().GetAttributes();
871         if (attr2.size()) {
872           anEmpty = false;  //There are attributes on the child label
873           break;
874         }
875       }
876       if (anEmpty) continue;
877     }
878
879     SALOMEDSImpl_SObject SO = SALOMEDSImpl_Study::SObject(itchild.Value());
880
881     std::string scoid = SO.GetID();
882     hdf_group_sobject = new HDFgroup(scoid.c_str(), hdf_group_datatype);
883     hdf_group_sobject->CreateOnDisk();
884     SaveAttributes(SO, hdf_group_sobject);
885     Impl_SaveObject(SO, hdf_group_sobject);
886     hdf_group_sobject->CloseOnDisk();
887     hdf_group_sobject =0; // will be deleted by father hdf object destructor
888   }
889   return true;
890 }
891
892 //============================================================================
893 /*! Function : CanCopy
894  *  Purpose  :
895  */
896 //============================================================================
897 bool SALOMEDSImpl_Study::CanCopy(const SALOMEDSImpl_SObject& theObject,
898                                  SALOMEDSImpl_Driver* theEngine)
899 {
900   _errorCode = "";
901   SALOMEDSImpl_SComponent aComponent = theObject.GetFatherComponent();
902   if (!aComponent) return false;
903   if (aComponent.GetLabel() == theObject.GetLabel()) return false;
904   std::string IOREngine;
905   if (!aComponent.ComponentIOR(IOREngine)) return false;
906   if (theEngine == NULL) return false;
907   return theEngine->CanCopy(theObject);
908 }
909
910 //============================================================================
911 /*! Function : CopyLabel
912  *  Purpose  :
913  */
914 //============================================================================
915 bool SALOMEDSImpl_Study::CopyLabel(SALOMEDSImpl_Driver* theEngine,
916                                    const int theSourceStartDepth,
917                                    const DF_Label& theSource,
918                                    const DF_Label& theDestinationMain)
919 {
920   _errorCode = "";
921
922   int a;
923   DF_Label aTargetLabel = theDestinationMain;
924   DF_Label aAuxTargetLabel = theDestinationMain.Father().FindChild(2);
925   for(a = theSource.Depth() - theSourceStartDepth; a > 0 ; a--) {
926     DF_Label aSourceLabel = theSource;
927     for(int aNbFather = 1; aNbFather < a; aNbFather++) aSourceLabel = aSourceLabel.Father();
928     aTargetLabel = aTargetLabel.FindChild(aSourceLabel.Tag());
929     aAuxTargetLabel = aAuxTargetLabel.FindChild(aSourceLabel.Tag());
930   }
931   // iterate attributes
932   std::vector<DF_Attribute*> attrList = theSource.GetAttributes();
933   for(int i = 0, len = attrList.size(); i<len; i++) {
934     DF_Attribute* anAttr = attrList[i];
935     std::string type = SALOMEDSImpl_GenericAttribute::Impl_GetType(anAttr);
936     if (type.substr(0, 17) == std::string("AttributeTreeNode")) continue; // never copy tree node attribute
937     if (type == std::string("AttributeTarget")) continue; // and target attribute
938
939     if (type == std::string("AttributeReference")) { // reference copied as Comment in aux tree
940       DF_Label aReferenced = dynamic_cast<SALOMEDSImpl_AttributeReference*>(anAttr)->Get();
941       std::string anEntry = aReferenced.Entry();
942       // store the value of name attribute of referenced label
943       SALOMEDSImpl_AttributeName* aNameAttribute;
944       if ((aNameAttribute=(SALOMEDSImpl_AttributeName*)aReferenced.FindAttribute(SALOMEDSImpl_AttributeName::GetID()))) {
945         anEntry += " ";
946         anEntry += aNameAttribute->Value();
947       }
948       SALOMEDSImpl_AttributeComment::Set(aAuxTargetLabel, anEntry);
949       continue;
950     }
951
952     if (type == std::string("AttributeIOR")) { // IOR => ID and TMPFile of Engine
953       std::string anEntry = theSource.Entry();
954       SALOMEDSImpl_SObject aSO = FindObjectID(anEntry);
955       int anObjID;
956       long aLen;
957       SALOMEDSImpl_TMPFile* aStream = theEngine->CopyFrom(aSO, anObjID, aLen);
958       std::string aResStr("");
959       for(a = 0; a < aLen; a++) {
960         aResStr += (char)(aStream->Get(a));
961       }
962
963       if(aStream) delete aStream;
964
965       SALOMEDSImpl_AttributeInteger::Set(aAuxTargetLabel, anObjID);
966       SALOMEDSImpl_AttributeName::Set(aAuxTargetLabel, aResStr);
967       continue;
968     }
969     DF_Attribute* aNewAttribute = anAttr->NewEmpty();
970     aTargetLabel.AddAttribute(aNewAttribute);
971     anAttr->Paste(aNewAttribute);
972   }
973
974   return true;
975 }
976
977 //============================================================================
978 /*! Function : Copy
979  *  Purpose  :
980  */
981 //============================================================================
982 bool SALOMEDSImpl_Study::Copy(const SALOMEDSImpl_SObject& theObject,
983                                     SALOMEDSImpl_Driver* theEngine)
984 {
985   _errorCode = "";
986
987   // adoptation for alliances datamodel copy: without IOR attributes !!!
988   bool aStructureOnly; // copy only SObjects and attributes without component help
989   aStructureOnly = !theObject.GetLabel().IsAttribute(SALOMEDSImpl_AttributeIOR::GetID());
990
991   // get component-engine
992   SALOMEDSImpl_Study* aStudy = theObject.GetStudy();
993
994   if (!_doc) {
995     _errorCode = "Document is null";
996     return false;
997   }
998
999   //Clear the clipboard
1000   _clipboard->Main().Root().ForgetAllAttributes(true);
1001   _appli->Close(_clipboard);
1002   _clipboard = _appli->NewDocument("SALOME_STUDY");
1003
1004   // set component data type to the name attribute of root label
1005   if (!aStructureOnly) {
1006     SALOMEDSImpl_AttributeComment::Set(_clipboard->Main().Root(),
1007                                        theEngine->ComponentDataType());
1008   }
1009   // iterate all theObject's label children
1010   DF_Label aStartLabel = theObject.GetLabel();
1011   int aSourceStartDepth = aStartLabel.Depth();
1012
1013   // copy main source label
1014   CopyLabel(theEngine, aSourceStartDepth, aStartLabel, _clipboard->Main());
1015
1016   // copy all subchildren of the main source label (all levels)
1017   DF_ChildIterator anIterator(aStartLabel, true);
1018   for(; anIterator.More(); anIterator.Next()) {
1019     CopyLabel(theEngine, aSourceStartDepth, anIterator.Value(), _clipboard->Main());
1020   }
1021
1022   return true;
1023 }
1024
1025 //============================================================================
1026 /*! Function : CanPaste
1027  *  Purpose  :
1028  */
1029 //============================================================================
1030 bool SALOMEDSImpl_Study::CanPaste(const SALOMEDSImpl_SObject& theObject,
1031                                          SALOMEDSImpl_Driver* theEngine)
1032 {
1033   _errorCode = "";
1034
1035   if (!_clipboard) {
1036     _errorCode = "Clipboard is null";
1037     return false;
1038   }
1039
1040   SALOMEDSImpl_AttributeComment* aCompName = NULL;
1041   if (!(aCompName=(SALOMEDSImpl_AttributeComment*)_clipboard->Main().Root().FindAttribute(SALOMEDSImpl_AttributeComment::GetID()))) {
1042     _errorCode = "Clipboard has no component type";
1043     return false;
1044   }
1045   SALOMEDSImpl_AttributeInteger* anObjID;
1046   if (!(anObjID=(SALOMEDSImpl_AttributeInteger*)_clipboard->Main().Father().FindChild(2).FindAttribute(SALOMEDSImpl_AttributeInteger::GetID()))) {
1047     _errorCode = "Clipboard has no object id";
1048     return false;
1049   }
1050   SALOMEDSImpl_SComponent aComponent = theObject.GetFatherComponent();
1051   if (!aComponent) {
1052     _errorCode = "Object doesn't belong to component";
1053     return false;
1054   }
1055
1056   std::string IOREngine;
1057   if (!aComponent.ComponentIOR(IOREngine)) {
1058     _errorCode = "component has no IOR";
1059     return false;
1060   }
1061   return theEngine->CanPaste(aCompName->Value(), anObjID->Value());
1062 }
1063
1064 //============================================================================
1065 /*! Function : PasteLabel
1066  *  Purpose  :
1067  */
1068 //============================================================================
1069 DF_Label SALOMEDSImpl_Study::PasteLabel(SALOMEDSImpl_Driver* theEngine,
1070                                         const DF_Label& theSource,
1071                                         const DF_Label& theDestinationStart,
1072                                         const bool isFirstElement)
1073 {
1074   _errorCode = "";
1075
1076   // get corresponding source, target and auxiliary labels
1077   DF_Label aTargetLabel = theDestinationStart;
1078
1079   DF_Label aAuxSourceLabel = theSource.Root().FindChild(2);
1080   int a;
1081   if (!isFirstElement) {
1082     for(a = theSource.Depth() - 1; a > 0 ; a--) {
1083       DF_Label aSourceLabel = theSource;
1084       for(int aNbFather = 1; aNbFather < a; aNbFather++) aSourceLabel = aSourceLabel.Father();
1085       aTargetLabel = aTargetLabel.FindChild(aSourceLabel.Tag());
1086       aAuxSourceLabel = aAuxSourceLabel.FindChild(aSourceLabel.Tag());
1087     }
1088     SALOMEDSImpl_SObject so = GetSObject(aTargetLabel);
1089     addSO_Notification(so);
1090   }
1091
1092   // check auxiliary label for TMPFile => IOR
1093   SALOMEDSImpl_AttributeName* aNameAttribute = NULL;
1094   if ((aNameAttribute=(SALOMEDSImpl_AttributeName*)aAuxSourceLabel.FindAttribute(SALOMEDSImpl_AttributeName::GetID()))) {
1095     SALOMEDSImpl_AttributeInteger* anObjID = (SALOMEDSImpl_AttributeInteger*)aAuxSourceLabel.FindAttribute(SALOMEDSImpl_AttributeInteger::GetID());
1096     SALOMEDSImpl_AttributeComment* aComponentName = (SALOMEDSImpl_AttributeComment*)theSource.Root().FindAttribute(SALOMEDSImpl_AttributeComment::GetID());
1097     std::string aCompName = aComponentName->Value();
1098
1099     if (theEngine->CanPaste(aCompName, anObjID->Value())) {
1100       std::string aTMPStr = aNameAttribute->Value();
1101       int aLen = aTMPStr.size();
1102       unsigned char* aStream = NULL;
1103       if(aLen > 0) {
1104         aStream = new unsigned char[aLen+10];
1105         for(a = 0; a < aLen; a++) {
1106           aStream[a] = aTMPStr[a];
1107         }
1108       }
1109
1110       std::string anEntry = aTargetLabel.Entry();
1111       SALOMEDSImpl_SObject aPastedSO = FindObjectID(anEntry);
1112
1113       if (isFirstElement) {
1114         std::string aDestEntry = theEngine->PasteInto(aStream,
1115                                                       aLen,
1116                                                       anObjID->Value(),
1117                                                       aPastedSO.GetFatherComponent());
1118         aTargetLabel = DF_Label::Label(theDestinationStart, aDestEntry);
1119       } else
1120         theEngine->PasteInto(aStream, aLen, anObjID->Value(), aPastedSO);
1121
1122       if(aStream != NULL) delete []aStream;
1123     }
1124   }
1125
1126   // iterate attributes
1127   std::vector<DF_Attribute*> attrList = theSource.GetAttributes();
1128   for(int i = 0, len = attrList.size(); i<len; i++) {
1129     DF_Attribute* anAttr = attrList[i];
1130     if (aTargetLabel.FindAttribute(anAttr->ID())) {
1131       aTargetLabel.ForgetAttribute(anAttr->ID());
1132     }
1133     DF_Attribute* aNewAttribute = anAttr->NewEmpty();
1134     aTargetLabel.AddAttribute(aNewAttribute);
1135     anAttr->Paste(aNewAttribute);
1136   }
1137
1138   // check auxiliary label for Comment => reference or name attribute of the referenced object
1139   SALOMEDSImpl_AttributeComment* aCommentAttribute = NULL;
1140   if ((aCommentAttribute=(SALOMEDSImpl_AttributeComment*)aAuxSourceLabel.FindAttribute(SALOMEDSImpl_AttributeComment::GetID()))) {
1141     char * anEntry = new char[aCommentAttribute->Value().size() + 1];
1142     strcpy(anEntry, std::string(aCommentAttribute->Value()).c_str());
1143     char* aNameStart = strchr(anEntry, ' ');
1144     if (aNameStart) {
1145       *aNameStart = '\0';
1146       aNameStart++;
1147     }
1148     // copy to the same study, reanimate reference
1149     DF_Label aRefLabel = DF_Label::Label(aTargetLabel, anEntry);
1150     SALOMEDSImpl_AttributeReference::Set(aTargetLabel, aRefLabel);
1151     // target attributes structure support
1152     SALOMEDSImpl_AttributeTarget::Set(aRefLabel)->Add(SALOMEDSImpl_Study::SObject(aTargetLabel));
1153
1154     delete [] anEntry;
1155   }
1156
1157   return aTargetLabel;
1158 }
1159
1160 //============================================================================
1161 /*! Function : Paste
1162  *  Purpose  :
1163  */
1164 //============================================================================
1165 SALOMEDSImpl_SObject SALOMEDSImpl_Study::Paste(const SALOMEDSImpl_SObject& theObject,
1166                                                SALOMEDSImpl_Driver* theEngine)
1167 {
1168   _errorCode = "";
1169
1170   SALOMEDSImpl_SObject so;
1171
1172   // if study is locked, then paste can't be done
1173   if (GetProperties()->IsLocked()) {
1174     _errorCode = "LockProtection";
1175     throw LockProtection("LockProtection");
1176   }
1177
1178   // if there is no component name, then paste only SObjects and attributes: without component help
1179   SALOMEDSImpl_AttributeComment* aComponentName = NULL;
1180   bool aStructureOnly = !(aComponentName=(SALOMEDSImpl_AttributeComment*)_clipboard->Main().Root().FindAttribute(SALOMEDSImpl_AttributeComment::GetID()));
1181
1182   // CAF document of current study usage
1183   if (!_doc) {
1184     _errorCode = "Document is null";
1185     return so;
1186   }
1187
1188   SALOMEDSImpl_SComponent aComponent = theObject.GetFatherComponent();
1189
1190   // fill root inserted SObject
1191   DF_Label aStartLabel;
1192   if (aStructureOnly) {
1193     DF_Label anObjectLabel = DF_Label::Label(_doc->Main(), theObject.GetID());
1194     aStartLabel = PasteLabel(theEngine, _clipboard->Main(), anObjectLabel, false);
1195   } else {
1196     DF_Label aComponentLabel = DF_Label::Label(_doc->Main(), aComponent.GetID());
1197     aStartLabel = PasteLabel(theEngine, _clipboard->Main(), aComponentLabel, true);
1198   }
1199
1200   // paste all sublebels
1201   DF_ChildIterator anIterator(_clipboard->Main(), true);
1202   for(; anIterator.More(); anIterator.Next()) {
1203     PasteLabel(theEngine, anIterator.Value(), aStartLabel, false);
1204   }
1205
1206   return SALOMEDSImpl_Study::SObject(aStartLabel);
1207 }
1208
1209 //============================================================================
1210 /*! Function : GetPersistentReference
1211  *  Purpose  : Get persistent reference of study (idem URL())
1212  */
1213 //============================================================================
1214 std::string SALOMEDSImpl_Study::GetPersistentReference()
1215 {
1216   _errorCode = "";
1217   return URL();
1218 }
1219 //============================================================================
1220 /*! Function : GetTransientReference
1221  *  Purpose  : Get IOR of the Study (registred in Document in doc->Root)
1222  */
1223 //============================================================================
1224 std::string SALOMEDSImpl_Study::GetTransientReference()
1225 {
1226   _errorCode = "";
1227   std::string IOR = "";
1228
1229   SALOMEDSImpl_AttributeIOR* Att;
1230   DF_Label _lab = _doc->Root();
1231   if ((Att=(SALOMEDSImpl_AttributeIOR*)_lab.FindAttribute(SALOMEDSImpl_AttributeIOR::GetID()))) {
1232     IOR = Att->Value();
1233   }
1234   else {
1235     _errorCode = "IOR is empty";
1236   }
1237
1238   return IOR;
1239 }
1240
1241 void SALOMEDSImpl_Study::SetTransientReference(const std::string& theIOR)
1242 {
1243   _errorCode = "";
1244
1245   SALOMEDSImpl_AttributeStudyProperties* aProp = GetProperties();
1246   int aLocked = aProp->IsLocked();
1247   if (aLocked) aProp->SetLocked(false);
1248
1249   // Assign the value of the IOR in the study->root
1250   SALOMEDSImpl_AttributeIOR::Set(_doc->Main().Root(), theIOR);
1251
1252   if (aLocked) aProp->SetLocked(true);
1253 }
1254
1255 //============================================================================
1256 /*! Function : IsEmpty
1257  *  Purpose  : Detect if study is empty
1258  */
1259 //============================================================================
1260 bool SALOMEDSImpl_Study::IsEmpty()
1261 {
1262   _errorCode = "";
1263   if (!_doc) return true;
1264   return _doc->IsEmpty();
1265 }
1266
1267 //============================================================================
1268 /*! Function : FindComponent
1269  *  Purpose  : Find a Component with ComponentDataType = aComponentName
1270  */
1271 //============================================================================
1272 SALOMEDSImpl_SComponent SALOMEDSImpl_Study::FindComponent (const std::string& aComponentName)
1273 {
1274   _errorCode = "";
1275   bool _find = false;
1276   std::string name;
1277   SALOMEDSImpl_SComponentIterator itcomp = NewComponentIterator();
1278   SALOMEDSImpl_SComponent compo;
1279
1280   for (; itcomp.More(); itcomp.Next()) {
1281     SALOMEDSImpl_SComponent SC = itcomp.Value();
1282     name = SC.ComponentDataType();
1283     if(aComponentName == name) {
1284       _find = true;
1285       return SC;
1286     }
1287   }
1288
1289   if(!_find)
1290     {
1291       _errorCode = "No component was found";
1292       return compo;
1293     }
1294   return compo;
1295 }
1296
1297 //============================================================================
1298 /*! Function : FindComponentID
1299  *  Purpose  : Find a Component from it's ID
1300  */
1301 //============================================================================
1302 SALOMEDSImpl_SComponent SALOMEDSImpl_Study::FindComponentID(const std::string& aComponentID)
1303 {
1304   _errorCode = "";
1305
1306   // Iterate on each components defined in the study
1307   // Get the component ID and compare with aComponentID
1308   bool _find = false;
1309   std::string ID;
1310   SALOMEDSImpl_SComponent compo;
1311
1312   SALOMEDSImpl_SComponentIterator itcomp = NewComponentIterator();
1313   for (; itcomp.More(); itcomp.Next()) {
1314     SALOMEDSImpl_SComponent SC = itcomp.Value();
1315     ID = SC.GetID();
1316     if(aComponentID == ID)
1317       {
1318         // ComponentID found
1319         _find = true;
1320         compo = SC;
1321       }
1322   }
1323   if(!_find)
1324     {
1325       _errorCode = "No component was found";
1326       compo = compo;
1327     }
1328
1329   return compo;
1330 }
1331
1332 //============================================================================
1333 /*! Function : FindObject
1334  *  Purpose  : Find an Object with SALOMEDSImpl_Name = anObjectName
1335  */
1336 //============================================================================
1337 SALOMEDSImpl_SObject SALOMEDSImpl_Study::FindObject(const std::string& anObjectName)
1338 {
1339   _errorCode = "";
1340
1341   // Iterate to all components defined in the study
1342   // After testing the component name, iterate in all objects defined under
1343   // components (function _FindObject)
1344   bool _find = false;
1345   SALOMEDSImpl_SObject RefSO;
1346
1347   SALOMEDSImpl_SComponentIterator it = NewComponentIterator();
1348   for (; it.More();it.Next()){
1349     if(!_find)
1350       {
1351         SALOMEDSImpl_SComponent SC = it.Value();
1352         if (SC.GetName() == anObjectName)
1353         {
1354             _find = true;
1355             RefSO = SC;
1356
1357         }
1358         if (!_find) RefSO =  _FindObject(SC, anObjectName, _find);
1359       }
1360   }
1361   if(!RefSO) _errorCode = "No object was found";
1362   return RefSO;
1363 }
1364
1365 //============================================================================
1366 /*! Function : FindObjectID
1367  *  Purpose  : Find an Object with ID = anObjectID
1368  */
1369 //============================================================================
1370 SALOMEDSImpl_SObject SALOMEDSImpl_Study::FindObjectID(const std::string& anObjectID)
1371 {
1372   _errorCode = "";
1373   SALOMEDSImpl_SObject so;
1374
1375   // Convert aSO->GetID in DF_Label.
1376   DF_Label Lab = DF_Label::Label(_doc->Main(), anObjectID, false);
1377
1378   if (Lab.IsNull()) {
1379     _errorCode = "No label was found by ID";
1380     return so;
1381   }
1382   return GetSObject(Lab);
1383
1384 }
1385
1386 //============================================================================
1387 /*! Function : CreateObjectID
1388  *  Purpose  : Creates an Object with ID = anObjectID
1389  */
1390 //============================================================================
1391 SALOMEDSImpl_SObject SALOMEDSImpl_Study::CreateObjectID(const std::string& anObjectID)
1392 {
1393   _errorCode = "";
1394   SALOMEDSImpl_SObject so;
1395
1396   // Convert aSO->GetID in DF_Label.
1397   DF_Label Lab = DF_Label::Label(_doc->Main(), anObjectID, true);
1398
1399   if (Lab.IsNull()) {
1400     _errorCode = "Can not create a label";
1401     return so;
1402   }
1403   return GetSObject(Lab);
1404
1405 }
1406
1407 //============================================================================
1408 /*! Function : FindObjectByName
1409  *  Purpose  : Find Objects with SALOMEDSImpl_Name = anObjectName in a Component
1410  *           : with ComponentDataType = aComponentName
1411  */
1412 //============================================================================
1413 std::vector<SALOMEDSImpl_SObject> SALOMEDSImpl_Study::FindObjectByName(const std::string& anObjectName,
1414                                                                        const std::string& aComponentName)
1415 {
1416   _errorCode = "";
1417
1418   std::vector<SALOMEDSImpl_SObject> listSO;
1419
1420   SALOMEDSImpl_SComponent compo = FindComponent(aComponentName) ;
1421   if ( !compo ) {
1422     _errorCode = "Can not find the component";
1423     return listSO;
1424   }
1425
1426   // Iterate on each object and subobject of the component
1427   // If objectName is found add it to the list of SObjects
1428   std::string childName ;
1429
1430   std::string compoId = compo.GetID();
1431   SALOMEDSImpl_ChildIterator it = NewChildIterator(compo);
1432   for ( ; it.More(); it.Next() ) {
1433
1434     SALOMEDSImpl_SObject CSO = it.Value();
1435     if ( CSO.GetName() == anObjectName ) {
1436         /* add to list */
1437         listSO.push_back(CSO) ;
1438     }
1439
1440     /* looks also for eventual children */
1441     bool found = false ;
1442     CSO = _FindObject( CSO, anObjectName, found ) ;
1443     if( found) {
1444       listSO.push_back(CSO) ;
1445     }
1446   }
1447
1448   return listSO;
1449 }
1450
1451
1452
1453 //============================================================================
1454 /*! Function : FindObjectIOR
1455  *  Purpose  : Find an Object with IOR = anObjectIOR
1456  */
1457 //============================================================================
1458 SALOMEDSImpl_SObject SALOMEDSImpl_Study::FindObjectIOR(const std::string& anObjectIOR)
1459 {
1460   _errorCode = "";
1461
1462   SALOMEDSImpl_SObject aResult ;
1463
1464   // searching in the datamap for optimization
1465   std::map<std::string, DF_Label>::iterator it=myIORLabels.find(anObjectIOR);
1466   if (it != myIORLabels.end()) {
1467     aResult = GetSObject(it->second);
1468     // 11 oct 2002: forbidden attributes must be checked here
1469     if (!aResult.GetLabel().IsAttribute(SALOMEDSImpl_AttributeIOR::GetID())) {
1470       myIORLabels.erase(anObjectIOR);
1471       aResult = SALOMEDSImpl_SObject();
1472     }
1473   }
1474
1475   if(!aResult) _errorCode = "No object was found";
1476   return aResult;
1477 }
1478
1479 //============================================================================
1480 /*! Function : FindObjectByPath
1481  *  Purpose  : Find an Object by its path = thePath
1482  */
1483 //============================================================================
1484 SALOMEDSImpl_SObject SALOMEDSImpl_Study::FindObjectByPath(const std::string& thePath)
1485 {
1486   _errorCode = "";
1487
1488   std::string aPath(thePath), aToken;
1489   SALOMEDSImpl_SObject aSO;
1490   int aLength = aPath.size();
1491   bool isRelative = false;
1492
1493   if(aLength == 0) {  //Empty path - return the current context
1494     return GetSObject(_current);
1495   }
1496
1497   if(aPath[0] != '/')  //Relative path
1498     isRelative = true;
1499
1500   DF_ChildIterator anIterator;
1501   DF_Label aLabel;
1502   SALOMEDSImpl_AttributeName* anAttr;
1503
1504   if(isRelative) {
1505     if(_current.IsNull()) return aSO;
1506     anIterator.Init(_current, false);
1507   }
1508   else {
1509     if(aPath.size() == 1 && aPath[0] == '/') {    //Root
1510       return GetSObject(_doc->Main());
1511     }
1512     anIterator.Init(_doc->Main(), false);
1513   }
1514
1515   std::vector<std::string> vs = SALOMEDSImpl_Tool::splitString(aPath, '/');
1516   for(int i = 0, len = vs.size(); i<len; i++) {
1517
1518     aToken = vs[i];
1519     if(aToken.size() == 0) break;
1520
1521     for ( ; anIterator.More(); anIterator.Next() ) {
1522       aLabel = anIterator.Value();
1523       if((anAttr=(SALOMEDSImpl_AttributeName*)aLabel.FindAttribute(SALOMEDSImpl_AttributeName::GetID()))) {
1524         if(anAttr->Value() == aToken) {
1525           if(i == (len-1)) {  //The searched label is found (no part of the path is left)
1526               return GetSObject(aLabel);
1527           }
1528
1529           anIterator.Init(aLabel, false);
1530           break;
1531         }
1532       }
1533     }
1534
1535   }
1536
1537   if(!aSO) _errorCode = "No object was found";
1538   return aSO;
1539 }
1540
1541 //============================================================================
1542 /*! Function : GetObjectPath
1543  *  Purpose  :
1544  */
1545 //============================================================================
1546 std::string SALOMEDSImpl_Study::GetObjectPath(const SALOMEDSImpl_SObject& theObject)
1547 {
1548   _errorCode = "";
1549
1550   std::string aPath("");
1551   if(!theObject) {
1552     _errorCode = "Null object";
1553     return aPath;
1554   }
1555
1556   std::string aName = theObject.GetName();
1557   if(!aName.empty() && aName != "" ) {
1558     std::string aValue("/");
1559     aValue+=aName;
1560     aValue += aPath;
1561     aPath = aValue;
1562     SALOMEDSImpl_SObject aFather = theObject.GetFather();
1563     if(aFather) {
1564        aName = aFather.GetName();
1565        if(!aName.empty() && aName != "") {
1566            aValue = GetObjectPath(aFather);
1567           aPath = aValue + aPath;
1568        }
1569     }
1570   }
1571
1572   return aPath;
1573 }
1574
1575
1576 //============================================================================
1577 /*! Function : GetObjectPathByIOR
1578  *  Purpose  :
1579  */
1580 //============================================================================
1581 std::string SALOMEDSImpl_Study::GetObjectPathByIOR(const std::string& theIOR)
1582 {
1583   _errorCode = "";
1584
1585   std::string aPath;
1586   SALOMEDSImpl_SObject so = FindObjectIOR(theIOR);
1587   if(!so) {
1588     _errorCode = "No SObject was found by IOR";
1589     return aPath;
1590   }
1591
1592   return GetObjectPath(so);
1593 }
1594
1595
1596 //============================================================================
1597 /*! Function : SetContext
1598  *  Purpose  : Sets the current context
1599  */
1600 //============================================================================
1601 bool SALOMEDSImpl_Study::SetContext(const std::string& thePath)
1602 {
1603   _errorCode = "";
1604   if(thePath.empty()) {
1605     _errorCode = "InvalidPath";
1606     return false;
1607   }
1608
1609   std::string aPath(thePath), aContext("");
1610   bool isInvalid = false;
1611   SALOMEDSImpl_SObject aSO;
1612
1613   if(aPath[0] != '/') { //Relative path
1614     aContext = GetContext();
1615     aContext += '/';
1616     aContext += aPath;
1617   }
1618   else
1619     aContext = aPath;
1620
1621   try {
1622     aSO = FindObjectByPath(aContext);
1623   }
1624   catch( ... ) {
1625     isInvalid = true;
1626   }
1627
1628   if(isInvalid || !aSO) {
1629     _errorCode = "InvalidContext";
1630     return false;
1631   }
1632
1633   DF_Label aLabel = aSO.GetLabel();
1634   if(aLabel.IsNull()) {
1635     _errorCode = "InvalidContext";
1636     return false;
1637   }
1638   else
1639     _current = aLabel;  //Set the current context
1640
1641   return true;
1642 }
1643
1644 //============================================================================
1645 /*! Function : GetContext
1646  *  Purpose  : Gets the current context
1647  */
1648 //============================================================================
1649 std::string SALOMEDSImpl_Study::GetContext()
1650 {
1651   _errorCode = "";
1652
1653   if(_current.IsNull()) {
1654     _errorCode = "InvaidContext";
1655     return "";
1656   }
1657   SALOMEDSImpl_SObject so = GetSObject(_current);
1658   return GetObjectPath(so);
1659 }
1660
1661 //============================================================================
1662 /*! Function : GetObjectNames
1663  *  Purpose  : method to get all object names in the given context (or in the current context, if 'theContext' is empty)
1664  */
1665 //============================================================================
1666 std::vector<std::string> SALOMEDSImpl_Study::GetObjectNames(const std::string& theContext)
1667 {
1668   _errorCode = "";
1669
1670   std::vector<std::string> aResultSeq;
1671   DF_Label aLabel;
1672   if (theContext.empty()) {
1673     aLabel = _current;
1674   } else {
1675     DF_Label aTmp = _current;
1676     SetContext(theContext);
1677     aLabel = _current;
1678     _current = aTmp;
1679   }
1680   if (aLabel.IsNull()) {
1681     _errorCode = "InvalidContext";
1682     return aResultSeq;
1683   }
1684
1685   DF_ChildIterator anIter (aLabel, true); // iterate all subchildren at all sublevels
1686   for (; anIter.More(); anIter.Next()) {
1687     DF_Label aLabel = anIter.Value();
1688     SALOMEDSImpl_AttributeName* aName;
1689     if ((aName=(SALOMEDSImpl_AttributeName*)aLabel.FindAttribute(SALOMEDSImpl_AttributeName::GetID())))
1690       aResultSeq.push_back(aName->Value());
1691   }
1692
1693   return aResultSeq;
1694 }
1695
1696 //============================================================================
1697 /*! Function : GetDirectoryNames
1698  *  Purpose  : method to get all directory names in the given context (or in the current context, if 'theContext' is empty)
1699  */
1700 //============================================================================
1701 std::vector<std::string> SALOMEDSImpl_Study::GetDirectoryNames(const std::string& theContext)
1702 {
1703   _errorCode = "";
1704
1705   std::vector<std::string> aResultSeq;
1706   DF_Label aLabel;
1707   if (theContext.empty()) {
1708     aLabel = _current;
1709   } else {
1710     DF_Label aTmp = _current;
1711     SetContext(theContext);
1712     aLabel = _current;
1713     _current = aTmp;
1714   }
1715   if (aLabel.IsNull()) {
1716     _errorCode = "InvalidContext";
1717     return aResultSeq;
1718   }
1719
1720   DF_ChildIterator anIter (aLabel, true); // iterate first-level children at all sublevels
1721   for (; anIter.More(); anIter.Next()) {
1722     DF_Label aLabel = anIter.Value();
1723     SALOMEDSImpl_AttributeLocalID* anID;
1724     if ((anID=(SALOMEDSImpl_AttributeLocalID*)aLabel.FindAttribute(SALOMEDSImpl_AttributeLocalID::GetID()))) {
1725       if (anID->Value() == DIRECTORYID) {
1726         SALOMEDSImpl_AttributeName* aName;
1727         if ((aName=(SALOMEDSImpl_AttributeName*)aLabel.FindAttribute(SALOMEDSImpl_AttributeName::GetID()))) {
1728           aResultSeq.push_back(aName->Value());
1729         }
1730       }
1731     }
1732   }
1733
1734   return aResultSeq;
1735 }
1736
1737 //============================================================================
1738 /*! Function : GetFileNames
1739  *  Purpose  : method to get all file names in the given context (or in the current context, if 'theContext' is empty)
1740  */
1741 //============================================================================
1742 std::vector<std::string> SALOMEDSImpl_Study::GetFileNames(const std::string& theContext)
1743 {
1744   _errorCode = "";
1745
1746   std::vector<std::string> aResultSeq;
1747   DF_Label aLabel;
1748   if (theContext.empty()) {
1749     aLabel = _current;
1750   } else {
1751     DF_Label aTmp = _current;
1752     SetContext(theContext);
1753     aLabel = _current;
1754     _current = aTmp;
1755   }
1756   if (aLabel.IsNull()) {
1757     _errorCode = "InvalidContext";
1758     return aResultSeq;
1759   }
1760
1761   DF_ChildIterator anIter (aLabel, true); // iterate all subchildren at all sublevels
1762   for (; anIter.More(); anIter.Next()) {
1763     DF_Label aLabel = anIter.Value();
1764     SALOMEDSImpl_AttributeLocalID* anID;
1765     if ((anID=(SALOMEDSImpl_AttributeLocalID*)aLabel.FindAttribute(SALOMEDSImpl_AttributeLocalID::GetID()))) {
1766       if (anID->Value() == FILELOCALID) {
1767         SALOMEDSImpl_AttributePersistentRef* aName;
1768         if ((aName=(SALOMEDSImpl_AttributePersistentRef*)aLabel.FindAttribute(SALOMEDSImpl_AttributePersistentRef::GetID()))) {
1769           std::string aFileName = aName->Value();
1770           if (aFileName.size() > 0)
1771             aResultSeq.push_back(aFileName.substr(strlen(FILEID), aFileName.size()));
1772         }
1773       }
1774     }
1775   }
1776
1777   return aResultSeq;
1778 }
1779
1780 //============================================================================
1781 /*! Function : GetComponentNames
1782  *  Purpose  : method to get all components names
1783  */
1784 //============================================================================
1785 std::vector<std::string> SALOMEDSImpl_Study::GetComponentNames(const std::string& theContext)
1786 {
1787   _errorCode = "";
1788
1789   std::vector<std::string> aResultSeq;
1790   DF_ChildIterator anIter(_doc->Main(), false); // iterate all subchildren at first level
1791   for(; anIter.More(); anIter.Next()) {
1792     DF_Label aLabel = anIter.Value();
1793     SALOMEDSImpl_AttributeName* aName;
1794     if ((aName=(SALOMEDSImpl_AttributeName*)aLabel.FindAttribute(SALOMEDSImpl_AttributeName::GetID())))
1795       aResultSeq.push_back(aName->Value());
1796   }
1797
1798   return aResultSeq;
1799 }
1800
1801 //============================================================================
1802 /*! Function : NewChildIterator
1803  *  Purpose  : Create a ChildIterator from an SObject
1804  */
1805 //============================================================================
1806 SALOMEDSImpl_ChildIterator SALOMEDSImpl_Study::NewChildIterator(const SALOMEDSImpl_SObject& aSO)
1807 {
1808   _errorCode = "";
1809   return SALOMEDSImpl_ChildIterator(aSO);
1810 }
1811
1812
1813 //============================================================================
1814 /*! Function : NewComponentIterator
1815  *  Purpose  : Create a SComponentIterator
1816  */
1817 //============================================================================
1818 SALOMEDSImpl_SComponentIterator SALOMEDSImpl_Study::NewComponentIterator()
1819 {
1820   _errorCode = "";
1821   return SALOMEDSImpl_SComponentIterator(_doc);
1822 }
1823
1824
1825 //============================================================================
1826 /*! Function : NewBuilder
1827  *  Purpose  : Create a StudyBuilder
1828  */
1829 //============================================================================
1830 SALOMEDSImpl_StudyBuilder* SALOMEDSImpl_Study::NewBuilder()
1831 {
1832   _errorCode = "";
1833   if(_autoFill) {
1834     _builder->SetOnAddSObject(_cb);
1835     _builder->SetOnRemoveSObject(_cb);
1836   }
1837   return _builder;
1838
1839 }
1840
1841 //============================================================================
1842 /*! Function : Name
1843  *  Purpose  : get study name
1844  */
1845 //============================================================================
1846 std::string SALOMEDSImpl_Study::Name()
1847 {
1848   _errorCode = "";
1849   return Kernel_Utils::GetBaseName( _name, false );
1850 }
1851
1852 //============================================================================
1853 /*! Function : IsSaved
1854  *  Purpose  : get if study has been saved
1855  */
1856 //============================================================================
1857 bool SALOMEDSImpl_Study::IsSaved()
1858 {
1859   _errorCode = "";
1860   return _Saved;
1861 }
1862
1863 //============================================================================
1864 /*! Function : IsSaved
1865  *  Purpose  : set if study has been saved
1866  */
1867 //============================================================================
1868 void SALOMEDSImpl_Study::IsSaved(bool save)
1869 {
1870   _errorCode = "";
1871   _Saved = save;
1872   if(save) _doc->SetModified(false);
1873 }
1874
1875 //============================================================================
1876 /*! Function : IsModified
1877  *  Purpose  : Detect if a Study has been modified since it has been saved
1878  */
1879 //============================================================================
1880 bool SALOMEDSImpl_Study::IsModified()
1881 {
1882   _errorCode = "";
1883
1884   // True if is modified
1885   if (_doc && _doc->IsModified()) return true;
1886
1887   return false;
1888 }
1889
1890 //============================================================================
1891 /*! Function : URL
1892  *  Purpose  : get URL of the study (persistent reference of the study)
1893  */
1894 //============================================================================
1895 std::string SALOMEDSImpl_Study::URL()
1896 {
1897   _errorCode = "";
1898   if ( _URL.empty() )
1899     return Kernel_Utils::AddExtension( _name );
1900   return _URL;
1901 }
1902
1903 //============================================================================
1904 /*! Function : URL
1905  *  Purpose  : set URL of the study (persistent reference of the study)
1906  */
1907 //============================================================================
1908 void SALOMEDSImpl_Study::URL(const std::string& url)
1909 {
1910   _errorCode = "";
1911   _URL = url;
1912   _name = url;
1913
1914   /*jfa: Now name of SALOMEDS study will correspond to name of SalomeApp study
1915   std::string tmp(_URL);
1916
1917   char *aName = (char*)tmp.ToCString();
1918   char *adr = strtok(aName, "/");
1919   while (adr)
1920     {
1921       aName = adr;
1922       adr = strtok(NULL, "/");
1923     }
1924   Name(aName);*/
1925 }
1926
1927
1928 //============================================================================
1929 /*! Function : _FindObject
1930  *  Purpose  : Find an Object with SALOMEDSImpl_Name = anObjectName
1931  */
1932 //============================================================================
1933 SALOMEDSImpl_SObject SALOMEDSImpl_Study::_FindObject(const SALOMEDSImpl_SObject& SO,
1934                                                      const std::string& theObjectName,
1935                                                      bool& _find)
1936 {
1937   SALOMEDSImpl_SObject RefSO;
1938   if(!SO) return RefSO;
1939
1940   // Iterate on each objects and subobjects of the component
1941   // If objectName find, stop the loop and get the object reference
1942   SALOMEDSImpl_AttributeName* anAttr;
1943
1944   std::string soid = SO.GetID();
1945   DF_ChildIterator it(SO.GetLabel());
1946   for (; it.More(); it.Next()){
1947     if(!_find)
1948       {
1949         if ((anAttr=(SALOMEDSImpl_AttributeName*)it.Value().FindAttribute(SALOMEDSImpl_AttributeName::GetID())))
1950         {
1951           std::string Val(anAttr->Value());
1952           if (Val == theObjectName)
1953             {
1954               RefSO = GetSObject(it.Value());
1955               _find = true;
1956             }
1957         }
1958         if (!_find) RefSO = _FindObject(GetSObject(it.Value()), theObjectName, _find);
1959       }
1960   }
1961   return RefSO;
1962 }
1963
1964 //============================================================================
1965 /*! Function : _FindObjectIOR
1966  *  Purpose  : Find an Object with SALOMEDSImpl_IOR = anObjectIOR
1967  */
1968 //============================================================================
1969 SALOMEDSImpl_SObject
1970 SALOMEDSImpl_Study::_FindObjectIOR(const SALOMEDSImpl_SObject& SO,
1971                                    const std::string& theObjectIOR,
1972                                    bool& _find)
1973 {
1974   SALOMEDSImpl_SObject RefSO, aSO;
1975   if(!SO) return RefSO;
1976
1977   // Iterate on each objects and subobjects of the component
1978   // If objectName find, stop the loop and get the object reference
1979   SALOMEDSImpl_AttributeIOR* anAttr;
1980
1981   DF_ChildIterator it(SO.GetLabel());
1982   for (; it.More();it.Next()){
1983     if(!_find)
1984       {
1985         if ((anAttr=(SALOMEDSImpl_AttributeIOR*)it.Value().FindAttribute(SALOMEDSImpl_AttributeIOR::GetID())))
1986         {
1987           std::string Val(anAttr->Value());
1988           if (Val == theObjectIOR)
1989             {
1990               RefSO = GetSObject(it.Value());
1991               _find = true;
1992             }
1993         }
1994         aSO = GetSObject(it.Value());
1995         if (!_find) RefSO =  _FindObjectIOR(aSO, theObjectIOR, _find);
1996       }
1997   }
1998   return RefSO;
1999 }
2000
2001 //============================================================================
2002 /*! Function : _GetNoteBookAccessor
2003  *  Purpose  : Find an Object with SALOMEDSImpl_IOR = anObjectIOR
2004  */
2005 //============================================================================
2006 std::string SALOMEDSImpl_Study::_GetNoteBookAccessor(){
2007   return std::string("notebook");
2008 }
2009
2010 //============================================================================
2011 /*! Function : _GetStudyVariablesScript
2012  *  Purpose  :
2013  */
2014 //============================================================================
2015 std::string SALOMEDSImpl_Study::_GetStudyVariablesScript()
2016 {
2017   std::string dump("");
2018
2019   if(myNoteBookVars.empty())
2020     return dump;
2021
2022   Kernel_Utils::Localizer loc;
2023
2024   dump += "####################################################\n";
2025   dump += "##       Begin of NoteBook variables section      ##\n";
2026   dump += "####################################################\n";
2027
2028   std::string set_method = _GetNoteBookAccessor()+".set(";
2029   std::string varName;
2030   std::string varValue;
2031   for(int i = 0 ; i < myNoteBookVars.size();i++ ) {
2032     varName = myNoteBookVars[i]->Name();
2033     varValue = myNoteBookVars[i]->SaveToScript();
2034     dump+=set_method+"\""+varName+"\", "+varValue+")\n";
2035   }
2036
2037   dump += "####################################################\n";
2038   dump += "##        End of NoteBook variables section       ##\n";
2039   dump += "####################################################\n";
2040
2041   return dump;
2042 }
2043
2044 //============================================================================
2045 /*! Function : _GetNoteBookAccess
2046  *  Purpose  :
2047  */
2048 //============================================================================
2049 std::string SALOMEDSImpl_Study::_GetNoteBookAccess(const std::string& theStudyVar)
2050 {
2051   std::string notebook = "import salome_notebook\n";
2052   notebook += _GetNoteBookAccessor() + " = salome_notebook.NoteBook(" + theStudyVar + ")" ;
2053   return notebook;
2054 }
2055
2056 bool SALOMEDSImpl_Study::IsLocked()
2057 {
2058   _errorCode = "";
2059   return GetProperties()->IsLocked();
2060 }
2061
2062 void SALOMEDSImpl_Study::UpdateIORLabelMap(const std::string& anIOR,const std::string& anEntry)
2063 {
2064   _errorCode = "";
2065   DF_Label aLabel = DF_Label::Label(_doc->Main(), anEntry, true);
2066   std::map<std::string, DF_Label>::iterator it=myIORLabels.find(anIOR);
2067   if (it != myIORLabels.end()) myIORLabels.erase(it);
2068   myIORLabels[anIOR] = aLabel;
2069 }
2070
2071 void SALOMEDSImpl_Study::DeleteIORLabelMapItem(const std::string& anIOR)
2072 {
2073   std::map<std::string, DF_Label>::iterator it=myIORLabels.find(anIOR);
2074   if (it != myIORLabels.end())
2075     {
2076       //remove the ior entry and decref the genericobj (if it's one)
2077       myIORLabels.erase(it);
2078     }
2079 }
2080
2081 SALOMEDSImpl_Study* SALOMEDSImpl_Study::GetStudy(const DF_Label& theLabel)
2082 {
2083   SALOMEDSImpl_StudyHandle* Att;
2084   if ((Att=(SALOMEDSImpl_StudyHandle*)theLabel.Root().FindAttribute(SALOMEDSImpl_StudyHandle::GetID()))) {
2085     return Att->Get();
2086   }
2087   return NULL;
2088 }
2089
2090 SALOMEDSImpl_SObject SALOMEDSImpl_Study::SObject(const DF_Label& theLabel)
2091 {
2092   return GetStudy(theLabel)->GetSObject(theLabel);
2093 }
2094
2095 SALOMEDSImpl_SComponent SALOMEDSImpl_Study::SComponent(const DF_Label& theLabel)
2096 {
2097   return GetStudy(theLabel)->GetSComponent(theLabel);
2098 }
2099
2100
2101 void SALOMEDSImpl_Study::IORUpdated(const SALOMEDSImpl_AttributeIOR* theAttribute)
2102 {
2103   std::string aString = theAttribute->Label().Entry();
2104   GetStudy(theAttribute->Label())->UpdateIORLabelMap(theAttribute->Value(), aString);
2105 }
2106
2107 std::vector<SALOMEDSImpl_SObject> SALOMEDSImpl_Study::FindDependances(const SALOMEDSImpl_SObject& anObject)
2108 {
2109   _errorCode = "";
2110   std::vector<SALOMEDSImpl_SObject> aSeq;
2111
2112   SALOMEDSImpl_AttributeTarget* aTarget;
2113   if ((aTarget=(SALOMEDSImpl_AttributeTarget*)anObject.GetLabel().FindAttribute(SALOMEDSImpl_AttributeTarget::GetID()))) {
2114     return aTarget->Get();
2115   }
2116
2117   return aSeq;
2118 }
2119
2120
2121 SALOMEDSImpl_AttributeStudyProperties* SALOMEDSImpl_Study::GetProperties()
2122 {
2123   _errorCode = "";
2124   return SALOMEDSImpl_AttributeStudyProperties::Set(_doc->Main());
2125 }
2126
2127 std::string SALOMEDSImpl_Study::GetLastModificationDate()
2128 {
2129   _errorCode = "";
2130   SALOMEDSImpl_AttributeStudyProperties* aProp = GetProperties();
2131
2132   std::vector<std::string> aNames;
2133   std::vector<int> aMinutes, aHours, aDays, aMonths, aYears;
2134   aProp->GetModifications(aNames, aMinutes, aHours, aDays, aMonths, aYears);
2135
2136   int aLastIndex = aNames.size()-1;
2137   char aResult[20];
2138   sprintf(aResult, "%2.2d/%2.2d/%4.4d %2.2d:%2.2d",
2139           (int)(aDays[aLastIndex]),(int)(aMonths[aLastIndex]), (int)(aYears[aLastIndex]),
2140           (int)(aHours[aLastIndex]), (int)(aMinutes[aLastIndex]));
2141   std::string aResStr (aResult);
2142   return aResStr;
2143 }
2144
2145 std::vector<std::string> SALOMEDSImpl_Study::GetModificationsDate()
2146 {
2147   _errorCode = "";
2148   SALOMEDSImpl_AttributeStudyProperties* aProp = GetProperties();
2149
2150   std::vector<std::string> aNames;
2151   std::vector<int> aMinutes, aHours, aDays, aMonths, aYears;
2152   aProp->GetModifications(aNames, aMinutes, aHours, aDays, aMonths, aYears);
2153
2154   int anIndex, aLength = aNames.size();
2155   std::vector<std::string> aDates;
2156
2157   for (anIndex = 1; anIndex < aLength; anIndex++) {
2158     char aDate[20];
2159     sprintf(aDate, "%2.2d/%2.2d/%4.4d %2.2d:%2.2d",
2160             (int)(aDays[anIndex]), (int)(aMonths[anIndex]), (int)(aYears[anIndex]),
2161             (int)(aHours[anIndex]), (int)(aMinutes[anIndex]));
2162     aDates.push_back(aDate);
2163   }
2164   return aDates;
2165 }
2166
2167
2168
2169 //============================================================================
2170 /*! Function : GetUseCaseBuilder
2171  *  Purpose  : Returns a UseCase builder
2172  */
2173 //============================================================================
2174 SALOMEDSImpl_UseCaseBuilder* SALOMEDSImpl_Study::GetUseCaseBuilder()
2175 {
2176   _errorCode = "";
2177   return _useCaseBuilder;
2178 }
2179
2180 //============================================================================
2181 /*! Function : GetSComponent
2182  *  Purpose  :
2183  */
2184 //============================================================================
2185 SALOMEDSImpl_SComponent SALOMEDSImpl_Study::GetSComponent(const std::string& theEntry)
2186 {
2187   SALOMEDSImpl_SComponent aSCO;
2188   if(_mapOfSCO.find(theEntry) != _mapOfSCO.end())
2189     aSCO = _mapOfSCO[theEntry];
2190   else {
2191     DF_Label aLabel = DF_Label::Label(_doc->Main(), theEntry);
2192     aSCO = SALOMEDSImpl_SComponent(aLabel);
2193     _mapOfSCO[theEntry] = aSCO;
2194   }
2195
2196   return aSCO;
2197 }
2198
2199 //============================================================================
2200 /*! Function : GetSComponent
2201  *  Purpose  :
2202  */
2203 //============================================================================
2204 SALOMEDSImpl_SComponent SALOMEDSImpl_Study::GetSComponent(const DF_Label& theLabel)
2205 {
2206   return SALOMEDSImpl_SComponent(theLabel);
2207 }
2208
2209 //============================================================================
2210 /*! Function : GetSObject
2211  *  Purpose  :
2212  */
2213 //============================================================================
2214 SALOMEDSImpl_SObject SALOMEDSImpl_Study::GetSObject(const std::string& theEntry)
2215 {
2216   SALOMEDSImpl_SObject aSO;
2217   std::map<std::string, SALOMEDSImpl_SObject>::iterator it=_mapOfSO.find(theEntry);
2218   if(it != _mapOfSO.end())
2219     aSO = it->second;
2220   else {
2221     DF_Label aLabel = DF_Label::Label(_doc->Main(), theEntry);
2222     aSO = SALOMEDSImpl_SObject(aLabel);
2223     _mapOfSO[theEntry] = aSO;
2224   }
2225
2226   return aSO;
2227 }
2228
2229 //============================================================================
2230 /*! Function : GetSObject
2231  *  Purpose  :
2232  */
2233 //============================================================================
2234 SALOMEDSImpl_SObject SALOMEDSImpl_Study::GetSObject(const DF_Label& theLabel)
2235 {
2236   return SALOMEDSImpl_SObject(theLabel);
2237 }
2238
2239 //============================================================================
2240 /*! Function : GetAttribute
2241  *  Purpose  :
2242  */
2243 //============================================================================
2244 DF_Attribute* SALOMEDSImpl_Study::GetAttribute(const std::string& theEntry,
2245                                                const std::string& theType)
2246 {
2247   SALOMEDSImpl_SObject aSO = GetSObject(theEntry);
2248   DF_Attribute* anAttr;
2249   aSO.FindAttribute(anAttr, theType);
2250   return anAttr;
2251 }
2252
2253 //! number of spaces for indentation in Python dump files (to replace \t symbols)
2254 static const int indent_size = 2;
2255
2256 static std::string replace_tabs( const std::string& in )
2257 {
2258   std::string out = in;
2259 #ifdef WITHOUT_TABS
2260   size_t pos = out.find( '\t' );
2261   while ( pos != std::string::npos ) {
2262     out.replace( pos, 1, indent_size, ' ' );
2263     pos = out.find( '\t' );
2264   }
2265 #endif
2266   return out;
2267 }
2268
2269 static std::string GetComponentHeader(const char* theComponentName)
2270 {
2271   std::stringstream txt;
2272   txt << "###" << std::endl;
2273   txt << "### " << theComponentName << " component" << std::endl;
2274   txt << "###" << std::endl;
2275   return txt.str();
2276 }
2277
2278 //============================================================================
2279 /*! Function : DumpStudy
2280  *  Purpose  :
2281  */
2282 //============================================================================
2283 bool SALOMEDSImpl_Study::DumpStudy(const std::string& thePath,
2284                                    const std::string& theBaseName,
2285                                    bool isPublished,
2286                                    bool isMultiFile,
2287                                    SALOMEDSImpl_DriverFactory* theFactory)
2288 {
2289   _errorCode = "";
2290
2291   if(theFactory == NULL) {
2292     _errorCode = "Null factory for creation of Engines";
2293     return false;
2294   }
2295
2296   std::vector<std::string> aSeq;
2297   std::string aCompType, aFactoryType;
2298
2299   //Build a list of all components in the Study
2300   SALOMEDSImpl_SComponentIterator itcomponent = NewComponentIterator();
2301
2302   for (; itcomponent.More(); itcomponent.Next()) {
2303     SALOMEDSImpl_SComponent sco = itcomponent.Value();
2304     aCompType = sco.ComponentDataType();
2305    if (aCompType == "GEOM")
2306       aSeq.insert(aSeq.begin(), aCompType);
2307     else
2308       aSeq.push_back(aCompType);
2309   }
2310   // re-arrange modules in the sequence, if specific order is given via SALOME_MODULES_ORDER environment variable.
2311   if ( getenv("SALOME_MODULES_ORDER") != 0 ) {
2312     std::string order = getenv("SALOME_MODULES_ORDER");
2313     std::vector<std::string> mlist;
2314     while ( !order.empty() ) {
2315       size_t idx = order.find( "," );
2316       std::string m = order.substr(0, idx);
2317       order = order.substr( ( idx == std::string::npos ) ? order.size() : idx+1 );
2318       if ( m.empty() || std::find( mlist.begin(), mlist.end(), m ) != mlist.end() ) continue;
2319       mlist.push_back( m );
2320     }
2321
2322     for ( std::vector<std::string>::reverse_iterator mit = mlist.rbegin(); mit != mlist.rend(); ++mit ) {
2323       std::vector<std::string>::iterator it = std::find( aSeq.begin(), aSeq.end(), *mit );
2324       if ( it != aSeq.end() ) {
2325         aSeq.erase( it );
2326         aSeq.insert( aSeq.begin(), *mit );
2327       }
2328     }
2329   }
2330
2331 #ifdef WIN32
2332   std::string aFileName =
2333     thePath + std::string("\\") + theBaseName + std::string(".py");
2334 #else
2335   std::string aFileName =
2336     thePath + std::string("/")  + theBaseName + std::string(".py");
2337 #endif
2338
2339   //Create a file that will contain a main Study script
2340   std::fstream fp;
2341   fp.open(aFileName.c_str(), std::ios::out);
2342
2343 #ifdef WIN32
2344   bool isOpened = fp.is_open();
2345 #else
2346   bool isOpened = fp.rdbuf()->is_open();
2347 #endif
2348
2349   if(!isOpened) {
2350     _errorCode = std::string("Can't create a file ")+aFileName;
2351     return false;
2352   }
2353
2354   std::stringstream sfp;
2355
2356   std::string aBatchModeScript = "salome";
2357
2358   //Output to the main Study script required Python modules import,
2359   //set sys.path and add a creation of the study.
2360
2361   // dump header
2362   sfp << GetDumpStudyComment() << std::endl;
2363
2364   // global imports
2365   sfp << "import sys" << std::endl;
2366   sfp << "import " << aBatchModeScript << std::endl << std::endl;
2367
2368   std::string aStudyVar = "salome.myStudy";
2369   // initialization function
2370   sfp << aBatchModeScript << ".salome_init()" << std::endl;
2371   if ( !isMultiFile ) {
2372     sfp << "theStudy = " << aStudyVar << std::endl << std::endl;
2373     aStudyVar = "theStudy";
2374   }
2375   // notebook initialization
2376   sfp << _GetNoteBookAccess(aStudyVar) << std::endl;
2377
2378   // extend sys.path with the directory where the script is being dumped to
2379   sfp << "sys.path.insert( 0, r\'" << thePath << "\')" << std::endl << std::endl;
2380
2381   // dump NoteBook variables
2382   sfp << _GetStudyVariablesScript();
2383
2384   // dump visual parameters if necessary
2385   bool isDumpVisuals = SALOMEDSImpl_IParameters::isDumpPython(this);
2386   int lastSavePoint = -1;
2387   if(isDumpVisuals) {
2388     lastSavePoint = SALOMEDSImpl_IParameters::getLastSavePoint(this);
2389     if(lastSavePoint > 0) {
2390       sfp << SALOMEDSImpl_IParameters::getStudyScript(this, lastSavePoint) << std::endl << std::endl;
2391     }
2392   }
2393
2394   std::vector<std::string> aSeqOfFileNames;
2395
2396   // dump all components and create the components specific scripts
2397   bool isOk = true;
2398   int aLength = aSeq.size();
2399   for(int i = 1; i <= aLength; i++) {
2400
2401     aCompType = aSeq[i-1];
2402     SALOMEDSImpl_SComponent sco = FindComponent(aCompType);
2403     SALOMEDSImpl_Driver* aDriver = NULL;
2404     // if there is an associated Engine call its method for saving
2405     std::string IOREngine;
2406     try {
2407       if (!sco.ComponentIOR(IOREngine)) {
2408         if (!aCompType.empty()) {
2409
2410           aDriver = theFactory->GetDriverByType(aCompType);
2411
2412           if (aDriver != NULL) {
2413             SALOMEDSImpl_StudyBuilder* SB = NewBuilder();
2414             if(!SB->LoadWith(sco, aDriver)) {
2415               _errorCode = SB->GetErrorCode();
2416               return false;
2417             }
2418           }
2419           else continue;
2420         }
2421       }
2422       else {
2423         aDriver = theFactory->GetDriverByIOR(IOREngine);
2424       }
2425     } catch(...) {
2426       _errorCode = "Can not restore information to dump it";
2427       return false;
2428     }
2429
2430     if(aDriver == NULL) continue;
2431
2432     bool isValidScript;
2433     long aStreamLength  = 0;
2434     SALOMEDSImpl_TMPFile* aStream = aDriver->DumpPython(isPublished, isMultiFile, isValidScript, aStreamLength);
2435     if ( !isValidScript )
2436       isOk = false;
2437
2438     std::stringstream sfp2;
2439     
2440     //Output the Python script generated by the component in the newly created file.
2441     if ( isMultiFile )
2442       sfp2 << GetDumpStudyComment( aCompType.c_str() ) << std::endl;
2443     else
2444       sfp2 << GetComponentHeader( aCompType.c_str() ) << std::endl;
2445     sfp2 << aStream->Data();
2446     
2447     if ( isMultiFile ) {
2448       //Create a file that will contain the component specific script
2449       std::fstream fp2;
2450 #ifdef WIN32
2451       aFileName=thePath+std::string("\\");
2452 #else
2453       aFileName=thePath+std::string("/");
2454 #endif
2455       std::string aScriptName;
2456       aScriptName += theBaseName;
2457       aScriptName += "_";
2458       aScriptName += aCompType;
2459       
2460       aFileName += aScriptName+ std::string(".py");
2461       aSeqOfFileNames.push_back(aFileName);
2462       
2463       fp2.open(aFileName.c_str(), std::ios::out);
2464       
2465 #ifdef WIN32
2466       isOpened = fp2.is_open();
2467 #else
2468       isOpened = fp2.rdbuf()->is_open();
2469 #endif
2470       
2471       if(!isOpened) {
2472         _errorCode = std::string("Can't create a file ")+aFileName;
2473         SALOMEDSImpl_Tool::RemoveTemporaryFiles(thePath, aSeqOfFileNames, false);
2474         return false;
2475       }
2476      
2477       // replace '\t' symbols
2478       fp2 << replace_tabs( sfp2.str() );
2479
2480       fp2.close();
2481
2482       //Add to the main script a call to RebuildData of the generated by the component the Python script
2483       sfp << "import " << aScriptName << std::endl;
2484       sfp << aScriptName << ".RebuildData(" << aBatchModeScript << ".myStudy)" << std::endl;
2485     }
2486     else
2487       sfp << sfp2.str();
2488
2489     if(aStream) delete aStream;
2490   }
2491
2492   sfp << std::endl;
2493   sfp << "if salome.sg.hasDesktop():" << std::endl;
2494   sfp << "\tsalome.sg.updateObjBrowser(True)" << std::endl;
2495
2496   if(isDumpVisuals) { //Output the call to Session's method restoreVisualState
2497     sfp << "\tiparameters.getSession().restoreVisualState(1)" << std::endl;
2498   }
2499
2500   // replace '\t' symbols
2501   fp << replace_tabs( sfp.str() );
2502   
2503   fp.close();
2504
2505   return isOk;
2506 }
2507
2508 //=======================================================================
2509 //function : GetDumpStudyComment
2510 //purpose  : return a header comment for a DumpStudy script
2511 //=======================================================================
2512
2513 std::string SALOMEDSImpl_Study::GetDumpStudyComment(const char* theComponentName)
2514 {
2515   std::stringstream txt;
2516   txt << "# -*- coding: utf-8 -*-" << std::endl << std::endl;
2517   txt << "###" << std::endl;
2518   txt << "### This file is generated automatically by SALOME v"
2519       << KERNEL_VERSION_STR
2520       << " with dump python functionality";
2521   if ( theComponentName )
2522     txt << " (" << theComponentName << " component)";
2523   txt << std::endl;
2524   txt << "###" << std::endl;
2525   return txt.str();
2526 }
2527
2528 void dumpSO(const SALOMEDSImpl_SObject& theSO,
2529             std::fstream& fp,
2530             const std::string& Tab,
2531             SALOMEDSImpl_Study* theStudy);
2532
2533 //============================================================================
2534 /*! Function : dump
2535  *  Purpose  :
2536  */
2537 //============================================================================
2538 void SALOMEDSImpl_Study::dump(const std::string& theFileName)
2539 {
2540   //Create a file that will contain a main Study script
2541   std::fstream fp;
2542   fp.open(theFileName.c_str(), std::ios::out);
2543
2544 #ifdef WIN32
2545   bool isOpened = fp.is_open();
2546 #else
2547   bool isOpened = fp.rdbuf()->is_open();
2548 #endif
2549
2550   if(!isOpened) {
2551     _errorCode = std::string("Can't create a file ")+theFileName;
2552     std::cout << "### SALOMEDSImpl_Study::dump Error: " << _errorCode << std::endl;
2553     return;
2554   }
2555
2556   SALOMEDSImpl_SObject aSO = FindObjectID("0:1");
2557   fp << "0:1" << std::endl;
2558   SALOMEDSImpl_ChildIterator Itr = NewChildIterator(aSO);
2559   std::string aTab("   ");
2560   for(; Itr.More(); Itr.Next()) {
2561     dumpSO(Itr.Value(), fp, aTab, this);
2562   }
2563
2564   fp.close();
2565 }
2566
2567
2568 void dumpSO(const SALOMEDSImpl_SObject& theSO,
2569             std::fstream& fp,
2570             const std::string& Tab,
2571             SALOMEDSImpl_Study* theStudy)
2572 {
2573   std::string aTab(Tab), anID(theSO.GetID());
2574   fp << aTab << anID << std::endl;
2575   std::vector<DF_Attribute*> attribs = theSO.GetLabel().GetAttributes();
2576   for(int i = 0; i<attribs.size(); i++) {
2577     SALOMEDSImpl_GenericAttribute* anAttr = dynamic_cast<SALOMEDSImpl_GenericAttribute*>(attribs[i]);
2578
2579     if(!anAttr) {
2580       continue;
2581     }
2582
2583     std::string aType = anAttr->GetClassType();
2584     fp << Tab << "  -- " << aType;
2585
2586     if(aType == std::string("AttributeReal")) {
2587       fp << " : " << dynamic_cast<SALOMEDSImpl_AttributeReal*>(anAttr)->Value();
2588     }
2589     else if(aType == std::string("AttributeInteger")) {
2590       fp << " : " << dynamic_cast<SALOMEDSImpl_AttributeInteger*>(anAttr)->Value();
2591     }
2592     else if(aType ==  std::string("AttributeName")) {
2593       fp << " : " << dynamic_cast<SALOMEDSImpl_AttributeName*>(anAttr)->Value();
2594     }
2595     else if(aType == std::string("AttributeComment")) {
2596       fp << " : " << dynamic_cast<SALOMEDSImpl_AttributeComment*>(anAttr)->Value();
2597     }
2598     else if(aType == std::string("AttributeReference")) {
2599       fp << " : " << dynamic_cast<SALOMEDSImpl_AttributeReference*>(anAttr)->Save();
2600     }
2601     fp << std::endl;
2602   }
2603
2604   SALOMEDSImpl_ChildIterator Itr = theStudy->NewChildIterator(theSO);
2605   std::string aNewTab("   ");
2606   aNewTab+=aTab;
2607   for(; Itr.More(); Itr.Next()) {
2608     dumpSO(Itr.Value(), fp, aNewTab, theStudy);
2609   }
2610
2611   return;
2612 }
2613
2614 void SALOMEDSImpl_Study::Modify()
2615 {
2616   _errorCode = "";
2617   _doc->SetModified(true);
2618 }
2619
2620 //============================================================================
2621 /*! Function :
2622  *  Purpose  :
2623  */
2624 //============================================================================
2625 SALOMEDSImpl_AttributeParameter* SALOMEDSImpl_Study::GetCommonParameters(const char* theID, int theSavePoint)
2626 {
2627   if (theSavePoint < -1) return NULL;
2628   SALOMEDSImpl_StudyBuilder* builder = NewBuilder();
2629   SALOMEDSImpl_SObject so = FindComponent((char*)theID);
2630   if (!so) so = builder->NewComponent((char*)theID);
2631   SALOMEDSImpl_AttributeParameter* attParam = NULL;
2632
2633   if (theSavePoint == -1) {
2634     int ctag = 1;
2635     DF_Label savePointLabel = so.GetLabel().FindChild( ctag, /*create=*/0 );
2636     DF_Label prevPointLabel;
2637     while ( !savePointLabel.IsNull() ) {
2638       ctag++;
2639       prevPointLabel = savePointLabel;
2640       savePointLabel = so.GetLabel().FindChild( ctag, /*create=*/0 );
2641     }
2642     if ( !prevPointLabel.IsNull() )
2643       so = GetSObject( prevPointLabel );
2644   }
2645   if (theSavePoint > 0) { // Try to find SObject that contains attribute parameter ...
2646     DF_Label savePointLabel = so.GetLabel().FindChild( theSavePoint, /*create=*/0 );
2647     if ( !savePointLabel.IsNull() )
2648       so = GetSObject( savePointLabel );
2649     else // ... if it does not exist - create a new one
2650       so = builder->NewObjectToTag( so, theSavePoint );
2651   }
2652
2653   DF_Attribute* A;
2654   if (so) {
2655     builder->FindAttribute(so, A, "AttributeParameter");
2656     if ( !A ) { // first call of GetCommonParameters on "Interface Applicative" component
2657       A = builder->FindOrCreateAttribute(so, "AttributeParameter");
2658     }
2659     attParam = dynamic_cast<SALOMEDSImpl_AttributeParameter*>( A );
2660   }
2661   return attParam;
2662 }
2663
2664 //============================================================================
2665 /*! Function :
2666  *  Purpose  :
2667  */
2668 //============================================================================
2669 SALOMEDSImpl_AttributeParameter* SALOMEDSImpl_Study::GetModuleParameters(const char* theID,
2670                                                                          const char* theModuleName,
2671                                                                          int theSavePoint)
2672 {
2673   if(theSavePoint < -1) return NULL;
2674   SALOMEDSImpl_AttributeParameter* main_ap = GetCommonParameters(theID, theSavePoint);
2675   SALOMEDSImpl_SObject main_so = main_ap->GetSObject();
2676   SALOMEDSImpl_AttributeParameter* par = NULL;
2677
2678   SALOMEDSImpl_ChildIterator it = NewChildIterator(main_so);
2679   std::string moduleName(theModuleName);
2680   for(; it.More(); it.Next()) {
2681     SALOMEDSImpl_SObject so(it.Value());
2682     if((par=(SALOMEDSImpl_AttributeParameter*)so.GetLabel().FindAttribute(SALOMEDSImpl_AttributeParameter::GetID()))) {
2683       if(!par->IsSet("AP_MODULE_NAME", (Parameter_Types)3)) continue; //3 -> PT_STRING
2684       if(par->GetString("AP_MODULE_NAME") == moduleName) return par;
2685     }
2686   }
2687
2688   SALOMEDSImpl_StudyBuilder* builder = NewBuilder();
2689   SALOMEDSImpl_SObject so = builder->NewObject(main_so);
2690   par  = dynamic_cast<SALOMEDSImpl_AttributeParameter*>(builder->FindOrCreateAttribute(so, "AttributeParameter"));
2691   par->SetString("AP_MODULE_NAME", moduleName);
2692   return par;
2693 }
2694
2695 //============================================================================
2696 /*! Function : SetStudyLock
2697  *  Purpose  :
2698  */
2699 //============================================================================
2700 void SALOMEDSImpl_Study::SetStudyLock(const char* theLockerID)
2701 {
2702   _lockers.push_back(theLockerID);
2703 }
2704
2705 //============================================================================
2706 /*! Function : IsStudyLocked
2707  *  Purpose  :
2708  */
2709 //============================================================================
2710 bool SALOMEDSImpl_Study::IsStudyLocked()
2711 {
2712   return (_lockers.size() > 0);
2713 }
2714
2715 //============================================================================
2716 /*! Function : UnLockStudy
2717  *  Purpose  :
2718  */
2719 //============================================================================
2720 void SALOMEDSImpl_Study::UnLockStudy(const char* theLockerID)
2721 {
2722   std::vector<std::string>::iterator vsI = _lockers.begin();
2723   int length = _lockers.size();
2724   bool isFound = false;
2725   std::string id(theLockerID);
2726   for(int i = 0; i<length; i++, vsI++) {
2727     if(id == _lockers[i]) {
2728       isFound = true;;
2729       break;
2730     }
2731   }
2732   if(isFound) _lockers.erase(vsI);
2733 }
2734
2735 //============================================================================
2736 /*! Function : GetLockerID
2737  *  Purpose  :
2738  */
2739 //============================================================================
2740 std::vector<std::string> SALOMEDSImpl_Study::GetLockerID()
2741 {
2742   return _lockers;
2743 }
2744
2745 //============================================================================
2746 /*! Function : SetVariable
2747  *  Purpose  :
2748  */
2749 //============================================================================
2750 void SALOMEDSImpl_Study::SetVariable(const std::string& theVarName,
2751                                      const double theValue,
2752                                      const SALOMEDSImpl_GenericVariable::VariableTypes theType)
2753 {
2754   bool modified = false;
2755   SALOMEDSImpl_GenericVariable* aGVar = GetVariable(theVarName);
2756
2757   if( aGVar == NULL ) {
2758
2759     SALOMEDSImpl_ScalarVariable* aSVar = new SALOMEDSImpl_ScalarVariable(theType, theVarName);
2760
2761     aSVar->setValue(theValue);
2762     myNoteBookVars.push_back(aSVar);
2763     modified = true;
2764   }
2765   else {
2766     if(SALOMEDSImpl_ScalarVariable* aSVar = dynamic_cast<SALOMEDSImpl_ScalarVariable*>(aGVar)) {
2767       modified = aSVar->setValue(theValue) || modified;
2768       modified = aSVar->setType(theType) || modified;
2769     }
2770   }
2771   if(modified)
2772     Modify();
2773 }
2774
2775 //============================================================================
2776 /*! Function : SetStringVariable
2777  *  Purpose  :
2778  */
2779 //============================================================================
2780 void SALOMEDSImpl_Study::SetStringVariable(const std::string& theVarName,
2781                                            const std::string& theValue,
2782                                            const SALOMEDSImpl_GenericVariable::VariableTypes theType)
2783 {
2784   bool modified = false;
2785   SALOMEDSImpl_GenericVariable* aGVar = GetVariable(theVarName);
2786
2787   if( aGVar == NULL ) {
2788
2789     SALOMEDSImpl_ScalarVariable* aSVar = new SALOMEDSImpl_ScalarVariable(theType, theVarName);
2790
2791     aSVar->setStringValue(theValue);
2792     myNoteBookVars.push_back(aSVar);
2793     modified = true;
2794   }
2795   else {
2796     if(SALOMEDSImpl_ScalarVariable* aSVar = dynamic_cast<SALOMEDSImpl_ScalarVariable*>(aGVar)) {
2797       modified = aSVar->setStringValue(theValue) || modified;
2798       modified = aSVar->setType(theType) || modified;
2799     }
2800   }
2801   if(modified)
2802     Modify();
2803 }
2804
2805 //============================================================================
2806 /*! Function : SetStringVariableAsDouble
2807  *  Purpose  :
2808  */
2809 //============================================================================
2810 void SALOMEDSImpl_Study::SetStringVariableAsDouble(const std::string& theVarName,
2811                                                    const double theValue,
2812                                                    const SALOMEDSImpl_GenericVariable::VariableTypes theType)
2813 {
2814   SALOMEDSImpl_GenericVariable* aGVar = GetVariable(theVarName);
2815   if(SALOMEDSImpl_ScalarVariable* aSVar = dynamic_cast<SALOMEDSImpl_ScalarVariable*>(aGVar))
2816     aSVar->setValue(theValue);
2817 }
2818
2819 //============================================================================
2820 /*! Function : GetReal
2821  *  Purpose  :
2822  */
2823 //============================================================================
2824 double SALOMEDSImpl_Study::GetVariableValue(const std::string& theVarName)
2825 {
2826   SALOMEDSImpl_GenericVariable* aGVar = GetVariable(theVarName);
2827
2828   if(aGVar != NULL )
2829     if(SALOMEDSImpl_ScalarVariable* aSVar = dynamic_cast<SALOMEDSImpl_ScalarVariable*>(aGVar))
2830       return aSVar->getValue();
2831
2832   return 0;
2833 }
2834
2835 //============================================================================
2836 /*! Function : GetString
2837  *  Purpose  :
2838  */
2839 //============================================================================
2840 std::string SALOMEDSImpl_Study::GetStringVariableValue(const std::string& theVarName)
2841 {
2842   SALOMEDSImpl_GenericVariable* aGVar = GetVariable(theVarName);
2843
2844   if(aGVar != NULL )
2845     if(SALOMEDSImpl_ScalarVariable* aSVar = dynamic_cast<SALOMEDSImpl_ScalarVariable*>(aGVar))
2846       return aSVar->getStringValue();
2847
2848   return 0;
2849 }
2850
2851 //============================================================================
2852 /*! Function : IsTypeOf
2853  *  Purpose  :
2854  */
2855 //============================================================================
2856 bool SALOMEDSImpl_Study::IsTypeOf(const std::string& theVarName,
2857                                   SALOMEDSImpl_GenericVariable::
2858                                   VariableTypes theType) const
2859 {
2860   SALOMEDSImpl_GenericVariable* aGVar = GetVariable(theVarName);
2861
2862   if(aGVar != NULL )
2863     return aGVar->Type() == theType;
2864
2865   return false;
2866 }
2867
2868 //============================================================================
2869 /*! Function : IsVariable
2870  *  Purpose  :
2871  */
2872 //============================================================================
2873 bool SALOMEDSImpl_Study::IsVariable(const std::string& theVarName) const
2874 {
2875   SALOMEDSImpl_GenericVariable* aGVar = GetVariable(theVarName);
2876   return (aGVar != NULL);
2877 }
2878
2879 //============================================================================
2880 /*! Function : GetVariableNames
2881  *  Purpose  :
2882  */
2883 //============================================================================
2884 std::vector<std::string> SALOMEDSImpl_Study::GetVariableNames() const
2885 {
2886   std::vector<std::string> aResult;
2887
2888   for(int i = 0; i < myNoteBookVars.size(); i++)
2889     aResult.push_back(myNoteBookVars[i]->Name());
2890
2891   return aResult;
2892 }
2893
2894 //============================================================================
2895 /*! Function : AddVariable
2896  *  Purpose  :
2897  */
2898 //============================================================================
2899 void SALOMEDSImpl_Study::AddVariable(SALOMEDSImpl_GenericVariable* theVariable)
2900 {
2901   myNoteBookVars.push_back(theVariable);
2902 }
2903
2904 //============================================================================
2905 /*! Function : AddVariable
2906  *  Purpose  :
2907  */
2908 //============================================================================
2909 SALOMEDSImpl_GenericVariable* SALOMEDSImpl_Study::GetVariable(const std::string& theName) const
2910 {
2911   SALOMEDSImpl_GenericVariable* aResult = NULL;
2912   for(int i = 0; i < myNoteBookVars.size();i++) {
2913     if(theName.compare(myNoteBookVars[i]->Name()) == 0) {
2914       aResult = myNoteBookVars[i];
2915       break;
2916     }
2917   }
2918   return aResult;
2919 }
2920
2921 //============================================================================
2922 /*! Function : RemoveVariable
2923  *  Purpose  :
2924  */
2925 //============================================================================
2926 bool SALOMEDSImpl_Study::RemoveVariable(const std::string& theVarName)
2927 {
2928   SALOMEDSImpl_GenericVariable* aVariable = GetVariable( theVarName );
2929   if( !aVariable )
2930     return false;
2931
2932   std::string aValue = aVariable->SaveToScript();
2933   ReplaceVariableAttribute( theVarName, aValue );
2934
2935   std::vector<SALOMEDSImpl_GenericVariable*>::iterator it = myNoteBookVars.begin(), itEnd = myNoteBookVars.end();
2936   for( ; it != itEnd; it++ )
2937   {
2938     SALOMEDSImpl_GenericVariable* aVariableRef = *it;
2939     if( aVariableRef && theVarName.compare( aVariableRef->Name() ) == 0 )
2940     {
2941       myNoteBookVars.erase( it );
2942       Modify();
2943       break;
2944     }
2945   }
2946
2947   return true;
2948 }
2949
2950 //============================================================================
2951 /*! Function : RenameVariable
2952  *  Purpose  :
2953  */
2954 //============================================================================
2955 bool SALOMEDSImpl_Study::RenameVariable(const std::string& theVarName, const std::string& theNewVarName)
2956 {
2957   SALOMEDSImpl_GenericVariable* aVariable = GetVariable( theVarName );
2958   if( !aVariable )
2959     return false;
2960
2961   ReplaceVariableAttribute( theVarName, theNewVarName );
2962
2963   std::vector<SALOMEDSImpl_GenericVariable*>::iterator it = myNoteBookVars.begin(), itEnd = myNoteBookVars.end();
2964   for( ; it != itEnd; it++ )
2965   {
2966     SALOMEDSImpl_GenericVariable* aVariableRef = *it;
2967     if( aVariableRef && theVarName.compare( aVariableRef->Name() ) == 0 )
2968     {
2969       aVariableRef->setName( theNewVarName );
2970       Modify();
2971       break;
2972     }
2973   }
2974
2975   return true;
2976 }
2977
2978 //============================================================================
2979 /*! Function : IsVariableUsed
2980  *  Purpose  :
2981  */
2982 //============================================================================
2983 bool SALOMEDSImpl_Study::IsVariableUsed(const std::string& theVarName)
2984 {
2985   return FindVariableAttribute( theVarName );
2986 }
2987
2988 //============================================================================
2989 /*! Function : FindVariableAttribute
2990  *  Purpose  :
2991  */
2992 //============================================================================
2993 bool SALOMEDSImpl_Study::FindVariableAttribute(SALOMEDSImpl_StudyBuilder* theStudyBuilder,
2994                                                SALOMEDSImpl_SObject theSObject,
2995                                                const std::string& theName)
2996 {
2997   SALOMEDSImpl_ChildIterator anIter = NewChildIterator( theSObject );
2998   for( ; anIter.More(); anIter.Next() )
2999     if( FindVariableAttribute( theStudyBuilder, anIter.Value(), theName ) )
3000       return true;
3001
3002   DF_Attribute* anAttr;
3003   if( theStudyBuilder->FindAttribute( theSObject, anAttr, "AttributeString" ) )
3004   {
3005     if( SALOMEDSImpl_AttributeString* aStringAttr = ( SALOMEDSImpl_AttributeString* )anAttr )
3006     {
3007       std::string aString = aStringAttr->Value();
3008
3009       std::vector< std::vector<std::string> > aSections = ParseVariables( aString );
3010       for( int i = 0, n = aSections.size(); i < n; i++ )
3011       {
3012         std::vector<std::string> aVector = aSections[i];
3013         for( int j = 0, m = aVector.size(); j < m; j++ )
3014         {
3015           std::string aStr = aVector[j];
3016           if( aStr.compare( theName ) == 0 )
3017             return true;
3018         }
3019       }
3020     }
3021   }
3022   return false;
3023 }
3024
3025 //============================================================================
3026 /*! Function : FindVariableAttribute
3027  *  Purpose  :
3028  */
3029 //============================================================================
3030 bool SALOMEDSImpl_Study::FindVariableAttribute(const std::string& theName)
3031 {
3032   SALOMEDSImpl_StudyBuilder* aStudyBuilder = NewBuilder();
3033   SALOMEDSImpl_SComponentIterator aCompIter = NewComponentIterator();
3034   for( ; aCompIter.More(); aCompIter.Next() )
3035   {
3036     SALOMEDSImpl_SObject aComp = aCompIter.Value();
3037     if( FindVariableAttribute( aStudyBuilder, aComp, theName ) )
3038       return true;
3039   }
3040   return false;
3041 }
3042
3043 //============================================================================
3044 /*! Function : ReplaceVariableAttribute
3045  *  Purpose  :
3046  */
3047 //============================================================================
3048 void SALOMEDSImpl_Study::ReplaceVariableAttribute(SALOMEDSImpl_StudyBuilder* theStudyBuilder,
3049                                                   SALOMEDSImpl_SObject theSObject,
3050                                                   const std::string& theSource,
3051                                                   const std::string& theDest)
3052 {
3053   SALOMEDSImpl_ChildIterator anIter = NewChildIterator( theSObject );
3054   for( ; anIter.More(); anIter.Next() )
3055     ReplaceVariableAttribute( theStudyBuilder, anIter.Value(), theSource, theDest );
3056
3057   DF_Attribute* anAttr;
3058   if( theStudyBuilder->FindAttribute( theSObject, anAttr, "AttributeString" ) )
3059   {
3060     if( SALOMEDSImpl_AttributeString* aStringAttr = ( SALOMEDSImpl_AttributeString* )anAttr )
3061     {
3062       bool isChanged = false;
3063       std::string aNewString, aCurrentString = aStringAttr->Value();
3064
3065       std::vector< std::vector<std::string> > aSections = ParseVariables( aCurrentString );
3066       for( int i = 0, n = aSections.size(); i < n; i++ )
3067       {
3068         std::vector<std::string> aVector = aSections[i];
3069         for( int j = 0, m = aVector.size(); j < m; j++ )
3070         {
3071           std::string aStr = aVector[j];
3072           if( aStr.compare( theSource ) == 0 )
3073           {
3074             isChanged = true;
3075             aStr = theDest;
3076           }
3077
3078           aNewString.append( aStr );
3079           if( j != m - 1 )
3080             aNewString.append( ":" );
3081         }
3082         if( i != n - 1 )
3083           aNewString.append( "|" );
3084       }
3085
3086       if( isChanged )
3087         aStringAttr->SetValue( aNewString );
3088     }
3089   }
3090 }
3091
3092 //============================================================================
3093 /*! Function : ReplaceVariableAttribute
3094  *  Purpose  :
3095  */
3096 //============================================================================
3097 void SALOMEDSImpl_Study::ReplaceVariableAttribute(const std::string& theSource, const std::string& theDest)
3098 {
3099   SALOMEDSImpl_StudyBuilder* aStudyBuilder = NewBuilder();
3100   SALOMEDSImpl_SComponentIterator aCompIter = NewComponentIterator();
3101   for( ; aCompIter.More(); aCompIter.Next() )
3102   {
3103     SALOMEDSImpl_SObject aComp = aCompIter.Value();
3104     ReplaceVariableAttribute( aStudyBuilder, aComp, theSource, theDest );
3105   }
3106 }
3107
3108 //============================================================================
3109 /*! Function : ParseVariables
3110  *  Purpose  :
3111  */
3112 //============================================================================
3113 std::vector< std::vector< std::string > > SALOMEDSImpl_Study::ParseVariables(const std::string& theVariables) const
3114 {
3115   return SALOMEDSImpl_Tool::splitStringWithEmpty( theVariables, OPERATION_SEPARATOR, VARIABLE_SEPARATOR );
3116 }
3117
3118 //============================================================================
3119 /*! Function : EnableUseCaseAutoFilling
3120  *  Purpose  :
3121  */
3122 //============================================================================
3123 void SALOMEDSImpl_Study::EnableUseCaseAutoFilling(bool isEnabled)
3124 {
3125   _errorCode = ""; _autoFill = isEnabled;
3126   if(isEnabled) {
3127     _builder->SetOnAddSObject(_cb);
3128     _builder->SetOnRemoveSObject(_cb);
3129   }
3130   else {
3131     _builder->SetOnAddSObject(NULL);
3132     _builder->SetOnRemoveSObject(NULL);
3133   }
3134 }
3135
3136 //============================================================================
3137 /*! Function : GetIORs
3138  *  Purpose  :
3139  */
3140 //============================================================================
3141 std::vector<std::string> SALOMEDSImpl_Study::GetIORs()
3142 {
3143   std::vector<std::string> anIORs;
3144   std::map<std::string, DF_Label>::const_iterator MI;
3145   for(MI = myIORLabels.begin(); MI!=myIORLabels.end(); MI++)
3146     anIORs.push_back(MI->first);
3147
3148   return anIORs;
3149 }
3150
3151 //============================================================================
3152 /*! Function : addSO_Notification
3153  *  Purpose  : This function tells all the observers that a SO has been added
3154  */
3155 //============================================================================
3156 bool SALOMEDSImpl_Study::addSO_Notification (const SALOMEDSImpl_SObject& theSObject)
3157 {
3158   if(_notifier)
3159     return _notifier->addSO_Notification(theSObject);
3160   else
3161     return false;
3162 }
3163
3164 //============================================================================
3165 /*! Function : removeSO_Notification
3166  *  Purpose  : This function tells all the observers that a SO has been removed
3167  */
3168 //============================================================================
3169 bool SALOMEDSImpl_Study::removeSO_Notification (const SALOMEDSImpl_SObject& theSObject)
3170 {
3171   if(_notifier)
3172     return _notifier->removeSO_Notification(theSObject);
3173   else
3174     return false;
3175 }
3176
3177 //============================================================================
3178 /*! Function : modifySO_Notification
3179  *  Purpose  : This function tells all the observers that a SO has been modified and
3180                pass the mofification reason
3181  */
3182 //============================================================================
3183 bool SALOMEDSImpl_Study::modifySO_Notification (const SALOMEDSImpl_SObject& theSObject, int reason) 
3184 {
3185   if(_notifier)
3186     return _notifier->modifySO_Notification(theSObject, reason);
3187   else
3188     return false;
3189 }
3190
3191 //============================================================================
3192 /*! Function : setNotifier
3193  *  Purpose  : register a notifier
3194  */
3195 //============================================================================
3196 void SALOMEDSImpl_Study::setNotifier(SALOMEDSImpl_AbstractCallback* notifier) 
3197 {
3198   _notifier=notifier;
3199 }
3200
3201 //#######################################################################################################
3202 //#                                     STATIC PRIVATE FUNCTIONS
3203 //#######################################################################################################
3204
3205 //============================================================================
3206 /*! Function : SaveAttributes
3207  *  Purpose  : Save attributes for object
3208  */
3209 //============================================================================
3210 static void SaveAttributes(const SALOMEDSImpl_SObject& aSO, HDFgroup *hdf_group_sobject)
3211 {
3212   hdf_size size[1];
3213   std::vector<DF_Attribute*> attrList = aSO.GetLabel().GetAttributes();
3214   DF_Attribute* anAttr = NULL;
3215   for(int i = 0, len = attrList.size(); i<len; i++) {
3216     anAttr = attrList[i];
3217     //The following attributes are not supposed to be written to the file
3218     std::string type = SALOMEDSImpl_GenericAttribute::Impl_GetType(anAttr);
3219     if(type == std::string("AttributeIOR")) continue; //IOR attribute is not saved
3220     std::string aSaveStr =anAttr->Save();
3221     //cout << "Saving: " << aSO.GetID() << " type: "<< type<<"|" << endl;
3222     size[0] = (hdf_int32) strlen(aSaveStr.c_str()) + 1;
3223     HDFdataset *hdf_dataset = new HDFdataset((char*)type.c_str(), hdf_group_sobject, HDF_STRING,size, 1);
3224     hdf_dataset->CreateOnDisk();
3225     hdf_dataset->WriteOnDisk((char*)aSaveStr.c_str());
3226     hdf_dataset->CloseOnDisk();
3227     hdf_dataset=0; //will be deleted by hdf_sco_group destructor
3228   }
3229 }
3230
3231 //===========================================================================
3232 //Function : ReadAttributes
3233 //===========================================================================
3234 static void ReadAttributes(SALOMEDSImpl_Study* theStudy,
3235                            const SALOMEDSImpl_SObject& aSO,
3236                            HDFdataset* hdf_dataset)
3237 {
3238   hdf_dataset->OpenOnDisk();
3239
3240   DF_Attribute* anAttr = NULL;
3241   char* current_string = new char[hdf_dataset->GetSize()+1];
3242   hdf_dataset->ReadFromDisk(current_string);
3243   //cout << "Reading attr type = " << hdf_dataset->GetName() << "  SO = " << aSO.GetID() << endl;
3244   if (!strcmp(hdf_dataset->GetName(),"COMPONENTDATATYPE")) {
3245     anAttr = theStudy->NewBuilder()->FindOrCreateAttribute(aSO, "AttributeComment");
3246   }
3247   else if (!strcmp(hdf_dataset->GetName(),"AttributeReference") ||
3248            !strcmp(hdf_dataset->GetName(),"Reference")) { // Old format maintainance
3249     theStudy->NewBuilder()->Addreference(aSO, theStudy->CreateObjectID(current_string));
3250     delete [] (current_string);
3251     hdf_dataset->CloseOnDisk();
3252     return;
3253   }
3254   else {
3255     anAttr = theStudy->NewBuilder()->FindOrCreateAttribute(aSO, hdf_dataset->GetName());
3256   }
3257
3258   if (anAttr) {
3259     anAttr->Load(current_string);
3260   }
3261
3262   delete [] (current_string);
3263   hdf_dataset->CloseOnDisk();
3264 }
3265
3266 //============================================================================
3267 //Function : BuildlTree
3268 //============================================================================
3269 static void BuildTree (SALOMEDSImpl_Study* theStudy, HDFgroup* hdf_current_group)
3270 {
3271   hdf_current_group->OpenOnDisk();
3272   SALOMEDSImpl_SObject aSO;
3273   char* Entry = hdf_current_group->GetName();
3274   if (strcmp(Entry,"STUDY_STRUCTURE") == 0) {
3275     aSO = theStudy->CreateObjectID("0:1");
3276   }
3277   else {
3278     aSO = theStudy->CreateObjectID(Entry);
3279   }
3280
3281   char name[HDF_NAME_MAX_LEN+1];
3282   int nbsons = hdf_current_group->nInternalObjects();
3283   for (int i=0; i<nbsons; i++) {
3284     hdf_current_group->InternalObjectIndentify(i,name);
3285     if (strncmp(name, "INTERNAL_COMPLEX",16) == 0) continue;
3286     hdf_object_type type = hdf_current_group->InternalObjectType(name);
3287
3288     if (type == HDF_DATASET) {
3289       HDFdataset* new_dataset = new HDFdataset(name,hdf_current_group);
3290       ReadAttributes(theStudy,aSO,new_dataset);
3291       new_dataset = 0; // will be deleted by father destructor
3292     }
3293     else if (type == HDF_GROUP)   {
3294       HDFgroup* new_group = new HDFgroup(name,hdf_current_group);
3295       BuildTree (theStudy, new_group);
3296       new_group = 0; // will be deleted by father destructor
3297     }
3298   }
3299   hdf_current_group->CloseOnDisk();
3300 }
3301
3302
3303 //============================================================================
3304 //Function : Translate_IOR_to_persistentID
3305 //============================================================================
3306 static void Translate_IOR_to_persistentID (const SALOMEDSImpl_SObject& so,
3307                                            SALOMEDSImpl_Driver*        engine,
3308                                            bool                        isMultiFile,
3309                                            bool                        isASCII)
3310 {
3311   DF_ChildIterator itchild(so.GetLabel());
3312   std::string ior_string,  persistent_string, curid;
3313
3314   for (; itchild.More(); itchild.Next()) {
3315     SALOMEDSImpl_SObject current = SALOMEDSImpl_Study::SObject(itchild.Value());
3316     SALOMEDSImpl_AttributeIOR* IOR = NULL;
3317     if ((IOR=(SALOMEDSImpl_AttributeIOR*)current.GetLabel().FindAttribute(SALOMEDSImpl_AttributeIOR::GetID()))) {
3318       ior_string = IOR->Value();
3319
3320       persistent_string = engine->IORToLocalPersistentID (current, ior_string, isMultiFile, isASCII);
3321       SALOMEDSImpl_AttributePersistentRef::Set(current.GetLabel(), persistent_string);
3322     }
3323     Translate_IOR_to_persistentID (current, engine, isMultiFile, isASCII);
3324   }
3325 }
3326
3327 void ReadNoteBookVariables(SALOMEDSImpl_Study* theStudy, HDFgroup* theGroup)
3328 {
3329   if(!theGroup)
3330     return;
3331
3332   HDFgroup* new_group =0;
3333   HDFdataset* new_dataset =0;
3334
3335   char aVarName[HDF_NAME_MAX_LEN+1];
3336   char *currentVarType = 0;
3337   char *currentVarValue = 0;
3338   char *currentVarIndex = 0;
3339   int order = 0;
3340   //Open HDF group with notebook variables
3341   theGroup->OpenOnDisk();
3342
3343   //Get Nb of variables
3344   int aNbVars = theGroup->nInternalObjects();
3345
3346   std::map<int,SALOMEDSImpl_GenericVariable*> aVarsMap;
3347
3348   for( int iVar=0;iVar < aNbVars;iVar++ ) {
3349     theGroup->InternalObjectIndentify(iVar,aVarName);
3350     hdf_object_type type = theGroup->InternalObjectType(aVarName);
3351     if(type == HDF_GROUP) {
3352
3353       //Read Variable
3354       new_group = new HDFgroup(aVarName,theGroup);
3355       new_group->OpenOnDisk();
3356
3357       //Read Type
3358       new_dataset = new HDFdataset("VARIABLE_TYPE",new_group);
3359       new_dataset->OpenOnDisk();
3360       currentVarType = new char[new_dataset->GetSize()+1];
3361       new_dataset->ReadFromDisk(currentVarType);
3362       new_dataset->CloseOnDisk();
3363       new_dataset = 0; //will be deleted by hdf_sco_group destructor
3364
3365       //Read Order
3366       if(new_group->ExistInternalObject("VARIABLE_INDEX")) {
3367         new_dataset = new HDFdataset("VARIABLE_INDEX",new_group);
3368         new_dataset->OpenOnDisk();
3369         currentVarIndex = new char[new_dataset->GetSize()+1];
3370         new_dataset->ReadFromDisk(currentVarIndex);
3371         new_dataset->CloseOnDisk();
3372         new_dataset = 0; //will be deleted by hdf_sco_group destructor
3373         order = atoi(currentVarIndex);
3374         delete [] currentVarIndex;
3375       }
3376       else
3377         order = iVar;
3378
3379       //Read Value
3380       new_dataset = new HDFdataset("VARIABLE_VALUE",new_group);
3381       new_dataset->OpenOnDisk();
3382       currentVarValue = new char[new_dataset->GetSize()+1];
3383       new_dataset->ReadFromDisk(currentVarValue);
3384       new_dataset->CloseOnDisk();
3385       new_dataset = 0; //will be deleted by hdf_sco_group destructor
3386
3387       new_group->CloseOnDisk();
3388       new_group = 0;  //will be deleted by hdf_sco_group destructor
3389
3390       SALOMEDSImpl_GenericVariable::VariableTypes aVarType =
3391         SALOMEDSImpl_GenericVariable::String2VariableType(std::string(currentVarType));
3392       delete [] currentVarType;
3393
3394       //Create variable and add it in the study
3395       SALOMEDSImpl_GenericVariable* aVariable =
3396         new SALOMEDSImpl_ScalarVariable(aVarType,std::string(aVarName));
3397       aVariable->Load(std::string(currentVarValue));
3398       aVarsMap.insert(std::make_pair(order,aVariable));
3399       delete [] currentVarValue;
3400     }
3401   }
3402
3403   std::map<int,SALOMEDSImpl_GenericVariable*>::const_iterator it= aVarsMap.begin();
3404   for(;it!=aVarsMap.end();it++)
3405     theStudy->AddVariable((*it).second);
3406
3407   theGroup->CloseOnDisk();
3408 }
3409