Salome HOME
Merging from V3_2_6pre4
[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];
339     char ASCIIfileState[2];
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       } else
361         aStreamFile = NULL;
362
363       HDFdataset *multifile_hdf_dataset = new HDFdataset("MULTIFILE_STATE", hdf_sco_group);
364       multifile_hdf_dataset->OpenOnDisk();
365       multifile_hdf_dataset->ReadFromDisk(aMultifileState);
366
367       HDFdataset *ascii_hdf_dataset = new HDFdataset("ASCII_STATE", hdf_sco_group);
368       ascii_hdf_dataset->OpenOnDisk();
369       ascii_hdf_dataset->ReadFromDisk(ASCIIfileState);
370
371       // set path without file name from URL 
372       //int aFileNameSize = Res.Length();
373       //char* aDir = new char[aFileNameSize];
374       //memcpy(aDir, TCollection_AsciiString(Res).ToCString(), aFileNameSize);
375       //for(int aCounter = aFileNameSize-1; aCounter>=0; aCounter--)
376       //if (aDir[aCounter] == '/') {
377       //  aDir[aCounter+1] = 0;
378       //  break;
379       //}
380       // Above code was working wrong for paths without '/' inside.
381       TCollection_AsciiString aDir = SALOMEDSImpl_Tool::GetDirFromPath(Res);
382
383       bool aResult = (ASCIIfileState[0]=='A')?
384         aDriver->LoadASCII(anSCO, aStreamFile, aStreamSize, aDir.ToCString(), aMultifileState[0]=='M'):
385         aDriver->Load(anSCO, aStreamFile, aStreamSize, aDir.ToCString(), aMultifileState[0]=='M');
386
387       if(aStreamFile != NULL) delete []aStreamFile; 
388
389       if(!aResult) {
390         RemoveAttribute( anSCO, "AttributeIOR" );
391
392         _errorCode = "Can't load component";
393         throw HDFexception("Unable to load component");
394       }
395
396       //if(aDir != NULL) delete []aDir;
397
398       multifile_hdf_dataset->CloseOnDisk();
399       multifile_hdf_dataset = 0;
400       ascii_hdf_dataset->CloseOnDisk();
401       ascii_hdf_dataset = 0;
402
403       hdf_sco_group->CloseOnDisk();
404       hdf_sco_group = 0;
405       hdf_group->CloseOnDisk();
406       hdf_group = 0;
407       hdf_file->CloseOnDisk();
408       delete hdf_file;
409
410       if (isASCII) {
411         Handle(TColStd_HSequenceOfAsciiString) aFilesToRemove = new TColStd_HSequenceOfAsciiString;
412         aFilesToRemove->Append("hdf_from_ascii.hdf");
413         SALOMEDSImpl_Tool::RemoveTemporaryFiles(SALOMEDSImpl_Tool::GetDirFromPath(aHDFUrl),
414                                                 aFilesToRemove, true);
415       }      
416     }
417     catch (HDFexception) {
418       delete hdf_file;
419
420       if (isASCII) {
421         Handle(TColStd_HSequenceOfAsciiString) aFilesToRemove = new TColStd_HSequenceOfAsciiString;
422         aFilesToRemove->Append(aHDFUrl);
423         SALOMEDSImpl_Tool::RemoveTemporaryFiles(SALOMEDSImpl_Tool::GetDirFromPath(aHDFUrl), aFilesToRemove, true);
424       }
425
426       if (aLocked) anSCO->GetStudy()->GetProperties()->SetLocked(true);
427       _errorCode = "No persistent file";   
428       return false;
429     }
430
431     try {
432       Translate_persistentID_to_IOR (Lab, aDriver, aMultifileState[0]=='M', ASCIIfileState[0] == 'A');
433     } catch(...) {
434       _errorCode = "Can not convert persistent IDs to IORs";
435       return false;
436     }
437
438     if (aLocked) anSCO->GetStudy()->GetProperties()->SetLocked(true);
439   } else {
440     _errorCode = "No persistent file";   
441   }
442
443   return true;
444 }
445
446
447 //============================================================================
448 /*! Function : Load
449  *  Purpose  : 
450  */
451 //============================================================================
452 bool SALOMEDSImpl_StudyBuilder::Load(const Handle(SALOMEDSImpl_SObject)& sco)
453 {
454   _errorCode = "Not implemented";
455   return false;
456 }
457
458 //============================================================================
459 /*! Function : FindOrCreateAttribute
460  *  Purpose  : Add attribute of given type to SObject, if there is attribute of such type, returns
461  *  existing one
462  */
463 //============================================================================
464 Handle(TDF_Attribute) SALOMEDSImpl_StudyBuilder::FindOrCreateAttribute(const Handle(SALOMEDSImpl_SObject)& anObject, 
465                                                                        const TCollection_AsciiString& aTypeOfAttribute)
466 {
467   _errorCode = "";
468   if(anObject.IsNull()) {
469     _errorCode = "Invalid arguments";
470     return NULL;
471   }
472
473   TDF_Label Lab = anObject->GetLabel();
474   if(Lab.IsNull()) {
475     _errorCode = "Null label";
476     return NULL;
477   }
478
479   _doc->Modify();  
480
481   //The macro adds all necessary checks for standardly behaiving attributes
482   __FindOrCreateAttributeForBuilder
483
484  
485   //Add checks for TreeNode and UserID attributes  
486   if (strncmp(aTypeOfAttribute.ToCString(), "AttributeTreeNode",17) == 0 ) {
487     
488     Standard_GUID aTreeNodeGUID;
489     if (strcmp(aTypeOfAttribute.ToCString(), "AttributeTreeNode") == 0) {
490       aTreeNodeGUID = SALOMEDSImpl_AttributeTreeNode::GetDefaultTreeID();
491     } else {
492       char* aGUIDString = new char[41];
493       char* aType = (char*)aTypeOfAttribute.ToCString();
494       sprintf(aGUIDString, &(aType[17]));
495       if(!Standard_GUID::CheckGUIDFormat(aGUIDString)) {
496         delete(aGUIDString);
497         return NULL;      
498       }
499       aTreeNodeGUID = Standard_GUID(aGUIDString); // create tree node GUID by name
500       delete(aGUIDString);
501     }
502     Handle(SALOMEDSImpl_AttributeTreeNode) anAttr;
503     if (!Lab.FindAttribute(aTreeNodeGUID, anAttr)) {
504       CheckLocked();
505       anAttr = SALOMEDSImpl_AttributeTreeNode::Set(Lab, aTreeNodeGUID);
506     }
507     return anAttr;
508   }
509
510   if (strncmp(aTypeOfAttribute.ToCString(), "AttributeUserID",15) == 0 ) {
511     Standard_GUID aUserGUID;
512     if (strcmp(aTypeOfAttribute.ToCString(), "AttributeUserID") == 0) {
513       aUserGUID = SALOMEDSImpl_AttributeUserID::DefaultID();
514     } else {
515       char* aGUIDString = new char[41];
516       char* aType = (char*)aTypeOfAttribute.ToCString();
517       sprintf(aGUIDString, &(aType[15]));
518       if(!Standard_GUID::CheckGUIDFormat(aGUIDString)) {
519         delete(aGUIDString);
520         return NULL;      
521       }
522       aUserGUID = Standard_GUID(aGUIDString); // create tree node GUID by name
523       delete(aGUIDString);
524     }
525     Handle(SALOMEDSImpl_AttributeUserID) anAttr;
526     if (!Lab.FindAttribute(SALOMEDSImpl_AttributeUserID::DefaultID(), anAttr)) {
527       CheckLocked();
528       anAttr = SALOMEDSImpl_AttributeUserID::Set(Lab, aUserGUID);
529     }
530     return anAttr;
531   }
532   _errorCode = "Can not create an attribute";
533
534   return NULL;
535 }
536
537 //============================================================================
538 /*! Function : FindAttribute
539  *  Purpose  : Find attribute of given type assigned SObject, returns Standard_True if it is found
540  */
541 //============================================================================
542
543 bool SALOMEDSImpl_StudyBuilder::FindAttribute(const Handle(SALOMEDSImpl_SObject)& anObject, 
544                                               Handle(TDF_Attribute)& anAttribute, 
545                                               const TCollection_AsciiString& aTypeOfAttribute)
546 {
547   _errorCode = "";
548   if(anObject.IsNull()) {
549     _errorCode = "Invalid arguments";
550     return false;
551   }
552   TDF_Label Lab = anObject->GetLabel();
553   if (Lab.FindAttribute(SALOMEDSImpl_SObject::GetGUID(aTypeOfAttribute), anAttribute)) {
554     // commented out because NO MODIFICATION is done to attributes when calling FindAttribute()
555     // _doc->Modify();  
556     return Standard_True;
557   }
558   return Standard_False;
559 }
560
561 //============================================================================
562 /*! Function : RemoveAttribute
563  *  Purpose  : Remove attribute of given type assigned SObject
564  */
565 //============================================================================
566
567 bool SALOMEDSImpl_StudyBuilder::RemoveAttribute(const Handle(SALOMEDSImpl_SObject)& anObject, 
568                                                 const TCollection_AsciiString& aTypeOfAttribute)
569 {
570   _errorCode = "";
571   CheckLocked();
572   if(anObject.IsNull()) {
573     _errorCode = "Invalid arguments";
574     return false;
575   }
576   TDF_Label Lab = anObject->GetLabel();
577   
578   if (aTypeOfAttribute == "AttributeIOR") { // postponed removing of CORBA objects
579     Handle(SALOMEDSImpl_AttributeIOR) anAttr;
580     if (Lab.FindAttribute(SALOMEDSImpl_AttributeIOR::GetID(), anAttr))
581       SALOMEDSImpl_Study::GetStudy(_doc->Main())->AddPostponed(anAttr->Value());
582   }
583
584   Lab.ForgetAttribute (SALOMEDSImpl_SObject::GetGUID(aTypeOfAttribute));
585     
586   _doc->Modify();  
587     
588   return true;
589 }
590
591 //============================================================================
592 /*! Function : Addreference
593  *  Purpose  : 
594  */
595 //============================================================================
596 bool SALOMEDSImpl_StudyBuilder::Addreference(const Handle(SALOMEDSImpl_SObject)& me, 
597                                              const Handle(SALOMEDSImpl_SObject)& theReferencedObject)
598 {
599   _errorCode = "";
600   if(me.IsNull() || theReferencedObject.IsNull()) {
601    _errorCode = "Invalid arguments";
602    return false;
603   }
604   CheckLocked();
605   TDF_Label Lab = me->GetLabel();
606   TDF_Label RefLab = theReferencedObject->GetLabel();
607   SALOMEDSImpl_AttributeReference::Set(Lab,RefLab);
608
609   SALOMEDSImpl_AttributeTarget::Set(RefLab)->Add(SALOMEDSImpl_Study::SObject(Lab));
610
611   if(!_callbackOnRemove.IsNull() && Lab.IsDescendant(_doc->Main())) _callbackOnRemove->OnRemoveSObject(me);
612   
613   return true;
614 }
615
616 //============================================================================
617 /*! Function : RemoveReference
618  *  Purpose  : 
619  */
620 //============================================================================
621 bool SALOMEDSImpl_StudyBuilder::RemoveReference(const Handle(SALOMEDSImpl_SObject)& me)
622 {
623   _errorCode = "";
624   Handle(SALOMEDSImpl_SObject) theReferencedObject;
625   if(!me->ReferencedObject(theReferencedObject)) return false;  //No reference is found
626
627   CheckLocked();
628   TDF_Label Lab = me->GetLabel();
629
630   Lab.ForgetAttribute(SALOMEDSImpl_AttributeReference::GetID());  
631
632   //SRN: 30 Aug, 2004 : fix from Ecole l'ete version 
633
634   TDF_Label RefLab = theReferencedObject->GetLabel();
635        
636   Handle(SALOMEDSImpl_AttributeTarget) aTarget;
637   if(RefLab.FindAttribute(SALOMEDSImpl_AttributeTarget::GetID(), aTarget)) 
638     aTarget->Remove(SALOMEDSImpl_Study::SObject(Lab));
639   
640   _doc->Modify();  
641   
642   return true;
643 }
644
645
646
647 //============================================================================
648 /*! Function : AddDirectory
649  *  Purpose  : adds a new directory with a path = thePath
650  */
651 //============================================================================
652 bool SALOMEDSImpl_StudyBuilder::AddDirectory(const TCollection_AsciiString& thePath) 
653 {
654   _errorCode = "";
655   CheckLocked();
656   if(thePath.IsEmpty() || thePath == "") {
657     _errorCode = "Invalid path";
658     return false;
659   }
660
661   TCollection_AsciiString aPath(thePath), aContext(""), aFatherPath;
662   TDF_Label aLabel;
663   Handle(SALOMEDSImpl_Study) aStudy = SALOMEDSImpl_Study::GetStudy(_doc->Main());
664   Handle(SALOMEDSImpl_SObject) anObject;
665
666   try { 
667     anObject = aStudy->FindObjectByPath(thePath); //Check if the directory already exists
668   }
669   catch(...) { }
670
671   if(!anObject.IsNull()) {
672     _errorCode = "StudyNameAlreadyUsed";
673     return false; 
674   }
675
676   if(aPath.Value(1) != '/') { //Relative path 
677     aPath.Prepend('/');
678     aPath = aStudy->GetContext() + aPath;
679   }
680
681   TCollection_AsciiString aToken = aPath.Token("/", 1);
682   if(aToken.Length() == 0) aFatherPath = "/";
683
684   int i = 1;  
685   while(aToken.Length() != 0) {
686     if(aPath.Token("/", i+1).Length() > 0) {
687       aFatherPath += "/";
688       aFatherPath += aToken;
689     }
690     aToken = aPath.Token("/", ++i);
691   }
692
693   anObject.Nullify();
694   try { 
695     anObject = aStudy->FindObjectByPath(aFatherPath); //Check if the father directory exists
696   }
697   catch(...) { ; }
698   if(anObject.IsNull()) {
699     _errorCode = "StudyInvalidDirectory";
700     return false; 
701   }
702
703   Handle(SALOMEDSImpl_SObject) aNewObject = NewObject(anObject);
704   aLabel = aNewObject->GetLabel();
705   if(aLabel.IsNull()) {
706     _errorCode = "StudyInvalidComponent";
707     return false;
708   }
709
710   SALOMEDSImpl_AttributeName::Set(aLabel, aPath.Token("/", i-1));
711
712   //Set LocalID attribute to identify the directory object
713   Handle(SALOMEDSImpl_AttributeLocalID) aLocalID = SALOMEDSImpl_AttributeLocalID::Set(aLabel, DIRECTORYID);
714   
715   _doc->Modify(); 
716   
717   return true;
718 }
719
720
721 //============================================================================
722 /*! Function : SetGUID
723  *  Purpose  : 
724  */
725 //============================================================================
726 bool SALOMEDSImpl_StudyBuilder::SetGUID(const Handle(SALOMEDSImpl_SObject)& anObject, 
727                                         const TCollection_AsciiString& theGUID)
728 {
729   _errorCode = "";
730   CheckLocked();
731   if(anObject.IsNull()) {
732     _errorCode = "Invalid arguments";
733     return false;
734   }
735
736   TDF_Label aLabel = anObject->GetLabel();
737   SALOMEDSImpl_AttributeUserID::Set(aLabel, theGUID.ToCString());
738
739   _doc->Modify();  
740
741   return true;
742 }
743
744 //============================================================================
745 /*! Function : IsGUID
746  *  Purpose  : 
747  */
748 //============================================================================
749 bool SALOMEDSImpl_StudyBuilder::IsGUID(const Handle(SALOMEDSImpl_SObject)& anObject, 
750                                        const TCollection_AsciiString& theGUID)
751 {
752   _errorCode = "";
753   if(anObject.IsNull()) {
754     _errorCode = "Invalid arguments";
755     return false;
756   }
757   TDF_Label aLabel = anObject->GetLabel();
758   return aLabel.IsAttribute(theGUID.ToCString());
759 }
760
761
762 //============================================================================
763 /*! Function : NewCommand
764  *  Purpose  : 
765  */
766 //============================================================================
767 void SALOMEDSImpl_StudyBuilder::NewCommand()
768 {
769   _errorCode = "";
770   // mpv: for SAL2114 - unset "lock changed" flag at the operation start
771   Handle(SALOMEDSImpl_AttributeStudyProperties) anAttr;
772   if (!_doc->Main().FindAttribute(SALOMEDSImpl_AttributeStudyProperties::GetID(), anAttr)) {
773     anAttr = new SALOMEDSImpl_AttributeStudyProperties;
774     _doc->Main().AddAttribute(anAttr);
775   }
776   anAttr->IsLockChanged(true);
777   
778   _doc->NewCommand();
779 }
780
781 //============================================================================
782 /*! Function : CommitCommand
783  *  Purpose  : 
784  */
785 //============================================================================
786 void SALOMEDSImpl_StudyBuilder::CommitCommand()
787 {
788   _errorCode = "";
789   Handle(SALOMEDSImpl_AttributeStudyProperties) anAttr;
790   if (!_doc->Main().FindAttribute(SALOMEDSImpl_AttributeStudyProperties::GetID(), anAttr)) {
791     anAttr = new SALOMEDSImpl_AttributeStudyProperties;
792     _doc->Main().AddAttribute(anAttr);
793   }
794   if (anAttr->IsLocked() && !anAttr->IsLockChanged(true)) {
795     AbortCommand();
796     _errorCode = "LockProtection";
797     throw LockProtection("LockProtection");
798   } else {
799     SALOMEDSImpl_Study::GetStudy(_doc->Main())->RemovePostponed(_doc->GetUndoLimit());
800
801     int aModif = anAttr->GetModified();
802     if (aModif < 0) aModif = 1000; // if user make undo and then - new transaction "modify" will never be zero
803     anAttr->SetModified(aModif+1);
804     _doc->CommitCommand();
805   }
806   
807   _doc->Modify();  
808 }
809
810 //============================================================================
811 /*! Function : HasOpenCommand
812  *  Purpose  : 
813  */
814 //============================================================================
815 bool SALOMEDSImpl_StudyBuilder::HasOpenCommand()
816 {
817   _errorCode = "";
818   return _doc->HasOpenCommand();
819 }
820
821 //============================================================================
822 /*! Function : AbortCommand
823  *  Purpose  : 
824  */
825 //============================================================================
826 void SALOMEDSImpl_StudyBuilder::AbortCommand()
827 {
828   _errorCode = "";
829   SALOMEDSImpl_Study::GetStudy(_doc->Main())->UndoPostponed(0);
830   
831   _doc->AbortCommand();
832 }
833
834 //============================================================================
835 /*! Function : Undo
836  *  Purpose  : 
837  */
838 //============================================================================
839 void SALOMEDSImpl_StudyBuilder::Undo()
840 {
841   _errorCode = "";
842   Handle(SALOMEDSImpl_AttributeStudyProperties) anAttr;
843   if (!_doc->Main().FindAttribute(SALOMEDSImpl_AttributeStudyProperties::GetID(), anAttr)) {
844     anAttr = new SALOMEDSImpl_AttributeStudyProperties;
845     _doc->Main().AddAttribute(anAttr);
846     }
847   if (anAttr->IsLocked()) {
848     _errorCode = "LockProtection";
849     throw LockProtection("LockProtection");
850   } else {
851     SALOMEDSImpl_Study::GetStudy(_doc->Main())->UndoPostponed(1);
852     _doc->Undo();
853     anAttr->SetModified(anAttr->GetModified()-1);
854   }
855
856   _doc->Modify();  
857 }
858
859 //============================================================================
860 /*! Function : Redo
861  *  Purpose  : 
862  */
863 //============================================================================
864 void SALOMEDSImpl_StudyBuilder::Redo() 
865 {
866   _errorCode = "";
867   Handle(SALOMEDSImpl_AttributeStudyProperties) anAttr;
868   if (!_doc->Main().FindAttribute(SALOMEDSImpl_AttributeStudyProperties::GetID(), anAttr)) {
869     anAttr = new SALOMEDSImpl_AttributeStudyProperties;
870     _doc->Main().AddAttribute(anAttr);
871   }
872   
873   if (anAttr->IsLocked()) {
874     _errorCode = "LockProtection";
875     throw LockProtection("LockProtection");
876   } else {
877     _doc->Redo();
878     SALOMEDSImpl_Study::GetStudy(_doc->Main())->UndoPostponed(-1);
879     anAttr->SetModified(anAttr->GetModified()+1);
880   }
881    
882   _doc->Modify();  
883 }
884
885 //============================================================================
886 /*! Function : GetAvailableUndos
887  *  Purpose  : 
888  */
889 //============================================================================
890 bool SALOMEDSImpl_StudyBuilder::GetAvailableUndos()
891 {
892   _errorCode = "";
893   return _doc->GetAvailableUndos();
894 }
895
896 //============================================================================
897 /*! Function : GetAvailableRedos
898  *  Purpose  : 
899  */
900 //============================================================================
901 bool  SALOMEDSImpl_StudyBuilder::GetAvailableRedos()
902 {
903   _errorCode = "";
904   return _doc->GetAvailableRedos();
905 }
906
907 //============================================================================
908 /*! Function : UndoLimit
909  *  Purpose  : 
910  */
911 //============================================================================
912 int  SALOMEDSImpl_StudyBuilder::UndoLimit()
913 {
914   _errorCode = "";
915   return _doc->GetUndoLimit();
916 }
917
918 //============================================================================
919 /*! Function : UndoLimit
920  *  Purpose  : 
921  */
922 //============================================================================
923 void SALOMEDSImpl_StudyBuilder::UndoLimit(int n)
924 {
925   _errorCode = "";
926   CheckLocked();
927   _doc->SetUndoLimit (n);
928 }
929
930 //============================================================================
931 /*! Function : SetOnAddSObject
932  *  Purpose  : 
933  */
934 //============================================================================
935 Handle(SALOMEDSImpl_Callback) 
936 SALOMEDSImpl_StudyBuilder::SetOnAddSObject(const Handle(SALOMEDSImpl_Callback)& theCallback)
937 {
938   _errorCode = "";
939   Handle(SALOMEDSImpl_Callback) aRet = _callbackOnAdd;
940   _callbackOnAdd = theCallback;
941   return aRet;
942 }
943
944 //============================================================================
945 /*! Function : SetOnNewSObject
946  *  Purpose  : 
947  */
948 //============================================================================
949 Handle(SALOMEDSImpl_Callback) 
950 SALOMEDSImpl_StudyBuilder::SetOnRemoveSObject(const Handle(SALOMEDSImpl_Callback)& theCallback)
951 {
952   _errorCode = "";
953   Handle(SALOMEDSImpl_Callback) aRet = _callbackOnRemove;
954   _callbackOnRemove = theCallback;
955   return aRet;
956 }
957
958 //============================================================================
959 /*! Function : CheckLocked
960  *  Purpose  : 
961  */
962 //============================================================================
963 void SALOMEDSImpl_StudyBuilder::CheckLocked()
964 {
965   _errorCode = "";
966   if (_doc->HasOpenCommand()) return;
967   Handle(SALOMEDSImpl_AttributeStudyProperties) anAttr;
968   if (!_doc->Main().FindAttribute(SALOMEDSImpl_AttributeStudyProperties::GetID(), anAttr)) {
969     anAttr = new SALOMEDSImpl_AttributeStudyProperties;
970     _doc->Main().AddAttribute(anAttr);
971     }
972   if (anAttr->IsLocked()) {
973     _errorCode = "LockProtection";
974     throw LockProtection("LockProtection");
975   }
976 }
977
978 //============================================================================
979 /*! Function : SetName
980  *  Purpose  : 
981  */
982 //============================================================================
983 bool SALOMEDSImpl_StudyBuilder::SetName(const Handle(SALOMEDSImpl_SObject)& theSO, 
984                                         const TCollection_AsciiString& theValue)
985 {
986   _errorCode = "";
987   CheckLocked();
988   if(theSO.IsNull()) {
989     _errorCode = "Invalid arguments";
990     return false;
991   }
992   SALOMEDSImpl_AttributeName::Set(theSO->GetLabel(), theValue);
993
994   _doc->Modify();  
995
996   return true;
997 }
998
999 //============================================================================
1000 /*! Function : SetComment
1001  *  Purpose  : 
1002  */
1003 //============================================================================
1004 bool SALOMEDSImpl_StudyBuilder::SetComment(const Handle(SALOMEDSImpl_SObject)& theSO, 
1005                                            const TCollection_AsciiString& theValue)
1006 {
1007   _errorCode = "";
1008   CheckLocked();
1009   if(theSO.IsNull()) {
1010     _errorCode = "Invalid arguments";
1011     return false;
1012   }
1013   SALOMEDSImpl_AttributeComment::Set(theSO->GetLabel(), theValue);
1014
1015   _doc->Modify();  
1016
1017   return true;
1018 }
1019
1020 //============================================================================
1021 /*! Function : SetIOR
1022  *  Purpose  : 
1023  */
1024 //============================================================================
1025 bool SALOMEDSImpl_StudyBuilder::SetIOR(const Handle(SALOMEDSImpl_SObject)& theSO, 
1026                                        const TCollection_AsciiString& theValue)
1027 {
1028   _errorCode = "";
1029   CheckLocked();
1030   if(theSO.IsNull()) {
1031     _errorCode = "Invalid arguments";
1032     return false;
1033   }
1034   SALOMEDSImpl_AttributeIOR::Set(theSO->GetLabel(), theValue);
1035
1036   _doc->Modify();  
1037
1038   return true;
1039 }
1040
1041
1042 //============================================================================
1043 /*! Function : Translate_persistentID_to_IOR
1044  *  Purpose  :
1045  */
1046 //============================================================================
1047 static void Translate_persistentID_to_IOR(TDF_Label& Lab, SALOMEDSImpl_Driver* driver, bool isMultiFile, bool isASCII)
1048 {
1049   if(driver == NULL) return;
1050   TDF_ChildIterator  itchild (Lab);
1051   
1052   for (; itchild.More(); itchild.Next()) {
1053     TDF_Label current = itchild.Value();
1054     Handle(SALOMEDSImpl_AttributePersistentRef) Att;
1055     if (current.FindAttribute(SALOMEDSImpl_AttributePersistentRef::GetID(),Att)) {  
1056
1057       Handle(SALOMEDSImpl_AttributeLocalID) anID;
1058       if (current.FindAttribute(SALOMEDSImpl_AttributeLocalID::GetID(), anID)) 
1059         if (anID->Value() == FILELOCALID) continue;        //SRN: This attribute store a file name, skip it 
1060
1061       TCollection_AsciiString persist_ref(Att->Value());
1062       Handle(SALOMEDSImpl_SObject) so = SALOMEDSImpl_Study::SObject(current);
1063       TCollection_AsciiString ior_string = driver->LocalPersistentIDToIOR(so, 
1064                                                                           persist_ref, 
1065                                                                           isMultiFile, 
1066                                                                           isASCII);
1067       SALOMEDSImpl_AttributeIOR::Set (current, ior_string); 
1068      
1069     }
1070     Translate_persistentID_to_IOR (current, driver, isMultiFile, isASCII);
1071   }
1072 }
1073