/* Ousía Copyright (C) 2014, 2015 Benjamin Paaßen, Andreas Stöckel This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include "Domain.hpp" namespace ousia { namespace model { /* Class FieldDescriptor */ /* Class Descriptor */ void Descriptor::continueResolve(ResolutionState &state) { if (attributesDescriptor != nullptr) { const NodeVector &attributes = attributesDescriptor->getAttributes(); continueResolveComposita(attributes, attributes.getIndex(), state); } continueResolveComposita(fieldDescriptors, fieldDescriptors.getIndex(), 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) { if (!continueResolveComposita(structuredClasses, structuredClasses.getIndex(), state) | continueResolveComposita(annotationClasses, annotationClasses.getIndex(), state)) { continueResolveReferences(typesystems, state); } } } /* Type registrations */ namespace RttiTypes { const Rtti FieldDescriptor = RttiBuilder("FieldDescriptor").parent(&Node); const Rtti Descriptor = RttiBuilder("Descriptor").parent(&Node); const Rtti StructuredClass = RttiBuilder("StructuredClass").parent(&Descriptor).composedOf( &FieldDescriptor); const Rtti AnnotationClass = RttiBuilder("AnnotationClass").parent(&Descriptor); const Rtti Domain = RttiBuilder("Domain").parent(&Node).composedOf( {&StructuredClass, &AnnotationClass}); } }