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