From 824daa54eda59944593d6b726c3f79ab8b038998 Mon Sep 17 00:00:00 2001 From: Benjamin Paassen Date: Tue, 17 Feb 2015 18:07:00 +0100 Subject: added annotation support in XmlOutput. --- src/plugins/xml/XmlOutput.cpp | 116 ++++++++++++++++++++++++++++++++---------- src/plugins/xml/XmlOutput.hpp | 20 ++++++-- 2 files changed, 104 insertions(+), 32 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/xml/XmlOutput.cpp b/src/plugins/xml/XmlOutput.cpp index e17b4ab..37d95ec 100644 --- a/src/plugins/xml/XmlOutput.cpp +++ b/src/plugins/xml/XmlOutput.cpp @@ -55,14 +55,16 @@ void XmlTransformer::writeXml(Handle doc, std::ostream &out, createImportElement(document, d, resourceManager, "domain"); if (import != nullptr) { document->addChild(import); + // add the import as namespace information to the document node as + // well. + document->getAttributes().emplace( + std::string("xmlns:") + d->getName(), + import->getAttributes()["src"]); } else { logger.warning(std::string( - "The location of domain \")" + d->getName() + + "The location of domain \"" + d->getName() + "\" could not be retrieved using the given ResourceManager.")); } - // add the import as namespace information to the document node as well. - document->getAttributes().emplace(std::string("xmlns:") + d->getName(), - import->getAttributes()["src"]); } // write imports for all referenced typesystems. for (auto t : doc->getTypesystems()) { @@ -72,7 +74,7 @@ void XmlTransformer::writeXml(Handle doc, std::ostream &out, document->addChild(import); } else { logger.warning(std::string( - "The location of typesystem \")" + t->getName() + + "The location of typesystem \"" + t->getName() + "\" could not be retrieved using the given ResourceManager.")); } } @@ -96,46 +98,50 @@ static std::string toString(Variant v, bool pretty) } } -Rooted XmlTransformer::transformStructuredEntity( - Handle parent, Handle s, Logger &logger, - bool pretty) -{ - Manager &mgr = parent->getManager(); - // TODO: Is this the right handling? - // copy the attributes. - Variant attrs = s->getAttributes(); +std::map XmlTransformer::transformAttributes( + DocumentEntity *entity, Logger &logger, bool pretty) +{ // copy the attributes. + Variant attrs = entity->getAttributes(); // build them. - s->getDescriptor()->getAttributesDescriptor()->build(attrs, logger); + entity->getDescriptor()->getAttributesDescriptor()->build(attrs, logger); // get the array representation. Variant::arrayType attrArr = attrs.asArray(); // transform them to string key-value pairs. NodeVector as = - s->getDescriptor()->getAttributesDescriptor()->getAttributes(); + entity->getDescriptor()->getAttributesDescriptor()->getAttributes(); std::map xmlAttrs; for (size_t a = 0; a < as.size(); a++) { xmlAttrs.emplace(as[a]->getName(), toString(attrArr[a], pretty)); } + return xmlAttrs; +} + +void XmlTransformer::addNameAttribute(Handle n, + std::map &attrs) +{ // copy the name attribute. - if (!s->getName().empty()) { - xmlAttrs.emplace("name", s->getName()); + if (!n->getName().empty()) { + attrs.emplace("name", n->getName()); } +} - // create the XML element itself. - Rooted elem{ - new Element{mgr, parent, s->getDescriptor()->getName(), xmlAttrs, - s->getDescriptor()->getParent().cast()->getName()}}; - // then transform the fields. +void XmlTransformer::transformChildren(DocumentEntity *parentEntity, + Handle parent, Logger &logger, + bool pretty) +{ + Manager &mgr = parent->getManager(); NodeVector fieldDescs = - s->getDescriptor()->getFieldDescriptors(); + parentEntity->getDescriptor()->getFieldDescriptors(); for (size_t f = 0; f < fieldDescs.size(); f++) { - NodeVector field = s->getField(f); + NodeVector field = parentEntity->getField(f); Rooted fieldDesc = fieldDescs[f]; // if this is not the default field create an intermediate node for it. - Rooted par = elem; + Rooted par = parent; if (fieldDesc->getFieldType() != FieldDescriptor::FieldType::TREE && !fieldDesc->isPrimitive()) { - par = Rooted{new Element(mgr, elem, fieldDesc->getName())}; - elem->addChild(par); + par = + Rooted{new Element(mgr, parent, fieldDesc->getName())}; + parent->addChild(par); } for (auto c : field) { // transform each child. @@ -146,13 +152,67 @@ Rooted XmlTransformer::transformStructuredEntity( } else if (c->isa(&RttiTypes::DocumentPrimitive)) { child = transformPrimitive(par, c.cast(), logger, pretty); + } else { + child = transformAnchor(par, c.cast(), logger, pretty); } - // TODO: Handle Anchors if (child != nullptr) { par->addChild(child); } } } +} + +Rooted XmlTransformer::transformStructuredEntity( + Handle parent, Handle s, Logger &logger, + bool pretty) +{ + Manager &mgr = parent->getManager(); + // transform the attributes. + auto attrs = transformAttributes(s.get(), logger, pretty); + addNameAttribute(s, attrs); + // create the XML element itself. + Rooted elem{ + new Element{mgr, parent, s->getDescriptor()->getName(), + transformAttributes(s.get(), logger, pretty), + s->getDescriptor()->getParent().cast()->getName()}}; + // then transform the children. + transformChildren(s.get(), elem, logger, pretty); + return elem; +} + +Rooted XmlTransformer::transformAnchor(Handle parent, + Handle a, + Logger &logger, bool pretty) +{ + Rooted elem; + if (a->isStart()) { + // if this is the start anchor we append all the additional information + // of the annotation here. + // transform the attributes. + auto attrs = + transformAttributes(a->getAnnotation().get(), logger, pretty); + addNameAttribute(a->getAnnotation(), attrs); + + elem = Rooted{new Element( + parent->getManager(), parent, + a->getAnnotation()->getDescriptor()->getName(), attrs, "a:start")}; + // and handle the children. + transformChildren(a->getAnnotation().get(), elem, logger, pretty); + } else if (a->isEnd()) { + /* + * in principle !a->isStart() should imply a->isEnd() but if no + * annotation is set both is false, so we check it to be sure. + * In case of an end anchor we just create an empty element with the + * annotation name. + */ + std::map attrs; + addNameAttribute(a->getAnnotation(), attrs); + elem = Rooted{new Element( + parent->getManager(), parent, + a->getAnnotation()->getDescriptor()->getName(), attrs, "a:end")}; + } else { + logger.warning("Ignoring disconnected Anchor", *a); + } return elem; } diff --git a/src/plugins/xml/XmlOutput.hpp b/src/plugins/xml/XmlOutput.hpp index 2bb4190..24f2d49 100644 --- a/src/plugins/xml/XmlOutput.hpp +++ b/src/plugins/xml/XmlOutput.hpp @@ -37,13 +37,25 @@ namespace xml { class XmlTransformer { private: + std::map transformAttributes( + DocumentEntity *entity, Logger &logger, bool pretty); + + void addNameAttribute(Handle n, + std::map &attrs); + + void transformChildren(DocumentEntity *parentEntity, Handle parent, + Logger &logger, bool pretty); + Rooted transformStructuredEntity(Handle parent, Handle s, Logger &logger, bool pretty); + Rooted transformAnchor(Handle parent, Handle a, + Logger &logger, bool pretty); + Rooted transformPrimitive(Handle parent, - Handle p, - Logger &logger, bool pretty); + Handle p, Logger &logger, + bool pretty); public: /** @@ -62,8 +74,8 @@ public: * @param pretty is a flag that manipulates whether newlines and tabs are * used. */ - void writeXml(Handle doc, std::ostream &out, Logger &logger,ResourceManager& resMgr, - bool pretty); + void writeXml(Handle doc, std::ostream &out, Logger &logger, + ResourceManager &resMgr, bool pretty); }; } } -- cgit v1.2.3