0030773: Application Framework - To allow to inherit existing attributes to reuse...
[occt.git] / src / TDF / TDF_DerivedAttribute.cxx
1 // Copyright (c) 2020 OPEN CASCADE SAS
2 //
3 // This file is part of Open CASCADE Technology software library.
4 //
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
10 //
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
13
14 #include <TDF_DerivedAttribute.hxx>
15
16 #include <NCollection_DataMap.hxx>
17 #include <Standard_Mutex.hxx>
18 #include <TCollection_AsciiString.hxx>
19
20 namespace TDF_DerivedAttributeGlobals
21 {
22
23   //! Data for the derived attribute correct creation
24   struct CreatorData
25   {
26     TDF_DerivedAttribute::NewDerived myCreator;
27     Standard_CString                 myNameSpace;
28     Standard_CString                 myTypeName;
29   };
30
31   //! List that contains the methods that create all registered derived attributes
32   static NCollection_List<CreatorData>& Creators()
33   {
34     static NCollection_List<CreatorData> THE_CREATORS_LIST;
35     return THE_CREATORS_LIST;
36   }
37   //! Global map of the string-type of derived attribute -> instance of such attribute
38   static NCollection_DataMap<Standard_CString, Handle(TDF_Attribute)>& Attributes()
39   {
40     static NCollection_DataMap<Standard_CString, Handle(TDF_Attribute)> THE_DERIVED;
41     return THE_DERIVED;
42   }
43
44   //! Global map of the string-type of derived attribute -> type name to identify this attribute
45   static NCollection_DataMap<Standard_CString, TCollection_AsciiString*>& Types()
46   {
47     static NCollection_DataMap<Standard_CString, TCollection_AsciiString*> THE_DERIVED_TYPES;
48     return THE_DERIVED_TYPES;
49   }
50
51   //! To minimize simultaneous access to global "DERIVED" maps from parallel threads
52   static Standard_Mutex& Mutex()
53   {
54     static Standard_Mutex THE_DERIVED_MUTEX;
55     return THE_DERIVED_MUTEX;
56   }
57 } // namespace TDF_DerivedAttributeGlobals
58
59 //=======================================================================
60 // function : Register
61 // purpose  : Registers a derived by the pointer to a method that creates a new derived attribute instance
62 //=======================================================================
63 TDF_DerivedAttribute::NewDerived TDF_DerivedAttribute::Register (NewDerived       theNewAttributeFunction,
64                                                                  Standard_CString theNameSpace,
65                                                                  Standard_CString theTypeName)
66 {
67   TDF_DerivedAttributeGlobals::CreatorData aData = {theNewAttributeFunction, theNameSpace, theTypeName};
68   Standard_Mutex::Sentry                   aSentry (TDF_DerivedAttributeGlobals::Mutex());
69   TDF_DerivedAttributeGlobals::Creators().Append (aData);
70   return theNewAttributeFunction;
71 }
72
73 //=======================================================================
74 // function : Initialize
75 // purpose  : Checks synchronization and performs initialization of derived attributes maps if needed
76 //=======================================================================
77 static void Initialize()
78 {
79   if (!TDF_DerivedAttributeGlobals::Creators().IsEmpty())
80   { // initialization
81     NCollection_List<TDF_DerivedAttributeGlobals::CreatorData>::Iterator aCreator;
82     for (aCreator.Initialize (TDF_DerivedAttributeGlobals::Creators()); aCreator.More(); aCreator.Next())
83     {
84       Handle(TDF_Attribute) aDerived      = aCreator.Value().myCreator();
85       Standard_CString aDerivedDynamicType = aDerived->DynamicType()->Name();
86
87       TCollection_AsciiString aTypeName;
88       if (aCreator.Value().myNameSpace != NULL)
89       {
90         if (aCreator.Value().myNameSpace[0] != '\0')
91         {
92           aTypeName = aCreator.Value().myNameSpace;
93           aTypeName += ':';
94         }
95       }
96       if (aCreator.Value().myTypeName == NULL)
97       {
98         aTypeName += aDerivedDynamicType;
99       }
100       else
101       {
102         aTypeName += aCreator.Value().myTypeName;
103       }
104
105       // persistent storage of types strings: they are not changed like maps on resize
106       static NCollection_List<TCollection_AsciiString> THE_TYPES_STORAGE;
107       THE_TYPES_STORAGE.Append(aTypeName);
108       TDF_DerivedAttributeGlobals::Types().Bind (aDerivedDynamicType, &(THE_TYPES_STORAGE.Last()));
109       TDF_DerivedAttributeGlobals::Attributes().Bind (aDerivedDynamicType, aDerived);
110     }
111     TDF_DerivedAttributeGlobals::Creators().Clear();
112   }
113 }
114
115 //=======================================================================
116 // function : Attribute
117 // purpose  :
118 //=======================================================================
119 Handle(TDF_Attribute) TDF_DerivedAttribute::Attribute (Standard_CString theType)
120 {
121   Standard_Mutex::Sentry aSentry (TDF_DerivedAttributeGlobals::Mutex());
122   Initialize();
123   if (const Handle(TDF_Attribute)* aResult = TDF_DerivedAttributeGlobals::Attributes().Seek (theType))
124   {
125     return *aResult;
126   }
127
128   static const Handle(TDF_Attribute) aNullAttrib;
129   return aNullAttrib;
130 }
131
132 //=======================================================================
133 // function : TypeName
134 // purpose  :
135 //=======================================================================
136 const TCollection_AsciiString& TDF_DerivedAttribute::TypeName (Standard_CString theType)
137 {
138   Standard_Mutex::Sentry aSentry (TDF_DerivedAttributeGlobals::Mutex());
139   Initialize();
140   if (TCollection_AsciiString *const* aResult = TDF_DerivedAttributeGlobals::Types().Seek (theType))
141   {
142     return **aResult;
143   }
144
145   static const TCollection_AsciiString anEmpty;
146   return anEmpty;
147 }
148
149 //=======================================================================
150 // function : Attributes
151 // purpose  :
152 //=======================================================================
153 void TDF_DerivedAttribute::Attributes (NCollection_List<Handle(TDF_Attribute)>& theList)
154 {
155   Standard_Mutex::Sentry aSentry (TDF_DerivedAttributeGlobals::Mutex());
156   Initialize();
157   NCollection_DataMap<Standard_CString, Handle(TDF_Attribute)>::Iterator anAttrIter;
158   for (anAttrIter.Initialize (TDF_DerivedAttributeGlobals::Attributes()); anAttrIter.More(); anAttrIter.Next())
159   {
160     theList.Append (anAttrIter.Value());
161   }
162 }