summaryrefslogtreecommitdiff
path: root/src/core/model
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/model')
-rw-r--r--src/core/model/Node.cpp26
-rw-r--r--src/core/model/Node.hpp17
-rw-r--r--src/core/model/Typesystem.cpp107
-rw-r--r--src/core/model/Typesystem.hpp116
4 files changed, 162 insertions, 104 deletions
diff --git a/src/core/model/Node.cpp b/src/core/model/Node.cpp
index 6c00e89..7cbbbe1 100644
--- a/src/core/model/Node.cpp
+++ b/src/core/model/Node.cpp
@@ -60,14 +60,14 @@ using VisitorSet =
class SharedResolutionState {
public:
/**
- * Actual path (name pattern) that was requested for resolution.
+ * Type of the node that was requested for resolution.
*/
- const std::vector<std::string> &path;
+ const Rtti &type;
/**
- * Type of the node that was requested for resolution.
+ * Actual path (name pattern) that was requested for resolution.
*/
- const Rtti &type;
+ const std::vector<std::string> &path;
/**
* Tracks all nodes that have already been visited.
@@ -82,13 +82,13 @@ public:
/**
* Constructor of the SharedResolutionState class.
*
+ * @param type is the type of the node that should be resolved.
* @param path is a const reference to the actual path that should be
* resolved.
- * @param type is the type of the node that should be resolved.
*/
- SharedResolutionState(const std::vector<std::string> &path,
- const Rtti &type)
- : path(path), type(type)
+ SharedResolutionState(const Rtti &type,
+ const std::vector<std::string> &path)
+ : type(type), path(path)
{
}
};
@@ -329,10 +329,10 @@ bool Node::continueResolveReference(Handle<Node> h, ResolutionState &state)
}
std::vector<ResolutionResult> Node::resolve(
- const std::vector<std::string> &path, const Rtti &type)
+ const Rtti &type, const std::vector<std::string> &path)
{
// Create the state variables
- SharedResolutionState sharedState(path, type);
+ SharedResolutionState sharedState(type, path);
ResolutionState state(sharedState, this);
// Kickstart the resolution process by treating this very node as compositum
@@ -344,11 +344,11 @@ std::vector<ResolutionResult> Node::resolve(
return sharedState.result;
}
-std::vector<ResolutionResult> Node::resolve(const std::string &name,
- const Rtti &type)
+std::vector<ResolutionResult> Node::resolve(const Rtti &type,
+ const std::string &name)
{
// Place the name in a vector and call the corresponding resolve function
- return resolve(std::vector<std::string>{name}, type);
+ return resolve(type, std::vector<std::string>{name});
}
bool Node::checkDuplicate(Handle<Node> elem,
diff --git a/src/core/model/Node.hpp b/src/core/model/Node.hpp
index 036bcae..61bf418 100644
--- a/src/core/model/Node.hpp
+++ b/src/core/model/Node.hpp
@@ -223,7 +223,7 @@ private:
* @param thisRef is the Node of which the reference should be returned.
* @return the value of the reference.
*/
- using NodeReferenceCallback = const Node* (const Node* thisRef);
+ using NodeReferenceCallback = const Node *(const Node *thisRef);
/**
* Checks whether the a certain property is acyclic.
@@ -400,7 +400,8 @@ protected:
* @return true if the parent reference is acyclic, false otherwise.
*/
bool validateIsAcyclic(const std::string &name,
- NodeReferenceCallback callback, Logger &logger) const;
+ NodeReferenceCallback callback,
+ Logger &logger) const;
/**
* Makes sure the "parent" reference is not cyclic.
@@ -538,26 +539,26 @@ public:
* Function which resolves a name path to a list of possible nodes starting
* from this node.
*
+ * @param type specifies the type of the node that should be located.
* @param path is a list specifying a path of node names meant to specify a
* certain named node.
- * @param type specifies the type of the node that should be located.
* @return a vector containing ResolutionResult structures which describe
* the resolved elements.
*/
- std::vector<ResolutionResult> resolve(const std::vector<std::string> &path,
- const Rtti &type);
+ std::vector<ResolutionResult> resolve(const Rtti &type,
+ const std::vector<std::string> &path);
/**
* Function which resolves a single name to a list of possible nodes
* starting from this node.
*
- * @param name is the name which should be resolved.
* @param type specifies the type of the node that should be located.
+ * @param name is the name which should be resolved.
* @return a vector containing ResolutionResult structures which describe
* the resolved elements.
*/
- std::vector<ResolutionResult> resolve(const std::string &name,
- const Rtti &type);
+ std::vector<ResolutionResult> resolve(const Rtti &type,
+ const std::string &name);
/**
* Checks whether this node is valid and returns true if it is and false
diff --git a/src/core/model/Typesystem.cpp b/src/core/model/Typesystem.cpp
index 8a50492..591dcbe 100644
--- a/src/core/model/Typesystem.cpp
+++ b/src/core/model/Typesystem.cpp
@@ -24,12 +24,28 @@
namespace ousia {
+/* Static helper functions */
+
+static void NullMagicCallback(Variant &, bool, ManagedUid) {}
+
/* Class Type */
-bool Type::build(Variant &data, Logger &logger) const
+bool Type::build(Variant &data, Logger &logger,
+ const MagicCallback &magicCallback) const
{
+ // If the given variant is marked as "magic", try to resolve the real value
+ if (data.isMagic()) {
+ Variant strData = Variant::fromString(data.asString());
+ Logger nullLogger;
+ bool valid = isValid(strData, nullLogger);
+ magicCallback(data, valid,
+ getUid());
+ build(strData, nullLogger);
+ return true; // Just return true for now
+ }
+
try {
- return doBuild(data, logger);
+ return doBuild(data, logger, magicCallback);
}
catch (LoggableException ex) {
logger.log(ex);
@@ -38,37 +54,47 @@ bool Type::build(Variant &data, Logger &logger) const
}
}
+bool Type::build(Variant &data, Logger &logger) const
+{
+ return build(data, logger, NullMagicCallback);
+}
+
/* Class BoolType */
-bool BoolType::doBuild(Variant &data, Logger &logger) const
+bool BoolType::doBuild(Variant &data, Logger &logger,
+ const MagicCallback &magicCallback) const
{
return VariantConverter::toBool(data, logger);
}
/* Class IntType */
-bool IntType::doBuild(Variant &data, Logger &logger) const
+bool IntType::doBuild(Variant &data, Logger &logger,
+ const MagicCallback &magicCallback) const
{
return VariantConverter::toInt(data, logger);
}
/* Class DoubleType */
-bool DoubleType::doBuild(Variant &data, Logger &logger) const
+bool DoubleType::doBuild(Variant &data, Logger &logger,
+ const MagicCallback &magicCallback) const
{
return VariantConverter::toDouble(data, logger);
}
/* Class StringType */
-bool StringType::doBuild(Variant &data, Logger &logger) const
+bool StringType::doBuild(Variant &data, Logger &logger,
+ const MagicCallback &magicCallback) const
{
return VariantConverter::toString(data, logger);
}
/* Class EnumType */
-bool EnumType::doBuild(Variant &data, Logger &logger) const
+bool EnumType::doBuild(Variant &data, Logger &logger,
+ const MagicCallback &magicCallback) const
{
// If the variant is an int, check whether the value is in range
if (data.isInt()) {
@@ -152,7 +178,7 @@ Attribute::Attribute(Manager &mgr, std::string name, Handle<Type> type,
Variant defaultValue, bool optional)
: Node(mgr, std::move(name)),
type(acquire(type)),
- rawDefaultValue(defaultValue),
+ defaultValue(std::move(defaultValue)),
optional(optional)
{
ExceptionLogger logger;
@@ -173,7 +199,6 @@ Attribute::Attribute(Manager &mgr, std::string name, Variant defaultValue,
void Attribute::initialize(Logger &logger)
{
if (optional) {
- defaultValue = rawDefaultValue;
type->build(defaultValue, logger);
}
}
@@ -187,7 +212,6 @@ void Attribute::setDefaultValue(const Variant &defaultValue, Logger &logger)
{
invalidate();
- rawDefaultValue = defaultValue;
optional = true;
initialize(logger);
}
@@ -196,7 +220,6 @@ void Attribute::removeDefaultValue()
{
invalidate();
- rawDefaultValue = nullptr;
defaultValue = nullptr;
optional = false;
}
@@ -264,7 +287,9 @@ bool StructType::insertDefaults(Variant &data, const std::vector<bool> &set,
return ok;
}
-bool StructType::buildFromArray(Variant &data, Logger &logger, bool trim) const
+bool StructType::buildFromArray(Variant &data, Logger &logger,
+ const MagicCallback &magicCallback,
+ bool trim) const
{
bool ok = true;
Variant::arrayType &arr = data.asArray();
@@ -286,14 +311,16 @@ bool StructType::buildFromArray(Variant &data, Logger &logger, bool trim) const
// Make sure the given attributes have to correct type
const size_t len = std::min(n, N);
for (size_t a = 0; a < len; a++) {
- set[a] = attributes[a]->getType()->build(arr[a], logger);
+ set[a] = attributes[a]->getType()->build(arr[a], logger, magicCallback);
ok = ok && set[a];
}
return insertDefaults(data, set, logger) && ok;
}
-bool StructType::buildFromMap(Variant &data, Logger &logger, bool trim) const
+bool StructType::buildFromMap(Variant &data, Logger &logger,
+ const MagicCallback &magicCallback,
+ bool trim) const
{
bool ok = true;
const Variant::mapType &map = data.asMap();
@@ -323,7 +350,8 @@ bool StructType::buildFromMap(Variant &data, Logger &logger, bool trim) const
// Convert the value to the type of the attribute
arr[idx] = value;
- set[idx] = attributes[idx]->getType()->build(arr[idx], logger);
+ set[idx] = attributes[idx]->getType()->build(arr[idx], logger,
+ magicCallback);
} else if (!trim) {
ok = false;
logger.error(std::string("Invalid attribute key \"") + key +
@@ -337,13 +365,14 @@ bool StructType::buildFromMap(Variant &data, Logger &logger, bool trim) const
}
bool StructType::buildFromArrayOrMap(Variant &data, Logger &logger,
+ const MagicCallback &magicCallback,
bool trim) const
{
if (data.isArray()) {
- return buildFromArray(data, logger, trim);
+ return buildFromArray(data, logger, magicCallback, trim);
}
if (data.isMap()) {
- return buildFromMap(data, logger, trim);
+ return buildFromMap(data, logger, magicCallback, trim);
}
throw LoggableException(
std::string(
@@ -375,9 +404,10 @@ void StructType::initialize(Logger &logger)
}
}
-bool StructType::doBuild(Variant &data, Logger &logger) const
+bool StructType::doBuild(Variant &data, Logger &logger,
+ const MagicCallback &magicCallback) const
{
- return buildFromArrayOrMap(data, logger, false);
+ return buildFromArrayOrMap(data, logger, magicCallback, false);
}
bool StructType::doValidate(Logger &logger) const
@@ -491,7 +521,7 @@ bool StructType::derivedFrom(Handle<StructType> other) const
bool StructType::cast(Variant &data, Logger &logger) const
{
- return buildFromArrayOrMap(data, logger, true);
+ return buildFromArrayOrMap(data, logger, NullMagicCallback, true);
}
ssize_t StructType::indexOf(const std::string &name) const
@@ -510,7 +540,8 @@ bool StructType::hasAttribute(const std::string &name) const
/* Class ArrayType */
-bool ArrayType::doBuild(Variant &data, Logger &logger) const
+bool ArrayType::doBuild(Variant &data, Logger &logger,
+ const MagicCallback &magicCallback) const
{
if (!data.isArray()) {
throw LoggableException(std::string("Expected array, but got ") +
@@ -518,23 +549,32 @@ bool ArrayType::doBuild(Variant &data, Logger &logger) const
}
bool res = true;
for (auto &v : data.asArray()) {
- if (!innerType->build(v, logger)) {
+ if (!innerType->build(v, logger, magicCallback)) {
res = false;
}
}
return res;
}
+/* Class UnknownType */
+
+bool UnknownType::doBuild(Variant &, Logger &, const MagicCallback &) const
+{
+ return true;
+}
+
+UnknownType::UnknownType(Manager &mgr) : Type(mgr, "unknown", nullptr, false) {}
+
+Variant UnknownType::create() const { return Variant{nullptr}; }
+
/* Class Constant */
Constant::Constant(Manager &mgr, std::string name, Handle<Typesystem> system,
Handle<Type> type, Variant value)
- : Node(mgr, std::move(name), system),
- type(acquire(type)),
- rawValue(std::move(value))
+ : Node(mgr, std::move(name), system), type(acquire(type)), value(value)
{
ExceptionLogger logger;
- initialize(logger);
+ this->type->build(this->value, logger);
}
Constant::Constant(Manager &mgr, std::string name, Handle<Typesystem> system,
@@ -543,27 +583,20 @@ Constant::Constant(Manager &mgr, std::string name, Handle<Typesystem> system,
{
}
-void Constant::initialize(Logger &logger)
-{
- value = rawValue;
- type->build(value, logger);
-}
-
Rooted<Type> Constant::getType() const { return type; }
void Constant::setType(Handle<Type> type, Logger &logger)
{
this->type = acquire(type);
- initialize(logger);
+ this->type->build(this->value, logger);
}
-const Variant &Constant::getValue() const { return value; }
+Variant &Constant::getValue() { return value; }
void Constant::setValue(Variant value, Logger &logger)
{
- this->rawValue = value;
this->value = std::move(value);
- initialize(logger);
+ this->type->build(this->value, logger);
}
/* Class Typesystem */
@@ -571,7 +604,7 @@ void Constant::setValue(Variant value, Logger &logger)
void Typesystem::doResolve(ResolutionState &state)
{
continueResolveComposita(constants, constants.getIndex(), state);
- continueResolveComposita(types, constants.getIndex(), state);
+ continueResolveComposita(types, types.getIndex(), state);
continueResolveReferences(typesystems, state);
}
diff --git a/src/core/model/Typesystem.hpp b/src/core/model/Typesystem.hpp
index 5b1254a..d88a7e9 100644
--- a/src/core/model/Typesystem.hpp
+++ b/src/core/model/Typesystem.hpp
@@ -29,6 +29,7 @@
#ifndef _OUSIA_MODEL_TYPESYSTEM_HPP_
#define _OUSIA_MODEL_TYPESYSTEM_HPP_
+#include <functional>
#include <map>
#include <vector>
@@ -55,6 +56,21 @@ class SystemTypesystem;
* definitions.
*/
class Type : public Node {
+public:
+ /**
+ * Callback function called when a variant with "magic" value is reached.
+ * This callback allows to transform these magic values into something else.
+ * This mechanism is used to resolve constants.
+ *
+ * @param data is the magic value that should be looked up.
+ * @param isValid is set to true if the magic value does not necessarily
+ * have to be looked up, in this case no error message has to be generated
+ * if the lookup for a constant fails.
+ * @param type is the managed uid of the underlying Type for which the magic
+ * value should be looked up.
+ */
+ using MagicCallback = std::function<void(Variant &data, bool isValid, ManagedUid Type)>;
+
protected:
/**
* Protected constructor to be called by the classes derived from the Type
@@ -82,9 +98,12 @@ protected:
* -- if possible and necessary -- converted to a variant adhering to the
* internal representation used by the Type class.
* @param logger is the Logger instance into which errors should be written.
+ * @param magicCallback is a callback that should be called to other "build"
+ * functions.
* @return true if the conversion was successful, false otherwise.
*/
- virtual bool doBuild(Variant &data, Logger &logger) const = 0;
+ virtual bool doBuild(Variant &data, Logger &logger,
+ const MagicCallback &magicCallback) const = 0;
public:
/**
@@ -109,6 +128,22 @@ public:
* internal representation used by the Type class.
* @param logger is the Logger instance into which errors should be
* written.
+ * @param magicCallback is the callback function to be called whenever
+ * a variant with "magic" value is reached.
+ * @return true if the conversion was successful, false otherwise.
+ */
+ bool build(Variant &data, Logger &logger,
+ const MagicCallback &magicCallback) const;
+
+ /**
+ * Validates and completes the given variant which was read from a
+ * user-supplied source.
+ *
+ * @param data is a variant containing the data that should be checked and
+ * -- if possible and necessary -- converted to a variant adhering to the
+ * internal representation used by the Type class.
+ * @param logger is the Logger instance into which errors should be
+ * written.
* @return true if the conversion was successful, false otherwise.
*/
bool build(Variant &data, Logger &logger) const;
@@ -154,7 +189,8 @@ protected:
* @param logger is the Logger instance into which errors should be written.
* @return true if the conversion was successful, false otherwise.
*/
- bool doBuild(Variant &data, Logger &logger) const override;
+ bool doBuild(Variant &data, Logger &logger,
+ const MagicCallback &magicCallback) const override;
public:
/**
@@ -192,7 +228,8 @@ protected:
* @param logger is the Logger instance into which errors should be written.
* @return true if the conversion was successful, false otherwise.
*/
- bool doBuild(Variant &data, Logger &logger) const override;
+ bool doBuild(Variant &data, Logger &logger,
+ const MagicCallback &magicCallback) const override;
public:
/**
@@ -230,7 +267,8 @@ protected:
* @param logger is the Logger instance into which errors should be written.
* @return true if the conversion was successful, false otherwise.
*/
- bool doBuild(Variant &data, Logger &logger) const override;
+ bool doBuild(Variant &data, Logger &logger,
+ const MagicCallback &magicCallback) const override;
public:
/**
@@ -268,7 +306,8 @@ protected:
* @param logger is the Logger instance into which errors should be written.
* @return true if the conversion was successful, false otherwise.
*/
- bool doBuild(Variant &data, Logger &logger) const override;
+ bool doBuild(Variant &data, Logger &logger,
+ const MagicCallback &magicCallback) const override;
public:
/**
@@ -332,7 +371,8 @@ protected:
* @param logger is the Logger instance into which errors should be written.
* @return true if the conversion was successful, false otherwise.
*/
- bool doBuild(Variant &data, Logger &logger) const override;
+ bool doBuild(Variant &data, Logger &logger,
+ const MagicCallback &magicCallback) const override;
public:
/**
@@ -384,12 +424,6 @@ private:
Owned<Type> type;
/**
- * Initial default value passed to the constructor of the Attribute class
- * that has not been passed through the "build" method of the type.
- */
- Variant rawDefaultValue;
-
- /**
* Default value of the attribute.
*/
Variant defaultValue;
@@ -400,11 +434,7 @@ private:
bool optional;
/**
- * Reinitializes the default value from the raw default value with the
- * current type.
- *
- * @param logger is the logger instance to which errors while building the
- * default value should be passed.
+ * Function used to parse the Attribute default value with the current type.
*/
void initialize(Logger &logger);
@@ -473,7 +503,7 @@ public:
* @return the default value of the attribute. If no default value has been
* given a null variant is returned (the opposite does not hold).
*/
- Variant getDefaultValue() const { return defaultValue; }
+ Variant& getDefaultValue() { return defaultValue; }
/**
* Removes any default value from the attribute, making this attribute
@@ -589,7 +619,8 @@ private:
* of attributes (as needed when casting from a derived type).
* @return true if the operation is successful, false otherwise.
*/
- bool buildFromArray(Variant &data, Logger &logger, bool trim) const;
+ bool buildFromArray(Variant &data, Logger &logger,
+ const MagicCallback &magicCallback, bool trim) const;
/**
* Checks a map and its entries for validity and if possible updates its
@@ -601,7 +632,8 @@ private:
* when casting from a derived type.
* @return true if the operation is successful, false otherwise.
*/
- bool buildFromMap(Variant &data, Logger &logger, bool trim) const;
+ bool buildFromMap(Variant &data, Logger &logger,
+ const MagicCallback &magicCallback, bool trim) const;
/**
* Checks a map or an array for validity and if possible updates its content
@@ -613,7 +645,9 @@ private:
* when casting from a derived type.
* @return true if the operation is successful, false otherwise.
*/
- bool buildFromArrayOrMap(Variant &data, Logger &logger, bool trim) const;
+ bool buildFromArrayOrMap(Variant &data, Logger &logger,
+ const MagicCallback &magicCallback,
+ bool trim) const;
/**
* Rebuilds the internal index and attribute list depending on the parent
@@ -645,7 +679,8 @@ protected:
* @param logger is the Logger instance into which errors should be written.
* @return true if the conversion was successful, false otherwise.
*/
- bool doBuild(Variant &data, Logger &logger) const override;
+ bool doBuild(Variant &data, Logger &logger,
+ const MagicCallback &magicCallback) const override;
/**
* Checks the struct descriptor for being valid.
@@ -819,17 +854,18 @@ protected:
* @param logger is the Logger instance into which errors should be written.
* @return true if the conversion was successful, false otherwise.
*/
- bool doBuild(Variant &data, Logger &logger) const override;
+ bool doBuild(Variant &data, Logger &logger,
+ const MagicCallback &magicCallback) const override;
public:
/**
* Constructor of the ArrayType class.
*
- * @param mgr is the Manager instance to be used for the Node.
* @param innerType is the type of the elements stored in the array.
*/
- ArrayType(Manager &mgr, Handle<Type> innerType)
- : Type(mgr, "", innerType->getTypesystem(), false),
+ ArrayType(Handle<Type> innerType)
+ : Type(innerType->getManager(), innerType->getName() + "[]",
+ innerType->getTypesystem(), false),
innerType(acquire(innerType))
{
}
@@ -869,7 +905,7 @@ protected:
*
* @return always true.
*/
- bool doBuild(Variant &, Logger &) const override { return true; }
+ bool doBuild(Variant &, Logger &, const MagicCallback &) const override;
public:
/**
@@ -878,14 +914,14 @@ public:
*
* @param mgr is the Manager instance to be used for the Node.
*/
- UnknownType(Manager &mgr) : Type(mgr, "unknown", nullptr, false) {}
+ UnknownType(Manager &mgr);
/**
* Returns a nullptr variant.
*
* @return a Variant instance with nullptr value.
*/
- Variant create() const override { return Variant{nullptr}; }
+ Variant create() const override;
};
/**
@@ -900,23 +936,10 @@ private:
Owned<Type> type;
/**
- * Value of the value before a proper type was set.
- */
- Variant rawValue;
-
- /**
* Actual value of the constant.
*/
Variant value;
- /**
- * Reinitializes the value from the raw value with the current type.
- *
- * @param logger is the logger instance to which errors while building the
- * value should be passed.
- */
- void initialize(Logger &logger);
-
public:
/**
* Constructor of the Constant node.
@@ -952,9 +975,10 @@ public:
Rooted<Type> getType() const;
/**
- * Sets the type of the constant to the given type. This will cause the raw
- * value of the variant to be reparsed and any error to be logged in the
- * given logger.
+ * Sets the type of the constant to the given type. This will cause the
+ * value of the variant to be built with the given type and any error to be
+ * logged in the given logger. Note: This operation is possibly lossy and
+ * will destroy values if the current variant value doesn't match the type.
*
* @param type is the new type of the constant.
* @param logger is the logger instance to which errors that occur during
@@ -968,7 +992,7 @@ public:
*
* @return a const reference to the actual value of the constant.
*/
- const Variant &getValue() const;
+ Variant &getValue();
/**
* Sets the value of the constant. The value will be passed to the "build"