summaryrefslogtreecommitdiff
path: root/src/core/model/Domain.cpp
diff options
context:
space:
mode:
authorBenjamin Paassen <bpaassen@techfak.uni-bielefeld.de>2015-03-01 20:47:25 +0100
committerBenjamin Paassen <bpaassen@techfak.uni-bielefeld.de>2015-03-01 20:47:25 +0100
commita7019614896fdd3e29b9a28f6a8cfd2c1b365983 (patch)
tree8a9f102649e88ebf24de0a07cf5f348804a6212d /src/core/model/Domain.cpp
parent0d4ce5c555a1ba3a87cb9a1e350854eda7a243e1 (diff)
Renamed domain to ontology.
Diffstat (limited to 'src/core/model/Domain.cpp')
-rw-r--r--src/core/model/Domain.cpp981
1 files changed, 0 insertions, 981 deletions
diff --git a/src/core/model/Domain.cpp b/src/core/model/Domain.cpp
deleted file mode 100644
index 8255401..0000000
--- a/src/core/model/Domain.cpp
+++ /dev/null
@@ -1,981 +0,0 @@
-/*
- 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 <http://www.gnu.org/licenses/>.
-*/
-
-#include <memory>
-#include <queue>
-#include <set>
-
-#include <core/common/RttiBuilder.hpp>
-#include <core/common/Exceptions.hpp>
-
-#include "Domain.hpp"
-
-namespace ousia {
-
-/* Helper Functions */
-
-struct PathState {
- std::shared_ptr<PathState> pred;
- Node *node;
- size_t length;
-
- PathState(std::shared_ptr<PathState> pred, Node *node)
- : pred(pred), node(node)
- {
- if (pred == nullptr) {
- length = 1;
- } else {
- length = pred->length + 1;
- }
- }
-};
-
-static void constructPath(std::shared_ptr<PathState> state,
- NodeVector<Node> &vec)
-{
- if (state->pred != nullptr) {
- constructPath(state->pred, vec);
- }
- vec.push_back(state->node);
-}
-
-static NodeVector<Node> pathTo(const Node *start, Logger &logger,
- Handle<Node> target, bool &success)
-{
- success = false;
- // shortest path.
- NodeVector<Node> shortest;
- // state queue for breadth-first search.
- std::queue<std::shared_ptr<PathState>> states;
- if (start->isa(&RttiTypes::Descriptor)) {
- const Descriptor *desc = static_cast<const Descriptor *>(start);
- // initially put every field descriptor on the queue.
- NodeVector<FieldDescriptor> fields = desc->getFieldDescriptors();
-
- for (auto fd : fields) {
- if (fd == target) {
- // if we have found the target directly, return without search.
- success = true;
- return shortest;
- }
- if (fd->getFieldType() == FieldDescriptor::FieldType::TREE) {
- states.push(std::make_shared<PathState>(nullptr, fd.get()));
- }
- }
- } else {
- const FieldDescriptor *field =
- static_cast<const FieldDescriptor *>(start);
- // initially put every child and its subclasses to the queue.
- for (auto c : field->getChildrenWithSubclasses()) {
- // if we have found the target directly, return without search.
- if (c == target) {
- success = true;
- return shortest;
- }
- if (c->isTransparent()) {
- states.push(std::make_shared<PathState>(nullptr, c.get()));
- }
- }
- }
- // set of visited nodes.
- std::unordered_set<const Node *> visited;
- while (!states.empty()) {
- std::shared_ptr<PathState> current = states.front();
- states.pop();
- // do not proceed if this node was already visited.
- if (!visited.insert(current->node).second) {
- continue;
- }
- // also do not proceed if we can't get better than the current shortest
- // path anymore.
- if (!shortest.empty() && current->length > shortest.size()) {
- continue;
- }
-
- bool fin = false;
- if (current->node->isa(&RttiTypes::StructuredClass)) {
- const StructuredClass *strct =
- static_cast<const StructuredClass *>(current->node);
-
- // look through all fields.
- NodeVector<FieldDescriptor> fields = strct->getFieldDescriptors();
- for (auto fd : fields) {
- // if we found our target, break off the search in this branch.
- if (fd == target) {
- fin = true;
- continue;
- }
- // only continue in the TREE field.
- if (fd->getFieldType() == FieldDescriptor::FieldType::TREE) {
- states.push(std::make_shared<PathState>(current, fd.get()));
- }
- }
- } else {
- // otherwise this is a FieldDescriptor.
- const FieldDescriptor *field =
- static_cast<const FieldDescriptor *>(current->node);
- // and we proceed by visiting all permitted children.
- for (auto c : field->getChildrenWithSubclasses()) {
- // if we found our target, break off the search in this branch.
- if (c == target) {
- fin = true;
- continue;
- }
- // We only allow to continue our path via transparent children.
- if (c->isTransparent()) {
- states.push(std::make_shared<PathState>(current, c.get()));
- }
- }
- }
- // check if we are finished.
- if (fin) {
- success = true;
- // if so we look if we found a shorter path than the current minimum
- if (shortest.empty() || current->length < shortest.size()) {
- NodeVector<Node> newPath;
- constructPath(current, newPath);
- shortest = newPath;
- } else if (current->length == shortest.size()) {
- // if the length is the same the result is ambigous and we log
- // an error.
- NodeVector<Node> newPath;
- constructPath(current, newPath);
- logger.error(
- std::string("Can not unambigously create a path from \"") +
- start->getName() + "\" to \"" + target->getName() + "\".");
- logger.note("Dismissed the path:", SourceLocation{},
- MessageMode::NO_CONTEXT);
- for (auto n : newPath) {
- logger.note(n->getName());
- }
- }
- }
- }
- return shortest;
-}
-
-template <typename F>
-static NodeVector<Node> collect(const Node *start, F match)
-{
- // result
- NodeVector<Node> res;
- // queue for breadth-first search of graph.
- std::queue<Rooted<Node>> q;
- // put the initial node on the stack.
- q.push(const_cast<Node *>(start));
- // set of visited nodes.
- std::unordered_set<const Node *> visited;
- while (!q.empty()) {
- Rooted<Node> n = q.front();
- q.pop();
- // do not proceed if this node was already visited.
- if (!visited.insert(n.get()).second) {
- continue;
- }
-
- if (n->isa(&RttiTypes::StructuredClass)) {
- Rooted<StructuredClass> strct = n.cast<StructuredClass>();
-
- // look through all fields.
- NodeVector<FieldDescriptor> fields = strct->getFieldDescriptors();
- for (auto fd : fields) {
- // note matches.
- if (match(fd)) {
- res.push_back(fd);
- }
- // only continue in the TREE field.
- if (fd->getFieldType() == FieldDescriptor::FieldType::TREE) {
- q.push(fd);
- }
- }
- } else {
- // otherwise this is a FieldDescriptor.
- Rooted<FieldDescriptor> field = n.cast<FieldDescriptor>();
- // and we proceed by visiting all permitted children.
- for (auto c : field->getChildrenWithSubclasses()) {
- // note matches.
- if (match(c)) {
- res.push_back(c);
- }
- // We only continue our search via transparent children.
- if (c->isTransparent()) {
- q.push(c);
- }
- }
- }
- }
- return res;
-}
-
-/* Class FieldDescriptor */
-
-FieldDescriptor::FieldDescriptor(Manager &mgr, Handle<Type> primitiveType,
- Handle<Descriptor> parent, FieldType fieldType,
- std::string name, bool optional)
- : Node(mgr, std::move(name), parent),
- children(this),
- fieldType(fieldType),
- primitiveType(acquire(primitiveType)),
- optional(optional),
- primitive(true)
-{
-}
-
-FieldDescriptor::FieldDescriptor(Manager &mgr, Handle<Descriptor> parent,
- FieldType fieldType, std::string name,
- bool optional)
- : Node(mgr, std::move(name), parent),
- children(this),
- fieldType(fieldType),
- optional(optional),
- primitive(false)
-{
-}
-
-bool FieldDescriptor::doValidate(Logger &logger) const
-{
- bool valid = true;
- // check parent type
- if (getParent() == nullptr) {
- logger.error(std::string("Field \"") + getName() + "\" has no parent!",
- *this);
- valid = false;
- } else if (!getParent()->isa(&RttiTypes::Descriptor)) {
- logger.error(std::string("The parent of Field \"") + getName() +
- "\" is not a descriptor!",
- *this);
- valid = false;
- }
- // check name
- if (getName().empty()) {
- if (fieldType != FieldType::TREE) {
- logger.error(std::string("Field \"") + getName() +
- "\" is not the main field but has an empty name!",
- *this);
- valid = false;
- }
- } else {
- valid = valid & validateName(logger);
- }
-
- // check consistency of FieldType with the rest of the FieldDescriptor.
- if (primitive) {
- if (children.size() > 0) {
- logger.error(std::string("Field \"") + getName() +
- "\" is supposed to be primitive but has "
- "registered child classes!",
- *this);
- valid = false;
- }
- if (primitiveType == nullptr) {
- logger.error(std::string("Field \"") + getName() +
- "\" is supposed to be primitive but has "
- "no primitive type!",
- *this);
- valid = false;
- }
- } else {
- if (primitiveType != nullptr) {
- logger.error(std::string("Field \"") + getName() +
- "\" is supposed to be non-primitive but has "
- "a primitive type!",
- *this);
- valid = false;
- }
- // if this is not a primitive field we require at least one child.
- if (children.empty()) {
- logger.error(std::string("Field \"") + getName() +
- "\" is non primitive but does not allow children!",
- *this);
- valid = false;
- }
- }
- /*
- * we are not allowed to call the validation functions of each child because
- * this might lead to cycles. What we should do, however, is to check if
- * there are duplicates.
- */
- std::set<std::string> names;
- for (Handle<StructuredClass> c : getChildrenWithSubclasses()) {
- if (!names.insert(c->getName()).second) {
- logger.error(std::string("Field \"") + getName() +
- "\" had multiple children with the name \"" +
- c->getName() + "\"",
- *this);
- valid = false;
- }
- }
-
- return valid;
-}
-
-static void gatherSubclasses(
- std::unordered_set<const StructuredClass *>& visited,
- NodeVector<StructuredClass> &res, Handle<StructuredClass> strct)
-{
- // this check is to prevent cycles.
- if (!visited.insert(strct.get()).second) {
- return;
- }
- for (auto sub : strct->getSubclasses()) {
- // this check is to prevent cycles.
- if(visited.count(sub.get())){
- continue;
- }
- res.push_back(sub);
- gatherSubclasses(visited, res, sub);
- }
-}
-
-NodeVector<StructuredClass> FieldDescriptor::getChildrenWithSubclasses() const
-{
- std::unordered_set<const StructuredClass *> visited;
- NodeVector<StructuredClass> res;
- for (auto c : children) {
- res.push_back(c);
- gatherSubclasses(visited, res, c);
- }
- return res;
-}
-
-bool FieldDescriptor::removeChild(Handle<StructuredClass> c)
-{
- auto it = children.find(c);
- if (it != children.end()) {
- invalidate();
- children.erase(it);
- return true;
- }
- return false;
-}
-
-std::pair<NodeVector<Node>, bool> FieldDescriptor::pathTo(
- Handle<StructuredClass> childDescriptor, Logger &logger) const
-{
- bool success = false;
- NodeVector<Node> path =
- ousia::pathTo(this, logger, childDescriptor, success);
- return std::make_pair(path, success);
-}
-NodeVector<Node> FieldDescriptor::pathTo(Handle<FieldDescriptor> field,
- Logger &logger) const
-{
- bool success = false;
- return ousia::pathTo(this, logger, field, success);
-}
-NodeVector<FieldDescriptor> FieldDescriptor::getDefaultFields() const
-{
- // TODO: In principle a cast would be nicer here, but for now we copy.
- NodeVector<Node> nodes = collect(this, [](Handle<Node> n) {
- if (!n->isa(&RttiTypes::FieldDescriptor)) {
- return false;
- }
- Handle<FieldDescriptor> f = n.cast<FieldDescriptor>();
- return f->getFieldType() == FieldDescriptor::FieldType::TREE &&
- f->isPrimitive();
- });
- NodeVector<FieldDescriptor> res;
- for (auto n : nodes) {
- res.push_back(n.cast<FieldDescriptor>());
- }
- return res;
-}
-
-/* Class Descriptor */
-
-void Descriptor::doResolve(ResolutionState &state)
-{
- const NodeVector<Attribute> &attributes =
- attributesDescriptor->getAttributes();
- continueResolveComposita(attributes, attributes.getIndex(), state);
- continueResolveComposita(fieldDescriptors, fieldDescriptors.getIndex(),
- state);
-}
-
-bool Descriptor::doValidate(Logger &logger) const
-{
- bool valid = true;
- // check parent type
- if (getParent() == nullptr) {
- logger.error(
- std::string("Descriptor \"") + getName() + "\" has no parent!",
- *this);
- valid = false;
- } else if (!getParent()->isa(&RttiTypes::Domain)) {
- logger.error(std::string("The parent of Descriptor \"") + getName() +
- "\" is not a Domain!",
- *this);
- valid = false;
- }
- // check name
- if (getName().empty()) {
- logger.error("The name of this Descriptor is empty!", *this);
- valid = false;
- } else {
- valid = valid & validateName(logger);
- }
- // ensure that no attribute with the key "name" exists.
- if (attributesDescriptor == nullptr) {
- logger.error(std::string("Descriptor \"") + getName() +
- "\" has no Attribute specification!");
- valid = false;
- } else {
- if (attributesDescriptor->hasAttribute("name")) {
- logger.error(
- std::string("Descriptor \"") + getName() +
- "\" has an attribute \"name\" which is a reserved word!");
- valid = false;
- }
- valid = valid & attributesDescriptor->validate(logger);
- }
- // check that only one FieldDescriptor is of type TREE.
- auto fds = Descriptor::getFieldDescriptors();
- bool hasTREE = false;
- for (auto fd : fds) {
- if (fd->getFieldType() == FieldDescriptor::FieldType::TREE) {
- if (!hasTREE) {
- hasTREE = true;
- } else {
- logger.error(
- std::string("Descriptor \"") + getName() +
- "\" has multiple TREE fields, which is not permitted",
- *fd);
- valid = false;
- break;
- }
- }
- }
-
- // check attributes and the FieldDescriptors
- return valid & continueValidationCheckDuplicates(fds, logger);
-}
-
-NodeVector<Node> Descriptor::pathTo(Handle<StructuredClass> target,
- Logger &logger) const
-{
- bool success = false;
- return ousia::pathTo(this, logger, target, success);
-}
-
-std::pair<NodeVector<Node>, bool> Descriptor::pathTo(
- Handle<FieldDescriptor> field, Logger &logger) const
-{
- bool success = false;
- NodeVector<Node> path = ousia::pathTo(this, logger, field, success);
- return std::make_pair(path, success);
-}
-
-NodeVector<FieldDescriptor> Descriptor::getDefaultFields() const
-{
- // TODO: In principle a cast would be nicer here, but for now we copy.
- NodeVector<Node> nodes = collect(this, [](Handle<Node> n) {
- if (!n->isa(&RttiTypes::FieldDescriptor)) {
- return false;
- }
- Handle<FieldDescriptor> f = n.cast<FieldDescriptor>();
- return f->getFieldType() == FieldDescriptor::FieldType::TREE &&
- f->isPrimitive();
- });
- NodeVector<FieldDescriptor> res;
- for (auto n : nodes) {
- res.push_back(n.cast<FieldDescriptor>());
- }
- return res;
-}
-
-NodeVector<StructuredClass> Descriptor::getPermittedChildren() const
-{
- // TODO: In principle a cast would be nicer here, but for now we copy.
- NodeVector<Node> nodes = collect(this, [](Handle<Node> n) {
- return n->isa(&RttiTypes::StructuredClass);
- });
- NodeVector<StructuredClass> res;
- for (auto n : nodes) {
- res.push_back(n.cast<StructuredClass>());
- }
- return res;
-}
-
-static ssize_t getFieldDescriptorIndex(const NodeVector<FieldDescriptor> &fds,
- const std::string &name)
-{
- if (fds.empty()) {
- return -1;
- }
-
- if (name == DEFAULT_FIELD_NAME) {
- if (fds.back()->getFieldType() == FieldDescriptor::FieldType::TREE) {
- return fds.size() - 1;
- } else {
- /* The last field has to be the TREE field. If the last field does
- * not have the FieldType TREE no TREE-field exists at all. So we
- * return -1.
- */
- return -1;
- }
- }
-
- for (size_t f = 0; f < fds.size(); f++) {
- if (fds[f]->getName() == name) {
- return f;
- }
- }
- return -1;
-}
-
-ssize_t Descriptor::getFieldDescriptorIndex(const std::string &name) const
-{
- NodeVector<FieldDescriptor> fds = getFieldDescriptors();
- return ousia::getFieldDescriptorIndex(fds, name);
-}
-
-ssize_t Descriptor::getFieldDescriptorIndex(Handle<FieldDescriptor> fd) const
-{
- size_t f = 0;
- for (auto &fd2 : getFieldDescriptors()) {
- if (fd == fd2) {
- return f;
- }
- f++;
- }
- return -1;
-}
-
-Rooted<FieldDescriptor> Descriptor::getFieldDescriptor(
- const std::string &name) const
-{
- NodeVector<FieldDescriptor> fds = getFieldDescriptors();
- ssize_t idx = ousia::getFieldDescriptorIndex(fds, name);
- if (idx != -1) {
- return fds[idx];
- } else {
- return nullptr;
- }
-}
-
-bool Descriptor::addAndSortFieldDescriptor(Handle<FieldDescriptor> fd,
- Logger &logger)
-{
- // only add it if we need to.
- auto fds = getFieldDescriptors();
- if (fds.find(fd) == fds.end()) {
- invalidate();
- // check if the previous field is a tree field already.
- if (!fieldDescriptors.empty() &&
- fieldDescriptors.back()->getFieldType() ==
- FieldDescriptor::FieldType::TREE &&
- fd->getFieldType() != FieldDescriptor::FieldType::TREE) {
- // if so we add the new field before the TREE field.
- fieldDescriptors.insert(fieldDescriptors.end() - 1, fd);
- return true;
- } else {
- fieldDescriptors.push_back(fd);
- }
- }
- return false;
-}
-
-bool Descriptor::addFieldDescriptor(Handle<FieldDescriptor> fd, Logger &logger)
-{
- if (fd->getParent() == nullptr) {
- fd->setParent(this);
- }
- return addAndSortFieldDescriptor(fd, logger);
-}
-
-bool Descriptor::moveFieldDescriptor(Handle<FieldDescriptor> fd, Logger &logger)
-{
- bool sorted = addAndSortFieldDescriptor(fd, logger);
- Handle<Managed> par = fd->getParent();
- if (par != this) {
- if (par != nullptr) {
- // remove the FieldDescriptor from the old parent.
- par.cast<Descriptor>()->removeFieldDescriptor(fd);
- }
- fd->setParent(this);
- }
- return sorted;
-}
-
-bool Descriptor::copyFieldDescriptor(Handle<FieldDescriptor> fd, Logger &logger)
-{
- Rooted<FieldDescriptor> copy;
- if (fd->isPrimitive()) {
- copy = Rooted<FieldDescriptor>{new FieldDescriptor(
- getManager(), fd->getPrimitiveType(), this, fd->getFieldType(),
- fd->getName(), fd->isOptional())};
- } else {
- /*
- * In case of non-primitive FieldDescriptors we also want to copy the
- * child references.
- */
- copy = Rooted<FieldDescriptor>{
- new FieldDescriptor(getManager(), this, fd->getFieldType(),
- fd->getName(), fd->isOptional())};
- for (auto c : fd->getChildren()) {
- copy->addChild(c);
- }
- }
- return addFieldDescriptor(copy, logger);
-}
-
-bool Descriptor::removeFieldDescriptor(Handle<FieldDescriptor> fd)
-{
- auto it = fieldDescriptors.find(fd);
- if (it != fieldDescriptors.end()) {
- invalidate();
- fieldDescriptors.erase(it);
- fd->setParent(nullptr);
- return true;
- }
- return false;
-}
-
-std::pair<Rooted<FieldDescriptor>, bool>
-Descriptor::createPrimitiveFieldDescriptor(Handle<Type> primitiveType,
- Logger &logger,
- FieldDescriptor::FieldType fieldType,
- std::string name, bool optional)
-{
- Rooted<FieldDescriptor> fd{new FieldDescriptor(getManager(), primitiveType,
- this, fieldType,
- std::move(name), optional)};
- bool sorted = addFieldDescriptor(fd, logger);
- return std::make_pair(fd, sorted);
-}
-
-std::pair<Rooted<FieldDescriptor>, bool> Descriptor::createFieldDescriptor(
- Logger &logger, FieldDescriptor::FieldType fieldType, std::string name,
- bool optional)
-{
- Rooted<FieldDescriptor> fd{new FieldDescriptor(
- getManager(), this, fieldType, std::move(name), optional)};
- bool sorted = addFieldDescriptor(fd, logger);
- return std::make_pair(fd, sorted);
-}
-
-/* Class StructuredClass */
-
-StructuredClass::StructuredClass(Manager &mgr, std::string name,
- Handle<Domain> domain, Variant cardinality,
- Handle<StructuredClass> superclass,
- bool transparent, bool root)
- : Descriptor(mgr, std::move(name), domain),
- cardinality(cardinality),
- superclass(acquire(superclass)),
- subclasses(this),
- transparent(transparent),
- root(root)
-{
- ExceptionLogger logger;
- if (superclass != nullptr) {
- superclass->addSubclass(this, logger);
- }
- if (domain != nullptr) {
- domain->addStructuredClass(this);
- }
-}
-
-bool StructuredClass::doValidate(Logger &logger) const
-{
- bool valid = true;
- // check if all registered subclasses have this StructuredClass as parent.
- for (Handle<StructuredClass> sub : subclasses) {
- if (sub->getSuperclass() != this) {
- logger.error(std::string("Struct \"") + sub->getName() +
- "\" is registered as subclass of \"" + getName() +
- "\" but does not have it as superclass!",
- *this);
- valid = false;
- }
- }
- // check the cardinality.
- if (!cardinality.isCardinality()) {
- logger.error(cardinality.toString() + " is not a cardinality!", *this);
- valid = false;
- }
- // check the validity of this superclass.
- if (superclass != nullptr) {
- valid = valid & superclass->validate(logger);
- }
- // check the validity as a Descriptor.
- /*
- * Note that we do not check the validity of all subclasses. This is because
- * it will lead to cycles as the subclasses would call validate on their
- * superclass, which is this one.
- */
- return valid & Descriptor::doValidate(logger);
-}
-
-void StructuredClass::setSuperclass(Handle<StructuredClass> sup, Logger &logger)
-{
- if (superclass == sup) {
- return;
- }
- // remove this subclass from the old superclass.
- if (superclass != nullptr) {
- superclass->removeSubclass(this, logger);
- }
- // set the new superclass
- superclass = acquire(sup);
- invalidate();
- // add this class as new subclass of the new superclass.
- if (sup != nullptr) {
- sup->addSubclass(this, logger);
- // set the attribute descriptor supertype
- getAttributesDescriptor()->setParentStructure(
- sup->getAttributesDescriptor(), logger);
- } else {
- getAttributesDescriptor()->setParentStructure(nullptr, logger);
- }
-}
-
-bool StructuredClass::isSubclassOf(Handle<StructuredClass> c) const
-{
- if (c == nullptr || superclass == nullptr) {
- return false;
- }
- if (c == superclass) {
- return true;
- }
- return superclass->isSubclassOf(c);
-}
-
-void StructuredClass::addSubclass(Handle<StructuredClass> sc, Logger &logger)
-{
- if (sc == nullptr) {
- return;
- }
- // check if we already have that class.
- if (subclasses.find(sc) == subclasses.end()) {
- invalidate();
- subclasses.push_back(sc);
- }
- sc->setSuperclass(this, logger);
-}
-
-void StructuredClass::removeSubclass(Handle<StructuredClass> sc, Logger &logger)
-{
- // if we don't have this subclass we can return directly.
- if (sc == nullptr) {
- return;
- }
- auto it = subclasses.find(sc);
- if (it == subclasses.end()) {
- return;
- }
- // otherwise we have to erase it.
- invalidate();
- subclasses.erase(it);
- sc->setSuperclass(nullptr, logger);
-}
-
-Rooted<FieldDescriptor> StructuredClass::gatherFieldDescriptors(
- NodeVector<FieldDescriptor> &current,
- std::unordered_set<const StructuredClass *> &visited,
- std::set<std::string> &overriddenFields, bool hasTREE) const
-{
- // this check is to prevent cycles of inheritance to mess up this function.
- if (!visited.insert(this).second) {
- return nullptr;
- }
- Rooted<FieldDescriptor> mainField;
- NodeVector<FieldDescriptor> tmp;
- // first gather the non-overridden fields.
- for (auto f : Descriptor::getFieldDescriptors()) {
- if (overriddenFields.insert(f->getName()).second) {
- bool isTREE = f->getFieldType() == FieldDescriptor::FieldType::TREE;
- if (!isTREE) {
- tmp.push_back(f);
- } else {
- if (!hasTREE) {
- hasTREE = true;
- mainField = f;
- }
- }
- }
- }
- // append all non-overridden superclass fields.
-
- if (superclass != nullptr) {
- Rooted<FieldDescriptor> super_main_field =
- superclass->gatherFieldDescriptors(current, visited,
- overriddenFields, hasTREE);
- if (!hasTREE) {
- mainField = super_main_field;
- }
- }
- // then append all subtree fields of this level.
- current.insert(current.end(), tmp.begin(), tmp.end());
- // and return the main field.
- return mainField;
-}
-
-NodeVector<FieldDescriptor> StructuredClass::getFieldDescriptors() const
-{
- // in this case we return a NodeVector of Rooted entries without owner.
- NodeVector<FieldDescriptor> vec;
- std::unordered_set<const StructuredClass *> visited;
- std::set<std::string> overriddenFields;
- Rooted<FieldDescriptor> mainField =
- gatherFieldDescriptors(vec, visited, overriddenFields, false);
- if (mainField != nullptr) {
- vec.push_back(mainField);
- }
- return vec;
-}
-
-/* Class AnnotationClass */
-
-AnnotationClass::AnnotationClass(Manager &mgr, std::string name,
- Handle<Domain> domain)
- : Descriptor(mgr, std::move(name), domain)
-{
- if (domain != nullptr) {
- domain->addAnnotationClass(this);
- }
-}
-
-/* Class Domain */
-
-void Domain::doResolve(ResolutionState &state)
-{
- continueResolveComposita(structuredClasses, structuredClasses.getIndex(),
- state);
- continueResolveComposita(annotationClasses, annotationClasses.getIndex(),
- state);
- continueResolveReferences(typesystems, state);
- continueResolveReferences(domains, state);
-}
-
-bool Domain::doValidate(Logger &logger) const
-{
- // check validity of name, of StructuredClasses, of AnnotationClasses and
- // TypeSystems.
- return validateName(logger) &
- continueValidationCheckDuplicates(structuredClasses, logger) &
- continueValidationCheckDuplicates(annotationClasses, logger) &
- continueValidationCheckDuplicates(typesystems, logger);
-}
-
-void Domain::doReference(Handle<Node> node)
-{
- if (node->isa(&RttiTypes::Typesystem)) {
- referenceTypesystem(node.cast<Typesystem>());
- }
- if (node->isa(&RttiTypes::Domain)) {
- referenceDomain(node.cast<Domain>());
- }
-}
-
-RttiSet Domain::doGetReferenceTypes() const
-{
- return RttiSet{&RttiTypes::Domain, &RttiTypes::Typesystem};
-}
-
-void Domain::addStructuredClass(Handle<StructuredClass> s)
-{
- // only add it if we need to.
- if (structuredClasses.find(s) == structuredClasses.end()) {
- invalidate();
- structuredClasses.push_back(s);
- }
- Handle<Managed> par = s->getParent();
- if (par != this) {
- if (par != nullptr) {
- // remove the StructuredClass from the old parent.
- par.cast<Domain>()->removeStructuredClass(s);
- }
- s->setParent(this);
- }
-}
-
-bool Domain::removeStructuredClass(Handle<StructuredClass> s)
-{
- auto it = structuredClasses.find(s);
- if (it != structuredClasses.end()) {
- invalidate();
- structuredClasses.erase(it);
- s->setParent(nullptr);
- return true;
- }
- return false;
-}
-
-Rooted<StructuredClass> Domain::createStructuredClass(
- std::string name, Variant cardinality, Handle<StructuredClass> superclass,
- bool transparent, bool root)
-{
- return Rooted<StructuredClass>{new StructuredClass(
- getManager(), std::move(name), this, cardinality, superclass,
- std::move(transparent), std::move(root))};
-}
-
-void Domain::addAnnotationClass(Handle<AnnotationClass> a)
-{
- // only add it if we need to.
- if (annotationClasses.find(a) == annotationClasses.end()) {
- invalidate();
- annotationClasses.push_back(a);
- }
- Handle<Managed> par = a->getParent();
- if (par != this) {
- if (par != nullptr) {
- // remove the StructuredClass from the old parent.
- par.cast<Domain>()->removeAnnotationClass(a);
- }
- a->setParent(this);
- }
-}
-
-bool Domain::removeAnnotationClass(Handle<AnnotationClass> a)
-{
- auto it = annotationClasses.find(a);
- if (it != annotationClasses.end()) {
- invalidate();
- annotationClasses.erase(it);
- a->setParent(nullptr);
- return true;
- }
- return false;
-}
-
-Rooted<AnnotationClass> Domain::createAnnotationClass(std::string name)
-{
- return Rooted<AnnotationClass>{
- new AnnotationClass(getManager(), std::move(name), this)};
-}
-
-/* Type registrations */
-
-namespace RttiTypes {
-const Rtti FieldDescriptor =
- RttiBuilder<ousia::FieldDescriptor>("FieldDescriptor").parent(&Node);
-const Rtti Descriptor =
- RttiBuilder<ousia::Descriptor>("Descriptor").parent(&Node);
-const Rtti StructuredClass =
- RttiBuilder<ousia::StructuredClass>("StructuredClass")
- .parent(&Descriptor)
- .composedOf(&FieldDescriptor);
-const Rtti AnnotationClass =
- RttiBuilder<ousia::AnnotationClass>("AnnotationClass").parent(&Descriptor);
-const Rtti Domain = RttiBuilder<ousia::Domain>("Domain")
- .parent(&RootNode)
- .composedOf({&StructuredClass, &AnnotationClass});
-}
-} \ No newline at end of file