Lumiera 0.pre.04
»edit your freedom«
Loading...
Searching...
No Matches
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"
104#include "lib/format-string.hpp"
105#include "lib/idi/entry-id.hpp"
106
107#include <utility>
108
109
110namespace lib {
111namespace diff{
112
113 namespace { // Mutator-Builder decorator components...
114
115
125 template<class PAR>
127 : public PAR
128 {
129
131
132 protected:
133 AttributeBindingBase (BareEntryID attribID, PAR&& chain)
134 : PAR(std::forward<PAR>(chain))
135 , attribID_(attribID)
136 { }
137
145 bool
146 isApplicable (GenNode const& spec)
147 {
148 return spec.isNamed()
149 and attribID_ == spec.idi;
150 }
151
152 void
154 {
155 if (this->isApplicable(spec))
156 throw error::Logic (_Fmt{"attempt to %s attribute '%s', "
157 "but this binding for '%s' is linked to a data field and "
158 "thus does not support any notion of 'order' or 'position', "
159 "inserting or deletion."}
160 % oper % spec.idi % this->attribID_);
161 }
162
163
164 /* ==== re-Implementation of the operation API ==== */
165 public:
171 virtual bool
172 matchSrc (GenNode const& spec) override
173 {
174 return isApplicable (spec)
175 or PAR::matchSrc (spec);
176 }
177
178
179 // note: hasSrc() not overridden here --> delegate to parent layer
180
181
183 virtual bool
184 acceptSrc (GenNode const& spec) override
185 {
186 return isApplicable (spec)
187 or PAR::acceptSrc (spec);
188 }
189
196 virtual void
197 skipSrc (GenNode const& refSpec) override
198 {
199 __ifApplicable_refuse_to ("skip or drop", refSpec);
200 PAR::skipSrc (refSpec);
201 }
202
203 virtual bool
204 findSrc (GenNode const& refSpec) override
205 {
206 __ifApplicable_refuse_to ("re-order", refSpec);
207 return PAR::findSrc (refSpec);
208 }
209
219 virtual bool
220 accept_until (GenNode const& spec) override
221 {
222 if (Ref::END == spec or Ref::ATTRIBS == spec)
223 return PAR::accept_until(spec);
224 else
225 {
226 __ifApplicable_refuse_to ("navigate to a position behind", spec);
227 return PAR::accept_until(spec);
228 }
229 }
230 };
231
232
233
234
235 template<class PAR, class CLO>
237 : public AttributeBindingBase<PAR>
238 {
242
243
245
246 public:
247 ChangeOperation (Symbol attribKey, CLO clo, PAR&& chain)
248 : AttributeBindingBase<PAR>(ID{attribKey}, std::forward<PAR>(chain))
249 , setter_(clo)
250 { }
251
252
253 /* ==== Implementation of value assignment operation ==== */
254
262 virtual bool
263 injectNew (GenNode const& spec) override
264 {
265 if (not this->isApplicable(spec))
266 return PAR::injectNew(spec);
267
268 setter_(spec.data.get<ValueType>());
269 return true;
270 }
271
273 virtual bool
274 assignElm (GenNode const& spec) override
275 {
276 if (not this->isApplicable(spec))
277 return PAR::assignElm(spec);
278
279 setter_(spec.data.get<ValueType>());
280 return true;
281 }
282 };
283
284
285
286 template<class PAR, class MUT>
288 : public AttributeBindingBase<PAR>
289 {
290
292
294
295
296 public:
297 MutationOperation (BareEntryID const& attribID, MUT clo, PAR&& chain)
298 : AttributeBindingBase<PAR>(attribID, std::forward<PAR>(chain))
299 , mutatorBuilder_(clo)
300 { }
301
302
306 virtual bool
307 mutateChild (GenNode const& spec, TreeMutator::Handle targetBuff) override
308 {
309 if (not this->isApplicable(spec))
310 return PAR::mutateChild(spec, targetBuff);
311
312 mutatorBuilder_(targetBuff);
313 return true;
314 }
315
316
332 virtual bool
333 injectNew (GenNode const& spec) override
334 {
335 return this->isApplicable(spec)
336 or PAR::injectNew(spec);
337 }
338 };
339
340
341
343 template<class PAR>
344 template<typename CLO>
345 inline auto
346 Builder<PAR>::change (Symbol attributeID, CLO setterClosure)
347 {
348 return chainedBuilder<ChangeOperation<PAR,CLO>> (attributeID, setterClosure);
349 }
350
351
353 template<class PAR>
354 template<typename CLO>
355 inline auto
356 Builder<PAR>::mutateAttrib (Symbol attributeID, CLO mutatorBuilderClosure)
357 {
358 idi::EntryID<Rec> key{attributeID};
359 return chainedBuilder<MutationOperation<PAR,CLO>> (key, mutatorBuilderClosure);
360 }
361
363 template<class PAR>
364 template<typename CLO>
365 inline auto
366 Builder<PAR>::mutateAttrib (idi::BareEntryID const& rawID, CLO mutatorBuilderClosure)
367 {
368 return chainedBuilder<MutationOperation<PAR,CLO>> (rawID, mutatorBuilderClosure);
369 }
370
371
372
373 }//(END)Mutator-Builder decorator components...
374
375}} // namespace lib::diff
376#endif /*LIB_DIFF_TREE_MUTATOR_ATTRIBUTE_BINDING_H*/
Inline string literal.
Definition symbol.hpp:78
A handle to allow for safe »remote implantation« of an unknown subclass into a given opaque InPlaceBu...
Token or Atom with distinct identity.
Definition symbol.hpp:120
virtual bool accept_until(GenNode const &spec) override
there is no real support for navigating to a 'position', since attribute / data field binding has no ...
virtual bool matchSrc(GenNode const &spec) override
ensure the given spec is deemed appropriate at that point.
virtual bool acceptSrc(GenNode const &spec) override
accept status quo, after verifying the spec from the diff verb
virtual void skipSrc(GenNode const &refSpec) override
any reordering or deletion of object fields is prohibited
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 injectNew(GenNode const &spec) override
while, strictly speaking, one can not "insert" fields into a given class definition,...
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...
virtual bool injectNew(GenNode const &spec) override
default setup: silently absorb insert.
type erased baseclass for building a combined hash and symbolic ID.
Definition entry-id.hpp:134
A front-end for using printf-style formatting.
Bare symbolic and hash ID used for accounting of asset like entries.
Lumiera error handling (C++ interface).
Front-end for printf-style string template interpolation.
Generic building block for tree shaped (meta)data structures.
»Empty« mark
Definition typelist.hpp:82
Implementation namespace for support and library code.
LumieraError< LERR_(LOGIC)> Logic
Definition error.hpp:207
STL namespace.
generic data element node within a tree
Definition gen-node.hpp:224
bool isNamed() const
Definition gen-node.hpp:337
Builder-DSL to create and configure a concrete TreeMutator.
typed symbolic and hash ID for asset-like position accounting.
Definition entry-id.hpp:219
Trait template for uniform access to function signature types.
Definition function.hpp:144
Marker types to indicate a literal string and a Symbol.
Customisable intermediary to abstract generic tree mutation operations.
Some basic facilities for manipulating type sequences.