diff options
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);  };  /** | 
