Lumiera  0.pre.03
»edit your freedom«
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
tree-mutator-attribute-binding.hpp
Go to the documentation of this file.
1 /*
2  TREE-MUTATOR-ATTRIBUTE-BINDING.hpp - diff::TreeMutator implementation building block
3 
4  Copyright (C)
5  2016, Hermann Vosseler <Ichthyostega@web.de>
6 
7   **Lumiera** is free software; you can redistribute it and/or modify it
8   under the terms of the GNU General Public License as published by the
9   Free Software Foundation; either version 2 of the License, or (at your
10   option) any later version. See the file COPYING for further details.
11 
12 */
13 
14 
95 #ifndef LIB_DIFF_TREE_MUTATOR_ATTRIBUTE_BINDING_H
96 #define LIB_DIFF_TREE_MUTATOR_ATTRIBUTE_BINDING_H
97 
98 
99 #include "lib/error.hpp"
100 #include "lib/symbol.hpp"
101 #include "lib/diff/gen-node.hpp"
102 #include "lib/diff/tree-mutator.hpp"
103 #include "lib/format-string.hpp"
104 #include "lib/idi/entry-id.hpp"
105 
106 #include <utility>
107 
108 
109 namespace lib {
110 namespace diff{
111 
112  namespace { // Mutator-Builder decorator components...
113 
114 
124  template<class PAR>
126  : public PAR
127  {
128 
129  BareEntryID attribID_;
130 
131  protected:
132  AttributeBindingBase (BareEntryID attribID, PAR&& chain)
133  : PAR(std::forward<PAR>(chain))
134  , attribID_(attribID)
135  { }
136 
144  bool
145  isApplicable (GenNode const& spec)
146  {
147  return spec.isNamed()
148  and attribID_ == spec.idi;
149  }
150 
151  void
152  __ifApplicable_refuse_to(Literal oper, GenNode const& spec)
153  {
154  if (this->isApplicable(spec))
155  throw error::Logic (_Fmt{"attempt to %s attribute '%s', "
156  "but this binding for '%s' is linked to a data field and "
157  "thus does not support any notion of 'order' or 'position', "
158  "inserting or deletion."}
159  % oper % spec.idi % this->attribID_);
160  }
161 
162 
163  /* ==== re-Implementation of the operation API ==== */
164  public:
170  virtual bool
171  matchSrc (GenNode const& spec) override
172  {
173  return isApplicable (spec)
174  or PAR::matchSrc (spec);
175  }
176 
177 
178  // note: hasSrc() not overridden here --> delegate to parent layer
179 
180 
182  virtual bool
183  acceptSrc (GenNode const& spec) override
184  {
185  return isApplicable (spec)
186  or PAR::acceptSrc (spec);
187  }
188 
195  virtual void
196  skipSrc (GenNode const& refSpec) override
197  {
198  __ifApplicable_refuse_to ("skip or drop", refSpec);
199  PAR::skipSrc (refSpec);
200  }
201 
202  virtual bool
203  findSrc (GenNode const& refSpec) override
204  {
205  __ifApplicable_refuse_to ("re-order", refSpec);
206  return PAR::findSrc (refSpec);
207  }
208 
218  virtual bool
219  accept_until (GenNode const& spec) override
220  {
221  if (Ref::END == spec or Ref::ATTRIBS == spec)
222  return PAR::accept_until(spec);
223  else
224  {
225  __ifApplicable_refuse_to ("navigate to a position behind", spec);
226  return PAR::accept_until(spec);
227  }
228  }
229  };
230 
231 
232 
233 
234  template<class PAR, class CLO>
236  : public AttributeBindingBase<PAR>
237  {
238  using CloArgs = typename lib::meta::_Fun<CLO>::Args;
239  using ValueType = typename lib::meta::Pick<CloArgs, 0>::Type;
240  using ID = idi::EntryID<ValueType>;
241 
242 
243  CLO setter_;
244 
245  public:
246  ChangeOperation (Symbol attribKey, CLO clo, PAR&& chain)
247  : AttributeBindingBase<PAR>(ID{attribKey}, std::forward<PAR>(chain))
248  , setter_(clo)
249  { }
250 
251 
252  /* ==== Implementation of value assignment operation ==== */
253 
261  virtual bool
262  injectNew (GenNode const& spec) override
263  {
264  if (not this->isApplicable(spec))
265  return PAR::injectNew(spec);
266 
267  setter_(spec.data.get<ValueType>());
268  return true;
269  }
270 
272  virtual bool
273  assignElm (GenNode const& spec) override
274  {
275  if (not this->isApplicable(spec))
276  return PAR::assignElm(spec);
277 
278  setter_(spec.data.get<ValueType>());
279  return true;
280  }
281  };
282 
283 
284 
285  template<class PAR, class MUT>
287  : public AttributeBindingBase<PAR>
288  {
289 
291 
292  MUT mutatorBuilder_;
293 
294 
295  public:
296  MutationOperation (BareEntryID const& attribID, MUT clo, PAR&& chain)
297  : AttributeBindingBase<PAR>(attribID, std::forward<PAR>(chain))
298  , mutatorBuilder_(clo)
299  { }
300 
301 
305  virtual bool
306  mutateChild (GenNode const& spec, TreeMutator::Handle targetBuff) override
307  {
308  if (not this->isApplicable(spec))
309  return PAR::mutateChild(spec, targetBuff);
310 
311  mutatorBuilder_(targetBuff);
312  return true;
313  }
314 
315 
331  virtual bool
332  injectNew (GenNode const& spec) override
333  {
334  return this->isApplicable(spec)
335  or PAR::injectNew(spec);
336  }
337  };
338 
339 
340 
342  template<class PAR>
343  template<typename CLO>
344  inline auto
345  Builder<PAR>::change (Symbol attributeID, CLO setterClosure)
346  {
347  return chainedBuilder<ChangeOperation<PAR,CLO>> (attributeID, setterClosure);
348  }
349 
350 
352  template<class PAR>
353  template<typename CLO>
354  inline auto
355  Builder<PAR>::mutateAttrib (Symbol attributeID, CLO mutatorBuilderClosure)
356  {
357  idi::EntryID<Rec> key{attributeID};
358  return chainedBuilder<MutationOperation<PAR,CLO>> (key, mutatorBuilderClosure);
359  }
360 
362  template<class PAR>
363  template<typename CLO>
364  inline auto
365  Builder<PAR>::mutateAttrib (idi::BareEntryID const& rawID, CLO mutatorBuilderClosure)
366  {
367  return chainedBuilder<MutationOperation<PAR,CLO>> (rawID, mutatorBuilderClosure);
368  }
369 
370 
371 
372  }//(END)Mutator-Builder decorator components...
373 
374 }} // namespace lib::diff
375 #endif /*LIB_DIFF_TREE_MUTATOR_ATTRIBUTE_BINDING_H*/
type erased baseclass for building a combined hash and symbolic ID.
Definition: entry-id.hpp:133
#define ASSERT_VALID_SIGNATURE(_FUN_, _SIG_)
Macro for a compile-time check to verify the given generic functors or lambdas expose some expected s...
Definition: function.hpp:247
virtual bool matchSrc(GenNode const &spec) override
ensure the given spec is deemed appropriate at that point.
inline string literal This is a marker type to indicate that
Definition: symbol.hpp:76
Front-end for printf-style string template interpolation.
typed symbolic and hash ID for asset-like position accounting.
Definition: entry-id.hpp:126
virtual bool acceptSrc(GenNode const &spec) override
accept status quo, after verifying the spec from the diff verb
Helper for uniform access to function signature types.
Definition: function.hpp:99
A front-end for using printf-style formatting.
Implementation namespace for support and library code.
Derived specific exceptions within Lumiera&#39;s exception hierarchy.
Definition: error.hpp:190
Token or Atom with distinct identity.
Definition: symbol.hpp:117
A handle to allow for safe »remote implantation« of an unknown subclass into a given opaque InPlaceBu...
Definition: record.hpp:104
static const Ref END
symbolic ID ref "_END_"
Definition: gen-node.hpp:862
virtual bool mutateChild(GenNode const &spec, TreeMutator::Handle targetBuff) override
if this binding layer is in charge, then invoke the closure, which is assumed to construct a nested T...
Marker types to indicate a literal string and a Symbol.
bool isApplicable(GenNode const &spec)
hard wired "selector predicate" for this binding layer.
virtual bool assignElm(GenNode const &spec) override
invoke the setter lambda, when this binding layer is in charge
virtual bool accept_until(GenNode const &spec) override
there is no real support for navigating to a &#39;position&#39;, since attribute / data field binding has no ...
virtual void skipSrc(GenNode const &refSpec) override
any reordering or deletion of object fields is prohibited
Generic building block for tree shaped (meta)data structures.
virtual bool injectNew(GenNode const &spec) override
while, strictly speaking, one can not "insert" fields into a given class definition, this binding can tolerate an INS verb whenever this means to touch a field which is actually known and present in the class definition underlying this binding.
Lumiera error handling (C++ interface).
static const Ref ATTRIBS
symbolic ID ref "_ATTRIBS_"
Definition: gen-node.hpp:865
Customisable intermediary to abstract generic tree mutation operations.
Bare symbolic and hash ID used for accounting of asset like entries.
virtual bool injectNew(GenNode const &spec) override
default setup: silently absorb insert.
generic data element node within a tree
Definition: gen-node.hpp:222