DiffMessage: consider to unite the handling of mutation messages (#1066)

This commit is contained in:
Fischlurch 2017-08-11 15:23:33 +02:00
parent f498f3be1b
commit f6baef16c5
7 changed files with 413 additions and 40 deletions

View file

@ -36,8 +36,9 @@
** @todo as of 8/2017 I am still rather clueless regarding the concrete situation to generate DiffMessage,
** and as a move into the dark I'll just define it to be based on IterSource...
**
** @see DiffMessage_test
** @see AbstractTangible_test
** @see mutation-message.hpp
** @see BusTerm::change()
**
*/

View file

@ -571,6 +571,8 @@ namespace test {
*
* Here in this test case, we use a hard wired diff sequence,
* so we can check the expected structural changes actually took place.
*
* @see DiffMessage_test
*/
void
mutate ()

View file

@ -21,7 +21,11 @@
* *****************************************************/
/** @file diff-complex-application-test.cpp
** unit test \ref DiffComplexApplication_test
** unit test \ref DiffComplexApplication_test.
** Demonstrates the concept of tree mutation by diff messages.
** This is an elaborate demonstration setup to highlight some
** of the more intricate, the flexibility and support for
** and complex opaque implementation variations.
*/
@ -173,11 +177,13 @@ namespace test{
* This function builds a TreeMutator implementation into the given buffer space
* @note some crucial details for this binding to work properly...
* - we define several "onion layers" of binding to deal with various scopes.
* - the priority of these bindings is ordered from lowest to highest
* - the priority of these bindings is layered backwards from lowest to highest,
* i.e. the resulting mutator will fist check for attribute δ and then work
* its way down do the `collection(nestedData_)`
* - actually this is a quite complicated setup, including object fields
* to represent attributes, where one special attribute which actually holds
* a nested object, then both a collection of child objects and a collection
* of data values
* to represent attributes, where only one specific attribute actually holds
* a nested object and thus needs special treatment; beyond that we have both
* a collection of child objects and a collection of child data values
* - the selector predicate (`isApplicableIf`) actually decides if a binding layer
* becomes responsible for a given diff verb. Here, this decision is based on
* the classification of the verb or spec to be handled, either being an
@ -251,8 +257,8 @@ namespace test{
})
.mutateAttrib("δ", [&](TreeMutator::Handle buff)
{
if (not delta_) // note: object managed automatically,
delta_.reset (new Opaque("δ")); // no INS-implementation necessary
if (not delta_) // note: object is managed automatically,
delta_.reset (new Opaque("δ")); // thus no INS-implementation necessary
REQUIRE (delta_);
delta_->buildMutator(buff);
@ -281,7 +287,7 @@ namespace test{
/***********************************************************************//**
* @test Demonstration: apply a structural change to unspecified private
* data structures, with the help of an [dynamic adapter](\ref TreeMutator)
* - we use private data classes, defined here in the test fixture
* - we use private data classes, defined right here in the test fixture
* to represent "just some" pre-existing data structure.
* - we re-assign some attribute values
* - we add, re-order and delete child "elements", without knowing

View file

@ -0,0 +1,225 @@
/*
DiffMessage(Test) - demonstrate the basics of tree diff representation
Copyright (C) Lumiera.org
2017, Hermann Vosseler <Ichthyostega@web.de>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* *****************************************************/
/** @file diff-message-test.cpp
** unit test \ref DiffMessage_test
*/
#include "lib/test/run.hpp"
#include "lib/format-util.hpp"
#include "lib/diff/tree-diff-application.hpp"
#include "lib/iter-adapter-stl.hpp"
#include "lib/time/timevalue.hpp"
#include "lib/format-util.hpp"
#include "lib/util.hpp"
#include <string>
#include <vector>
using lib::iter_stl::snapshot;
using util::isnil;
using util::join;
using std::string;
using std::vector;
using lib::time::Time;
namespace lib {
namespace diff{
namespace test{
namespace {//Test fixture....
// define some GenNode elements
// to act as templates within the concrete diff
// NOTE: everything in this diff language is by-value
const GenNode ATTRIB1("α", 1), // attribute α = 1
ATTRIB2("β", int64_t(2)), // attribute α = 2L (int64_t)
ATTRIB3("γ", 3.45), // attribute γ = 3.45 (double)
TYPE_X("type", "X"), // a "magic" type attribute "X"
TYPE_Y("type", "Y"), //
CHILD_A("a"), // unnamed string child node
CHILD_B('b'), // unnamed char child node
CHILD_T(Time(12,34,56,78)), // unnamed time value child
SUB_NODE = MakeRec().genNode(), // empty anonymous node used to open a sub scope
ATTRIB_NODE = MakeRec().genNode("δ"), // empty named node to be attached as attribute δ
CHILD_NODE = SUB_NODE; // yet another child node, same ID as SUB_NODE (!)
}//(End)Test fixture
/***********************************************************************//**
* @test properties of a container to transport a diff from an abstracted
* source generator to an abstracted consumer.
* - this covers a standard usage scenario within Lumiera, where some
* producer in the Session core detects changes in session structure
* and sends a message to make the UI conform to the new structure
* - #########TODO
* The representation is given as a linearised sequence of verb tokens.
* In addition to the verbs used for list diffing, here we additionally
* have to deal with nested scopes, which can be entered thorough a
* bracketing construct \c mut(ID)...emu(ID).
* This test demonstrates the application of such diff sequences
* - in the first step, an empty root #Record<GenNode> is populated
* with a type-ID, three named attribute values, three child values
* and a nested child-Record.
* - the second step demonstrates various diff language constructs
* to alter, reshape and mutate this data structure
* After applying those two diff sequences, we verify the data
* is indeed in the expected shape.
* @remarks to follow this test, you should be familiar both with our
* \link diff::Record generic data record \endlink, as well as with
* the \link diff::GenNode variant data node \endlink. The key point
* to note is the usage of Record elements as payload within GenNode,
* which allows to represent tree shaped object like data structures.
* @see AbstractTangible_test::mutate() concrete usage scenario for UI-elements
* @see DiffTreeApplication_test change a tree-like data structure by diff
* @see DiffComplexApplication_test handling arbitrary data structures
* @see DiffListApplication_test
* @see DiffMessage
* @see ui-bus.hpp
*/
class DiffMessage_test
: public Test
, TreeDiffLanguage
{
using DiffSeq = iter_stl::IterSnapshot<DiffStep>;
DiffSeq
populationDiff()
{
return snapshot({ins(TYPE_X)
, ins(ATTRIB1)
, ins(ATTRIB2)
, ins(ATTRIB3)
, ins(CHILD_A)
, ins(CHILD_T)
, ins(CHILD_T)
, ins(SUB_NODE)
, mut(SUB_NODE)
, ins(CHILD_B)
, ins(CHILD_A)
, emu(SUB_NODE)
});
}
DiffSeq
mutationDiff()
{
// prepare for direct assignment of new value
// NOTE: the target ID will be reconstructed, including hash
GenNode childA_upper(CHILD_A.idi.getSym(), "A");
return snapshot({after(Ref::ATTRIBS) // fast forward to the first child
, find(CHILD_T)
, pick(CHILD_A)
, skip(CHILD_T)
, del(CHILD_T)
, after(Ref::END) // accept anything beyond as-is
, mut(SUB_NODE)
, ins(ATTRIB3)
, ins(ATTRIB_NODE) // attributes can also be nested objects
, find(CHILD_A)
, del(CHILD_B)
, ins(CHILD_NODE)
, ins(CHILD_T)
, skip(CHILD_A)
, mut(CHILD_NODE)
, ins(TYPE_Y)
, ins(ATTRIB2)
, emu(CHILD_NODE)
, set(childA_upper) // direct assignment, target found by ID (out of order)
, mut(ATTRIB_NODE) // mutation can be out-of order, target found by ID
, ins(CHILD_A)
, ins(CHILD_A)
, ins(CHILD_A)
, emu(ATTRIB_NODE)
, emu(SUB_NODE)
});
}
virtual void
run (Arg)
{
Rec::Mutator target;
Rec& subject = target;
DiffApplicator<Rec::Mutator> application(target);
// Part I : apply diff to populate
application.consume(populationDiff());
CHECK (!isnil (subject)); // nonempty -- content has been added
CHECK ("X" == subject.getType()); // type was set to "X"
CHECK (1 == subject.get("α").data.get<int>()); // has gotten our int attribute "α"
CHECK (2L == subject.get("β").data.get<int64_t>()); // ... the long attribute "β"
CHECK (3.45 == subject.get("γ").data.get<double>()); // ... and double attribute "γ"
auto scope = subject.scope(); // look into the scope contents...
CHECK ( *scope == CHILD_A); // there is CHILD_A
CHECK (*++scope == CHILD_T); // followed by a copy of CHILD_T
CHECK (*++scope == CHILD_T); // and another copy of CHILD_T
CHECK (*++scope == MakeRec().appendChild(CHILD_B) // and there is a nested Record
.appendChild(CHILD_A) // with CHILD_B
.genNode(SUB_NODE.idi.getSym())); // and CHILD_A
CHECK (isnil(++scope)); // thats all -- no more children
// Part II : apply the second diff
application.consume(mutationDiff());
CHECK (join (subject.keys()) == "α, β, γ"); // the attributes weren't altered
scope = subject.scope(); // but the scope was reordered
CHECK ( *scope == CHILD_T); // CHILD_T
CHECK (*++scope == CHILD_A); // CHILD_A
Rec nested = (++scope)->data.get<Rec>(); // and our nested Record, which too has been altered:
CHECK (nested.get("γ").data.get<double>() == 3.45); // it carries now an attribute "δ", which is again
CHECK (nested.get("δ") == MakeRec().appendChild(CHILD_A) // a nested Record with three children CHILD_A
.appendChild(CHILD_A) //
.appendChild(CHILD_A) //
.genNode("δ")); //
auto subScope = nested.scope(); // and within the nested sub-scope we find
CHECK ( *subScope != CHILD_A); // CHILD_A has been altered by assigment
CHECK (CHILD_A.idi == subScope->idi); // ...: same ID as CHILD_A
CHECK ("A" == subScope->data.get<string>()); // ...: but mutated payload
CHECK (*++subScope == MakeRec().type("Y") // a yet-again nested sub-Record of type "Y"
.set("β", int64_t(2)) // with just an attribute "β" == 2L
.genNode(CHILD_NODE.idi.getSym())); // (and an empty child scope)
CHECK (*++subScope == CHILD_T); // followed by another copy of CHILD_T
CHECK (isnil (++subScope)); //
CHECK (isnil (++scope)); // and nothing beyond that.
}
};
/** Register this test class... */
LAUNCHER (DiffMessage_test, "unit common");
}}} // namespace lib::diff::test

View file

@ -21,7 +21,9 @@
* *****************************************************/
/** @file diff-tree-application-test.cpp
** unit test \ref DiffTreeApplication_test
** unit test \ref DiffTreeApplication_test.
** Demonstrates the basic concept of reshaping structured data
** through a tree-diff sequence.
*/
@ -53,7 +55,7 @@ namespace test{
// define some GenNode elements
// to act as templates within the concrete diff
// NOTE: everything in this diff language is by-value
const GenNode ATTRIB1("α", 1), // attribute α = 1
const GenNode ATTRIB1("α", 1), // attribute α = 1
ATTRIB2("β", int64_t(2)), // attribute α = 2L (int64_t)
ATTRIB3("γ", 3.45), // attribute γ = 3.45 (double)
TYPE_X("type", "X"), // a "magic" type attribute "X"

View file

@ -4018,9 +4018,11 @@ As an immediate consequence of not being able to reduce processing to elementary
* the PlayProcess serves to join both views, providing a single PlayController front-end, while [[dispatching|FrameDispatcher]] to single channel processing.
</pre>
</div>
<div title="MutationMessage" creator="Ichthyostega" modifier="Ichthyostega" created="201610011953" modified="201612031608" tags="def" changecount="5">
<div title="MutationMessage" creator="Ichthyostega" modifier="Ichthyostega" created="201610011953" modified="201708111318" tags="def" changecount="7">
<pre>//message on the UI-Bus to cause changes on the targeted UI-Element.//
The UI-Bus offers a dedicated API to direct ~MutationMessages towards {{{Tangible}}} elements, as designated by the given ID. Actually, such messages serve as //capsule to transport a [[diff-sequence|TreeDiffModel]]// -- since a diff sequence as such is always concrete and tied to a specific context, we can not represent it directly as an abstract type at interface level. The receiver of a diff sequence must offer the ability to be reshaped through diff messages, which is expressed through the interface {{{DiffMutable}}}. In our case here, {{{Tangible}}} offers this interface and thus the ability to construct a concrete TreeMutator, which in turn is bound to the internals of the actual UI-Element in question. Together this allows for a generic implementation of MutationMessage handling, where the designated UI-Element is reshaped by applying an embedded concrete diff message with the help of a {{{DiffApplicator&lt;DiffMutable&gt;}}}, based on the TreeMutator exposed.</pre>
The UI-Bus offers a dedicated API to direct ~MutationMessages towards {{{Tangible}}} elements, as designated by the given ID. Actually, such messages serve as //capsule to transport a [[diff-sequence|TreeDiffModel]]// -- since a diff sequence as such is always concrete and tied to a specific context, we can not represent it directly as an abstract type at interface level. The receiver of a diff sequence must offer the ability to be reshaped through diff messages, which is expressed through the interface {{{DiffMutable}}}.
In the case at hand, the basic building block of the Lumiera UI, the {{{Tangible}}} offers this interface and thus the ability to construct a concrete TreeMutator, which in turn is bound to the internals of the actual UI-Element in question. Together this allows for a generic implementation of MutationMessage handling, where the designated UI-Element is reshaped by applying a concrete diff sequence embedded in the message with the help of a {{{DiffApplicator&lt;DiffMutable&gt;}}}, based on the TreeMutator exposed.</pre>
</div>
<div title="NodeConfiguration" modifier="Ichthyostega" created="200909041806" modified="200909041807" tags="spec Builder Rendering">
<pre>Various aspects of the individual [[render node|ProcNode]] are subject to configuration and may influence the output quality or the behaviour of the render process.

View file

@ -914,8 +914,14 @@
</node>
<node CREATED="1484877585605" ID="ID_101718446" MODIFIED="1502403195803" TEXT="verwende MutationMessage">
<icon BUILTIN="yes"/>
<node CREATED="1502401956093" ID="ID_322700967" MODIFIED="1502403195803" TEXT="MutationMessage von DiffMessage erzeugen"/>
<node CREATED="1502401987033" ID="ID_1584846573" MODIFIED="1502403195803" TEXT="erfordert Festlegung der Natur der DiffMessage">
<node CREATED="1502401956093" ID="ID_322700967" MODIFIED="1502454616016" TEXT="MutationMessage von DiffMessage erzeugen">
<icon BUILTIN="button_cancel"/>
</node>
<node CREATED="1502454601603" ID="ID_384770680" MODIFIED="1502454613220" TEXT="nein: MutationMessage wird &#xfc;berfl&#xfc;ssig">
<icon BUILTIN="button_ok"/>
</node>
<node CREATED="1502401987033" ID="ID_1584846573" MODIFIED="1502454045750" TEXT="erfordert Festlegung der Natur der DiffMessage">
<arrowlink COLOR="#bdbad3" DESTINATION="ID_89098030" ENDARROW="Default" ENDINCLINATION="821;-1406;" ID="Arrow_ID_554743885" STARTARROW="None" STARTINCLINATION="1459;870;"/>
<icon BUILTIN="messagebox_warning"/>
<node CREATED="1502402004383" ID="ID_1491065212" MODIFIED="1502403195803" TEXT="generisch bleiben?">
<icon BUILTIN="button_cancel"/>
@ -5813,7 +5819,7 @@
</node>
</node>
</node>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#990000" CREATED="1455422030995" FOLDED="true" HGAP="35" ID="ID_1455265273" MODIFIED="1491009391795" TEXT="mutation" VSHIFT="7">
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#990000" CREATED="1455422030995" HGAP="35" ID="ID_1455265273" MODIFIED="1502453247050" TEXT="mutation" VSHIFT="7">
<icon BUILTIN="pencil"/>
<node CREATED="1455666294927" FOLDED="true" ID="ID_373207685" MODIFIED="1488423342665" TEXT="Ausgangspunkt">
<node CREATED="1455666301630" ID="ID_933452284" MODIFIED="1455666310209" TEXT="Element-Protokoll steht"/>
@ -5833,7 +5839,7 @@
<icon BUILTIN="full-3"/>
</node>
</node>
<node CREATED="1455668897947" FOLDED="true" HGAP="211" ID="ID_1897861223" MODIFIED="1491009320473" TEXT="Konsequenzen" VSHIFT="23">
<node CREATED="1455668897947" FOLDED="true" HGAP="211" ID="ID_1897861223" MODIFIED="1502453346306" TEXT="Konsequenzen" VSHIFT="23">
<node CREATED="1455668923175" ID="ID_1183550957" MODIFIED="1472219338326" TEXT="brauche passendes UI-Bus API">
<richcontent TYPE="NOTE"><html>
<head>
@ -6246,16 +6252,16 @@
</node>
</node>
</node>
<node COLOR="#3a3785" CREATED="1455927009621" FOLDED="true" HGAP="148" ID="ID_153254427" MODIFIED="1488423342546" STYLE="fork" TEXT="&#xbb;generic tree diff&#xab;" VSHIFT="22">
<node COLOR="#3a3785" CREATED="1455927009621" FOLDED="true" HGAP="148" ID="ID_153254427" MODIFIED="1502453338387" STYLE="fork" TEXT="&#xbb;generic tree diff&#xab;" VSHIFT="22">
<cloud COLOR="#edd8ba"/>
<font NAME="SansSerif" SIZE="15"/>
<node CREATED="1455927154554" FOLDED="true" ID="ID_1055035778" MODIFIED="1488423308112" TEXT="Prinzip">
<node CREATED="1455927154554" ID="ID_1055035778" MODIFIED="1502453320550" TEXT="Prinzip">
<node CREATED="1455927162321" ID="ID_285833614" MODIFIED="1455927166972" TEXT="chained adapters"/>
<node CREATED="1455927169432" ID="ID_1685554012" MODIFIED="1455927207911" TEXT="inline closures"/>
<node CREATED="1455927216698" ID="ID_817434960" MODIFIED="1455927225756" TEXT="selector predicate"/>
</node>
<node CREATED="1455927270458" FOLDED="true" ID="ID_1471647972" MODIFIED="1488423308112" TEXT="Struktur">
<node CREATED="1455927276314" FOLDED="true" ID="ID_1425598677" MODIFIED="1488423308097" TEXT="Diff-verben">
<node CREATED="1455927270458" ID="ID_1471647972" MODIFIED="1502453310933" TEXT="Struktur">
<node CREATED="1455927276314" FOLDED="true" ID="ID_1425598677" MODIFIED="1502453333012" TEXT="Diff-verben">
<cloud COLOR="#fce9c0"/>
<font NAME="SansSerif" SIZE="16"/>
<node CREATED="1455927329507" FOLDED="true" ID="ID_949976479" MODIFIED="1488423308078" TEXT="pick">
@ -6328,7 +6334,7 @@
</node>
</node>
</node>
<node CREATED="1455927276314" FOLDED="true" HGAP="91" ID="ID_1209647803" MODIFIED="1488423308097" VSHIFT="-3">
<node CREATED="1455927276314" FOLDED="true" HGAP="91" ID="ID_1209647803" MODIFIED="1502453336188" VSHIFT="-3">
<richcontent TYPE="NODE"><html>
<head>
@ -10869,9 +10875,9 @@
</node>
</node>
</node>
<node CREATED="1473352396906" FOLDED="true" HGAP="-48" ID="ID_392196966" MODIFIED="1491009383729" TEXT="Integration" VSHIFT="25">
<node CREATED="1473352396906" HGAP="-48" ID="ID_392196966" MODIFIED="1502453253062" TEXT="Integration" VSHIFT="25">
<icon BUILTIN="pencil"/>
<node CREATED="1473352465473" FOLDED="true" ID="ID_158999012" MODIFIED="1488423342547" TEXT="in Tangible">
<node CREATED="1473352465473" ID="ID_158999012" MODIFIED="1502453392316" TEXT="in Tangible">
<icon BUILTIN="button_ok"/>
<node CREATED="1475250911087" FOLDED="true" ID="ID_1042895809" MODIFIED="1488423308115" TEXT="zu kl&#xe4;ren">
<font ITALIC="true" NAME="SansSerif" SIZE="12"/>
@ -10931,11 +10937,13 @@
<icon BUILTIN="help"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1475342135193" FOLDED="true" HGAP="31" ID="ID_336806935" MODIFIED="1488423308115" TEXT="Problem: Diff-Nachricht" VSHIFT="7">
<node COLOR="#990000" CREATED="1475342135193" HGAP="31" ID="ID_336806935" MODIFIED="1502453682285" TEXT="Problem: Diff-Nachricht" VSHIFT="7">
<arrowlink COLOR="#a7afc1" DESTINATION="ID_1363153586" ENDARROW="Default" ENDINCLINATION="931;-187;" ID="Arrow_ID_324877454" STARTARROW="Default" STARTINCLINATION="835;592;"/>
<font ITALIC="true" NAME="SansSerif" SIZE="12"/>
<icon BUILTIN="messagebox_warning"/>
<node CREATED="1475342157302" ID="ID_1383404259" MODIFIED="1475342166025" TEXT="&quot;Diff&quot; ist kein Typ"/>
<node CREATED="1475342185707" ID="ID_787925049" MODIFIED="1475342190662" TEXT="Lumiera-Iteratoren sind generisch"/>
<node CREATED="1475342218598" FOLDED="true" ID="ID_686706998" MODIFIED="1488423308102" TEXT="Alternativen">
<node CREATED="1475342218598" ID="ID_686706998" MODIFIED="1502453541592" TEXT="Alternativen">
<icon BUILTIN="idea"/>
<node CREATED="1475342242123" FOLDED="true" ID="ID_996905586" MODIFIED="1488423308087" TEXT="implizite Diff-Facade">
<icon BUILTIN="button_cancel"/>
@ -10948,26 +10956,29 @@
<icon BUILTIN="button_cancel"/>
</node>
</node>
<node CREATED="1475342230013" FOLDED="true" ID="ID_129545687" MODIFIED="1488423308087" TEXT="UI-Bus-Interface erweitern">
<node CREATED="1475342230013" ID="ID_129545687" MODIFIED="1502453545312" TEXT="UI-Bus-Interface erweitern">
<icon BUILTIN="button_ok"/>
<node CREATED="1475342469085" ID="ID_218240539" MODIFIED="1475342487060" TEXT="Ausgangspunkt: DiffMutable">
<icon BUILTIN="idea"/>
</node>
<node CREATED="1475342391631" ID="ID_1330153391" MODIFIED="1475342446252" TEXT="Platzhalter-Typ: DiffMessage"/>
<node CREATED="1475342401278" ID="ID_1020722080" MODIFIED="1475342430750" TEXT="macht Diff zug&#xe4;nglich"/>
<node CREATED="1475342391631" ID="ID_1330153391" MODIFIED="1502453602627" TEXT="Transport per DiffMessage"/>
<node CREATED="1475342401278" ID="ID_1020722080" MODIFIED="1502453642509" TEXT="abstrakte Koppelung"/>
</node>
</node>
<node CREATED="1475444207483" ID="ID_920212553" MODIFIED="1475444236127" TEXT="Festlegung: Tangible als Zieltyp">
<linktarget COLOR="#9287b2" DESTINATION="ID_920212553" ENDARROW="Default" ENDINCLINATION="398;0;" ID="Arrow_ID_52222580" SOURCE="ID_62520790" STARTARROW="None" STARTINCLINATION="398;0;"/>
<icon BUILTIN="yes"/>
</node>
<node COLOR="#338800" CREATED="1475356047496" FOLDED="true" HGAP="29" ID="ID_667427572" MODIFIED="1488423308102" TEXT="Implementierung" VSHIFT="14">
<node COLOR="#338800" CREATED="1475356047496" HGAP="29" ID="ID_667427572" MODIFIED="1502454682718" TEXT="Implementierung" VSHIFT="14">
<arrowlink COLOR="#71e5ac" DESTINATION="ID_60387485" ENDARROW="Default" ENDINCLINATION="50;-12;" ID="Arrow_ID_1384671312" STARTARROW="None" STARTINCLINATION="12;195;"/>
<icon BUILTIN="button_ok"/>
<node CREATED="1475356059342" ID="ID_1039482059" MODIFIED="1475444176904" TEXT="wie wird Diff eingebettet">
<icon BUILTIN="help"/>
</node>
<node CREATED="1475439403514" FOLDED="true" ID="ID_1619035258" MODIFIED="1488423308087" TEXT="Entscheidung">
<node CREATED="1475439403514" ID="ID_1619035258" MODIFIED="1502453694045" TEXT="Entscheidung">
<icon BUILTIN="yes"/>
<node CREATED="1502453744365" ID="ID_452337305" MODIFIED="1502453752074" TEXT="Schritt-1">
<icon BUILTIN="button_cancel"/>
<node CREATED="1475439416185" ID="ID_963854956" MODIFIED="1475444176904" TEXT="Builder-Funktion nicht sinnvoll">
<richcontent TYPE="NOTE"><html>
<head>
@ -11018,15 +11029,59 @@
<icon BUILTIN="ksmiletris"/>
</node>
<node CREATED="1475439436134" ID="ID_583247605" MODIFIED="1475444176904" TEXT="verwende InPlaceBuffer"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1475356066853" FOLDED="true" ID="ID_821643910" MODIFIED="1488423308087" TEXT="Problem: Puffergr&#xf6;&#xdf;e">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1475356066853" ID="ID_821643910" MODIFIED="1502453801372" TEXT="Problem: Puffergr&#xf6;&#xdf;e">
<icon BUILTIN="messagebox_warning"/>
<node CREATED="1475444135180" ID="ID_1434100612" MODIFIED="1475444176904" TEXT="sinnvoll: Spezialfall f&#xfc;r Tangible"/>
<node CREATED="1475444145458" ID="ID_62520790" MODIFIED="1475444244452" TEXT="kann dann DiffSizeTraits spezialisieren">
<arrowlink COLOR="#9287b2" DESTINATION="ID_920212553" ENDARROW="Default" ENDINCLINATION="398;0;" ID="Arrow_ID_52222580" STARTARROW="None" STARTINCLINATION="398;0;"/>
</node>
</node>
</node>
<node CREATED="1502453753155" ID="ID_89098030" MODIFIED="1502454045750" TEXT="Schritt-2">
<linktarget COLOR="#bdbad3" DESTINATION="ID_89098030" ENDARROW="Default" ENDINCLINATION="821;-1406;" ID="Arrow_ID_554743885" SOURCE="ID_1584846573" STARTARROW="None" STARTINCLINATION="1459;870;"/>
<icon BUILTIN="pencil"/>
<node CREATED="1502453814499" ID="ID_727706359" MODIFIED="1502453827917" TEXT="Puffer-Ansatz...">
<node CREATED="1502453828721" ID="ID_1337002332" MODIFIED="1502453830621" TEXT="komplex"/>
<node CREATED="1502453831233" ID="ID_443299660" MODIFIED="1502453835332" TEXT="unflexibel"/>
<node CREATED="1502453842463" ID="ID_1995272746" MODIFIED="1502453861969" TEXT="unn&#xf6;tiges Kopieren"/>
<node CREATED="1502453836112" ID="ID_1547334309" MODIFIED="1502453841067" TEXT="insgeheim doch gekoppelt"/>
</node>
<node CREATED="1502454064930" ID="ID_1876117833" MODIFIED="1502454072133" TEXT="brauche Entkoppelung"/>
<node CREATED="1502454072649" ID="ID_1325287539" MODIFIED="1502454083982">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
Abstraktion
</p>
<p>
nach beiden Setien
</p>
</body>
</html>
</richcontent>
<node CREATED="1502454089783" ID="ID_104095093" MODIFIED="1502454093290" TEXT="zum Erzeuger"/>
<node CREATED="1502454093814" ID="ID_1063793799" MODIFIED="1502454099337" TEXT="zum Empf&#xe4;nger"/>
</node>
<node CREATED="1502454117907" ID="ID_995116747" MODIFIED="1502454124761" TEXT="abstrakter Iterator">
<icon BUILTIN="forward"/>
<node CREATED="1502454128617" ID="ID_1019985292" MODIFIED="1502454135844" TEXT="mu&#xdf; Interface sein"/>
<node CREATED="1502454136368" ID="ID_1196043940" MODIFIED="1502454138836" TEXT="IterSource"/>
<node CREATED="1502454139496" ID="ID_455247221" MODIFIED="1502454151066" TEXT="Problem: &#xdc;bergabe">
<icon BUILTIN="messagebox_warning"/>
<node CREATED="1502454152431" ID="ID_1452648004" MODIFIED="1502454163000" TEXT="Diff &#xfc;ber Thread-Grenzen hinweg"/>
<node CREATED="1502454163685" ID="ID_1591230048" MODIFIED="1502454169704" TEXT="Pull-Prinzip"/>
<node CREATED="1502454183682" ID="ID_1647826766" MODIFIED="1502454194490" TEXT="Callback aus anderen Thread"/>
<node CREATED="1502454170228" ID="ID_1401327421" MODIFIED="1502454181097" TEXT="mu&#xdf; Erzeugungskontext weitergeben">
<icon BUILTIN="forward"/>
</node>
</node>
</node>
</node>
</node>
</node>
</node>
<node CREATED="1475449460694" FOLDED="true" HGAP="13" ID="ID_425831735" MODIFIED="1488423308115" TEXT="Prototyp: MockElm" VSHIFT="32">
<icon BUILTIN="button_ok"/>
@ -11216,11 +11271,15 @@
</node>
</node>
</node>
<node CREATED="1473352470896" FOLDED="true" HGAP="21" ID="ID_864450713" MODIFIED="1491009381377" TEXT="Unit-Tests" VSHIFT="18">
<node CREATED="1473352470896" HGAP="21" ID="ID_864450713" MODIFIED="1502453269037" TEXT="Unit-Tests" VSHIFT="18">
<node COLOR="#338800" CREATED="1473352475375" ID="ID_731425414" MODIFIED="1475546284267" TEXT="AbstractTangible_test">
<icon BUILTIN="button_ok"/>
</node>
<node CREATED="1473352482502" ID="ID_1891838260" MODIFIED="1473352485210" TEXT="UiBus_test"/>
<node CREATED="1473352482502" ID="ID_1891838260" MODIFIED="1502454735741" TEXT="BusTerm_test"/>
<node CREATED="1502453280050" ID="ID_60387485" MODIFIED="1502454672712" TEXT="DiffMessage_test">
<linktarget COLOR="#71e5ac" DESTINATION="ID_60387485" ENDARROW="Default" ENDINCLINATION="50;-12;" ID="Arrow_ID_1384671312" SOURCE="ID_667427572" STARTARROW="None" STARTINCLINATION="12;195;"/>
<icon BUILTIN="pencil"/>
</node>
</node>
</node>
</node>
@ -11670,7 +11729,7 @@
</node>
</node>
</node>
<node CREATED="1448070547667" FOLDED="true" HGAP="23" ID="ID_669457401" MODIFIED="1492444367631" TEXT="Bus-Terminal" VSHIFT="20">
<node CREATED="1448070547667" FOLDED="true" HGAP="23" ID="ID_669457401" MODIFIED="1502453232689" TEXT="Bus-Terminal" VSHIFT="20">
<icon BUILTIN="go"/>
<node CREATED="1448070601165" ID="ID_1711137699" MODIFIED="1448070603296" TEXT="Methoden">
<node CREATED="1448407030239" ID="ID_619913132" MODIFIED="1448560681641">
@ -11737,7 +11796,7 @@
</node>
</node>
<node CREATED="1434128059966" ID="ID_823283341" MODIFIED="1488672648352" TEXT="Connect">
<node CREATED="1434128071126" FOLDED="true" HGAP="13" ID="ID_1618124128" MODIFIED="1492444374310" TEXT="UI-Bus" VSHIFT="11">
<node CREATED="1434128071126" HGAP="13" ID="ID_1618124128" MODIFIED="1502453416754" TEXT="UI-Bus" VSHIFT="11">
<linktarget COLOR="#3a8df0" DESTINATION="ID_1618124128" ENDARROW="Default" ENDINCLINATION="-25;-262;" ID="Arrow_ID_539627804" SOURCE="ID_257833497" STARTARROW="Default" STARTINCLINATION="-2;35;"/>
<font NAME="SansSerif" SIZE="14"/>
<icon BUILTIN="go"/>
@ -11908,7 +11967,7 @@
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1485548830035" HGAP="5" ID="ID_1295711115" MODIFIED="1485548844056" TEXT="Nutzen" VSHIFT="17">
<icon BUILTIN="bell"/>
<node CREATED="1485548856639" ID="ID_1677281474" MODIFIED="1485548861522" TEXT="spezifische Aktionen">
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1485548894522" FOLDED="true" ID="ID_826011549" MODIFIED="1501859685960" TEXT="Problem: globale Aktionen">
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1485548894522" FOLDED="true" ID="ID_826011549" MODIFIED="1502452702879" TEXT="Problem: globale Aktionen">
<richcontent TYPE="NOTE"><html>
<head>
@ -11944,6 +12003,24 @@
<node CREATED="1492444328031" ID="ID_1628732201" MODIFIED="1492444335898" TEXT="mu&#xdf; im Lauf der Zeit wachsen"/>
</node>
</node>
<node CREATED="1502452724107" ID="ID_689474303" MODIFIED="1502452764489" TEXT="Mutationen">
<node CREATED="1502452771285" ID="ID_1091994004" MODIFIED="1502452862896" TEXT="Diff-Format">
<arrowlink COLOR="#a9acc1" DESTINATION="ID_143203937" ENDARROW="Default" ENDINCLINATION="115;-2033;" ID="Arrow_ID_136706418" STARTARROW="None" STARTINCLINATION="1656;0;"/>
<icon BUILTIN="idea"/>
</node>
<node CREATED="1502452875447" FOLDED="true" ID="ID_1363153586" MODIFIED="1502453538318" TEXT="DiffMessage">
<linktarget COLOR="#a7afc1" DESTINATION="ID_1363153586" ENDARROW="Default" ENDINCLINATION="931;-187;" ID="Arrow_ID_324877454" SOURCE="ID_336806935" STARTARROW="Default" STARTINCLINATION="835;592;"/>
<node CREATED="1502452903075" ID="ID_726723452" MODIFIED="1502453137630" TEXT="abstrahierter Iterator">
<node CREATED="1502453110640" ID="ID_1024081141" MODIFIED="1502453115659" TEXT="IterSource-Interface"/>
<node CREATED="1502453116327" ID="ID_1762714186" MODIFIED="1502453127417" TEXT="opaque generaction context"/>
<node CREATED="1502453128198" ID="ID_1311188906" MODIFIED="1502453133721" TEXT="per smart-ptr gehalten"/>
</node>
<node CREATED="1502452909091" ID="ID_638887155" MODIFIED="1502452913262" TEXT="nur einmal konsumierbar"/>
<node CREATED="1502452913906" ID="ID_1500100371" MODIFIED="1502453059636" TEXT="Framework zur Hanhabung">
<arrowlink COLOR="#afb1bd" DESTINATION="ID_1651893758" ENDARROW="Default" ENDINCLINATION="-1257;0;" ID="Arrow_ID_1786455458" STARTARROW="None" STARTINCLINATION="1858;0;"/>
</node>
</node>
</node>
<node CREATED="1485548866990" ID="ID_664933854" MODIFIED="1485548877800" TEXT="Commands"/>
<node CREATED="1485548878292" ID="ID_49934573" MODIFIED="1485548882087" TEXT="Broadcast"/>
</node>
@ -15597,8 +15674,9 @@
</node>
</node>
</node>
<node CREATED="1443733567706" HGAP="241" ID="ID_143203937" MODIFIED="1473353232804" TEXT="Diff-Language" VSHIFT="23">
<node CREATED="1443733567706" HGAP="241" ID="ID_143203937" MODIFIED="1502452847840" TEXT="Diff-Language" VSHIFT="23">
<cloud COLOR="#cfba9d"/>
<linktarget COLOR="#a9acc1" DESTINATION="ID_143203937" ENDARROW="Default" ENDINCLINATION="115;-2033;" ID="Arrow_ID_136706418" SOURCE="ID_1091994004" STARTARROW="None" STARTINCLINATION="1656;0;"/>
<font NAME="SansSerif" SIZE="14"/>
<icon BUILTIN="go"/>
<node CREATED="1443733726563" ID="ID_410650103" MODIFIED="1443733731422" TEXT="Grundlagen">
@ -16628,6 +16706,63 @@
<icon BUILTIN="flag"/>
</node>
</node>
<node CREATED="1502452581379" HGAP="11" ID="ID_1651893758" MODIFIED="1502453059637" TEXT="Darstellung" VSHIFT="17">
<linktarget COLOR="#afb1bd" DESTINATION="ID_1651893758" ENDARROW="Default" ENDINCLINATION="-1257;0;" ID="Arrow_ID_1786455458" SOURCE="ID_1500100371" STARTARROW="None" STARTINCLINATION="1858;0;"/>
<node CREATED="1502452597604" ID="ID_172363215" MODIFIED="1502452604960" TEXT="DiffMessage">
<icon BUILTIN="pencil"/>
<node CREATED="1502454531772" ID="ID_445867436" MODIFIED="1502454536184" TEXT="abstrakter Iterator"/>
<node CREATED="1502454536636" ID="ID_643452930" MODIFIED="1502454542390" TEXT="opaque generation context"/>
</node>
<node CREATED="1502452625232" ID="ID_328973433" MODIFIED="1502454510192" TEXT="Diagnose">
<icon BUILTIN="button_ok"/>
<node CREATED="1502454361347" ID="ID_1601614353" MODIFIED="1502454363150" TEXT="toString">
<node CREATED="1502454303107" ID="ID_712801862" MODIFIED="1502454329405" TEXT="Problem: Pull-Prinzip">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
Diff ist eine abstrakte Quelle,
</p>
<p>
die nur einmal verbraucht werden kann
</p>
</body>
</html></richcontent>
</node>
<node CREATED="1502454341085" ID="ID_1620101988" MODIFIED="1502454351680" TEXT="L&#xf6;sung: Adapter mit Snapshot"/>
<node CREATED="1502454374017" ID="ID_355618162" MODIFIED="1502454376725" TEXT="Konsequenz">
<node CREATED="1502454377713" ID="ID_1122938295" MODIFIED="1502454386323" TEXT="normaler Diff bleibt opaque"/>
<node CREATED="1502454387047" ID="ID_1949389197" MODIFIED="1502454395770" TEXT="Dekorator f&#xfc;r Tests">
<node CREATED="1502454398686" ID="ID_1736428769" MODIFIED="1502454409496" TEXT="Anforderung: drop-in"/>
<node CREATED="1502454410012" ID="ID_364935696" MODIFIED="1502454438242" TEXT="durch Allokations-Kette l&#xf6;sen">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
Dekorator-Prinzip.
</p>
<p>
Pa&#223;t hier, da IterSource genau dieses Vorgehen nahelegt
</p>
</body>
</html>
</richcontent>
</node>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1502454451191" ID="ID_1968344683" MODIFIED="1502454502337" TEXT="pretty-print">
<icon BUILTIN="hourglass"/>
<node CREATED="1502454475268" ID="ID_1399873401" MODIFIED="1502454479199" TEXT="f&#xfc;r Systemdiagnose"/>
<node CREATED="1502454479907" ID="ID_234469818" MODIFIED="1502454491525" TEXT="lesbare Formattierung"/>
<node CREATED="1502454492162" ID="ID_983774503" MODIFIED="1502454496237" TEXT="auf sp&#xe4;ter vertagt"/>
</node>
</node>
</node>
</node>
<node CREATED="1460934597764" HGAP="163" ID="ID_1014666775" MODIFIED="1488423307306" TEXT="Review" VSHIFT="6">
<font NAME="SansSerif" SIZE="15"/>