Lumiera  0.pre.03
»edit your freedom«
Builder< PAR > Struct Template Reference

#include "lib/diff/tree-mutator.hpp"

Description

template<class PAR>
struct lib::diff::anonymous_namespace{tree-mutator.hpp}::Builder< PAR >

Builder-DSL to create and configure a concrete TreeMutator.

Remarks
all generated follow-up builders are chained and derive from the implementation of the preceding "binding layer" and the TreeMutator interface.
Note
on each chained builder call, the compound is moved "inside out" into the next builder.

Definition at line 122 of file tree-mutator.hpp.

Public Member Functions

 Builder (PAR &&par)
 
template<typename BIN >
auto attach (BIN &&collectionBindingSetup)
 set up a binding to a structure of "child objects", implemented through a typical STL container More...
 
auto attach (Rec::Mutator &targetTree)
 set up binding to a GenNode tree: Special setup to build a concrete TreeMutator. More...
 
auto attachDummy (TestMutationTarget &dummy)
 set up a diagnostic layer, binding to TestMutationTarget. More...
 
template<typename BIN , typename... ARGS>
Builder< BIN > chainedBuilder (ARGS &&...args)
 
template<typename CLO >
auto change (Symbol attributeID, CLO setterClosure)
 set up a binding to represent an "attribute" through a data or object field. More...
 
auto ignoreAllChanges ()
 set up a catch-all and ignore-everything layer
 
template<typename CLO >
auto mutateAttrib (Symbol attributeID, CLO mutatorBuilderClosure)
 set up a binding for an object valued "attribute" or named scope. More...
 
template<typename CLO >
auto mutateAttrib (idi::BareEntryID const &rawID, CLO mutatorBuilderClosure)
 
template<typename LIS >
auto onLocalChange (LIS changeListener)
 attach a listener function, to be invoked on any local change. This includes the structural changes, but also value assignments to any attribute or element. More...
 
template<typename LIS >
auto onSeqChange (LIS changeListener)
 attach a listener function, to be invoked on structural changes. Here, we define any change as "structural", which alters the sequence of child elements, as opposed to their content. More...
 

Member Function Documentation

◆ change()

auto change ( Symbol  attributeID,
CLO  setterClosure 
)

set up a binding to represent an "attribute" through a data or object field.

This binding will allow to apply basic diff operations, but no re-ordering or deletion. Rationale is the fixed nature of a class definition, which does not support any notion of ordering, or adding and removal of members.

Parameters
attributeIDsymbolic key to denote this "attribute"
setterClosurefunctor or lambda to apply a new value
Note
the nominal value type of the "attribute" is picked up from the setterClosure's (single) argument. It must be one of the types supported as payload for GenNode. In case the target data field needs any other value type, it is the closure's responsibility to convert appropriately.
the combination of attributeID and nominal value type is used to build an (EntryID). The hash of this EntryID needs to match the GenNode::ID in any diff verb considered to be "applicable" to this attribute and binding. Similar to GenNode, the provided attributeID is used as-is, without further sanitising.
Returns
a chained builder, which establishes this building and can then be used to define additional binding layers on top

◆ mutateAttrib() [1/2]

auto mutateAttrib ( Symbol  attributeID,
CLO  mutatorBuilderClosure 
)

set up a binding for an object valued "attribute" or named scope.

This covers the rather special case, where some relevant sub object is accessed as a (named) property of a managing parent object. On implementation level, this corresponds to using a getter to access a subcomponent or "PImpl". On a formal level, for tree diff handling, such counts as attribute, yet with the special twist that we can not just assign a new "value", but rather have to enter a sub scope and handle a nested diff – similar to how nested child objects are dealt with in general. Thus, all we need here is a way how to build a nested TreeMutator for this sub-scope.

Parameters
attributeIDsymbolic key to denote this "attribute"
mutatorBuilderClosurefunctor or lambda to emplace a custom sub TreeMutator into the given buffer (handle). Such a nested mutator shall be wired internally to the object representation of the attribute in question.
See also
CollectionBindingBuilder::buildChildMutator

◆ mutateAttrib() [2/2]

auto mutateAttrib ( idi::BareEntryID const &  rawID,
CLO  mutatorBuilderClosure 
)
Parameters
rawIDthe explicitly given ID of an attribute object, used literally to match the attribute in question

