From dd3e14ec4dd2386cc8af61157975118acb4d6ee2 Mon Sep 17 00:00:00 2001 From: Benjamin Paassen Date: Sun, 4 Jan 2015 12:31:36 +0100 Subject: improved documentation. --- src/core/model/Document.hpp | 64 +++++++++++++++++++++++++++++++++------------ 1 file changed, 48 insertions(+), 16 deletions(-) (limited to 'src/core/model/Document.hpp') diff --git a/src/core/model/Document.hpp b/src/core/model/Document.hpp index 2d792c5..6ca1a30 100644 --- a/src/core/model/Document.hpp +++ b/src/core/model/Document.hpp @@ -32,21 +32,33 @@ * Structure Nodes, effectively resulting in a Document Graph instead of a * Document Tree (other references may introduce cycles as well). * - * Consider this simplified XML representation of a document (TODO: Use - * non-simplified XML as soon as possible): + * Consider this XML representation of a document using the "book" domain: * - * - * - * - * - * This is some text with some emphasized and - * strong text. - * - * - * - * - * - * + * + * + * + * + * + * + * + * This might be some introductory text or a dedication. Ideally, of + * course, such elements would be semantically specified as such in + * additional domains (or in this one). + * + * Here we might have an introduction to the chapter, including some + * overview of the chapters structure. + *
+ * Here we might find the actual section content. + *
+ *
+ * Here we might find the actual section content. + * + * + * And there might even be another paragraph. + *
+ *
+ *
+ *
* * As can be seen the StructureEntities inherently follow a tree structure that * is restricted by the implicit context free grammar of the "book" Domain @@ -56,12 +68,32 @@ * Another interesting fact is the special place of AnnotationEntities: They are * Defined by start and end Anchors in the text. Note that this allows for * overlapping annotations and provides a more intuitive (and semantically - * sound) handling of such span-like concepts. + * sound) handling of such span-like concepts. So the + * + * content + * + * is implicitly expanded to: + * + * content + * + * * Note that the place of an AnnotationEntity within the XML above is not * strictly defined. It might as well be placed as a child of the "book" node. * In general it is recommended to use the lowest possible place in the * StructureTree to include the AnnotationEntity for better readability. * + * Also note that text content like + * + * Here we might find the actual section content. + * + * is implicitly expanded using transparency to: + * + * + * + * Here we might find the actual section content. + * + * + * * @author Benjamin Paaßen (bpaassen@techfak.uni-bielefeld.de) */ @@ -365,7 +397,7 @@ public: */ class Document : public Node { private: - //TODO: Might there be several roots? E.g. metadata? + // TODO: Might there be several roots? E.g. metadata? Owned root; public: -- cgit v1.2.3 From 7d22aac0c7be52381822abdd0cb6860deaf01096 Mon Sep 17 00:00:00 2001 From: Benjamin Paassen Date: Sun, 4 Jan 2015 19:30:56 +0100 Subject: fixed a nasty bug in the getField method of DocumentEntity. Also corrected some issues in the TestDocument and TestDomain. --- src/core/model/Document.cpp | 20 ++++++------- src/core/model/Document.hpp | 33 ++++++--------------- test/core/model/DocumentTest.cpp | 62 +++++++++++++++++++++++++++++++++++++++- test/core/model/TestDocument.hpp | 26 +++++++++++------ test/core/model/TestDomain.hpp | 15 ++++++++-- 5 files changed, 109 insertions(+), 47 deletions(-) (limited to 'src/core/model/Document.hpp') diff --git a/src/core/model/Document.cpp b/src/core/model/Document.cpp index 854e717..e5d0755 100644 --- a/src/core/model/Document.cpp +++ b/src/core/model/Document.cpp @@ -57,20 +57,22 @@ int DocumentEntity::getFieldDescriptorIndex(const std::string &fieldName) return -1; } -void DocumentEntity::getField(NodeVector &res, - const std::string &fieldName) +NodeVector &DocumentEntity::getField( + const std::string &fieldName) { int f = getFieldDescriptorIndex(fieldName); if (f < 0) { - NodeVector empty{this}; - res = NodeVector(this); + throw OusiaException("No field for the given name exists!"); } - res = fields[f]; + return fields[f]; } NodeVector &DocumentEntity::getField( - Rooted fieldDescriptor) + Handle fieldDescriptor) { + if(fieldDescriptor.isNull()){ + throw OusiaException("The given FieldDescriptor handle is null!"); + } const NodeVector &fds = descriptor->getFieldDescriptors(); int f = 0; for (auto &fd : fds) { @@ -155,8 +157,7 @@ Rooted StructuredEntity::buildEntity( return {nullptr}; } // append the new entity to the right field. - NodeVector field(parent); - parent->getField(field, fieldName); + NodeVector& field = parent->getField(fieldName); field.push_back(entity); // and return it. @@ -179,8 +180,7 @@ Rooted DocumentPrimitive::buildEntity( return {nullptr}; } // append the new entity to the right field. - NodeVector field(parent); - parent->getField(field, fieldName); + NodeVector& field = parent->getField(fieldName); field.push_back(entity); // and return it. diff --git a/src/core/model/Document.hpp b/src/core/model/Document.hpp index 6ca1a30..fabdcaf 100644 --- a/src/core/model/Document.hpp +++ b/src/core/model/Document.hpp @@ -155,12 +155,6 @@ public: Variant getAttributes() const { return attributes; } - /** - * This allows a direct manipulation of the internal data structure of a - * DocumentEntity and is not recommended. TODO: Delete this? - */ - std::vector> &getFields() { return fields; } - /** * This returns true if there is a FieldDescriptor in the Descriptor for * this DocumentEntity which has the given name. If an empty name is @@ -180,29 +174,18 @@ public: /** * This returns the vector of entities containing all members of the field - * for which the FieldDescriptor has the specified name. If an empty name is - * given it is assumed that the 'default' FieldDescriptor is referenced, - * where 'default' means either: + * with the given name. If an empty name is given it is assumed that the + * 'default' FieldDescriptor is referenced, where 'default' means either: * 1.) The only TREE typed FieldDescriptor (if present) or * 2.) the only FieldDescriptor (if only one is specified). * - * Note that the output of this method might well be ambigous: If no - * FieldDescriptor matches the given name an empty NodeVector is - * returned. This is also the case, however, if there are no members for an - * existing field. Therefore it is recommended to additionally check the - * output of "hasField" or use the version of this method with - * a FieldDescriptor as input. + * If the name is unknown an exception is thrown. * - * @param fieldName is the name of the field as specified in the + * @param fieldName is the name of a field as specified in the * FieldDescriptor in the Domain description. - * @param res is a NodeVector reference where the result will be - * stored. After using this method the reference will - * either refer to all StructuredEntities in that field. If - * the field is unknown or if no members exist in that - * field yet, the NodeVector will be empty. + * @return a NodeVector of all StructuredEntities in that field. */ - void getField(NodeVector &res, - const std::string &fieldName = ""); + NodeVector &getField(const std::string &fieldName = ""); /** * This returns the vector of entities containing all members of the field @@ -216,7 +199,7 @@ public: * @return a NodeVector of all StructuredEntities in that field. */ NodeVector &getField( - Rooted fieldDescriptor); + Handle fieldDescriptor); }; /** @@ -407,7 +390,7 @@ public: { } - void setRoot(Handle root) { root = acquire(root); }; + void setRoot(Handle root) { this->root = acquire(root); }; Rooted getRoot() const { return root; } }; diff --git a/test/core/model/DocumentTest.cpp b/test/core/model/DocumentTest.cpp index 9e3229c..a671d2c 100644 --- a/test/core/model/DocumentTest.cpp +++ b/test/core/model/DocumentTest.cpp @@ -37,8 +37,68 @@ TEST(Document, testDocumentConstruction) // Construct the document. Rooted doc = constructBookDocument(mgr, domain); - // If that works we are happy already. + // Check the document content. ASSERT_FALSE(doc.isNull()); + // get root node. + Rooted root = doc->getRoot(); + ASSERT_FALSE(root.isNull()); + ASSERT_EQ("book", root->getDescriptor()->getName()); + ASSERT_TRUE(root->hasField()); + ASSERT_EQ(2, root->getField().size()); + // get foreword (paragraph) + { + Rooted foreword = root->getField()[0]; + ASSERT_FALSE(foreword.isNull()); + ASSERT_EQ("paragraph", foreword->getDescriptor()->getName()); + // it should contain one text node + ASSERT_TRUE(foreword->hasField()); + ASSERT_EQ(1, foreword->getField().size()); + // which in turn should have a primitive content field containing the + // right text. + { + Rooted text = foreword->getField()[0]; + ASSERT_FALSE(text.isNull()); + ASSERT_EQ("text", text->getDescriptor()->getName()); + ASSERT_TRUE(text->hasField()); + ASSERT_EQ(1, text->getField().size()); + ASSERT_TRUE(text->getField()[0]->isa(typeOf())); + Variant content = + text->getField()[0].cast()->getContent(); + ASSERT_EQ("Some introductory text", content.asString()); + } + } + // get section + { + Rooted section = root->getField()[1]; + ASSERT_FALSE(section.isNull()); + ASSERT_EQ("section", section->getDescriptor()->getName()); + // it should contain one paragraph + ASSERT_TRUE(section->hasField()); + ASSERT_EQ(1, section->getField().size()); + { + Rooted par = section->getField()[0]; + ASSERT_FALSE(par.isNull()); + ASSERT_EQ("paragraph", par->getDescriptor()->getName()); + // it should contain one text node + ASSERT_TRUE(par->hasField()); + ASSERT_EQ(1, par->getField().size()); + // which in turn should have a primitive content field containing + // the + // right text. + { + Rooted text = par->getField()[0]; + ASSERT_FALSE(text.isNull()); + ASSERT_EQ("text", text->getDescriptor()->getName()); + ASSERT_TRUE(text->hasField()); + ASSERT_EQ(1, text->getField().size()); + ASSERT_TRUE( + text->getField()[0]->isa(typeOf())); + Variant content = + text->getField()[0].cast()->getContent(); + ASSERT_EQ("Some actual text", content.asString()); + } + } + } } } } diff --git a/test/core/model/TestDocument.hpp b/test/core/model/TestDocument.hpp index a1a3434..6b0267a 100644 --- a/test/core/model/TestDocument.hpp +++ b/test/core/model/TestDocument.hpp @@ -50,13 +50,18 @@ static Rooted constructBookDocument(Manager &mgr, return {nullptr}; } // Add its text. - Variant text{std::map{ - {"content", Variant("Some introductory text")}}}; - Rooted foreword_text = - DocumentPrimitive::buildEntity(foreword, text, "text"); + Rooted foreword_text = + StructuredEntity::buildEntity(foreword, {bookDomain}, "text"); if (foreword_text.isNull()) { return {nullptr}; } + // And its primitive content + Variant text{"Some introductory text"}; + Rooted foreword_primitive = + DocumentPrimitive::buildEntity(foreword_text, text, "content"); + if (foreword_primitive.isNull()) { + return {nullptr}; + } // Add a section. Rooted section = StructuredEntity::buildEntity(root, {bookDomain}, "section"); @@ -67,13 +72,18 @@ static Rooted constructBookDocument(Manager &mgr, return {nullptr}; } // Add its text. - text = Variant{std::map{ - {"content", Variant("Some introductory text")}}}; - Rooted main_text = - DocumentPrimitive::buildEntity(foreword, text, "text"); + Rooted main_text = + StructuredEntity::buildEntity(main, {bookDomain}, "text"); if (main_text.isNull()) { return {nullptr}; } + // And its primitive content + text = Variant{"Some actual text"}; + Rooted main_primitive = + DocumentPrimitive::buildEntity(main_text, text, "content"); + if (main_primitive.isNull()) { + return {nullptr}; + } return doc; } diff --git a/test/core/model/TestDomain.hpp b/test/core/model/TestDomain.hpp index d55bff7..f457531 100644 --- a/test/core/model/TestDomain.hpp +++ b/test/core/model/TestDomain.hpp @@ -81,11 +81,20 @@ static Rooted constructBookDomain(Manager &mgr, Logger &logger) section_field->getChildren().push_back(paragraph); book_field->getChildren().push_back(paragraph); domain->getStructureClasses().push_back(paragraph); + // And the field of it. + Rooted paragraph_field{new FieldDescriptor(mgr, paragraph)}; + paragraph->getFieldDescriptors().push_back(paragraph_field); + + // Finally we add the "text" node, which is transparent as well. + Rooted text{new StructuredClass( + mgr, "text", domain, any, {nullptr}, {nullptr}, true)}; + paragraph_field->getChildren().push_back(text); + domain->getStructureClasses().push_back(text); // ... and has a primitive field. - Rooted paragraph_field{new FieldDescriptor( - mgr, paragraph, domain->getTypesystems()[0]->getTypes()[1], "text", + Rooted text_field{new FieldDescriptor( + mgr, text, domain->getTypesystems()[0]->getTypes()[0], "content", false)}; - paragraph->getFieldDescriptors().push_back(paragraph_field); + text->getFieldDescriptors().push_back(text_field); return domain; } -- cgit v1.2.3