diff options
Diffstat (limited to 'src/core/model/Document.cpp')
-rw-r--r-- | src/core/model/Document.cpp | 113 |
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!"); } } |