finish and document some loose ends

...with the exception of a GenNode binding, the whole
diff application and binding framework is now built and ready for use
This commit is contained in:
Fischlurch 2016-08-29 22:14:03 +02:00
parent ffd40d86e7
commit 3774960dcc
5 changed files with 129 additions and 39 deletions

View file

@ -26,7 +26,17 @@
** Decision how to access the target structure and how to construct
** a suitable TreeMutator as attached to this opaque target data.
**
** @todo this is WIP as of 8/2016
** In a nutshell, if some private data structure wants to receive
** mutation diff messages...
** - it must either implement the interface DiffMutable
** - or provide the function point `void buildMutator(TreeMutator::Handle)`
** Additionally, when the size of the custom TreeMutator object exceeds some
** hard wired limit (200 bytes), then the target type also needs to define
** the extension point `size_t treeMutatorSize(TargetType)`
**
** All of this boils down to somewhere / somehow using the TreeMutator::Builder
** (a DSL API) to construct a custom binding, which allows to talk to our
** private data structure through the TreeMutator interface.
**
** @see DiffComplexApplication_test
** @see DiffTreeApplication_test
@ -91,7 +101,7 @@ namespace diff{
constexpr size_t
treeMutatorSize (...)
treeMutatorSize (...) ///< fallback to detect absence of a custom definition
{
return 0;
}
@ -120,7 +130,7 @@ namespace diff{
/* ======= derive a TreeMutator binding for a given opaque data structure ======= */
/* ======= derive TreeMutator binding for a given opaque data structure ======= */
using meta::enable_if;
@ -139,8 +149,7 @@ namespace diff{
META_DETECT_FUNCTION (void, buildMutator, (TreeMutator::Handle));
public:
enum{ value = HasFunSig_buildMutator<T>::value
};
enum{ value = HasFunSig_buildMutator<T>::value };
};
@ -188,6 +197,16 @@ namespace diff{
using Ret = Wrapper;
};
/**
* public access point to this configuration machinery
* @return depending on the circumstances, either a direct reference
* to DiffMutable, or a transient functor object implementing
* the DiffMutable interface
* @warning beware of dangling references! either use this call immediately
* inline, or (preferably) use an `auto` typed variable to hold
* the return value in local scope as long as necessary
*/
template<class TAR>
auto
mutatorBinding (TAR& subject) -> typename TreeDiffTraits<TAR>::Ret

View file

@ -371,7 +371,7 @@
template<class FUN>
CollectionBindingBuilder<COLL, FUN ,CTR,SEL,ASS,MUT>
matchElement (FUN matcher)
matchElement (FUN matcher) ///< expected lambda: `bool(GenNode const& spec, Elm const& elm)`
{
return { this->collection
, matcher
@ -384,7 +384,7 @@
template<class FUN>
CollectionBindingBuilder<COLL,MAT, FUN ,SEL,ASS,MUT>
constructFrom (FUN constructor)
constructFrom (FUN constructor) ///< expected lambda: `Elm (GenNode const&)`
{
return { this->collection
, this->matches
@ -397,7 +397,7 @@
template<class FUN>
CollectionBindingBuilder<COLL,MAT,CTR, FUN ,ASS,MUT>
isApplicableIf (FUN selector)
isApplicableIf (FUN selector) ///< expected lambda: `bool(GenNode const&)`
{
return { this->collection
, this->matches
@ -410,7 +410,7 @@
template<class FUN>
CollectionBindingBuilder<COLL,MAT,CTR,SEL, FUN ,MUT>
assignElement (FUN setter)
assignElement (FUN setter) ///< expected lambda: `bool(Elm&, GenNode const&)`
{
return { this->collection
, this->matches
@ -423,7 +423,7 @@
template<class FUN>
CollectionBindingBuilder<COLL,MAT,CTR,SEL,ASS, FUN >
buildChildMutator (FUN childMutationBuilder)
buildChildMutator (FUN childMutationBuilder) ///< expected lambda: `bool(Elm&, GenNode::ID const&, TreeMutator::Handle)`
{
return { this->collection
, this->matches

View file

@ -441,7 +441,21 @@ namespace diff{
return Change<CLO> (attributeID, setterClosure, move(*this));
}
///////////////////////////////////////TODO documentation
/** 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.
* @param attributeID symbolic key to denote this "attribute"
* @param mutatorBuilderClosure functor 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 CollectionBindingBuilder::buildChildMutator
*/
template<typename CLO>
Builder<MutateAttrib<CLO>>
mutateAttrib (Symbol attributeID, CLO mutatorBuilderClosure)
@ -450,7 +464,8 @@ namespace diff{
return MutateAttrib<CLO> (key, mutatorBuilderClosure, move(*this));
}
///////////////////////////////////////TODO define variant taking a GenNode::ID
///////////////////////////////////////TODO define variant taking a GenNode::ID ??
/** set up a binding to a structure of "child objects",
* implemented through a typical STL container
@ -461,6 +476,25 @@ namespace diff{
* 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
* - 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)
* - 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. The code invoking this closure
* typically pushes the buffer on some internal stack and switches then to use
* this nested mutator until encountering the corresponding `EMU` bracket verb.
*/
template<typename BIN>
Builder<Collection<BIN>>

View file

@ -8049,7 +8049,7 @@ Used this way, diff representation helps to separate structure and raw data in e
:Chunks of raw data are attached inline to the structural diff, assuming that each element implicitly knows the kind of data to expect
</pre>
</div>
<div title="TreeDiffImplementation" creator="Ichthyostega" modifier="Ichthyostega" created="201412210015" modified="201602190009" tags="Model GuiPattern design draft" changecount="54">
<div title="TreeDiffImplementation" creator="Ichthyostega" modifier="Ichthyostega" created="201412210015" modified="201608292011" tags="Model GuiPattern design draft" changecount="61">
<pre>//This page details decisions taken for implementation of Lumiera's diff handling framework//
This topic is rather abstract, since diff handling is multi purpose within Lumiera: Diff representation is seen as a meta language and abstraction mechanism; it enables tight collaboration without the need to tie and tangle the involved implementation data structures. Used this way, diff representation reduces coupling and helps to cut down overall complexity -- so to justify the considerable amount of complexity seen within the diff framework implementation.
@ -8068,7 +8068,7 @@ Provided as a loosely coupled collection of tools in the namespace {{{lib::diff}
:*differences are spelled out in ''linearised form'': as a sequence of constant-size diff actions (called &amp;raquo;diff verbs&amp;laquo;)
:*these are conceived as operations, which, when applied consuming the input sequence, will produce the target sequence of the diff.
!{{red{WIP 12/2014}}}building a list diff detector
!building a list diff detector
transforming the algorithm sketch (&amp;rarr; see [[technical documentation|http://lumiera.org/documentation/technical/library/DiffFramework.html]]) into working code incurs some challenges at the level of technical details.
!!!interface of the index component
@ -8081,7 +8081,7 @@ A first attempt was made to come up with a rather clever swapping and rotating s
!!!goal of a generic implementation
The diff handling framework we intend to build here is meant to be //generic// -- the actual element data type, as well as the underlying data structure and the index access shall be supplied by strategy and specialisation. This has the downside (maybe this is even a benefit?) that most efficiency considerations are moot at this level; we need to look at actual use cases and investigate the composite performance in practice later.
!{{red{WIP 1/2015}}}building the tree diff handling
!building the tree diff handling
Our tree diff handling framework is conceived as a direct specialisation of and extension to list diffing. We rely on a very specific element type for the tree nodes: the GenNode. This specific node element type is inherently generic, and the tree diff handling explicitly relies on some part of this generic nature to represent object features. Following the gist of the linearised list diff representation, also tree handling relies on an implicit ''tree representation protocol'':
* every GenNode is a distinct element and considered unique within context.
* nodes are inherently typed, but this typing is outside of the diff representation scope
@ -8141,9 +8141,23 @@ Within the context of GuiModelUpdate, we discern two distinct situations necessi
* a GenNode representing an object pulls diff information provided by Proc. This information contains mutations of attributes, and //some// of these attributes are relevant for the GUI and thus represented within the GuiModel
* a widget was notified of pending changes in the GuiModel and calls back to pull a diff. While interpreting the attributes mentioned in the diff, it has to determine which widget state corresponds to the mentioned attributes, if applicable. Detected changes need to be interpreted and pushed into the corresponding widget and GTK elements.
the second case is what poses the real challenge in terms of writing well organised code. Since in that case, the receiver side has to translate generic diff verbs into operations on hard wired language level data structures -- structures, we can not control, predict or limit beforhand. We deal with this situation by introducing a specific intermediary, the &amp;rarr; TreeMutator.
</pre>
!!!apply a diff onto implementation data
Thus we need to carry the idea one step further. The goal is to allow a loose cooperation of components, without the need of a common data structure set in stone. Up to now, with our symbolic diff language and tree representation, we're able to render objects in some kind of DOM notation, and we're able to apply changes onto them. This is fine for maintaining an intermediary GuiModel, but to really achieve the desired loose coupling of cooperating components, we need //the ability to apply changes to implementation data structures.// To do so, we need a ''binding'' from the diff language to »''implemetation data''« -- without imposing restrictions onto the latter: We do not intend to invent yet another introspection framework, working on yet another meta object type. Thus, at some point, finally we need the help of the implementation context to //make sense of the diff verbs.//
As said, this turns out to be a tricky challenge: implementing the application of diff messages is inevitably an involved and technical task; we should avoid imposing these technicalities onto client code. But, at minimum, we need to know some basic traits regarding the target data structures, in order to handle receiving change messages properly. We solve this problem through implicit conventions plus an indirection layer
* we impose some very vague requirements onto the structure of target data: it is required to comply to our conceptual notion of an &quot;object&quot;; target data //needs to be congruent to [[ETD|ExternalTreeDescription]].//
* we introduce an adapter interface, the TreeMutator. Diff application can then be implemented in terms of this new abstraction
* we offer pre configured building blocks and a DSL, for client code to assemble a suitable {{{TreeMutator}}} implementation, privately tied into the opaque implementation data structure
* client code has to fill in some necessary information in the form of ''closures'' (lambdas)
** how to construct a new data element
** how to match a //diff verb// against a given data element
** how to determine applicability of a verb, allowing for multi layered binding
** how to assign a new value, given the corresponding diff verb
** how to open a nested scope for recursive mutation
</pre>
</div>
<div title="TreeDiffModel" creator="Ichthyostega" modifier="Ichthyostega" created="201410270313" modified="201602191532" tags="Model GuiPattern spec draft" changecount="63">
<div title="TreeDiffModel" creator="Ichthyostega" modifier="Ichthyostega" created="201410270313" modified="201608291945" tags="Model GuiPattern spec draft" changecount="64">
<pre>for the purpose of handling updates in the GUI timeline display efficiently, we need to determine and represent //structural differences//
This leads to what could be considered the very opposite of data-centric programming. Instead of embody »the truth« into a central data model with predefined layout, we base our achitecture on a set of actors and their collaboration. In the mentioned example this would be the high-level view in the Session, the Builder, the UI-Bus and the presentation elements within the timeline view. Underlying to each such collaboration is a shared conception of data. There is no need to //actually represent that data// -- it can be conceived to exist in a more descriptive, declarative [[external tree description (ETD)|ExternalTreeDescription]]. In fact, what we //do represent// is a ''diff'' against such an external rendering.
@ -8210,7 +8224,7 @@ To complement this language construct, we define some special, magical (meta) el
All these additional language constructs aren't strictly necessary, but widen the usability of the langauge, also to cover the description of incomplete or fuzzy diffs.
!!!deriving conventional representations
On receiving the terms of this &quot;diff language&quot;, it is possible to generate the well known and more conventional diff representations,
On receiving a stream of tokens of this &quot;diff language&quot;, it is possible to generate the well known and more conventional diff representations,
i.e. a ''unified diff'' or the ''predicate notation'' used above to describe the list diffing algorithm, just by accumulating changes.
</pre>
</div>

View file

@ -2416,7 +2416,7 @@
</node>
</node>
</node>
<node CREATED="1457232734636" FOLDED="true" ID="ID_1873945047" MODIFIED="1472219585812" TEXT="STL Collection">
<node CREATED="1457232734636" ID="ID_1873945047" MODIFIED="1472498604863" TEXT="STL Collection">
<icon BUILTIN="full-2"/>
<node CREATED="1458175823858" ID="ID_438044714" MODIFIED="1458175828956" TEXT="Design-Grundlagen">
<node CREATED="1457741673001" ID="ID_1873415490" MODIFIED="1457742700335" TEXT="konkrete Beispiele">
@ -2628,7 +2628,7 @@
<node CREATED="1458178223723" ID="ID_798018180" MODIFIED="1458178247755" TEXT="es gibt eine freie Funktion, die einen nested Builder f&#xfc;r das Binding liefert"/>
</node>
</node>
<node COLOR="#338800" CREATED="1458178288690" FOLDED="true" ID="ID_562189277" MODIFIED="1470521349868" TEXT="Implementierung">
<node COLOR="#338800" CREATED="1458178288690" FOLDED="true" ID="ID_562189277" MODIFIED="1472498684254" TEXT="Implementierung">
<icon BUILTIN="button_ok"/>
<node CREATED="1458178298328" ID="ID_1964300614" MODIFIED="1458178300324" TEXT="Builder">
<node CREATED="1458325962991" ID="ID_1955400674" MODIFIED="1460753004725" TEXT="Typ-Definitionen schwierig anzuschreiben">
@ -2637,7 +2637,7 @@
<node CREATED="1458325973486" ID="ID_1711903796" MODIFIED="1458325992405" TEXT="Code ziemlich redundant und undurchsichtig">
<icon BUILTIN="messagebox_warning"/>
</node>
<node CREATED="1458326045724" ID="ID_338749301" MODIFIED="1461878392468" TEXT="Typ-Check erst sehr sp&#xe4;t">
<node CREATED="1458326045724" ID="ID_338749301" MODIFIED="1472498604875" TEXT="Typ-Check erst sehr sp&#xe4;t">
<richcontent TYPE="NOTE"><html>
<head>
@ -2656,9 +2656,13 @@
eine wom&#246;glich irref&#252;hrende Meldung generiert
</p>
</body>
</html></richcontent>
</html>
</richcontent>
<arrowlink DESTINATION="ID_428365633" ENDARROW="Default" ENDINCLINATION="176;0;" ID="Arrow_ID_1501436647" STARTARROW="None" STARTINCLINATION="176;0;"/>
</node>
<node CREATED="1472498654730" ID="ID_1869339299" MODIFIED="1472498676884" TEXT="gel&#xf6;st durch static_assert">
<icon BUILTIN="button_ok"/>
</node>
</node>
<node CREATED="1458178300984" ID="ID_1152672899" MODIFIED="1458178309971" TEXT="Binding-Layer">
<node CREATED="1458850722203" ID="ID_1565475995" MODIFIED="1458850731470" TEXT="Fehler bei fehlender Funktionalit&#xe4;t">
@ -4392,8 +4396,8 @@
</node>
</node>
</node>
<node CREATED="1465428839332" ID="ID_909803930" MODIFIED="1465665730709" TEXT="Diff-Anwendung" VSHIFT="36">
<icon BUILTIN="pencil"/>
<node CREATED="1465428839332" ID="ID_909803930" MODIFIED="1472495575428" TEXT="Diff-Anwendung" VSHIFT="36">
<icon BUILTIN="button_ok"/>
<node CREATED="1465428850946" ID="ID_1085608480" MODIFIED="1465428866278">
<richcontent TYPE="NODE"><html>
<head>
@ -4883,20 +4887,31 @@
<node CREATED="1465864167187" ID="ID_1126324374" MODIFIED="1465864171974" TEXT="Aufruf: freie Funktion"/>
<node CREATED="1465864172514" ID="ID_523639016" MODIFIED="1465864180668" TEXT="delegiert auf Template"/>
<node CREATED="1465864181193" ID="ID_214760095" MODIFIED="1465864192611" TEXT="explizite / regelbasierte Spezialisierung"/>
<node CREATED="1465864193607" ID="ID_910823091" MODIFIED="1465864216053" TEXT="Problem: Storage f&#xfc;r die Closure">
<node CREATED="1465864193607" FOLDED="true" ID="ID_910823091" MODIFIED="1472495561111" TEXT="Problem: Storage f&#xfc;r die Closure">
<icon BUILTIN="messagebox_warning"/>
<node CREATED="1465864217628" ID="ID_234805162" MODIFIED="1465864228510" TEXT="typischerweise sind alles transiente Objekte"/>
<node CREATED="1465864229170" ID="ID_1100042937" MODIFIED="1465864240501" TEXT="also mu&#xdf; die Closure als Wert-Objekt rausgegeben werden"/>
<node CREATED="1465864247152" ID="ID_1684145985" MODIFIED="1465864259507" TEXT="gesucht: elegantes API">
<icon BUILTIN="pencil"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1472219502519" ID="ID_602618555" MODIFIED="1472219513437" TEXT="noch fertig zu integrieren....">
<icon BUILTIN="flag-yellow"/>
<node CREATED="1472495487478" FOLDED="true" ID="ID_57266631" MODIFIED="1472495543911" TEXT="L&#xf6;sung...">
<node CREATED="1472495496574" ID="ID_618531871" MODIFIED="1472495510056" TEXT="auto typed return value"/>
<node CREATED="1472495510531" ID="ID_1366125392" MODIFIED="1472495513703" TEXT="keep in local scope"/>
<node CREATED="1472495514203" ID="ID_1694911368" MODIFIED="1472495529197" TEXT="tightly integrate into ctor of DiffAplicator"/>
</node>
<node CREATED="1465864247152" ID="ID_1684145985" MODIFIED="1472494408902" TEXT="gesucht: elegantes API">
<node CREATED="1472494557762" ID="ID_1916007342" MODIFIED="1472494575309" TEXT="DiffAplicator&lt;TargetTyp&gt;">
<icon BUILTIN="idea"/>
</node>
<node CREATED="1472494413960" ID="ID_1460674703" MODIFIED="1472494571740" TEXT="Erweiterungspunkt f&#xfc;r ADL..."/>
<node CREATED="1472494432219" ID="ID_1801329518" MODIFIED="1472494446981" TEXT="...wird vom ctor des Diff-Applikators verwendet"/>
<node CREATED="1472494466926" ID="ID_1882750560" MODIFIED="1472494484296" TEXT="...und der wiederum greift nur"/>
<node CREATED="1472494485388" ID="ID_1744987934" MODIFIED="1472494501141" TEXT="...wenn TreeDiffTraits definiert sind"/>
<node CREATED="1472494501778" ID="ID_300920526" MODIFIED="1472494506323" TEXT="not too bad">
<icon BUILTIN="ksmiletris"/>
</node>
</node>
</node>
</node>
<node CREATED="1465860736044" ID="ID_40337378" MODIFIED="1472122049229" TEXT="Implementierung">
<icon BUILTIN="pencil"/>
<node CREATED="1465860736044" ID="ID_40337378" MODIFIED="1472494390376" TEXT="Implementierung">
<icon BUILTIN="button_ok"/>
<node CREATED="1472121965308" ID="ID_292673963" MODIFIED="1472121974646" TEXT="Verb delegiert an Mutator-Primitive"/>
<node CREATED="1472121976018" ID="ID_421028989" MODIFIED="1472121995995" TEXT="Fehlerbehandlung anhand R&#xfc;ckgabewert dieser"/>
<node CREATED="1472122015157" ID="ID_151735071" MODIFIED="1472122038334" TEXT="sinnvolle interne Fehler-Funktionen aufbauen"/>
@ -5004,9 +5019,9 @@
</node>
</node>
</node>
<node CREATED="1465860740971" ID="ID_1662787747" MODIFIED="1472219629782" TEXT="Unit-Test">
<node CREATED="1465860740971" ID="ID_1662787747" MODIFIED="1472494384251" TEXT="Unit-Test">
<linktarget COLOR="#a9b4c1" DESTINATION="ID_1662787747" ENDARROW="Default" ENDINCLINATION="114;0;" ID="Arrow_ID_1608349913" SOURCE="ID_1209021141" STARTARROW="None" STARTINCLINATION="114;0;"/>
<icon BUILTIN="pencil"/>
<icon BUILTIN="button_ok"/>
<node CREATED="1472122365079" ID="ID_1033283113" MODIFIED="1472122376193" TEXT="Aussagekr&#xe4;ftiges Beispiel-Diff">
<node CREATED="1472122379548" ID="ID_270981817" MODIFIED="1472122384864" TEXT="sollte alle Features vorf&#xfc;hren"/>
<node CREATED="1472122385380" ID="ID_773660909" MODIFIED="1472122391943" TEXT="sollte wichtige Grenzf&#xe4;lle aktivieren"/>
@ -5080,7 +5095,7 @@
<font NAME="SansSerif" SIZE="14"/>
<icon BUILTIN="flag-yellow"/>
<node CREATED="1458850122091" ID="ID_15024219" MODIFIED="1458850140244" TEXT="Collection-Binding: bessere Fehlermeldungen">
<node CREATED="1458850141920" ID="ID_428365633" MODIFIED="1472219338977" TEXT="bei Signatur-Mismatch">
<node CREATED="1458850141920" ID="ID_428365633" MODIFIED="1472498706370" TEXT="bei Signatur-Mismatch">
<richcontent TYPE="NOTE"><html>
<head>
@ -5093,6 +5108,7 @@
</html>
</richcontent>
<linktarget COLOR="#a9b4c1" DESTINATION="ID_428365633" ENDARROW="Default" ENDINCLINATION="176;0;" ID="Arrow_ID_1501436647" SOURCE="ID_338749301" STARTARROW="None" STARTINCLINATION="176;0;"/>
<icon BUILTIN="button_ok"/>
</node>
<node CREATED="1458850154575" ID="ID_725958518" MODIFIED="1472219338982" TEXT="wenn der Default-Matcher greift">
<richcontent TYPE="NOTE"><html>
@ -5108,12 +5124,20 @@
</richcontent>
</node>
</node>
<node CREATED="1458850212503" ID="ID_321552356" MODIFIED="1458850218977" TEXT="Signaturen f&#xfc;r Lambdas dokumentieren"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1465860661877" ID="ID_942624903" MODIFIED="1465860714295" TEXT="Builder-API f&#xfc;r Attribut-Binding dokumentieren">
<icon BUILTIN="flag-yellow"/>
<node CREATED="1458850212503" ID="ID_321552356" MODIFIED="1472498583464" TEXT="Signaturen f&#xfc;r Lambdas dokumentieren">
<icon BUILTIN="button_ok"/>
</node>
<node CREATED="1465860661877" ID="ID_942624903" MODIFIED="1472498127725" TEXT="Builder-API f&#xfc;r Attribut-Binding dokumentieren">
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1465860672852" ID="ID_432641404" MODIFIED="1465860718271" TEXT="Variante zum Attribut-Binding, wobei die Attribut-ID als GenNode::ID gegeben ist">
<icon BUILTIN="flag-yellow"/>
<node CREATED="1472498724880" ID="ID_1122881728" MODIFIED="1472498733392" TEXT="f&#xfc;r sp&#xe4;ter">
<icon BUILTIN="yes"/>
</node>
<node CREATED="1472498734359" ID="ID_888090802" MODIFIED="1472498742262" TEXT="brauchen wir das wirklich">
<icon BUILTIN="help"/>
</node>
</node>
<node CREATED="1460847222865" ID="ID_362820787" MODIFIED="1472219338993" TEXT="abstrakte operationale Semantik der Diff-Anwendung dokumentieren">
<richcontent TYPE="NOTE"><html>
@ -5163,8 +5187,7 @@
</node>
<node CREATED="1472216217388" HGAP="21" ID="ID_1810727202" MODIFIED="1472216290504" TEXT="Semantik der Diff-Sprache" VSHIFT="5">
<node CREATED="1472216261102" ID="ID_1057680407" MODIFIED="1472216264937" TEXT="sinnvoll definiert"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1472216265486" ID="ID_1774905589" MODIFIED="1472216278990" TEXT="sp&#xe4;ter re-evaluieren (Ticket)">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1472216265486" ID="ID_1774905589" MODIFIED="1472495973662" TEXT="sp&#xe4;ter re-evaluieren (Ticket #996)">
<node CREATED="1472216306208" ID="ID_310892577" MODIFIED="1472216342802" TEXT="AFTER">
<arrowlink DESTINATION="ID_1957591180" ENDARROW="Default" ENDINCLINATION="-27;14;" ID="Arrow_ID_228215960" STARTARROW="None" STARTINCLINATION="139;3;"/>
</node>