From c6b502d45d2bf916f747411df37df186c4ed4981 Mon Sep 17 00:00:00 2001 From: Benjamin Paassen Date: Tue, 13 Jan 2015 23:32:48 +0100 Subject: First version of 'pathTo' function enabling users to request a Structure Path from some descriptor to another. --- src/core/model/Domain.cpp | 74 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) (limited to 'src/core/model/Domain.cpp') diff --git a/src/core/model/Domain.cpp b/src/core/model/Domain.cpp index 17b1d2d..1fb057e 100644 --- a/src/core/model/Domain.cpp +++ b/src/core/model/Domain.cpp @@ -17,6 +17,7 @@ */ #include +#include #include "Domain.hpp" @@ -38,6 +39,79 @@ void Descriptor::continueResolve(ResolutionState &state) state); } +std::vector> Descriptor::pathTo( + Handle target) const +{ + std::vector> path; + continuePath(target, path); + return path; +} + +static bool pathEquals(const Descriptor& a, const Descriptor& b) +{ + // We assume that two Descriptors are equal if their names and domain names + // are equal. + if (a.getName() != b.getName()) { + return false; + } + Handle aDom = a.getParent().cast(); + Handle bDom = b.getParent().cast(); + return aDom->getName() == bDom->getName(); +} + +//TODO: isa-handling. +bool Descriptor::continuePath(Handle target, + std::vector> &path) const +{ + // look if our current node is reachable using the parent references + for (auto &pfd : target->getParents()) { + Handle p = pfd->getParent().cast(); + if (pathEquals(*this, *p)) { + // if we have made the connection, stop the search. + path.push_back(pfd); + return true; + } + // look for transparent intermediate nodes. + if (!p->isa(RttiTypes::StructuredClass)) { + continue; + } + Handle pc = p.cast(); + if (pc->transparent) { + // recursion + std::vector> cPath = path; + if (continuePath(pc, cPath)) { + path = std::move(cPath); + path.push_back(pc); + path.push_back(pfd); + return true; + } + } + } + // use recursive depth-first search from the top to reach the given child + 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> cPath = path; + cPath.push_back(fd); + cPath.push_back(c); + // recursion. + if (c->continuePath(target, cPath)) { + path = std::move(cPath); + return true; + } + } + } + } + return false; +} + /* Class Domain */ void Domain::continueResolve(ResolutionState &state) -- cgit v1.2.3