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