From a56226f297fd593f61ab7e21b4bc5f228f004b9b Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Mon, 17 Aug 2015 22:13:36 +0200 Subject: [PATCH] Record "object" representation now finished and passes Test --- src/lib/diff/record.hpp | 14 +++--- .../generic-record-representation-test.cpp | 47 +++++++++++++++---- wiki/thinkPad.ichthyo.mm | 32 ++++++++----- 3 files changed, 66 insertions(+), 27 deletions(-) diff --git a/src/lib/diff/record.hpp b/src/lib/diff/record.hpp index 8531695f9..900971a29 100644 --- a/src/lib/diff/record.hpp +++ b/src/lib/diff/record.hpp @@ -47,11 +47,13 @@ ** - the parts or \em realms within this symbolic representation are distinguished ** by convention solely ** - ** * metadata is very limited and boils down to magic attributes known by name + ** * metadata is very limited and boils down to a type attribute known by name ** * children (scope contents) can be recognised by \em not bearing a name ** ** Record entities are meant to be immutable. The proper way to alter a Record is - ** to apply a \link tree-diff.hpp diff \endlink + ** to apply a \link tree-diff.hpp diff \endlink. Yet for the \em implementation + ** of this diff handling, a Record::Mutator is provided, to allow controlled + ** partial re-building of a given data element. ** ** \par rationale ** The underlying theme of this design is negative, dialectical: we do not want to @@ -62,7 +64,7 @@ ** which is to exchange diff messages drawn against a symbolic representation ** of a typed object tree. Especially, we assume that there is only a small ** number of attributes (so linear search for access by key is adequate). - ** - moreover, we assume that the value type allows to somehow to embed + ** - moreover, we assume that the value type allows for somehow embedding ** the key of each attribute; the implementation needs an explicit ** specialisation of the binding functions for each value type. ** - this header defines a specialisation for VAL = std::string -- @@ -483,7 +485,7 @@ namespace diff{ /** * wrapped record reference. * A helper for lib::GenNode and the diff representation. - * RecordRef is copyable and assignable, but like a reference + * RecordRef is copyable and movable, but like a reference * can not be rebound. It can be used to refer to a subtree * within the diff representation, without the need to copy. * @remarks this is almost identical to std::ref, with the @@ -497,7 +499,7 @@ namespace diff{ using Target = Record; Target* record_; - + public: /** by default create an * invalid ("bottom") reference */ @@ -640,7 +642,7 @@ namespace diff{ { return string(key + " = " + extractVal(payload)); } - + diff --git a/tests/library/diff/generic-record-representation-test.cpp b/tests/library/diff/generic-record-representation-test.cpp index 1c65a8c62..11150950e 100644 --- a/tests/library/diff/generic-record-representation-test.cpp +++ b/tests/library/diff/generic-record-representation-test.cpp @@ -26,10 +26,8 @@ #include "lib/format-util.hpp" #include "lib/diff/record.hpp" #include "lib/itertools.hpp" -#include "lib/util.hpp" //////TODO necessary? #include -//#include #include #include @@ -38,7 +36,7 @@ using util::isSameObject; using util::isnil; using util::join; using std::vector; -//using std::swap; +using std::swap; using std::cout; using std::endl; @@ -47,7 +45,6 @@ namespace lib { namespace diff{ namespace test{ -// using lumiera::error::LUMIERA_ERROR_LOGIC; using lumiera::error::LUMIERA_ERROR_INVALID; using lumiera::error::LUMIERA_ERROR_BOTTOM_VALUE; @@ -92,10 +89,37 @@ namespace test{ /*************************************************************************************//** * @test Verify properties of a special collection type meant for external representation - * of object-like data. + * of object-like data, especially for symbolic representation in diff messages. + * - there is a type meta attribute + * - a Record can have attributes (by key) and contents (ordered list of values) + * - various kinds of iterators are provided + * - besides the regular constructor, which explicitly takes a type, a collection + * of attributes, and a collection of contents, there is a convenience constructor + * especially for literal notation and data definition. This one figures out the + * break between attributes and contents automatically; a type meta attribute + * is recognised and the first element without a given key or ID ends the + * attributes and starts the content scope + * - Record elements are conceived as values and equality is defined in terms + * of their contents, including the order (no normalisation, no sorting) + * - they are \em immutable after construction. But we provide a Mutator + * for remoulding a given element, enabling object builder notation. + * - a reference wrapper for handling of large structures is provided. + * @remarks this test uses the specialisation \c Record solely, to cover the + * basic properties and behaviour, while leaving out the complexities of specific + * payload data types. For the actual use case, the symbolic description of + * data structure differences, we use a specific "value" within Record, + * the diff::GenNode, which is a limited typesafe Variant element, and in + * turn allows Record as embedded payload. Effectively this creates + * a "recursive data type", which is key to typesafe functional processing of + * unlimited data structures. The design of diff::Record only makes sense with + * this use case in mind; most notably, we have the keys (attribute names) + * embedded within the value payload, which turns attributes into just another + * content scope with special access operations. This also explains, why we + * do not normalise the content in any way; content is meant to reflect + * other data structures, which are normalised and maintained by their owner. * - * @see IndexTable - * @see DiffListApplication_test + * @see GenNodeBasic_test + * @see tree-diff.cpp */ class GenericRecordRepresentation_test : public Test { @@ -131,10 +155,10 @@ namespace test{ CHECK (enterprise.hasAttribute("Owner")); CHECK (!enterprise.hasAttribute("owner")); - CHECK (!enterprise.hasAttribute("Owner ")); + CHECK (!enterprise.hasAttribute("Owner ")); // no normalisation CHECK (enterprise.contains("Data")); - CHECK (!enterprise.contains("Woof")); + CHECK (!enterprise.contains("Woof")); // it is /Worf/, madam CHECK (util::contains (enterprise, "Worf")); VERIFY_ERROR (INVALID, enterprise.get("warp10")); @@ -231,6 +255,7 @@ namespace test{ RecS aaa({"a","a"}); RecS ax({"type=a","a"}); RecS ay({"a=a","a"}); + RecS az({"a =a","a"}); CHECK (a != aa); CHECK (aa != a); CHECK (aa != aaa); CHECK (aaa != aa); @@ -239,7 +264,9 @@ namespace test{ CHECK (a != ay); CHECK (ay != a); CHECK (ax != ay); CHECK (ay != ax); CHECK (aaa != ay); CHECK (ay != aaa); - + CHECK (ay != az); CHECK (az != ay); // NOTE: attributes are *not* normalised, + // rather, they are used as-is, + // thus "a=a" != "a =a" RecS a2({"a","aa"}); CHECK (aa == a2); CHECK (a2 == aa); diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 49e3fe972..3afc3b3d3 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -32,7 +32,8 @@ - + + @@ -50,6 +51,7 @@ + @@ -185,8 +187,10 @@ - - + + + + @@ -315,12 +319,12 @@ - - + + - - + + @@ -466,7 +470,8 @@ - + + @@ -518,7 +523,7 @@ - + @@ -752,7 +757,7 @@ - + @@ -768,7 +773,8 @@ - + + @@ -1178,6 +1184,10 @@ + + + +