summaryrefslogtreecommitdiff
path: root/src/core/model
diff options
context:
space:
mode:
authorAndreas Stöckel <astoecke@techfak.uni-bielefeld.de>2015-01-30 03:09:37 +0100
committerAndreas Stöckel <astoecke@techfak.uni-bielefeld.de>2015-01-30 03:09:37 +0100
commitc4da68ba28e742810d05d35f0a26ef1d9b8c5b6c (patch)
treee506de597542f2a48fc025b13b4765a791339fb9 /src/core/model
parent90b2e9507e9d720452792b863b422221fe96d948 (diff)
stuff
Diffstat (limited to 'src/core/model')
-rw-r--r--src/core/model/Typesystem.cpp107
-rw-r--r--src/core/model/Typesystem.hpp116
2 files changed, 140 insertions, 83 deletions
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"