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