HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
resolver.h
Go to the documentation of this file.
1 //
2 // Copyright 2020 Pixar
3 //
4 // Licensed under the terms set forth in the LICENSE.txt file available at
5 // https://openusd.org/license.
6 //
7 #ifndef PXR_USD_AR_RESOLVER_H
8 #define PXR_USD_AR_RESOLVER_H
9 
10 /// \file ar/resolver.h
11 
12 #include "pxr/pxr.h"
13 #include "pxr/usd/ar/api.h"
14 #include "pxr/usd/ar/ar.h"
17 #include "pxr/usd/ar/timestamp.h"
18 
19 #include <memory>
20 #include <string>
21 #include <vector>
22 
24 
25 class ArAsset;
26 class ArAssetInfo;
27 class ArResolverContext;
28 class ArWritableAsset;
29 class TfType;
30 class VtValue;
31 
32 /// \class ArResolver
33 ///
34 /// Interface for the asset resolution system. An asset resolver is
35 /// responsible for resolving asset information (including the asset's
36 /// physical path) from a logical path.
37 ///
38 /// See \ref ar_implementing_resolver for information on how to customize
39 /// asset resolution behavior by implementing a subclass of ArResolver.
40 /// Clients may use #ArGetResolver to access the configured asset resolver.
41 ///
42 class ArResolver
43 {
44 public:
45  AR_API
46  virtual ~ArResolver();
47 
48  // Disallow copies
49  ArResolver(const ArResolver&) = delete;
50  ArResolver& operator=(const ArResolver&) = delete;
51 
52  // --------------------------------------------------------------------- //
53  /// \anchor ArResolver_identifier
54  /// \name Identifiers
55  ///
56  /// Identifiers are canonicalized asset paths that may be assigned
57  /// to a logical asset to facilitate comparisons and lookups. They
58  /// may be used to determine if different asset paths might refer to
59  /// the same asset without performing resolution.
60  ///
61  /// Since identifiers are just a form of asset path, they may be used
62  /// with other functions on ArResolver that require an asset path, like
63  /// Resolve.
64  ///
65  /// If two asset paths produce the same identifier, those asset paths
66  /// must refer to the same asset. However, in some cases comparing
67  /// identifiers may not be sufficient to determine if assets are equal.
68  /// For example, there could be two assets with the same identifier
69  /// but whose contents were read from different resolved paths because
70  /// different resolver contexts were bound when those assets were loaded.
71  ///
72  /// @{
73  // --------------------------------------------------------------------- //
74 
75  /// Returns an identifier for the asset specified by \p assetPath.
76  /// If \p anchorAssetPath is not empty, it is the resolved asset path
77  /// that \p assetPath should be anchored to if it is a relative path.
78  AR_API
79  std::string CreateIdentifier(
80  const std::string& assetPath,
81  const ArResolvedPath& anchorAssetPath = ArResolvedPath()) const;
82 
83  /// Returns an identifier for a new asset specified by \p assetPath.
84  /// If \p anchorAssetPath is not empty, it is the resolved asset path
85  /// that \p assetPath should be anchored to if it is a relative path.
86  AR_API
87  std::string CreateIdentifierForNewAsset(
88  const std::string& assetPath,
89  const ArResolvedPath& anchorAssetPath = ArResolvedPath()) const;
90 
91  /// @}
92 
93  // --------------------------------------------------------------------- //
94  /// \anchor ArResolver_resolution
95  /// \name Path Resolution Operations
96  ///
97  /// @{
98  // --------------------------------------------------------------------- //
99 
100  /// Returns the resolved path for the asset identified by the given \p
101  /// assetPath if it exists. If the asset does not exist, returns an empty
102  /// ArResolvedPath.
103  AR_API
105  const std::string& assetPath) const;
106 
107  /// Returns the resolved path for the given \p assetPath that may be used
108  /// to create a new asset. If such a path cannot be computed for
109  /// \p assetPath, returns an empty ArResolvedPath.
110  ///
111  /// Note that an asset might or might not already exist at the returned
112  /// resolved path.
113  AR_API
115  const std::string& assetPath) const;
116 
117  /// @}
118 
119  // --------------------------------------------------------------------- //
120  /// \anchor ArResolver_context
121  /// \name Asset Resolver Context Operations
122  ///
123  /// @{
124  // --------------------------------------------------------------------- //
125 
126  /// Binds the given context to this resolver.
127  ///
128  /// Clients should generally use ArResolverContextBinder instead of calling
129  /// this function directly.
130  ///
131  /// \see ArResolverContextBinder
132  AR_API
133  void BindContext(
134  const ArResolverContext& context,
135  VtValue* bindingData);
136 
137  /// Unbind the given context from this resolver.
138  ///
139  /// Clients should generally use ArResolverContextBinder instead of calling
140  /// this function directly.
141  ///
142  /// \see ArResolverContextBinder
143  AR_API
144  void UnbindContext(
145  const ArResolverContext& context,
146  VtValue* bindingData);
147 
148  /// Return an ArResolverContext that may be bound to this resolver
149  /// to resolve assets when no other context is explicitly specified.
150  ///
151  /// The returned ArResolverContext will contain the default context
152  /// returned by the primary resolver and all URI/IRI resolvers.
153  AR_API
155 
156  /// Return an ArResolverContext that may be bound to this resolver
157  /// to resolve the asset located at \p assetPath or referenced by
158  /// that asset when no other context is explicitly specified.
159  ///
160  /// The returned ArResolverContext will contain the default context
161  /// for \p assetPath returned by the primary resolver and all URI/IRI
162  /// resolvers.
163  AR_API
165  const std::string& assetPath) const;
166 
167  /// Return an ArResolverContext created from the primary ArResolver
168  /// implementation using the given \p contextStr.
169  AR_API
171  const std::string& contextStr) const;
172 
173  /// Return an ArResolverContext created from the ArResolver registered
174  /// for the given \p uriScheme using the given \p contextStr.
175  ///
176  /// An empty \p uriScheme indicates the primary resolver and is
177  /// equivalent to CreateContextFromString(string).
178  ///
179  /// If no resolver is registered for \p uriScheme, returns an empty
180  /// ArResolverContext.
181  ///
182  /// \note 'uriScheme' can be used to register IRI resolvers
183  AR_API
185  const std::string& uriScheme, const std::string& contextStr) const;
186 
187  /// Return an ArResolverContext created by combining the ArResolverContext
188  /// objects created from the given \p contextStrs.
189  ///
190  /// \p contextStrs is a list of pairs of strings. The first element in the
191  /// pair is the URI/IRI scheme for the ArResolver that will be used to
192  /// create the ArResolverContext from the second element in the pair. An
193  /// empty resource identifier scheme indicates the primary resolver.
194  ///
195  /// For example:
196  ///
197  /// \code
198  /// ArResolverContext ctx = ArGetResolver().CreateContextFromStrings(
199  /// { {"", "context str 1"},
200  /// {"my-scheme", "context str 2"} });
201  /// \endcode
202  ///
203  /// This will use the primary resolver to create an ArResolverContext
204  /// using the string "context str 1" and use the resolver registered for
205  /// the "my-scheme" URI/IRI scheme to create an ArResolverContext using
206  /// "context str 2". These contexts will be combined into a single
207  /// ArResolverContext and returned.
208  ///
209  /// If no resolver is registered for a URI/IRI scheme in an entry in
210  /// \p contextStrs, that entry will be ignored.
211  AR_API
213  const std::vector<
214  std::pair<std::string, std::string>>& contextStrs) const;
215 
216  /// Refresh any caches associated with the given context. If doing so
217  /// would invalidate asset paths that had previously been resolved,
218  /// an ArNotice::ResolverChanged notice will be sent to inform clients
219  /// of this.
220  ///
221  /// Avoid calling RefreshContext() on the same context from more than one
222  /// thread concurrently as ArNotice::ResolverChanged notice listeners may
223  /// mutate their state in response to receiving the notice.
224  ///
225  /// Avoid calling RefreshContext() with a context that is active (bound to
226  /// a resolver). Unbind the context before refreshing it.
227  ///
228  /// \see \ref Usd_Page_MultiThreading "Threading Model and Performance Considerations"
229  AR_API
230  void RefreshContext(
231  const ArResolverContext& context);
232 
233  /// Returns the asset resolver context currently bound in this thread.
234  ///
235  /// \see ArResolver::BindContext, ArResolver::UnbindContext
236  AR_API
238 
239  /// Returns true if \p assetPath is a context-dependent path, false
240  /// otherwise.
241  ///
242  /// A context-dependent path may result in different resolved paths
243  /// depending on what asset resolver context is bound when Resolve
244  /// is called. Assets located at the same context-dependent path may not
245  /// be the same since those assets may have been loaded from different
246  /// resolved paths. In this case, the assets' resolved paths must be
247  /// consulted to determine if they are the same.
248  AR_API
250  const std::string& assetPath) const;
251 
252  /// @}
253 
254  // --------------------------------------------------------------------- //
255  /// \anchor ArResolver_files
256  /// \name File/asset-specific Operations
257  ///
258  /// @{
259  // --------------------------------------------------------------------- //
260 
261  /// Returns the file extension for the given \p assetPath. The returned
262  /// extension does not include a "." at the beginning.
263  AR_API
264  std::string GetExtension(
265  const std::string& assetPath) const;
266 
267  /// Returns an ArAssetInfo populated with additional metadata (if any)
268  /// about the asset at the given \p assetPath. \p resolvedPath is the
269  /// resolved path computed for the given \p assetPath.
270  AR_API
272  const std::string& assetPath,
273  const ArResolvedPath& resolvedPath) const;
274 
275  /// Returns an ArTimestamp representing the last time the asset at
276  /// \p assetPath was modified. \p resolvedPath is the resolved path
277  /// computed for the given \p assetPath. If a timestamp cannot be
278  /// retrieved, return an invalid ArTimestamp.
279  AR_API
281  const std::string& assetPath,
282  const ArResolvedPath& resolvedPath) const;
283 
284  /// Returns an ArAsset object for the asset located at \p resolvedPath.
285  /// Returns an invalid std::shared_ptr if object could not be created.
286  ///
287  /// The returned ArAsset object provides functions for accessing the
288  /// contents of the specified asset.
289  AR_API
290  std::shared_ptr<ArAsset> OpenAsset(
291  const ArResolvedPath& resolvedPath) const;
292 
293  /// Enumeration of write modes for OpenAssetForWrite
294  enum class WriteMode
295  {
296  /// Open asset for in-place updates. If the asset exists, its contents
297  /// will not be discarded and writes may overwrite existing data.
298  /// Otherwise, the asset will be created.
299  Update = 0,
300 
301  /// Open asset for replacement. If the asset exists, its contents will
302  /// be discarded by the time the ArWritableAsset is destroyed.
303  /// Otherwise, the asset will be created.
304  Replace
305  };
306 
307  /// Returns an ArWritableAsset object for the asset located at \p
308  /// resolvedPath using the specified \p writeMode. Returns an invalid
309  /// std::shared_ptr if object could not be created.
310  ///
311  /// The returned ArWritableAsset object provides functions for writing data
312  /// to the specified asset.
313  ///
314  /// Note that support for reading an asset through other APIs while it
315  /// is open for write is implementation-specific. For example, writes to
316  /// an asset may or may not be immediately visible to other threads or
317  /// processes depending on the implementation.
318  AR_API
319  std::shared_ptr<ArWritableAsset> OpenAssetForWrite(
320  const ArResolvedPath& resolvedPath,
321  WriteMode writeMode) const;
322 
323  /// Returns true if an asset may be written to the given \p resolvedPath,
324  /// false otherwise. If this function returns false and \p whyNot is not
325  /// \c nullptr, it may be filled with an explanation.
326  AR_API
327  bool CanWriteAssetToPath(
328  const ArResolvedPath& resolvedPath,
329  std::string* whyNot = nullptr) const;
330 
331  /// @}
332 
333  // --------------------------------------------------------------------- //
334  /// \anchor ArResolver_scopedCache
335  /// \name Scoped Resolution Cache
336  ///
337  /// A scoped resolution cache indicates to the resolver that results of
338  /// calls to Resolve should be cached for a certain scope. This is
339  /// important for performance and also for consistency -- it ensures
340  /// that repeated calls to Resolve with the same parameters will
341  /// return the same result.
342  ///
343  /// A resolution cache scope is opened by a call to BeginCacheScope and
344  /// must be closed with a matching call to EndCacheScope. The resolver must
345  /// cache the results of Resolve until the scope is closed. Note that these
346  /// calls may be nested.
347  ///
348  /// Cache scopes are thread-specific: if multiple threads are running and
349  /// a cache scope is opened in one of those threads, caching should be
350  /// enabled in that thread only.
351  ///
352  /// When opening a scope, a resolver may return additional data for
353  /// implementation-specific purposes. This data may be shared across
354  /// threads, so long as it is safe to access this data concurrently.
355  ///
356  /// ArResolverScopedCache is an RAII object for managing cache scope
357  /// lifetimes and data. Clients should generally use that class rather
358  /// than calling the BeginCacheScope and EndCacheScope functions manually.
359  ///
360  /// \see ArResolverScopedCache
361  /// @{
362  // --------------------------------------------------------------------- //
363 
364  /// Mark the start of a resolution caching scope.
365  ///
366  /// Clients should generally use ArResolverScopedCache instead of calling
367  /// this function directly.
368  ///
369  /// Resolvers may fill \p cacheScopeData with arbitrary data. Clients may
370  /// also pass in a \p cacheScopeData populated by an earlier call to
371  /// BeginCacheScope to allow the resolver access to that information.
372  ///
373  /// \see ArResolverScopedCache
374  AR_API
375  void BeginCacheScope(
376  VtValue* cacheScopeData);
377 
378  /// Mark the end of a resolution caching scope.
379  ///
380  /// Clients should generally use ArResolverScopedCache instead of calling
381  /// this function directly.
382  ///
383  /// \p cacheScopeData should contain the data that was populated by the
384  /// previous corresponding call to BeginCacheScope.
385  ///
386  /// \see ArResolverScopedCache
387  AR_API
388  void EndCacheScope(
389  VtValue* cacheScopeData);
390 
391  /// @}
392 
393  // --------------------------------------------------------------------- //
394  /// \anchor ArResolver_deprecated
395  /// \name Deprecated APIs
396  ///
397  /// The functions in this section are deprecated in Ar 2.0 and slated
398  /// for removal. Most have default implementations to allow subclasses
399  /// to ignore them completely.
400  ///
401  /// @{
402  // --------------------------------------------------------------------- //
403 
404  /// \deprecated
405  /// Returns true if the given path is a repository path.
406  AR_API
407  bool IsRepositoryPath(const std::string& path) const;
408 
409  /// @}
410 
411 protected:
412  AR_API
413  ArResolver();
414 
415  // --------------------------------------------------------------------- //
416  /// \anchor ArResolver_implementation
417  /// \name Implementation
418  ///
419  /// @{
420 
421  /// Return an identifier for the asset at the given \p assetPath.
422  /// See \ref ArResolver_identifier "Identifiers" for more information.
423  ///
424  /// If \p anchorAssetPath is non-empty, it should be used as the anchoring
425  /// asset if \p assetPath is relative. For example, for a filesystem-based
426  /// implementation _CreateIdentifier might return:
427  ///
428  /// _CreateIdentifier(
429  /// /* assetPath = */ "/abs/path/to/model.usd",
430  /// /* anchorAssetPath = */ ArResolvedPath("/abs/path/to/shot.usd"))
431  /// => "/abs/path/to/model.usd"
432  ///
433  /// _CreateIdentifier(
434  /// /* assetPath = */ "relative/model.usd",
435  /// /* anchorAssetPath = */ ArResolvedPath("/abs/path/to/shot.usd"))
436  /// => "/abs/path/to/relative/model.usd"
437  ///
438  /// Identifiers may be compared to determine if given paths refer to the
439  /// same asset, so implementations should take care to canonicalize and
440  /// normalize the returned identifier to a consistent format.
441  ///
442  /// If either \p assetPath or \p anchorAssetPath have a URI/IRI scheme,
443  /// this function will be called on the resolver associated with that
444  /// URI/IRI scheme, if any.
445  ///
446  /// Example uses:
447  /// - When opening a layer via SdfLayer::FindOrOpen or Find,
448  /// CreateIdentifier will be called with the asset path given to those
449  /// functions and no anchoring asset path. The result will be used as the
450  /// layer's identifier.
451  ///
452  /// - When processing composition arcs that refer to other layers, this
453  /// function will be called with the asset path of the referenced layer
454  /// and the resolved path of the layer where the composition arc was
455  /// authored. The result will be passed to SdfLayer::FindOrOpen to
456  /// open the referenced layer.
457  virtual std::string _CreateIdentifier(
458  const std::string& assetPath,
459  const ArResolvedPath& anchorAssetPath) const = 0;
460 
461  /// Return an identifier for a new asset at the given \p assetPath.
462  ///
463  /// This is similar to _CreateIdentifier but is used to create identifiers
464  /// for assets that may not exist yet and are being created.
465  ///
466  /// Example uses:
467  /// - When creating a new layer via SdfLayer::CreateNew,
468  /// CreateIdentifierForNewAsset will be called with the asset path given
469  /// to the function. The result will be used as the new layer's
470  /// identifier.
471  virtual std::string _CreateIdentifierForNewAsset(
472  const std::string& assetPath,
473  const ArResolvedPath& anchorAssetPath) const = 0;
474 
475  /// Return the resolved path for the given \p assetPath or an empty
476  /// ArResolvedPath if no asset exists at that path.
477  virtual ArResolvedPath _Resolve(
478  const std::string& assetPath) const = 0;
479 
480  /// Return the resolved path for the given \p assetPath that may be used
481  /// to create a new asset or an empty ArResolvedPath if such a path cannot
482  /// be computed.
484  const std::string& assetPath) const = 0;
485 
486  /// @}
487 
488  // --------------------------------------------------------------------- //
489  /// \anchor ArResolver_contextImplementation
490  /// \name Context Operations Implementation
491  ///
492  /// If any of these functions are implemented in a subclass, the plugin
493  /// metadata for that subclass in the plugin library's plugInfo.json
494  /// must specify:
495  /// \code
496  /// "implementsContexts" : true.
497  /// \endcode
498  ///
499  /// If a subclass indicates that it implements any of these functions,
500  /// its plugin library will be loaded and these functions will be called
501  /// when the corresponding public ArResolver API is called. Otherwise,
502  /// these functions will not be called.
503  ///
504  /// @{
505 
506  /// Bind the given \p context to this resolver. \p bindingData may be
507  /// populated with additional information that will be kept alive while
508  /// \p context is bound. Both \p context and \p bindingData will be
509  /// passed to UnbindContext when the context is being unbound.
510  ///
511  /// Contexts may be nested; if multiple contexts are bound, the context
512  /// that was most recently bound must take precedence and block all
513  /// previously bound contexts.
514  ///
515  /// Context binding is thread-specific; contexts bound in a thread must
516  /// only affect other resolver calls in the same thread.
517  ///
518  /// ArResolver itself manages thread-local stacks of bound contexts.
519  /// Subclasses can retrieve the most recent context object which was passed
520  /// to BindContext using _GetCurrentContextObject. Because of this,
521  /// subclasses typically do not need to implement this function unless they
522  /// need to be informed when a context object is bound. For example, this
523  /// may be needed if the context needs to be passed on to another subsystem
524  /// that manages these bindings itself.
525  ///
526  /// The default implementation does nothing.
527  AR_API
528  virtual void _BindContext(
529  const ArResolverContext& context,
530  VtValue* bindingData);
531 
532  /// Unbind the given \p context from this resolver.
533  ///
534  /// It is an error if the context being unbound is not the currently
535  /// bound context.
536  ///
537  /// Subclasses typically do not need to implement this function since
538  /// ArResolver itself keeps track of the contexts that are bound via calls
539  /// to BindContext. However, subclasses may need to implement this function
540  /// if they are managing these bindings itself.
541  ///
542  /// The default implementation does nothing.
543  AR_API
544  virtual void _UnbindContext(
545  const ArResolverContext& context,
546  VtValue* bindingData);
547 
548  /// Return a default ArResolverContext that may be bound to this resolver
549  /// to resolve assets when no other context is explicitly specified.
550  ///
551  /// When CreateDefaultContext is called on the configured asset resolver,
552  /// Ar will call this method on the primary resolver and all URI/IRI
553  /// resolvers and merge the results into a single ArResolverContext that
554  /// will be returned to the consumer.
555  ///
556  /// This function should not automatically bind this context, but should
557  /// create one that may be used later.
558  ///
559  /// The default implementation returns a default-constructed
560  /// ArResolverContext.
561  ///
562  /// Example uses:
563  /// - UsdStage will call CreateDefaultContext when creating a new stage with
564  /// an anonymous root layer and without a given context. The returned
565  /// context will be bound when resolving asset paths on that stage.
566  AR_API
568 
569  /// Return an ArResolverContext that may be bound to this resolver
570  /// to resolve the asset located at \p assetPath or referenced by
571  /// that asset when no other context is explicitly specified.
572  ///
573  /// When CreateDefaultContextForAsset is called on the configured asset
574  /// resolver, Ar will call this method on the primary resolver and all
575  /// URI/IRI resolvers and merge the results into a single ArResolverContext
576  /// that will be returned to the consumer.
577  ///
578  /// Note that this means this method may be called with asset paths that
579  /// are not associated with this resolver. For example, this method may
580  /// be called on a URI/IRI resolver with a non-URI/IRI asset path. This is
581  /// to support cases where the asset at \p assetPath references other
582  /// assets with URI/IRI schemes that differ from the URI/IRI scheme
583  /// (if any) in \p assetPath.
584  ///
585  /// This function should not automatically bind this context, but should
586  /// create one that may be used later.
587  ///
588  /// The default implementation returns a default-constructed
589  /// ArResolverContext.
590  ///
591  /// Example uses:
592  /// - UsdStage will call CreateDefaultContextForAsset when creating a new
593  /// stage with a non-anonymous root layer and without a given context. The
594  /// resolved path of the root layer will be passed in as the
595  /// \p assetPath. The returned context will be bound when resolving asset
596  /// paths on that stage.
597  AR_API
599  const std::string& assetPath) const;
600 
601  /// Return an ArResolverContext created from the given \p contextStr.
602  ///
603  /// The default implementation returns a default-constructed
604  /// ArResolverContext.
605  AR_API
607  const std::string& contextStr) const;
608 
609  /// Refresh any caches associated with the given context. If doing so
610  /// would invalidate asset paths that had previously been resolved,
611  /// this function should send an ArNotice::ResolverChanged notice to
612  /// inform clients of this. See documentation on that class for more
613  /// details.
614  ///
615  /// The default implementation does nothing.
616  AR_API
617  virtual void _RefreshContext(
618  const ArResolverContext& context);
619 
620  /// Return the currently bound context. Since context binding is
621  /// thread-specific, this should return the context that was most recently
622  /// bound in this thread.
623  ///
624  /// Subclasses typically do not need to implement this function since
625  /// ArResolver itself keeps track of the contexts that are bound via calls
626  /// to BindContext. However, if a subclass is managing bound contexts itself
627  /// and allows clients to bind context objects via other API outside of
628  /// BindContext, this function should return the context object as described
629  /// above. This typically happens with subclasses that are wrappers around
630  /// other resolution subsystems. \see _BindContext for more information.
631  ///
632  /// The default implementation returns a default-constructed
633  /// ArResolverContext.
634  AR_API
635  virtual ArResolverContext _GetCurrentContext() const;
636 
637  /// Return true if the result of resolving the given \p assetPath may
638  /// differ depending on the asset resolver context that is bound when
639  /// Resolve is called, false otherwise.
640  ///
641  /// The default implementation returns false.
642  ///
643  /// Example uses:
644  /// - SdfLayer will call this function to check if the identifier given
645  /// to SdfLayer::Find or SdfLayer::FindOrOpen is context-dependent.
646  /// If it is and a layer exists with the same identifier, SdfLayer
647  /// can return it without resolving the identifier. If it is not,
648  /// SdfLayer must resolve the identifier and search for a layer with
649  /// the same resolved path, even if a layer exists with the same
650  /// identifier.
651  AR_API
652  virtual bool _IsContextDependentPath(
653  const std::string& assetPath) const;
654 
655  /// @}
656 
657  // --------------------------------------------------------------------- //
658  /// \anchor ArResolver_assetImplementation
659  /// \name Asset Operations Implementation
660  ///
661  /// @{
662 
663  /// Return the file extension for the given \p assetPath. This extension
664  /// should not include a "." at the beginning of the string.
665  ///
666  /// The default implementation returns the string after the last "."
667  /// in \p assetPath. If \p assetPath begins with a ".", the extension
668  /// will be empty unless there is another "." in the path. If
669  /// \p assetPath has components separated by '/' (or '\' on Windows),
670  /// only the last component will be considered.
671  AR_API
672  virtual std::string _GetExtension(
673  const std::string& assetPath) const;
674 
675  /// Return an ArAssetInfo populated with additional metadata (if any)
676  /// about the asset at the given \p assetPath. \p resolvedPath is the
677  /// resolved path computed for the given \p assetPath.
678  /// The default implementation returns a default-constructed ArAssetInfo.
679  AR_API
680  virtual ArAssetInfo _GetAssetInfo(
681  const std::string& assetPath,
682  const ArResolvedPath& resolvedPath) const;
683 
684  /// Return an ArTimestamp representing the last time the asset at
685  /// \p assetPath was modified. \p resolvedPath is the resolved path
686  /// computed for the given \p assetPath. If a timestamp cannot be
687  /// retrieved, return an invalid ArTimestamp.
688  ///
689  /// The default implementation returns an invalid ArTimestamp.
690  ///
691  /// Example uses:
692  /// - SdfLayer will call GetModificationTimestamp when opening a
693  /// layer and store the returned timestamp. When SdfLayer::Reload
694  /// is called on that layer, this method will be called again.
695  /// If the returned timestamp differs from the stored timestamp,
696  /// or if it is invalid, the layer will be reloaded.
697  AR_API
699  const std::string& assetPath,
700  const ArResolvedPath& resolvedPath) const;
701 
702  /// Return an ArAsset object for the asset located at \p resolvedPath.
703  /// Return an invalid std::shared_ptr if object could not be created
704  /// (for example, if the asset at the given path could not be opened).
705  ///
706  /// Note that clients may still be using the data associated with
707  /// this object even after the last shared_ptr has been destroyed. For
708  /// example, a client may have created a memory mapping using the FILE*
709  /// presented in the ArAsset object; this would preclude truncating or
710  /// overwriting any of the contents of that file.
711  AR_API
712  virtual std::shared_ptr<ArAsset> _OpenAsset(
713  const ArResolvedPath& resolvedPath) const = 0;
714 
715  /// Return true if an asset may be written to the given \p resolvedPath,
716  /// false otherwise. If this function returns false and \p whyNot is not
717  /// \c nullptr, it may be filled with an explanation. The default
718  /// implementation returns true.
719  AR_API
720  virtual bool _CanWriteAssetToPath(
721  const ArResolvedPath& resolvedPath,
722  std::string* whyNot) const;
723 
724  /// Return an ArWritableAsset object for the asset at \p resolvedPath
725  /// using the specified \p writeMode. Return an invalid std::shared_ptr
726  /// if object could not be created (for example, if writing to the
727  /// given path is not allowed).
728  ///
729  /// Implementations should create any parent paths that are necessary
730  /// to write this asset. The returned ArWritableAsset must obey the
731  /// behaviors for the given \p writeMode, see the documentation for
732  /// the WriteMode enum for more details.
733  AR_API
734  virtual std::shared_ptr<ArWritableAsset>
736  const ArResolvedPath& resolvedPath,
737  WriteMode writeMode) const = 0;
738 
739  /// @}
740 
741  // --------------------------------------------------------------------- //
742  /// \anchor ArResolver_scopedCacheImplementation
743  /// \name Scoped Resolution Cache Implementation
744  ///
745  /// If any of these functions are implemented in a subclass, the plugin
746  /// metadata for that subclass in the plugin library's plugInfo.json
747  /// must specify:
748  /// \code
749  /// "implementsScopedCaches" : true.
750  /// \endcode
751  ///
752  /// If a subclass indicates that it implements these functions, ArResolver
753  /// will assume the subclass is handling all caching of resolved paths
754  /// and will call these functions when a caching scope is opened and closed.
755  /// Otherwise, these functions will not be called. Instead, ArResolver
756  /// itself will handle caching and returning resolved paths as needed.
757  ///
758  /// @{
759 
760  /// Mark the start of a resolution caching scope.
761  ///
762  /// Resolvers may fill \p cacheScopeData with arbitrary data. Clients may
763  /// also pass in a \p cacheScopeData populated by an earlier call to
764  /// BeginCacheScope to allow the resolver access to that information.
765  ///
766  /// See \ref ArResolver_scopedCacheImplementation "Scoped Resolution Cache Implementation"
767  /// for more implementation details.
768  AR_API
769  virtual void _BeginCacheScope(
770  VtValue* cacheScopeData);
771 
772  /// Mark the end of a resolution caching scope.
773  ///
774  /// \p cacheScopeData should contain the data that was populated by the
775  /// previous corresponding call to BeginCacheScope.
776  ///
777  /// See \ref ArResolver_scopedCacheImplementation "Scoped Resolution Cache Implementation"
778  /// for more implementation details.
779  AR_API
780  virtual void _EndCacheScope(
781  VtValue* cacheScopeData);
782 
783  /// @}
784 
785  /// \deprecated
786  /// Return true if the given path is a repository path, false otherwise.
787  /// Default implementation returns false.
788  AR_API
789  virtual bool _IsRepositoryPath(
790  const std::string& path) const;
791 
792  // --------------------------------------------------------------------- //
793  /// \anchor ArResolver_implementationUtils
794  /// \name Implementation Utilities
795  ///
796  /// Utility functions for implementations.
797  ///
798  /// @{
799 
800  /// Returns a pointer to the context object of type \p ContextObj from
801  /// the last ArResolverContext that was bound via a call to BindContext,
802  /// or \c NULL if no context object of that type exists.
803  ///
804  /// Typically, a subclass might use this in their _Resolve function to
805  /// get the currently bound context to drive their resolution behavior.
806  ///
807  /// \code
808  /// if (const MyContextObject* ctx =
809  /// _GetCurrentContextObject<MyContextObject>()) {
810  ///
811  /// // Use information in ctx to resolve given path
812  /// }
813  /// else {
814  /// // Resolve given path with no context object
815  /// }
816  /// \endcode
817  ///
818  /// This is the same as GetCurrentContext().Get<ContextObj>() but more
819  /// efficient, since it does not make a copy of the ArResolverContext.
820  /// However, it is *not* the same as _GetCurrentContext().Get<ContextObj>().
821  /// Subclasses that manage context binding themselves may have overridden
822  /// _GetCurrentContext to return a context that was bound without calling
823  /// BindContext. These subclasses should not use this function and should
824  /// retrieve the current context from their own internal data structures.
825  template <class ContextObj>
826  const ContextObj* _GetCurrentContextObject() const
827  {
828  const ArResolverContext* ctx = _GetInternallyManagedCurrentContext();
829  return ctx ? ctx->Get<ContextObj>() : nullptr;
830  }
831 
832  /// @}
833 
834 private:
835  // Returns pointer to ArResolverContext that was most recently bound
836  // via BindContext. This is *not* the same as GetCurrentContext,
837  // since subclasses may return an ArResolverContext that hasn't
838  // been bound via BindContext in their implementations.
839  AR_API
840  const ArResolverContext* _GetInternallyManagedCurrentContext() const;
841 
842 };
843 
844 /// Returns the configured asset resolver.
845 ///
846 /// When first called, this function will determine the ArResolver subclass
847 /// to use for asset resolution via the following process:
848 ///
849 /// - If a preferred resolver has been set via \ref ArSetPreferredResolver,
850 /// it will be selected.
851 ///
852 /// - Otherwise, a list of available ArResolver subclasses in plugins will
853 /// be generated. If multiple ArResolver subclasses are found, the list
854 /// will be sorted by typename. ArDefaultResolver will be added as the last
855 /// element of this list, and the first resolver in the list will be
856 /// selected.
857 ///
858 /// - The plugin for the selected subclass will be loaded and an instance
859 /// of the subclass will be constructed.
860 ///
861 /// - If an error occurs, an ArDefaultResolver will be constructed.
862 ///
863 /// The constructed ArResolver subclass will be cached and used to service
864 /// function calls made on the returned resolver.
865 ///
866 /// Note that this function may not return the constructed subclass itself,
867 /// meaning that dynamic casts to the subclass type may fail. See
868 /// ArGetUnderlyingResolver if access to this object is needed.
869 AR_API
871 
872 /// Set the preferred ArResolver subclass used by ArGetResolver.
873 ///
874 /// Consumers may override ArGetResolver's plugin resolver discovery and
875 /// force the use of a specific resolver subclass by calling this
876 /// function with the typename of the implementation to use.
877 ///
878 /// If the subclass specified by \p resolverTypeName cannot be found,
879 /// ArGetResolver will issue a warning and fall back to using
880 /// ArDefaultResolver.
881 ///
882 /// This must be called before the first call to ArGetResolver.
883 AR_API
884 void ArSetPreferredResolver(const std::string& resolverTypeName);
885 
886 /// \name Advanced API
887 ///
888 /// \warning These functions should typically not be used by consumers except
889 /// in very specific cases. Consumers who want to retrieve an ArResolver to
890 /// perform asset resolution should use \ref ArGetResolver.
891 ///
892 /// @{
893 
894 /// Returns the underlying ArResolver instance used by ArGetResolver.
895 ///
896 /// This function returns the instance of the ArResolver subclass used by
897 /// ArGetResolver and can be dynamic_cast to that type.
898 ///
899 /// \warning This functions should typically not be used by consumers except
900 /// in very specific cases. Consumers who want to retrieve an ArResolver to
901 /// perform asset resolution should use \ref ArGetResolver.
902 AR_API
904 
905 /// Returns list of TfTypes for available ArResolver subclasses.
906 ///
907 /// This function returns the list of ArResolver subclasses used to determine
908 /// the resolver implementation returned by \ref ArGetResolver. See
909 /// documentation on that function for more details.
910 ///
911 /// If this function is called from within a call (or calls) to
912 /// \ref ArCreateResolver, the ArResolver subclass(es) being created will
913 /// be removed from the returned list.
914 ///
915 /// This function is not safe to call concurrently with itself or
916 /// \ref ArCreateResolver.
917 ///
918 /// \warning This functions should typically not be used by consumers except
919 /// in very specific cases. Consumers who want to retrieve an ArResolver to
920 /// perform asset resolution should use \ref ArGetResolver.
921 AR_API
922 std::vector<TfType> ArGetAvailableResolvers();
923 
924 /// Returns list of all URI schemes for which a resolver has been
925 /// registered. Schemes are returned in all lower-case and in alphabetically
926 /// sorted order.
927 AR_API
928 const std::vector<std::string>& ArGetRegisteredURISchemes();
929 
930 /// Construct an instance of the ArResolver subclass specified by
931 /// \p resolverType.
932 ///
933 /// This function will load the plugin for the given \p resolverType and
934 /// construct and return a new instance of the specified ArResolver subclass.
935 /// If an error occurs, coding errors will be emitted and this function
936 /// will return an ArDefaultResolver instance.
937 ///
938 /// Note that this function *does not* change the resolver used by
939 /// \ref ArGetResolver to an instance of \p resolverType.
940 ///
941 /// This function is not safe to call concurrently with itself or
942 /// \ref ArGetAvailableResolvers.
943 ///
944 /// \warning This functions should typically not be used by consumers except
945 /// in very specific cases. Consumers who want to retrieve an ArResolver to
946 /// perform asset resolution should use \ref ArGetResolver.
947 AR_API
948 std::unique_ptr<ArResolver> ArCreateResolver(const TfType& resolverType);
949 
950 /// @}
951 
953 
954 #endif
virtual std::string _CreateIdentifierForNewAsset(const std::string &assetPath, const ArResolvedPath &anchorAssetPath) const =0
virtual AR_API ArResolverContext _CreateDefaultContext() const
AR_API ArTimestamp GetModificationTimestamp(const std::string &assetPath, const ArResolvedPath &resolvedPath) const
AR_API std::unique_ptr< ArResolver > ArCreateResolver(const TfType &resolverType)
virtual AR_API ArAssetInfo _GetAssetInfo(const std::string &assetPath, const ArResolvedPath &resolvedPath) const
virtual AR_API void _BindContext(const ArResolverContext &context, VtValue *bindingData)
AR_API void RefreshContext(const ArResolverContext &context)
const ContextObj * Get() const
AR_API ArResolverContext GetCurrentContext() const
AR_API ArResolverContext CreateContextFromString(const std::string &contextStr) const
virtual AR_API std::string _GetExtension(const std::string &assetPath) const
GLsizei const GLchar *const * path
Definition: glcorearb.h:3341
abs path to model * ArResolvedPath("/abs/path/to/shot.usd"))*
AR_API void BindContext(const ArResolverContext &context, VtValue *bindingData)
Definition: asset.h:27
virtual AR_API ArTimestamp _GetModificationTimestamp(const std::string &assetPath, const ArResolvedPath &resolvedPath) const
#define AR_API
Definition: api.h:23
virtual AR_API void _UnbindContext(const ArResolverContext &context, VtValue *bindingData)
AR_API ArResolverContext CreateDefaultContext() const
AR_API ArResolver()
AR_API std::string CreateIdentifierForNewAsset(const std::string &assetPath, const ArResolvedPath &anchorAssetPath=ArResolvedPath()) const
virtual AR_API ArResolverContext _CreateDefaultContextForAsset(const std::string &assetPath) const
virtual AR_API ~ArResolver()
AR_API bool IsRepositoryPath(const std::string &path) const
AR_API const std::vector< std::string > & ArGetRegisteredURISchemes()
virtual AR_API ArResolverContext _CreateContextFromString(const std::string &contextStr) const
virtual ArResolvedPath _ResolveForNewAsset(const std::string &assetPath) const =0
const ContextObj * _GetCurrentContextObject() const
Definition: resolver.h:826
AR_API void BeginCacheScope(VtValue *cacheScopeData)
ArResolver & operator=(const ArResolver &)=delete
AR_API ArResolver & ArGetResolver()
AR_API ArAssetInfo GetAssetInfo(const std::string &assetPath, const ArResolvedPath &resolvedPath) const
virtual AR_API std::shared_ptr< ArAsset > _OpenAsset(const ArResolvedPath &resolvedPath) const =0
AR_API bool IsContextDependentPath(const std::string &assetPath) const
AR_API void ArSetPreferredResolver(const std::string &resolverTypeName)
virtual AR_API void _BeginCacheScope(VtValue *cacheScopeData)
AR_API std::vector< TfType > ArGetAvailableResolvers()
AR_API ArResolverContext CreateDefaultContextForAsset(const std::string &assetPath) const
AR_API ArResolvedPath Resolve(const std::string &assetPath) const
AR_API ArResolverContext CreateContextFromStrings(const std::vector< std::pair< std::string, std::string >> &contextStrs) const
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1425
WriteMode
Enumeration of write modes for OpenAssetForWrite.
Definition: resolver.h:294
AR_API ArResolver & ArGetUnderlyingResolver()
virtual AR_API void _EndCacheScope(VtValue *cacheScopeData)
virtual AR_API bool _CanWriteAssetToPath(const ArResolvedPath &resolvedPath, std::string *whyNot) const
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74
AR_API void UnbindContext(const ArResolverContext &context, VtValue *bindingData)
Definition: type.h:47
AR_API bool CanWriteAssetToPath(const ArResolvedPath &resolvedPath, std::string *whyNot=nullptr) const
AR_API std::shared_ptr< ArWritableAsset > OpenAssetForWrite(const ArResolvedPath &resolvedPath, WriteMode writeMode) const
AR_API std::shared_ptr< ArAsset > OpenAsset(const ArResolvedPath &resolvedPath) const
virtual AR_API std::shared_ptr< ArWritableAsset > _OpenAssetForWrite(const ArResolvedPath &resolvedPath, WriteMode writeMode) const =0
AR_API std::string GetExtension(const std::string &assetPath) const
AR_API ArResolvedPath ResolveForNewAsset(const std::string &assetPath) const
virtual AR_API bool _IsContextDependentPath(const std::string &assetPath) const
virtual AR_API bool _IsRepositoryPath(const std::string &path) const
Definition: value.h:146
virtual AR_API void _RefreshContext(const ArResolverContext &context)
virtual ArResolvedPath _Resolve(const std::string &assetPath) const =0
AR_API std::string CreateIdentifier(const std::string &assetPath, const ArResolvedPath &anchorAssetPath=ArResolvedPath()) const
AR_API void EndCacheScope(VtValue *cacheScopeData)
virtual AR_API ArResolverContext _GetCurrentContext() const