diff options
author | Andreas Stöckel <astoecke@techfak.uni-bielefeld.de> | 2015-03-03 18:23:15 +0100 |
---|---|---|
committer | Andreas Stöckel <andreas@somweyr.de> | 2015-03-03 18:23:15 +0100 |
commit | 4ee3c4042d267c010babb2ab86e15a6b31950849 (patch) | |
tree | c4204e0504de047cecf239f10e68e17246f99e8f /src/core/model/Document.cpp | |
parent | f6b22312127f29f71aa26ca28142ad3e5f193445 (diff) |
added a method to find the matching start anchor for some end anchor.
Diffstat (limited to 'src/core/model/Document.cpp')
-rw-r--r-- | src/core/model/Document.cpp | 114 |
1 files changed, 112 insertions, 2 deletions
diff --git a/src/core/model/Document.cpp b/src/core/model/Document.cpp index b29767e..62dad11 100644 --- a/src/core/model/Document.cpp +++ b/src/core/model/Document.cpp @@ -452,6 +452,112 @@ Rooted<Anchor> DocumentEntity::createChildAnchor(const size_t &fieldIdx) return Rooted<Anchor>{new Anchor(subInst->getManager(), subInst, fieldIdx)}; } +static bool matchStartAnchor(Handle<AnnotationClass> desc, + const std::string &name, Handle<Anchor> a) +{ + return (a->getAnnotation() != nullptr) && + (a->getAnnotation()->getEnd() == nullptr) && + (desc == nullptr || a->getAnnotation()->getDescriptor() == desc) && + (name.empty() || a->getAnnotation()->getName() == name); +} + +template <typename Iterator> +Rooted<Anchor> DocumentEntity::searchStartAnchorInField( + Handle<AnnotationClass> desc, const std::string &name, Iterator begin, + Iterator end) +{ + for (Iterator it = begin; it != end; it++) { + Handle<StructureNode> strct = *it; + if (strct->isa(&RttiTypes::Anchor)) { + // check if this Anchor is the right one. + Handle<Anchor> a = strct.cast<Anchor>(); + if (matchStartAnchor(desc, name, a)) { + return a; + } + continue; + } else if (strct->isa(&RttiTypes::StructuredEntity)) { + // search downwards. + Rooted<Anchor> a = + strct.cast<StructuredEntity>()->searchStartAnchorDownwards( + desc, name); + if (a != nullptr) { + return a; + } + } + } + return nullptr; +} + +Rooted<Anchor> DocumentEntity::searchStartAnchorDownwards( + Handle<AnnotationClass> desc, const std::string &name) +{ + if (fields.empty()) { + return nullptr; + } + // get the default field. + NodeVector<StructureNode> children = fields[fields.size() - 1]; + // search it from back to front. + return searchStartAnchorInField(desc, name, children.rbegin(), + children.rend()); +} + +Rooted<Anchor> DocumentEntity::searchStartAnchorUpwards( + Handle<AnnotationClass> desc, const std::string &name, + const DocumentEntity *child) +{ + if (fields.empty()) { + return nullptr; + } + // get the default field. + NodeVector<StructureNode> children = fields[fields.size() - 1]; + // search for the child from back to front. + auto it = children.rbegin(); + while (static_cast<void *>(it->get()) != child->subInst.get() && + it != children.rend()) { + it++; + } + // increment the reverse iterator once more to prevent downwards search + // to the child. + if (it != children.rend()) { + it++; + return searchStartAnchorInField(desc, name, it, children.rend()); + } + throw OusiaException("Internal error: Child node not found in parent!"); +} + +Rooted<Anchor> DocumentEntity::searchStartAnchor(size_t fieldIdx, + Handle<AnnotationClass> desc, + const std::string &name) +{ + // get the correct field. + NodeVector<StructureNode> children = fields[fieldIdx]; + // search it from back to front. + Rooted<Anchor> a = searchStartAnchorInField(desc, name, children.rbegin(), + children.rend()); + // if we found the Anchor, return it. + if (a != nullptr) { + return a; + } + + // If this is either an AnnotationEntity or a SUBTREE field we can not + // search upwards. + if (subInst->isa(&RttiTypes::AnnotationEntity) || + fieldIdx + 1 < fields.size()) { + return nullptr; + } + // if the children here did not contain the right start Anchor go upwards. + if (subInst->getParent()->isa(&RttiTypes::StructuredEntity)) { + return subInst->getParent() + .cast<StructuredEntity>() + ->searchStartAnchorUpwards(desc, name, this); + } + if (subInst->getParent()->isa(&RttiTypes::AnnotationEntity)) { + subInst->getParent().cast<AnnotationEntity>()->searchStartAnchorUpwards( + desc, name, this); + } + return nullptr; +} + /* Class StructureNode */ bool StructureNode::doValidate(Logger &logger) const @@ -702,7 +808,9 @@ void AnnotationEntity::setStart(Handle<Anchor> s) } invalidate(); start = acquire(s); - s->setAnnotation(this, true); + if (s != nullptr) { + s->setAnnotation(this, true); + } } void AnnotationEntity::setEnd(Handle<Anchor> e) @@ -712,7 +820,9 @@ void AnnotationEntity::setEnd(Handle<Anchor> e) } invalidate(); end = acquire(e); - e->setAnnotation(this, false); + if (e != nullptr) { + e->setAnnotation(this, false); + } } /* Class Document */ |