summaryrefslogtreecommitdiff
path: root/src/core/model
diff options
context:
space:
mode:
authorBenjamin Paassen <bpaassen@techfak.uni-bielefeld.de>2015-02-12 11:33:01 +0100
committerBenjamin Paassen <bpaassen@techfak.uni-bielefeld.de>2015-02-12 11:33:01 +0100
commitebac41111fa33790acce7be45e599f8de37e7f43 (patch)
treef23a5875d30d28c35e5a8e352856f5f9a9ef7cf2 /src/core/model
parentdbf2eebdd88118dca79045ad0524061f8078e668 (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.cpp112
-rw-r--r--src/core/model/Document.hpp66
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);
};
/**