Salome HOME
To avoid compilation pb on RedHat 8.0.
[modules/kernel.git] / src / SALOMEDSImpl / SALOMEDSImpl_StudyBuilder.cxx
1 // Copyright (C) 2005  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
3 // 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either 
7 // version 2.1 of the License.
8 // 
9 // This library is distributed in the hope that it will be useful 
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
12 // Lesser General Public License for more details.
13 //
14 // You should have received a copy of the GNU Lesser General Public  
15 // License along with this library; if not, write to the Free Software 
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17 //
18 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 //
20 //  File   : SALOMEDSImpl_StudyBuilder.cxx
21 //  Author : Sergey RUIN
22 //  Module : SALOME
23
24
25
26 #include "SALOMEDSImpl_Attributes.hxx"
27
28 using namespace std;
29
30 #include "SALOMEDSImpl_Study.hxx"
31 #include "SALOMEDSImpl_StudyBuilder.hxx"
32 #include "SALOMEDSImpl_SObject.hxx"
33 #include "SALOMEDSImpl_SComponent.hxx"
34 #include "SALOMEDSImpl_Tool.hxx"
35
36 #include <SALOMEDSImpl_ChildNodeIterator.hxx>
37
38 #include <TDF_ChildIterator.hxx>
39 #include <TDF_Label.hxx>
40 #include <TDF_Tool.hxx>
41 #include <TDF_Data.hxx>
42 #include <TDF_ListIteratorOfAttributeList.hxx>
43
44 #include <OSD_Path.hxx>
45
46 #include <HDFOI.hxx>
47 #include <stdlib.h> 
48
49 IMPLEMENT_STANDARD_HANDLE( SALOMEDSImpl_StudyBuilder, MMgt_TShared )
50 IMPLEMENT_STANDARD_RTTIEXT( SALOMEDSImpl_StudyBuilder, MMgt_TShared )
51
52 #define USE_CASE_LABEL_TAG            2
53 #define DIRECTORYID                   16661
54 #define FILELOCALID                   26662 
55
56 static void Translate_persistentID_to_IOR(TDF_Label& Lab, SALOMEDSImpl_Driver* driver, bool isMultiFile, bool isASCII);
57
58 //============================================================================
59 /*! Function : constructor
60  *  Purpose  :
61  */
62 //============================================================================
63 SALOMEDSImpl_StudyBuilder::SALOMEDSImpl_StudyBuilder(const Handle(Standard_Transient)& theOwner)
64 {
65    _errorCode = "";
66    _study = theOwner;
67    _doc = Handle(SALOMEDSImpl_Study)::DownCast(theOwner)->GetDocument();
68 }
69
70 //============================================================================
71 /*! Function : destructor
72  *  Purpose  :
73  */
74 //============================================================================
75 SALOMEDSImpl_StudyBuilder::~SALOMEDSImpl_StudyBuilder()
76 {}
77
78 //============================================================================
79 /*! Function : NewComponent
80  *  Purpose  : Create a new component (Scomponent)
81  */
82 //============================================================================
83 Handle(SALOMEDSImpl_SComponent) SALOMEDSImpl_StudyBuilder::NewComponent(const TCollection_AsciiString& DataType)
84 {
85   _errorCode = "";
86   CheckLocked();
87
88   if(DataType.Length() == 0) return 0;
89
90   //Always create component under main label.
91   TDF_Label L  = _doc->Main();
92
93   int imax = 0;
94   for (TDF_ChildIterator it(L); it.More(); it.Next()) {
95     if (it.Value().Tag() > imax)
96       imax = it.Value().Tag();
97   }
98   imax++;
99   TDF_Label NL = L.FindChild(imax);
100
101   SALOMEDSImpl_AttributeComment::Set(NL, DataType);
102
103   Handle(SALOMEDSImpl_SComponent) so =  Handle(SALOMEDSImpl_Study)::DownCast(_study)->GetSComponent (NL);
104
105   if(!_callbackOnAdd.IsNull()) _callbackOnAdd->OnAddSObject(so);
106
107   _doc->Modify();
108
109   return so;
110 }
111
112 //============================================================================
113 /*! Function : DefineComponentInstance
114  *  Purpose  : Add IOR attribute of a Scomponent
115  */
116 //============================================================================
117 bool SALOMEDSImpl_StudyBuilder::DefineComponentInstance(const Handle(SALOMEDSImpl_SComponent)& aComponent,
118                                                         const TCollection_AsciiString& IOR)
119 {
120    _errorCode = "";
121
122   CheckLocked();
123   if(aComponent.IsNull() || IOR.IsEmpty()) {
124     _errorCode = "Invalid arguments";
125     return false;
126   }
127   //add IOR definition 
128   SALOMEDSImpl_AttributeIOR::Set(aComponent->GetLabel(), IOR);  
129
130   //_doc->Modify();
131
132   return true;
133 }
134
135 //============================================================================
136 /*! Function : RemoveComponent
137  *  Purpose  : Delete a Scomponent
138  */
139 //============================================================================
140 bool SALOMEDSImpl_StudyBuilder::RemoveComponent(const Handle(SALOMEDSImpl_SComponent)& aComponent)
141 {
142    _errorCode = "";
143   CheckLocked();
144   return RemoveObject(aComponent);
145 }
146
147 //============================================================================
148 /*! Function : NewObject
149  *  Purpose  : Create a new SObject
150  */
151 //============================================================================
152 Handle(SALOMEDSImpl_SObject) SALOMEDSImpl_StudyBuilder::NewObject(const Handle(SALOMEDSImpl_SObject)& theFatherObject)
153 {
154    _errorCode = "";
155   CheckLocked();
156
157   //Find label of father
158   TDF_Label Lab = theFatherObject->GetLabel();
159   
160   //Create a new label
161   int imax = 0;
162   for (TDF_ChildIterator it(Lab); it.More(); it.Next()) {
163     if (it.Value().Tag() > imax)
164       imax = it.Value().Tag();
165   }
166   imax++;
167   TDF_Label NewLab = Lab.FindChild(imax);
168   
169   Handle(SALOMEDSImpl_SObject) so = Handle(SALOMEDSImpl_Study)::DownCast(_study)->GetSObject(NewLab);
170   if(!_callbackOnAdd.IsNull()) _callbackOnAdd->OnAddSObject(so);
171
172   _doc->Modify();  
173   return so;
174 }
175
176 //============================================================================
177 /*! Function : NewObjectToTag
178  *  Purpose  :
179  */
180 //============================================================================
181 Handle(SALOMEDSImpl_SObject) SALOMEDSImpl_StudyBuilder::NewObjectToTag(const Handle(SALOMEDSImpl_SObject)& theFatherObject,
182                                                                        const int theTag)
183 {
184   _errorCode = "";
185   CheckLocked();
186   //Find label of father
187   TDF_Label Lab = theFatherObject->GetLabel();
188
189   //Create or find label
190   TDF_Label NewLab = Lab.FindChild(theTag, 1);
191
192   Handle(SALOMEDSImpl_SObject) so = Handle(SALOMEDSImpl_Study)::DownCast(_study)->GetSObject(NewLab);
193
194   if(!_callbackOnAdd.IsNull()) _callbackOnAdd->OnAddSObject(so);
195
196   _doc->Modify();  
197   return so;
198 }
199
200 //============================================================================
201 /*! Function : RemoveObject
202  *  Purpose  :
203  */
204 //============================================================================
205 bool SALOMEDSImpl_StudyBuilder::RemoveObject(const Handle(SALOMEDSImpl_SObject)& anObject)
206 {
207    _errorCode = "";
208   CheckLocked();
209   if(anObject.IsNull()) {
210     _errorCode = "Null object";
211     return false;
212   }
213
214   if(!_callbackOnRemove.IsNull()) _callbackOnRemove->OnRemoveSObject(anObject);
215
216   TDF_Label Lab = anObject->GetLabel();
217
218   Handle(SALOMEDSImpl_AttributeReference) aReference;
219   if (Lab.FindAttribute(SALOMEDSImpl_AttributeReference::GetID(), aReference)) {
220     Handle(SALOMEDSImpl_AttributeTarget) aTarget;
221     if (aReference->Get().FindAttribute(SALOMEDSImpl_AttributeTarget::GetID(),aTarget))
222       aTarget->Remove(SALOMEDSImpl_Study::SObject(Lab));
223   }
224
225   Handle(SALOMEDSImpl_AttributeIOR) anAttr; // postponed removing of CORBA objects
226   if (Lab.FindAttribute(SALOMEDSImpl_AttributeIOR::GetID(), anAttr))
227     SALOMEDSImpl_Study::GetStudy(_doc->Main())->AddPostponed(TCollection_AsciiString(anAttr->Value()).ToCString());
228
229   Lab.ForgetAllAttributes();
230  
231   _doc->Modify();  
232     
233   return true;
234 }
235
236 //============================================================================
237 /*! Function : RemoveObjectWithChildren
238  *  Purpose  :
239  */
240 //============================================================================
241 bool SALOMEDSImpl_StudyBuilder::RemoveObjectWithChildren(const Handle(SALOMEDSImpl_SObject)& anObject)
242 {
243    _errorCode = "";
244   CheckLocked();
245   if(anObject.IsNull()) {
246     _errorCode = "Null object";
247     return false;
248   }
249
250   if(!_callbackOnRemove.IsNull()) _callbackOnRemove->OnRemoveSObject(anObject);
251
252   TDF_Label Lab = anObject->GetLabel();
253
254   Handle(SALOMEDSImpl_AttributeReference) aReference;
255   if (Lab.FindAttribute(SALOMEDSImpl_AttributeReference::GetID(), aReference)) {
256     Handle(SALOMEDSImpl_AttributeTarget) aTarget;
257     if (aReference->Get().FindAttribute(SALOMEDSImpl_AttributeTarget::GetID(),aTarget))
258       aTarget->Remove(SALOMEDSImpl_Study::SObject(Lab));
259   }
260   Handle(SALOMEDSImpl_AttributeIOR) anAttr; // postponed removing of CORBA objects
261   if (Lab.FindAttribute(SALOMEDSImpl_AttributeIOR::GetID(), anAttr))
262     SALOMEDSImpl_Study::GetStudy(_doc->Main())->AddPostponed(TCollection_AsciiString(anAttr->Value()).ToCString());
263
264   TDF_ChildIterator it(Lab, Standard_True);
265   for(;it.More();it.Next()) {
266     TDF_Label aLabel = it.Value();
267     if (aLabel.FindAttribute(SALOMEDSImpl_AttributeReference::GetID(), aReference)) {
268       Handle(SALOMEDSImpl_AttributeTarget) aTarget;
269       if (aReference->Get().FindAttribute(SALOMEDSImpl_AttributeTarget::GetID(),aTarget))
270         aTarget->Remove(SALOMEDSImpl_Study::SObject(aLabel));
271     }
272     Handle(SALOMEDSImpl_AttributeIOR) anAttr; // postponed removing of CORBA objects
273     if (aLabel.FindAttribute(SALOMEDSImpl_AttributeIOR::GetID(), anAttr))
274       SALOMEDSImpl_Study::GetStudy(_doc->Main())->AddPostponed(TCollection_AsciiString(anAttr->Value()).ToCString());
275   }
276
277   Lab.ForgetAllAttributes(Standard_True);
278
279   _doc->Modify();  
280   
281   return true;
282 }
283
284 //============================================================================
285 /*! Function : LoadWith
286  *  Purpose  : 
287  */
288 //============================================================================
289 bool SALOMEDSImpl_StudyBuilder::LoadWith(const Handle(SALOMEDSImpl_SComponent)& anSCO,
290                                          SALOMEDSImpl_Driver* aDriver) 
291 {
292   _errorCode = "";
293
294   TDF_Label Lab = anSCO->GetLabel();
295   Handle(SALOMEDSImpl_AttributePersistentRef) Att;
296
297   //Find the current Url of the study  
298   if (_doc->Main().FindAttribute(SALOMEDSImpl_AttributePersistentRef::GetID(),Att)) {
299     int aLocked = anSCO->GetStudy()->GetProperties()->IsLocked();
300     if (aLocked) anSCO->GetStudy()->GetProperties()->SetLocked(false);
301
302     TCollection_ExtendedString Res(Att->Value());
303     TCollection_AsciiString aHDFPath(Res);
304
305     Handle(SALOMEDSImpl_AttributeComment) type;
306     TCollection_ExtendedString DataType;
307     if (Lab.FindAttribute(SALOMEDSImpl_AttributeComment::GetID(),type))
308       DataType = type->Value();
309
310     // associate the driver to the SComponent
311     if(aDriver == NULL) {
312       _errorCode = "Driver is null";
313       return false;
314     }
315
316     // mpv 06.03.2003: SAL1927 - if component data if already loaded, it is not necessary to do it again
317     Handle(SALOMEDSImpl_AttributeIOR) attrIOR;
318     if (Lab.FindAttribute(SALOMEDSImpl_AttributeIOR::GetID(), attrIOR)) {
319       if (aLocked) anSCO->GetStudy()->GetProperties()->SetLocked(true);
320       return true;
321     }
322
323     DefineComponentInstance (anSCO, aDriver->GetIOR());
324
325     TCollection_AsciiString aHDFUrl;
326     bool isASCII = false;
327     if (HDFascii::isASCII(aHDFPath.ToCString())) {
328       isASCII = true;
329       aHDFUrl = HDFascii::ConvertFromASCIIToHDF(aHDFPath.ToCString());
330       aHDFUrl += "hdf_from_ascii.hdf";
331     } else {
332       aHDFUrl = aHDFPath;
333     }
334
335     //Open the Study HDF file 
336     HDFfile *hdf_file = new HDFfile(aHDFUrl.ToCString()); 
337
338     char aMultifileState[2] = "S"; // default: single
339     char ASCIIfileState[2] = "B"; // default: binary
340     try {
341       TCollection_AsciiString scoid = anSCO->GetID();
342       hdf_file->OpenOnDisk(HDF_RDONLY);
343       HDFgroup *hdf_group = new HDFgroup("DATACOMPONENT",hdf_file);
344       hdf_group->OpenOnDisk();
345       HDFgroup *hdf_sco_group = new HDFgroup(scoid.ToCString(), hdf_group);
346       hdf_sco_group->OpenOnDisk();
347
348       unsigned char* aStreamFile = NULL;
349       int aStreamSize = 0;
350
351       if (hdf_sco_group->ExistInternalObject("FILE_STREAM")) {
352         HDFdataset *hdf_dataset = new HDFdataset("FILE_STREAM", hdf_sco_group);
353         hdf_dataset->OpenOnDisk();
354         aStreamSize = hdf_dataset->GetSize();
355         aStreamFile  = new unsigned char[aStreamSize];
356         if(aStreamFile == NULL) throw HDFexception("Unable to open dataset FILE_STREAM");
357         hdf_dataset->ReadFromDisk(aStreamFile);
358         hdf_dataset->CloseOnDisk();
359         hdf_dataset = 0;
360       }
361       else
362         aStreamFile = NULL;
363
364       if (hdf_sco_group->ExistInternalObject("MULTIFILE_STATE")) {
365         HDFdataset *multifile_hdf_dataset = new HDFdataset("MULTIFILE_STATE", hdf_sco_group);
366         multifile_hdf_dataset->OpenOnDisk();
367         multifile_hdf_dataset->ReadFromDisk(aMultifileState);
368
369         multifile_hdf_dataset->CloseOnDisk();
370         multifile_hdf_dataset = 0;
371       }
372
373       if (hdf_sco_group->ExistInternalObject("ASCII_STATE")) {
374         HDFdataset *ascii_hdf_dataset = new HDFdataset("ASCII_STATE", hdf_sco_group);
375         ascii_hdf_dataset->OpenOnDisk();
376         ascii_hdf_dataset->ReadFromDisk(ASCIIfileState);
377
378         ascii_hdf_dataset->CloseOnDisk();
379         ascii_hdf_dataset = 0;
380       }
381
382       // set path without file name from URL 
383       //int aFileNameSize = Res.Length();
384       //char* aDir = new char[aFileNameSize];
385       //memcpy(aDir, TCollection_AsciiString(Res).ToCString(), aFileNameSize);
386       //for(int aCounter = aFileNameSize-1; aCounter>=0; aCounter--)
387       //if (aDir[aCounter] == '/') {
388       //  aDir[aCounter+1] = 0;
389       //  break;
390       //}
391       // Above code was working wrong for paths without '/' inside.
392       TCollection_AsciiString aDir = SALOMEDSImpl_Tool::GetDirFromPath(Res);
393
394       bool aResult = (ASCIIfileState[0]=='A')?
395         aDriver->LoadASCII(anSCO, aStreamFile, aStreamSize, aDir.ToCString(), aMultifileState[0]=='M'):
396         aDriver->Load(anSCO, aStreamFile, aStreamSize, aDir.ToCString(), aMultifileState[0]=='M');
397
398       if(aStreamFile != NULL) delete []aStreamFile; 
399
400       if(!aResult) {
401         RemoveAttribute( anSCO, "AttributeIOR" );
402
403         _errorCode = "Can't load component";
404         throw HDFexception("Unable to load component");
405       }
406
407       //if(aDir != NULL) delete []aDir;
408
409       hdf_sco_group->CloseOnDisk();
410       hdf_sco_group = 0;
411       hdf_group->CloseOnDisk();
412       hdf_group = 0;
413       hdf_file->CloseOnDisk();
414       delete hdf_file;
415
416       if (isASCII) {
417         Handle(TColStd_HSequenceOfAsciiString) aFilesToRemove = new TColStd_HSequenceOfAsciiString;
418         aFilesToRemove->Append("hdf_from_ascii.hdf");
419         SALOMEDSImpl_Tool::RemoveTemporaryFiles(SALOMEDSImpl_Tool::GetDirFromPath(aHDFUrl),
420                                                 aFilesToRemove, true);
421       }      
422     }
423     catch (HDFexception) {
424       delete hdf_file;
425
426       if (isASCII) {
427         Handle(TColStd_HSequenceOfAsciiString) aFilesToRemove = new TColStd_HSequenceOfAsciiString;
428         aFilesToRemove->Append(aHDFUrl);
429         SALOMEDSImpl_Tool::RemoveTemporaryFiles(SALOMEDSImpl_Tool::GetDirFromPath(aHDFUrl),
430                                                 aFilesToRemove, true);
431       }
432
433       if (aLocked) anSCO->GetStudy()->GetProperties()->SetLocked(true);
434       _errorCode = "No persistent file";   
435       return false;
436     }
437
438     try {
439       Translate_persistentID_to_IOR (Lab, aDriver, aMultifileState[0]=='M', ASCIIfileState[0] == 'A');
440     } catch(...) {
441       _errorCode = "Can not convert persistent IDs to IORs";
442       return false;
443     }
444
445     if (aLocked) anSCO->GetStudy()->GetProperties()->SetLocked(true);
446   } else {
447     _errorCode = "No persistent file";   
448   }
449
450   return true;
451 }
452
453
454 //============================================================================
455 /*! Function : Load
456  *  Purpose  : 
457  */
458 //============================================================================
459 bool SALOMEDSImpl_StudyBuilder::Load(const Handle(SALOMEDSImpl_SObject)& sco)
460 {
461   _errorCode = "Not implemented";
462   return false;
463 }
464
465 //============================================================================
466 /*! Function : FindOrCreateAttribute
467  *  Purpose  : Add attribute of given type to SObject, if there is attribute of such type, returns
468  *  existing one
469  */
470 //============================================================================
471 Handle(TDF_Attribute) SALOMEDSImpl_StudyBuilder::FindOrCreateAttribute(const Handle(SALOMEDSImpl_SObject)& anObject, 
472                                                                        const TCollection_AsciiString& aTypeOfAttribute)
473 {
474   _errorCode = "";
475   if(anObject.IsNull()) {
476     _errorCode = "Invalid arguments";
477     return NULL;
478   }
479
480   TDF_Label Lab = anObject->GetLabel();
481   if(Lab.IsNull()) {
482     _errorCode = "Null label";
483     return NULL;
484   }
485
486   _doc->Modify();  
487
488   //The macro adds all necessary checks for standardly behaiving attributes
489   __FindOrCreateAttributeForBuilder
490
491  
492   //Add checks for TreeNode and UserID attributes  
493   if (strncmp(aTypeOfAttribute.ToCString(), "AttributeTreeNode",17) == 0 ) {
494     
495     Standard_GUID aTreeNodeGUID;
496     if (strcmp(aTypeOfAttribute.ToCString(), "AttributeTreeNode") == 0) {
497       aTreeNodeGUID = SALOMEDSImpl_AttributeTreeNode::GetDefaultTreeID();
498     } else {
499       char* aGUIDString = new char[41];
500       char* aType = (char*)aTypeOfAttribute.ToCString();
501       sprintf(aGUIDString, &(aType[17]));
502       if(!Standard_GUID::CheckGUIDFormat(aGUIDString)) {
503         delete(aGUIDString);
504         return NULL;      
505       }
506       aTreeNodeGUID = Standard_GUID(aGUIDString); // create tree node GUID by name
507       delete(aGUIDString);
508     }
509     Handle(SALOMEDSImpl_AttributeTreeNode) anAttr;
510     if (!Lab.FindAttribute(aTreeNodeGUID, anAttr)) {
511       CheckLocked();
512       anAttr = SALOMEDSImpl_AttributeTreeNode::Set(Lab, aTreeNodeGUID);
513     }
514     return anAttr;
515   }
516
517   if (strncmp(aTypeOfAttribute.ToCString(), "AttributeUserID",15) == 0 ) {
518     Standard_GUID aUserGUID;
519     if (strcmp(aTypeOfAttribute.ToCString(), "AttributeUserID") == 0) {
520       aUserGUID = SALOMEDSImpl_AttributeUserID::DefaultID();
521     } else {
522       char* aGUIDString = new char[41];
523       char* aType = (char*)aTypeOfAttribute.ToCString();
524       sprintf(aGUIDString, &(aType[15]));
525       if(!Standard_GUID::CheckGUIDFormat(aGUIDString)) {
526         delete(aGUIDString);
527         return NULL;      
528       }
529       aUserGUID = Standard_GUID(aGUIDString); // create tree node GUID by name
530       delete(aGUIDString);
531     }
532     Handle(SALOMEDSImpl_AttributeUserID) anAttr;
533     if (!Lab.FindAttribute(SALOMEDSImpl_AttributeUserID::DefaultID(), anAttr)) {
534       CheckLocked();
535       anAttr = SALOMEDSImpl_AttributeUserID::Set(Lab, aUserGUID);
536     }
537     return anAttr;
538   }
539   _errorCode = "Can not create an attribute";
540
541   return NULL;
542 }
543
544 //============================================================================
545 /*! Function : FindAttribute
546  *  Purpose  : Find attribute of given type assigned SObject, returns Standard_True if it is found
547  */
548 //============================================================================
549
550 bool SALOMEDSImpl_StudyBuilder::FindAttribute(const Handle(SALOMEDSImpl_SObject)& anObject, 
551                                               Handle(TDF_Attribute)& anAttribute, 
552                                               const TCollection_AsciiString& aTypeOfAttribute)
553 {
554   _errorCode = "";
555   if(anObject.IsNull()) {
556     _errorCode = "Invalid arguments";
557     return false;
558   }
559   TDF_Label Lab = anObject->GetLabel();
560   if (Lab.FindAttribute(SALOMEDSImpl_SObject::GetGUID(aTypeOfAttribute), anAttribute)) {
561     // commented out because NO MODIFICATION is done to attributes when calling FindAttribute()
562     // _doc->Modify();  
563     return Standard_True;
564   }
565   return Standard_False;
566 }
567
568 //============================================================================
569 /*! Function : RemoveAttribute
570  *  Purpose  : Remove attribute of given type assigned SObject
571  */
572 //============================================================================
573
574 bool SALOMEDSImpl_StudyBuilder::RemoveAttribute(const Handle(SALOMEDSImpl_SObject)& anObject, 
575                                                 const TCollection_AsciiString& aTypeOfAttribute)
576 {
577   _errorCode = "";
578   CheckLocked();
579   if(anObject.IsNull()) {
580     _errorCode = "Invalid arguments";
581     return false;
582   }
583   TDF_Label Lab = anObject->GetLabel();
584   
585   if (aTypeOfAttribute == "AttributeIOR") { // postponed removing of CORBA objects
586     Handle(SALOMEDSImpl_AttributeIOR) anAttr;
587     if (Lab.FindAttribute(SALOMEDSImpl_AttributeIOR::GetID(), anAttr))
588       SALOMEDSImpl_Study::GetStudy(_doc->Main())->AddPostponed(anAttr->Value());
589   }
590
591   Lab.ForgetAttribute (SALOMEDSImpl_SObject::GetGUID(aTypeOfAttribute));
592     
593   _doc->Modify();  
594     
595   return true;
596 }
597
598 //============================================================================
599 /*! Function : Addreference
600  *  Purpose  : 
601  */
602 //============================================================================
603 bool SALOMEDSImpl_StudyBuilder::Addreference(const Handle(SALOMEDSImpl_SObject)& me, 
604                                              const Handle(SALOMEDSImpl_SObject)& theReferencedObject)
605 {
606   _errorCode = "";
607   if(me.IsNull() || theReferencedObject.IsNull()) {
608    _errorCode = "Invalid arguments";
609    return false;
610   }
611   CheckLocked();
612   TDF_Label Lab = me->GetLabel();
613   TDF_Label RefLab = theReferencedObject->GetLabel();
614   SALOMEDSImpl_AttributeReference::Set(Lab,RefLab);
615
616   SALOMEDSImpl_AttributeTarget::Set(RefLab)->Add(SALOMEDSImpl_Study::SObject(Lab));
617
618   if(!_callbackOnRemove.IsNull() && Lab.IsDescendant(_doc->Main())) _callbackOnRemove->OnRemoveSObject(me);
619   
620   return true;
621 }
622
623 //============================================================================
624 /*! Function : RemoveReference
625  *  Purpose  : 
626  */
627 //============================================================================
628 bool SALOMEDSImpl_StudyBuilder::RemoveReference(const Handle(SALOMEDSImpl_SObject)& me)
629 {
630   _errorCode = "";
631   Handle(SALOMEDSImpl_SObject) theReferencedObject;
632   if(!me->ReferencedObject(theReferencedObject)) return false;  //No reference is found
633
634   CheckLocked();
635   TDF_Label Lab = me->GetLabel();
636
637   Lab.ForgetAttribute(SALOMEDSImpl_AttributeReference::GetID());  
638
639   //SRN: 30 Aug, 2004 : fix from Ecole l'ete version 
640
641   TDF_Label RefLab = theReferencedObject->GetLabel();
642        
643   Handle(SALOMEDSImpl_AttributeTarget) aTarget;
644   if(RefLab.FindAttribute(SALOMEDSImpl_AttributeTarget::GetID(), aTarget)) 
645     aTarget->Remove(SALOMEDSImpl_Study::SObject(Lab));
646   
647   _doc->Modify();  
648   
649   return true;
650 }
651
652
653
654 //============================================================================
655 /*! Function : AddDirectory
656  *  Purpose  : adds a new directory with a path = thePath
657  */
658 //============================================================================
659 bool SALOMEDSImpl_StudyBuilder::AddDirectory(const TCollection_AsciiString& thePath) 
660 {
661   _errorCode = "";
662   CheckLocked();
663   if(thePath.IsEmpty() || thePath == "") {
664     _errorCode = "Invalid path";
665     return false;
666   }
667
668   TCollection_AsciiString aPath(thePath), aContext(""), aFatherPath;
669   TDF_Label aLabel;
670   Handle(SALOMEDSImpl_Study) aStudy = SALOMEDSImpl_Study::GetStudy(_doc->Main());
671   Handle(SALOMEDSImpl_SObject) anObject;
672
673   try { 
674     anObject = aStudy->FindObjectByPath(thePath); //Check if the directory already exists
675   }
676   catch(...) { }
677
678   if(!anObject.IsNull()) {
679     _errorCode = "StudyNameAlreadyUsed";
680     return false; 
681   }
682
683   if(aPath.Value(1) != '/') { //Relative path 
684     aPath.Prepend('/');
685     aPath = aStudy->GetContext() + aPath;
686   }
687
688   TCollection_AsciiString aToken = aPath.Token("/", 1);
689   if(aToken.Length() == 0) aFatherPath = "/";
690
691   int i = 1;  
692   while(aToken.Length() != 0) {
693     if(aPath.Token("/", i+1).Length() > 0) {
694       aFatherPath += "/";
695       aFatherPath += aToken;
696     }
697     aToken = aPath.Token("/", ++i);
698   }
699
700   anObject.Nullify();
701   try { 
702     anObject = aStudy->FindObjectByPath(aFatherPath); //Check if the father directory exists
703   }
704   catch(...) { ; }
705   if(anObject.IsNull()) {
706     _errorCode = "StudyInvalidDirectory";
707     return false; 
708   }
709
710   Handle(SALOMEDSImpl_SObject) aNewObject = NewObject(anObject);
711   aLabel = aNewObject->GetLabel();
712   if(aLabel.IsNull()) {
713     _errorCode = "StudyInvalidComponent";
714     return false;
715   }
716
717   SALOMEDSImpl_AttributeName::Set(aLabel, aPath.Token("/", i-1));
718
719   //Set LocalID attribute to identify the directory object
720   Handle(SALOMEDSImpl_AttributeLocalID) aLocalID = SALOMEDSImpl_AttributeLocalID::Set(aLabel, DIRECTORYID);
721   
722   _doc->Modify(); 
723   
724   return true;
725 }
726
727
728 //============================================================================
729 /*! Function : SetGUID
730  *  Purpose  : 
731  */
732 //============================================================================
733 bool SALOMEDSImpl_StudyBuilder::SetGUID(const Handle(SALOMEDSImpl_SObject)& anObject, 
734                                         const TCollection_AsciiString& theGUID)
735 {
736   _errorCode = "";
737   CheckLocked();
738   if(anObject.IsNull()) {
739     _errorCode = "Invalid arguments";
740     return false;
741   }
742
743   TDF_Label aLabel = anObject->GetLabel();
744   SALOMEDSImpl_AttributeUserID::Set(aLabel, theGUID.ToCString());
745
746   _doc->Modify();  
747
748   return true;
749 }
750
751 //============================================================================
752 /*! Function : IsGUID
753  *  Purpose  : 
754  */
755 //============================================================================
756 bool SALOMEDSImpl_StudyBuilder::IsGUID(const Handle(SALOMEDSImpl_SObject)& anObject, 
757                                        const TCollection_AsciiString& theGUID)
758 {
759   _errorCode = "";
760   if(anObject.IsNull()) {
761     _errorCode = "Invalid arguments";
762     return false;
763   }
764   TDF_Label aLabel = anObject->GetLabel();
765   return aLabel.IsAttribute(theGUID.ToCString());
766 }
767
768
769 //============================================================================
770 /*! Function : NewCommand
771  *  Purpose  : 
772  */
773 //============================================================================
774 void SALOMEDSImpl_StudyBuilder::NewCommand()
775 {
776   _errorCode = "";
777   // mpv: for SAL2114 - unset "lock changed" flag at the operation start
778   Handle(SALOMEDSImpl_AttributeStudyProperties) anAttr;
779   if (!_doc->Main().FindAttribute(SALOMEDSImpl_AttributeStudyProperties::GetID(), anAttr)) {
780     anAttr = new SALOMEDSImpl_AttributeStudyProperties;
781     _doc->Main().AddAttribute(anAttr);
782   }
783   anAttr->IsLockChanged(true);
784   
785   _doc->NewCommand();
786 }
787
788 //============================================================================
789 /*! Function : CommitCommand
790  *  Purpose  : 
791  */
792 //============================================================================
793 void SALOMEDSImpl_StudyBuilder::CommitCommand()
794 {
795   _errorCode = "";
796   Handle(SALOMEDSImpl_AttributeStudyProperties) anAttr;
797   if (!_doc->Main().FindAttribute(SALOMEDSImpl_AttributeStudyProperties::GetID(), anAttr)) {
798     anAttr = new SALOMEDSImpl_AttributeStudyProperties;
799     _doc->Main().AddAttribute(anAttr);
800   }
801   if (anAttr->IsLocked() && !anAttr->IsLockChanged(true)) {
802     AbortCommand();
803     _errorCode = "LockProtection";
804     throw LockProtection("LockProtection");
805   } else {
806     SALOMEDSImpl_Study::GetStudy(_doc->Main())->RemovePostponed(_doc->GetUndoLimit());
807
808     int aModif = anAttr->GetModified();
809     if (aModif < 0) aModif = 1000; // if user make undo and then - new transaction "modify" will never be zero
810     anAttr->SetModified(aModif+1);
811     _doc->CommitCommand();
812   }
813   
814   _doc->Modify();  
815 }
816
817 //============================================================================
818 /*! Function : HasOpenCommand
819  *  Purpose  : 
820  */
821 //============================================================================
822 bool SALOMEDSImpl_StudyBuilder::HasOpenCommand()
823 {
824   _errorCode = "";
825   return _doc->HasOpenCommand();
826 }
827
828 //============================================================================
829 /*! Function : AbortCommand
830  *  Purpose  : 
831  */
832 //============================================================================
833 void SALOMEDSImpl_StudyBuilder::AbortCommand()
834 {
835   _errorCode = "";
836   SALOMEDSImpl_Study::GetStudy(_doc->Main())->UndoPostponed(0);
837   
838   _doc->AbortCommand();
839 }
840
841 //============================================================================
842 /*! Function : Undo
843  *  Purpose  : 
844  */
845 //============================================================================
846 void SALOMEDSImpl_StudyBuilder::Undo()
847 {
848   _errorCode = "";
849   Handle(SALOMEDSImpl_AttributeStudyProperties) anAttr;
850   if (!_doc->Main().FindAttribute(SALOMEDSImpl_AttributeStudyProperties::GetID(), anAttr)) {
851     anAttr = new SALOMEDSImpl_AttributeStudyProperties;
852     _doc->Main().AddAttribute(anAttr);
853     }
854   if (anAttr->IsLocked()) {
855     _errorCode = "LockProtection";
856     throw LockProtection("LockProtection");
857   } else {
858     SALOMEDSImpl_Study::GetStudy(_doc->Main())->UndoPostponed(1);
859     _doc->Undo();
860     anAttr->SetModified(anAttr->GetModified()-1);
861   }
862
863   _doc->Modify();  
864 }
865
866 //============================================================================
867 /*! Function : Redo
868  *  Purpose  : 
869  */
870 //============================================================================
871 void SALOMEDSImpl_StudyBuilder::Redo() 
872 {
873   _errorCode = "";
874   Handle(SALOMEDSImpl_AttributeStudyProperties) anAttr;
875   if (!_doc->Main().FindAttribute(SALOMEDSImpl_AttributeStudyProperties::GetID(), anAttr)) {
876     anAttr = new SALOMEDSImpl_AttributeStudyProperties;
877     _doc->Main().AddAttribute(anAttr);
878   }
879   
880   if (anAttr->IsLocked()) {
881     _errorCode = "LockProtection";
882     throw LockProtection("LockProtection");
883   } else {
884     _doc->Redo();
885     SALOMEDSImpl_Study::GetStudy(_doc->Main())->UndoPostponed(-1);
886     anAttr->SetModified(anAttr->GetModified()+1);
887   }
888    
889   _doc->Modify();  
890 }
891
892 //============================================================================
893 /*! Function : GetAvailableUndos
894  *  Purpose  : 
895  */
896 //============================================================================
897 bool SALOMEDSImpl_StudyBuilder::GetAvailableUndos()
898 {
899   _errorCode = "";
900   return _doc->GetAvailableUndos();
901 }
902
903 //============================================================================
904 /*! Function : GetAvailableRedos
905  *  Purpose  : 
906  */
907 //============================================================================
908 bool  SALOMEDSImpl_StudyBuilder::GetAvailableRedos()
909 {
910   _errorCode = "";
911   return _doc->GetAvailableRedos();
912 }
913
914 //============================================================================
915 /*! Function : UndoLimit
916  *  Purpose  : 
917  */
918 //============================================================================
919 int  SALOMEDSImpl_StudyBuilder::UndoLimit()
920 {
921   _errorCode = "";
922   return _doc->GetUndoLimit();
923 }
924
925 //============================================================================
926 /*! Function : UndoLimit
927  *  Purpose  : 
928  */
929 //============================================================================
930 void SALOMEDSImpl_StudyBuilder::UndoLimit(int n)
931 {
932   _errorCode = "";
933   CheckLocked();
934   _doc->SetUndoLimit (n);
935 }
936
937 //============================================================================
938 /*! Function : SetOnAddSObject
939  *  Purpose  : 
940  */
941 //============================================================================
942 Handle(SALOMEDSImpl_Callback) 
943 SALOMEDSImpl_StudyBuilder::SetOnAddSObject(const Handle(SALOMEDSImpl_Callback)& theCallback)
944 {
945   _errorCode = "";
946   Handle(SALOMEDSImpl_Callback) aRet = _callbackOnAdd;
947   _callbackOnAdd = theCallback;
948   return aRet;
949 }
950
951 //============================================================================
952 /*! Function : SetOnNewSObject
953  *  Purpose  : 
954  */
955 //============================================================================
956 Handle(SALOMEDSImpl_Callback) 
957 SALOMEDSImpl_StudyBuilder::SetOnRemoveSObject(const Handle(SALOMEDSImpl_Callback)& theCallback)
958 {
959   _errorCode = "";
960   Handle(SALOMEDSImpl_Callback) aRet = _callbackOnRemove;
961   _callbackOnRemove = theCallback;
962   return aRet;
963 }
964
965 //============================================================================
966 /*! Function : CheckLocked
967  *  Purpose  : 
968  */
969 //============================================================================
970 void SALOMEDSImpl_StudyBuilder::CheckLocked()
971 {
972   _errorCode = "";
973   if (_doc->HasOpenCommand()) return;
974   Handle(SALOMEDSImpl_AttributeStudyProperties) anAttr;
975   if (!_doc->Main().FindAttribute(SALOMEDSImpl_AttributeStudyProperties::GetID(), anAttr)) {
976     anAttr = new SALOMEDSImpl_AttributeStudyProperties;
977     _doc->Main().AddAttribute(anAttr);
978     }
979   if (anAttr->IsLocked()) {
980     _errorCode = "LockProtection";
981     throw LockProtection("LockProtection");
982   }
983 }
984
985 //============================================================================
986 /*! Function : SetName
987  *  Purpose  : 
988  */
989 //============================================================================
990 bool SALOMEDSImpl_StudyBuilder::SetName(const Handle(SALOMEDSImpl_SObject)& theSO, 
991                                         const TCollection_AsciiString& theValue)
992 {
993   _errorCode = "";
994   CheckLocked();
995   if(theSO.IsNull()) {
996     _errorCode = "Invalid arguments";
997     return false;
998   }
999   SALOMEDSImpl_AttributeName::Set(theSO->GetLabel(), theValue);
1000
1001   _doc->Modify();  
1002
1003   return true;
1004 }
1005
1006 //============================================================================
1007 /*! Function : SetComment
1008  *  Purpose  : 
1009  */
1010 //============================================================================
1011 bool SALOMEDSImpl_StudyBuilder::SetComment(const Handle(SALOMEDSImpl_SObject)& theSO, 
1012                                            const TCollection_AsciiString& theValue)
1013 {
1014   _errorCode = "";
1015   CheckLocked();
1016   if(theSO.IsNull()) {
1017     _errorCode = "Invalid arguments";
1018     return false;
1019   }
1020   SALOMEDSImpl_AttributeComment::Set(theSO->GetLabel(), theValue);
1021
1022   _doc->Modify();  
1023
1024   return true;
1025 }
1026
1027 //============================================================================
1028 /*! Function : SetIOR
1029  *  Purpose  : 
1030  */
1031 //============================================================================
1032 bool SALOMEDSImpl_StudyBuilder::SetIOR(const Handle(SALOMEDSImpl_SObject)& theSO, 
1033                                        const TCollection_AsciiString& theValue)
1034 {
1035   _errorCode = "";
1036   CheckLocked();
1037   if(theSO.IsNull()) {
1038     _errorCode = "Invalid arguments";
1039     return false;
1040   }
1041   SALOMEDSImpl_AttributeIOR::Set(theSO->GetLabel(), theValue);
1042
1043   _doc->Modify();  
1044
1045   return true;
1046 }
1047
1048
1049 //============================================================================
1050 /*! Function : Translate_persistentID_to_IOR
1051  *  Purpose  :
1052  */
1053 //============================================================================
1054 static void Translate_persistentID_to_IOR(TDF_Label& Lab, SALOMEDSImpl_Driver* driver, bool isMultiFile, bool isASCII)
1055 {
1056   if(driver == NULL) return;
1057   TDF_ChildIterator  itchild (Lab);
1058   
1059   for (; itchild.More(); itchild.Next()) {
1060     TDF_Label current = itchild.Value();
1061     Handle(SALOMEDSImpl_AttributePersistentRef) Att;
1062     if (current.FindAttribute(SALOMEDSImpl_AttributePersistentRef::GetID(),Att)) {  
1063
1064       Handle(SALOMEDSImpl_AttributeLocalID) anID;
1065       if (current.FindAttribute(SALOMEDSImpl_AttributeLocalID::GetID(), anID)) 
1066         if (anID->Value() == FILELOCALID) continue;        //SRN: This attribute store a file name, skip it 
1067
1068       TCollection_AsciiString persist_ref(Att->Value());
1069       Handle(SALOMEDSImpl_SObject) so = SALOMEDSImpl_Study::SObject(current);
1070       TCollection_AsciiString ior_string = driver->LocalPersistentIDToIOR(so, 
1071                                                                           persist_ref, 
1072                                                                           isMultiFile, 
1073                                                                           isASCII);
1074       SALOMEDSImpl_AttributeIOR::Set (current, ior_string); 
1075      
1076     }
1077     Translate_persistentID_to_IOR (current, driver, isMultiFile, isASCII);
1078   }
1079 }
1080