diff options
Diffstat (limited to 'src/core/model')
-rw-r--r-- | src/core/model/Document.cpp | 2 | ||||
-rw-r--r-- | src/core/model/Document.hpp | 5 | ||||
-rw-r--r-- | src/core/model/Domain.cpp | 4 | ||||
-rw-r--r-- | src/core/model/Domain.hpp | 4 | ||||
-rw-r--r-- | src/core/model/Node.cpp | 30 | ||||
-rw-r--r-- | src/core/model/Node.hpp | 76 | ||||
-rw-r--r-- | src/core/model/Typesystem.cpp | 47 | ||||
-rw-r--r-- | src/core/model/Typesystem.hpp | 81 |
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 |