summaryrefslogtreecommitdiff
path: root/src/plugins
diff options
context:
space:
mode:
authorBenjamin Paassen <bpaassen@techfak.uni-bielefeld.de>2015-02-13 17:51:03 +0100
committerBenjamin Paassen <bpaassen@techfak.uni-bielefeld.de>2015-02-13 17:51:03 +0100
commitc99b5932ef47a5d74b5bccffb52c1ccabac6ae53 (patch)
tree40ee309ecba2408cb72eb44454db7b928be48fa0 /src/plugins
parent28f58e33e49a18d86592ca38fc44c106f54d7cec (diff)
refactored handler classes of XMLParser into own files in core/parser/stack.
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/xml/XmlParser.cpp929
1 files changed, 5 insertions, 924 deletions
diff --git a/src/plugins/xml/XmlParser.cpp b/src/plugins/xml/XmlParser.cpp
index 9ef08a5..6dfad49 100644
--- a/src/plugins/xml/XmlParser.cpp
+++ b/src/plugins/xml/XmlParser.cpp
@@ -16,7 +16,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <algorithm>
#include <iostream>
#include <map>
#include <sstream>
@@ -25,940 +24,22 @@
#include <expat.h>
#include <core/common/CharReader.hpp>
-#include <core/common/RttiBuilder.hpp>
#include <core/common/Utils.hpp>
#include <core/common/VariantReader.hpp>
-#include <core/parser/ParserStack.hpp>
#include <core/parser/ParserScope.hpp>
+#include <core/parser/ParserStack.hpp>
+#include <core/parser/stack/DocumentHandler.hpp>
+#include <core/parser/stack/DomainHandler.hpp>
+#include <core/parser/stack/ImportIncludeHandler.hpp>
+#include <core/parser/stack/TypesystemHandler.hpp>
#include <core/model/Document.hpp>
#include <core/model/Domain.hpp>
-#include <core/model/Project.hpp>
-#include <core/model/RootNode.hpp>
#include <core/model/Typesystem.hpp>
#include "XmlParser.hpp"
namespace ousia {
-/* HeadNode Helper class */
-
-namespace {
-class HeadNode : public Node {
-public:
- using Node::Node;
-};
-}
-
-namespace RttiTypes {
-static Rtti HeadNode = RttiBuilder<ousia::HeadNode>("HeadNode");
-}
-
-/* Element Handler Classes */
-
-class DocumentHandler : public Handler {
-public:
- using Handler::Handler;
-
- void start(Variant::mapType &args) override
- {
- Rooted<Document> document =
- project()->createDocument(args["name"].asString());
- document->setLocation(location());
- scope().push(document);
- scope().setFlag(ParserFlag::POST_HEAD, false);
- }
-
- void end() override { scope().pop(); }
-
- static Handler *create(const HandlerData &handlerData)
- {
- return new DocumentHandler{handlerData};
- }
-};
-
-class DocumentField : public Node {
-public:
- DocumentField(Manager &mgr, std::string name, Handle<Node> parent)
- : Node(mgr, name, parent)
- {
- }
-};
-
-namespace RttiTypes {
-const Rtti DocumentField =
- RttiBuilder<ousia::DocumentField>("DocumentField").parent(&Node);
-}
-
-class DocumentChildHandler : public Handler {
-public:
- using Handler::Handler;
-
- void preamble(Handle<Node> parentNode, std::string &fieldName,
- DocumentEntity *&parent, bool &inField)
- {
- // check if the parent in the structure tree was an explicit field
- // reference.
- inField = parentNode->isa(&RttiTypes::DocumentField);
- if (inField) {
- fieldName = parentNode->getName();
- parentNode = scope().selectOrThrow(
- {&RttiTypes::StructuredEntity, &RttiTypes::AnnotationEntity});
- } else {
- // if it wasn't an explicit reference, we use the default field.
- fieldName = DEFAULT_FIELD_NAME;
- }
- // reference the parent entity explicitly.
- parent = nullptr;
- if (parentNode->isa(&RttiTypes::StructuredEntity)) {
- parent = static_cast<DocumentEntity *>(
- parentNode.cast<StructuredEntity>().get());
- } else if (parentNode->isa(&RttiTypes::AnnotationEntity)) {
- parent = static_cast<DocumentEntity *>(
- parentNode.cast<AnnotationEntity>().get());
- }
- }
-
- void createPath(const NodeVector<Node> &path, DocumentEntity *&parent)
- {
- size_t S = path.size();
- for (size_t p = 1; p < S; p = p + 2) {
- parent = static_cast<DocumentEntity *>(
- parent->createChildStructuredEntity(
- path[p].cast<StructuredClass>(), Variant::mapType{},
- path[p - 1]->getName(), "").get());
- }
- }
-
- void start(Variant::mapType &args) override
- {
- scope().setFlag(ParserFlag::POST_HEAD, true);
- Rooted<Node> parentNode = scope().selectOrThrow(
- {&RttiTypes::Document, &RttiTypes::StructuredEntity,
- &RttiTypes::AnnotationEntity, &RttiTypes::DocumentField});
-
- std::string fieldName;
- DocumentEntity *parent;
- bool inField;
-
- preamble(parentNode, fieldName, parent, inField);
-
- // try to find a FieldDescriptor for the given tag if we are not in a
- // field already. This does _not_ try to construct transparent paths
- // in between.
- if (!inField && parent != nullptr &&
- parent->getDescriptor()->hasField(name())) {
- Rooted<DocumentField> field{new DocumentField(
- parentNode->getManager(), fieldName, parentNode)};
- field->setLocation(location());
- scope().push(field);
- return;
- }
-
- // Otherwise create a new StructuredEntity
- // TODO: Consider Anchors and AnnotationEntities
- Rooted<StructuredClass> strct = scope().resolve<StructuredClass>(
- Utils::split(name(), ':'), logger());
- if (strct == nullptr) {
- // if we could not resolve the name, throw an exception.
- throw LoggableException(
- std::string("\"") + name() + "\" could not be resolved.",
- location());
- }
-
- std::string name;
- auto it = args.find("name");
- if (it != args.end()) {
- name = it->second.asString();
- args.erase(it);
- }
-
- Rooted<StructuredEntity> entity;
- if (parentNode->isa(&RttiTypes::Document)) {
- entity = parentNode.cast<Document>()->createRootStructuredEntity(
- strct, args, name);
- } else {
- // calculate a path if transparent entities are needed in between.
- auto path = parent->getDescriptor()->pathTo(strct, logger());
- if (path.empty()) {
- throw LoggableException(
- std::string("An instance of \"") + strct->getName() +
- "\" is not allowed as child of an instance of \"" +
- parent->getDescriptor()->getName() + "\"",
- location());
- }
-
- // create all transparent entities until the last field.
- createPath(path, parent);
- entity = parent->createChildStructuredEntity(strct, args, fieldName,
- name);
- }
- entity->setLocation(location());
- scope().push(entity);
- }
-
- void end() override { scope().pop(); }
-
- std::pair<bool, Variant> convertData(Handle<FieldDescriptor> field,
- Logger &logger,
- const std::string &data)
- {
- // if the content is supposed to be of type string, we can finish
- // directly.
- auto vts = field->getPrimitiveType()->getVariantTypes();
- if (std::find(vts.begin(), vts.end(), VariantType::STRING) != vts.end()) {
- return std::make_pair(true, Variant::fromString(data));
- }
-
- // then try to parse the content using the type specification.
- auto res = field->getPrimitiveType()->read(
- data, logger, location().getSourceId(), location().getStart());
- return res;
- }
-
- void data(const std::string &data, int fieldIdx) override
- {
- Rooted<Node> parentNode = scope().selectOrThrow(
- {&RttiTypes::StructuredEntity, &RttiTypes::AnnotationEntity,
- &RttiTypes::DocumentField});
-
- std::string fieldName;
- DocumentEntity *parent;
- bool inField;
-
- preamble(parentNode, fieldName, parent, inField);
-
- Rooted<Descriptor> desc = parent->getDescriptor();
- /*
- * We distinguish two cases here: One for fields that are given.
- */
- if (fieldName != DEFAULT_FIELD_NAME) {
- // retrieve the actual FieldDescriptor
- Rooted<FieldDescriptor> field = desc->getFieldDescriptor(fieldName);
- if (field == nullptr) {
- logger().error(
- std::string(
- "Can't handle data because no field with name \"") +
- fieldName + "\" exists in descriptor\"" +
- desc->getName() + "\".",
- location());
- return;
- }
- // if it is not primitive at all, we can't parse the content.
- if (!field->isPrimitive()) {
- logger().error(
- std::string("Can't handle data because field \"") +
- fieldName + "\" of descriptor \"" + desc->getName() +
- "\" is not primitive!",
- location());
- return;
- }
- // then try to parse the content using the type specification.
- auto res = convertData(field, logger(), data);
- // add it as primitive content.
- if (res.first) {
- parent->createChildDocumentPrimitive(res.second, fieldName);
- }
- } else {
- /*
- * The second case is for primitive fields. Here we search through
- * all FieldDescriptors that allow primitive content at this point
- * and could be constructed via transparent intermediate entities.
- * We then try to parse the data using the type specified by the
- * respective field. If that does not work we proceed to the next
- * possible field.
- */
- // retrieve all fields.
- NodeVector<FieldDescriptor> fields = desc->getDefaultFields();
- for (auto field : fields) {
- // then try to parse the content using the type specification.
- LoggerFork loggerFork = logger().fork();
- auto res = convertData(field, loggerFork, data);
- if (res.first) {
- loggerFork.commit();
- // if that worked, construct the necessary path.
- auto pathRes = desc->pathTo(field, logger());
- assert(pathRes.second);
- NodeVector<Node> path = pathRes.first;
- createPath(path, parent);
- // then create the primitive element.
- parent->createChildDocumentPrimitive(res.second, fieldName);
- return;
- }
- }
- logger().error(
- "Could not read the data with any of the possible fields.",
- location());
- }
- }
-
- static Handler *create(const HandlerData &handlerData)
- {
- return new DocumentChildHandler{handlerData};
- }
-};
-
-class TypesystemHandler : public Handler {
-public:
- using Handler::Handler;
-
- void start(Variant::mapType &args) override
- {
- // Create the typesystem instance
- Rooted<Typesystem> typesystem =
- project()->createTypesystem(args["name"].asString());
- typesystem->setLocation(location());
-
- // Push the typesystem onto the scope, set the POST_HEAD flag to true
- scope().push(typesystem);
- scope().setFlag(ParserFlag::POST_HEAD, false);
- }
-
- void end() override { scope().pop(); }
-
- static Handler *create(const HandlerData &handlerData)
- {
- return new TypesystemHandler{handlerData};
- }
-};
-
-class TypesystemEnumHandler : public Handler {
-public:
- using Handler::Handler;
-
- void start(Variant::mapType &args) override
- {
- scope().setFlag(ParserFlag::POST_HEAD, true);
-
- // Fetch the current typesystem and create the enum node
- Rooted<Typesystem> typesystem = scope().selectOrThrow<Typesystem>();
- Rooted<EnumType> enumType =
- typesystem->createEnumType(args["name"].asString());
- enumType->setLocation(location());
-
- scope().push(enumType);
- }
-
- void end() override { scope().pop(); }
-
- static Handler *create(const HandlerData &handlerData)
- {
- return new TypesystemEnumHandler{handlerData};
- }
-};
-
-class TypesystemEnumEntryHandler : public Handler {
-public:
- using Handler::Handler;
-
- std::string entry;
-
- void start(Variant::mapType &args) override {}
-
- void end() override
- {
- Rooted<EnumType> enumType = scope().selectOrThrow<EnumType>();
- enumType->addEntry(entry, logger());
- }
-
- void data(const std::string &data, int field) override
- {
- if (field != 0) {
- // TODO: This should be stored in the HandlerData
- logger().error("Enum entry only has one field.");
- return;
- }
- entry.append(data);
- }
-
- static Handler *create(const HandlerData &handlerData)
- {
- return new TypesystemEnumEntryHandler{handlerData};
- }
-};
-
-class TypesystemStructHandler : public Handler {
-public:
- using Handler::Handler;
-
- void start(Variant::mapType &args) override
- {
- scope().setFlag(ParserFlag::POST_HEAD, true);
-
- // Fetch the arguments used for creating this type
- const std::string &name = args["name"].asString();
- const std::string &parent = args["parent"].asString();
-
- // Fetch the current typesystem and create the struct node
- Rooted<Typesystem> typesystem = scope().selectOrThrow<Typesystem>();
- Rooted<StructType> structType = typesystem->createStructType(name);
- structType->setLocation(location());
-
- // Try to resolve the parent type and set it as parent structure
- if (!parent.empty()) {
- scope().resolve<StructType>(
- parent, structType, logger(),
- [](Handle<Node> parent, Handle<Node> structType,
- Logger &logger) {
- if (parent != nullptr) {
- structType.cast<StructType>()->setParentStructure(
- parent.cast<StructType>(), logger);
- }
- });
- }
- scope().push(structType);
- }
-
- void end() override { scope().pop(); }
-
- static Handler *create(const HandlerData &handlerData)
- {
- return new TypesystemStructHandler{handlerData};
- }
-};
-
-class TypesystemStructFieldHandler : public Handler {
-public:
- using Handler::Handler;
-
- void start(Variant::mapType &args) override
- {
- // Read the argument values
- const std::string &name = args["name"].asString();
- const std::string &type = args["type"].asString();
- const Variant &defaultValue = args["default"];
- const bool optional =
- !(defaultValue.isObject() && defaultValue.asObject() == nullptr);
-
- Rooted<StructType> structType = scope().selectOrThrow<StructType>();
- Rooted<Attribute> attribute =
- structType->createAttribute(name, defaultValue, optional, logger());
- attribute->setLocation(location());
-
- // Try to resolve the type and default value
- if (optional) {
- scope().resolveTypeWithValue(
- type, attribute, attribute->getDefaultValue(), logger(),
- [](Handle<Node> type, Handle<Node> attribute, Logger &logger) {
- if (type != nullptr) {
- attribute.cast<Attribute>()->setType(type.cast<Type>(),
- logger);
- }
- });
- } else {
- scope().resolveType(
- type, attribute, logger(),
- [](Handle<Node> type, Handle<Node> attribute, Logger &logger) {
- if (type != nullptr) {
- attribute.cast<Attribute>()->setType(type.cast<Type>(),
- logger);
- }
- });
- }
- }
-
- void end() override {}
-
- static Handler *create(const HandlerData &handlerData)
- {
- return new TypesystemStructFieldHandler{handlerData};
- }
-};
-
-class TypesystemConstantHandler : public Handler {
-public:
- using Handler::Handler;
-
- void start(Variant::mapType &args) override
- {
- scope().setFlag(ParserFlag::POST_HEAD, true);
-
- // Read the argument values
- const std::string &name = args["name"].asString();
- const std::string &type = args["type"].asString();
- const Variant &value = args["value"];
-
- Rooted<Typesystem> typesystem = scope().selectOrThrow<Typesystem>();
- Rooted<Constant> constant = typesystem->createConstant(name, value);
- constant->setLocation(location());
-
- // Try to resolve the type
- scope().resolveTypeWithValue(
- type, constant, constant->getValue(), logger(),
- [](Handle<Node> type, Handle<Node> constant, Logger &logger) {
- if (type != nullptr) {
- constant.cast<Constant>()->setType(type.cast<Type>(),
- logger);
- }
- });
- }
-
- void end() override {}
-
- static Handler *create(const HandlerData &handlerData)
- {
- return new TypesystemConstantHandler{handlerData};
- }
-};
-
-/*
- * Domain Handlers
- */
-
-class DomainHandler : public Handler {
-public:
- using Handler::Handler;
-
- void start(Variant::mapType &args) override
- {
- Rooted<Domain> domain =
- project()->createDomain(args["name"].asString());
- domain->setLocation(location());
-
- scope().push(domain);
- }
-
- void end() override { scope().pop(); }
-
- static Handler *create(const HandlerData &handlerData)
- {
- return new DomainHandler{handlerData};
- }
-};
-
-class DomainStructHandler : public Handler {
-public:
- using Handler::Handler;
-
- void start(Variant::mapType &args) override
- {
- scope().setFlag(ParserFlag::POST_HEAD, true);
-
- Rooted<Domain> domain = scope().selectOrThrow<Domain>();
-
- Rooted<StructuredClass> 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<StructuredClass>(
- isa, structuredClass, logger(),
- [](Handle<Node> superclass, Handle<Node> structuredClass,
- Logger &logger) {
- if (superclass != nullptr) {
- structuredClass.cast<StructuredClass>()->setSuperclass(
- superclass.cast<StructuredClass>(), logger);
- }
- });
- }
-
- scope().push(structuredClass);
- }
-
- void end() override { scope().pop(); }
-
- static Handler *create(const HandlerData &handlerData)
- {
- return new DomainStructHandler{handlerData};
- }
-};
-
-class DomainAnnotationHandler : public Handler {
-public:
- using Handler::Handler;
-
- void start(Variant::mapType &args) override
- {
- scope().setFlag(ParserFlag::POST_HEAD, true);
-
- Rooted<Domain> domain = scope().selectOrThrow<Domain>();
-
- Rooted<AnnotationClass> annotationClass =
- domain->createAnnotationClass(args["name"].asString());
- annotationClass->setLocation(location());
-
- scope().push(annotationClass);
- }
-
- void end() override { scope().pop(); }
-
- static Handler *create(const HandlerData &handlerData)
- {
- return new DomainAnnotationHandler{handlerData};
- }
-};
-
-class DomainAttributesHandler : public Handler {
-public:
- using Handler::Handler;
-
- void start(Variant::mapType &args) override
- {
- // Fetch the current typesystem and create the struct node
- Rooted<Descriptor> parent = scope().selectOrThrow<Descriptor>();
-
- Rooted<StructType> attrDesc = parent->getAttributesDescriptor();
- attrDesc->setLocation(location());
-
- scope().push(attrDesc);
- }
-
- void end() override { scope().pop(); }
-
- static Handler *create(const HandlerData &handlerData)
- {
- return new DomainAttributesHandler{handlerData};
- }
-};
-
-class DomainFieldHandler : public Handler {
-public:
- using Handler::Handler;
-
- void start(Variant::mapType &args) override
- {
- FieldDescriptor::FieldType type;
- if (args["isSubtree"].asBool()) {
- type = FieldDescriptor::FieldType::SUBTREE;
- } else {
- type = FieldDescriptor::FieldType::TREE;
- }
-
- Rooted<Descriptor> parent = scope().selectOrThrow<Descriptor>();
-
- Rooted<FieldDescriptor> field = parent->createFieldDescriptor(
- logger(), type, args["name"].asString(), args["optional"].asBool());
- field->setLocation(location());
-
- scope().push(field);
- }
-
- void end() override { scope().pop(); }
-
- static Handler *create(const HandlerData &handlerData)
- {
- return new DomainFieldHandler{handlerData};
- }
-};
-
-class DomainFieldRefHandler : public Handler {
-public:
- using Handler::Handler;
-
- void start(Variant::mapType &args) override
- {
- Rooted<Descriptor> parent = scope().selectOrThrow<Descriptor>();
-
- const std::string &name = args["ref"].asString();
- scope().resolveFieldDescriptor(
- name, parent, logger(),
- [](Handle<Node> field, Handle<Node> parent, Logger &logger) {
- if (field != nullptr) {
- parent.cast<StructuredClass>()->addFieldDescriptor(
- field.cast<FieldDescriptor>(), logger);
- }
- });
- }
-
- void end() override {}
-
- static Handler *create(const HandlerData &handlerData)
- {
- return new DomainFieldRefHandler{handlerData};
- }
-};
-
-class DomainPrimitiveHandler : public Handler {
-public:
- using Handler::Handler;
-
- void start(Variant::mapType &args) override
- {
- Rooted<Descriptor> parent = scope().selectOrThrow<Descriptor>();
-
- FieldDescriptor::FieldType fieldType;
- if (args["isSubtree"].asBool()) {
- fieldType = FieldDescriptor::FieldType::SUBTREE;
- } else {
- fieldType = FieldDescriptor::FieldType::TREE;
- }
-
- Rooted<FieldDescriptor> field = parent->createPrimitiveFieldDescriptor(
- nullptr, logger(), fieldType, args["name"].asString(),
- args["optional"].asBool());
- field->setLocation(location());
-
- const std::string &type = args["type"].asString();
- scope().resolve<Type>(
- type, field, logger(),
- [](Handle<Node> type, Handle<Node> field, Logger &logger) {
- if (type != nullptr) {
- field.cast<FieldDescriptor>()->setPrimitiveType(
- type.cast<Type>());
- }
- });
-
- scope().push(field);
- }
-
- void end() override { scope().pop(); }
-
- static Handler *create(const HandlerData &handlerData)
- {
- return new DomainPrimitiveHandler{handlerData};
- }
-};
-
-class DomainChildHandler : public Handler {
-public:
- using Handler::Handler;
-
- void start(Variant::mapType &args) override
- {
- Rooted<FieldDescriptor> field =
- scope().selectOrThrow<FieldDescriptor>();
-
- const std::string &ref = args["ref"].asString();
- scope().resolve<StructuredClass>(
- ref, field, logger(),
- [](Handle<Node> child, Handle<Node> field, Logger &logger) {
- if (child != nullptr) {
- field.cast<FieldDescriptor>()->addChild(
- child.cast<StructuredClass>());
- }
- });
- }
-
- void end() override {}
-
- static Handler *create(const HandlerData &handlerData)
- {
- return new DomainChildHandler{handlerData};
- }
-};
-
-class DomainParent : public Node {
-public:
- DomainParent(Manager &mgr, std::string name, Handle<Node> parent)
- : Node(mgr, name, parent)
- {
- }
-};
-
-namespace RttiTypes {
-const Rtti DomainParent =
- RttiBuilder<ousia::DomainParent>("DomainParent").parent(&Node);
-}
-
-class DomainParentHandler : public Handler {
-public:
- using Handler::Handler;
-
- void start(Variant::mapType &args) override
- {
- Rooted<StructuredClass> strct =
- scope().selectOrThrow<StructuredClass>();
-
- Rooted<DomainParent> parent{new DomainParent(
- strct->getManager(), args["ref"].asString(), strct)};
- parent->setLocation(location());
- scope().push(parent);
- }
-
- void end() override { scope().pop(); }
-
- static Handler *create(const HandlerData &handlerData)
- {
- return new DomainParentHandler{handlerData};
- }
-};
-
-class DomainParentFieldHandler : public Handler {
-public:
- using Handler::Handler;
-
- void start(Variant::mapType &args) override
- {
- Rooted<DomainParent> parentNameNode =
- scope().selectOrThrow<DomainParent>();
- 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<StructuredClass> strct =
- parentNameNode->getParent().cast<StructuredClass>();
-
- // resolve the parent, create the declared field and add the declared
- // StructuredClass as child to it.
- scope().resolve<Descriptor>(
- parentNameNode->getName(), strct, logger(),
- [type, name, optional](Handle<Node> parent, Handle<Node> strct,
- Logger &logger) {
- if (parent != nullptr) {
- Rooted<FieldDescriptor> field =
- parent.cast<Descriptor>()->createFieldDescriptor(
- logger, type, name, optional);
- field->addChild(strct.cast<StructuredClass>());
- }
- });
- }
-
- void end() override {}
-
- static Handler *create(const HandlerData &handlerData)
- {
- return new DomainParentFieldHandler{handlerData};
- }
-};
-
-class DomainParentFieldRefHandler : public Handler {
-public:
- using Handler::Handler;
-
- void start(Variant::mapType &args) override
- {
- Rooted<DomainParent> parentNameNode =
- scope().selectOrThrow<DomainParent>();
-
- const std::string &name = args["ref"].asString();
- Rooted<StructuredClass> strct =
- parentNameNode->getParent().cast<StructuredClass>();
- auto loc = location();
-
- // resolve the parent, get the referenced field and add the declared
- // StructuredClass as child to it.
- scope().resolve<Descriptor>(parentNameNode->getName(), strct, logger(),
- [name, loc](Handle<Node> parent,
- Handle<Node> strct,
- Logger &logger) {
- if (parent != nullptr) {
- Rooted<FieldDescriptor> field =
- parent.cast<Descriptor>()->getFieldDescriptor(name);
- if (field == nullptr) {
- logger.error(
- std::string("Could not find referenced field ") + name,
- loc);
- return;
- }
- field->addChild(strct.cast<StructuredClass>());
- }
- });
- }
-
- void end() override {}
-
- static Handler *create(const HandlerData &handlerData)
- {
- return new DomainParentFieldRefHandler{handlerData};
- }
-};
-
-/*
- * Import and Include Handler
- */
-
-class ImportIncludeHandler : public Handler {
-public:
- using Handler::Handler;
-
- bool srcInArgs = false;
- std::string rel;
- std::string type;
- std::string src;
-
- void start(Variant::mapType &args) override
- {
- rel = args["rel"].asString();
- type = args["type"].asString();
- src = args["src"].asString();
- srcInArgs = !src.empty();
- }
-
- void data(const std::string &data, int field) override
- {
- if (srcInArgs) {
- logger().error("\"src\" attribute has already been set");
- return;
- }
- if (field != 0) {
- logger().error("Command has only one field.");
- return;
- }
- src.append(data);
- }
-};
-
-class ImportHandler : public ImportIncludeHandler {
-public:
- using ImportIncludeHandler::ImportIncludeHandler;
-
- void start(Variant::mapType &args) override
- {
- ImportIncludeHandler::start(args);
-
- // Make sure imports are still possible
- if (scope().getFlag(ParserFlag::POST_HEAD)) {
- logger().error("Imports must be listed before other commands.",
- location());
- return;
- }
- }
-
- void end() override
- {
- // Fetch the last node and check whether an import is valid at this
- // position
- Rooted<Node> leaf = scope().getLeaf();
- if (leaf == nullptr || !leaf->isa(&RttiTypes::RootNode)) {
- logger().error(
- "Import not supported here, must be inside a document, domain "
- "or typesystem command.",
- location());
- return;
- }
- Rooted<RootNode> leafRootNode = leaf.cast<RootNode>();
-
- // Perform the actual import, register the imported node within the leaf
- // node
- Rooted<Node> imported =
- context().import(src, type, rel, leafRootNode->getReferenceTypes());
- if (imported != nullptr) {
- leafRootNode->reference(imported);
- }
- }
-
- static Handler *create(const HandlerData &handlerData)
- {
- return new ImportHandler{handlerData};
- }
-};
-
-class IncludeHandler : public ImportIncludeHandler {
-public:
- using ImportIncludeHandler::ImportIncludeHandler;
-
- void start(Variant::mapType &args) override
- {
- ImportIncludeHandler::start(args);
- }
-
- void end() override
- {
- context().include(src, type, rel, {&RttiTypes::Node});
- }
-
- static Handler *create(const HandlerData &handlerData)
- {
- return new IncludeHandler{handlerData};
- }
-};
-
namespace ParserStates {
/* Document states */
static const ParserState Document =