Skip to content

v0.2.47..v0.2.48 changeset AttributeValueCriterion.cpp

Garret Voltz edited this page Sep 27, 2019 · 1 revision
diff --git a/hoot-core/src/main/cpp/hoot/core/criterion/AttributeValueCriterion.cpp b/hoot-core/src/main/cpp/hoot/core/criterion/AttributeValueCriterion.cpp
new file mode 100644
index 0000000..c30adda
--- /dev/null
+++ b/hoot-core/src/main/cpp/hoot/core/criterion/AttributeValueCriterion.cpp
@@ -0,0 +1,185 @@
+/*
+ * 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/)
+ */
+#include "AttributeValueCriterion.h"
+
+// hoot
+#include <hoot/core/util/Factory.h>
+#include <hoot/core/elements/OsmUtils.h>
+
+namespace hoot
+{
+
+int AttributeValueCriterion::logWarnCount = 0;
+
+HOOT_FACTORY_REGISTER(ElementCriterion, AttributeValueCriterion)
+
+AttributeValueCriterion::AttributeValueCriterion() :
+_comparisonType(0),
+_isNumericComparison(false)
+{
+}
+
+AttributeValueCriterion::AttributeValueCriterion(const ElementAttributeType& attributeType,
+                                                 const QString& comparisonVal,
+                                                 const TextComparisonType& comparisonType) :
+_attributeType(attributeType),
+_comparisonVal(comparisonVal),
+_comparisonType(comparisonType.getEnum()),
+_isNumericComparison(false)
+{
+  if (_attributeType.getEnum() == ElementAttributeType::Uid ||
+      _attributeType.getEnum() == ElementAttributeType::Version)
+  {
+    throw IllegalArgumentException(
+      "Invalid comparison type: textual, with attribute: " + _attributeType.toString());
+  }
+}
+
+AttributeValueCriterion::AttributeValueCriterion(const ElementAttributeType& attributeType,
+                                                 const double comparisonVal,
+                                                 const NumericComparisonType& comparisonType) :
+_attributeType(attributeType),
+_comparisonVal(comparisonVal),
+_comparisonType(comparisonType.getEnum()),
+_isNumericComparison(true)
+{
+  if (_attributeType.getEnum() == ElementAttributeType::Timestamp ||
+      _attributeType.getEnum() == ElementAttributeType::User)
+  {
+    throw IllegalArgumentException(
+      "Invalid comparison type: numeric, with attribute: " + _attributeType.toString());
+  }
+
+  bool ok = false;
+  _comparisonVal.toDouble(&ok);
+  if (!ok)
+  {
+    throw IllegalArgumentException(
+      "Unable to convert " + _comparisonVal.toString() + " to a numeric value.");
+  }
+}
+
+void AttributeValueCriterion::setConfiguration(const Settings& conf)
+{
+  ConfigOptions configOptions(conf);
+  _attributeType = ElementAttributeType::fromString(configOptions.getAttributeValueCriterionType());
+  QString comparisonTypeStr = configOptions.getAttributeValueCriterionComparisonType();
+  if (comparisonTypeStr.toLower().startsWith("text"))
+  {
+    _comparisonType =
+       TextComparisonType(
+         TextComparisonType::fromString(comparisonTypeStr.remove("text"))).getEnum();
+    _isNumericComparison = false;
+  }
+  else
+  {
+    _comparisonType =
+      NumericComparisonType(
+        NumericComparisonType::fromString(comparisonTypeStr.remove("numeric"))).getEnum();
+    _isNumericComparison = true;
+  }
+  _comparisonVal = configOptions.getAttributeValueCriterionComparisonValue();
+}
+
+bool AttributeValueCriterion::isSatisfied(const ConstElementPtr& e) const
+{
+  switch (_attributeType.getEnum())
+  {
+    case ElementAttributeType::Changeset:
+      return _satisfiesComparison(QVariant((qlonglong)e->getChangeset()));
+    case ElementAttributeType::Timestamp:
+      return _satisfiesComparison(QVariant(OsmUtils::toTimeString(e->getTimestamp())));
+    case ElementAttributeType::User:
+      return _satisfiesComparison(QVariant(e->getUser()));
+    case ElementAttributeType::Uid:
+      return _satisfiesComparison(QVariant((qlonglong)e->getUid()));
+    case ElementAttributeType::Version:
+      return _satisfiesComparison(QVariant((qlonglong)e->getVersion()));
+    default:
+      throw IllegalArgumentException("Invalid attribute type: " + _attributeType.toString());
+  }
+
+  return false;
+}
+
+bool AttributeValueCriterion::_satisfiesComparison(const QVariant& val) const
+{
+  if (_isNumericComparison)
+  {
+    bool ok = false;
+    const double numericVal = val.toDouble(&ok);
+
+    if (!ok)
+    {
+      if (logWarnCount < Log::getWarnMessageLimit())
+      {
+        LOG_WARN("Unable to convert " << val.toString() << " to a numeric value.");
+      }
+      else if (logWarnCount == Log::getWarnMessageLimit())
+      {
+        LOG_WARN(className() << ": " << Log::LOG_WARN_LIMIT_REACHED_MESSAGE);
+      }
+      logWarnCount++;
+      return false;
+    }
+
+    switch (_comparisonType)
+    {
+      case NumericComparisonType::EqualTo:
+        return numericVal == _comparisonVal.toDouble();
+      case NumericComparisonType::LessThan:
+        return numericVal < _comparisonVal.toDouble();
+      case NumericComparisonType::LessThanOrEqualTo:
+        return numericVal <= _comparisonVal.toDouble();
+      case NumericComparisonType::GreaterThan:
+        return numericVal > _comparisonVal.toDouble();
+      case NumericComparisonType::GreaterThanOrEqualTo:
+        return numericVal >= _comparisonVal.toDouble();
+      default:
+        throw IllegalArgumentException("Invalid comparison type: " + _comparisonType);
+    }
+  }
+  else
+  {
+    const QString textVal = val.toString();
+    switch (_comparisonType)
+    {
+      case TextComparisonType::EqualTo:
+        return textVal == _comparisonVal.toString();
+      case TextComparisonType::Contains:
+        return textVal.contains(_comparisonVal.toString());
+      case TextComparisonType::StartsWith:
+        return textVal.startsWith(_comparisonVal.toString());
+      case TextComparisonType::EndsWith:
+        return textVal.endsWith(_comparisonVal.toString());
+      default:
+        throw IllegalArgumentException("Invalid comparison type: " + _comparisonType);
+    }
+  }
+}
+
+}
Clone this wiki locally