summaryrefslogtreecommitdiff
path: root/src/core/model
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/model')
-rw-r--r--src/core/model/Document.cpp2
-rw-r--r--src/core/model/Document.hpp5
-rw-r--r--src/core/model/Domain.cpp4
-rw-r--r--src/core/model/Domain.hpp4
-rw-r--r--src/core/model/Node.cpp30
-rw-r--r--src/core/model/Node.hpp76
-rw-r--r--src/core/model/Typesystem.cpp47
-rw-r--r--src/core/model/Typesystem.hpp81
8 files changed, 206 insertions, 43 deletions
diff --git a/src/core/model/Document.cpp b/src/core/model/Document.cpp
index 0b0a42a..5f0ad4c 100644
--- a/src/core/model/Document.cpp
+++ b/src/core/model/Document.cpp
@@ -297,7 +297,7 @@ bool AnnotationEntity::doValidate(Logger &logger) const
/* Class Document */
-void Document::continueResolve(ResolutionState &state)
+void Document::doResolve(ResolutionState &state)
{
continueResolveComposita(annotations, annotations.getIndex(), state);
if (root != nullptr) {
diff --git a/src/core/model/Document.hpp b/src/core/model/Document.hpp
index 18ec3d5..9410d17 100644
--- a/src/core/model/Document.hpp
+++ b/src/core/model/Document.hpp
@@ -512,6 +512,7 @@ class AnnotationEntity : public Node, public DocumentEntity {
private:
Owned<Anchor> start;
Owned<Anchor> end;
+
protected:
bool doValidate(Logger &logger) const override;
@@ -567,7 +568,7 @@ private:
NodeVector<AnnotationEntity> annotations;
NodeVector<Domain> domains;
- void continueResolve(ResolutionState &state) override;
+ void doResolve(ResolutionState &state) override;
protected:
bool doValidate(Logger &logger) const override;
@@ -625,7 +626,7 @@ public:
{
domains.insert(domains.end(), d.begin(), d.end());
}
-
+
/**
* Returns true if and only if the given StructureNode is part of this
* document, meaning that there is a path of parent references in the
diff --git a/src/core/model/Domain.cpp b/src/core/model/Domain.cpp
index 17f3e02..9a0ed0d 100644
--- a/src/core/model/Domain.cpp
+++ b/src/core/model/Domain.cpp
@@ -70,7 +70,7 @@ FieldDescriptor::FieldDescriptor(Manager &mgr, Handle<Descriptor> parent,
/* Class Descriptor */
-void Descriptor::continueResolve(ResolutionState &state)
+void Descriptor::doResolve(ResolutionState &state)
{
if (attributesDescriptor != nullptr) {
const NodeVector<Attribute> &attributes =
@@ -254,7 +254,7 @@ AnnotationClass::AnnotationClass(
/* Class Domain */
-void Domain::continueResolve(ResolutionState &state)
+void Domain::doResolve(ResolutionState &state)
{
if (!continueResolveComposita(structuredClasses,
structuredClasses.getIndex(), state) |
diff --git a/src/core/model/Domain.hpp b/src/core/model/Domain.hpp
index 5cc7874..d1ba44f 100644
--- a/src/core/model/Domain.hpp
+++ b/src/core/model/Domain.hpp
@@ -390,7 +390,7 @@ private:
std::vector<Rooted<Node>> &path) const;
protected:
- void continueResolve(ResolutionState &state) override;
+ void doResolve(ResolutionState &state) override;
/**
* Adds a FieldDescriptor and checks for name uniqueness.
@@ -695,7 +695,7 @@ private:
NodeVector<Typesystem> typesystems;
protected:
- void continueResolve(ResolutionState &state) override;
+ void doResolve(ResolutionState &state) override;
void addStructuredClass(Handle<StructuredClass> s);
void addAnnotationClass(Handle<AnnotationClass> a);
diff --git a/src/core/model/Node.cpp b/src/core/model/Node.cpp
index a935715..bd023e1 100644
--- a/src/core/model/Node.cpp
+++ b/src/core/model/Node.cpp
@@ -23,6 +23,7 @@
#include <core/common/Logger.hpp>
#include <core/common/Rtti.hpp>
#include <core/common/TypedRttiBuilder.hpp>
+#include <core/common/Utils.hpp>
#include "Node.hpp"
@@ -272,14 +273,14 @@ bool Node::resolve(ResolutionState &state)
}
} else {
size_t resCount = state.resultCount();
- continueResolve(state);
+ doResolve(state);
return state.resultCount() > resCount;
}
}
return false;
}
-void Node::continueResolve(ResolutionState &state)
+void Node::doResolve(ResolutionState &state)
{
// Do nothing in the default implementation
}
@@ -353,8 +354,33 @@ std::vector<ResolutionResult> Node::resolve(const std::string &name,
return resolve(std::vector<std::string>{name}, type);
}
+bool Node::checkDuplicate(Handle<Node> elem,
+ std::unordered_set<std::string> &names,
+ Logger &logger) const
+{
+ const std::string &name = elem->getName();
+ if (!names.emplace(name).second) {
+ logger.error(std::string("Element with name \"") + name +
+ std::string("\" defined multiple times in parent ") +
+ type().name + std::string(" \"") +
+ Utils::join(path(), ".") + std::string("\""));
+ return false;
+ }
+ return true;
+}
+
bool Node::doValidate(Logger &logger) const { return true; }
+bool Node::validateName(Logger &logger) const
+{
+ if (!Utils::isIdentifier(name)) {
+ logger.error(type().name + std::string(" name \"") + name +
+ std::string("\" is not a valid identifier"));
+ return false;
+ }
+ return true;
+}
+
void Node::invalidate()
{
// Only perform the invalidation if necessary
diff --git a/src/core/model/Node.hpp b/src/core/model/Node.hpp
index 0523c69..0168a3e 100644
--- a/src/core/model/Node.hpp
+++ b/src/core/model/Node.hpp
@@ -31,6 +31,7 @@
#include <cstdint>
#include <map>
#include <set>
+#include <unordered_set>
#include <string>
#include <vector>
@@ -196,6 +197,19 @@ private:
*/
bool continueResolveIndex(const Index &index, ResolutionState &state);
+ /**
+ * Checks whether the name of the given node is already stored in the given
+ * set, if yes, logs a corresponding error message.
+ *
+ * @param node is the node of which the name should be checked.
+ * @param names is a set in which all encountered names are stored.
+ * @param logger is the logger instance to which error messages are written.
+ * @return true if the given node has a unique name, false otherwise.
+ */
+ bool checkDuplicate(Handle<Node> node,
+ std::unordered_set<std::string> &names,
+ Logger &logger) const;
+
protected:
/**
* Function which should be overwritten by derived classes in order to
@@ -207,7 +221,7 @@ protected:
*
* @param state is used internally to manage the resolution process.
*/
- virtual void continueResolve(ResolutionState &state);
+ virtual void doResolve(ResolutionState &state);
/**
* Tries to advance the resolution process with the compositum pointed at
@@ -329,6 +343,56 @@ protected:
*/
virtual bool doValidate(Logger &logger) const;
+ /**
+ * Makes sure the name of this node is a valid identifier and loggs a
+ * corresponding error message.
+ *
+ * @param logger is the logger to which the error message is logged.
+ * @return true if the name is valid, false otherwise.
+ */
+ bool validateName(Logger &logger) const;
+
+ /**
+ * Helper function that can be used to forward the validation process to
+ * child nodes.
+ *
+ * @tparam T is the type of the list that should be handled.
+ * @param list is a list of arbitrary kind. The "validate" function is
+ * called for all elementsd of the list.
+ * @param logger is the logger to which any errors should be reported.
+ */
+ template <class T>
+ bool continueValidation(const T &list, Logger &logger) const
+ {
+ bool res = true;
+ for (auto elem : list) {
+ res = elem->validate(logger) & res;
+ }
+ return res;
+ }
+
+ /**
+ * Helper function that can be used to forward the validation process to
+ * child nodes while at the same time checking that the children have no
+ * duplicated names.
+ *
+ * @tparam T is the type of the list that should be handled.
+ * @param list is a list of arbitrary kind. The "validate" function is
+ * called for all elementsd of the list.
+ * @param logger is the logger to which any errors should be reported.
+ */
+ template <class T>
+ bool continueValidationCheckDuplicates(const T &list, Logger &logger) const
+ {
+ bool res = true;
+ std::unordered_set<std::string> names;
+ for (auto elem : list) {
+ res = elem->validate(logger) & checkDuplicate(elem, names, logger) &
+ res;
+ }
+ return res;
+ }
+
public:
/**
* Initializes the node with empty name and parent.
@@ -460,8 +524,9 @@ class NodeVector
: public ManagedGenericList<T, std::vector<Handle<T>>,
ListAccessor<Handle<T>>, Listener> {
public:
- using ManagedGenericList<T, std::vector<Handle<T>>, ListAccessor<Handle<T>>,
- Listener>::ManagedGenericList;
+ using Base = ManagedGenericList<T, std::vector<Handle<T>>, ListAccessor<Handle<T>>,
+ Listener>;
+ using Base::Base;
/**
* Returns the reference to the internal index.
@@ -490,9 +555,10 @@ class NodeMap
: public ManagedGenericMap<K, T, std::map<K, Handle<T>>,
MapAccessor<std::pair<K, Handle<T>>>, Listener> {
public:
- using ManagedGenericMap<K, T, std::map<K, Handle<T>>,
+ using Base = ManagedGenericMap<K, T, std::map<K, Handle<T>>,
MapAccessor<std::pair<K, Handle<T>>>,
- Listener>::ManagedGenericMap;
+ Listener>;
+ using Base::Base;
/**
* Returns the reference to the internal index.
diff --git a/src/core/model/Typesystem.cpp b/src/core/model/Typesystem.cpp
index 726de3e..a3d354c 100644
--- a/src/core/model/Typesystem.cpp
+++ b/src/core/model/Typesystem.cpp
@@ -151,12 +151,7 @@ EnumType::Ordinal EnumType::valueOf(const std::string &name) const
bool Attribute::doValidate(Logger &logger) const
{
- if (!Utils::isIdentifier(getName())) {
- logger.error("Attribute name \"" + getName() +
- "\" is not a valid identifier.");
- return false;
- }
- return true;
+ return validateName(logger);
}
/* Class StructType */
@@ -332,22 +327,8 @@ bool StructType::doBuild(Variant &data, Logger &logger) const
bool StructType::doValidate(Logger &logger) const
{
- // Check whether all attributes are valid and unique
- std::unordered_set<std::string> names;
- bool res = true;
- for (Handle<Attribute> a : attributes) {
- res = a->validate(logger) && res;
- const std::string &name = a->getName();
- if (!names.emplace(name).second) {
- logger.error(
- std::string("Attribute with name \"") + name +
- std::string("\" defined multiple times in structure \"") +
- Utils::join(path(), ".") + std::string("\""));
- res = false;
- }
- }
-
- return res;
+ return validateName(logger) &
+ continueValidationCheckDuplicates(attributes, logger);
}
Rooted<StructType> StructType::createValidated(
@@ -473,6 +454,28 @@ bool ArrayType::doBuild(Variant &data, Logger &logger) const
return res;
}
+/* Class Typesystem */
+
+void Typesystem::doResolve(ResolutionState &state)
+{
+ continueResolveComposita(constants, constants.getIndex(), state);
+ continueResolveComposita(types, constants.getIndex(), state);
+}
+
+bool Typesystem::doValidate(Logger &logger) const
+{
+ return validateName(logger) &
+ continueValidationCheckDuplicates(constants, logger) &
+ continueValidationCheckDuplicates(types, logger);
+}
+
+Rooted<StructType> Typesystem::createStructType(const std::string &name)
+{
+ Rooted<StructType> structType{new StructType(getManager(), name, this)};
+ addType(structType);
+ return structType;
+}
+
/* Class SystemTypesystem */
SystemTypesystem::SystemTypesystem(Manager &mgr)
diff --git a/src/core/model/Typesystem.hpp b/src/core/model/Typesystem.hpp
index 7bc8950..64922f0 100644
--- a/src/core/model/Typesystem.hpp
+++ b/src/core/model/Typesystem.hpp
@@ -368,10 +368,7 @@ public:
*/
class Attribute : public Node {
private:
- /**
- * Reference to the actual type of the attribute.
- */
- const Owned<Type> type;
+
protected:
/**
@@ -384,14 +381,25 @@ protected:
public:
/**
+ * Reference to the actual type of the attribute.
+ */
+ 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.
*/
- const Variant defaultValue;
+ Variant defaultValue;
/**
* Flag indicating whether this attribute is actually optional or not.
*/
- const bool optional;
+ bool optional;
/**
* Constructor of the Attribute class.
@@ -430,6 +438,50 @@ public:
}
/**
+ * Sets a new default value. This makes the Attribute optional. The given
+ * default value is passed through the "build" function of the current
+ * type.
+ *
+ * @param defaultValue is the new default value.
+ * @param logger is the logger instance to which errors that occur during
+ * reinterpretion of the default value.
+ */
+ void setDefaultValue(const Variant &defaultValue, Logger &logger);
+
+ /**
+ * Returns the default value of the attribute.
+ *
+ * @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;
+
+ /**
+ * Removes any default value from the attribute, making this attribute
+ * non-optional.
+ */
+ void removeDefaultValue();
+
+ /**
+ * Returns true if the attribute is optional (a default value has been
+ * supplied by the user).
+ *
+ * @return true if the attribute is optional, false otherwise.
+ */
+ bool isOptional() const {return optional; }
+
+ /**
+ * Sets the type of the attribute to the specified value. This will
+ * reinterpret the default value that has been passed to the attribute (if
+ * available).
+ *
+ * @param type is the new type that should be used for the attribute.
+ * @param logger is the logger instance to which errors that occur during
+ * reinterpretion of the default value.
+ */
+ void setType(Handle<Type> type, Logger &logger);
+
+ /**
* Returns a reference to the type descriptor holding the type of the
* attribute.
*
@@ -859,6 +911,12 @@ private:
*/
NodeVector<Constant> constants;
+protected:
+
+ void doResolve(ResolutionState &state) override;
+
+ bool doValidate(Logger &logger) const override;
+
public:
/**
* Constructor of the Typesystem class.
@@ -867,11 +925,20 @@ public:
* @param name is the name of the typesystem.
*/
Typesystem(Manager &mgr, std::string name)
- : Node(mgr, name), types(this), constants(this)
+ : Node(mgr, std::move(name)), types(this), constants(this)
{
}
/**
+ * Creates a new StructType instance with the given name. Adds the new
+ * StructType as member to the typesystem.
+ *
+ * @param name is the name of the structure that should be created.
+ * @return the new StructType instance.
+ */
+ Rooted<StructType> createStructType(const std::string &name);
+
+ /**
* Adds the given type to the to the type list.
*
* @param type is the Type that should be stored in this Typesystem