From 40428e90ae8b1a5d1c769b6eb2fec9a53b7173bc Mon Sep 17 00:00:00 2001 From: Benjamin Paassen Date: Sun, 18 Jan 2015 11:45:16 +0100 Subject: changed the cycle error message. --- src/core/model/Node.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/core/model') diff --git a/src/core/model/Node.cpp b/src/core/model/Node.cpp index da83598..a935715 100644 --- a/src/core/model/Node.cpp +++ b/src/core/model/Node.cpp @@ -404,7 +404,7 @@ bool Node::validate(Logger &logger) const case ValidationState::VALIDATING: // We've run into recursion -- a circular structure cannot be // properly validated, so return false - logger.error("The given document is cyclic."); + logger.error("This validation run lead to a cycle. As a fallback it is set to invalid!"); return false; } return false; -- cgit v1.2.3 From 4e590891e9723c42858165a96c96a9f19d4e4c94 Mon Sep 17 00:00:00 2001 From: Benjamin Paassen Date: Sun, 18 Jan 2015 12:58:55 +0100 Subject: added Document validation function and finished implementation of AnnotationEntity validation function. Tests still have to be made, though. --- src/core/model/Document.cpp | 53 ++++++++++++++++++++++++++++++++++++++++----- src/core/model/Document.hpp | 16 +++++++++++++- 2 files changed, 63 insertions(+), 6 deletions(-) (limited to 'src/core/model') diff --git a/src/core/model/Document.cpp b/src/core/model/Document.cpp index 0de750f..0b0a42a 100644 --- a/src/core/model/Document.cpp +++ b/src/core/model/Document.cpp @@ -92,7 +92,7 @@ int DocumentEntity::getFieldDescriptorIndex( } } -bool DocumentEntity::validate(Logger &logger) const +bool DocumentEntity::doValidate(Logger &logger) const { // TODO: check the validated form of Attributes // iterate over every field @@ -246,7 +246,7 @@ bool StructuredEntity::doValidate(Logger &logger) const return false; } // check the validity as a DocumentEntity. - return DocumentEntity::validate(logger); + return DocumentEntity::doValidate(logger); } /* Class AnnotationEntity */ @@ -281,12 +281,17 @@ bool AnnotationEntity::doValidate(Logger &logger) const logger.error("This annotation was not registered at the document."); return false; } - + // check if the Anchors are part of the right document. + if (!doc->hasChild(start)) { + return false; + } + if (!doc->hasChild(end)) { + return false; + } // check the validity as a DocumentEntity. - if (!DocumentEntity::validate(logger)) { + if (!DocumentEntity::doValidate(logger)) { return false; } - // TODO: then check if the anchors are in the correct document. return true; } @@ -300,6 +305,44 @@ void Document::continueResolve(ResolutionState &state) } continueResolveReferences(domains, state); } + +bool Document::doValidate(Logger &logger) const +{ + if (root != nullptr) { + // check if the root is allowed to be a root. + if (!root->getDescriptor().cast()->root) { + logger.error(std::string("A node of type ") + + root->getDescriptor()->getName() + + " is not allowed to be the Document root!"); + return false; + } + // then call validate on the root + if (!root->validate(logger)) { + return false; + } + } + // call validate on the AnnotationEntities + for (auto &a : annotations) { + if (!a->validate(logger)) { + return false; + } + } + return true; +} + +bool Document::hasChild(Handle s) const +{ + Rooted parent = s->getParent(); + if (parent->isa(RttiTypes::StructureNode)) { + return hasChild(parent.cast()); + } else if (parent->isa(RttiTypes::AnnotationEntity)) { + Handle a = parent.cast(); + return this == a->getParent(); + } else if (parent->isa(RttiTypes::Document)) { + return this == parent; + } + return false; +} } /* Type registrations */ diff --git a/src/core/model/Document.hpp b/src/core/model/Document.hpp index 5af3ce2..18ec3d5 100644 --- a/src/core/model/Document.hpp +++ b/src/core/model/Document.hpp @@ -161,7 +161,7 @@ protected: fields[getFieldDescriptorIndex(fieldName, true)].push_back(s); } - bool validate(Logger &logger) const; + bool doValidate(Logger &logger) const; public: /** @@ -569,6 +569,9 @@ private: void continueResolve(ResolutionState &state) override; +protected: + bool doValidate(Logger &logger) const override; + public: Document(Manager &mgr, std::string name) // TODO: Can a document have a parent? @@ -622,6 +625,17 @@ 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 + * Structure Tree leading from the given StructureNode to this Document. + * + * @param s is some StructureNode. + * @return true if and only if the given StructureNode is part of this + * document. + */ + bool hasChild(Handle s) const; }; } -- cgit v1.2.3 From 3e63d6539b9738018a4aca68d07a119e4402e9aa Mon Sep 17 00:00:00 2001 From: Benjamin Paassen Date: Sun, 18 Jan 2015 13:36:10 +0100 Subject: added the getEffectiveFieldDescriptors for StructuredClasses which returns the list of FieldDescriptors including all non-overridden fields of superclasses. This also made the continuePath function easier. --- src/core/model/Domain.cpp | 78 ++++++++++++++++++++++++++--------------------- src/core/model/Domain.hpp | 35 ++++++++++++++------- 2 files changed, 68 insertions(+), 45 deletions(-) (limited to 'src/core/model') diff --git a/src/core/model/Domain.cpp b/src/core/model/Domain.cpp index 2ac2d8d..17f3e02 100644 --- a/src/core/model/Domain.cpp +++ b/src/core/model/Domain.cpp @@ -36,7 +36,7 @@ static void checkUniqueName(Handle parent, NodeVector vec, childNames.insert(c->getName()); } if (childNames.find(child->getName()) != childNames.end()) { - //TODO: Do we really want to have an exception here? + // TODO: Do we really want to have an exception here? throw OusiaException(std::string("The ") + parentClassName + " " + parent->getName() + " already has a " + childClassName + " with name " + child->getName()); @@ -97,10 +97,7 @@ std::vector> Descriptor::pathTo( } bool Descriptor::continuePath(Handle target, - std::vector> ¤tPath, - std::set ignoredFields, - bool exploreSuperclass, - bool exploreSubclasses) const + std::vector> ¤tPath) const { // check if we are at the target already if (this == target) { @@ -111,11 +108,16 @@ bool Descriptor::continuePath(Handle target, // the currently optimal path. std::vector> optimum; // use recursive depth-first search from the top to reach the given child - for (auto &fd : fieldDescriptors) { - if (!(ignoredFields.insert(fd->getName()).second)) { - // if we want to ignore that field, we continue. - continue; - } + // get the list of effective FieldDescriptors. + NodeVector fields; + if (isa(RttiTypes::StructuredClass)) { + const StructuredClass *tis = static_cast(this); + fields = tis->getEffectiveFieldDescriptors(); + } else { + fields = getFieldDescriptors(); + } + + for (auto &fd : fields) { for (auto &c : fd->getChildren()) { // check if a child is the target node. if (c == target) { @@ -142,35 +144,17 @@ bool Descriptor::continuePath(Handle target, if (isa(RttiTypes::StructuredClass)) { const StructuredClass *tis = static_cast(this); - /* - * if this is a StructuredClass, we can also use the super class - * (at least for fields that are not overridden) - */ - if (exploreSuperclass && tis->getSuperclass() != nullptr) { + // if this is a StructuredClass we also can call the subclasses. + for (auto &c : tis->getSubclasses()) { // copy the path. std::vector> cPath = currentPath; - if (tis->getSuperclass()->continuePath(target, cPath, ignoredFields, - true, false) && + if (c->continuePath(target, cPath) && (!found || optimum.size() > cPath.size())) { // look if this path is better than the current optimum. optimum = std::move(cPath); found = true; } } - - // we also can call the subclasses. - if (exploreSubclasses) { - for (auto &c : tis->getSubclasses()) { - // copy the path. - std::vector> cPath = currentPath; - if (c->continuePath(target, cPath, {}, false) && - (!found || optimum.size() > cPath.size())) { - // look if this path is better than the current optimum. - optimum = std::move(cPath); - found = true; - } - } - } } // put the optimum in the given path reference. @@ -219,16 +203,42 @@ StructuredClass::StructuredClass(Manager &mgr, std::string name, } } -bool StructuredClass::isSubclassOf(Handle c) const{ - if(c == nullptr || superclass == nullptr){ +bool StructuredClass::isSubclassOf(Handle c) const +{ + if (c == nullptr || superclass == nullptr) { return false; } - if(c == superclass){ + if (c == superclass) { return true; } return superclass->isSubclassOf(c); } +const void StructuredClass::gatherFieldDescriptors( + NodeVector ¤t, + std::set &overriddenFields) const +{ + // append all FieldDescriptors that are not overridden. + for (auto &f : Descriptor::getFieldDescriptors()) { + if (overriddenFields.insert(f->getName()).second) { + current.push_back(f); + } + } + if (superclass != nullptr) { + superclass->gatherFieldDescriptors(current, overriddenFields); + } +} + +NodeVector StructuredClass::getEffectiveFieldDescriptors() + const +{ + // in this case we return a NodeVector of Rooted entries without owner. + NodeVector vec; + std::set overriddenFields; + gatherFieldDescriptors(vec, overriddenFields); + return std::move(vec); +} + /* Class AnnotationClass */ AnnotationClass::AnnotationClass( diff --git a/src/core/model/Domain.hpp b/src/core/model/Domain.hpp index ac02ec7..5cc7874 100644 --- a/src/core/model/Domain.hpp +++ b/src/core/model/Domain.hpp @@ -380,22 +380,18 @@ public: * */ class Descriptor : public Node { - -friend FieldDescriptor; + friend FieldDescriptor; private: Owned attributesDescriptor; NodeVector fieldDescriptors; bool continuePath(Handle target, - std::vector> &path, - std::set ignoredFields = {}, - bool exploreSuperclass = true, - bool exploreSubclasses = true) const; + std::vector> &path) const; protected: void continueResolve(ResolutionState &state) override; - + /** * Adds a FieldDescriptor and checks for name uniqueness. */ @@ -553,6 +549,13 @@ private: Owned superclass; NodeVector subclasses; + /** + * Helper method for getFieldDescriptors. + */ + const void gatherFieldDescriptors( + NodeVector ¤t, + std::set &overriddenFields) const; + public: const bool transparent; // TODO: Is it possible to have root=true and cardinality other than 1? @@ -606,7 +609,7 @@ public: * @return the superclass of this StructuredClass. */ Rooted getSuperclass() const { return superclass; } - + /** * Returns true if this class is a subclass of the given class. It does not * return true if the other class is equal to the given class. @@ -635,6 +638,17 @@ public: { return subclasses; } + + /** + * Returns a const reference to the NodeVector of all FieldDescriptors of + * this StructuredClass. This does more than the getter for FieldDescriptor, + * because in this method we gather the FieldDescriptors of all superclasses + * as well that have not been overridden in child classes. + * + * @return a const reference to the NodeVector of all FieldDescriptors of + * this StructuredClass. + */ + NodeVector getEffectiveFieldDescriptors() const; }; /** @@ -670,9 +684,8 @@ public: * to certain Structures? */ class Domain : public Node { - -friend StructuredClass; -friend AnnotationClass; + friend StructuredClass; + friend AnnotationClass; private: NodeVector structuredClasses; -- cgit v1.2.3