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