Salome HOME
BugID: PAL10141, added a possibility to lock the study by several processes.
[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("hdf_from_ascii.hdf");
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     // commented out because NO MODIFICATION is done to attributes when calling FindAttribute()
528     // _doc->Modify();  
529     return Standard_True;
530   }
531   return Standard_False;
532 }
533
534 //============================================================================
535 /*! Function : RemoveAttribute
536  *  Purpose  : Remove attribute of given type assigned SObject
537  */
538 //============================================================================
539
540 bool SALOMEDSImpl_StudyBuilder::RemoveAttribute(const Handle(SALOMEDSImpl_SObject)& anObject, 
541                                                 const TCollection_AsciiString& aTypeOfAttribute)
542 {
543   _errorCode = "";
544   CheckLocked();
545   if(anObject.IsNull()) {
546     _errorCode = "Invalid arguments";
547     return false;
548   }
549   TDF_Label Lab = anObject->GetLabel();
550   
551   if (aTypeOfAttribute == "AttributeIOR") { // postponed removing of CORBA objects
552     Handle(SALOMEDSImpl_AttributeIOR) anAttr;
553     if (Lab.FindAttribute(SALOMEDSImpl_AttributeIOR::GetID(), anAttr))
554       SALOMEDSImpl_Study::GetStudy(_doc->Main())->AddPostponed(anAttr->Value());
555   }
556
557   Lab.ForgetAttribute (SALOMEDSImpl_SObject::GetGUID(aTypeOfAttribute));
558     
559   _doc->Modify();  
560     
561   return true;
562 }
563
564 //============================================================================
565 /*! Function : Addreference
566  *  Purpose  : 
567  */
568 //============================================================================
569 bool SALOMEDSImpl_StudyBuilder::Addreference(const Handle(SALOMEDSImpl_SObject)& me, 
570                                              const Handle(SALOMEDSImpl_SObject)& theReferencedObject)
571 {
572   _errorCode = "";
573   if(me.IsNull() || theReferencedObject.IsNull()) {
574    _errorCode = "Invalid arguments";
575    return false;
576   }
577   CheckLocked();
578   TDF_Label Lab = me->GetLabel();
579   TDF_Label RefLab = theReferencedObject->GetLabel();
580   SALOMEDSImpl_AttributeReference::Set(Lab,RefLab);
581
582   SALOMEDSImpl_AttributeTarget::Set(RefLab)->Add(SALOMEDSImpl_Study::SObject(Lab));
583
584   if(!_callbackOnRemove.IsNull() && Lab.IsDescendant(_doc->Main())) _callbackOnRemove->OnRemoveSObject(me);
585   
586   return true;
587 }
588
589 //============================================================================
590 /*! Function : RemoveReference
591  *  Purpose  : 
592  */
593 //============================================================================
594 bool SALOMEDSImpl_StudyBuilder::RemoveReference(const Handle(SALOMEDSImpl_SObject)& me)
595 {
596   _errorCode = "";
597   Handle(SALOMEDSImpl_SObject) theReferencedObject;
598   if(!me->ReferencedObject(theReferencedObject)) return false;  //No reference is found
599
600   CheckLocked();
601   TDF_Label Lab = me->GetLabel();
602
603   Lab.ForgetAttribute(SALOMEDSImpl_AttributeReference::GetID());  
604
605   //SRN: 30 Aug, 2004 : fix from Ecole l'ete version 
606
607   TDF_Label RefLab = theReferencedObject->GetLabel();
608        
609   Handle(SALOMEDSImpl_AttributeTarget) aTarget;
610   if(RefLab.FindAttribute(SALOMEDSImpl_AttributeTarget::GetID(), aTarget)) 
611     aTarget->Remove(SALOMEDSImpl_Study::SObject(Lab));
612   
613   _doc->Modify();  
614   
615   return true;
616 }
617
618
619
620 //============================================================================
621 /*! Function : AddDirectory
622  *  Purpose  : adds a new directory with a path = thePath
623  */
624 //============================================================================
625 bool SALOMEDSImpl_StudyBuilder::AddDirectory(const TCollection_AsciiString& thePath) 
626 {
627   _errorCode = "";
628   CheckLocked();
629   if(thePath.IsEmpty() || thePath == "") {
630     _errorCode = "Invalid path";
631     return false;
632   }
633
634   TCollection_AsciiString aPath(thePath), aContext(""), aFatherPath;
635   TDF_Label aLabel;
636   Handle(SALOMEDSImpl_Study) aStudy = SALOMEDSImpl_Study::GetStudy(_doc->Main());
637   Handle(SALOMEDSImpl_SObject) anObject;
638
639   try { 
640     anObject = aStudy->FindObjectByPath(thePath); //Check if the directory already exists
641   }
642   catch(...) { }
643
644   if(!anObject.IsNull()) {
645     _errorCode = "StudyNameAlreadyUsed";
646     return false; 
647   }
648
649   if(aPath.Value(1) != '/') { //Relative path 
650     aPath.Prepend('/');
651     aPath = aStudy->GetContext() + aPath;
652   }
653
654   TCollection_AsciiString aToken = aPath.Token("/", 1);
655   if(aToken.Length() == 0) aFatherPath = "/";
656
657   int i = 1;  
658   while(aToken.Length() != 0) {
659     if(aPath.Token("/", i+1).Length() > 0) {
660       aFatherPath += "/";
661       aFatherPath += aToken;
662     }
663     aToken = aPath.Token("/", ++i);
664   }
665
666   anObject.Nullify();
667   try { 
668     anObject = aStudy->FindObjectByPath(aFatherPath); //Check if the father directory exists
669   }
670   catch(...) { ; }
671   if(anObject.IsNull()) {
672     _errorCode = "StudyInvalidDirectory";
673     return false; 
674   }
675
676   Handle(SALOMEDSImpl_SObject) aNewObject = NewObject(anObject);
677   aLabel = aNewObject->GetLabel();
678   if(aLabel.IsNull()) {
679     _errorCode = "StudyInvalidComponent";
680     return false;
681   }
682
683   SALOMEDSImpl_AttributeName::Set(aLabel, aPath.Token("/", i-1));
684
685   //Set LocalID attribute to identify the directory object
686   Handle(SALOMEDSImpl_AttributeLocalID) aLocalID = SALOMEDSImpl_AttributeLocalID::Set(aLabel, DIRECTORYID);
687   
688   _doc->Modify(); 
689   
690   return true;
691 }
692
693
694 //============================================================================
695 /*! Function : SetGUID
696  *  Purpose  : 
697  */
698 //============================================================================
699 bool SALOMEDSImpl_StudyBuilder::SetGUID(const Handle(SALOMEDSImpl_SObject)& anObject, 
700                                         const TCollection_AsciiString& theGUID)
701 {
702   _errorCode = "";
703   CheckLocked();
704   if(anObject.IsNull()) {
705     _errorCode = "Invalid arguments";
706     return false;
707   }
708
709   TDF_Label aLabel = anObject->GetLabel();
710   SALOMEDSImpl_AttributeUserID::Set(aLabel, theGUID.ToCString());
711
712   _doc->Modify();  
713
714   return true;
715 }
716
717 //============================================================================
718 /*! Function : IsGUID
719  *  Purpose  : 
720  */
721 //============================================================================
722 bool SALOMEDSImpl_StudyBuilder::IsGUID(const Handle(SALOMEDSImpl_SObject)& anObject, 
723                                        const TCollection_AsciiString& theGUID)
724 {
725   _errorCode = "";
726   if(anObject.IsNull()) {
727     _errorCode = "Invalid arguments";
728     return false;
729   }
730   TDF_Label aLabel = anObject->GetLabel();
731   return aLabel.IsAttribute(theGUID.ToCString());
732 }
733
734
735 //============================================================================
736 /*! Function : NewCommand
737  *  Purpose  : 
738  */
739 //============================================================================
740 void SALOMEDSImpl_StudyBuilder::NewCommand()
741 {
742   _errorCode = "";
743   // mpv: for SAL2114 - unset "lock changed" flag at the operation start
744   Handle(SALOMEDSImpl_AttributeStudyProperties) anAttr;
745   if (!_doc->Main().FindAttribute(SALOMEDSImpl_AttributeStudyProperties::GetID(), anAttr)) {
746     anAttr = new SALOMEDSImpl_AttributeStudyProperties;
747     _doc->Main().AddAttribute(anAttr);
748   }
749   anAttr->IsLockChanged(true);
750   
751   _doc->NewCommand();
752 }
753
754 //============================================================================
755 /*! Function : CommitCommand
756  *  Purpose  : 
757  */
758 //============================================================================
759 void SALOMEDSImpl_StudyBuilder::CommitCommand()
760 {
761   _errorCode = "";
762   Handle(SALOMEDSImpl_AttributeStudyProperties) anAttr;
763   if (!_doc->Main().FindAttribute(SALOMEDSImpl_AttributeStudyProperties::GetID(), anAttr)) {
764     anAttr = new SALOMEDSImpl_AttributeStudyProperties;
765     _doc->Main().AddAttribute(anAttr);
766   }
767   if (anAttr->IsLocked() && !anAttr->IsLockChanged(true)) {
768     AbortCommand();
769     _errorCode = "LockProtection";
770     throw LockProtection("LockProtection");
771   } else {
772     SALOMEDSImpl_Study::GetStudy(_doc->Main())->RemovePostponed(_doc->GetUndoLimit());
773
774     int aModif = anAttr->GetModified();
775     if (aModif < 0) aModif = 1000; // if user make undo and then - new transaction "modify" will never be zero
776     anAttr->SetModified(aModif+1);
777     _doc->CommitCommand();
778   }
779   
780   _doc->Modify();  
781 }
782
783 //============================================================================
784 /*! Function : HasOpenCommand
785  *  Purpose  : 
786  */
787 //============================================================================
788 bool SALOMEDSImpl_StudyBuilder::HasOpenCommand()
789 {
790   _errorCode = "";
791   return _doc->HasOpenCommand();
792 }
793
794 //============================================================================
795 /*! Function : AbortCommand
796  *  Purpose  : 
797  */
798 //============================================================================
799 void SALOMEDSImpl_StudyBuilder::AbortCommand()
800 {
801   _errorCode = "";
802   SALOMEDSImpl_Study::GetStudy(_doc->Main())->UndoPostponed(0);
803   
804   _doc->AbortCommand();
805 }
806
807 //============================================================================
808 /*! Function : Undo
809  *  Purpose  : 
810  */
811 //============================================================================
812 void SALOMEDSImpl_StudyBuilder::Undo()
813 {
814   _errorCode = "";
815   Handle(SALOMEDSImpl_AttributeStudyProperties) anAttr;
816   if (!_doc->Main().FindAttribute(SALOMEDSImpl_AttributeStudyProperties::GetID(), anAttr)) {
817     anAttr = new SALOMEDSImpl_AttributeStudyProperties;
818     _doc->Main().AddAttribute(anAttr);
819     }
820   if (anAttr->IsLocked()) {
821     _errorCode = "LockProtection";
822     throw LockProtection("LockProtection");
823   } else {
824     SALOMEDSImpl_Study::GetStudy(_doc->Main())->UndoPostponed(1);
825     _doc->Undo();
826     anAttr->SetModified(anAttr->GetModified()-1);
827   }
828
829   _doc->Modify();  
830 }
831
832 //============================================================================
833 /*! Function : Redo
834  *  Purpose  : 
835  */
836 //============================================================================
837 void SALOMEDSImpl_StudyBuilder::Redo() 
838 {
839   _errorCode = "";
840   Handle(SALOMEDSImpl_AttributeStudyProperties) anAttr;
841   if (!_doc->Main().FindAttribute(SALOMEDSImpl_AttributeStudyProperties::GetID(), anAttr)) {
842     anAttr = new SALOMEDSImpl_AttributeStudyProperties;
843     _doc->Main().AddAttribute(anAttr);
844   }
845   
846   if (anAttr->IsLocked()) {
847     _errorCode = "LockProtection";
848     throw LockProtection("LockProtection");
849   } else {
850     _doc->Redo();
851     SALOMEDSImpl_Study::GetStudy(_doc->Main())->UndoPostponed(-1);
852     anAttr->SetModified(anAttr->GetModified()+1);
853   }
854    
855   _doc->Modify();  
856 }
857
858 //============================================================================
859 /*! Function : GetAvailableUndos
860  *  Purpose  : 
861  */
862 //============================================================================
863 bool SALOMEDSImpl_StudyBuilder::GetAvailableUndos()
864 {
865   _errorCode = "";
866   return _doc->GetAvailableUndos();
867 }
868
869 //============================================================================
870 /*! Function : GetAvailableRedos
871  *  Purpose  : 
872  */
873 //============================================================================
874 bool  SALOMEDSImpl_StudyBuilder::GetAvailableRedos()
875 {
876   _errorCode = "";
877   return _doc->GetAvailableRedos();
878 }
879
880 //============================================================================
881 /*! Function : UndoLimit
882  *  Purpose  : 
883  */
884 //============================================================================
885 int  SALOMEDSImpl_StudyBuilder::UndoLimit()
886 {
887   _errorCode = "";
888   return _doc->GetUndoLimit();
889 }
890
891 //============================================================================
892 /*! Function : UndoLimit
893  *  Purpose  : 
894  */
895 //============================================================================
896 void SALOMEDSImpl_StudyBuilder::UndoLimit(int n)
897 {
898   _errorCode = "";
899   CheckLocked();
900   _doc->SetUndoLimit (n);
901 }
902
903 //============================================================================
904 /*! Function : SetOnAddSObject
905  *  Purpose  : 
906  */
907 //============================================================================
908 Handle(SALOMEDSImpl_Callback) 
909 SALOMEDSImpl_StudyBuilder::SetOnAddSObject(const Handle(SALOMEDSImpl_Callback)& theCallback)
910 {
911   _errorCode = "";
912   Handle(SALOMEDSImpl_Callback) aRet = _callbackOnAdd;
913   _callbackOnAdd = theCallback;
914   return aRet;
915 }
916
917 //============================================================================
918 /*! Function : SetOnNewSObject
919  *  Purpose  : 
920  */
921 //============================================================================
922 Handle(SALOMEDSImpl_Callback) 
923 SALOMEDSImpl_StudyBuilder::SetOnRemoveSObject(const Handle(SALOMEDSImpl_Callback)& theCallback)
924 {
925   _errorCode = "";
926   Handle(SALOMEDSImpl_Callback) aRet = _callbackOnRemove;
927   _callbackOnRemove = theCallback;
928   return aRet;
929 }
930
931 //============================================================================
932 /*! Function : CheckLocked
933  *  Purpose  : 
934  */
935 //============================================================================
936 void SALOMEDSImpl_StudyBuilder::CheckLocked()
937 {
938   _errorCode = "";
939   if (_doc->HasOpenCommand()) return;
940   Handle(SALOMEDSImpl_AttributeStudyProperties) anAttr;
941   if (!_doc->Main().FindAttribute(SALOMEDSImpl_AttributeStudyProperties::GetID(), anAttr)) {
942     anAttr = new SALOMEDSImpl_AttributeStudyProperties;
943     _doc->Main().AddAttribute(anAttr);
944     }
945   if (anAttr->IsLocked()) {
946     _errorCode = "LockProtection";
947     throw LockProtection("LockProtection");
948   }
949 }
950
951 //============================================================================
952 /*! Function : SetName
953  *  Purpose  : 
954  */
955 //============================================================================
956 bool SALOMEDSImpl_StudyBuilder::SetName(const Handle(SALOMEDSImpl_SObject)& theSO, 
957                                         const TCollection_AsciiString& theValue)
958 {
959   _errorCode = "";
960   CheckLocked();
961   if(theSO.IsNull()) {
962     _errorCode = "Invalid arguments";
963     return false;
964   }
965   SALOMEDSImpl_AttributeName::Set(theSO->GetLabel(), theValue);
966
967   _doc->Modify();  
968
969   return true;
970 }
971
972 //============================================================================
973 /*! Function : SetComment
974  *  Purpose  : 
975  */
976 //============================================================================
977 bool SALOMEDSImpl_StudyBuilder::SetComment(const Handle(SALOMEDSImpl_SObject)& theSO, 
978                                            const TCollection_AsciiString& theValue)
979 {
980   _errorCode = "";
981   CheckLocked();
982   if(theSO.IsNull()) {
983     _errorCode = "Invalid arguments";
984     return false;
985   }
986   SALOMEDSImpl_AttributeComment::Set(theSO->GetLabel(), theValue);
987
988   _doc->Modify();  
989
990   return true;
991 }
992
993 //============================================================================
994 /*! Function : SetIOR
995  *  Purpose  : 
996  */
997 //============================================================================
998 bool SALOMEDSImpl_StudyBuilder::SetIOR(const Handle(SALOMEDSImpl_SObject)& theSO, 
999                                        const TCollection_AsciiString& theValue)
1000 {
1001   _errorCode = "";
1002   CheckLocked();
1003   if(theSO.IsNull()) {
1004     _errorCode = "Invalid arguments";
1005     return false;
1006   }
1007   SALOMEDSImpl_AttributeIOR::Set(theSO->GetLabel(), theValue);
1008
1009   _doc->Modify();  
1010
1011   return true;
1012 }
1013
1014
1015 //============================================================================
1016 /*! Function : Translate_persistentID_to_IOR
1017  *  Purpose  :
1018  */
1019 //============================================================================
1020 static void Translate_persistentID_to_IOR(TDF_Label& Lab, SALOMEDSImpl_Driver* driver, bool isMultiFile, bool isASCII)
1021 {
1022   if(driver == NULL) return;
1023   TDF_ChildIterator  itchild (Lab);
1024   
1025   for (; itchild.More(); itchild.Next()) {
1026     TDF_Label current = itchild.Value();
1027     Handle(SALOMEDSImpl_AttributePersistentRef) Att;
1028     if (current.FindAttribute(SALOMEDSImpl_AttributePersistentRef::GetID(),Att)) {  
1029
1030       Handle(SALOMEDSImpl_AttributeLocalID) anID;
1031       if (current.FindAttribute(SALOMEDSImpl_AttributeLocalID::GetID(), anID)) 
1032         if (anID->Value() == FILELOCALID) continue;        //SRN: This attribute store a file name, skip it 
1033
1034       TCollection_AsciiString persist_ref(Att->Value());
1035       Handle(SALOMEDSImpl_SObject) so = SALOMEDSImpl_Study::SObject(current);
1036       TCollection_AsciiString ior_string = driver->LocalPersistentIDToIOR(so, 
1037                                                                           persist_ref, 
1038                                                                           isMultiFile, 
1039                                                                           isASCII);
1040       SALOMEDSImpl_AttributeIOR::Set (current, ior_string); 
1041      
1042     }
1043     Translate_persistentID_to_IOR (current, driver, isMultiFile, isASCII);
1044   }
1045 }
1046