settle on an approach for handling attributes
Initially, I considered to build an index table like collection of ordered attributes. But since our actual use case is Record<GenNode>, this was ruled out in favour of just a vector<GenNode>, where the keys are embedded right within the nameID-Field of GenNode. A decisive factor was the observation, that this design is basically forced to encode the attribute keys somehow into the attribute values, because otherwise the whole collection like initialisation and iteration would break down. Thus, a fully generic implementation is not possible, and a pseudo generic implementation just for the purpose of writing unit tests would be overkill. Basically this decision means that Record requires an explicit specialisation to implement the attribute-key binding for each value type to use.
This commit is contained in:
parent
e664ea552f
commit
cecb5db972
2 changed files with 135 additions and 38 deletions
|
|
@ -157,6 +157,50 @@ namespace diff{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* === Specialisation for handling of attributes in Record<GenNode> === */
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline bool
|
||||||
|
Record<GenNode>::isAttribute (GenNode const& v)
|
||||||
|
{
|
||||||
|
return false; ////TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline bool
|
||||||
|
Record<GenNode>::isTypeID (GenNode const& v)
|
||||||
|
{
|
||||||
|
return false; ////TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline string
|
||||||
|
Record<GenNode>::extractTypeID (GenNode const& v)
|
||||||
|
{
|
||||||
|
return "todo"; ////TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline GenNode
|
||||||
|
Record<GenNode>::buildTypeAttribute (string const& typeID)
|
||||||
|
{
|
||||||
|
return GenNode(); ///TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline string
|
||||||
|
Record<GenNode>::extractKey (GenNode const& v)
|
||||||
|
{
|
||||||
|
return "todo"; ////TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline GenNode
|
||||||
|
Record<GenNode>::extractVal (GenNode const& v)
|
||||||
|
{
|
||||||
|
return GenNode(); ///TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}} // namespace lib::diff
|
}} // namespace lib::diff
|
||||||
#endif /*LIB_DIFF_GEN_NODE_H*/
|
#endif /*LIB_DIFF_GEN_NODE_H*/
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,25 @@
|
||||||
**
|
**
|
||||||
** \par rationale
|
** \par rationale
|
||||||
** The underlying theme of this design is negative, dialectical: we do not want to
|
** The underlying theme of this design is negative, dialectical: we do not want to
|
||||||
** build yet another object system. The object model of C++ is deemed adequate.
|
** build yet another object system. The object model of C++ is deemed adequate.
|
||||||
|
**
|
||||||
|
** @remarks
|
||||||
|
** - the implementation is focused on the intended primary use case,
|
||||||
|
** 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
|
||||||
|
** 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 --
|
||||||
|
** while the most relevant specialisation for GenNode is provided
|
||||||
|
** alongside with this special, monadic value type.
|
||||||
|
** - an alternative implementation approach would have been to use a
|
||||||
|
** dedicated helper type to represent the collection of attributes.
|
||||||
|
** This type might then be specialised, e.g. to utilise an index table
|
||||||
|
** for key-value lookup. However, in the light of the intended usage
|
||||||
|
** of Record entities as tree nodes within a GenNode monad, such a
|
||||||
|
** more elaborate approach was deemed unnecessary for the time being.
|
||||||
**
|
**
|
||||||
** @see GenericRecordRepresentation_test
|
** @see GenericRecordRepresentation_test
|
||||||
**
|
**
|
||||||
|
|
@ -78,7 +96,7 @@
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
//#include <map>
|
|
||||||
|
|
||||||
|
|
||||||
namespace lib {
|
namespace lib {
|
||||||
|
|
@ -91,7 +109,24 @@ namespace diff{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** object-like record of data */
|
/**
|
||||||
|
* object-like record of data.
|
||||||
|
* For symbolic representation of "objects".
|
||||||
|
* A Record holds both \em attributes (key-value data)
|
||||||
|
* plus a list of \em enclosed children, which are conceived
|
||||||
|
* to be within the "scope" of this Record. Optionally, a \em typeID
|
||||||
|
* (metadata) may be defined. Otherwise, this typeID defaults to \c "NIL".
|
||||||
|
* The representation of attributes depends on the actual value type, which
|
||||||
|
* somehow need the ability to encode the keys within the value data.
|
||||||
|
* By default, a specialisation is given for string, using the \c "key = val"
|
||||||
|
* syntax. Yet the most relevant use case is \c Record<GenNode> -- using the
|
||||||
|
* embedded name-ID of the GenNode elements as key for attributes.
|
||||||
|
*
|
||||||
|
* Recode elements meant to be immutable; they can be created from a
|
||||||
|
* defining collection. However, we provide a #Mutator mechanism to allow
|
||||||
|
* for rebuilding and mutating symbolic data structures based on Records
|
||||||
|
* and GenNode. Especially, Lumiera's diff framework relies on this.
|
||||||
|
*/
|
||||||
template<typename VAL>
|
template<typename VAL>
|
||||||
class Record
|
class Record
|
||||||
{
|
{
|
||||||
|
|
@ -265,41 +300,13 @@ namespace diff{
|
||||||
} }
|
} }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static bool
|
/* === abstract attribute handling : needs specialisation === */
|
||||||
isAttribute (VAL const& v)
|
static bool isAttribute (VAL const& v);
|
||||||
{
|
static bool isTypeID (VAL const& v);
|
||||||
return false; ////TODO
|
static string extractTypeID (VAL const& v);
|
||||||
}
|
static VAL buildTypeAttribute (string const& typeID);
|
||||||
|
static string extractKey (VAL const& v);
|
||||||
static bool
|
static VAL extractVal (VAL const& v);
|
||||||
isTypeID (VAL const& v)
|
|
||||||
{
|
|
||||||
return false; ////TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
static string
|
|
||||||
extractTypeID (VAL const& v)
|
|
||||||
{
|
|
||||||
return "todo"; ////TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
static VAL
|
|
||||||
buildTypeAttribute (string const& typeID)
|
|
||||||
{
|
|
||||||
return VAL(); ///TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
static string
|
|
||||||
extractKey (VAL const& v)
|
|
||||||
{
|
|
||||||
return "todo"; ////TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
static VAL
|
|
||||||
extractVal (VAL const& v)
|
|
||||||
{
|
|
||||||
return VAL(); ///TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
friend bool
|
friend bool
|
||||||
|
|
@ -384,5 +391,51 @@ namespace diff{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* === Specialisations to define the handling of attributes === */
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline bool
|
||||||
|
Record<string>::isAttribute (string const& v)
|
||||||
|
{
|
||||||
|
return false; ////TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline bool
|
||||||
|
Record<string>::isTypeID (string const& v)
|
||||||
|
{
|
||||||
|
return false; ////TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline string
|
||||||
|
Record<string>::extractTypeID (string const& v)
|
||||||
|
{
|
||||||
|
return "todo"; ////TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline string
|
||||||
|
Record<string>::buildTypeAttribute (string const& typeID)
|
||||||
|
{
|
||||||
|
return string(); ///TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline string
|
||||||
|
Record<string>::extractKey (string const& v)
|
||||||
|
{
|
||||||
|
return "todo"; ////TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline string
|
||||||
|
Record<string>::extractVal (string const& v)
|
||||||
|
{
|
||||||
|
return string(); ///TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}} // namespace lib::diff
|
}} // namespace lib::diff
|
||||||
#endif /*LIB_DIFF_GEN_NODE_H*/
|
#endif /*LIB_DIFF_GEN_NODE_H*/
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue