HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
registry.h
Go to the documentation of this file.
1 //
2 // Copyright 2018 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 // names, trademarks, service marks, or product names of the Licensor
11 // and its affiliates, except as required to comply with Section 4(c) of
12 // the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 // http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24 
25 #ifndef PXR_USD_NDR_REGISTRY_H
26 #define PXR_USD_NDR_REGISTRY_H
27 
28 /// \file ndr/registry.h
29 
30 #include "pxr/pxr.h"
31 #include "pxr/usd/ndr/api.h"
32 #include "pxr/base/tf/singleton.h"
33 #include "pxr/base/tf/weakBase.h"
34 #include "pxr/usd/ndr/declare.h"
36 #include "pxr/usd/ndr/node.h"
39 #include "pxr/usd/sdf/assetPath.h"
40 
42 
43 /// \class NdrRegistry
44 ///
45 /// The registry provides access to node information. "Discovery Plugins" are
46 /// responsible for finding the nodes that should be included in the registry.
47 ///
48 /// Discovery plugins are found through the plugin system. If additional
49 /// discovery plugins need to be specified, a client can pass them to
50 /// `SetExtraDiscoveryPlugins()`.
51 ///
52 /// When the registry is first told about the discovery plugins, the plugins
53 /// will be asked to discover nodes. These plugins will generate
54 /// `NdrNodeDiscoveryResult` instances, which only contain basic metadata. Once
55 /// the client asks for information that would require the node's contents to
56 /// be parsed (eg, what its inputs and outputs are), the registry will begin the
57 /// parsing process on an as-needed basis. See `NdrNodeDiscoveryResult` for the
58 /// information that can be retrieved without triggering a parse.
59 ///
60 /// Some methods in this library may allow for a "family" to be provided. A
61 /// family is simply a generic grouping which is optional.
62 ///
63 class NdrRegistry : public TfWeakBase
64 {
65 public:
66  using DiscoveryPluginRefPtrVec = NdrDiscoveryPluginRefPtrVector;
67 
68  /// Get the single `NdrRegistry` instance.
69  NDR_API
70  static NdrRegistry& GetInstance();
71 
72  /// Allows the client to set any additional discovery plugins that would
73  /// otherwise NOT be found through the plugin system. Runs the discovery
74  /// process for the specified plugins immediately.
75  ///
76  /// Note that this method cannot be called after any nodes in the registry
77  /// have been parsed (eg, through GetNode*()), otherwise an error will
78  /// result.
79  NDR_API
81 
82  /// Allows the client to set any additional discovery plugins that would
83  /// otherwise NOT be found through the plugin system. Runs the discovery
84  /// process for the specified plugins immediately.
85  ///
86  /// Note that this method cannot be called after any nodes in the registry
87  /// have been parsed (eg, through GetNode*()), otherwise an error will
88  /// result.
89  NDR_API
90  void SetExtraDiscoveryPlugins(const std::vector<TfType>& pluginTypes);
91 
92  /// Allows the client to set any additional parser plugins that would
93  /// otherwise NOT be found through the plugin system.
94  ///
95  /// Note that this method cannot be called after any nodes in the registry
96  /// have been parsed (eg, through GetNode*()), otherwise an error will
97  /// result.
98  NDR_API
99  void SetExtraParserPlugins(const std::vector<TfType>& pluginTypes);
100 
101  /// Parses the given \p asset, constructs a NdrNode from it and adds it to
102  /// the registry.
103  ///
104  /// Nodes created from an asset using this API can be looked up by the
105  /// unique identifier and sourceType of the returned node, or by URI,
106  /// which will be set to the unresolved asset path value.
107  ///
108  /// \p metadata contains additional metadata needed for parsing and
109  /// compiling the source code in the file pointed to by \p asset correctly.
110  /// This metadata supplements the metadata available in the asset and
111  /// overrides it in cases where there are key collisions.
112  ///
113  /// \p subidentifier is optional, and it would be used to indicate a
114  /// particular definition in the asset file if the asset contains multiple
115  /// node definitions.
116  ///
117  /// \p sourceType is optional, and it is only needed to indicate a
118  /// particular type if the asset file is capable of representing a node
119  /// definition of multiple source types.
120  ///
121  /// Returns a valid node if the asset is parsed successfully using one
122  /// of the registered parser plugins.
123  NDR_API
125  const NdrTokenMap &metadata,
126  const TfToken &subIdentifier=TfToken(),
127  const TfToken &sourceType=TfToken());
128 
129  /// Parses the given \p sourceCode string, constructs a NdrNode from it and
130  /// adds it to the registry. The parser to be used is determined by the
131  /// specified \p sourceType.
132  ///
133  /// Nodes created from source code using this API can be looked up by the
134  /// unique identifier and sourceType of the returned node.
135  ///
136  /// \p metadata contains additional metadata needed for parsing and
137  /// compiling the source code correctly. This metadata supplements the
138  /// metadata available in \p sourceCode and overrides it cases where there
139  /// are key collisions.
140  ///
141  /// Returns a valid node if the given source code is parsed successfully
142  /// using the parser plugins that is registered for the specified
143  /// \p sourceType.
144  NDR_API
146  const TfToken &sourceType,
147  const NdrTokenMap &metadata);
148 
149  /// Get the locations where the registry is searching for nodes.
150  ///
151  /// Depending on which discovery plugins were used, this may include
152  /// non-filesystem paths.
153  NDR_API
154  NdrStringVec GetSearchURIs() const;
155 
156  /// Get the identifiers of all the nodes that the registry is aware of.
157  ///
158  /// This will not run the parsing plugins on the nodes that have been
159  /// discovered, so this method is relatively quick. Optionally, a "family"
160  /// name can be specified to only get the identifiers of nodes that belong
161  /// to that family and a filter can be specified to get just the default
162  /// version (the default) or all versions of the node.
163  NDR_API
165  GetNodeIdentifiers(const TfToken& family = TfToken(),
168 
169  /// Get the names of all the nodes that the registry is aware of.
170  ///
171  /// This will not run the parsing plugins on the nodes that have been
172  /// discovered, so this method is relatively quick. Optionally, a "family"
173  /// name can be specified to only get the names of nodes that belong to
174  /// that family.
175  NDR_API
176  NdrStringVec GetNodeNames(const TfToken& family = TfToken()) const;
177 
178  /// Get the node with the specified identifier, and an optional
179  /// priority list specifying the set of node SOURCE types (see
180  /// `NdrNode::GetSourceType()`) that should be searched.
181  ///
182  /// Nodes of the same identifier but different source type can exist
183  /// in the registry. If a node 'Foo' with source types 'abc' and 'xyz'
184  /// exist in the registry, and you want to make sure the 'abc' version
185  /// is fetched before the 'xyz' version, the priority list would be
186  /// specified as ['abc', 'xyz']. If the 'abc' version did not exist in
187  /// the registry, then the 'xyz' version would be returned.
188  ///
189  /// Note that this \em will run the parsing routine. However, unlike some
190  /// other methods that run parsing, this will only parse the node(s) that
191  /// matches the specified identifier and type(s).
192  ///
193  /// Returns `nullptr` if a node matching the arguments can't be found.
194  NDR_API
196  const NdrTokenVec& typePriority = NdrTokenVec());
197 
198  /// A convenience wrapper around `GetNodeByIdentifier()`. Instead of
199  /// providing a priority list, an exact type is specified, and
200  /// `nullptr` is returned if a node with the exact identifier and
201  /// type does not exist.
202  NDR_API
204  const TfToken& nodeType);
205 
206  /// Get the node with the specified name. An optional priority list
207  /// specifies the set of node SOURCE types (\sa NdrNode::GetSourceType())
208  /// that should be searched and in what order.
209  ///
210  /// Optionally, a filter can be specified to consider just the default
211  /// versions of nodes matching \p name (the default) or all versions
212  /// of the nodes.
213  ///
214  /// \sa GetNodeByIdentifier().
215  NDR_API
217  const NdrTokenVec& typePriority = NdrTokenVec(),
220 
221  /// A convenience wrapper around \c GetNodeByName(). Instead of
222  /// providing a priority list, an exact type is specified, and
223  /// `nullptr` is returned if a node with the exact identifier and
224  /// type does not exist.
225  ///
226  /// Optionally, a filter can be specified to consider just the default
227  /// versions of nodes matching \p name (the default) or all versions
228  /// of the nodes.
229  NDR_API
231  const TfToken& nodeType,
234 
235  /// Get all nodes matching the specified identifier (multiple nodes of
236  /// the same identifier, but different source types, may exist). Only
237  /// nodes matching the specified identifier will be parsed. If no nodes
238  /// match the identifier, an empty vector is returned.
239  NDR_API
241 
242  /// Get all nodes matching the specified name. Only nodes matching the
243  /// specified name will be parsed. Optionally, a filter can be specified
244  /// to get just the default version (the default) or all versions of the
245  /// node. If no nodes match an empty vector is returned.
246  NDR_API
250 
251  /// Get all nodes from the registry, optionally restricted to the nodes
252  /// that fall under a specified family and/or the default version.
253  ///
254  /// Note that this will parse \em all nodes that the registry is aware of
255  /// (unless a family is specified), so this may take some time to run
256  /// the first time it is called.
257  NDR_API
261 
262  /// Get a sorted list of all node source types that may be present on the
263  /// nodes in the registry.
264  ///
265  /// Source types originate from the discovery process, but there is no
266  /// guarantee that the discovered source types will also have a registered
267  /// parser plugin. The actual supported source types here depend on the
268  /// parsers that are available. Also note that some parser plugins may not
269  /// advertise a source type.
270  ///
271  /// See the documentation for `NdrParserPlugin` and
272  /// `NdrNode::GetSourceType()` for more information.
273  NDR_API
275 
276 protected:
277  NdrRegistry(const NdrRegistry&) = delete;
278  NdrRegistry& operator=(const NdrRegistry&) = delete;
279 
280  // Allow TF to construct the class
281  friend class TfSingleton<NdrRegistry>;
282 
283  NDR_API
284  NdrRegistry();
285 
286  NDR_API
287  virtual ~NdrRegistry();
288 
289 private:
291  friend class _DiscoveryContext;
292 
293  typedef std::unordered_map<TfToken, NdrParserPlugin*,
294  TfToken::HashFunctor> TypeToParserPluginMap;
295  typedef std::pair<NdrIdentifier, TfToken> NodeMapKey;
296  struct NodeMapKeyHashFunctor {
297  size_t operator()(const NodeMapKey& x) const {
298  return NdrIdentifierHashFunctor()(x.first) ^
299  TfToken::HashFunctor()(x.second);
300  }
301  };
302  typedef std::unordered_multimap<NodeMapKey, NdrNodeUniquePtr,
303  NodeMapKeyHashFunctor> NodeMap;
304 
305  // The discovery result vec is not a concurrent data structure, thus it
306  // needs some locking infrastructure.
307  mutable std::mutex _discoveryResultMutex;
308 
309  // The node map is not a concurrent data structure, thus it needs some
310  // locking infrastructure.
311  mutable std::mutex _nodeMapMutex;
312 
313  // Runs each discovery plugin provided and appends the results to the
314  // internal discovery results vector
315  void _RunDiscoveryPlugins(const DiscoveryPluginRefPtrVec& discoveryPlugins);
316 
317  // Finds and instantiates the discovery plugins
318  void _FindAndInstantiateDiscoveryPlugins();
319 
320  // Finds and instantiates the parser plugins
321  void _FindAndInstantiateParserPlugins();
322 
323  // Instantiates the specified parser plugins and adds them to
324  // the registry.
325  void _InstantiateParserPlugins(const std::set<TfType>& parserPluginTypes);
326 
327  // Parses all nodes that match the specified predicate, optionally only
328  // parsing the first node that matches (good to use when the predicate will
329  // only ever match one node). This is a lightweight, single-threaded version
330  // of the parsing routine found in `GetNodes()`. Note that if a node matches
331  // the predicate and it has already been parsed, the already-parsed version
332  // will be returned, and a new node will not be inserted into the map.
333  NdrNodeConstPtrVec _ParseNodesMatchingPredicate(
334  std::function<bool(const NdrNodeDiscoveryResult&)> shouldParsePredicate,
335  bool onlyParseFirstMatch);
336 
337  // Inserts a new node into the node cache. If a node with the
338  // same name and type already exists in the cache, the pointer to the
339  // existing node will be returned. If there was an error inserting the node,
340  // `nullptr` will be returned.
341  NdrNodeConstPtr _InsertNodeIntoCache(const NdrNodeDiscoveryResult& dr);
342 
343  // Get a vector of all of the node unique_ptrs in the node map as raw ptrs
344  NdrNodeConstPtrVec _GetNodeMapAsNodePtrVec(const TfToken& family,
345  NdrVersionFilter filter) const;
346 
347  // Return the source type for a discovery type or the empty token if
348  // no parser plugin has that discovery type.
350  _GetParserForDiscoveryType(const TfToken& discoveryType) const;
351 
352  // Return the first node matching the strongest possible source type.
353  // That is, for each source type from beginning to end, check every
354  // node in nodes beginning-to-end and return the first node that
355  // has the source type.
356  static NdrNodeConstPtr
357  _GetNodeByTypePriority(const NdrNodeConstPtrVec& nodes,
358  const NdrTokenVec& typePriority);
359 
360  // The discovery plugins that were found through libplug and/or provided by
361  // the client
362  DiscoveryPluginRefPtrVec _discoveryPlugins;
363 
364  // The parser plugins that have been discovered via the plugin system. Maps
365  // a discovery result's "discovery type" to a specific parser.
366  TypeToParserPluginMap _parserPluginMap;
367 
368  // The parser plugins. This has ownership of the plugin objects.
369  std::vector<std::unique_ptr<NdrParserPlugin>> _parserPlugins;
370 
371  // The preliminary discovery results prior to parsing. If accessing or
372  // mutating, _discoveryResultMutex should be used.
373  NdrNodeDiscoveryResultVec _discoveryResults;
374 
375  // Maps a node's name to a node instance. If accessing or mutating,
376  // _nodeMapMutex should be used.
377  NodeMap _nodeMap;
378 
379  // The source types that have been made available via parser plugins
380  NdrTokenVec _availableSourceTypes;
381 };
382 
384 
385 #endif // PXR_USD_NDR_REGISTRY_H
NDR_API NdrStringVec GetSearchURIs() const
NdrVersionFilter
Enumeration used to select nodes by version.
Definition: declare.h:203
GLuint const GLchar * name
Definition: glew.h:1814
std::vector< TfToken > NdrTokenVec
Definition: declare.h:59
virtual NDR_API ~NdrRegistry()
NdrNode const * NdrNodeConstPtr
Definition: declare.h:73
std::vector< NdrNodeDiscoveryResult > NdrNodeDiscoveryResultVec
Functor to use for hash maps from tokens to other things.
Definition: token.h:166
TfToken::HashFunctor NdrIdentifierHashFunctor
Definition: declare.h:51
std::vector< NdrNodeConstPtr > NdrNodeConstPtrVec
Definition: declare.h:75
NdrRegistry & operator=(const NdrRegistry &)=delete
static NDR_API NdrRegistry & GetInstance()
Get the single NdrRegistry instance.
friend class _DiscoveryContext
Definition: registry.h:290
NDR_API NdrRegistry()
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
Definition: glew.h:2981
Definition: token.h:87
std::vector< NdrIdentifier > NdrIdentifierVec
Definition: declare.h:54
GLint GLint GLint GLint GLint x
Definition: glew.h:1252
NDR_API NdrIdentifierVec GetNodeIdentifiers(const TfToken &family=TfToken(), NdrVersionFilter filter=NdrVersionFilterDefaultOnly) const
std::vector< std::string > NdrStringVec
Definition: declare.h:79
NDR_API NdrNodeConstPtr GetNodeByIdentifier(const NdrIdentifier &identifier, const NdrTokenVec &typePriority=NdrTokenVec())
NDR_API NdrNodeConstPtr GetNodeByIdentifierAndType(const NdrIdentifier &identifier, const TfToken &nodeType)
NDR_API NdrNodeConstPtr GetNodeFromSourceCode(const std::string &sourceCode, const TfToken &sourceType, const NdrTokenMap &metadata)
NdrDiscoveryPluginRefPtrVector DiscoveryPluginRefPtrVec
Definition: registry.h:66
#define NDR_API
Definition: api.h:40
NDR_API NdrNodeConstPtrVec GetNodesByIdentifier(const NdrIdentifier &identifier)
GLsizei const GLchar *const * string
Definition: glew.h:1844
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1346
NDR_API NdrNodeConstPtr GetNodeByNameAndType(const std::string &name, const TfToken &nodeType, NdrVersionFilter filter=NdrVersionFilterDefaultOnly)
NDR_API void SetExtraDiscoveryPlugins(DiscoveryPluginRefPtrVec plugins)
std::unique_ptr< NdrNode > NdrNodeUniquePtr
Definition: declare.h:74
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:91
NDR_API NdrStringVec GetNodeNames(const TfToken &family=TfToken()) const
std::unordered_map< TfToken, std::string, TfToken::HashFunctor > NdrTokenMap
Definition: declare.h:61
NDR_API void SetExtraParserPlugins(const std::vector< TfType > &pluginTypes)
NDR_API NdrNodeConstPtr GetNodeFromAsset(const SdfAssetPath &asset, const NdrTokenMap &metadata, const TfToken &subIdentifier=TfToken(), const TfToken &sourceType=TfToken())
NDR_API NdrNodeConstPtr GetNodeByName(const std::string &name, const NdrTokenVec &typePriority=NdrTokenVec(), NdrVersionFilter filter=NdrVersionFilterDefaultOnly)
NDR_API NdrNodeConstPtrVec GetNodesByName(const std::string &name, NdrVersionFilter filter=NdrVersionFilterDefaultOnly)
NDR_API NdrNodeConstPtrVec GetNodesByFamily(const TfToken &family=TfToken(), NdrVersionFilter filter=NdrVersionFilterDefaultOnly)
NDR_API NdrTokenVec GetAllNodeSourceTypes() const