From 76c33b56df9ae13ba7e8c1f3d7ec6bc2118f3e26 Mon Sep 17 00:00:00 2001 From: Benjamin Paassen Date: Sun, 15 Feb 2015 20:16:53 +0100 Subject: fixed a bug in instance counting in DocumentEntity::doValidate and made the validation process faster and more compact using advanced programming techniques. --- src/core/model/Document.cpp | 62 +++++++++++++++++++++------------------------ 1 file changed, 29 insertions(+), 33 deletions(-) (limited to 'src/core/model/Document.cpp') diff --git a/src/core/model/Document.cpp b/src/core/model/Document.cpp index a2ba5cf..4e101fc 100644 --- a/src/core/model/Document.cpp +++ b/src/core/model/Document.cpp @@ -135,6 +135,15 @@ bool DocumentEntity::doValidate(Logger &logger) const continue; } + std::unordered_set childClasses; + { + NodeVector tmp = + fieldDescs[f]->getChildrenWithSubclasses(); + for (auto s : tmp) { + childClasses.insert(s.get()); + } + } + // 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. @@ -145,7 +154,7 @@ bool DocumentEntity::doValidate(Logger &logger) const * if it is not optional we have to check if zero is a valid * cardinality. */ - for (auto childClass : fieldDescs[f]->getChildren()) { + for (auto childClass : childClasses) { const size_t min = childClass->getCardinality().asCardinality().min(); if (min > 0) { @@ -163,15 +172,10 @@ bool DocumentEntity::doValidate(Logger &logger) const continue; } - // create a set of allowed classes identified by their unique id. - std::set childClasses; - for (auto &childClass : fieldDescs[f]->getChildren()) { - childClasses.insert(childClass->getUid()); - } // store the actual numbers of children for each child class in a map - std::map nums; + std::unordered_map nums; - // iterate over every actual child of this DocumentEntity + // iterate over every actual child of this field for (auto child : fields[f]) { // check if the parent reference is correct. if (child->getParent() != subInst) { @@ -195,25 +199,11 @@ bool DocumentEntity::doValidate(Logger &logger) const } // otherwise this is a StructuredEntity Handle c = child.cast(); + StructuredClass *classPtr = + c->getDescriptor().cast().get(); - ManagedUid id = c->getDescriptor()->getUid(); // check if its class is allowed. - bool allowed = childClasses.find(id) != childClasses.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 childClass : fieldDescs[f]->getChildren()) { - if (c->getDescriptor() - .cast() - ->isSubclassOf(childClass)) { - allowed = true; - id = childClass->getUid(); - } - } - } - if (!allowed) { + if (childClasses.find(classPtr) == childClasses.end()) { logger.error( std::string("An instance of \"") + c->getDescriptor()->getName() + @@ -224,18 +214,24 @@ bool DocumentEntity::doValidate(Logger &logger) const valid = false; continue; } - // note the number of occurences. - const auto &n = nums.find(id); - if (n != nums.end()) { - n->second++; - } else { - nums.emplace(id, 1); + // note the number of occurences for this class and all + // superclasses, because a subclass instance should count for + // superclasses as well. + while (classPtr != nullptr && + childClasses.find(classPtr) != childClasses.end()) { + const auto &n = nums.find(classPtr); + if (n != nums.end()) { + n->second++; + } else { + nums.emplace(classPtr, 1); + } + classPtr = classPtr->getSuperclass().get(); } } // now check if the cardinalities are right. - for (auto childClass : fieldDescs[f]->getChildren()) { - const auto &n = nums.find(childClass->getUid()); + for (auto childClass : childClasses) { + const auto &n = nums.find(childClass); unsigned int num = 0; if (n != nums.end()) { num = n->second; -- cgit v1.2.3