From 4ee3c4042d267c010babb2ab86e15a6b31950849 Mon Sep 17 00:00:00 2001 From: Andreas Stöckel Date: Tue, 3 Mar 2015 18:23:15 +0100 Subject: added a method to find the matching start anchor for some end anchor. --- src/core/model/Document.cpp | 114 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 112 insertions(+), 2 deletions(-) (limited to 'src/core/model/Document.cpp') 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 DocumentEntity::createChildAnchor(const size_t &fieldIdx) return Rooted{new Anchor(subInst->getManager(), subInst, fieldIdx)}; } +static bool matchStartAnchor(Handle desc, + const std::string &name, Handle a) +{ + return (a->getAnnotation() != nullptr) && + (a->getAnnotation()->getEnd() == nullptr) && + (desc == nullptr || a->getAnnotation()->getDescriptor() == desc) && + (name.empty() || a->getAnnotation()->getName() == name); +} + +template +Rooted DocumentEntity::searchStartAnchorInField( + Handle desc, const std::string &name, Iterator begin, + Iterator end) +{ + for (Iterator it = begin; it != end; it++) { + Handle strct = *it; + if (strct->isa(&RttiTypes::Anchor)) { + // check if this Anchor is the right one. + Handle a = strct.cast(); + if (matchStartAnchor(desc, name, a)) { + return a; + } + continue; + } else if (strct->isa(&RttiTypes::StructuredEntity)) { + // search downwards. + Rooted a = + strct.cast()->searchStartAnchorDownwards( + desc, name); + if (a != nullptr) { + return a; + } + } + } + return nullptr; +} + +Rooted DocumentEntity::searchStartAnchorDownwards( + Handle desc, const std::string &name) +{ + if (fields.empty()) { + return nullptr; + } + // get the default field. + NodeVector children = fields[fields.size() - 1]; + // search it from back to front. + return searchStartAnchorInField(desc, name, children.rbegin(), + children.rend()); +} + +Rooted DocumentEntity::searchStartAnchorUpwards( + Handle desc, const std::string &name, + const DocumentEntity *child) +{ + if (fields.empty()) { + return nullptr; + } + // get the default field. + NodeVector children = fields[fields.size() - 1]; + // search for the child from back to front. + auto it = children.rbegin(); + while (static_cast(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 DocumentEntity::searchStartAnchor(size_t fieldIdx, + Handle desc, + const std::string &name) +{ + // get the correct field. + NodeVector children = fields[fieldIdx]; + // search it from back to front. + Rooted 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() + ->searchStartAnchorUpwards(desc, name, this); + } + if (subInst->getParent()->isa(&RttiTypes::AnnotationEntity)) { + subInst->getParent().cast()->searchStartAnchorUpwards( + desc, name, this); + } + return nullptr; +} + /* Class StructureNode */ bool StructureNode::doValidate(Logger &logger) const @@ -702,7 +808,9 @@ void AnnotationEntity::setStart(Handle s) } invalidate(); start = acquire(s); - s->setAnnotation(this, true); + if (s != nullptr) { + s->setAnnotation(this, true); + } } void AnnotationEntity::setEnd(Handle e) @@ -712,7 +820,9 @@ void AnnotationEntity::setEnd(Handle e) } invalidate(); end = acquire(e); - e->setAnnotation(this, false); + if (e != nullptr) { + e->setAnnotation(this, false); + } } /* Class Document */ -- cgit v1.2.3