diff options
author | Benjamin Paassen <bpaassen@techfak.uni-bielefeld.de> | 2015-01-14 23:41:28 +0100 |
---|---|---|
committer | Benjamin Paassen <bpaassen@techfak.uni-bielefeld.de> | 2015-01-14 23:41:28 +0100 |
commit | 7d14fd98944996192047659afcdae67e6c8c3b03 (patch) | |
tree | 33f2fc862ac2e28faca8ed37ec056a233dd4258d /src/core | |
parent | fda708058907c6cfb803c883f1505c2cde7057a6 (diff) |
finished pathTo function with rather nasty test.
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/model/Domain.cpp | 117 | ||||
-rw-r--r-- | src/core/model/Domain.hpp | 34 |
2 files changed, 102 insertions, 49 deletions
diff --git a/src/core/model/Domain.cpp b/src/core/model/Domain.cpp index d664809..be9aa05 100644 --- a/src/core/model/Domain.cpp +++ b/src/core/model/Domain.cpp @@ -16,6 +16,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include <set> + #include <core/common/Rtti.hpp> #include <core/common/Exceptions.hpp> @@ -60,65 +62,88 @@ static bool pathEquals(const Descriptor &a, const Descriptor &b) } bool Descriptor::continuePath(Handle<StructuredClass> target, - std::vector<Rooted<Node>> &path) const + std::vector<Rooted<Node>> ¤tPath, + std::set<std::string> ignoredFields, + bool exploreSuperclass, + bool exploreSubclasses) const { + // TODO: REMOVE + std::string targetName = target->getName(); + std::string thisName = getName(); + std::string currentPathName; + for (auto &n : currentPath) { + currentPathName += "."; + currentPathName += n->getName(); + } + // a variable to determine if we already found a solution bool found = false; + // the currently optimal path. + std::vector<Rooted<Node>> optimum; // use recursive depth-first search from the top to reach the given child - if (fieldDescriptors.size() > 0) { - for (auto &fd : fieldDescriptors) { - for (auto &c : fd->getChildren()) { - if (pathEquals(*c, *target)) { - // if we have made the connection, stop the search. - path.push_back(fd); - return true; - } - // look for transparent intermediate nodes. - if (c->transparent) { - // copy the path. - std::vector<Rooted<Node>> cPath = path; - cPath.push_back(fd); - cPath.push_back(c); - // recursion. - if (c->continuePath(target, cPath) && - (!found || path.size() > cPath.size())) { - // look if this path is better than the current optimum. - path = std::move(cPath); - found = true; - } - } - } + for (auto &fd : fieldDescriptors) { + if (!(ignoredFields.insert(fd->getName()).second)) { + // if we want to ignore that field, we continue. + continue; } - } else { - // if this is a StructuredClass and if it did not formulate own - // fieldDescriptors (overriding the parent), we can also use the - // (inheritance-wise) parent - if (isa(RttiTypes::StructuredClass)) { - const StructuredClass *tis = - static_cast<const StructuredClass *>(this); - if (!tis->getIsA().isNull()) { + for (auto &c : fd->getChildren()) { + if (pathEquals(*c, *target)) { + // if we have made the connection, stop the search. + currentPath.push_back(fd); + return true; + } + // look for transparent intermediate nodes. + if (c->transparent) { // copy the path. - std::vector<Rooted<Node>> cPath = path; - if (tis->getIsA()->continuePath(target, cPath) && - (found || path.size() > cPath.size())) { + std::vector<Rooted<Node>> cPath = currentPath; + cPath.push_back(fd); + cPath.push_back(c); + // recursion. + if (c->continuePath(target, cPath) && + (!found || optimum.size() > cPath.size())) { // look if this path is better than the current optimum. - path = std::move(cPath); + optimum = std::move(cPath); found = true; } } } } - // either way we can try to find the targets parent (inheritance-wise) - // instead of the target itself. - if (!target->getIsA().isNull()) { - // copy the path. - std::vector<Rooted<Node>> cPath = path; - if (continuePath(target->getIsA(), cPath) && - (!found || path.size() > cPath.size())) { - // look if this path is better than the current optimum. - path = std::move(cPath); - found = true; + + 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->getIsA().isNull()) { + // copy the path. + std::vector<Rooted<Node>> cPath = currentPath; + if (tis->getIsA()->continuePath(target, cPath, ignoredFields, true, + false) && + (!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. + currentPath = std::move(optimum); + // return if we found something. return found; } diff --git a/src/core/model/Domain.hpp b/src/core/model/Domain.hpp index 1f65242..4b26917 100644 --- a/src/core/model/Domain.hpp +++ b/src/core/model/Domain.hpp @@ -394,7 +394,10 @@ private: NodeVector<FieldDescriptor> fieldDescriptors; bool continuePath(Handle<StructuredClass> target, - std::vector<Rooted<Node>> &path) const; + std::vector<Rooted<Node>> &path, + std::set<std::string> ignoredFields = {}, + bool exploreSuperclass = true, + bool exploreSubclasses = true) const; protected: void continueResolve(ResolutionState &state) override; @@ -558,6 +561,7 @@ class StructuredClass : public Descriptor { private: const Cardinality cardinality; Owned<StructuredClass> isa; + NodeVector<StructuredClass> subclasses; public: const bool transparent; @@ -583,7 +587,9 @@ public: * @param isa references a parent StructuredClass. Please * look for more information on inheritance in * the class documentation above. The default is - * a null reference, meaning no parent class. + * a null reference, meaning no super class. + * The constructor automatically registers this + * class as a subclass at the super class. * @param transparent specifies whether this StructuredClass is * transparent. For more information on * transparency please refer to the class @@ -598,9 +604,13 @@ public: : Descriptor(mgr, std::move(name), domain, attributesDescriptor), cardinality(cardinality), isa(acquire(isa)), + subclasses(this), transparent(transparent), root(root) { + if (!isa.isNull()) { + isa->subclasses.push_back(this); + } } /** @@ -618,6 +628,24 @@ public: * hierarchy (!). */ Rooted<StructuredClass> getIsA() const { return isa; } + + /** + * Returns the StructuredClasses that are subclasses of this class. This + * is the inverted version of isa, meaning: each class c that has a isa + * relationship to this class is part of the returned vector. + * + * Note that the order of subclasses is not strictly defined. + * + * You are not allowed to add subclasses directly to the vector. When you + * construct a new StructuredClass with a non-empty isa-handle it will + * automatically register as subclass at the super class. + * + * @return the StructuredClasses that are subclasses of this class. + */ + const NodeVector<StructuredClass> &getSubclasses() const + { + return subclasses; + } }; /** @@ -637,7 +665,7 @@ public: * be used for later references to this * AnnotationClass. * @param domain is the Domain this AnnotationClass belongs - *to. + * to. * @param attributesDescriptor is a StructType that specifies the attribute * keys as well as value domains for this * Descriptor. |