Skip to content

v0.2.49..v0.2.50 changeset ManualMatchValidator.h

Garret Voltz edited this page Nov 6, 2019 · 1 revision
diff --git a/hoot-core/src/main/cpp/hoot/core/ops/ManualMatchValidator.h b/hoot-core/src/main/cpp/hoot/core/ops/ManualMatchValidator.h
new file mode 100644
index 0000000..20578e3
--- /dev/null
+++ b/hoot-core/src/main/cpp/hoot/core/ops/ManualMatchValidator.h
@@ -0,0 +1,139 @@
+/*
+ * This file is part of Hootenanny.
+ *
+ * Hootenanny is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * --------------------------------------------------------------------
+ *
+ * The following copyright notices are generated automatically. If you
+ * have a new notice to add, please use the format:
+ * " * @copyright Copyright ..."
+ * This will properly maintain the copyright information. DigitalGlobe
+ * copyrights will be updated automatically.
+ *
+ * @copyright Copyright (C) 2019 DigitalGlobe (http://www.digitalglobe.com/)
+ */
+#ifndef MANUAL_MATCH_VALIDATOR_H
+#define MANUAL_MATCH_VALIDATOR_H
+
+// Hoot
+#include <hoot/core/elements/OsmMap.h>
+#include <hoot/core/ops/ConstOsmMapOperation.h>
+#include <hoot/core/info/OperationStatusInfo.h>
+#include <hoot/core/visitors/ElementIdToTagValueMapper.h>
+
+namespace hoot
+{
+
+/**
+ * Finds errors in manual matches made by a human that are to be scored against hoot conflation
+ * with the score-matches command
+ *
+ * A note on _requireRef1:
+ *
+ * If a regression test already exists where the input data has been cropped and the cropping
+ * split any features, you will end up with missing ref1 tags. One remedy may be to re-create the
+ * cropped input data with crop.keep.entire.features.crossing.bounds=true, but this might resut in
+ * larger inputs than you want. If the manual matches are dense, it might not work anyway. If
+ * re-creating the input data is not an option (input data created before this class was integrated
+ * with score-matches, etc.), then you can change the validator to only log warnings, which allows
+ * score-matches to proceed with missing ref1's by setting _requireRef1=false;
+ */
+class ManualMatchValidator : public ConstOsmMapOperation, public OperationStatusInfo
+{
+public:
+
+  static std::string className() { return "hoot::ManualMatchValidator"; }
+
+  ManualMatchValidator();
+
+  /**
+   * Validates all manual matches in the map and records the first error found for each element
+   *
+   * @param map
+   */
+  virtual void apply(const OsmMapPtr& map);
+
+  virtual QString getDescription() const { return "Validates manual matches"; }
+
+  virtual QString getInitStatusMessage() const
+  { return "Validating manual matches..."; }
+
+  virtual QString getCompletedStatusMessage() const
+  { return "Validated " + QString::number(_numAffected) + " manual matches"; }
+
+  /**
+   * Returns found errors grouped by element ID (up to one for each element)
+   *
+   * @return a collection of errors
+   */
+  QMap<ElementId, QString> getErrors() const { return _errors; }
+
+  /**
+   * Returns found warnings grouped by element ID (up to one for each element)
+   *
+   * @return a collection of warnings
+   */
+  QMap<ElementId, QString> getWarnings() const { return _warnings; }
+
+  /**
+   * Determines if any errors were found by validation
+   *
+   * @return true if any errors were found; false otherwise
+   */
+  bool hasErrors() const { return _errors.size() > 0; }
+
+  /**
+   * Determines if any warnings were found by validation
+   *
+   * @return true if any errors were found; false otherwise
+   */
+  bool hasWarnings() const { return _warnings.size() > 0; }
+
+  void setRequireRef1(bool require) { _requireRef1 = require; }
+  void setAllowUuidManualMatchIds(bool allow) { _allowUuidManualMatchIds = allow; }
+  void setFullDebugOutput(bool fullDebugOutput) { _fullDebugOutput = fullDebugOutput; }
+
+private:
+
+  QMap<ElementId, QString> _errors;
+  QMap<ElementId, QString> _warnings;
+  ElementIdToTagValueMapper _ref1Mappings;
+
+  // if true, every ref2/review id must have a correponding ref1 id in order to not trigger an error
+  bool _requireRef1;
+
+  // The original manual matching implementation used uuids as ids instead of the 6 char hex used
+  // now, since manual matchers found the uuids a little unwieldy. There are still some regression
+  // tests with the uuid ids, so to avoid the cost of redoing the matches we'll support them on a
+  // case by case basis.
+  bool _allowUuidManualMatchIds;
+  QRegExp _uuidRegEx;
+
+  // TODO
+  bool _fullDebugOutput;
+
+  void _validate(const ConstElementPtr& element);
+
+  bool _isValidRef1Id(const QString& matchId) const;
+  bool _isValidRef2OrReviewId(const QString& matchId) const;
+  bool _isValidUniqueMatchId(const QString& matchId) const;
+  bool _isValidNonUniqueMatchId(const QString& matchId) const;
+
+  void _recordIssue(const ConstElementPtr& element, QString message, const bool isError = true);
+};
+
+}
+
+#endif // MANUAL_MATCH_VALIDATOR_H
Clone this wiki locally