void RemoveDuplicateReviewsOp::apply(shared_ptr<OsmMap>& map) { _map = map; // go through all the relations to get duplicate reviews const RelationMap& relations = map->getRelationMap(); QMap< set<ElementId>, QList<ReviewMarker::ReviewUid> > membersToReview; for (RelationMap::const_iterator it = relations.begin(); it != relations.end(); it++) { ElementId eid = ElementId::relation(it->first); if (ReviewMarker::isReviewUid(map, eid)) { membersToReview[ReviewMarker::getReviewElements(map, eid)].append(eid); } } //loop through dupplicate reviews QMap< set<ElementId>, QList<ReviewMarker::ReviewUid> >::iterator it = membersToReview.begin(); while (it != membersToReview.end()) { set<ElementId> eids = it.key(); //remove duplicate reviews QList<ReviewMarker::ReviewUid> duplicateReviews = it.value(); //Only remove reviews and process if there is more than one review // See discussion here: https://github.com/ngageoint/hootenanny/issues/81#issuecomment-162980656 if (eids.size() == 2 && duplicateReviews.size() > 1) { for (int i = 0; i < duplicateReviews.size(); i++) { ReviewMarker::removeElement(map, duplicateReviews[i]); } ElementId beid = *eids.begin(); ElementId eeid = *eids.rbegin(); OsmMapPtr copy(new OsmMap()); CopySubsetOp(map, beid, eeid).apply(copy); copy->getElement(beid)->setStatus(Status::Unknown1); copy->getElement(eeid)->setStatus(Status::Unknown2); Match* match = MatchFactory::getInstance().createMatch(copy, beid, eeid); if (match && match->getType() != MatchType::Miss) { QString explain = match->explain(); if (match->getType() == MatchType::Match) { if (explain.isEmpty()) { explain = "Multiple overlapping high confidence reviews"; } else { explain = "Multiple overlapping high confidence reviews: " + explain; } } ReviewMarker::mark(map, map->getElement(beid), map->getElement(eeid), explain, match->getMatchName(), match->getClassification().getReviewP()); } } ++it; } }
bool ScriptMatch::isConflicting(const Match& other, const ConstOsmMapPtr& map) const { if (_neverCausesConflict) { return false; } bool conflicting = true; const ScriptMatch* hm = dynamic_cast<const ScriptMatch*>(&other); if (hm == 0) { return true; } if (hm == this) { return false; } // See ticket #5272 if (getClassification().getReviewP() == 1.0 || other.getClassification().getReviewP() == 1.0) { return true; } ElementId sharedEid; if (_eid1 == hm->_eid1 || _eid1 == hm->_eid2) { sharedEid = _eid1; } if (_eid2 == hm->_eid1 || _eid2 == hm->_eid2) { // both eids should never be the same. assert(sharedEid.isNull()); sharedEid = _eid2; } // if the matches don't share at least one eid then it isn't a conflict. if (sharedEid.isNull()) { return false; } // assign o1 and o2 to the non-shared eids ElementId o1 = _eid1 == sharedEid ? _eid2 : _eid1; ElementId o2 = hm->_eid1 == sharedEid ? hm->_eid2 : hm->_eid1; bool foundCache = false; bool cacheConflict = false; QHash<ConflictKey, bool>::const_iterator cit1 = _conflicts.find(hm->_getConflictKey()); if (cit1 != _conflicts.end()) { foundCache = true; cacheConflict = cit1.value(); } QHash<ConflictKey, bool>::const_iterator cit2 = hm->_conflicts.find(_getConflictKey()); if (cit2 != hm->_conflicts.end()) { foundCache = true; cacheConflict = cit2.value(); } if (foundCache) { conflicting = cacheConflict; } else { try { // we need to check for a conflict in two directions. Is it conflicting if we merge the shared // EID with this class first, then is it a conflict if we merge with the other EID first. if (_isOrderedConflicting(map, sharedEid, o1, o2) || hm->_isOrderedConflicting(map, sharedEid, o2, o1)) { conflicting = true; } else { conflicting = false; } } catch (const NeedsReviewException& e) { conflicting = true; } _conflicts[hm->_getConflictKey()] = conflicting; } return conflicting; }