From b87c0c1aba1f2c4fe4c805119a48991dac128ee8 Mon Sep 17 00:00:00 2001 From: Benjamin Paassen Date: Tue, 17 Feb 2015 18:05:53 +0100 Subject: sorted test list alphabetical and added XML output test. --- CMakeLists.txt | 51 ++++++++++------- test/plugins/xml/XmlOutputTest.cpp | 111 +++++++++++++++++++++++++++++++++++++ 2 files changed, 142 insertions(+), 20 deletions(-) create mode 100644 test/plugins/xml/XmlOutputTest.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 5b310a2..15e2f32 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -319,16 +319,6 @@ IF(TEST) ousia_core ) - ADD_EXECUTABLE(ousia_test_filesystem - test/plugins/filesystem/FileLocatorTest - ) - - TARGET_LINK_LIBRARIES(ousia_test_filesystem - ${GTEST_LIBRARIES} - ousia_core - ousia_filesystem - ) - # ADD_EXECUTABLE(ousia_test_css # test/plugins/css/Tokenizer # test/plugins/css/CodeTokenizerTest @@ -341,6 +331,16 @@ IF(TEST) # ousia_css # ) + ADD_EXECUTABLE(ousia_test_filesystem + test/plugins/filesystem/FileLocatorTest + ) + + TARGET_LINK_LIBRARIES(ousia_test_filesystem + ${GTEST_LIBRARIES} + ousia_core + ousia_filesystem + ) + ADD_EXECUTABLE(ousia_test_html test/plugins/html/DemoOutputTest ) @@ -351,6 +351,16 @@ IF(TEST) ousia_html ) +# ADD_EXECUTABLE(ousia_test_mozjs +# test/plugins/mozjs/MozJsScriptEngineTest +# ) + +# TARGET_LINK_LIBRARIES(ousia_test_mozjs +# ${GTEST_LIBRARIES} +# ousia_core +# ousia_mozjs +# ) + ADD_EXECUTABLE(ousia_test_osml test/formats/osml/OsmlParserTest test/formats/osml/OsmlStreamParserTest @@ -375,24 +385,25 @@ IF(TEST) ousia_filesystem ) -# ADD_EXECUTABLE(ousia_test_mozjs -# test/plugins/mozjs/MozJsScriptEngineTest -# ) + ADD_EXECUTABLE(ousia_test_xml + test/plugins/xml/XmlOutputTest + ) -# TARGET_LINK_LIBRARIES(ousia_test_mozjs -# ${GTEST_LIBRARIES} -# ousia_core -# ousia_mozjs -# ) + TARGET_LINK_LIBRARIES(ousia_test_xml + ${GTEST_LIBRARIES} + ousia_core + ousia_xml + ) # Register the unit tests ADD_TEST(ousia_test_core ousia_test_core) - ADD_TEST(ousia_test_filesystem ousia_test_filesystem) # ADD_TEST(ousia_test_css ousia_test_css) + ADD_TEST(ousia_test_filesystem ousia_test_filesystem) ADD_TEST(ousia_test_html ousia_test_html) +# ADD_TEST(ousia_test_mozjs ousia_test_mozjs) ADD_TEST(ousia_test_osml ousia_test_osml) ADD_TEST(ousia_test_osxml ousia_test_osxml) -# ADD_TEST(ousia_test_mozjs ousia_test_mozjs) + ADD_TEST(ousia_test_xml ousia_test_xml) ENDIF() ################################################################################ diff --git a/test/plugins/xml/XmlOutputTest.cpp b/test/plugins/xml/XmlOutputTest.cpp new file mode 100644 index 0000000..403078d --- /dev/null +++ b/test/plugins/xml/XmlOutputTest.cpp @@ -0,0 +1,111 @@ +/* + 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 + +#include +#include + +#include + +#include +#include +#include +#include + +#include +#include + +namespace ousia { +namespace xml { + +TEST(DemoHTMLTransformer, writeHTML) +{ + // Construct Manager + TerminalLogger logger{std::cerr, true}; + Manager mgr{1}; + Rooted sys{new SystemTypesystem(mgr)}; + // Get the domains. + Rooted bookDom = constructBookDomain(mgr, sys, logger); + Rooted headingDom = + constructHeadingDomain(mgr, sys, bookDom, logger); + Rooted listDom = constructListDomain(mgr, sys, bookDom, logger); + Rooted emDom = constructEmphasisDomain(mgr, sys, logger); + // Construct the document. + Rooted doc = constructAdvancedDocument( + mgr, logger, bookDom, headingDom, listDom, emDom); + ASSERT_TRUE(doc != nullptr); + + // we can only do a rough check here. + ResourceManager dummy; + XmlTransformer transformer; + std::stringstream out; + transformer.writeXml(doc, out, logger, dummy, true); + const std::string res = out.str(); + ASSERT_FALSE(res == ""); + ASSERT_TRUE(res.find("Was ist Aufklärung?") != std::string::npos); + ASSERT_TRUE(res.find( + "Aufklärung ist der Ausgang des Menschen aus seiner " + "selbstverschuldeten Unmündigkeit!") != std::string::npos); + ASSERT_TRUE(res.find("Sapere aude!") != std::string::npos); +} + +TEST(DemoHTMLTransformer, AnnotationProcessing) +{ + // Construct Manager + TerminalLogger logger{std::cerr, true}; + Manager mgr{1}; + Rooted sys{new SystemTypesystem(mgr)}; + // Get the domains. + Rooted bookDom = constructBookDomain(mgr, sys, logger); + Rooted emDom = constructEmphasisDomain(mgr, sys, logger); + // Construct a document only containing overlapping annotations. + // it has the form: blablubbla + Rooted doc{new Document(mgr, "annotations.oxd")}; + doc->referenceDomains({bookDom, emDom}); + Rooted book = + buildRootStructuredEntity(doc, logger, {"book"}); + ASSERT_TRUE(book != nullptr); + Rooted p = + buildStructuredEntity(doc, logger, book, {"paragraph"}); + ASSERT_TRUE(p != nullptr); + Rooted em_start{new Anchor(mgr, p)}; + ASSERT_TRUE(addText(logger, doc, p, "bla")); + Rooted strong_start{new Anchor(mgr, p)}; + ASSERT_TRUE(addText(logger, doc, p, "blub")); + Rooted em_end{new Anchor(mgr, p)}; + ASSERT_TRUE(addText(logger, doc, p, "bla")); + Rooted strong_end{new Anchor(mgr, p)}; + buildAnnotationEntity(doc, logger, {"emphasized"}, em_start, em_end); + buildAnnotationEntity(doc, logger, {"strong"}, strong_start, strong_end); + + // Check serialization. + ResourceManager dummy; + XmlTransformer transformer; + std::stringstream out; + transformer.writeXml(doc, out, logger, dummy, false); + const std::string res = out.str(); + // In HTML the overlapping structure must be serialized as follows: + ASSERT_TRUE( + res.find( + "blablubbla") != std::string::npos); +} +} +} \ No newline at end of file -- cgit v1.2.3 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(-) 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 From 2d835e93def7bd88e27e71fdec0f82d87d2e5a1b Mon Sep 17 00:00:00 2001 From: Benjamin Paassen Date: Tue, 17 Feb 2015 18:07:22 +0100 Subject: fixed wrong handling of empty attributes in TestAdvanced. --- test/core/model/TestAdvanced.hpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/test/core/model/TestAdvanced.hpp b/test/core/model/TestAdvanced.hpp index 8e81554..71379d2 100644 --- a/test/core/model/TestAdvanced.hpp +++ b/test/core/model/TestAdvanced.hpp @@ -65,8 +65,10 @@ static Rooted constructHeadingDomain(Manager &mgr, "paragraph"}; for (auto &s : secclasses) { Rooted desc = resolveDescriptor(bookDomain, s); - Rooted heading_field = desc->createFieldDescriptor( - logger, FieldDescriptor::FieldType::SUBTREE, "heading", true).first; + Rooted heading_field = + desc->createFieldDescriptor(logger, + FieldDescriptor::FieldType::SUBTREE, + "heading", true).first; heading_field->addChild(heading); } return domain; @@ -139,7 +141,7 @@ static bool addHeading(Logger &logger, Handle doc, { // Add the heading. Rooted heading = buildStructuredEntity( - doc, logger, parent, {"heading"}, "heading", {}, ""); + doc, logger, parent, {"heading"}, "heading", Variant::mapType{}, ""); if (heading.isNull()) { return false; } @@ -193,7 +195,7 @@ static Rooted constructAdvancedDocument(Manager &mgr, Logger &logger, // Add the heading. { Rooted heading = buildStructuredEntity( - doc, logger, book, {"heading"}, "heading", {}, ""); + doc, logger, book, {"heading"}, "heading", Variant::mapType{}, ""); if (heading.isNull()) { return {nullptr}; } @@ -311,4 +313,4 @@ static Rooted constructAdvancedDocument(Manager &mgr, Logger &logger, } } -#endif /* _TEST_DOCUMENT_HPP_ */ +#endif /* _TEST_DOCUMENT_HPP_ */ \ No newline at end of file -- cgit v1.2.3