diff options
author | Benjamin Paassen <bpaassen@techfak.uni-bielefeld.de> | 2015-01-12 15:50:10 +0100 |
---|---|---|
committer | Benjamin Paassen <bpaassen@techfak.uni-bielefeld.de> | 2015-01-12 15:50:10 +0100 |
commit | 51de9238ddbd6b7f4cdaa5e9a5918cae952891b2 (patch) | |
tree | 90f9a91e8a67a5ee95b1cb2e3addda6b51ff7209 | |
parent | 60d9d3f9f54fab975c39d4c341f118df90628375 (diff) |
Tried to introduce another StructureNode class as common superclass for StructuredEntity, Anchor and DocumentPrimitive. Nearly seems to work, but not entirely so. There are still issues with the Manager it seems.
-rw-r--r-- | src/core/managed/Managed.hpp | 2 | ||||
-rw-r--r-- | src/core/model/Document.cpp | 8 | ||||
-rw-r--r-- | src/core/model/Document.hpp | 73 | ||||
-rw-r--r-- | src/plugins/html/DemoOutput.cpp | 38 | ||||
-rw-r--r-- | test/core/model/DocumentTest.cpp | 20 | ||||
-rw-r--r-- | test/core/model/TestDocumentBuilder.hpp | 2 | ||||
-rw-r--r-- | test/plugins/html/DemoOutputTest.cpp | 2 |
7 files changed, 93 insertions, 52 deletions
diff --git a/src/core/managed/Managed.hpp b/src/core/managed/Managed.hpp index 8ad609f..dd1a23a 100644 --- a/src/core/managed/Managed.hpp +++ b/src/core/managed/Managed.hpp @@ -357,7 +357,7 @@ public: * Statically casts the handle to a handle of the given type. */ template <class T2> - Handle<T2> cast() + Handle<T2> cast() const { return Handle<T2>(static_cast<T2 *>(ptr)); } diff --git a/src/core/model/Document.cpp b/src/core/model/Document.cpp index f591095..723aafd 100644 --- a/src/core/model/Document.cpp +++ b/src/core/model/Document.cpp @@ -111,13 +111,15 @@ const Rtti<model::Document> Document = const Rtti<model::AnnotationEntity> AnnotationEntity = RttiBuilder("AnnotationEntity").parent(&DocumentEntity).composedOf( &StructuredEntity); +const Rtti<model::StructureNode> StructureNode = + RttiBuilder("StructureNode").parent(&Node); const Rtti<model::StructuredEntity> StructuredEntity = - RttiBuilder("StructuredEntity").parent(&DocumentEntity).composedOf( + RttiBuilder("StructuredEntity").parent(&DocumentEntity).parent(&StructureNode).composedOf( {&StructuredEntity, &Anchor, &DocumentPrimitive}); const Rtti<model::DocumentPrimitive> DocumentPrimitive = - RttiBuilder("DocumentPrimitive").parent(&StructuredEntity); + RttiBuilder("DocumentPrimitive").parent(&StructureNode); const Rtti<model::AnnotationEntity::Anchor> Anchor = - RttiBuilder("Anchor").parent(&StructuredEntity); + RttiBuilder("Anchor").parent(&StructureNode); } } diff --git a/src/core/model/Document.hpp b/src/core/model/Document.hpp index 6e3b320..9bf8f07 100644 --- a/src/core/model/Document.hpp +++ b/src/core/model/Document.hpp @@ -124,9 +124,8 @@ class Rtti; namespace model { -class StructuredEntity; -class AnnotationEntity; class Document; +class StructureNode; /** * A DocumentEntity is the common superclass for StructuredEntities and @@ -139,11 +138,11 @@ class Document; * name. * */ -class DocumentEntity : public Node { +class DocumentEntity : public virtual Node { private: Owned<Descriptor> descriptor; const Variant attributes; - std::vector<NodeVector<StructuredEntity>> fields; + std::vector<NodeVector<StructureNode>> fields; int getFieldDescriptorIndex(const std::string &fieldName, bool enforce) const; @@ -164,10 +163,12 @@ public: if (!descriptor.isNull()) { for (size_t f = 0; f < descriptor->getFieldDescriptors().size(); f++) { - fields.push_back(NodeVector<StructuredEntity>(this)); + fields.push_back(NodeVector<StructureNode>(this)); } } } + //TODO: Is this necessary? + virtual ~DocumentEntity() {}; Rooted<Descriptor> getDescriptor() const { return descriptor; } @@ -203,7 +204,7 @@ public: * FieldDescriptor in the Domain description. * @return a NodeVector of all StructuredEntities in that field. */ - const NodeVector<StructuredEntity> &getField( + const NodeVector<StructureNode> &getField( const std::string &fieldName = "") const { return fields[getFieldDescriptorIndex(fieldName, true)]; @@ -220,7 +221,7 @@ public: * this DocumentEntity. * @return a NodeVector of all StructuredEntities in that field. */ - const NodeVector<StructuredEntity> &getField( + const NodeVector<StructureNode> &getField( Handle<FieldDescriptor> fieldDescriptor) const { return fields[getFieldDescriptorIndex(fieldDescriptor, true)]; @@ -238,7 +239,7 @@ public: * @param fieldName is the name of a field as specified in the * FieldDescriptor in the Domain description. */ - void addStructuredEntity(Handle<StructuredEntity> s, + void addStructuredEntity(Handle<StructureNode> s, const std::string &fieldName = "") { fields[getFieldDescriptorIndex(fieldName, true)].push_back(s); @@ -256,10 +257,10 @@ public: * @param fieldName is the name of a field as specified in the * FieldDescriptor in the Domain description. */ - void addStructuredEntities(const std::vector<Handle<StructuredEntity>> &ss, + void addStructuredEntities(const std::vector<Handle<StructureNode>> &ss, const std::string &fieldName = "") { - NodeVector<StructuredEntity> &field = + NodeVector<StructureNode> &field = fields[getFieldDescriptorIndex(fieldName, true)]; field.insert(field.end(), ss.begin(), ss.end()); } @@ -274,7 +275,7 @@ public: * @param fieldDescriptor is a FieldDescriptor defined in the Descriptor for * this DocumentEntity. */ - void addStructuredEntity(Handle<StructuredEntity> s, + void addStructuredEntity(Handle<StructureNode> s, Handle<FieldDescriptor> fieldDescriptor) { fields[getFieldDescriptorIndex(fieldDescriptor, true)].push_back(s); @@ -291,26 +292,42 @@ public: * @param fieldDescriptor is a FieldDescriptor defined in the Descriptor for * this DocumentEntity. */ - void addStructuredEntities(const std::vector<Handle<StructuredEntity>> &ss, + void addStructuredEntities(const std::vector<Handle<StructureNode>> &ss, Handle<FieldDescriptor> fieldDescriptor) { - NodeVector<StructuredEntity> &field = + NodeVector<StructureNode> &field = fields[getFieldDescriptorIndex(fieldDescriptor, true)]; field.insert(field.end(), ss.begin(), ss.end()); } }; /** - * A StructuredEntity is a node in the Structure Tree of a document. For more + * A StructureNode is a Node of the StructureTree of the document. This is a + * common superclass for StructuredEntity, Anchor and DocumentPrimitive. + */ +class StructureNode : public virtual Node { +public: + StructureNode(Manager &mgr, std::string name, Handle<Node> parent) + : Node(mgr, std::move(name), parent) + { + } + //TODO: Is this necessary? + virtual ~StructureNode(){}; +}; + +/** + * A StructuredEntity is an instance of a StructuredClass. For more * information please refer to the header documentation above. */ -class StructuredEntity : public DocumentEntity { +class StructuredEntity : public DocumentEntity, public StructureNode { public: StructuredEntity(Manager &mgr, Handle<Node> parent, Handle<StructuredClass> descriptor, Variant attributes, std::string name = "") - : DocumentEntity(mgr, parent, descriptor, std::move(attributes), - std::move(name)) + : Node(mgr, std::move(name), parent), + DocumentEntity(mgr, parent, descriptor, std::move(attributes), + std::move(name)), + StructureNode(mgr, std::move(name), parent) { } }; @@ -320,15 +337,20 @@ public: * The most straightforward example for this is the actual document text, e.g. * inside a paragraph. In that case this would represent a mere string. */ -class DocumentPrimitive : public StructuredEntity { +class DocumentPrimitive : public StructureNode { +private: + Variant content; + public: DocumentPrimitive(Manager &mgr, Handle<DocumentEntity> parent, Variant content = {}) - : StructuredEntity(mgr, parent, nullptr, std::move(content)) + : Node(mgr, parent), + StructureNode(mgr, "", parent), + content(content) { } - Variant getContent() const { return getAttributes(); } + Variant getContent() const { return content; } // TODO: Override such methods like "getField" to disable them? }; @@ -361,7 +383,7 @@ public: * referenced by an AnnotationEntity as it start and end point. * Please refer to the AnnotationEntity documentation for more information. */ - class Anchor : public StructuredEntity { + class Anchor : public StructureNode { public: /** * @param mgr is the Manager instance. @@ -369,8 +391,9 @@ public: * not the AnnotationEntity that references this Anchor. * @param name is the Anchor id. */ - Anchor(Manager &mgr, Handle<DocumentEntity> parent, std::string name) - : StructuredEntity(mgr, parent, nullptr, Variant(), std::move(name)) + Anchor(Manager &mgr, std::string name, Handle<DocumentEntity> parent) + : Node(mgr, std::move(name), parent), + StructureNode(mgr, std::move(name), parent) { } }; @@ -399,7 +422,8 @@ public: Handle<AnnotationClass> descriptor, Handle<Anchor> start, Handle<Anchor> end, Variant attributes = {}, std::string name = "") - : DocumentEntity(mgr, parent, descriptor, attributes, std::move(name)), + : Node(mgr, std::move(name), parent), + DocumentEntity(mgr, parent, descriptor, attributes, std::move(name)), start(acquire(start)), end(acquire(end)) { @@ -509,6 +533,7 @@ namespace RttiTypes { extern const Rtti<model::Document> Document; extern const Rtti<model::DocumentEntity> DocumentEntity; extern const Rtti<model::AnnotationEntity> AnnotationEntity; +extern const Rtti<model::StructureNode> StructureNode; extern const Rtti<model::StructuredEntity> StructuredEntity; extern const Rtti<model::DocumentPrimitive> DocumentPrimitive; extern const Rtti<model::AnnotationEntity::Anchor> Anchor; diff --git a/src/plugins/html/DemoOutput.cpp b/src/plugins/html/DemoOutput.cpp index 4cadf12..7dc1660 100644 --- a/src/plugins/html/DemoOutput.cpp +++ b/src/plugins/html/DemoOutput.cpp @@ -33,8 +33,7 @@ void DemoHTMLTransformer::writeHTML(Handle<model::Document> doc, { Manager &mgr = doc->getManager(); // Create an XML object tree for the document first. - Rooted<xml::Element> html{new xml::Element{ - mgr, {nullptr}, "html"}}; + Rooted<xml::Element> html{new xml::Element{mgr, {nullptr}, "html"}}; // add the head Element Rooted<xml::Element> head{new xml::Element{mgr, html, "head"}}; html->addChild(head); @@ -117,8 +116,8 @@ Rooted<xml::Element> DemoHTMLTransformer::transformSection( // check if we have a heading. if (section->hasField("heading") && section->getField("heading").size() > 0) { - Rooted<model::StructuredEntity> heading = - section->getField("heading")[0]; + Handle<model::StructuredEntity> heading = + section->getField("heading")[0].cast<model::StructuredEntity>(); std::string headingclass; switch (type) { case SectionType::BOOK: @@ -147,8 +146,11 @@ Rooted<xml::Element> DemoHTMLTransformer::transformSection( } // Then we get all the children. - NodeVector<model::StructuredEntity> mainField = section->getField(); - for (auto &n : mainField) { + for (auto &n : section->getField()) { + if (!n->isa(RttiTypes::StructuredEntity)) { + continue; + } + Handle<model::StructuredEntity> s = n.cast<model::StructuredEntity>(); /* * Strictly speaking this is the wrong mechanism, because we would have * to make an "isa" call here because we can not rely on our knowledge @@ -156,14 +158,14 @@ Rooted<xml::Element> DemoHTMLTransformer::transformSection( * to be a listener structure of transformations that check if they can * transform this specific node. */ - const std::string childDescriptorName = n->getDescriptor()->getName(); + const std::string childDescriptorName = s->getDescriptor()->getName(); Rooted<xml::Element> child; if (childDescriptorName == "paragraph") { - child = transformParagraph(sec, n, startMap, endMap); + child = transformParagraph(sec, s, startMap, endMap); } else if (childDescriptorName == "ul" || childDescriptorName == "ol") { - child = transformList(sec, n, startMap, endMap); + child = transformList(sec, s, startMap, endMap); } else { - child = transformSection(sec, n, startMap, endMap); + child = transformSection(sec, s, startMap, endMap); } if (!child.isNull()) { sec->addChild(child); @@ -181,7 +183,9 @@ Rooted<xml::Element> DemoHTMLTransformer::transformList( std::string listclass = list->getDescriptor()->getName(); Rooted<xml::Element> l{new xml::Element{mgr, parent, listclass}}; // iterate through list items. - for (auto &item : list->getField()) { + for (auto &it : list->getField()) { + Handle<model::StructuredEntity> item = + it.cast<model::StructuredEntity>(); std::string itDescrName = item->getDescriptor()->getName(); if (itDescrName == "item") { // create the list item. @@ -259,7 +263,8 @@ Rooted<xml::Element> DemoHTMLTransformer::transformParagraph( // check if we have a heading. if (par->hasField("heading") && par->getField("heading").size() > 0) { - Rooted<model::StructuredEntity> heading = par->getField("heading")[0]; + Handle<model::StructuredEntity> heading = + par->getField("heading")[0].cast<model::StructuredEntity>(); // put the heading in a strong xml::Element. Rooted<xml::Element> strong{new xml::Element{mgr, p, "strong"}}; p->addChild(strong); @@ -334,10 +339,15 @@ Rooted<xml::Element> DemoHTMLTransformer::transformParagraph( continue; } // if this is not an anchor, we can only handle text. - std::string childDescriptorName = n->getDescriptor()->getName(); + if(!n->isa(RttiTypes::StructuredEntity)){ + continue; + } + Handle<model::StructuredEntity> t = n.cast<model::StructuredEntity>(); + + std::string childDescriptorName = t->getDescriptor()->getName(); if (childDescriptorName == "text") { Handle<model::DocumentPrimitive> primitive = - n->getField()[0].cast<model::DocumentPrimitive>(); + t->getField()[0].cast<model::DocumentPrimitive>(); if (primitive.isNull()) { throw OusiaException("Text field is not primitive!"); } diff --git a/test/core/model/DocumentTest.cpp b/test/core/model/DocumentTest.cpp index d11bb78..4b0447d 100644 --- a/test/core/model/DocumentTest.cpp +++ b/test/core/model/DocumentTest.cpp @@ -34,7 +34,7 @@ namespace model { TEST(Document, testDocumentConstruction) { // Construct Manager - TerminalLogger logger {std::cerr, true}; + TerminalLogger logger{std::cerr, true}; Manager mgr{1}; Rooted<SystemTypesystem> sys{new SystemTypesystem(mgr)}; // Get the domain. @@ -52,7 +52,8 @@ TEST(Document, testDocumentConstruction) ASSERT_EQ(2U, root->getField().size()); // get foreword (paragraph) { - Rooted<StructuredEntity> foreword = root->getField()[0]; + Rooted<StructuredEntity> foreword = + root->getField()[0].cast<StructuredEntity>(); ASSERT_FALSE(foreword.isNull()); ASSERT_EQ("paragraph", foreword->getDescriptor()->getName()); // it should contain one text node @@ -61,7 +62,8 @@ TEST(Document, testDocumentConstruction) // which in turn should have a primitive content field containing the // right text. { - Rooted<StructuredEntity> text = foreword->getField()[0]; + Rooted<StructuredEntity> text = + foreword->getField()[0].cast<StructuredEntity>(); ASSERT_FALSE(text.isNull()); ASSERT_EQ("text", text->getDescriptor()->getName()); ASSERT_TRUE(text->hasField()); @@ -74,24 +76,26 @@ TEST(Document, testDocumentConstruction) } // get section { - Rooted<StructuredEntity> section = root->getField()[1]; + Rooted<StructuredEntity> section = + root->getField()[1].cast<StructuredEntity>(); ASSERT_FALSE(section.isNull()); ASSERT_EQ("section", section->getDescriptor()->getName()); // it should contain one paragraph ASSERT_TRUE(section->hasField()); ASSERT_EQ(1U, section->getField().size()); { - Rooted<StructuredEntity> par = section->getField()[0]; + Rooted<StructuredEntity> par = + section->getField()[0].cast<StructuredEntity>(); ASSERT_FALSE(par.isNull()); ASSERT_EQ("paragraph", par->getDescriptor()->getName()); // it should contain one text node ASSERT_TRUE(par->hasField()); ASSERT_EQ(1U, par->getField().size()); // which in turn should have a primitive content field containing - // the - // right text. + // the right text. { - Rooted<StructuredEntity> text = par->getField()[0]; + Rooted<StructuredEntity> text = + par->getField()[0].cast<StructuredEntity>(); ASSERT_FALSE(text.isNull()); ASSERT_EQ("text", text->getDescriptor()->getName()); ASSERT_TRUE(text->hasField()); diff --git a/test/core/model/TestDocumentBuilder.hpp b/test/core/model/TestDocumentBuilder.hpp index 4662a28..a1c8dde 100644 --- a/test/core/model/TestDocumentBuilder.hpp +++ b/test/core/model/TestDocumentBuilder.hpp @@ -235,7 +235,7 @@ Rooted<AnnotationEntity::Anchor> buildAnchor(Logger &logger, } // Then construct the Anchor itself Rooted<AnnotationEntity::Anchor> anchor{ - new AnnotationEntity::Anchor(parent->getManager(), parent, id)}; + new AnnotationEntity::Anchor(parent->getManager(), id, parent)}; // append the new entity to the right field. if (!parent->hasField(fieldName)) { logger.error(std::string("The parent has no field of the name ") + diff --git a/test/plugins/html/DemoOutputTest.cpp b/test/plugins/html/DemoOutputTest.cpp index ddd8f1c..9d1949e 100644 --- a/test/plugins/html/DemoOutputTest.cpp +++ b/test/plugins/html/DemoOutputTest.cpp @@ -56,7 +56,7 @@ TEST(DemoHTMLTransformer, writeHTML) #ifdef MANAGER_GRAPHVIZ_EXPORT // dump the manager state - mgr.exportGraphviz("bookDocument.dot"); + mgr.exportGraphviz("build/bookDocument.dot"); #endif // we can only do a rough check here. |