-
Notifications
You must be signed in to change notification settings - Fork 74
v0.2.54..v0.2.55 changeset OptionsValidator.cpp
Garret Voltz edited this page Aug 14, 2020
·
1 revision
diff --git a/hoot-core/src/main/cpp/hoot/core/conflate/matching/OptionsValidator.cpp b/hoot-core/src/main/cpp/hoot/core/conflate/matching/OptionsValidator.cpp
new file mode 100644
index 0000000..1128f52
--- /dev/null
+++ b/hoot-core/src/main/cpp/hoot/core/conflate/matching/OptionsValidator.cpp
@@ -0,0 +1,252 @@
+/*
+ * 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) 2020 DigitalGlobe (http://www.digitalglobe.com/)
+ */
+#include "OptionsValidator.h"
+
+// hoot
+#include <hoot/core/util/StringUtils.h>
+#include <hoot/core/util/Log.h>
+#include <hoot/core/util/HootException.h>
+
+namespace hoot
+{
+
+bool OptionsValidator::_isGenericMatcher(const QString& matcher)
+{
+ // obviously this isn't extensible, but we'll just have to deal with that for now...the list may
+ // never change, though
+ QStringList genericMatchScripts;
+ genericMatchScripts.append("Point.js");
+ genericMatchScripts.append("Line.js");
+ genericMatchScripts.append("Polygon.js");
+ genericMatchScripts.append("PointPolygon.js");
+ return StringUtils::containsSubstrings(QStringList(matcher), genericMatchScripts);
+}
+
+bool OptionsValidator::_containsGenericMatcher(const QStringList& matchers)
+{
+ for (int i = 0; i < matchers.size(); i++)
+ {
+ if (_isGenericMatcher(matchers.at(i)))
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+void OptionsValidator::fixMisc()
+{
+ LOG_DEBUG("Fixing miscellaneous...");
+
+ QStringList matchCreators = ConfigOptions().getMatchCreators();
+ QStringList mergerCreators = ConfigOptions().getMergerCreators();
+ LOG_VART(matchCreators);
+ LOG_VART(mergerCreators);
+
+ if ((matchCreators.size() == 0 || mergerCreators.size() == 0))
+ {
+ LOG_WARN("Match or merger creators empty. Setting to defaults.");
+ matchCreators = ConfigOptions::getMatchCreatorsDefaultValue();
+ mergerCreators = ConfigOptions::getMergerCreatorsDefaultValue();
+ }
+
+ // We could also do something here even when the sizes are equal but not doing that yet, since
+ // the issue should be fixed in the UI soon.
+ if (matchCreators.size() != mergerCreators.size())
+ {
+ //going to make the mergers match whatever the matchers are
+ QStringList fixedMergerCreators;
+ for (int i = 0; i < matchCreators.size(); i++)
+ {
+ const QString matchCreator = matchCreators.at(i);
+ if (matchCreator == "hoot::BuildingMatchCreator")
+ {
+ fixedMergerCreators.append("hoot::BuildingMergerCreator");
+ }
+ else if (matchCreator.contains("hoot::ScriptMatchCreator"))
+ {
+ fixedMergerCreators.append("hoot::ScriptMergerCreator");
+ }
+ else if (matchCreator == "hoot::HighwayMatchCreator")
+ {
+ fixedMergerCreators.append("hoot::HighwayMergerCreator");
+ }
+ else if (matchCreator == "hoot::NetworkMatchCreator")
+ {
+ fixedMergerCreators.append("hoot::NetworkMergerCreator");
+ }
+ else if (matchCreator == "hoot::PoiPolygonMatchCreator")
+ {
+ fixedMergerCreators.append("hoot::PoiPolygonMergerCreator");
+ }
+ }
+ conf().set("merger.creators", fixedMergerCreators.join(";"));
+ }
+ LOG_VART(matchCreators);
+ LOG_VART(mergerCreators);
+
+ //fix way subline matcher options - https://github.com/ngageoint/hootenanny-ui/issues/970
+ if (matchCreators.contains("hoot::NetworkMatchCreator") &&
+ ConfigOptions().getWaySublineMatcher() != "hoot::FrechetSublineMatcher" &&
+ ConfigOptions().getWaySublineMatcher() != "hoot::MaximalSublineMatcher")
+ {
+ LOG_TRACE("Temp fixing way.subline.matcher...");
+ conf().set("way.subline.matcher", "hoot::MaximalSublineMatcher");
+ }
+ else if (matchCreators.contains("hoot::HighwayMatchCreator") &&
+ ConfigOptions().getWaySublineMatcher() != "hoot::FrechetSublineMatcher" &&
+ ConfigOptions().getWaySublineMatcher() != "hoot::MaximalNearestSublineMatcher")
+ {
+ LOG_TRACE("Temp fixing way.subline.matcher...");
+ conf().set("way.subline.matcher", "hoot::MaximalNearestSublineMatcher");
+ }
+ LOG_VART(ConfigOptions().getWaySublineMatcher());
+
+ //fix highway classifier - https://github.com/ngageoint/hootenanny-ui/issues/971
+ if (matchCreators.contains("hoot::NetworkMatchCreator") &&
+ ConfigOptions().getConflateMatchHighwayClassifier() != "hoot::HighwayExpertClassifier")
+ {
+ LOG_TRACE("Temp fixing conflate.match.highway.classifier...");
+ conf().set("conflate.match.highway.classifier", "hoot::HighwayExpertClassifier");
+ }
+ else if (matchCreators.contains("hoot::HighwayMatchCreator") &&
+ ConfigOptions().getConflateMatchHighwayClassifier() != "hoot::HighwayRfClassifier")
+ {
+ LOG_TRACE("Temp fixing conflate.match.highway.classifier...");
+ conf().set("conflate.match.highway.classifier", "hoot::HighwayRfClassifier");
+ }
+ LOG_VART(ConfigOptions().getConflateMatchHighwayClassifier());
+}
+
+void OptionsValidator::fixGenericMatcherOrdering()
+{
+ LOG_DEBUG("Fixing generic matcher ordering...");
+
+ QStringList matchCreators = ConfigOptions().getMatchCreators();
+ QStringList mergerCreators = ConfigOptions().getMergerCreators();
+ LOG_VART(matchCreators);
+ LOG_VART(mergerCreators);
+ assert(matchCreators.size() == mergerCreators.size());
+
+ // fix matchers/mergers - https://github.com/ngageoint/hootenanny-ui/issues/972,
+ // https://github.com/ngageoint/hootenanny-ui/issues/1764
+
+ // At this time we always want the generic matchers at the end, just before CollectionRelation.js,
+ // if they're present. So, don't even check to see if they're in the right order...just move them
+ // anyway. There overall order will be maintained, but they'll just be towards the end. We'll
+ // assume the corresponding merger for each is in the correct order and move it as well.
+ if (_containsGenericMatcher(matchCreators))
+ {
+ QStringList fixedMatchCreators = matchCreators;
+ QStringList fixedMergerCreators = mergerCreators;
+ LOG_VART(fixedMatchCreators);
+ LOG_VART(fixedMergerCreators);
+ for (int i = 0; i < matchCreators.size(); i++)
+ {
+ const QString matchCreator = matchCreators.at(i);
+ LOG_VART(matchCreator);
+ if (_isGenericMatcher(matchCreator))
+ {
+ LOG_VART(i);
+ const int fixedCreatorIndex = fixedMatchCreators.indexOf(matchCreator);
+ LOG_VART(fixedCreatorIndex);
+ fixedMatchCreators.move(fixedCreatorIndex, fixedMatchCreators.size() - 1);
+ fixedMergerCreators.move(fixedCreatorIndex, fixedMergerCreators.size() - 1);
+ LOG_VART(fixedMatchCreators);
+ LOG_VART(fixedMergerCreators);
+ }
+ }
+ conf().set("match.creators", fixedMatchCreators.join(";"));
+ conf().set("merger.creators", fixedMergerCreators.join(";"));
+ matchCreators = ConfigOptions().getMatchCreators();
+ mergerCreators = ConfigOptions().getMergerCreators();
+ }
+ LOG_VART(matchCreators);
+ LOG_VART(mergerCreators);
+
+ // now move CollectionRelation.js
+ const QString collectionRelationScript = "CollectionRelation.js";
+ if (StringUtils::containsSubstring(matchCreators, collectionRelationScript))
+ {
+ const int collectionRelationIndex =
+ StringUtils::indexOfSubstring(matchCreators, collectionRelationScript);
+ LOG_VART(collectionRelationIndex);
+ if (collectionRelationIndex < (matchCreators.size() - 1))
+ {
+ matchCreators.move(collectionRelationIndex, matchCreators.size() - 1);
+ mergerCreators.move(collectionRelationIndex, mergerCreators.size() - 1);
+ conf().set("match.creators", matchCreators.join(";"));
+ conf().set("merger.creators", mergerCreators.join(";"));
+ LOG_VART(matchCreators);
+ LOG_VART(mergerCreators);
+ }
+ }
+ LOG_VART(matchCreators);
+ LOG_VART(mergerCreators);
+}
+
+void OptionsValidator::validateMatchers()
+{
+ LOG_DEBUG("Validating matchers...");
+
+ const QStringList matchCreators = ConfigOptions().getMatchCreators();
+ const QStringList mergerCreators = ConfigOptions().getMergerCreators();
+ LOG_VART(matchCreators);
+ LOG_VART(mergerCreators);
+
+ if (matchCreators.isEmpty() || mergerCreators.isEmpty())
+ {
+ // This gets temp fixed in fixMisc, if needed.
+ throw IllegalArgumentException("Empty matcher or merger list specified.");
+ }
+ else if (matchCreators.size() != mergerCreators.size())
+ {
+ // This gets temp fixed in fixMisc, if needed.
+ throw HootException(
+ "The number of configured match creators (" + QString::number(matchCreators.size()) +
+ ") does not equal the number of configured merger creators (" +
+ QString::number(mergerCreators.size()) + ")");
+ }
+
+ for (int i = 0; i < matchCreators.size(); i++)
+ {
+ const QString matchCreator = matchCreators.at(i);
+ const QString mergerCreator = mergerCreators.at(i);
+ // Currently, there is only one kind of ScriptMergerCreator, so this check is useful for finding
+ // misuses of the generic conflation engine. If we add any more script merger creators, we'll
+ // need a better check.
+ if (matchCreator.startsWith("hoot::ScriptMatchCreator") &&
+ mergerCreator != "hoot::ScriptMergerCreator")
+ {
+ throw HootException(
+ "Attempted to use a ScriptMatchCreator without a ScriptMergerCreator. Match creator: " +
+ matchCreator + QString(" Merger creator: ") + mergerCreator);
+ }
+ }
+}
+
+}