From 9d9b65691347ce84d124fcafad7a562f91884c15 Mon Sep 17 00:00:00 2001 From: Andreas Stöckel Date: Wed, 15 Apr 2015 20:42:26 +0200 Subject: Implement resolution of referenced object --- src/core/model/Typesystem.cpp | 27 ++++++++++++++++++---- src/core/parser/stack/DocumentHandler.cpp | 38 ++++++++++++++++++++++++++----- 2 files changed, 55 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/core/model/Typesystem.cpp b/src/core/model/Typesystem.cpp index 86ee811..97cb043 100644 --- a/src/core/model/Typesystem.cpp +++ b/src/core/model/Typesystem.cpp @@ -16,8 +16,9 @@ along with this program. If not, see . */ -#include "Typesystem.hpp" +#include "Document.hpp" #include "Ontology.hpp" +#include "Typesystem.hpp" #include #include @@ -663,16 +664,34 @@ ReferenceType::ReferenceType(Manager &mgr, const std::string &name, bool ReferenceType::doBuild(Variant &data, Logger &logger, const ResolveCallback &resolveCallback) const { - // Null references are valid references + // Null references are valid references (these are mostly generated as a + // result of errors) if (data.isNull()) { return true; } if (data.isObject()) { - // TODO: Check: object is an instance of the entity descriptor + // Fetch the descriptor of the given object + Rooted obj = data.asObject(); + Rooted objectDescriptor; + if (obj->isa(&RttiTypes::AnnotationEntity)) { + objectDescriptor = obj.cast()->getDescriptor(); + } else if (obj->isa(&RttiTypes::StructuredEntity)) { + objectDescriptor = obj.cast()->getDescriptor(); + } else { + throw LoggableException("Reference targets wrong internal type \"" + + obj->type()->name + "\"!"); + } + + // Make sure the referenced object has the correct type + if (!objectDescriptor->inheritsFrom(descriptor)) { + throw LoggableException( + "Referenced entity of type \"" + objectDescriptor->getName() + + "\" is not compatible to reference type \"" + + descriptor->getName() + "\""); + } return true; } else if (data.isString()) { - // TODO: Lookup referenced object if (!Utils::isNamespacedIdentifier(data.asString())) { throw LoggableException("Reference must be a valid identifier", data); diff --git a/src/core/parser/stack/DocumentHandler.cpp b/src/core/parser/stack/DocumentHandler.cpp index 2228f11..e6b6d6a 100644 --- a/src/core/parser/stack/DocumentHandler.cpp +++ b/src/core/parser/stack/DocumentHandler.cpp @@ -768,9 +768,36 @@ bool DocumentChildHandler::convertData(Handle field, } // Now try to resolve the value for the primitive type - return valid && - scope().resolveValue(data, field->getParent().cast(), type, - logger); + return valid && scope().resolveValue(data, type, logger); +} + +static void createPrimitive(ParserScope &scope, Logger &logger, + Handle field, + DocumentEntity *parent, const Variant &data, + ssize_t fieldIdx = -1) +{ + // Create the primitive field + Rooted primitive; + if (fieldIdx < 0) { + primitive = parent->createChildDocumentPrimitive(data); + } else { + primitive = parent->createChildDocumentPrimitive(data, fieldIdx); + } + + // Fetch the primitive type, check whether it is a ReferenceType -- if yes, + // resolve the referenced object and set it once the resolution has finished + Rooted type = field->getPrimitiveType(); + if (type->isa(&RttiTypes::ReferenceType)) { + if (data.isString()) { + scope.resolve( + &RttiTypes::DocumentNode, Utils::split(data.asString(), ':'), + primitive, logger, + [](Handle resolved, Handle owner, Logger &logger) { + owner.cast()->getContent().setObject( + resolved, owner.get()); + }); + } + } } bool DocumentChildHandler::data() @@ -799,8 +826,7 @@ bool DocumentChildHandler::data() if (!convertData(field, text, logger())) { return false; } - - parent->createChildDocumentPrimitive(text, fieldIdx); + createPrimitive(scope(), logger(), field, parent, text, fieldIdx); return true; } @@ -830,7 +856,7 @@ bool DocumentChildHandler::data() createPath(fieldIdx, path, parent); // Then create the primitive element - parent->createChildDocumentPrimitive(text); + createPrimitive(scope(), logger(), primitiveField, parent, text); return true; } -- cgit v1.2.3