diff options
author | Benjamin Paassen <bpaassen@techfak.uni-bielefeld.de> | 2015-02-12 11:33:01 +0100 |
---|---|---|
committer | Benjamin Paassen <bpaassen@techfak.uni-bielefeld.de> | 2015-02-12 11:33:01 +0100 |
commit | ebac41111fa33790acce7be45e599f8de37e7f43 (patch) | |
tree | f23a5875d30d28c35e5a8e352856f5f9a9ef7cf2 /src/core/model | |
parent | dbf2eebdd88118dca79045ad0524061f8078e668 (diff) |
Anchors do not have a name anymore and have a unique mapping to their AnnotationEntities. This also makes serialization much easier.
Diffstat (limited to 'src/core/model')
-rw-r--r-- | src/core/model/Document.cpp | 112 | ||||
-rw-r--r-- | src/core/model/Document.hpp | 66 |
2 files changed, 149 insertions, 29 deletions
diff --git a/src/core/model/Document.cpp b/src/core/model/Document.cpp index 8b31f14..b38f2c0 100644 --- a/src/core/model/Document.cpp +++ b/src/core/model/Document.cpp @@ -275,9 +275,9 @@ static int enforceGetFieldDescriptorIndex(Handle<Descriptor> desc, { ssize_t idx = desc->getFieldDescriptorIndex(fieldName); if (idx == -1) { - throw OusiaException( - std::string("Descriptor \"") + desc->getName() + - "\" has no field with the name \"" + fieldName + "\""); + throw OusiaException(std::string("Descriptor \"") + desc->getName() + + "\" has no field with the name \"" + fieldName + + "\""); } return idx; } @@ -287,8 +287,7 @@ static int enforceGetFieldDescriptorIndex( { ssize_t idx = desc->getFieldDescriptorIndex(fieldDescriptor); if (idx == -1) { - throw OusiaException(std::string("Descriptor \"") + - desc->getName() + + throw OusiaException(std::string("Descriptor \"") + desc->getName() + "\" does not reference the given field \"" + fieldDescriptor->getName() + "\""); } @@ -419,11 +418,10 @@ Rooted<DocumentPrimitive> DocumentEntity::createChildDocumentPrimitive( subInst->getManager(), subInst, std::move(content), fieldName)}; } -Rooted<Anchor> DocumentEntity::createChildAnchor(std::string name, - const std::string &fieldName) +Rooted<Anchor> DocumentEntity::createChildAnchor(const std::string &fieldName) { return Rooted<Anchor>{ - new Anchor(subInst->getManager(), std::move(name), subInst, fieldName)}; + new Anchor(subInst->getManager(), subInst, fieldName)}; } /* Class StructureNode */ @@ -494,13 +492,61 @@ bool Anchor::doValidate(Logger &logger) const { bool valid = true; // check name - if (getName().empty()) { - logger.error("An Anchor needs a name!", *this); + if (!getName().empty()) { + logger.error( + "This anchor has a name! Anchors should only be referred to by " + "reference, not by name!", + *this); valid = false; } + if (annotation == nullptr) { + // this is valid but should throw a warning. + logger.warning("This anchor is disconnected.", *this); + } return valid & StructureNode::doValidate(logger); } +void Anchor::setAnnotation(Handle<AnnotationEntity> anno, bool start) +{ + if (annotation == anno) { + return; + } + invalidate(); + // unset the old reference. + if (annotation != nullptr) { + if (isStart()) { + annotation->setStart(nullptr); + } else { + annotation->setEnd(nullptr); + } + } + annotation = acquire(anno); + // set the new reference. + if (anno != nullptr) { + if (start) { + anno->setStart(this); + } else { + anno->setEnd(this); + } + } +} + +bool Anchor::isStart() const +{ + if (annotation == nullptr) { + return false; + } + return annotation->getStart() == this; +} + +bool Anchor::isEnd() const +{ + if (annotation == nullptr) { + return false; + } + return annotation->getEnd() == this; +} + /* Class AnnotationEntity */ AnnotationEntity::AnnotationEntity(Manager &mgr, Handle<Document> parent, @@ -508,13 +554,13 @@ AnnotationEntity::AnnotationEntity(Manager &mgr, Handle<Document> parent, Handle<Anchor> start, Handle<Anchor> end, Variant attributes, std::string name) : Node(mgr, std::move(name), parent), - DocumentEntity(this, descriptor, attributes), - start(acquire(start)), - end(acquire(end)) + DocumentEntity(this, descriptor, attributes) { if (parent != nullptr) { parent->addAnnotation(this); } + setStart(start); + setEnd(end); } bool AnnotationEntity::doValidate(Logger &logger) const @@ -567,10 +613,50 @@ bool AnnotationEntity::doValidate(Logger &logger) const valid = false; } } + // check if the Anchors reference this AnnotationEntity correctly. + if (start != nullptr) { + if (start->getAnnotation() != this) { + logger.error( + "This annotations start anchor does not have the correct " + "annotation as parent!", + *this); + valid = false; + } + } + if (end != nullptr) { + if (end->getAnnotation() != this) { + logger.error( + "This annotations end anchor does not have the correct " + "annotation as parent!", + *this); + valid = false; + } + } + // check the validity as a DocumentEntity. return valid & DocumentEntity::doValidate(logger); } +void AnnotationEntity::setStart(Handle<Anchor> s) +{ + if (start == s) { + return; + } + invalidate(); + start = acquire(s); + s->setAnnotation(this, true); +} + +void AnnotationEntity::setEnd(Handle<Anchor> e) +{ + if (end == e) { + return; + } + invalidate(); + end = acquire(e); + e->setAnnotation(this, false); +} + /* Class Document */ void Document::doResolve(ResolutionState &state) diff --git a/src/core/model/Document.hpp b/src/core/model/Document.hpp index b41393e..bffd397 100644 --- a/src/core/model/Document.hpp +++ b/src/core/model/Document.hpp @@ -126,6 +126,7 @@ class Document; class StructureNode; class StructuredEntity; class DocumentPrimitive; +class AnnotationEntity; class Anchor; /** @@ -409,14 +410,13 @@ public: /** * Creates a new Anchor as child of this DocumentEntity. * - * @param name is the Anchor id. * @param fieldName is the name of the field, where the newly created * Anchor shall be added to this DocumentEntity. * * @return the newly created Anchor. */ Rooted<Anchor> createChildAnchor( - std::string name, const std::string &fieldName = DEFAULT_FIELD_NAME); + const std::string &fieldName = DEFAULT_FIELD_NAME); }; /** @@ -577,6 +577,9 @@ public: * Please refer to the AnnotationEntity documentation for more information. */ class Anchor : public StructureNode { +private: + Owned<AnnotationEntity> annotation; + protected: bool doValidate(Logger &logger) const override; @@ -589,15 +592,55 @@ public: * not the AnnotationEntity that references this Anchor. * Note that this Anchor will automatically register itself * as child of the given parent. - * @param name is the Anchor id. * @param fieldName is the name of the field in the parent DocumentEntity * where this Anchor shall be added. */ - Anchor(Manager &mgr, std::string name, Handle<Node> parent, + Anchor(Manager &mgr, Handle<Node> parent, const std::string &fieldName = DEFAULT_FIELD_NAME) - : StructureNode(mgr, std::move(name), parent, fieldName) + : StructureNode(mgr, "", parent, fieldName) { } + + /** + * Returns the AnnotationEntity this Anchor belongs to. + * + * @return the AnnotationEntity this Anchor belongs to. + */ + Rooted<AnnotationEntity> getAnnotation() const { return annotation; } + + /** + * Sets the AnnotationEntity this Anchor belongs to. If this Anchor belonged + * to an AnnotationEntity before already, this reference is removed. This + * also sets the start/end reference of the new AnnotationEntity this Anchor + * shall belong to. + * + * @param anno the new AnnotationEntity this Anchor shall belong to. + * @param start true if this Anchor should be added as start anchor, false + * if it should be added as end Anchor. + */ + void setAnnotation(Handle<AnnotationEntity> anno, bool start); + + /** + * Returns true if and only if this Anchor is the start Anchor of the + * AnnotationEntity it belongs to. Note that this will return false also if + * no AnnotationEntity is set yet. So isStart() == false and isEnd() == + * false is possible and occurs if and only if getAnnotation() == nullptr. + * + * @return true if and only if this Anchor is the start Anchor of the + * AnnotationEntity it belongs to. + */ + bool isStart() const; + + /** + * Returns true if and only if this Anchor is the end Anchor of the + * AnnotationEntity it belongs to. Note that this will return false also if + * no AnnotationEntity is set yet. So isStart() == false and isEnd() == + * false is possible and occurs if and only if getAnnotation() == nullptr. + * + * @return true if and only if this Anchor is the end Anchor of the + * AnnotationEntity it belongs to. + */ + bool isEnd() const; }; /** @@ -679,22 +722,13 @@ public: * * @param s is the new start Anchor for this AnnotationEntity. */ - void setStart(Handle<Anchor> s) - { - invalidate(); - start = acquire(s); - } - + void setStart(Handle<Anchor> s); /** * Sets the end Anchor of this AnnotationEntity. * * @param e is the new end Anchor for this AnnotationEntity. */ - void setEnd(Handle<Anchor> e) - { - invalidate(); - end = acquire(e); - } + void setEnd(Handle<Anchor> e); }; /** |