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