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