summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Paassen <bpaassen@techfak.uni-bielefeld.de>2015-01-08 21:30:31 +0100
committerBenjamin Paassen <bpaassen@techfak.uni-bielefeld.de>2015-01-08 21:30:31 +0100
commit235cf24518ca40bec59b497a416d9831db12eaa3 (patch)
tree4892229aa435f81206480e256e71a7678dcbee22
parentb05499223916879e051d102e1b7e2fd080f46e7d (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.cpp54
-rw-r--r--src/core/model/Document.hpp58
-rw-r--r--src/core/model/Domain.hpp10
-rw-r--r--src/plugins/html/DemoOutput.cpp5
-rw-r--r--test/core/model/TestAdvanced.hpp117
-rw-r--r--test/plugins/html/DemoOutputTest.cpp2
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);