◆ attach() [1/2]

auto attach ( BIN &&  collectionBindingSetup)

set up a binding to a structure of "child objects", implemented through a typical STL container

Parameters
collectionBindingSetupas created by invoking a nested DSL, initiated by a builder function collection(implRef), where implRef is a (language) reference to a STL compliant container existing somewhere within the otherwise opaque implementation. The type of the container and thus the type of the elements will be picked up, and the returned builder can be further outfitted with the builder methods, which take lambdas as callback into the implementation.
  • the matcher closure (CollectionBindingBuilder::matchElement) defines how to determine, if an implementation data element "matches" a given diff spec
  • the constructor closure (CollectionBindingBuilder::constructFrom) defines how to build a new implementation data element from the spec of an INS diff verb. Note: the result will be moved (move-constructed) into the target container.
  • the optional selector closure (CollectionBindingBuilder::isApplicableIf) allows to limit applicability of this whole binding (layer) to only some diff specs. E.g., we may set up a binding for elements with value semantics and another binding layer on top to deal with object like children (sub scopes). Please note that this selector also gets to judge upon the Ref::ATTRIBS spec, which indicates if this layer's contents can be considered "attributes".
  • the optional setter closure (CollectionBindingBuilder::assignElement) accepts a diff spec (GenNode) and should assign an equivalent value to the internal data representation of the corresponding element (typically by constructing an implementation data element and then invoking the corresponding setter)
  • the optional mutator closure (CollectionBindingBuilder::buildChildMutator) allows for recursive descent into nested child scopes. On invocation, it has to build a suitable custom TreeMutator implementation into the provided buffer (handle), and this nested TreeMutator should be wired with the internal representation of the nested scope to enter. At this point, the implementation can safely assume that the given target data element has already be checked with the configured matcher closure, and thus can be considered equivalent to the given ID. The code invoking this closure then typically pushes the buffer onto some internal stack and switches then to use this nested mutator until encountering the corresponding EMU bracket verb.
Note
the after(Ref::ATTRIBS) verb can only processed if the selector responds correct to a Ref::ATTRIBS spec. The implicit default selector does so, i.e. it rejects Ref::ATTRIBS. Please be sure to accept this token only if your layer indeed holds something meant to implement "attributes", because in that case, the verb after(Ref::ATTRIBS) will fast forward and accept all the current contents of this layer
Warning
please note the nested DSL. The builder functions used to define the various closures are to be invoked on the argument ("`collection(xyz)`"), not on the top level builder...

◆ attach() [2/2]

auto attach ( Rec::Mutator targetTree)

set up binding to a GenNode tree: Special setup to build a concrete TreeMutator.

This decorator is already outfitted with the necessary closures to work on a diff::Record<GenNode> – which is typically used as "meta representation" of object-like structures. Thus this binding allows to apply a MutationMessage onto such a given »External Tree Description«, mutating it into new shape.

Remarks
our meta representation of "objects" is based on Record<GenNode>, which is implemented through two STL collections, one for the attributes and one for the child elements. Thus we'll using two binding layers, based on the ChildCollectionMutator, configured with the necessary lambdas.

◆ attachDummy()

auto attachDummy ( TestMutationTarget dummy)

set up a diagnostic layer, binding to TestMutationTarget.

This can be used to monitor the behaviour of the resulting TreeMutator for tests.

Definition at line 530 of file test-mutation-target.hpp.

◆ onSeqChange()

auto onSeqChange ( LIS  changeListener)

attach a listener function, to be invoked on structural changes. Here, we define any change as "structural", which alters the sequence of child elements, as opposed to their content.

In practice, this listener will be invoked after applying a diff with any INS, DEL, FIND, SKIP verb.

Remarks
in theory, one could also drop contents indirectly, by sending only part of the necessary PICK verbs (or using AFTER(...)). However, such a diff is formally not allowed, and will indeed be detected as error when leaving a scope, in ChildCollectionMutator::completeScope()

◆ onLocalChange()

auto onLocalChange ( LIS  changeListener)

attach a listener function, to be invoked on any local change. This includes the structural changes, but also value assignments to any attribute or element.

Note
mutation of a nested child scope will not trigger this listener.
+ Inheritance diagram for Builder< PAR >:
+ Collaboration diagram for Builder< PAR >:

The documentation for this struct was generated from the following files: