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