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