HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
listEditor.h
Go to the documentation of this file.
1 //
2 // Copyright 2016 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_SDF_LIST_EDITOR_H
8 #define PXR_USD_SDF_LIST_EDITOR_H
9 
10 #include "pxr/pxr.h"
11 #include "pxr/base/tf/token.h"
12 #include "pxr/usd/sdf/allowed.h"
14 #include "pxr/usd/sdf/listOp.h"
15 #include "pxr/usd/sdf/path.h"
16 #include "pxr/usd/sdf/schema.h"
17 #include "pxr/usd/sdf/spec.h"
18 
19 #include <functional>
20 #include <optional>
21 
23 
26 
27 /// \class Sdf_ListEditor
28 ///
29 /// Base class for list editor implementations in which list editing operations
30 /// are stored in data field(s) associated with an owning spec.
31 ///
32 template <class TypePolicy>
34 {
35  Sdf_ListEditor(const Sdf_ListEditor&) = delete;
36  Sdf_ListEditor& operator=(const Sdf_ListEditor&) = delete;
37 private:
39 
40 public:
42  typedef std::vector<value_type> value_vector_type;
43 
44  virtual ~Sdf_ListEditor() = default;
45 
46  SdfLayerHandle GetLayer() const
47  {
48  return _owner ? _owner->GetLayer() : SdfLayerHandle();
49  }
50 
51  SdfPath GetPath() const
52  {
53  return _owner ? _owner->GetPath() : SdfPath();
54  }
55 
56  bool IsValid() const
57  {
58  return !IsExpired();
59  }
60 
61  bool IsExpired() const
62  {
63  return !_owner;
64  }
65 
66  bool HasKeys() const
67  {
68  if (IsExplicit()) {
69  return true;
70  }
71  else if (IsOrderedOnly()) {
72  return !_GetOperations(SdfListOpTypeOrdered).empty();
73  }
74  else {
75  return (!_GetOperations(SdfListOpTypeAdded).empty() ||
80  }
81  }
82 
83  virtual bool IsExplicit() const = 0;
84  virtual bool IsOrderedOnly() const = 0;
85 
87  {
88  if (!_owner) {
89  return SdfAllowed("List editor is expired");
90  }
91 
92  if (!_owner->PermissionToEdit()) {
93  return SdfAllowed("Permission denied");
94  }
95 
96  return true;
97  }
98 
99  virtual bool CopyEdits(const Sdf_ListEditor& rhs) = 0;
100  virtual bool ClearEdits() = 0;
101  virtual bool ClearEditsAndMakeExplicit() = 0;
102 
103  typedef std::function<
104  std::optional<value_type>(const value_type&)
105  >
107 
108  /// Modifies the operations stored in all operation lists.
109  /// \p callback is called for every key. If the returned key is
110  /// invalid then the key is removed, otherwise it's replaced with the
111  /// returned key. If the returned key matches a key that was previously
112  /// returned for the list being processed, the returned key will be
113  /// removed.
114  virtual void ModifyItemEdits(const ModifyCallback& cb) = 0;
115 
116  typedef std::function<
117  std::optional<value_type>(SdfListOpType, const value_type&)
118  >
120 
121  /// Apply the list operations represented by this interface to the given
122  /// vector of values \p vec. If \p callback is valid then it's called
123  /// for every key in the editor before applying it to \p vec. If the
124  /// returned key is empty then the key will not be applied. Otherwise
125  /// the returned key is applied, allowing callbacks to perform key
126  /// translation. Note that this means list editors can't meaningfully
127  /// hold the empty key.
128  virtual void ApplyEditsToList(
129  value_vector_type* vec,
130  const ApplyCallback& cb = ApplyCallback()) = 0;
131 
132  /// Returns the number of elements in the specified list of operations.
133  size_t GetSize(SdfListOpType op) const
134  {
135  return _GetOperations(op).size();
136  }
137 
138  /// Returns the \p i'th value in the specified list of operations.
139  value_type Get(SdfListOpType op, size_t i) const
140  {
141  return _GetOperations(op)[i];
142  }
143 
144  /// Returns the specified list of operations.
146  {
147  return _GetOperations(op);
148  }
149 
150  /// Returns the number of occurrences of \p val in the specified list of
151  /// operations.
152  size_t Count(SdfListOpType op, const value_type& val) const
153  {
154  const value_vector_type& ops = _GetOperations(op);
155  return std::count(ops.begin(), ops.end(), _typePolicy.Canonicalize(val));
156  }
157 
158  /// Returns the index of \p val in the specified list of operations, -1
159  /// if \p val is not found.
160  size_t Find(SdfListOpType op, const value_type& val) const
161  {
162  const value_vector_type& vec = _GetOperations(op);
163  typename value_vector_type::const_iterator findIt =
164  std::find(vec.begin(), vec.end(), _typePolicy.Canonicalize(val));
165  if (findIt != vec.end()) {
166  return std::distance(vec.begin(), findIt);
167  }
168 
169  return size_t(-1);
170  }
171 
172  /// Replaces the operations in the specified list of operations in range
173  /// [index, index + n) with the given \p elems.
174  virtual bool ReplaceEdits(
175  SdfListOpType op, size_t index, size_t n,
176  const value_vector_type& elems) = 0;
177 
178  /// Applies a \p rhs opinions about a given operation list to this one.
179  virtual void ApplyList(SdfListOpType op, const Sdf_ListEditor& rhs) = 0;
180 
181 protected:
183  {
184  }
185 
186  Sdf_ListEditor(const SdfSpecHandle& owner, const TfToken& field,
187  const TypePolicy& typePolicy)
188  : _owner(owner),
189  _field(field),
190  _typePolicy(typePolicy)
191  {
192  }
193 
194  const SdfSpecHandle& _GetOwner() const
195  {
196  return _owner;
197  }
198 
199  const TfToken& _GetField() const
200  {
201  return _field;
202  }
203 
204  const TypePolicy& _GetTypePolicy() const
205  {
206  return _typePolicy;
207  }
208 
210  const value_vector_type& oldValues,
211  const value_vector_type& newValues) const
212  {
213  // Disallow duplicate items from being stored in the new list
214  // editor values. This is O(n^2), but we expect the number of elements
215  // stored to be small enough that this won't matter.
216  //
217  // XXX:
218  // We assume that duplicate data items are never allowed to be
219  // authored. For full generality, this information ought to come from
220  // the layer schema.
221 
222  // We also assume that the `oldValues` are already valid and do not
223  // contain duplicates. With this assumption, we can accelerate the
224  // common case of appending new items at the end and skip over a common
225  // prefix of oldValues and newValues. Then we can only check for dupes
226  // in the tail of newValues.
227 
228  typename value_vector_type::const_iterator
229  oldValuesTail = oldValues.begin(),
230  newValuesTail = newValues.begin();
231  auto oldEnd = oldValues.end(), newEnd = newValues.end();
232  while (oldValuesTail != oldEnd && newValuesTail != newEnd &&
233  *oldValuesTail == *newValuesTail) {
234  ++oldValuesTail, ++newValuesTail;
235  }
236 
237  for (auto i = newValuesTail; i != newEnd; ++i) {
238  // Have to check unmatched new items for dupes.
239  for (auto j = newValues.begin(); j != i; ++j) {
240  if (*i == *j) {
241  TF_CODING_ERROR("Duplicate item '%s' not allowed for "
242  "field '%s' on <%s>",
243  TfStringify(*i).c_str(),
244  _field.GetText(),
245  this->GetPath().GetText());
246  return false;
247  }
248  }
249  }
250 
251  // Ensure that all new values are valid for this field.
252  const SdfSchema::FieldDefinition* fieldDef =
253  _owner->GetSchema().GetFieldDefinition(_field);
254  if (!fieldDef) {
255  TF_CODING_ERROR("No field definition for field '%s'",
256  _field.GetText());
257  }
258  else {
259  for (auto i = newValuesTail; i != newEnd; ++i) {
260  if (SdfAllowed isValid = fieldDef->IsValidListValue(*i)) { }
261  else {
262  TF_CODING_ERROR("%s", isValid.GetWhyNot().c_str());
263  return false;
264  }
265  }
266  }
267 
268  return true;
269  }
270 
271  virtual void _OnEdit(SdfListOpType op,
272  const value_vector_type& oldValues,
273  const value_vector_type& newValues) const
274  {
275  }
276 
277  virtual const value_vector_type& _GetOperations(SdfListOpType op) const = 0;
278 
279 private:
280  SdfSpecHandle _owner;
281  TfToken _field;
282  TypePolicy _typePolicy;
283 
284 };
285 
286 template <class TypePolicy>
287 std::ostream&
288 operator<<(std::ostream& s, const Sdf_ListEditor<TypePolicy>& x)
289 {
290  struct Util {
292  value_vector_type;
293 
294  static void _Write(std::ostream& s, const value_vector_type& v)
295  {
296  s << '[';
297  for (size_t i = 0, n = v.size(); i < n; ++i) {
298  if (i != 0) {
299  s << ", ";
300  }
301  s << v[i];
302  }
303  s << ']';
304  }
305  };
306 
307  if (!x.IsValid()) {
308  return s;
309  }
310  else if (x.IsExplicit()) {
311  Util::_Write(s, x.GetVector(SdfListOpTypeExplicit));
312  return s;
313  }
314  else {
315  s << "{ ";
316  if (!x.IsOrderedOnly()) {
317  s << "'added': ";
318  Util::_Write(s, x.GetVector(SdfListOpTypeAdded));
319  s << "'prepended': ";
320  Util::_Write(s, x.GetVector(SdfListOpTypePrepended));
321  s << "'appended': ";
322  Util::_Write(s, x.GetVector(SdfListOpTypeAppended));
323  s << ", 'deleted': ";
324  Util::_Write(s, x.GetVector(SdfListOpTypeDeleted));
325  s << ", ";
326  }
327  s << "'ordered': ";
328  Util::_Write(s, x.GetVector(SdfListOpTypeOrdered));
329  return s << " }";
330  }
331 }
332 
334 
335 #endif // PXR_USD_SDF_LIST_EDITOR_H
virtual const value_vector_type & _GetOperations(SdfListOpType op) const =0
SDF_API const char * GetText() const
Definition: layer.h:81
size_t Find(SdfListOpType op, const value_type &val) const
Definition: listEditor.h:160
virtual bool IsOrderedOnly() const =0
bool HasKeys() const
Definition: listEditor.h:66
const GLdouble * v
Definition: glcorearb.h:837
#define TF_CODING_ERROR
virtual void _OnEdit(SdfListOpType op, const value_vector_type &oldValues, const value_vector_type &newValues) const
Definition: listEditor.h:271
Definition: spec.h:32
GLdouble s
Definition: glad.h:3009
virtual bool ClearEdits()=0
FMT_CONSTEXPR auto find(Ptr first, Ptr last, T value, Ptr &out) -> bool
Definition: core.h:2138
uint64 value_type
Definition: GA_PrimCompat.h:29
TypePolicy::value_type value_type
Definition: listEditor.h:41
const TypePolicy & _GetTypePolicy() const
Definition: listEditor.h:204
value_type Get(SdfListOpType op, size_t i) const
Returns the i'th value in the specified list of operations.
Definition: listEditor.h:139
virtual SdfAllowed PermissionToEdit(SdfListOpType op) const
Definition: listEditor.h:86
const SdfSpecHandle & _GetOwner() const
Definition: listEditor.h:194
GLdouble n
Definition: glcorearb.h:2008
Definition: token.h:70
bool IsValid() const
Definition: listEditor.h:56
virtual bool ReplaceEdits(SdfListOpType op, size_t index, size_t n, const value_vector_type &elems)=0
virtual bool IsExplicit() const =0
SdfListOpType
Definition: listOp.h:29
Sdf_ListEditor(const SdfSpecHandle &owner, const TfToken &field, const TypePolicy &typePolicy)
Definition: listEditor.h:186
std::string TfStringify(const T &v)
Definition: stringUtils.h:556
SdfLayerHandle GetLayer() const
Definition: listEditor.h:46
virtual void ModifyItemEdits(const ModifyCallback &cb)=0
virtual void ApplyList(SdfListOpType op, const Sdf_ListEditor &rhs)=0
Applies a rhs opinions about a given operation list to this one.
const TfToken & _GetField() const
Definition: listEditor.h:199
Definition: path.h:273
GLint GLenum GLint x
Definition: glcorearb.h:409
std::vector< value_type > value_vector_type
Definition: listEditor.h:42
char const * GetText() const
Definition: token.h:179
GLint j
Definition: glad.h:2733
std::function< std::optional< value_type >const value_type &) > ModifyCallback
Definition: listEditor.h:106
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1425
size_t Count(SdfListOpType op, const value_type &val) const
Definition: listEditor.h:152
std::function< std::optional< value_type >SdfListOpType, const value_type &) > ApplyCallback
Definition: listEditor.h:119
GLuint index
Definition: glcorearb.h:786
SdfAllowed IsValidListValue(const T &value) const
Definition: schema.h:86
virtual bool ClearEditsAndMakeExplicit()=0
GLuint GLfloat * val
Definition: glcorearb.h:1608
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74
bool IsExpired() const
Definition: listEditor.h:61
virtual ~Sdf_ListEditor()=default
PXR_NAMESPACE_OPEN_SCOPE SDF_DECLARE_HANDLES(SdfLayer)
SdfPath GetPath() const
Definition: listEditor.h:51
SIM_API const UT_StringHolder distance
virtual void ApplyEditsToList(value_vector_type *vec, const ApplyCallback &cb=ApplyCallback())=0
size_t GetSize(SdfListOpType op) const
Returns the number of elements in the specified list of operations.
Definition: listEditor.h:133
value_vector_type GetVector(SdfListOpType op) const
Returns the specified list of operations.
Definition: listEditor.h:145
virtual bool _ValidateEdit(SdfListOpType op, const value_vector_type &oldValues, const value_vector_type &newValues) const
Definition: listEditor.h:209
virtual bool CopyEdits(const Sdf_ListEditor &rhs)=0