Salome HOME
Merge from branch CCRT_Port_V220.
[modules/kernel.git] / src / SALOMEDS / SALOMEDS_SObject_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_SObject_i.cxx
25 //  Author : Yves FRICAUD
26 //  Module : SALOME
27 //  $Header$
28
29 #include <TDF_Tool.hxx>
30 #include <TDF_Attribute.hxx>
31 #include <TDF_Reference.hxx>
32 #include <Standard_GUID.hxx>
33 #include <Standard_NoSuchObject.hxx>
34 #include <TDataStd_Name.hxx>
35 #include <TDataStd_Comment.hxx>
36 #include <TDataStd_Integer.hxx>
37 #include <TDataStd_Real.hxx>
38 #include <TDataStd_TreeNode.hxx>
39 #include <TDataStd_UAttribute.hxx>
40
41 #include <TCollection_AsciiString.hxx>
42 #include <TDF_AttributeIterator.hxx>
43
44 #include "SALOMEDS_SObject_i.hxx"
45
46 //SALOMEDS Headers
47 #include <SALOMEDS.hxx>
48 #include "SALOMEDS_Study_i.hxx"
49 #include "SALOMEDS_StudyManager_i.hxx"
50 #include "SALOMEDS_SComponent_i.hxx"
51
52 #include "SALOMEDS_AttributeComment_i.hxx"
53
54 #include "SALOMEDS_AttributeTreeNode_i.hxx"
55 #include "SALOMEDS_AttributeUserID_i.hxx"
56
57 #include "SALOMEDS_AttributePersistentRef_i.hxx"
58 #include "SALOMEDS_AttributeIOR_i.hxx"
59 #include "SALOMEDS_AttributeExternalFileDef_i.hxx"
60 #include "SALOMEDS_AttributeFileType_i.hxx"
61 #include "SALOMEDS_AttributeName_i.hxx"
62 #include "SALOMEDS_AttributeSequenceOfInteger_i.hxx"
63 #include "SALOMEDS_AttributeSequenceOfReal_i.hxx"
64 #include "SALOMEDS_AttributeTableOfInteger_i.hxx"
65 #include "SALOMEDS_AttributeTableOfReal_i.hxx"
66 #include "SALOMEDS_AttributeTableOfString_i.hxx"
67 #include "SALOMEDS_AttributeInteger_i.hxx"
68 #include "SALOMEDS_AttributeReal_i.hxx"
69 #include "SALOMEDS_AttributeDrawable_i.hxx"
70 #include "SALOMEDS_AttributeSelectable_i.hxx"
71 #include "SALOMEDS_AttributeExpandable_i.hxx"
72 #include "SALOMEDS_AttributeOpened_i.hxx"
73 #include "SALOMEDS_AttributeTextColor_i.hxx"
74 #include "SALOMEDS_AttributeTextHighlightColor_i.hxx"
75 #include "SALOMEDS_AttributePixMap_i.hxx"
76 #include "SALOMEDS_AttributeTarget_i.hxx"
77 #include "SALOMEDS_AttributeLocalID_i.hxx"
78 #include "SALOMEDS_AttributeStudyProperties_i.hxx"
79 #include "SALOMEDS_AttributePythonObject_i.hxx"
80
81 #include "SALOMEDS_AttributeGraphic_i.hxx"
82 #include "SALOMEDS_AttributeFlags_i.hxx"
83
84 #include "Utils_ExceptHandlers.hxx"
85 UNEXPECT_CATCH(GALockProtection, SALOMEDS::GenericAttribute::LockProtection);
86
87 #include "utilities.h"
88
89 using namespace std;
90 using namespace SALOMEDS;
91
92
93 inline bool operator<(const Standard_GUID& theLeft, const Standard_GUID& theRight)
94 {
95   char aLeft[40] = "";
96   theLeft.ToCString(aLeft);
97
98   char aRight[40] = "";
99   theRight.ToCString(aRight);
100   
101   return strcmp(aLeft,aRight) < 0;
102 }
103
104
105 namespace SALOMEDS{
106   const char* Str(const TCollection_ExtendedString& theString)
107   {
108     return TCollection_AsciiString(theString).ToCString();
109   }
110
111   typedef std::string TAttributeID;
112
113   typedef Standard_GUID (*TGetGUID)();
114   typedef bool (*TIsCheckLockedStudy)();
115   typedef Handle(TDF_Attribute) (*TNewAttribute)();
116   typedef SALOMEDS_GenericAttribute_i* (*TNewInstance)(const Handle(TDF_Attribute)&, SALOMEDS_SObject_i*);
117   
118   struct TAttrFun{
119     TAttrFun(const TGetGUID& theGetGUID,
120              const TIsCheckLockedStudy& theIsCheckLockedStudy,
121              const TNewAttribute& theNewAttribute,
122              const TNewInstance& theNewInstance):
123       myGetGUID(theGetGUID),
124       myIsCheckLockedStudy(theIsCheckLockedStudy),
125       myNewAttribute(theNewAttribute),
126       myNewInstance(theNewInstance)
127     {
128     }
129
130     TGetGUID myGetGUID;
131     TIsCheckLockedStudy myIsCheckLockedStudy;
132     TNewAttribute myNewAttribute;
133     TNewInstance myNewInstance;
134   };
135   
136   typedef std::map<TAttributeID,TAttrFun> TAttrID2FunMap;
137   static TAttrID2FunMap __AttrID2FunMap__;
138   
139   
140   typedef std::map<Standard_GUID,TAttributeID> TGUID2AttrIDMap;
141   static TGUID2AttrIDMap __GUID2AttrIDMap__;
142   
143   bool Init()
144   {
145     
146 #define ADD_ATTRID2FUNMAP_ITEM(theName) \
147     __AttrID2FunMap__.insert( \
148       TAttrID2FunMap::value_type(#theName,TAttrFun( \
149         &(SALOMEDS_##theName##_i::GetGUID), \
150         &(SALOMEDS_##theName##_i::IsCheckLockedStudy), \
151         &(SALOMEDS_##theName##_i::NewAttribute), \
152         &(SALOMEDS_##theName##_i::NewInstance) \
153     )))
154                                                        
155     ADD_ATTRID2FUNMAP_ITEM(AttributeName);
156     ADD_ATTRID2FUNMAP_ITEM(AttributeComment); 
157     ADD_ATTRID2FUNMAP_ITEM(AttributeIOR);
158     ADD_ATTRID2FUNMAP_ITEM(AttributeReal);
159     ADD_ATTRID2FUNMAP_ITEM(AttributeInteger);
160     ADD_ATTRID2FUNMAP_ITEM(AttributeSequenceOfInteger);
161     ADD_ATTRID2FUNMAP_ITEM(AttributeSequenceOfReal);
162     ADD_ATTRID2FUNMAP_ITEM(AttributeTableOfInteger);
163     ADD_ATTRID2FUNMAP_ITEM(AttributeTableOfReal);
164     ADD_ATTRID2FUNMAP_ITEM(AttributeTableOfString);
165     ADD_ATTRID2FUNMAP_ITEM(AttributeLocalID);
166     ADD_ATTRID2FUNMAP_ITEM(AttributePythonObject);
167     
168     ADD_ATTRID2FUNMAP_ITEM(AttributeUserID);
169     ADD_ATTRID2FUNMAP_ITEM(AttributeTreeNode);
170
171     ADD_ATTRID2FUNMAP_ITEM(AttributePersistentRef);
172     ADD_ATTRID2FUNMAP_ITEM(AttributeDrawable);
173     ADD_ATTRID2FUNMAP_ITEM(AttributeSelectable);
174     ADD_ATTRID2FUNMAP_ITEM(AttributeExpandable);
175     ADD_ATTRID2FUNMAP_ITEM(AttributeOpened);
176     ADD_ATTRID2FUNMAP_ITEM(AttributeTextColor);
177     ADD_ATTRID2FUNMAP_ITEM(AttributeTextHighlightColor);
178     ADD_ATTRID2FUNMAP_ITEM(AttributePixMap);
179     ADD_ATTRID2FUNMAP_ITEM(AttributeTarget);
180     ADD_ATTRID2FUNMAP_ITEM(AttributeStudyProperties);
181     ADD_ATTRID2FUNMAP_ITEM(AttributeExternalFileDef);
182     ADD_ATTRID2FUNMAP_ITEM(AttributeFileType);
183
184     ADD_ATTRID2FUNMAP_ITEM(AttributeGraphic);
185     ADD_ATTRID2FUNMAP_ITEM(AttributeFlags);
186
187     TAttrID2FunMap::const_iterator anIter = __AttrID2FunMap__.begin();
188     TAttrID2FunMap::const_iterator anEnd = __AttrID2FunMap__.end();
189     for(; anIter != anEnd; anIter++){
190       const TAttrID2FunMap::key_type& aKey = anIter->first;
191       const TAttrID2FunMap::mapped_type& aValue = anIter->second;
192       __GUID2AttrIDMap__[aValue.myGetGUID()] = aKey;
193     };
194
195 #undef ADD_ATTRID2FUNMAP_ITEM
196     return true;
197   }
198   
199
200   static bool __IsInitilized__ = Init();
201
202
203   //============================================================================
204   bool GetAttrFun(const Standard_GUID& theGUID, TAttrFun& theAttrFun)
205   {
206     TGUID2AttrIDMap::const_iterator anIter = __GUID2AttrIDMap__.find(theGUID);
207     if(anIter != __GUID2AttrIDMap__.end())
208     {
209       const TAttributeID& anAttributeID = anIter->second;
210       TAttrID2FunMap::const_iterator anIter2 = __AttrID2FunMap__.find(anAttributeID);
211       if(anIter2 != __AttrID2FunMap__.end())
212       {
213         theAttrFun = anIter2->second;
214         return true;
215       }
216     }
217     return false;
218   }
219
220
221   //============================================================================
222   Standard_GUID GetGUID(const char* theType)
223   {
224     TAttrID2FunMap::const_iterator anIter = __AttrID2FunMap__.find(theType);
225     if(anIter != __AttrID2FunMap__.end()){
226       const TAttrID2FunMap::mapped_type& aValue = anIter->second;
227       return aValue.myGetGUID();
228     }
229     // create tree node GUID by name
230     if(strncmp(theType,"AttributeTreeNodeGUID",21) == 0){
231       char aGUIDString[40] = "";
232       sprintf(aGUIDString,&theType[21]);
233       return aGUIDString;
234     }
235     
236     return Standard_GUID();
237   }
238
239
240   //============================================================================
241   std::string GetType(const Handle(TDF_Attribute)& theAttr)
242   {
243     if(theAttr.IsNull())
244       return CORBA::string_dup("");
245     
246     Standard_GUID aGUID = theAttr->ID();
247     TGUID2AttrIDMap::const_iterator anIter = __GUID2AttrIDMap__.find(aGUID);
248     if(anIter != __GUID2AttrIDMap__.end())
249     {
250       const TAttributeID& anAttributeID = anIter->second;
251       return anAttributeID;
252     }
253     
254     char aType[60] = "";
255     {
256       Handle(TDataStd_TreeNode) anAttr = Handle(TDataStd_TreeNode)::DownCast(theAttr);
257       if (!anAttr.IsNull()) {
258         char aGUID[40] = "";
259         anAttr->ID().ToCString(aGUID);
260         sprintf(aType, "AttributeTreeNodeGUID%s",aGUID);
261         return aType;
262       }
263     }
264     {
265       Handle(TDataStd_UAttribute) anAttr = Handle(TDataStd_UAttribute)::DownCast(theAttr);
266       if (!anAttr.IsNull()) {
267         char aGUID[40] = "";
268         anAttr->ID().ToCString(aGUID);
269         sprintf(aType, "AttributeUserID_%s",aGUID); 
270         return aType;
271       }
272     }
273     return aType;
274   }
275   
276 }  
277
278 //static SALOMEDS::Mutex SObjMutex;
279   
280 //============================================================================
281 SALOMEDS_Study_i::TSObjectHolder
282 SALOMEDS_SObject_i::New(SALOMEDS_Study_i* theStudy,
283                         const TDF_Label& theLabel)
284 {
285   SALOMEDS_Study_i::TSObjectHolder aSObjectHolder;
286   SALOMEDS_Study_i::TSObjectMap& anSObjectMap = theStudy->GetSObjectMap();
287   SALOMEDS_Study_i::TSObjectMap::const_iterator anIter = anSObjectMap.find(theLabel);
288   if(anIter != anSObjectMap.end())
289     aSObjectHolder = anIter->second;
290   else{
291     SALOMEDS_SObject_i* aSObject = new SALOMEDS_SObject_i(theStudy,theLabel);
292     aSObjectHolder.first = aSObject;
293     aSObjectHolder.second = aSObject->_this();
294     anSObjectMap[theLabel] = aSObjectHolder;
295
296     //TCollection_AsciiString anEntry;
297     //TDF_Tool::Entry(theLabel,anEntry);
298     //cout<<"APO - SALOMEDS_SObject_i::New - anEntry = "<<anEntry.ToCString()<<endl;
299   }
300   return aSObjectHolder;
301 }
302
303 SALOMEDS_SObject_i*
304 SALOMEDS_SObject_i::NewPtr(SALOMEDS_Study_i* theStudy,
305                            const TDF_Label& theLabel)
306 {
307   return New(theStudy,theLabel).first;
308 }
309
310 SALOMEDS::SObject_var
311 SALOMEDS_SObject_i::NewRef(SALOMEDS_Study_i* theStudy,
312                            const TDF_Label& theLabel)
313 {
314   return New(theStudy,theLabel).second;
315 }
316
317 //============================================================================
318 /*! Function : constructor
319  *  Purpose  : 
320  */
321 //============================================================================
322 SALOMEDS_SObject_i::SALOMEDS_SObject_i(SALOMEDS_Study_i* theStudy,
323                                        const TDF_Label& theLabel):
324   _lab(theLabel),
325   _study(theStudy)
326 {
327 }
328
329 //============================================================================
330 /*! Function : destructor
331  *  Purpose  : 
332  */
333 //============================================================================
334 SALOMEDS_SObject_i::~SALOMEDS_SObject_i()
335 {
336 }
337   
338
339 //============================================================================
340 CORBA::ORB_var SALOMEDS_SObject_i::GetORB() const
341 {
342   return _study->GetORB();
343 }
344
345
346 //============================================================================
347 PortableServer::POA_var SALOMEDS_SObject_i::GetPOA() const
348 {
349   return _study->GetPOA();
350 }
351
352
353 //============================================================================
354 /*! Function :
355  *  Purpose  : 
356  */
357 //============================================================================
358 char* SALOMEDS_SObject_i::GetID()
359 {
360   Locker lock;
361
362   TCollection_AsciiString anEntry;
363   TDF_Tool::Entry(_lab,anEntry);
364   return CORBA::string_dup(anEntry.ToCString());
365 }
366   
367 //============================================================================
368 /*! Function :
369  *  Purpose  : 
370  */
371 //============================================================================
372 TDF_Label SALOMEDS_SObject_i::GetFatherComponentLabel()
373 {
374   TDF_Label aLabel = _lab;
375   while(!SALOMEDS_SComponent_i::IsA(aLabel) && !aLabel.IsRoot())
376     aLabel = aLabel.Father();
377
378   return aLabel;
379 }
380
381 SALOMEDS::SComponent_ptr SALOMEDS_SObject_i::GetFatherComponent()
382 {
383   Locker lock;
384
385   TDF_Label aSCompLabel = GetFatherComponentLabel();
386
387   return SALOMEDS_SComponent_i::NewRef(_study,aSCompLabel)._retn();
388 }
389   
390 //============================================================================
391 /*! Function :
392  *  Purpose  : 
393  */
394 //============================================================================
395 SALOMEDS::SObject_ptr SALOMEDS_SObject_i::GetFather()
396 {
397   Locker lock;
398
399   return SALOMEDS_SObject_i::NewRef(_study,_lab.Father())._retn();
400 }
401
402 //============================================================================
403 /*! Function :
404  *  Purpose  : 
405  */
406 //============================================================================
407 SALOMEDS::Study_ptr SALOMEDS_SObject_i::GetStudy()
408 {
409   return _study->_this();
410 }
411
412 //============================================================================
413 /*! Function : ReferencedObject
414  *  Purpose  : 
415  */
416 //============================================================================
417 CORBA::Boolean SALOMEDS_SObject_i::ReferencedObject(SALOMEDS::SObject_out theSObject)
418 {
419   Locker lock;
420
421   Handle(TDF_Reference) aRef;
422   if (!_lab.FindAttribute(TDF_Reference::GetID(),aRef))
423     return false;
424   
425   theSObject = SALOMEDS_SObject_i::NewRef(_study,aRef->Get())._retn(); 
426   return true;
427 }
428
429 //============================================================================
430 /*! Function :
431  *  Purpose  : 
432  */
433 //============================================================================
434 CORBA::Boolean SALOMEDS_SObject_i::FindSubObject(CORBA::Long theTag, SALOMEDS::SObject_out theSObject)
435 {
436   Locker lock;
437
438   TDF_Label aLabel = _lab.FindChild(theTag,false);
439   if(aLabel.IsNull()) 
440     return false;
441   
442   theSObject = SALOMEDS_SObject_i::NewRef(_study,aLabel)._retn(); 
443   return true;
444 }  
445
446 //============================================================================
447 /*! Function :
448  *  Purpose  : 
449  */
450 //============================================================================
451 char* SALOMEDS_SObject_i::Name()
452 {
453   Locker lock;
454
455   return CORBA::string_dup(_name.c_str());
456 }
457   
458 //============================================================================
459 /*! Function :
460  *  Purpose  : 
461  */
462 //============================================================================
463 void  SALOMEDS_SObject_i::Name(const char* theName)
464 {
465   Locker lock;
466
467   _name = theName;
468 }
469   
470 //============================================================================
471 /*! Function :
472  *  Purpose  : 
473  */
474 //============================================================================
475 CORBA::Short SALOMEDS_SObject_i::Tag()
476 {
477   Locker lock;
478
479   return _lab.Tag();
480 }
481
482 //============================================================================
483 /*! Function :
484  *  Purpose  : 
485  */
486 //============================================================================
487 CORBA::Short SALOMEDS_SObject_i::Depth()
488 {
489   Locker lock;
490
491   return _lab.Depth();
492 }
493
494 //============================================================================
495 /*! Function :
496  *  Purpose  : 
497  */
498 //============================================================================
499 CORBA::Object_ptr SALOMEDS_SObject_i::GetObject()
500 {
501   Locker lock;
502
503   try {
504     Handle(SALOMEDS_IORAttribute) anAttr;
505     if(_lab.FindAttribute(SALOMEDS_IORAttribute::GetID(),anAttr)){
506       CORBA::ORB_var anORB = _study->GetStudyManager()->GetORB();
507       return anORB->string_to_object(Str(anAttr->Get()));
508     }
509   }catch(...){
510   }
511   return CORBA::Object::_nil();
512 }
513
514 //============================================================================
515 /*! Function :
516  *  Purpose  : 
517  */
518 //============================================================================
519 char* SALOMEDS_SObject_i::GetName() {
520   Locker lock;
521
522   Handle(TDataStd_Name) anAttr;
523   if(_lab.FindAttribute(TDataStd_Name::GetID(),anAttr))
524     return CORBA::string_dup(Str(anAttr->Get()));
525
526   return CORBA::string_dup("");
527 }
528
529 //============================================================================
530 /*! Function :
531  *  Purpose  : 
532  */
533 //============================================================================
534 char* SALOMEDS_SObject_i::GetComment() {
535   Locker lock;
536
537   Handle(TDataStd_Comment) anAttr;
538   if(_lab.FindAttribute(TDataStd_Comment::GetID(), anAttr))
539     return CORBA::string_dup(Str(anAttr->Get()));
540
541   return CORBA::string_dup("");
542 }
543
544 //============================================================================
545 /*! Function :
546  *  Purpose  : 
547  */
548 //============================================================================
549 char* SALOMEDS_SObject_i::GetIOR() {
550   Locker lock;
551
552   Handle(SALOMEDS_IORAttribute) anAttr;
553   if(_lab.FindAttribute(SALOMEDS_IORAttribute::GetID(),anAttr))
554     return CORBA::string_dup(Str(anAttr->Get()));
555
556   return CORBA::string_dup("");
557 }
558
559
560 //============================================================================
561 /*! Function : GetAllAttributes
562  *  Purpose  : Returns list of all attributes for this sobject
563  */
564 //============================================================================
565 SALOMEDS_SObject_i::TAttrHolder 
566 SALOMEDS_SObject_i::_FindGenAttribute(const Handle(TDF_Attribute)& theAttr)
567 {
568   std::string aType = GetType(theAttr);
569   return _FindGenAttribute(aType.c_str());
570 }
571
572
573 SALOMEDS::ListOfAttributes* SALOMEDS_SObject_i::GetAllAttributes()
574 {
575   Locker lock;
576
577   SALOMEDS::ListOfAttributes_var aSeqOfAttr = new SALOMEDS::ListOfAttributes;
578   if(_lab.NbAttributes() > 0){
579     Standard_Integer i = 0;
580     for(TDF_AttributeIterator iter(_lab); iter.More(); iter.Next()) {
581       Handle(TDF_Attribute) anAttr = iter.Value();
582       TAttrHolder anAttrHolder = _FindGenAttribute(anAttr);
583       SALOMEDS::GenericAttribute_var anGenAttr = anAttrHolder.second;
584       if(!anGenAttr->_is_nil())
585       {
586         aSeqOfAttr->length(++i);
587         aSeqOfAttr[i-1] = anGenAttr._retn();
588       }
589     }
590   }
591
592   return aSeqOfAttr._retn();
593 }
594
595
596 //============================================================================
597 /*! Function : FindAttribute
598  *  Purpose  : Find attribute of given type on this SObject
599  */
600 //============================================================================
601 SALOMEDS_SObject_i::TAttrHolder 
602 SALOMEDS_SObject_i::_CreateGenAttribute(const Handle(TDF_Attribute)& theAttr,
603                                         const char* theType) 
604 {
605   SALOMEDS_GenericAttribute_i* anAttr;
606   TAttrID2FunMap::const_iterator anIter = __AttrID2FunMap__.find(theType);
607   if(anIter != __AttrID2FunMap__.end()){
608     const TAttrID2FunMap::mapped_type& aValue = anIter->second;
609     
610     //if(aValue.myIsCheckLockedStudy()) // mpv 03.02.05: creation of CORBA objects does not modify the study
611     //  _study->CheckLocked();
612     
613     anAttr = aValue.myNewInstance(theAttr,this);
614     return TAttrHolder(anAttr,anAttr->_this());
615   }
616   
617   if(strncmp(theType,"AttributeTreeNode",17) == 0){
618     anAttr = new SALOMEDS_AttributeTreeNode_i(theAttr,this);
619     return TAttrHolder(anAttr,anAttr->_this());
620   }
621   
622   if(strncmp(theType,"AttributeUserID",15) == 0){
623     anAttr =  new SALOMEDS_AttributeUserID_i(theAttr,this);
624     return TAttrHolder(anAttr,anAttr->_this());
625   }
626   
627   return TAttrHolder();
628 }
629
630
631 SALOMEDS_SObject_i::TAttrHolder 
632 SALOMEDS_SObject_i::_FindGenAttribute(const char* theType)
633 {
634   TAttrHolder anAttrHolder;
635   TAttrMap::const_iterator anIter = myAttrMap.find(theType);
636   if(anIter != myAttrMap.end())
637     anAttrHolder = anIter->second;
638
639   Standard_GUID aGUID = ::GetGUID(theType);
640   Handle(TDF_Attribute) anAttr;
641
642   if(_lab.FindAttribute(aGUID,anAttr)){
643     SALOMEDS_GenericAttribute_i* aGenAttr = anAttrHolder.first;
644     if(aGenAttr != NULL){
645       if(aGenAttr->GetAttribute() != anAttr)
646         aGenAttr->SetAttribute(anAttr);
647     }else{
648       anAttrHolder = _CreateGenAttribute(anAttr,theType);
649     }
650     aGenAttr = anAttrHolder.first;
651     if(aGenAttr != NULL)
652       myAttrMap[theType] = anAttrHolder;
653   }else{
654     //myAttrMap.erase(theType);
655     //if(anGenAttr != NULL)
656     //  anGenAttr->Destroy();
657     return TAttrHolder();
658   }
659
660   return anAttrHolder;
661 }
662
663
664 CORBA::Boolean 
665 SALOMEDS_SObject_i::FindAttribute(SALOMEDS::GenericAttribute_out theAttribute, 
666                                   const char* theType)
667 {
668   Locker lock;
669
670   TAttrHolder anAttr = _FindGenAttribute(theType);
671   SALOMEDS::GenericAttribute_var anGenAttr = anAttr.second;
672   if(!CORBA::is_nil(anGenAttr)){
673     theAttribute = SALOMEDS::GenericAttribute::_duplicate(anGenAttr);
674     return true;
675   }
676   return false;
677 }
678
679
680 //============================================================================
681 /*! Function : FindAttribute
682  *  Purpose  : Find attribute of given type on this SObject
683  */
684 //============================================================================
685 Handle(TDF_Attribute) 
686   SALOMEDS_SObject_i::_AddAttribute(const char* theType) 
687 {
688   Handle(TDF_Attribute) anAttr;
689   TAttrID2FunMap::const_iterator anIter = __AttrID2FunMap__.find(theType);
690   if(anIter != __AttrID2FunMap__.end()){
691     const TAttrID2FunMap::mapped_type& aValue = anIter->second;
692     
693     if(aValue.myIsCheckLockedStudy())
694       _study->CheckLocked();
695     
696     anAttr = aValue.myNewAttribute();
697     _lab.AddAttribute(anAttr);
698     return anAttr;
699   }
700   
701   if(strncmp(theType, "AttributeTreeNode",17) == 0){
702     Standard_GUID aGUID;
703     if(strcmp(theType, "AttributeTreeNode") == 0){
704       aGUID = TDataStd_TreeNode::GetDefaultTreeID();
705     }else{
706       char aString[40] = "";
707       sprintf(aString, &theType[21]);
708       aGUID = Standard_GUID(aString); // create tree node GUID by name
709     }
710     if(!_lab.FindAttribute(aGUID,anAttr)){
711       _study->CheckLocked();
712       anAttr = TDataStd_TreeNode::Set(_lab,aGUID);
713       return anAttr;
714     }
715   }
716   
717   if(strncmp(theType, "AttributeUserID",15) == 0){
718     Standard_GUID aGUID = SALOMEDS_AttributeUserID_i::GetGUID();
719     if(!_lab.FindAttribute(aGUID,anAttr)){
720       _study->CheckLocked();
721       anAttr = TDataStd_UAttribute::Set(_lab,aGUID);
722       return anAttr;
723     }
724   }
725   
726   
727   return anAttr;
728 }
729
730
731 SALOMEDS::GenericAttribute_ptr 
732 SALOMEDS_SObject_i::FindOrCreateAttribute(const char* theType)
733 {
734   Locker lock;
735
736   TAttrHolder anAttrHolder = _FindGenAttribute(theType);
737   SALOMEDS::GenericAttribute_var anGenAttr = anAttrHolder.second;
738   if(!anGenAttr->_is_nil())
739     return anGenAttr._retn();
740
741   Handle(TDF_Attribute) anAttr = _AddAttribute(theType);
742   if(!anAttr.IsNull()){
743     anAttrHolder = _CreateGenAttribute(anAttr,theType);
744     anGenAttr = anAttrHolder.second;
745     if(!anGenAttr->_is_nil())
746       return anGenAttr._retn();
747   }
748
749   return SALOMEDS::GenericAttribute::_nil();
750 }
751
752
753 //============================================================================
754 /*! Function : FindAttribute
755  *  Purpose  : Find attribute of given type on this SObject
756  */
757 //============================================================================
758 void SALOMEDS_SObject_i::RemoveAttribute(const char* theType)
759 {
760   Locker lock;
761
762   _study->CheckLocked();
763   if(strcmp(theType, "AttributeIOR") == 0) { // postponed removing of CORBA objects
764     Handle(SALOMEDS_IORAttribute) anAttr;
765     if(_lab.FindAttribute(SALOMEDS_IORAttribute::GetID(), anAttr))
766       _study->AddPostponed(Str(anAttr->Get()));
767     else 
768       return;
769   }
770   TAttrMap::iterator anIter = myAttrMap.find(theType);
771   if(anIter != myAttrMap.end()){
772     //myAttrMap.erase(anIter);
773   }
774   _lab.ForgetAttribute(::GetGUID(theType));
775 }
776
777
778 void SALOMEDS_SObject_i::OnRemove()
779 {
780   Handle(TDF_Reference) aReference;
781   if(_lab.FindAttribute(TDF_Reference::GetID(),aReference)){
782     Handle(SALOMEDS_TargetAttribute) aTarget;
783     if(aReference->Get().FindAttribute(SALOMEDS_TargetAttribute::GetID(),aTarget))
784       aTarget->Remove(_lab);
785   }
786
787   Handle(SALOMEDS_IORAttribute) anAttr; // postponed removing of CORBA objects
788   if(_lab.FindAttribute(SALOMEDS_IORAttribute::GetID(),anAttr)){
789     _study->AddPostponed(TCollection_AsciiString(anAttr->Get()).ToCString());
790   }
791
792   //myAttrMap.clear();
793
794   //SALOMEDS_Study_i::TSObjectMap& anSObjectMap = _study->GetSObjectMap();
795   //anSObjectMap.erase(_lab);
796 }