HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
APEX_CompatibilityMap.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * NAME: APEX_CompatibilityMap.h (APEX Library, C++)
7  *
8  * COMMENTS: Implements the compatibility map used by APEX_Registry.
9  * The map stores name changes, as well as various update
10  * actions to make limited backwards compatible changes to a type
11  * (without needing to create a new incremented namespace version).
12  * It shares some similarities to the internal versioning of HDAs,
13  * with the update actions playing the role of the SyncNodeVersion
14  * script.
15  */
16 
17 #ifndef __APEX_COMPATIBILITYMAP_H__
18 #define __APEX_COMPATIBILITYMAP_H__
19 
20 #include "APEX_API.h"
21 #include "APEX_Callback.h"
22 
23 #include <UT/UT_Array.h>
24 #include <UT/UT_Assert.h>
25 #include <UT/UT_ErrorManager.h>
26 #include <UT/UT_StringHolder.h>
27 #include <UT/UT_UniquePtr.h>
28 #include <SYS/SYS_Types.h>
29 
30 class UT_IStream;
31 class UT_StringArray;
32 
33 namespace apex
34 {
35 
36 class APEX_Graph;
37 
38 
39 /// APEX_CompatibilityMap tracks backwards compatible transformations to
40 /// callback and subgraph node types.
41 ///
42 /// The map is stored in json format with the following schema:
43 ///
44 /// "oldname" : {
45 /// "remap" : ["newname", "oldname start version", "newname start version"],
46 /// "updates" : {
47 /// "product version string": [
48 /// [ "renameport", "old[in]", "new" ],
49 /// [ "renameport", "mesh[out]", "geo" ],
50 /// [ "insertport", "name[in]", 2 ],
51 /// [ "moveport", "success[out]", -1 ]
52 /// ],
53 /// "21.0.20": [
54 /// [ "insertport", "value[in]", 2 ]
55 /// ]
56 /// }
57 /// }
58 ///
59 /// Users do not need to provide the "update" or "remap" entries if it is not
60 /// applicable to their type.
61 ///
63 {
64 public:
67 
68  /// Loads the json representation of the compatibility map.
69  bool load(UT_IStream &is);
70  bool load(const char *filepath);
71 
72  /// Returns the current name associated with @a name at @a version.
73  /// When @a name is not found in the compatibility map, the empty string is
74  /// returned. When @a version is null, the current name is always returned.
75  /// In most scenarios, this function should be called with a null @a
76  /// version argument in order to find the current name of the node. The
77  /// version is useful for tracking the history of a name for the purpose of
78  /// creating a set of candidate nodes at a particular version (e.g. deciding
79  /// which namespace versioned nodes existed at a particular product version
80  /// so that their precedence order can be reconstructed at that version).
81  /// When version is "", it is interpreted as version "0".
82  const UT_StringHolder &findName(
83  const UT_StringRef &name,
84  const char *version = nullptr) const;
85 
86  /// Returns the keys of the compatibility map which were current node types
87  /// at @a version. If a version is not provided, then all keys are returned.
88  /// When version is "", it is interpreted as version "0".
89  UT_StringArray getKeys(const char *version = nullptr) const;
90 
91  class CompatibilityResolver;
92 
93  /// Creates a Resolver which builds a mapping from the type definition
94  /// of @a name at @a version to its current type @a nodetype. If @a version
95  /// is an empty string, then it is assumed to be the original version and
96  /// all compatibility entries are used.
97  template <typename NodeTypeT>
98  UT_UniquePtr<CompatibilityResolver> createCompatibilityResolver(
99  const UT_StringRef &name,
100  const UT_StringRef &version,
101  const NodeTypeT &nodetype) const;
102 
103 private:
104  class Impl;
105  UT_UniquePtr<Impl> myImpl;
106 };
107 
108 /// A CompatibilityResolver builds the mapping between an old type
109 /// definition and a new type definition based on the updates recorded in a
110 /// compatibility map.
111 class APEX_API APEX_CompatibilityMap::CompatibilityResolver
112 {
113 public:
114  const UT_StringHolder &oldName() const { return myOldName; }
115  const UT_StringHolder &newName() const { return myNewName; }
116 
117  const APEX_Signature &oldSignature() const { return myOldSig; }
118  const APEX_Signature &newSignature() const { return myNewSig; }
119 
120  exint numInputs() const { return myInputMap.size(); };
121  exint numOutputs() const { return myOutputMap.size(); };
122 
123  /// @name InputPortMappings
124  /// Functions to map input ports from the old signature to the new
125  /// signature.
126  /// @{
127  exint inputIndex(exint old_index) const;
128  exint inputIndex(const UT_StringRef &old_name) const;
129  const UT_StringHolder &inputName(exint old_index) const;
130  const UT_StringHolder &inputName(const UT_StringRef &old_name) const;
131  /// @}
132 
133  /// @name OutputPortMappings
134  /// Functions to map output ports from the old signature to the new
135  /// signature.
136  /// @{
137  exint outputIndex(exint old_index) const;
138  exint outputIndex(const UT_StringRef &old_name) const;
139  const UT_StringHolder &outputName(exint old_index) const;
140  const UT_StringHolder &outputName(const UT_StringRef &old_name) const;
141  /// @}
142 
143  /// Returns false if the resolver encountered an error. Errors can be
144  /// retrieved with errorManager().
145  bool isValid() const { return myIsValid; }
146 
147  /// Returns the error manager.
148  UT_ErrorManager &errorManager() { return myErrMgr; }
149 
150 private:
151  struct PassKey{};
152 
153 public:
154  CompatibilityResolver(
155  const UT_StringRef &name,
156  const UT_StringRef &version,
157  const APEX_FunctionBase &callback,
158  const APEX_CompatibilityMap &map,
159  const PassKey &);
160 
161  CompatibilityResolver(
162  const UT_StringRef &name,
163  const UT_StringRef &version,
164  const APEX_Graph &subgraph,
165  const APEX_CompatibilityMap &map,
166  const PassKey &);
167 
168 private:
169  friend class APEX_CompatibilityMap;
170 
171  bool resolve(
172  const UT_StringRef &name,
173  const UT_StringRef &version,
174  const UT_StringRef &min_version,
175  const APEX_CompatibilityMap &map);
176 
177  bool myIsValid = true;
178  UT_StringHolder myOldName;
179  UT_StringHolder myNewName;
180  APEX_Signature myOldSig;
181  APEX_Signature myNewSig;
182  UT_Array<exint> myInputMap;
183  UT_Array<exint> myOutputMap;
184  UT_ErrorManager myErrMgr;
185 };
186 
187 
188 //
189 // APEX_CompatibilityMap
190 //
191 template <typename NodeTypeT>
194  const UT_StringRef &name,
195  const UT_StringRef &version,
196  const NodeTypeT &nodetype) const
197 {
198  return UTmakeUnique<CompatibilityResolver>(
199  name, version, nodetype, *this, CompatibilityResolver::PassKey());
200 }
201 
202 //
203 // APEX_CompatibilityMap::CompatibilityResolver
204 //
205 inline exint
206 APEX_CompatibilityMap::CompatibilityResolver::inputIndex(exint old_index) const
207 {
208  UT_ASSERT(myIsValid);
209  UT_ASSERT(old_index >= 0 && old_index < myInputMap.size());
210  return myInputMap[old_index];
211 }
212 
213 inline exint
214 APEX_CompatibilityMap::CompatibilityResolver::inputIndex(
215  const UT_StringRef &old_name) const
216 {
217  const exint old_index = myOldSig.findInputIndex(old_name);
218  return inputIndex(old_index);
219 }
220 
221 inline const UT_StringHolder &
222 APEX_CompatibilityMap::CompatibilityResolver::inputName(exint old_index) const
223 {
224  const exint new_index = inputIndex(old_index);
225  return myNewSig.myInputs[new_index].name();
226 }
227 
228 inline const UT_StringHolder &
229 APEX_CompatibilityMap::CompatibilityResolver::inputName(
230  const UT_StringRef &old_name) const
231 {
232  const exint new_index = inputIndex(old_name);
233  return myNewSig.myInputs[new_index].name();
234 }
235 
236 inline exint
237 APEX_CompatibilityMap::CompatibilityResolver::outputIndex(
238  exint old_index) const
239 {
240  UT_ASSERT(myIsValid);
241  UT_ASSERT(old_index >= 0 && old_index < myOutputMap.size());
242  return myOutputMap[old_index];
243 }
244 
245 inline exint
246 APEX_CompatibilityMap::CompatibilityResolver::outputIndex(
247  const UT_StringRef &old_name) const
248 {
249  const exint old_index = myOldSig.findOutputIndex(old_name);
250  return outputIndex(old_index);
251 }
252 
253 inline const UT_StringHolder &
254 APEX_CompatibilityMap::CompatibilityResolver::outputName(exint old_index) const
255 {
256  const exint new_index = outputIndex(old_index);
257  return myNewSig.myOutputs[new_index].name();
258 }
259 
260 inline const UT_StringHolder &
261 APEX_CompatibilityMap::CompatibilityResolver::outputName(
262  const UT_StringRef &old_name) const
263 {
264  const exint new_index = outputIndex(old_name);
265  return myNewSig.myOutputs[new_index].name();
266 }
267 
268 } // namespace apex
269 
270 #endif //__APEX_COMPATIBILITYMAP_H__
UT_UniquePtr< CompatibilityResolver > createCompatibilityResolver(const UT_StringRef &name, const UT_StringRef &version, const NodeTypeT &nodetype) const
#define APEX_API
Definition: APEX_API.h:21
int64 exint
Definition: SYS_Types.h:125
const APEX_Signature & oldSignature() const
std::unique_ptr< T, Deleter > UT_UniquePtr
A smart pointer for unique ownership of dynamically allocated objects.
Definition: UT_UniquePtr.h:39
const UT_StringHolder & oldName() const
GLuint const GLchar * name
Definition: glcorearb.h:786
UT_ErrorManager & errorManager()
Returns the error manager.
GT_API const UT_StringHolder version
A global error manager scope.
const APEX_Signature & newSignature() const
#define UT_ASSERT(ZZ)
Definition: UT_Assert.h:156
const UT_StringHolder & newName() const