From e438a9fe51fe796dece41a0de2d014ba7427c395 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Fri, 23 Oct 2015 19:24:34 +0200 Subject: [PATCH] chosing an implementation approach for tree-diff-application --- src/lib/diff/record-content-mutator.hpp | 78 +++++++++++++++++ src/lib/diff/tree-diff-application.hpp | 21 +++++ src/lib/diff/tree-diff.hpp | 4 +- .../diff/generic-record-update-test.cpp | 86 +++++++++++++++++++ wiki/thinkPad.ichthyo.mm | 22 ++++- 5 files changed, 208 insertions(+), 3 deletions(-) create mode 100644 src/lib/diff/record-content-mutator.hpp create mode 100644 tests/library/diff/generic-record-update-test.cpp diff --git a/src/lib/diff/record-content-mutator.hpp b/src/lib/diff/record-content-mutator.hpp new file mode 100644 index 000000000..5ede5259f --- /dev/null +++ b/src/lib/diff/record-content-mutator.hpp @@ -0,0 +1,78 @@ +/* + RECORD-CONTENT-MUTATOR.hpp - helper to remould record contents + + Copyright (C) Lumiera.org + 2015, Hermann Vosseler + + 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 record-content-mutator.hpp + ** Implementation helper for reshaping the contents of a lib::diff::Record. + ** This technical helper is necessary to apply one level of a "Tree Diff" + ** to an object represented as #Record::Mutator. Since records as such are + ** designed as immutable value objects, we build a dedicated #Record::Mutator + ** when it comes to reordering the contents of a given record. The technical + ** details of doing so are highly coupled to the actual storage implementation + ** of #Record, as well as to the actual procedure to apply a diff message, as + ** implemented in lib::diff::DiffApplicationStrategy. + ** + ** @see generic-record-update-test.cpp + ** @see tree-diff-application-test.cpp + ** @see Record::Mutator + ** @see diff-language.hpp + ** + */ + + +#ifndef LIB_DIFF_RECORD_CONTENT_MUTATOR_H +#define LIB_DIFF_RECORD_CONTENT_MUTATOR_H + + +#include "lib/error.hpp" + +#include +#include + +namespace lib { +namespace diff{ + + using std::move; + using std::swap; + + + /** @internal helper for DiffApplicationStrategy */ + template + class RecordContentMutator + : boost::noncopyable + { + public: + explicit + RecordContentMutator() + { + swap (attribs_, target_.attribs()); + swap (children_, target_.children()); + + // heuristics for storage pre-allocation + target_.attribs().reserve (attribs_.size() * 120 / 100); + target_.children().reserve (children_.size() * 120 / 100); + } + }; + + +}} // namespace lib::diff +#endif /*LIB_DIFF_RECORD_CONTENT_MUTATOR_H*/ diff --git a/src/lib/diff/tree-diff-application.hpp b/src/lib/diff/tree-diff-application.hpp index 915b5c70f..e4c022edb 100644 --- a/src/lib/diff/tree-diff-application.hpp +++ b/src/lib/diff/tree-diff-application.hpp @@ -27,6 +27,27 @@ ** to receive linearised structural diff descriptions and apply them to ** a given target data structure, to effect the corresponding changes. ** + ** \par Design considerations + ** While -- conceptually -- our tree diff handling can be seen as an extension + ** and generalisation of list diffing, the decision was \em not to embody this + ** extension into the implementation technically, for sake of clarity. More so, + ** since the Record, which serves as foundation for our »External Tree Description«, + ** was made to look and behave like a list-like entity, but built with two distinct + ** scopes at implementation level: the attribute scope and the contents scope. This + ** carries over to the fine points of the list diff language semantics, especially + ** when it comes to fault tolerance and strictness vs fuzziness in diff application. + ** The implementation is thus faced with having to deal with an internal focus and + ** a switch from scope to scope, which adds a lot of complexity. So the list diff + ** application strategy can be seen as blueprint and demonstration of principles. + ** + ** Another point in question is weather see the diff application as manipulating + ** a target data structure, or rather building a reshaped copy. The fact that + ** GenNode and Record are designed as immutable values seems to favour the latter, + ** yet the very reason to engage into building this diff framework was how to + ** handle partial updates within a expectedly very large UI model, reflecting + ** the actual session model in Proc-Layer. So we end up working on a Mutator, + ** which clearly signals we're going to reshape and re-rig the target data. + ** ** @see diff-list-application-test.cpp ** @see VerbToken ** diff --git a/src/lib/diff/tree-diff.hpp b/src/lib/diff/tree-diff.hpp index 550ff26bc..3397bbef8 100644 --- a/src/lib/diff/tree-diff.hpp +++ b/src/lib/diff/tree-diff.hpp @@ -24,8 +24,8 @@ /** @file tree-diff.hpp ** A token language to represent structural changes in a tree like ** hierarchical data structure. In combination with the #DiffLanguage framework, - ** this building block defines the set of operations to express both content - ** and structural changes in a given data structure. + ** this building block defines the set of operations to express both structural + ** and content changes in a given data structure. ** ** @todo UNIMPLEMENTED as of 12/14 ** diff --git a/tests/library/diff/generic-record-update-test.cpp b/tests/library/diff/generic-record-update-test.cpp new file mode 100644 index 000000000..007c1ee88 --- /dev/null +++ b/tests/library/diff/generic-record-update-test.cpp @@ -0,0 +1,86 @@ +/* + GenericRecordUpdate(Test) - manipulate and reshape the generic record contents + + Copyright (C) Lumiera.org + 2015, Hermann Vosseler + + 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. + +* *****************************************************/ + + +#include "lib/test/run.hpp" +#include "lib/diff/record-content-mutator.hpp" +//#include "lib/iter-adapter-stl.hpp" +//#include "lib/time/timevalue.hpp" +//#include "lib/format-util.hpp" +#include "lib/util.hpp" + +#include +#include + +//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.... + + }//(End)Test fixture + + + + + + + + + + /*****************************************************************************//** + * @test cover technical details of rearranging the contents of lib::diff::Record. + * The implementation of our generic record (abstract object representation) + * uses two lists to hold the data of the attribute and content scopes. + * When receiving a diff message, we have to rearrange and alter the contents, + * which are by default immutable. Thus, for this specific task, embedded + * data is moved into this adapter, which exposes the mutating operation + * required to apply such a diff message. + * + * @see generic-record-representation-test.cpp + * @see tree-diff-application-test.cpp + */ + class GenericRecordUpdate_test + : public Test + { + + virtual void + run (Arg) + { + } + }; + + + /** Register this test class... */ + LAUNCHER (GenericRecordUpdate_test, "unit common"); + + + +}}} // namespace lib::diff::test diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index a1bed87c1..70f8ea860 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -1852,7 +1852,27 @@ - + + + + + + + + + + + + + + + + + + + + +