summaryrefslogtreecommitdiff
path: root/src/core/parser/stack/DocumentHandler.cpp
diff options
context:
space:
mode:
authorBenjamin Paassen <bpaassen@techfak.uni-bielefeld.de>2015-02-15 18:17:31 +0100
committerBenjamin Paassen <bpaassen@techfak.uni-bielefeld.de>2015-02-15 18:17:31 +0100
commit0d8da1277274ef1b79b48df47e4dbc070f543d33 (patch)
tree04682db724143c0e413f288e1c8e0b145478d095 /src/core/parser/stack/DocumentHandler.cpp
parent6f3100acc766efb0a4d838fcdcd609c6de3c4297 (diff)
added support for transparent elements between explicit fields and primitive content.
Diffstat (limited to 'src/core/parser/stack/DocumentHandler.cpp')
-rw-r--r--src/core/parser/stack/DocumentHandler.cpp127
1 files changed, 80 insertions, 47 deletions
diff --git a/src/core/parser/stack/DocumentHandler.cpp b/src/core/parser/stack/DocumentHandler.cpp
index ba7430d..01ee594 100644
--- a/src/core/parser/stack/DocumentHandler.cpp
+++ b/src/core/parser/stack/DocumentHandler.cpp
@@ -70,8 +70,25 @@ void DocumentChildHandler::preamble(Handle<Node> parentNode,
}
}
-void DocumentChildHandler::createPath(const NodeVector<Node> &path,
- DocumentEntity *&parent)
+static void createPath(const std::string &firstFieldName,
+ const NodeVector<Node> &path, DocumentEntity *&parent)
+{
+ // add the first element
+ parent = static_cast<DocumentEntity *>(
+ parent->createChildStructuredEntity(path[0].cast<StructuredClass>(),
+ Variant::mapType{}, firstFieldName,
+ "").get());
+
+ size_t S = path.size();
+ for (size_t p = 2; p < S; p = p + 2) {
+ parent = static_cast<DocumentEntity *>(
+ parent->createChildStructuredEntity(
+ path[p].cast<StructuredClass>(), Variant::mapType{},
+ path[p - 1]->getName(), "").get());
+ }
+}
+
+static void createPath(const NodeVector<Node> &path, DocumentEntity *&parent)
{
size_t S = path.size();
for (size_t p = 1; p < S; p = p + 2) {
@@ -101,7 +118,7 @@ void DocumentChildHandler::start(Variant::mapType &args)
if (!inField && parent != nullptr &&
parent->getDescriptor()->hasField(name())) {
Rooted<DocumentField> field{
- new DocumentField(parentNode->getManager(), fieldName, parentNode)};
+ new DocumentField(parentNode->getManager(), name(), parentNode)};
field->setLocation(location());
scope().push(field);
return;
@@ -174,12 +191,14 @@ void DocumentChildHandler::data(const std::string &data, int fieldIdx)
&RttiTypes::DocumentField});
std::string fieldName;
- DocumentEntity *parent;
+ DocumentEntity *strctParent;
bool inField;
- preamble(parentNode, fieldName, parent, inField);
+ preamble(parentNode, fieldName, strctParent, inField);
- Rooted<Descriptor> desc = parent->getDescriptor();
+ Rooted<Descriptor> desc = strctParent->getDescriptor();
+ // The parent from which we need to connect to the primitive content.
+ Rooted<Node> parentClass;
/*
* We distinguish two cases here: One for fields that are given.
*/
@@ -194,54 +213,68 @@ void DocumentChildHandler::data(const std::string &data, int fieldIdx)
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());
+ // if it is a primitive field directly, try to parse the content.
+ if (field->isPrimitive()) {
+ auto res = convertData(field, logger(), data);
+ // add it as primitive content.
+ if (res.first) {
+ strctParent->createChildDocumentPrimitive(res.second,
+ fieldName);
+ }
return;
}
+ // if it is not primitive we need to connect via transparent elements
+ // and default fields.
+ parentClass = field;
+ } else {
+ // in case of default fields we need to construct via default fields
+ // and maybe transparent elements.
+ parentClass = desc;
+ }
+ /*
+ * Search through all permitted default fields of the parent class 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 default fields at this point.
+ NodeVector<FieldDescriptor> defaultFields;
+ if (parentClass->isa(&RttiTypes::FieldDescriptor)) {
+ defaultFields = parentClass.cast<FieldDescriptor>()->getDefaultFields();
+ } else {
+ defaultFields = parentClass.cast<StructuredClass>()->getDefaultFields();
+ }
+ std::vector<LoggerFork> forks;
+ for (auto field : defaultFields) {
// then try to parse the content using the type specification.
- auto res = convertData(field, logger(), data);
- // add it as primitive content.
+ forks.emplace_back(logger().fork());
+ auto res = convertData(field, forks.back(), data);
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();
- std::vector<LoggerFork> forks;
- for (auto field : fields) {
- // then try to parse the content using the type specification.
- forks.emplace_back(logger().fork());
- auto res = convertData(field, forks.back(), data);
- if (res.first) {
- forks.back().commit();
- // if that worked, construct the necessary path.
+ forks.back().commit();
+ // if that worked, construct the necessary path.
+ if (parentClass->isa(&RttiTypes::FieldDescriptor)) {
+ NodeVector<Node> path =
+ parentClass.cast<FieldDescriptor>()->pathTo(field,
+ logger());
+ createPath(fieldName, path, strctParent);
+ } else {
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;
+ createPath(pathRes.first, strctParent);
}
+ // then create the primitive element.
+ strctParent->createChildDocumentPrimitive(res.second);
+ return;
}
- logger().error("Could not read data with any of the possible fields:");
- for (size_t f = 0; f < fields.size(); f++) {
- logger().note(Utils::join(fields[f]->path(), ".") + ":",
- SourceLocation{}, MessageMode::NO_CONTEXT);
- forks[f].commit();
- }
+ }
+ logger().error("Could not read data with any of the possible fields:");
+ size_t f = 0;
+ for (auto field : defaultFields) {
+ logger().note(Utils::join(field->path(), ".") + ":", SourceLocation{},
+ MessageMode::NO_CONTEXT);
+ forks[f].commit();
+ f++;
}
}
@@ -249,4 +282,4 @@ namespace RttiTypes {
const Rtti DocumentField =
RttiBuilder<ousia::DocumentField>("DocumentField").parent(&Node);
}
-}
+} \ No newline at end of file