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