diff options
author | Benjamin Paassen <bpaassen@techfak.uni-bielefeld.de> | 2015-01-08 21:30:31 +0100 |
---|---|---|
committer | Benjamin Paassen <bpaassen@techfak.uni-bielefeld.de> | 2015-01-08 21:30:31 +0100 |
commit | 235cf24518ca40bec59b497a416d9831db12eaa3 (patch) | |
tree | 4892229aa435f81206480e256e71a7678dcbee22 | |
parent | b05499223916879e051d102e1b7e2fd080f46e7d (diff) |
further extended example to include annotations (emphasized and strong). The DemoOutput for that is still missing, though. convenience build functions have also been implemented in Document.cpp.
-rw-r--r-- | src/core/model/Document.cpp | 54 | ||||
-rw-r--r-- | src/core/model/Document.hpp | 58 | ||||
-rw-r--r-- | src/core/model/Domain.hpp | 10 | ||||
-rw-r--r-- | src/plugins/html/DemoOutput.cpp | 5 | ||||
-rw-r--r-- | test/core/model/TestAdvanced.hpp | 117 | ||||
-rw-r--r-- | test/plugins/html/DemoOutputTest.cpp | 2 |
6 files changed, 211 insertions, 35 deletions
diff --git a/src/core/model/Document.cpp b/src/core/model/Document.cpp index 073f728..c653fe3 100644 --- a/src/core/model/Document.cpp +++ b/src/core/model/Document.cpp @@ -100,7 +100,7 @@ static Rooted<StructuredClass> resolveDescriptor( } // Otherwise take the first valid result. for (auto &r : resolved) { - if(r->isa(typeOf<StructuredClass>())){ + if (r->isa(typeOf<StructuredClass>())) { return r.cast<StructuredClass>(); } } @@ -155,6 +155,9 @@ Rooted<StructuredEntity> StructuredEntity::buildEntity( return {nullptr}; } // append the new entity to the right field. + if (!parent->hasField(fieldName)) { + return {nullptr}; + } NodeVector<StructuredEntity> &field = parent->getField(fieldName); field.push_back(entity); @@ -178,13 +181,60 @@ Rooted<DocumentPrimitive> DocumentPrimitive::buildEntity( return {nullptr}; } // append the new entity to the right field. + if (!parent->hasField(fieldName)) { + return {nullptr}; + } NodeVector<StructuredEntity> &field = parent->getField(fieldName); field.push_back(entity); - // and return it. return entity; } +Rooted<AnnotationEntity::Anchor> AnnotationEntity::buildAnchor( + Handle<DocumentEntity> parent, std::string id, const std::string &fieldName) +{ + // If the parent is not set, we can not build the anchor. + if (parent == nullptr) { + return {nullptr}; + } + // Then construct the Anchor itself + Rooted<Anchor> anchor{ + new AnnotationEntity::Anchor(parent->getManager(), parent, id)}; + // append the new entity to the right field. + if (!parent->hasField(fieldName)) { + return {nullptr}; + } + NodeVector<StructuredEntity> &field = parent->getField(fieldName); + field.push_back(anchor); + // and return it. + return anchor; +} + +Rooted<AnnotationEntity> AnnotationEntity::buildEntity( + Handle<Document> parent, std::vector<Handle<Domain>> domains, + const std::string &className, Handle<AnnotationEntity::Anchor> start, + Handle<AnnotationEntity::Anchor> end, Variant attributes, std::string name) +{ + // If the parent is not set, we can not build the AnnotationEntity. + if (parent == nullptr) { + return {nullptr}; + } + // If we can not find the correct descriptor, we can not build the entity + // either. + Rooted<StructuredClass> descriptor = resolveDescriptor(domains, className); + if (descriptor == nullptr) { + return {nullptr}; + } + // Then construct the AnnotationEntity itself + Rooted<AnnotationEntity> anno{ + new AnnotationEntity(parent->getManager(), parent, descriptor, + attributes, start, end, name)}; + // append the new entity to the document + parent->getAnnotations().push_back(anno); + // and return it. + return anno; +} + /* Type registrations */ } diff --git a/src/core/model/Document.hpp b/src/core/model/Document.hpp index 7523962..993df9e 100644 --- a/src/core/model/Document.hpp +++ b/src/core/model/Document.hpp @@ -207,21 +207,15 @@ public: * information please refer to the header documentation above. */ class StructuredEntity : public DocumentEntity { -private: - NodeVector<AnnotationEntity> annotations; - 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)), - annotations(this) + std::move(name)) { } - NodeVector<AnnotationEntity> &getAnnotations() { return annotations; } - /** * This builds the root StructuredEntity for the given document. It * automatically appends the newly build entity to the given document. @@ -343,12 +337,11 @@ public: public: /** * @param mgr is the Manager instance. - * @param name is the Anchor id. * @param parent is the parent of this Anchor in the Structure Tree (!), * not the AnnotationEntity that references this Anchor. + * @param name is the Anchor id. */ - Anchor(Manager &mgr, Handle<StructuredEntity> parent, - std::string name = "") + Anchor(Manager &mgr, Handle<DocumentEntity> parent, std::string name) : StructuredEntity(mgr, parent, nullptr, Variant(), std::move(name)) { } @@ -372,6 +365,45 @@ public: Rooted<Anchor> getStart() { return start; } Rooted<Anchor> getEnd() { return end; } + + /** + * This builds an Anchor as child of the given DocumentEntity. It + * automatically appends the newly build Anchor to its parent. + * + * @param parent is the parent DocumentEntity. The newly constructed + * Anchor will automatically be appended to it. + * @param id is the id of this Anchor. + * @param fieldName is the name of the field where the newly constructed + * Anchor shall be appended. + * + * @return the newly created Anchor or a nullptr if some + * input handle was empty. + */ + static Rooted<Anchor> buildAnchor(Handle<DocumentEntity> parent, + std::string id, + const std::string &fieldName = ""); + /** + * This builds an AnnotationEntity as child of the given DocumentEntity. It + * automatically appends the newly build entity to its parent. + * + * @param parent is the document the newly constructed AnnotationEntity + * will be appended to. + * @param domains are the domains that are used to find the + * AnnotationClass for the new node. The domains will be + * searched in the given order. + * @param className is the name of the AnnotationClass. + * @param attributes are the attributes of the new node in terms of a Struct + * variant (empty per default). + * @param name is the name of this AnnotationEntity (empty per + * default). + * @return the newly created AnnotationEntity or a nullptr if some + * input handle was empty or the given domains did not + * contain a AnnotationClass with the given name. + */ + static Rooted<AnnotationEntity> buildEntity(Handle<Document> parent, std::vector<Handle<Domain>> domains, + const std::string &className, + Handle<Anchor> start, Handle<Anchor> end, + Variant attributes = Variant(), std::string name = ""); }; /** @@ -382,17 +414,21 @@ class Document : public Node { private: // TODO: Might there be several roots? E.g. metadata? Owned<StructuredEntity> root; + NodeVector<AnnotationEntity> annotations; public: Document(Manager &mgr, std::string name) // TODO: Can a document have a parent? - : Node(mgr, std::move(name), nullptr) + : Node(mgr, std::move(name), nullptr), + annotations(this) { } void setRoot(Handle<StructuredEntity> root) { this->root = acquire(root); }; Rooted<StructuredEntity> getRoot() const { return root; } + + NodeVector<AnnotationEntity> getAnnotations() { return annotations; } }; } diff --git a/src/core/model/Domain.hpp b/src/core/model/Domain.hpp index 6a07b32..027cf88 100644 --- a/src/core/model/Domain.hpp +++ b/src/core/model/Domain.hpp @@ -306,8 +306,7 @@ public: */ FieldDescriptor(Manager &mgr, Handle<Descriptor> parent, FieldType fieldType = FieldType::TREE, - std::string name = "", - bool optional = false) + std::string name = "", bool optional = false) : Node(mgr, std::move(name), parent), children(this), fieldType(fieldType), @@ -532,6 +531,13 @@ public: * This class has no special properties and is in essence just a Descriptor. */ class AnnotationClass : public Descriptor { +public: + AnnotationClass(Manager &mgr, std::string name, Handle<Domain> domain, + // TODO: What would be a wise default value for attributes? + Handle<StructType> attributesDescriptor) + : Descriptor(mgr, std::move(name), domain, attributesDescriptor) + { + } }; /** diff --git a/src/plugins/html/DemoOutput.cpp b/src/plugins/html/DemoOutput.cpp index 307d37a..c858695 100644 --- a/src/plugins/html/DemoOutput.cpp +++ b/src/plugins/html/DemoOutput.cpp @@ -183,6 +183,10 @@ Rooted<xml::Element> DemoHTMLTransformer::transformParagraph( // transform paragraph children to XML as well for (auto &n : par->getField()) { + if (n->isa(typeOf<model::AnnotationEntity::Anchor>())) { + // TODO: Handle Anchors! + continue; + } std::string childDescriptorName = n->getDescriptor()->getName(); if (childDescriptorName == "text") { Handle<model::DocumentPrimitive> primitive = @@ -193,7 +197,6 @@ Rooted<xml::Element> DemoHTMLTransformer::transformParagraph( p->children.push_back( new xml::Text(mgr, primitive->getContent().asString())); } - // TODO: Handle non-text content } return p; } diff --git a/test/core/model/TestAdvanced.hpp b/test/core/model/TestAdvanced.hpp index bec00f9..5af6003 100644 --- a/test/core/model/TestAdvanced.hpp +++ b/test/core/model/TestAdvanced.hpp @@ -109,6 +109,25 @@ static Rooted<Domain> constructListDomain(Manager &mgr, return domain; } +/** + * This constructs the "emphasis" domain. + */ +static Rooted<Domain> constructEmphasisDomain(Manager &mgr, + Handle<SystemTypesystem> sys, + Logger &logger) +{ + // set up domain node. + Rooted<Domain> domain{new Domain(mgr, sys, "emphasis")}; + // create AnnotationClasses + Rooted<AnnotationClass> em{ + new AnnotationClass(mgr, "emphasized", domain, {nullptr})}; + domain->getAnnotationClasses().push_back(em); + Rooted<AnnotationClass> strong{ + new AnnotationClass(mgr, "strong", domain, {nullptr})}; + domain->getAnnotationClasses().push_back(strong); + return domain; +} + static bool addText(Handle<StructuredEntity> parent, std::vector<Handle<Domain>> &doms, const std::string &content) @@ -147,6 +166,34 @@ static bool addHeading(Handle<StructuredEntity> parent, return true; } +static int annoIdx = 1; + +// Only works for non-overlapping annotations! +static bool addAnnotation(Handle<Document> doc, Handle<StructuredEntity> parent, + std::vector<Handle<Domain>> &doms, + const std::string &text, const std::string &annoClass) +{ + Rooted<AnnotationEntity::Anchor> start = + AnnotationEntity::buildAnchor(parent, std::to_string(annoIdx++)); + if (start.isNull()) { + return false; + } + if (!addText(parent, doms, text)) { + return false; + } + Rooted<AnnotationEntity::Anchor> end = + AnnotationEntity::buildAnchor(parent, std::to_string(annoIdx++)); + if (end.isNull()) { + return false; + } + Rooted<AnnotationEntity> anno = + AnnotationEntity::buildEntity(doc, doms, annoClass, start, end); + if (anno.isNull()) { + return false; + } + return true; +} + /** * This constructs a more advanced book document using not only the book * domain but also headings, emphasis and lists. @@ -170,10 +217,19 @@ static Rooted<Document> constructAdvancedDocument(Manager &mgr, } // Add the heading. - // TODO: use em here. - if (!addHeading(book, doms, - "Beantwortung der Frage: <em>Was ist Aufklärung?</em>")) { - return {nullptr}; + { + Rooted<StructuredEntity> heading = StructuredEntity::buildEntity( + book, doms, "heading", "heading", {}, ""); + if (heading.isNull()) { + return {nullptr}; + } + if (!addText(heading, doms, "Beantwortung der Frage: ")) { + return {nullptr}; + } + if (!addAnnotation(doc, heading, doms, "Was ist Aufklärung?", + "emphasized")) { + return {nullptr}; + } } // Add the main section. @@ -196,20 +252,43 @@ static Rooted<Document> constructAdvancedDocument(Manager &mgr, return {nullptr}; } // Add its text. - // TODO: Use em and strong here - if (!addText(p, doms, - " <strong>Aufklärung ist der Ausgang des Menschen aus " - "seiner selbstverschuldeten Unmündigkeit</strong>. " - "<em>Unmündigkeit</em> ist das Unvermögen, sich seines " - "Verstandes ohne Leitung eines anderen zu bedienen. " - "<em>Selbstverschuldet</em> ist diese Unmündigkeit, wenn " - "die Ursache derselben nicht am Mangel des Verstandes, " - "sondern der Entschließung und des Mutes liegt, sich " - "seiner ohne Leitung eines andern zu bedienen. <em>Sapere " - "aude! Habe Mut, dich deines eigenen Verstandes zu " - "bedienen!</em> ist also der Wahlspruch der " - "Aufklärung.")) { - return {nullptr}; + { + if (!addAnnotation(doc, p, doms, + "Aufklärung ist der Ausgang des Menschen aus " + "seiner selbstverschuldeten Unmündigkeit", + "strong")) { + return {nullptr}; + } + if (!addAnnotation(doc, p, doms, "Unmündigkeit", + "emphasized")) { + return {nullptr}; + } + if (!addText(p, doms, + "ist das Unvermögen, sich seines Verstandes ohne " + "Leitung eines anderen zu bedienen. ")) { + return {nullptr}; + } + if (!addAnnotation(doc, p, doms, "Selbstverschuldet", + "emphasized")) { + return {nullptr}; + } + if (!addText(p, doms, + " ist diese Unmündigkeit, wenn die Ursache derselben " + "nicht am Mangel des Verstandes, sondern der " + "Entschließung und des Mutes liegt, sich seiner ohne " + "Leitung eines andern zu bedienen.")) { + return {nullptr}; + } + if (!addAnnotation(doc, p, doms, + "Sapere aude! Habe Mut, dich deines eigenen " + "Verstandes zu bedienen!", + "emphasized")) { + return {nullptr}; + } + if (!addText(p, doms, + " ist also der Wahlspruch der Aufklärung.")) { + return {nullptr}; + } } } @@ -225,7 +304,7 @@ static Rooted<Document> constructAdvancedDocument(Manager &mgr, } // Add list with citations { - //TODO: We need to restrict this to the list domain. Otherwise + // TODO: We need to restrict this to the list domain. Otherwise // this leads to resolve errors for some reason. Rooted<StructuredEntity> ul = StructuredEntity::buildEntity(lesarten, {listDom}, "ul"); diff --git a/test/plugins/html/DemoOutputTest.cpp b/test/plugins/html/DemoOutputTest.cpp index 471ccc3..36b53b4 100644 --- a/test/plugins/html/DemoOutputTest.cpp +++ b/test/plugins/html/DemoOutputTest.cpp @@ -45,6 +45,8 @@ TEST(DemoHTMLTransformer, writeHTML) model::constructHeadingDomain(mgr, sys, bookDom, logger); Rooted<model::Domain> listDom = model::constructListDomain(mgr, sys, bookDom, logger); + Rooted<model::Domain> emDom = + model::constructEmphasisDomain(mgr, sys, logger); // Construct the document. Rooted<model::Document> doc = model::constructAdvancedDocument(mgr, bookDom, headingDom, listDom); |