summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Stöckel <astoecke@techfak.uni-bielefeld.de>2015-01-18 13:48:45 +0100
committerAndreas Stöckel <astoecke@techfak.uni-bielefeld.de>2015-01-18 13:48:45 +0100
commit372c67e0844654362fc7d440b0b4a31500a6d02a (patch)
treed677aa19bdc77486be02171de77e5675ce5f0f80
parentdb51a874964b038c69f1336a8a659ae40471e26b (diff)
parent3e63d6539b9738018a4aca68d07a119e4402e9aa (diff)
Merge branch 'master' of somweyr.de:ousia
Conflicts: application/src/core/model/Domain.hpp
-rw-r--r--src/core/model/Document.cpp53
-rw-r--r--src/core/model/Document.hpp17
-rw-r--r--src/core/model/Domain.cpp78
-rw-r--r--src/core/model/Domain.hpp35
-rw-r--r--src/core/model/Node.cpp2
5 files changed, 133 insertions, 52 deletions
diff --git a/src/core/model/Document.cpp b/src/core/model/Document.cpp
index ee15e31..5f0ad4c 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::doResolve(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<StructuredClass>()->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<StructureNode> s) const
+{
+ Rooted<Managed> parent = s->getParent();
+ if (parent->isa(RttiTypes::StructureNode)) {
+ return hasChild(parent.cast<StructureNode>());
+ } else if (parent->isa(RttiTypes::AnnotationEntity)) {
+ Handle<AnnotationEntity> a = parent.cast<AnnotationEntity>();
+ 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 cb7f394..9410d17 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:
/**
@@ -512,6 +512,7 @@ class AnnotationEntity : public Node, public DocumentEntity {
private:
Owned<Anchor> start;
Owned<Anchor> end;
+
protected:
bool doValidate(Logger &logger) const override;
@@ -569,6 +570,9 @@ private:
void doResolve(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 +626,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<StructureNode> s) const;
};
}
diff --git a/src/core/model/Domain.cpp b/src/core/model/Domain.cpp
index bae0f4f..9a0ed0d 100644
--- a/src/core/model/Domain.cpp
+++ b/src/core/model/Domain.cpp
@@ -36,7 +36,7 @@ static void checkUniqueName(Handle<Node> parent, NodeVector<T> 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<Rooted<Node>> Descriptor::pathTo(
}
bool Descriptor::continuePath(Handle<StructuredClass> target,
- std::vector<Rooted<Node>> &currentPath,
- std::set<std::string> ignoredFields,
- bool exploreSuperclass,
- bool exploreSubclasses) const
+ std::vector<Rooted<Node>> &currentPath) const
{
// check if we are at the target already
if (this == target) {
@@ -111,11 +108,16 @@ bool Descriptor::continuePath(Handle<StructuredClass> target,
// the currently optimal path.
std::vector<Rooted<Node>> 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<FieldDescriptor> fields;
+ if (isa(RttiTypes::StructuredClass)) {
+ const StructuredClass *tis = static_cast<const StructuredClass *>(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<StructuredClass> target,
if (isa(RttiTypes::StructuredClass)) {
const StructuredClass *tis = static_cast<const StructuredClass *>(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<Rooted<Node>> 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<Rooted<Node>> 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<StructuredClass> c) const{
- if(c == nullptr || superclass == nullptr){
+bool StructuredClass::isSubclassOf(Handle<StructuredClass> 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<FieldDescriptor> &current,
+ std::set<std::string> &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<FieldDescriptor> StructuredClass::getEffectiveFieldDescriptors()
+ const
+{
+ // in this case we return a NodeVector of Rooted entries without owner.
+ NodeVector<FieldDescriptor> vec;
+ std::set<std::string> 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 a8d4a9e..d1ba44f 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<StructType> attributesDescriptor;
NodeVector<FieldDescriptor> fieldDescriptors;
bool continuePath(Handle<StructuredClass> target,
- std::vector<Rooted<Node>> &path,
- std::set<std::string> ignoredFields = {},
- bool exploreSuperclass = true,
- bool exploreSubclasses = true) const;
+ std::vector<Rooted<Node>> &path) const;
protected:
void doResolve(ResolutionState &state) override;
-
+
/**
* Adds a FieldDescriptor and checks for name uniqueness.
*/
@@ -553,6 +549,13 @@ private:
Owned<StructuredClass> superclass;
NodeVector<StructuredClass> subclasses;
+ /**
+ * Helper method for getFieldDescriptors.
+ */
+ const void gatherFieldDescriptors(
+ NodeVector<FieldDescriptor> &current,
+ std::set<std::string> &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<StructuredClass> 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<FieldDescriptor> getEffectiveFieldDescriptors() const;
};
/**
@@ -670,9 +684,8 @@ public:
* to certain Structures?
*/
class Domain : public Node {
-
-friend StructuredClass;
-friend AnnotationClass;
+ friend StructuredClass;
+ friend AnnotationClass;
private:
NodeVector<StructuredClass> structuredClasses;
diff --git a/src/core/model/Node.cpp b/src/core/model/Node.cpp
index 1c627fc..bd023e1 100644
--- a/src/core/model/Node.cpp
+++ b/src/core/model/Node.cpp
@@ -430,7 +430,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;