summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/Node.hpp5
-rw-r--r--src/core/managed/ManagedContainer.hpp11
-rw-r--r--src/core/model/Document.cpp104
-rw-r--r--src/core/model/Document.hpp108
-rw-r--r--src/core/model/Domain.cpp54
-rw-r--r--src/core/model/Domain.hpp112
-rw-r--r--src/core/model/Typesystem.hpp80
7 files changed, 412 insertions, 62 deletions
diff --git a/src/core/Node.hpp b/src/core/Node.hpp
index 4bc95be..516da03 100644
--- a/src/core/Node.hpp
+++ b/src/core/Node.hpp
@@ -350,6 +350,11 @@ public:
* Returns the name of the node.
*/
std::string getName() const { return name; }
+
+ /**
+ * Returns a reference to the name of the node.
+ */
+ const std::string& getNameRef() const { return name; }
/**
* Specifies whether the node has a name, e.g. whether the current name is
diff --git a/src/core/managed/ManagedContainer.hpp b/src/core/managed/ManagedContainer.hpp
index 19bff3f..6bf1915 100644
--- a/src/core/managed/ManagedContainer.hpp
+++ b/src/core/managed/ManagedContainer.hpp
@@ -32,6 +32,7 @@
#include <unordered_set>
#include <vector>
#include <map>
+#include <stdexcept>
#include <type_traits>
#include "Manager.hpp"
@@ -496,6 +497,16 @@ public:
}
Base::c.pop_back();
}
+
+ Rooted<T> operator[](int i) const {
+ for (const_iterator it = Base::cbegin(); it != Base::cend(); it++) {
+ if (i == 0) {
+ return Rooted<T>(*it);
+ }
+ i--;
+ }
+ throw std::out_of_range(std::to_string(i) + " is out of range!");
+ }
};
/**
diff --git a/src/core/model/Document.cpp b/src/core/model/Document.cpp
index 31b22e3..709981b 100644
--- a/src/core/model/Document.cpp
+++ b/src/core/model/Document.cpp
@@ -58,7 +58,7 @@ int DocumentEntity::getFieldDescriptorIndex(const std::string &fieldName)
}
void DocumentEntity::getField(ManagedVector<StructuredEntity> &res,
- const std::string &fieldName)
+ const std::string &fieldName)
{
int f = getFieldDescriptorIndex(fieldName);
if (f < 0) {
@@ -85,6 +85,108 @@ ManagedVector<StructuredEntity> &DocumentEntity::getField(
"The given FieldDescriptor is not specified in the Descriptor of this "
"node.");
}
+
+static Rooted<StructuredClass> resolveDescriptor(
+ std::vector<Handle<Domain>> domains, const std::string &className)
+{
+ // iterate over all domains.
+ for (auto &d : domains) {
+ // use the actual resolve method.
+ std::vector<Rooted<Managed>> resolved = d->resolve(className);
+ // if we don't find anything, continue.
+ if (resolved.size() == 0) {
+ continue;
+ }
+ // Otherwise take the first valid result.
+ for (auto &r : resolved) {
+ Managed *m = &(*r);
+ StructuredClass *c = dynamic_cast<StructuredClass *>(m);
+ if (c != nullptr) {
+ return Rooted<StructuredClass>(c);
+ }
+ }
+ }
+ return {nullptr};
+}
+
+Rooted<StructuredEntity> StructuredEntity::buildRootEntity(
+ Handle<Document> document, std::vector<Handle<Domain>> domains,
+ const std::string &className, Variant attributes, std::string name)
+{
+ // If the parent is not set, we can not build the entity.
+ if (document == nullptr) {
+ return {nullptr};
+ }
+ // If we can not find the correct descriptor, we can not build the entity
+ // either.
+ Rooted<StructuredClass> descriptor = resolveDescriptor(domains, className);
+ if (descriptor == nullptr) {
+ return {nullptr};
+ }
+ // Then construct the StructuredEntity itself.
+ Rooted<StructuredEntity> root{
+ new StructuredEntity(document->getManager(), document, descriptor,
+ attributes, std::move(name))};
+ // append it to the document.
+ document->setRoot(root);
+ // and return it.
+ return root;
+}
+
+Rooted<StructuredEntity> StructuredEntity::buildEntity(
+ Handle<DocumentEntity> parent, std::vector<Handle<Domain>> domains,
+ const std::string &className, const std::string &fieldName,
+ Variant attributes, std::string name)
+{
+ // If the parent is not set, we can not build the entity.
+ if (parent == nullptr) {
+ return {nullptr};
+ }
+ // If we can not find the correct descriptor, we can not build the entity
+ // either.
+ Rooted<StructuredClass> descriptor = resolveDescriptor(domains, className);
+ if (descriptor == nullptr) {
+ return {nullptr};
+ }
+ // Then construct the StructuredEntity itself.
+ Rooted<StructuredEntity> entity{new StructuredEntity(
+ parent->getManager(), parent, descriptor, attributes, std::move(name))};
+ // if the field does not exist, return null handle as well.
+ if (!parent->hasField(fieldName)) {
+ return {nullptr};
+ }
+ // append the new entity to the right field.
+ ManagedVector<StructuredEntity> field{parent};
+ parent->getField(field, fieldName);
+ field.push_back(entity);
+
+ // and return it.
+ return entity;
+}
+
+Rooted<DocumentPrimitive> DocumentPrimitive::buildEntity(
+ Handle<DocumentEntity> parent, Variant content,
+ const std::string &fieldName)
+{
+ // If the parent is not set, we can not build the entity.
+ if (parent == nullptr) {
+ return {nullptr};
+ }
+ // Then construct the StructuredEntity itself.
+ Rooted<DocumentPrimitive> entity{
+ new DocumentPrimitive(parent->getManager(), parent, content)};
+ // if the field does not exist, return null handle as well.
+ if (!parent->hasField(fieldName)) {
+ return {nullptr};
+ }
+ // append the new entity to the right field.
+ ManagedVector<StructuredEntity> field{parent};
+ parent->getField(field, fieldName);
+ field.push_back(entity);
+
+ // and return it.
+ return entity;
+}
}
}
diff --git a/src/core/model/Document.hpp b/src/core/model/Document.hpp
index 3114480..15a4599 100644
--- a/src/core/model/Document.hpp
+++ b/src/core/model/Document.hpp
@@ -26,9 +26,11 @@
*
* A Document, from top to bottom, consists of "Document" instance,
* which "owns" the structural root node of the in-document graph. This might
- * for example be a "book" node, if the respective document implements the
- * "book" domain. That root node in turn has structure nodes as children as well
- * as annotations that refer to the content of that structure node.
+ * for example be a "book" node of the "book" domain. That root node in turn has
+ * structure nodes as children, which in turn may have children. This
+ * constitutes a Structure Tree. Additionally annotations may be attached to
+ * Structure Nodes, effectively resulting in a Document Graph instead of a
+ * Document Tree (other references may introduce cycles as well).
*
* Consider this simplified XML representation of a document (TODO: Use
* non-simplified XML as soon as possible):
@@ -78,6 +80,7 @@ namespace model {
class StructuredEntity;
class AnnotationEntity;
+class Document;
/**
* A DocumentEntity is the common superclass for StructuredEntities and
@@ -108,8 +111,11 @@ public:
{
// TODO: Validation at construction time?
// insert empty vectors for each field.
- for (size_t f = 0; f < descriptor->getFieldDescriptors().size(); f++) {
- fields.push_back(ManagedVector<StructuredEntity>(this));
+ if (!descriptor.isNull()) {
+ for (size_t f = 0; f < descriptor->getFieldDescriptors().size();
+ f++) {
+ fields.push_back(ManagedVector<StructuredEntity>(this));
+ }
}
}
@@ -200,6 +206,57 @@ public:
}
ManagedVector<AnnotationEntity> &getAnnotations() { return annotations; }
+
+ /**
+ * This builds the root StructuredEntity for the given document. It
+ * automatically appends the newly build entity to the given document.
+ *
+ * @param document is the document this entity shall be build for. The
+ * resulting entity will automatically be appended to that
+ * document. Also the manager of that document will be
+ * used to register the new node.
+ * @param domains are the domains that are used to find the
+ * StructuredClass for the new node. The domains will be
+ * searched in the given order.
+ * @param className is the name of the StructuredClass.
+ * @param attributes are the attributes of the new node in terms of a Struct
+ * variant (empty per default).
+ * @param name is the name of this StructuredEntity (empty per
+ * default).
+ * @return the newly created StructuredEntity or a nullptr if some
+ * input handle was empty or the given domains did not
+ * contain a StructuredClass with the given name.
+ */
+ static Rooted<StructuredEntity> buildRootEntity(
+ Handle<Document> document, std::vector<Handle<Domain>> domains,
+ const std::string &className, Variant attributes = Variant(),
+ std::string name = "");
+
+ /**
+ * This builds a StructuredEntity as child of the given DocumentEntity. It
+ * automatically appends the newly build entity to its parent.
+ *
+ * @param parent is the parent DocumentEntity. The newly constructed
+ * StructuredEntity will automatically be appended to it.
+ * @param domains are the domains that are used to find the
+ * StructuredClass for the new node. The domains will be
+ * searched in the given order.
+ * @param className is the name of the StructuredClass.
+ * @param fieldName is the name of the field where the newly constructed
+ * StructuredEntity shall be appended.
+ * @param attributes are the attributes of the new node in terms of a Struct
+ * variant (empty per default).
+ * @param name is the name of this StructuredEntity (empty per
+ * default).
+ *
+ * @return the newly created StructuredEntity or a nullptr if some
+ * input handle was empty or the given domains did not
+ * contain a StructuredClass with the given name.
+ */
+ static Rooted<StructuredEntity> buildEntity(
+ Handle<DocumentEntity> parent, std::vector<Handle<Domain>> domains,
+ const std::string &className, const std::string &fieldName = "",
+ Variant attributes = Variant(), std::string name = "");
};
/**
@@ -209,7 +266,7 @@ public:
*/
class DocumentPrimitive : public StructuredEntity {
public:
- DocumentPrimitive(Manager &mgr, Handle<StructuredEntity> parent,
+ DocumentPrimitive(Manager &mgr, Handle<DocumentEntity> parent,
Variant content)
: StructuredEntity(mgr, parent, nullptr, std::move(content))
{
@@ -218,6 +275,25 @@ public:
Variant getContent() const { return getAttributes(); }
// TODO: Override such methods like "getField" to disable them?
+
+ /**
+ * This builds a DocumentPrimitive as child of the given DocumentEntity. It
+ * automatically appends the newly build entity to its parent.
+ *
+ * @param parent is the parent DocumentEntity. The newly constructed
+ * DocumentPrimitive will automatically be appended to it.
+ * @param content is the primitive content of the new node in terms of a
+ * Struct variant.
+ * @param fieldName is the name of the field where the newly constructed
+ * StructuredEntity shall be appended.
+ *
+ * @return the newly created StructuredEntity or a nullptr if some
+ * input handle was empty or the given domains did not
+ * contain a StructuredClass with the given name.
+ */
+ static Rooted<DocumentPrimitive> buildEntity(
+ Handle<DocumentEntity> parent,
+ Variant content, const std::string &fieldName = "");
};
/**
@@ -282,6 +358,26 @@ public:
Rooted<Anchor> getEnd() { return end; }
};
+
+/**
+ * A Document is mainly a wrapper for the Root structure node of the Document
+ * Graph.
+ */
+class Document : public Node {
+private:
+ Owned<StructuredEntity> root;
+
+public:
+ Document(Manager &mgr, std::string name)
+ // TODO: Can a document have a parent?
+ : Node(mgr, std::move(name), nullptr)
+ {
+ }
+
+ void setRoot(Handle<StructuredEntity> root) { root = acquire(root); };
+
+ Rooted<StructuredEntity> getRoot() const { return root; }
+};
}
}
diff --git a/src/core/model/Domain.cpp b/src/core/model/Domain.cpp
index bafd205..8eee86a 100644
--- a/src/core/model/Domain.cpp
+++ b/src/core/model/Domain.cpp
@@ -21,6 +21,60 @@
namespace ousia {
namespace model {
+void FieldDescriptor::doResolve(std::vector<Rooted<Managed>> &res,
+ const std::vector<std::string> &path,
+ Filter filter, void *filterData, unsigned idx,
+ VisitorSet &visited)
+{
+ // We call resolve for the children, but give them the field name as
+ // alias.
+ for (auto &c : children) {
+ c->resolve(res, path, filter, filterData, idx, visited, &getNameRef());
+ }
+}
+
+// TODO: better alias?
+static std::string DESCRIPTOR_ATTRIBUTES_ALIAS {"attributes"};
+
+void Descriptor::doResolve(std::vector<Rooted<Managed>> &res,
+ const std::vector<std::string> &path, Filter filter,
+ void *filterData, unsigned idx, VisitorSet &visited)
+{
+ // TODO: This could be a problem, because the name of the field might be
+ // needed in the path.
+ for (auto &fd : fieldDescriptors) {
+ fd->resolve(res, path, filter, filterData, idx, visited, nullptr);
+ }
+ // TODO: This throws a SEGFAULT for some reason.
+// attributesDescriptor->resolve(res, path, filter, filterData, idx, visited,
+// &DESCRIPTOR_ATTRIBUTES_ALIAS);
+}
+
+void StructuredClass::doResolve(std::vector<Rooted<Managed>> &res,
+ const std::vector<std::string> &path,
+ Filter filter, void *filterData, unsigned idx,
+ VisitorSet &visited)
+{
+ Descriptor::doResolve(res, path, filter, filterData, idx, visited);
+ if(!isa.isNull()){
+ isa->doResolve(res, path, filter, filterData, idx, visited);
+ }
+}
+
+void Domain::doResolve(std::vector<Rooted<Managed>> &res,
+ const std::vector<std::string> &path, Filter filter,
+ void *filterData, unsigned idx, VisitorSet &visited)
+{
+ for (auto &s : rootStructures) {
+ s->resolve(res, path, filter, filterData, idx, visited, nullptr);
+ }
+ for (auto &a : annotationClasses) {
+ a->resolve(res, path, filter, filterData, idx, visited, nullptr);
+ }
+ for (auto &t : typesystems) {
+ t->resolve(res, path, filter, filterData, idx, visited, nullptr);
+ }
+}
}
}
diff --git a/src/core/model/Domain.hpp b/src/core/model/Domain.hpp
index 50c0bb1..112f2fa 100644
--- a/src/core/model/Domain.hpp
+++ b/src/core/model/Domain.hpp
@@ -84,14 +84,16 @@
#include <core/managed/ManagedContainer.hpp>
#include <core/Node.hpp>
+#include <core/RangeSet.hpp>
#include "Typesystem.hpp"
namespace ousia {
namespace model {
-class StructuredClass;
class Descriptor;
+class StructuredClass;
+class Domain;
/**
* As mentioned in the description above a FieldDescriptor specifies the
@@ -137,6 +139,12 @@ private:
FieldType fieldType;
Owned<Type> primitiveType;
+protected:
+ void doResolve(std::vector<Rooted<Managed>> &res,
+ const std::vector<std::string> &path, Filter filter,
+ void *filterData, unsigned idx,
+ VisitorSet &visited) override;
+
public:
const bool optional;
@@ -146,17 +154,18 @@ public:
* set to "PRIMITIVE".
*
* @param mgr is the global Manager instance.
- * @param name is the name of this field.
* @param parent is a handle of the Descriptor node that has this
* FieldDescriptor.
* @param primitiveType is a handle to some Type in some Typesystem of which
* one instance is allowed to fill this field.
+ * @param name is the name of this field.
* @param optional should be set to 'false' is this field needs to be
* filled in order for an instance of the parent
* Descriptor to be valid.
*/
- FieldDescriptor(Manager &mgr, std::string name, Handle<Descriptor> parent,
- Handle<Type> primitiveType, bool optional)
+ FieldDescriptor(Manager &mgr, Handle<Descriptor> parent,
+ Handle<Type> primitiveType, std::string name = "",
+ bool optional = false)
: Node(mgr, std::move(name), parent),
children(this),
fieldType(FieldType::PRIMITIVE),
@@ -170,21 +179,21 @@ public:
* children here.
*
* @param mgr is the global Manager instance.
- * @param name is the name of this field.
* @param parent is a handle of the Descriptor node that has this
* FieldDescriptor.
* @param fieldType is the FieldType of this FieldDescriptor, either
* TREE for the main or default structure or SUBTREE
* for supporting structures.
+ * @param name is the name of this field.
* @param optional should be set to 'false' is this field needs to be
* filled in order for an instance of the parent
* Descriptor to be valid.
*/
- FieldDescriptor(Manager &mgr, std::string name, Handle<Descriptor> parent,
- FieldType fieldType,
- ManagedVector<StructuredClass> children, bool optional)
+ FieldDescriptor(Manager &mgr, Handle<Descriptor> parent,
+ FieldType fieldType = FieldType::TREE,
+ std::string name = "", bool optional = false)
: Node(mgr, std::move(name), parent),
- children(children),
+ children(this),
fieldType(fieldType),
// TODO: What would be a wise initialization of the primitiveType?
optional(optional)
@@ -194,6 +203,11 @@ public:
// TODO: Is returning a ManagedVector alright?
ManagedVector<StructuredClass> &getChildren() { return children; }
+ const ManagedVector<StructuredClass> &getChildren() const
+ {
+ return children;
+ }
+
FieldType getFieldType() const { return fieldType; }
bool isPrimitive() const { return fieldType == FieldType::PRIMITIVE; }
@@ -212,7 +226,7 @@ public:
* the attribute specification of a descriptor is done by referencing an
* appropriate StructType that contains all permitted keys and value types.
*
- * TODO: What aout optional attributes?
+ * TODO: What about optional attributes?
*
* In XML terms the difference between primitive fields and attributes can be
* explained as the difference between node attributes and node children.
@@ -233,14 +247,19 @@ private:
Owned<StructType> attributesDescriptor;
ManagedVector<FieldDescriptor> fieldDescriptors;
+protected:
+ void doResolve(std::vector<Rooted<Managed>> &res,
+ const std::vector<std::string> &path, Filter filter,
+ void *filterData, unsigned idx,
+ VisitorSet &visited) override;
+
public:
- Descriptor(Manager &mgr, std::string name, Handle<Node> parent,
+ Descriptor(Manager &mgr, std::string name, Handle<Domain> domain,
// TODO: What would be a wise default value for attributes?
- Handle<StructType> attributesDescriptor,
- ManagedVector<FieldDescriptor> fieldDescriptors)
- : Node(mgr, std::move(name), parent),
+ Handle<StructType> attributesDescriptor)
+ : Node(mgr, std::move(name), domain),
attributesDescriptor(acquire(attributesDescriptor)),
- fieldDescriptors(fieldDescriptors)
+ fieldDescriptors(this)
{
}
@@ -261,9 +280,7 @@ public:
}
};
-// TODO: Implement
-class Cardinality {
-};
+typedef RangeSet<size_t> Cardinality;
/**
* A StructuredClass specifies nodes in the StructureTree of a document that
@@ -346,21 +363,25 @@ private:
Owned<StructuredClass> isa;
ManagedVector<FieldDescriptor> parents;
+protected:
+ void doResolve(std::vector<Rooted<Managed>> &res,
+ const std::vector<std::string> &path, Filter filter,
+ void *filterData, unsigned idx,
+ VisitorSet &visited) override;
+
public:
const bool transparent;
- StructuredClass(Manager &mgr, std::string name, Handle<Node> parent,
- Handle<StructType> attributesDescriptor,
- ManagedVector<FieldDescriptor> fieldDescriptors,
+ StructuredClass(Manager &mgr, std::string name, Handle<Domain> domain,
const Cardinality &cardinality,
+ Handle<StructType> attributesDescriptor = {nullptr},
// TODO: What would be a wise default value for isa?
- Handle<StructuredClass> isa,
- ManagedVector<FieldDescriptor> parents, bool transparent)
- : Descriptor(mgr, std::move(name), parent, attributesDescriptor,
- fieldDescriptors),
+ Handle<StructuredClass> isa = {nullptr},
+ bool transparent = false)
+ : Descriptor(mgr, std::move(name), domain, attributesDescriptor),
cardinality(cardinality),
isa(acquire(isa)),
- parents(parents),
+ parents(this),
transparent(transparent)
{
}
@@ -370,7 +391,7 @@ public:
Rooted<StructuredClass> getIsA() const { return isa; }
// TODO: Is returning a ManagedVector alright?
- ManagedVector<FieldDescriptor>& getParents() { return parents; }
+ ManagedVector<FieldDescriptor> &getParents() { return parents; }
const ManagedVector<FieldDescriptor> &getParents() const { return parents; }
};
@@ -394,28 +415,51 @@ class Domain : public Node {
private:
ManagedVector<StructuredClass> rootStructures;
ManagedVector<AnnotationClass> annotationClasses;
+ ManagedVector<Typesystem> typesystems;
+
+protected:
+ void doResolve(std::vector<Rooted<Managed>> &res,
+ const std::vector<std::string> &path, Filter filter,
+ void *filterData, unsigned idx,
+ VisitorSet &visited) override;
public:
- Domain(Manager &mgr, std::string name,
- ManagedVector<StructuredClass> rootStructures,
- ManagedVector<AnnotationClass> annotationClasses)
+ Domain(Manager &mgr, std::string name)
// TODO: Can a domain have a parent?
: Node(mgr, std::move(name), nullptr),
- rootStructures(rootStructures),
- annotationClasses(annotationClasses)
+ rootStructures(this),
+ annotationClasses(this),
+ typesystems(this)
{
}
// TODO: Is returning a ManagedVector alright?
- ManagedVector<StructuredClass> getRootStructures()
+ ManagedVector<StructuredClass> &getRootStructures()
{
return rootStructures;
}
- ManagedVector<AnnotationClass> getAnnotationClasses()
+ const ManagedVector<StructuredClass> &getRootStructures() const
+ {
+ return rootStructures;
+ }
+
+ ManagedVector<AnnotationClass> &getAnnotationClasses()
+ {
+ return annotationClasses;
+ }
+
+ const ManagedVector<AnnotationClass> &getAnnotationClasses() const
{
return annotationClasses;
}
+
+ ManagedVector<Typesystem> &getTypesystems() { return typesystems; }
+
+ const ManagedVector<Typesystem> &getTypesystems() const
+ {
+ return typesystems;
+ }
};
}
}
diff --git a/src/core/model/Typesystem.hpp b/src/core/model/Typesystem.hpp
index 347adb8..20c6e8b 100644
--- a/src/core/model/Typesystem.hpp
+++ b/src/core/model/Typesystem.hpp
@@ -50,7 +50,7 @@ protected:
{
}
- virtual bool doPrepare(Variant &var, Logger &log) = 0;
+ virtual bool doPrepare(Variant &var, Logger &log) const = 0;
public:
/**
@@ -65,12 +65,12 @@ public:
/**
* TODO: DOC
*/
- virtual Variant create() = 0;
+ virtual Variant create() const = 0;
/**
* TODO: DOC
*/
- bool prepare(Variant &var, Logger &log)
+ bool prepare(Variant &var, Logger &log) const
{
try {
return doPrepare(var, log);
@@ -88,7 +88,7 @@ protected:
/**
* TODO: DOC
*/
- bool doPrepare(Variant &var, Logger &log) override
+ bool doPrepare(Variant &var, Logger &log) const override
{
if (!var.isPrimitive()) {
throw LoggableException{"Expected a string or primitive input."};
@@ -114,7 +114,7 @@ public:
/**
* TODO: DOC
*/
- Variant create() override { return Variant{""}; }
+ Variant create() const override { return Variant{""}; }
};
class IntType : public Type {
@@ -122,7 +122,7 @@ protected:
/**
* TODO: DOC
*/
- bool doPrepare(Variant &var, Logger &log) override
+ bool doPrepare(Variant &var, Logger &log) const override
{
if (!var.isInt()) {
throw LoggableException{"Expected an integer value."};
@@ -142,7 +142,7 @@ public:
/**
* TODO: DOC
*/
- Variant create() override { return Variant{0}; }
+ Variant create() const override { return Variant{0}; }
};
class DoubleType : public Type {
@@ -150,7 +150,7 @@ protected:
/**
* TODO: DOC
*/
- bool doPrepare(Variant &var, Logger &log) override
+ bool doPrepare(Variant &var, Logger &log) const override
{
if (!var.isInt() && !var.isDouble()) {
throw LoggableException{"Expected a double value."};
@@ -171,7 +171,7 @@ public:
/**
* TODO: DOC
*/
- Variant create() override { return Variant{0.}; }
+ Variant create() const override { return Variant{0.}; }
};
class UnknownType : public Type {
@@ -179,7 +179,7 @@ protected:
/**
* TODO: DOC
*/
- bool doPrepare(Variant &var, Logger &log) override { return true; }
+ bool doPrepare(Variant &var, Logger &log) const override { return true; }
public:
/**
@@ -193,7 +193,7 @@ public:
/**
* TODO: DOC
*/
- Variant create() override { return Variant{nullptr}; }
+ Variant create() const override { return Variant{nullptr}; }
};
class BoolType : public Type {
@@ -201,7 +201,7 @@ protected:
/**
* TODO: DOC
*/
- bool doPrepare(Variant &var, Logger &log) override
+ bool doPrepare(Variant &var, Logger &log) const override
{
if (!var.isBool()) {
throw LoggableException("Expected boolean value!");
@@ -221,7 +221,7 @@ public:
/**
* TODO: DOC
*/
- Variant create() override { return Variant{false}; }
+ Variant create() const override { return Variant{false}; }
};
class EnumerationType : public Type {
@@ -232,7 +232,7 @@ protected:
/**
* TODO: DOC
*/
- bool doPrepare(Variant &var, Logger &log) override
+ bool doPrepare(Variant &var, Logger &log) const override
{
if (var.isInt()) {
int i = var.asInt();
@@ -275,7 +275,7 @@ public:
/**
* TODO: DOC
*/
- Variant create() override { return Variant{0}; }
+ Variant create() const override { return Variant{0}; }
};
class StructType : public Type {
@@ -296,7 +296,45 @@ public:
}
};
-private:
+protected:
+ /**
+ * TODO: DOC
+ */
+ bool doPrepare(Variant &var, Logger &log) const override
+ {
+ // If we already have an array, we just check that.
+ if(var.isArray()){
+ auto arr = var.asArray();
+ for(size_t a = 0; a < attrs.size(); a++){
+ if(!attrs[a].type->prepare(arr[a], log)){
+ return false;
+ }
+ }
+ return true;
+ }
+ // Otherwise we expect a map.
+ if (!var.isMap()) {
+ throw LoggableException("Expected map!");
+ }
+ auto &map = var.asMap();
+ // We transform the map into an array with the correct values at the
+ // correct places.
+ std::vector<Variant> vec;
+ for (auto &a : attrs) {
+ auto it = map.find(a.name);
+ // we use the default if nothing is set.
+ if (it == map.end() || !a.type->prepare(it->second, log)) {
+ log.note(std::string("Using default value for ") + a.name);
+ vec.push_back(a.defaultValue);
+ } else{
+ vec.push_back(it->second);
+ }
+ }
+ var = Variant(vec);
+ return true;
+ }
+
+public:
std::vector<AttributeDescriptor> attrs;
StructType(Manager &mgr, std::string name, Handle<Typesystem> system,
@@ -305,15 +343,13 @@ private:
attrs(std::move(attrs))
{
}
-
-public:
// TODO
// static StructType createValidated(
// Manager &mgr, std::string name, Handle<Typesystem> system,
// Handle<StructType> parent,
// const std::vector<AttributeDescriptor> &attrs, Logger &logger);
- Variant create() override { return Variant{Variant::arrayType{}}; }
+ Variant create() const override { return Variant{Variant::arrayType{}}; }
};
class ArrayType : public Type {
@@ -324,7 +360,7 @@ protected:
/**
* TODO: DOC
*/
- bool doPrepare(Variant &var, Logger &log) override
+ bool doPrepare(Variant &var, Logger &log) const override
{
if (!var.isArray()) {
throw LoggableException("Expected array!");
@@ -353,7 +389,7 @@ public:
/**
* TODO: DOC
*/
- Variant create() override { return Variant{Variant::arrayType{}}; }
+ Variant create() const override { return Variant{Variant::arrayType{}}; }
Rooted<Type> getType() { return innerType; }
};
@@ -372,6 +408,8 @@ public:
* TODO: DOC
*/
void addType(Handle<Type> type) { types.push_back(type); }
+
+ const NodeVector<Type> &getTypes() const { return types; }
};
}
}