Salome HOME
Moved some functionality to VTKViewer_Utilities.h
[modules/kernel.git] / src / SALOMEDS / SALOMEDS_StudyBuilder_i.cxx
1 //  SALOME SALOMEDS : data structure of SALOME and sources of Salome data server 
2 //
3 //  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
5 // 
6 //  This library is free software; you can redistribute it and/or 
7 //  modify it under the terms of the GNU Lesser General Public 
8 //  License as published by the Free Software Foundation; either 
9 //  version 2.1 of the License. 
10 // 
11 //  This library is distributed in the hope that it will be useful, 
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of 
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
14 //  Lesser General Public License for more details. 
15 // 
16 //  You should have received a copy of the GNU Lesser General Public 
17 //  License along with this library; if not, write to the Free Software 
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
19 // 
20 //  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
21 //
22 //
23 //
24 //  File   : SALOMEDS_StudyBuilder_i.cxx
25 //  Author : Yves FRICAUD
26 //  Module : SALOME
27 //  $Header$
28
29 #include "SALOMEDS_StudyBuilder_i.hxx"
30 #include "SALOMEDS_StudyManager_i.hxx"
31 #include "SALOMEDS_Study_i.hxx"
32
33 #include "SALOMEDS_SObject_i.hxx"
34 #include "SALOMEDS_SComponent_i.hxx"
35 #include "SALOMEDS_ChildIterator_i.hxx"
36
37 #include "SALOMEDS_TargetAttribute.hxx"
38 #include "SALOMEDS_IORAttribute.hxx"
39 #include "SALOMEDS_PersRefAttribute.hxx"
40 #include "SALOMEDS_LocalIDAttribute.hxx"
41 #include "SALOMEDS_StudyPropertiesAttribute.hxx"
42
43 #include "SALOMEDS_Tool.hxx"
44
45 #include "Utils_CorbaException.hxx"
46 #include "Utils_ExceptHandlers.hxx"
47
48 #include <TDF_ChildIterator.hxx>
49 #include <TDF_Label.hxx>
50 #include <TDataStd_Name.hxx>
51 #include <TDataStd_Comment.hxx>
52 #include <TDataStd_UAttribute.hxx>
53 #include <TDataStd_Real.hxx>
54 #include <TDF_Tool.hxx>
55 #include <TDF_Reference.hxx>
56 #include <TDF_Data.hxx>
57 #include <TDataStd_ChildNodeIterator.hxx>
58 #include <TDF_ListIteratorOfAttributeList.hxx>
59
60 #include <HDFOI.hxx>
61 #include <stdlib.h> 
62
63 #define USE_CASE_LABEL_TAG            2
64 #define DIRECTORYID 16661
65 #define FILELOCALID 26662 
66
67 #include "utilities.h"
68
69 using namespace std;
70
71 UNEXPECT_CATCH(SBSalomeException, SALOME::SALOME_Exception);
72 UNEXPECT_CATCH(SBLockProtection, SALOMEDS::StudyBuilder::LockProtection);
73
74 //============================================================================
75 /*! Function : constructor
76  *  Purpose  :
77  */
78 //============================================================================
79 SALOMEDS_StudyBuilder_i::SALOMEDS_StudyBuilder_i(SALOMEDS_Study_i* theStudy,
80                                                  const Handle(TDocStd_Document)& theDocument):
81   _study(theStudy),
82   _doc(theDocument)
83 {
84 }
85
86 //============================================================================
87 /*! Function : destructor
88  *  Purpose  :
89  */
90 //============================================================================
91 SALOMEDS_StudyBuilder_i::~SALOMEDS_StudyBuilder_i()
92 {
93 }
94
95
96 //============================================================================
97 CORBA::ORB_var SALOMEDS_StudyBuilder_i::GetORB() const
98 {
99   return _study->GetORB();
100 }
101
102
103 //============================================================================
104 PortableServer::POA_var SALOMEDS_StudyBuilder_i::GetPOA() const
105 {
106   return _study->GetPOA();
107 }
108
109
110 //============================================================================
111 /*! Function : NewComponent
112  *  Purpose  : Create a new component (Scomponent)
113  */
114 //============================================================================
115 SALOMEDS::SComponent_ptr 
116 SALOMEDS_StudyBuilder_i::NewComponent(const char* DataType)
117 {
118   CheckLocked();
119   //Always create component under main label.
120   TDF_Label L  = _doc->Main();
121
122   // YFR DEBUG : 13/02/2002 TDF_Label NL = L.NewChild();
123   
124   Standard_Integer imax = 0;
125   for (TDF_ChildIterator it(L); it.More(); it.Next()) {
126     if (it.Value().Tag() > imax)
127       imax = it.Value().Tag();
128   }
129   imax++;
130   TDF_Label NL = L.FindChild(imax);
131
132    TDataStd_Comment::Set(NL,Standard_CString(DataType));
133    //  TDataStd_Comment::Set(NL,Standard_CString(CORBA::string_dup(DataType)));
134
135   SALOMEDS::SComponent_var aSComponent = SALOMEDS_SComponent_i::NewRef(_study,NL); 
136
137   OnAddSObject(aSComponent);
138
139   return aSComponent._retn();
140 }
141
142 //============================================================================
143 /*! Function : DefineComponentInstance
144  *  Purpose  : Add IOR attribute of a Scomponent
145  */
146 //============================================================================
147 void SALOMEDS_StudyBuilder_i::DefineComponentInstance(SALOMEDS::SComponent_ptr theComponent,
148                                                       CORBA::Object_ptr theObject)
149 {
150   CheckLocked();
151
152   if(CORBA::is_nil(theComponent) || CORBA::is_nil(theObject))
153     return;
154
155   //Find label
156   TDF_Label Lab;
157   CORBA::String_var aString = theComponent->GetID();
158   TDF_Tool::Label(_doc->GetData(),const_cast<char*>(aString.in()),Lab);
159
160   //add theObject definition 
161   aString = GetORB()->object_to_string(theObject);
162   SALOMEDS_IORAttribute::Set(Lab,const_cast<char*>(aString.in()),_study);
163 }
164
165 //============================================================================
166 /*! Function : RemoveComponent
167  *  Purpose  : Delete a Scomponent
168  */
169 //============================================================================
170 void 
171 SALOMEDS_StudyBuilder_i::RemoveComponent(SALOMEDS::SComponent_ptr theComponent)
172 {
173   CheckLocked();
174   RemoveObject(theComponent);
175 }
176
177 //============================================================================
178 /*! Function : NewObject
179  *  Purpose  : Create a new SObject
180  */
181 //============================================================================
182 SALOMEDS::SObject_ptr 
183 SALOMEDS_StudyBuilder_i::NewObject(SALOMEDS::SObject_ptr theFatherObject)
184 {
185   CheckLocked();
186
187   if(CORBA::is_nil(theFatherObject)) 
188     return SALOMEDS::SObject::_nil();
189
190   //Find label of father
191   TDF_Label aLabel;
192   TCollection_AsciiString anEntry;
193   
194   CORBA::String_var aFatherID = theFatherObject->GetID();
195   TDF_Tool::Label(_doc->GetData(),aFatherID,aLabel);
196
197   //Create a new label
198   //YFR DEBUG : 13/02/2002  TDF_Label NewLab = Lab.NewChild();
199   Standard_Integer imax = 0;
200   for (TDF_ChildIterator it(aLabel); it.More(); it.Next()) {
201     if (it.Value().Tag() > imax)
202       imax = it.Value().Tag();
203   }
204   imax++;
205   TDF_Label aNewLabel = aLabel.FindChild(imax);
206   
207   SALOMEDS::SObject_var aSObject = SALOMEDS_SObject_i::NewRef(_study,aNewLabel); 
208
209   OnAddSObject(aSObject);
210
211   return aSObject._retn();
212 }
213
214 //============================================================================
215 /*! Function : NewObjectToTag
216  *  Purpose  :
217  */
218 //============================================================================
219 SALOMEDS::SObject_ptr 
220 SALOMEDS_StudyBuilder_i::NewObjectToTag(SALOMEDS::SObject_ptr theFatherObject,
221                                         CORBA::Long theTag)
222 {
223   CheckLocked();
224
225   if(CORBA::is_nil(theFatherObject)) 
226     return SALOMEDS::SObject::_nil();
227
228   //Find label of father
229   TDF_Label Lab;
230   CORBA::String_var aFatherID = theFatherObject->GetID();
231   TDF_Tool::Label(_doc->GetData(),aFatherID,Lab);
232
233   //Create or find label
234   TDF_Label aNewLab = Lab.FindChild(theTag,1);
235
236   SALOMEDS::SObject_var aSObject = SALOMEDS_SObject_i::NewRef(_study,aNewLab); 
237
238   OnAddSObject(aSObject);
239
240   return aSObject._retn();
241 }
242
243 //============================================================================
244 /*! Function : RemoveObject
245  *  Purpose  :
246  */
247 //============================================================================
248 void SALOMEDS_StudyBuilder_i::RemoveObject(SALOMEDS::SObject_ptr theSObject)
249 {
250   RemoveSObject(theSObject);
251 }
252
253 SALOMEDS_SObject_i*
254 SALOMEDS_StudyBuilder_i::RemoveSObject(SALOMEDS::SObject_ptr theSObject,
255                                        bool theIsForgetAllAttributes)
256 {
257   CheckLocked();
258
259   if(SALOMEDS_SObject_i* aSObject = _study->DownCast(theSObject)){
260     OnRemoveSObject(theSObject);
261     aSObject->OnRemove();
262     if(theIsForgetAllAttributes){
263       TDF_Label aLabel = aSObject->GetLabel();
264       aLabel.ForgetAllAttributes();
265     }
266     return aSObject;
267   }
268
269   return NULL;
270 }
271
272 //============================================================================
273 /*! Function : RemoveObjectWithChildren
274  *  Purpose  :
275  */
276 //============================================================================
277 void SALOMEDS_StudyBuilder_i::RemoveObjectWithChildren(SALOMEDS::SObject_ptr theSObject)
278 {
279   if(SALOMEDS_SObject_i* aSObject = RemoveSObject(theSObject,false)){
280     SALOMEDS_ChildIterator_i aChildIter(_study,aSObject->GetLabel(),true);
281     for(; aChildIter.More(); aChildIter.Next()){
282       if(SALOMEDS_SObject_i* aSObj = aChildIter.GetValue())
283         aSObj->OnRemove();
284     }
285     TDF_Label aLabel = aSObject->GetLabel();
286     aLabel.ForgetAllAttributes(Standard_True);
287   }
288 }
289
290 //============================================================================
291 /*! Function : Translate_persistentID_to_IOR
292  *  Purpose  :
293  */
294 //============================================================================
295 static void  Translate_persistentID_to_IOR(TDF_Label theLabel,
296                                            SALOMEDS::Driver_ptr theDriver,
297                                            SALOMEDS_Study_i* theStudy,
298                                            CORBA::Boolean theIsMultiFile,
299                                            CORBA::Boolean theIsASCII)
300 {
301   if(CORBA::is_nil(theDriver))
302     return;
303
304   for (TDF_ChildIterator  aChildIter (theLabel); aChildIter.More(); aChildIter.Next()){
305     TDF_Label aCurrentLabel = aChildIter.Value();
306     Handle(TDF_Attribute) anAttr;
307     if(aCurrentLabel.FindAttribute(SALOMEDS_PersRefAttribute::GetID(),anAttr)){
308       Handle(SALOMEDS_LocalIDAttribute) anID;
309       if (aCurrentLabel.FindAttribute(SALOMEDS_LocalIDAttribute::GetID(),anID)) 
310         if (anID->Get() == FILELOCALID) continue;        //SRN: This attribute store a file name, skip it 
311
312       TCollection_ExtendedString res = Handle(TDataStd_Comment)::DownCast(anAttr)->Get();
313       TCollection_AsciiString ch(res);
314       
315       SALOMEDS::SObject_var aSObject = SALOMEDS_SObject_i::NewRef(theStudy,aCurrentLabel); 
316
317       CORBA::String_var anIOR = 
318         theDriver->LocalPersistentIDToIOR(aSObject,ch.ToCString(),theIsMultiFile,theIsASCII);
319       SALOMEDS_IORAttribute::Set(aCurrentLabel,const_cast<char*>(anIOR.in()),theStudy); 
320     }
321
322     Translate_persistentID_to_IOR(aCurrentLabel,theDriver,theStudy,theIsMultiFile,theIsASCII);
323   }
324 }
325
326 //============================================================================
327 /*! Function : LoadWith
328  *  Purpose  : 
329  */
330 //============================================================================
331
332 //============================================================================
333 void SALOMEDS_StudyBuilder_i::LoadWith(SALOMEDS::SComponent_ptr theSComponent, 
334                                        SALOMEDS::Driver_ptr theDriver) 
335   throw(SALOME::SALOME_Exception)
336 {
337   Unexpect aCatch(SBSalomeException);
338
339   if(CORBA::is_nil(theSComponent))
340     return;
341
342   TDF_Label Lab;
343   CORBA::String_var aString = theSComponent->GetID();
344   TDF_Tool::Label(_doc->GetData(),const_cast<char*>(aString.in()),Lab);
345   
346   //Find the current Url of the study  
347   Handle(TDF_Attribute) Att;
348   if (_doc->Main().FindAttribute(SALOMEDS_PersRefAttribute::GetID(),Att)) {
349     if(CORBA::is_nil(theDriver))
350       return;
351
352     int aLocked = _study->GetProperties()->IsLocked();
353     if(aLocked) 
354       _study->GetProperties()->SetLocked(false);
355     
356     // mpv 06.03.2003: SAL1927 - if component data if already loaded, it is not necessary to do it again
357     if (Lab.FindAttribute(SALOMEDS_IORAttribute::GetID(), Att)) {
358       if(aLocked) 
359         _study->GetProperties()->SetLocked(true);
360       return;
361     }
362     DefineComponentInstance (theSComponent,theDriver);
363     
364     TCollection_AsciiString aHDFPath(Handle(TDataStd_Comment)::DownCast(Att)->Get());
365     
366     bool isASCII = false;
367     std::ostringstream anURLStream;
368     if(HDFascii::isASCII(aHDFPath.ToCString())){
369       isASCII = true;
370       auto_ptr<char> aResultPath(HDFascii::ConvertFromASCIIToHDF(aHDFPath.ToCString()));
371       anURLStream<<aResultPath.get()<<"hdf_from_ascii.hdf";
372     } else {
373       anURLStream<<aHDFPath.ToCString();
374     }
375     std::string aHDFUrl = anURLStream.str();
376
377     //Open the Study HDF file 
378     auto_ptr<HDFfile> hdf_file(new HDFfile(const_cast<char*>(aHDFUrl.c_str())));
379     
380     char aMultifileState[2];
381     char ASCIIfileState[2];
382     try {
383       CORBA::String_var scoid = theSComponent->GetID();
384       hdf_file->OpenOnDisk(HDF_RDONLY);
385       HDFgroup *hdf_group = new HDFgroup("DATACOMPONENT",hdf_file.get());
386       hdf_group->OpenOnDisk();
387       HDFgroup *hdf_sco_group = new HDFgroup(scoid, hdf_group);
388       hdf_sco_group->OpenOnDisk();
389         
390       SALOMEDS::TMPFile_var aStreamFile;
391       if (hdf_sco_group->ExistInternalObject("FILE_STREAM")) {
392         HDFdataset *hdf_dataset = new HDFdataset("FILE_STREAM", hdf_sco_group);
393         hdf_dataset->OpenOnDisk();
394         int aStreamSize = hdf_dataset->GetSize();
395         unsigned char* aBuffer = new unsigned char[aStreamSize];
396         if(aBuffer == NULL) 
397           throw HDFexception("Unable to open dataset FILE_STREAM");
398         hdf_dataset->ReadFromDisk(aBuffer);
399         aStreamFile = new SALOMEDS::TMPFile(aStreamSize, aStreamSize, aBuffer, 1);
400         hdf_dataset->CloseOnDisk();
401         hdf_dataset = 0;
402       } else 
403         aStreamFile = new SALOMEDS::TMPFile(0);
404       
405       HDFdataset *multifile_hdf_dataset = new HDFdataset("MULTIFILE_STATE", hdf_sco_group);
406       multifile_hdf_dataset->OpenOnDisk();
407       multifile_hdf_dataset->ReadFromDisk(aMultifileState);
408       
409       HDFdataset *ascii_hdf_dataset = new HDFdataset("ASCII_STATE", hdf_sco_group);
410       ascii_hdf_dataset->OpenOnDisk();
411       ascii_hdf_dataset->ReadFromDisk(ASCIIfileState);
412       
413       // set path without file name from URL 
414       std::string aDir(aHDFPath.ToCString());
415       aDir = aDir.substr(0,aDir.rfind('/') + 1);
416       
417       CORBA::Boolean aResult = (ASCIIfileState[0]=='A')?
418         theDriver->LoadASCII(theSComponent, aStreamFile.in(), aDir.c_str(), aMultifileState[0]=='M'):
419           theDriver->Load(theSComponent, aStreamFile.in(), aDir.c_str(), aMultifileState[0]=='M');
420       if(!aResult) {
421         RemoveAttribute( theSComponent, "AttributeIOR" );
422         if (isASCII) {
423           SALOMEDS::ListOfFileNames_var aFilesToRemove = new SALOMEDS::ListOfFileNames;
424           aFilesToRemove->length(1);
425           std::string aDir = SALOMEDS_Tool::GetDirFromPath(aHDFUrl);
426           aFilesToRemove[0] = CORBA::string_dup(&aHDFUrl[strlen(aDir.c_str())]);
427           SALOMEDS_Tool::RemoveTemporaryFiles(aDir,aFilesToRemove,true);
428         }
429         MESSAGE("Can't load component");
430         THROW_SALOME_CORBA_EXCEPTION("Unable to load component data",SALOME::BAD_PARAM);
431       }
432       
433       multifile_hdf_dataset->CloseOnDisk();
434       multifile_hdf_dataset = 0;
435       ascii_hdf_dataset->CloseOnDisk();
436       ascii_hdf_dataset = 0;
437       hdf_sco_group->CloseOnDisk();
438       hdf_sco_group = 0;
439       hdf_group->CloseOnDisk();
440       hdf_group = 0;
441       hdf_file->CloseOnDisk();
442       
443       if (isASCII) {
444         SALOMEDS::ListOfFileNames_var aFilesToRemove = new SALOMEDS::ListOfFileNames;
445         aFilesToRemove->length(1);
446         std::string aDir = SALOMEDS_Tool::GetDirFromPath(aHDFUrl);
447         aFilesToRemove[0] = CORBA::string_dup(&aHDFUrl[strlen(aDir.c_str())]);
448         SALOMEDS_Tool::RemoveTemporaryFiles(aDir,aFilesToRemove,true);
449       }
450     }
451     catch (HDFexception) {
452       INFOS("No persistent file Name");
453       if (isASCII) {
454         SALOMEDS::ListOfFileNames_var aFilesToRemove = new SALOMEDS::ListOfFileNames;
455         aFilesToRemove->length(1);
456         std::string aDir = SALOMEDS_Tool::GetDirFromPath(aHDFUrl);
457         aFilesToRemove[0] = CORBA::string_dup(&aHDFUrl[strlen(aDir.c_str())]);
458         SALOMEDS_Tool::RemoveTemporaryFiles(aDir,aFilesToRemove,true);
459       }
460       if(aLocked)
461         _study->GetProperties()->SetLocked(true);
462       THROW_SALOME_CORBA_EXCEPTION("No persistent file Name found",SALOME::BAD_PARAM);
463     }
464     
465     try {
466       Translate_persistentID_to_IOR(Lab,theDriver,_study,aMultifileState[0]=='M',ASCIIfileState[0] == 'A');
467     } catch (SALOME::SALOME_Exception) {
468       INFOS("Can't translate PersRef to IOR");
469       if (aLocked) 
470         _study->GetProperties()->SetLocked(true);
471       THROW_SALOME_CORBA_EXCEPTION("Unable to convert component persistent data to the transient",SALOME::BAD_PARAM);
472       //        throw HDFexception("Unable to load component data");
473     }
474     if(aLocked)
475       _study->GetProperties()->SetLocked(true);
476   } else
477     MESSAGE("No persistent file Name");
478 }
479
480
481 //============================================================================
482 /*! Function : Load
483  *  Purpose  : 
484  */
485 //============================================================================
486 void SALOMEDS_StudyBuilder_i::Load(SALOMEDS::SObject_ptr sco)
487 {
488   MESSAGE ( "This function is not yet implemented");
489 }
490
491 //============================================================================
492 /*! Function : FindOrCreateAttribute
493  *  Purpose  : Add attribute of given type to SObject, if there is attribute of such type, returns
494  *  existing one
495  */
496 //============================================================================
497 SALOMEDS::GenericAttribute_ptr 
498 SALOMEDS_StudyBuilder_i::FindOrCreateAttribute(SALOMEDS::SObject_ptr theObject, 
499                                                const char* theTypeOfAttribute)
500 {
501   if(SALOMEDS_SObject_i* aSObject = _study->DownCast(theObject))
502     return aSObject->FindOrCreateAttribute(theTypeOfAttribute);
503
504   return SALOMEDS::GenericAttribute::_nil();
505 }
506
507 //============================================================================
508 /*! Function : FindAttribute
509  *  Purpose  : Find attribute of given type assigned SObject, returns Standard_True if it is found
510  */
511 //============================================================================
512
513 CORBA::Boolean SALOMEDS_StudyBuilder_i::FindAttribute(SALOMEDS::SObject_ptr theObject, 
514                                                       SALOMEDS::GenericAttribute_out theAttr, 
515                                                       const char* theTypeOfAttribute)
516 {
517   if(SALOMEDS_SObject_i* aSObject = _study->DownCast(theObject))
518     return aSObject->FindAttribute(theAttr,theTypeOfAttribute);
519
520   return Standard_False;
521 }
522
523 //============================================================================
524 /*! Function : RemoveAttribute
525  *  Purpose  : Remove attribute of given type assigned SObject
526  */
527 //============================================================================
528
529 void SALOMEDS_StudyBuilder_i::RemoveAttribute(SALOMEDS::SObject_ptr theSObject, 
530                                               const char* aTypeOfAttribute)
531 {
532   CheckLocked();
533
534   if(CORBA::is_nil(theSObject))
535     return;
536
537   TDF_Label Lab;
538   CORBA::String_var anobid = theSObject->GetID();
539   TDF_Tool::Label(_doc->GetData(),anobid,Lab);
540   
541   if (strcmp(aTypeOfAttribute, "AttributeIOR") == 0) { // postponed removing of CORBA objects
542     Handle(SALOMEDS_IORAttribute) anAttr;
543     if (Lab.FindAttribute(SALOMEDS_IORAttribute::GetID(), anAttr))
544       _study->AddPostponed(TCollection_AsciiString(anAttr->Get()).ToCString());
545     else
546       return;
547   }
548
549   Lab.ForgetAttribute(SALOMEDS::GetGUID(aTypeOfAttribute));
550 }
551
552 //============================================================================
553 /*! Function : Addreference
554  *  Purpose  : 
555  */
556 //============================================================================
557 void 
558 SALOMEDS_StudyBuilder_i::Addreference(SALOMEDS::SObject_ptr me, 
559                                       SALOMEDS::SObject_ptr theReferencedObject)
560 {
561   CheckLocked();
562   if(CORBA::is_nil(me) || CORBA::is_nil(theReferencedObject))
563     return;
564
565   TDF_Label Lab;
566   CORBA::String_var meid = me->GetID();
567   TDF_Tool::Label(_doc->GetData(),meid,Lab);  
568
569   TDF_Label RefLab;
570   CORBA::String_var roid = theReferencedObject->GetID();
571   TDF_Tool::Label(_doc->GetData(),roid,RefLab);
572
573   TDF_Reference::Set(Lab,RefLab);
574   SALOMEDS_TargetAttribute::Set(RefLab)->Append(Lab);
575
576   if(Lab.IsDescendant(_doc->Main())) 
577     OnRemoveSObject(me);
578 }
579
580 //============================================================================
581 /*! Function : RemoveReference
582  *  Purpose  : 
583  */
584 //============================================================================
585 void SALOMEDS_StudyBuilder_i::RemoveReference(SALOMEDS::SObject_ptr me)
586 {
587   SALOMEDS::SObject_var theReferencedObject;
588   if(!me->ReferencedObject(theReferencedObject)) return;  //No reference is found
589
590   if(CORBA::is_nil(me) || CORBA::is_nil(theReferencedObject))
591     return;
592
593   CheckLocked();
594   TDF_Label Lab;
595   CORBA::String_var meid = me->GetID();
596   TDF_Tool::Label(_doc->GetData(),meid,Lab);  
597
598   Lab.ForgetAttribute(TDF_Reference::GetID());  
599
600   TDF_Label RefLab;  
601   CORBA::String_var roid = theReferencedObject->GetID();
602   TDF_Tool::Label(_doc->GetData(),roid,RefLab);
603
604   RemoveAttribute(theReferencedObject, "AttributeTarget");
605 }
606
607
608
609 //============================================================================
610 /*! Function : AddDirectory
611  *  Purpose  : adds a new directory with a path = thePath
612  */
613 //============================================================================
614 void SALOMEDS_StudyBuilder_i::AddDirectory(const char* thePath) 
615 {
616   CheckLocked();
617   if(thePath == NULL || strlen(thePath) == 0) throw SALOMEDS::Study::StudyInvalidDirectory();
618
619   TCollection_AsciiString aPath(CORBA::string_dup(thePath)), aContext(""), aFatherPath;
620   Handle(TDataStd_Name) aName;
621   TDF_Label aLabel;
622   SALOMEDS::SObject_var anObject = SALOMEDS_SObject_i::NewRef(_study,_doc->Main()); 
623
624   try { 
625     anObject = _study->FindObjectByPath(thePath); //Check if the directory already exists
626   }
627   catch(...) { }
628
629   if(!anObject->_is_nil()) throw SALOMEDS::Study::StudyNameAlreadyUsed(); 
630
631   if(aPath.Value(1) != '/') { //Relative path 
632     aPath.Prepend('/');
633     aPath = TCollection_AsciiString(_study->GetContext()) + aPath;
634   }
635
636   TCollection_AsciiString aToken = aPath.Token("/", 1);
637   if(aToken.Length() == 0) aFatherPath = "/";
638
639   int i = 1;  
640   while(aToken.Length() != 0) {
641     if(aPath.Token("/", i+1).Length() > 0) {
642       aFatherPath += "/";
643       aFatherPath += aToken;
644     }
645     aToken = aPath.Token("/", ++i);
646   }
647
648   anObject = SALOMEDS::SObject::_nil();
649   try { 
650     anObject = _study->FindObjectByPath(aFatherPath.ToCString()); //Check if the father directory exists
651   }
652   catch(...) { ; }
653   if(anObject->_is_nil()) 
654     throw SALOMEDS::Study::StudyInvalidDirectory(); 
655
656   SALOMEDS::SObject_var aNewObject = NewObject(anObject);
657   TDF_Tool::Label(_doc->GetData(), aNewObject->GetID(), aLabel);
658   if(aLabel.IsNull()) {
659     MESSAGE("### NULL label");
660     throw SALOMEDS::Study::StudyInvalidComponent();      
661   }
662
663   TDataStd_Name::Set(aLabel, aPath.Token("/", i-1));
664
665   //Set LocalID attribute to identify the directory object
666   SALOMEDS::GenericAttribute_var anAttr = FindOrCreateAttribute(aNewObject, "AttributeLocalID");
667   SALOMEDS::AttributeLocalID_var aPersRef = SALOMEDS::AttributeLocalID::_narrow(anAttr);
668   if(aPersRef->_is_nil()) 
669     throw SALOMEDS::Study::StudyInvalidDirectory();
670
671   aPersRef->SetValue(DIRECTORYID);
672 }
673
674
675 //============================================================================
676 /*! Function : SetGUID
677  *  Purpose  : 
678  */
679 //============================================================================
680 void SALOMEDS_StudyBuilder_i::SetGUID(SALOMEDS::SObject_ptr anObject, const char* theGUID)
681 {
682   CheckLocked();
683
684   if(CORBA::is_nil(anObject))
685     return;
686
687   TDF_Label aLabel;
688   CORBA::String_var anEntry = anObject->GetID();
689   TDF_Tool::Label(_doc->GetData(), anEntry, aLabel);
690   TDataStd_UAttribute::Set(aLabel, (char*)theGUID);
691 }
692
693 //============================================================================
694 /*! Function : IsGUID
695  *  Purpose  : 
696  */
697 //============================================================================
698 bool SALOMEDS_StudyBuilder_i::IsGUID(SALOMEDS::SObject_ptr anObject, const char* theGUID)
699 {
700   if(CORBA::is_nil(anObject))
701     return false;
702
703   TDF_Label aLabel;
704   CORBA::String_var anEntry = anObject->GetID();
705   TDF_Tool::Label(_doc->GetData(), anEntry, aLabel);
706   return aLabel.IsAttribute((char*)theGUID);
707 }
708
709
710 //============================================================================
711 /*! Function : NewCommand
712  *  Purpose  : 
713  */
714 //============================================================================
715 void SALOMEDS_StudyBuilder_i::NewCommand()
716 {
717   // mpv: for SAL2114 - unset "lock changed" flag at the operation start
718   Handle(SALOMEDS_StudyPropertiesAttribute) anAttr;
719   if (!_doc->Main().FindAttribute(SALOMEDS_StudyPropertiesAttribute::GetID(), anAttr)) {
720     anAttr = new SALOMEDS_StudyPropertiesAttribute;
721     _doc->Main().AddAttribute(anAttr);
722   }
723   anAttr->IsLockChanged(true);
724   
725   _doc->NewCommand();
726 }
727
728 //============================================================================
729 /*! Function : CommitCommand
730  *  Purpose  : 
731  */
732 //============================================================================
733 void SALOMEDS_StudyBuilder_i::CommitCommand() throw (SALOMEDS::StudyBuilder::LockProtection)
734 {
735   Unexpect aCatch(SBLockProtection);
736   Handle(SALOMEDS_StudyPropertiesAttribute) anAttr;
737   if (!_doc->Main().FindAttribute(SALOMEDS_StudyPropertiesAttribute::GetID(), anAttr)) {
738     anAttr = new SALOMEDS_StudyPropertiesAttribute;
739     _doc->Main().AddAttribute(anAttr);
740   }
741   if (anAttr->IsLocked() && !anAttr->IsLockChanged(true)) {
742     MESSAGE("Locked document modification !!!");
743     AbortCommand();
744     throw SALOMEDS::StudyBuilder::LockProtection();
745   } else {
746     _study->RemovePostponed(_doc->GetUndoLimit());
747
748     int aModif = anAttr->GetModified();
749     if (aModif < 0) aModif = 1000; // if user make undo and then - new transaction "modify" will never be zero
750     anAttr->SetModified(aModif+1);
751     _doc->CommitCommand();
752   }
753 }
754
755 //============================================================================
756 /*! Function : HasOpenCommand
757  *  Purpose  : 
758  */
759 //============================================================================
760 CORBA::Boolean SALOMEDS_StudyBuilder_i::HasOpenCommand()
761 {
762   return _doc->HasOpenCommand();
763 }
764
765 //============================================================================
766 /*! Function : AbortCommand
767  *  Purpose  : 
768  */
769 //============================================================================
770 void SALOMEDS_StudyBuilder_i::AbortCommand()
771 {
772   _study->UndoPostponed(0);
773   
774   _doc->AbortCommand();
775 }
776
777 //============================================================================
778 /*! Function : Undo
779  *  Purpose  : 
780  */
781 //============================================================================
782 void SALOMEDS_StudyBuilder_i::Undo() throw (SALOMEDS::StudyBuilder::LockProtection)
783 {
784   Unexpect aCatch(SBLockProtection);
785   Handle(SALOMEDS_StudyPropertiesAttribute) anAttr;
786   if (!_doc->Main().FindAttribute(SALOMEDS_StudyPropertiesAttribute::GetID(), anAttr)) {
787     anAttr = new SALOMEDS_StudyPropertiesAttribute;
788     _doc->Main().AddAttribute(anAttr);
789     }
790   if (anAttr->IsLocked()) {
791     MESSAGE("Locked document modification !!!");
792     throw SALOMEDS::StudyBuilder::LockProtection();
793   } else {
794     _study->UndoPostponed(1);
795     _doc->Undo();
796     anAttr->SetModified(anAttr->GetModified()-1);
797   }
798 }
799
800 //============================================================================
801 /*! Function : Redo
802  *  Purpose  : 
803  */
804 //============================================================================
805 void SALOMEDS_StudyBuilder_i::Redo() throw (SALOMEDS::StudyBuilder::LockProtection)
806 {
807   Unexpect aCatch(SBLockProtection);
808   Handle(SALOMEDS_StudyPropertiesAttribute) anAttr;
809   if (!_doc->Main().FindAttribute(SALOMEDS_StudyPropertiesAttribute::GetID(), anAttr)) {
810     anAttr = new SALOMEDS_StudyPropertiesAttribute;
811     _doc->Main().AddAttribute(anAttr);
812   }
813   
814   if (anAttr->IsLocked()) {
815     MESSAGE("Locked document modification !!!");
816     throw SALOMEDS::StudyBuilder::LockProtection();
817   } else {
818     _doc->Redo();
819     _study->UndoPostponed(-1);
820     anAttr->SetModified(anAttr->GetModified()+1);
821   }
822  }
823
824 //============================================================================
825 /*! Function : GetAvailableUndos
826  *  Purpose  : 
827  */
828 //============================================================================
829 CORBA::Boolean SALOMEDS_StudyBuilder_i::GetAvailableUndos()
830 {
831   return _doc->GetAvailableUndos();
832 }
833
834 //============================================================================
835 /*! Function : GetAvailableRedos
836  *  Purpose  : 
837  */
838 //============================================================================
839 CORBA::Boolean  SALOMEDS_StudyBuilder_i::GetAvailableRedos()
840 {
841   return _doc->GetAvailableRedos();
842 }
843
844 //============================================================================
845 /*! Function : UndoLimit
846  *  Purpose  : 
847  */
848 //============================================================================
849 CORBA::Long  SALOMEDS_StudyBuilder_i::UndoLimit()
850 {
851   return _doc->GetUndoLimit();
852 }
853
854 //============================================================================
855 /*! Function : UndoLimit
856  *  Purpose  : 
857  */
858 //============================================================================
859 void  SALOMEDS_StudyBuilder_i::UndoLimit(CORBA::Long n)
860 {
861   CheckLocked();
862   _doc->SetUndoLimit (n);
863 }
864
865 //============================================================================
866 /*! Function : SetOnAddSObject
867  *  Purpose  : 
868  */
869 //============================================================================
870 SALOMEDS::Callback_ptr SALOMEDS_StudyBuilder_i::SetOnAddSObject(SALOMEDS::Callback_ptr theCallback)
871 {
872   return _study->SetOnAddSObject(theCallback);
873 }
874
875 void SALOMEDS_StudyBuilder_i::OnAddSObject(SALOMEDS::SObject_ptr theObject)
876 {
877   _study->OnAddSObject(theObject);
878 }
879
880 //============================================================================
881 /*! Function : SetOnNewSObject
882  *  Purpose  : 
883  */
884 //============================================================================
885 SALOMEDS::Callback_ptr SALOMEDS_StudyBuilder_i::SetOnRemoveSObject(SALOMEDS::Callback_ptr theCallback)
886 {
887   return _study->SetOnRemoveSObject(theCallback);
888 }
889
890 void SALOMEDS_StudyBuilder_i::OnRemoveSObject(SALOMEDS::SObject_ptr theObject)
891 {
892   _study->OnRemoveSObject(theObject);
893 }
894
895 //============================================================================
896 /*! Function : CheckLocked
897  *  Purpose  : 
898  */
899 //============================================================================
900 void SALOMEDS_StudyBuilder_i::CheckLocked() throw (SALOMEDS::StudyBuilder::LockProtection) {
901   _study->CheckLocked();
902 }
903
904 //============================================================================
905 /*! Function : SetName
906  *  Purpose  : 
907  */
908 //============================================================================
909 void SALOMEDS_StudyBuilder_i::SetName(SALOMEDS::SObject_ptr theSO, const char* theValue)
910      throw(SALOMEDS::StudyBuilder::LockProtection)
911 {
912   Unexpect aCatch(SBLockProtection);
913   CheckLocked();
914
915   if(CORBA::is_nil(theSO))
916     return;
917
918   //Find label
919   TDF_Label aLabel;
920   CORBA::String_var aSOID = theSO->GetID();
921   TDF_Tool::Label(_doc->GetData(), aSOID, aLabel);
922   TDataStd_Name::Set(aLabel, (char*)theValue);
923 }
924
925 //============================================================================
926 /*! Function : SetComment
927  *  Purpose  : 
928  */
929 //============================================================================
930 void SALOMEDS_StudyBuilder_i::SetComment(SALOMEDS::SObject_ptr theSO, const char* theValue)
931  throw(SALOMEDS::StudyBuilder::LockProtection)
932 {
933   Unexpect aCatch(SBLockProtection);
934   CheckLocked();
935
936   if(CORBA::is_nil(theSO))
937     return;
938
939    //Find label
940   TDF_Label aLabel;
941   CORBA::String_var aSOID = theSO->GetID();
942   TDF_Tool::Label(_doc->GetData(), aSOID, aLabel);
943   TDataStd_Comment::Set(aLabel, (char*)theValue);
944 }
945
946 //============================================================================
947 /*! Function : SetIOR
948  *  Purpose  : 
949  */
950 //============================================================================
951 void SALOMEDS_StudyBuilder_i::SetIOR(SALOMEDS::SObject_ptr theSO, const char* theValue)
952  throw(SALOMEDS::StudyBuilder::LockProtection)
953 {
954   Unexpect aCatch(SBLockProtection);
955   CheckLocked();
956
957   if(CORBA::is_nil(theSO))
958     return;
959
960   //Find label
961   TDF_Label aLabel;
962   CORBA::String_var aSOID = theSO->GetID();
963   TDF_Tool::Label(_doc->GetData(), aSOID, aLabel);
964   SALOMEDS_IORAttribute::Set(aLabel, TCollection_ExtendedString((char*)theValue),_study);
965 }