summaryrefslogtreecommitdiff
path: root/src/core/model/Document.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/model/Document.cpp')
-rw-r--r--src/core/model/Document.cpp113
1 files changed, 110 insertions, 3 deletions
diff --git a/src/core/model/Document.cpp b/src/core/model/Document.cpp
index 299b427..2f12acb 100644
--- a/src/core/model/Document.cpp
+++ b/src/core/model/Document.cpp
@@ -18,6 +18,9 @@
#include "Document.hpp"
+#include <map>
+#include <set>
+
#include <core/common/Exceptions.hpp>
#include <core/common/Rtti.hpp>
@@ -89,17 +92,121 @@ int DocumentEntity::getFieldDescriptorIndex(
}
}
+bool DocumentEntity::validate(Logger &logger) const
+{
+ // TODO: check the validated form of Attributes
+ // iterate over every field
+ for (unsigned int f = 0; f < fields.size(); f++) {
+ // we can do a faster check if this field is empty.
+ if (fields[f].size() == 0) {
+ // if this field is optional, an empty field is valid anyways.
+ if (descriptor->getFieldDescriptors()[f]->optional) {
+ continue;
+ }
+ /*
+ * if it is not optional we have to chack if zero is a valid
+ * cardinality.
+ */
+ for (auto &ac :
+ descriptor->getFieldDescriptors()[f]->getChildren()) {
+ const size_t min = ac->getCardinality().min();
+ if (min > 0) {
+ logger.error(
+ std::string("Field ") +
+ descriptor->getFieldDescriptors()[f]->getName() +
+ " was empty but needs at least " + std::to_string(min) +
+ " elements of class " + ac->getName() +
+ " according to the definition of " +
+ descriptor->getName());
+ return false;
+ }
+ }
+ continue;
+ }
+
+ // create a set of allowed classes identified by their unique id.
+ std::set<ManagedUid> accs;
+ for (auto &ac : descriptor->getFieldDescriptors()[f]->getChildren()) {
+ accs.insert(ac->getUid());
+ }
+ // store the actual numbers of children for each child class in a map
+ std::map<ManagedUid, unsigned int> nums;
+
+ // iterate over every actual child of this DocumentEntity
+ for (auto &rc : fields[f]) {
+ if (!rc->isa(RttiTypes::StructuredEntity)) {
+ continue;
+ }
+ Handle<StructuredEntity> c = rc.cast<StructuredEntity>();
+
+ ManagedUid id = c->getDescriptor()->getUid();
+ // check if its class is allowed.
+ bool allowed = accs.find(id) != accs.end();
+ /*
+ * if it is not allowed directly, we have to check if the class is a
+ * child of a permitted class.
+ */
+ if (!allowed) {
+ for (auto &ac :
+ descriptor->getFieldDescriptors()[f]->getChildren()) {
+ if (c->getDescriptor()
+ .cast<StructuredClass>()
+ ->isSubclassOf(ac)) {
+ allowed = true;
+ id = ac->getUid();
+ }
+ }
+ }
+ if (!allowed) {
+ logger.error(std::string("An instance of ") +
+ c->getDescriptor()->getName() +
+ " is not allowed as child of an instance of " +
+ descriptor->getName() + " in field " +
+ descriptor->getFieldDescriptors()[f]->getName());
+ return false;
+ }
+ // note the number of occurences.
+ const auto &n = nums.find(id);
+ if (n != nums.end()) {
+ n->second++;
+ } else {
+ nums.emplace(id, 1);
+ }
+ }
+
+ // now check if the cardinalities are right.
+ for (auto &ac : descriptor->getFieldDescriptors()[f]->getChildren()) {
+ const auto &n = nums.find(ac->getUid());
+ unsigned int num = 0;
+ if (n != nums.end()) {
+ num = n->second;
+ }
+ if (!ac->getCardinality().contains(num)) {
+ logger.error(
+ std::string("Field ") +
+ descriptor->getFieldDescriptors()[f]->getName() + " had " +
+ std::to_string(num) + " elements of class " +
+ ac->getName() +
+ ", which is invalid according to the definition of " +
+ descriptor->getName());
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
/* Class StructureNode */
StructureNode::StructureNode(Manager &mgr, std::string name,
Handle<Node> parent, const std::string &fieldName)
: Node(mgr, std::move(name), parent)
{
- if(parent->isa(RttiTypes::StructuredEntity)){
+ if (parent->isa(RttiTypes::StructuredEntity)) {
parent.cast<StructuredEntity>()->addStructureNode(this, fieldName);
- } else if(parent->isa(RttiTypes::AnnotationEntity)){
+ } else if (parent->isa(RttiTypes::AnnotationEntity)) {
parent.cast<AnnotationEntity>()->addStructureNode(this, fieldName);
- } else{
+ } else {
throw OusiaException("The proposed parent was no DocumentEntity!");
}
}