/*
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 "DomainHandler.hpp"
#include
#include
#include
namespace ousia {
/* DomainHandler */
void DomainHandler::start(Variant::mapType &args)
{
Rooted domain = project()->createDomain(args["name"].asString());
domain->setLocation(location());
scope().push(domain);
}
void DomainHandler::end() { scope().pop(); }
/* DomainStructHandler */
void DomainStructHandler::start(Variant::mapType &args)
{
scope().setFlag(ParserFlag::POST_HEAD, true);
Rooted domain = scope().selectOrThrow();
Rooted structuredClass = domain->createStructuredClass(
args["name"].asString(), args["cardinality"].asCardinality(), nullptr,
args["transparent"].asBool(), args["isRoot"].asBool());
structuredClass->setLocation(location());
const std::string &isa = args["isa"].asString();
if (!isa.empty()) {
scope().resolve(
isa, structuredClass, logger(),
[](Handle superclass, Handle structuredClass,
Logger &logger) {
if (superclass != nullptr) {
structuredClass.cast()->setSuperclass(
superclass.cast(), logger);
}
});
}
scope().push(structuredClass);
}
void DomainStructHandler::end() { scope().pop(); }
/* DomainAnnotationHandler */
void DomainAnnotationHandler::start(Variant::mapType &args)
{
scope().setFlag(ParserFlag::POST_HEAD, true);
Rooted domain = scope().selectOrThrow();
Rooted annotationClass =
domain->createAnnotationClass(args["name"].asString());
annotationClass->setLocation(location());
scope().push(annotationClass);
}
void DomainAnnotationHandler::end() { scope().pop(); }
/* DomainAttributesHandler */
void DomainAttributesHandler::start(Variant::mapType &args)
{
// Fetch the current typesystem and create the struct node
Rooted parent = scope().selectOrThrow();
Rooted attrDesc = parent->getAttributesDescriptor();
attrDesc->setLocation(location());
scope().push(attrDesc);
}
void DomainAttributesHandler::end() { scope().pop(); }
/* DomainFieldHandler */
void DomainFieldHandler::start(Variant::mapType &args)
{
FieldDescriptor::FieldType type;
if (args["isSubtree"].asBool()) {
type = FieldDescriptor::FieldType::SUBTREE;
} else {
type = FieldDescriptor::FieldType::TREE;
}
Rooted parent = scope().selectOrThrow();
Rooted field = parent->createFieldDescriptor(
logger(), type, args["name"].asString(), args["optional"].asBool());
field->setLocation(location());
scope().push(field);
}
void DomainFieldHandler::end() { scope().pop(); }
/* DomainFieldRefHandler */
void DomainFieldRefHandler::start(Variant::mapType &args)
{
Rooted parent = scope().selectOrThrow();
const std::string &name = args["ref"].asString();
scope().resolveFieldDescriptor(
name, parent, logger(),
[](Handle field, Handle parent, Logger &logger) {
if (field != nullptr) {
parent.cast()->addFieldDescriptor(
field.cast(), logger);
}
});
}
void DomainFieldRefHandler::end() {}
/* DomainPrimitiveHandler */
void DomainPrimitiveHandler::start(Variant::mapType &args)
{
Rooted parent = scope().selectOrThrow();
FieldDescriptor::FieldType fieldType;
if (args["isSubtree"].asBool()) {
fieldType = FieldDescriptor::FieldType::SUBTREE;
} else {
fieldType = FieldDescriptor::FieldType::TREE;
}
Rooted field = parent->createPrimitiveFieldDescriptor(
new UnknownType(manager()), logger(), fieldType,
args["name"].asString(), args["optional"].asBool());
field->setLocation(location());
const std::string &type = args["type"].asString();
scope().resolve(type, field, logger(),
[](Handle type, Handle field,
Logger &logger) {
if (type != nullptr) {
field.cast()->setPrimitiveType(type.cast());
}
});
scope().push(field);
}
void DomainPrimitiveHandler::end() { scope().pop(); }
/* DomainChildHandler */
void DomainChildHandler::start(Variant::mapType &args)
{
Rooted field = scope().selectOrThrow();
const std::string &ref = args["ref"].asString();
scope().resolve(
ref, field, logger(),
[](Handle child, Handle field, Logger &logger) {
if (child != nullptr) {
field.cast()->addChild(
child.cast());
}
});
}
void DomainChildHandler::end() {}
/* DomainParentHandler */
void DomainParentHandler::start(Variant::mapType &args)
{
Rooted strct = scope().selectOrThrow();
Rooted parent{
new DomainParent(strct->getManager(), args["ref"].asString(), strct)};
parent->setLocation(location());
scope().push(parent);
}
void DomainParentHandler::end() { scope().pop(); }
/* DomainParentFieldHandler */
void DomainParentFieldHandler::start(Variant::mapType &args)
{
Rooted parentNameNode = scope().selectOrThrow();
FieldDescriptor::FieldType type;
if (args["isSubtree"].asBool()) {
type = FieldDescriptor::FieldType::SUBTREE;
} else {
type = FieldDescriptor::FieldType::TREE;
}
const std::string &name = args["name"].asString();
const bool optional = args["optional"].asBool();
Rooted strct =
parentNameNode->getParent().cast();
// resolve the parent, create the declared field and add the declared
// StructuredClass as child to it.
scope().resolve(
parentNameNode->getName(), strct, logger(),
[type, name, optional](Handle parent, Handle strct,
Logger &logger) {
if (parent != nullptr) {
Rooted field =
parent.cast()->createFieldDescriptor(
logger, type, name, optional);
field->addChild(strct.cast());
}
});
}
void DomainParentFieldHandler::end() {}
/* DomainParentFieldRefHandler */
void DomainParentFieldRefHandler::start(Variant::mapType &args)
{
Rooted parentNameNode = scope().selectOrThrow();
const std::string &name = args["ref"].asString();
Rooted strct =
parentNameNode->getParent().cast();
auto loc = location();
// resolve the parent, get the referenced field and add the declared
// StructuredClass as child to it.
scope().resolve(
parentNameNode->getName(), strct, logger(),
[name, loc](Handle parent, Handle strct, Logger &logger) {
if (parent != nullptr) {
Rooted field =
parent.cast()->getFieldDescriptor(name);
if (field == nullptr) {
logger.error(
std::string("Could not find referenced field ") + name,
loc);
return;
}
field->addChild(strct.cast());
}
});
}
void DomainParentFieldRefHandler::end() {}
namespace RttiTypes {
const Rtti DomainParent =
RttiBuilder("DomainParent").parent(&Node);
}
}