Skip to content

v0.2.54..v0.2.55 changeset TagComparator.cpp

Garret Voltz edited this page Aug 14, 2020 · 1 revision
diff --git a/hoot-core/src/main/cpp/hoot/core/schema/TagComparator.cpp b/hoot-core/src/main/cpp/hoot/core/schema/TagComparator.cpp
index dbb1dbf..2e0d291 100644
--- a/hoot-core/src/main/cpp/hoot/core/schema/TagComparator.cpp
+++ b/hoot-core/src/main/cpp/hoot/core/schema/TagComparator.cpp
@@ -22,7 +22,7 @@
  * This will properly maintain the copyright information. DigitalGlobe
  * copyrights will be updated automatically.
  *
- * @copyright Copyright (C) 2015, 2016, 2017, 2018, 2019 DigitalGlobe (http://www.digitalglobe.com/)
+ * @copyright Copyright (C) 2015, 2016, 2017, 2018, 2019, 2020 DigitalGlobe (http://www.digitalglobe.com/)
  */
 
 #include "TagComparator.h"
@@ -46,8 +46,6 @@ using namespace std;
 namespace hoot
 {
 
-std::shared_ptr<TagComparator> TagComparator::_theInstance;
-
 struct Entry
 {
   int i, j;
@@ -59,13 +57,6 @@ struct Entry
   }
 };
 
-TagComparator::TagComparator() :
-_caseSensitive(false)
-{
-  ConfigOptions opts(conf());
-  setCaseSensitive(opts.getDuplicateNameCaseSensitive());
-}
-
 void TagComparator::_addAsDefault(Tags& t, const QString& key, const QString& value)
 {
   if (t.contains(key) == false || t[key].isEmpty() == true)
@@ -116,13 +107,13 @@ void TagComparator::_addNonConflictingTags(Tags& t1, const Tags& t2, Tags& resul
 }
 
 void TagComparator::averageTags(const Tags& t1, const Tags& t2, Tags& result,
-                                bool keepAllUnknownTags)
+                                bool keepAllUnknownTags, bool caseSensitive)
 {
-  averageTags(t1, 1.0, t2, 1.0, result, keepAllUnknownTags);
+  averageTags(t1, 1.0, t2, 1.0, result, keepAllUnknownTags, caseSensitive);
 }
 
 void TagComparator::averageTags(const Tags& t1In, double w1, const Tags& t2In, double w2,
-                                Tags& result, bool keepAllUnknownTags)
+                                Tags& result, bool keepAllUnknownTags, bool caseSensitive)
 {
   result.clear();
   OsmSchema& schema = OsmSchema::getInstance();
@@ -132,10 +123,10 @@ void TagComparator::averageTags(const Tags& t1In, double w1, const Tags& t2In, d
 
   set<QString> k1, k2;
 
-  mergeNames(t1, t2, result);
+  mergeNames(t1, t2, result, QStringList()/*FIXEME*/, caseSensitive);
 
   // Merge any text fields by concatenating the lists.
-  mergeText(t1, t2, result);
+  mergeText(t1, t2, result, QStringList()/*FIXEME*/, caseSensitive);
 
   if (keepAllUnknownTags)
   {
@@ -418,10 +409,10 @@ double TagComparator::compareTags(const Tags &t1, const Tags &t2, bool strict)
   }
 }
 
-bool TagComparator::nonNameTagsExactlyMatch(const Tags& t1, const Tags& t2)
+bool TagComparator::nonNameTagsExactlyMatch(const Tags& t1, const Tags& t2, bool caseSensitive)
 {
   const Qt::CaseSensitivity caseSensitivity =
-    _caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive;
+    caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive;
 
   Tags t1Filtered;
   for (Tags::const_iterator it1 = t1.begin(); it1 != t1.end(); ++it1)
@@ -433,7 +424,7 @@ bool TagComparator::nonNameTagsExactlyMatch(const Tags& t1, const Tags& t2)
         //case check needed.
         !OsmSchema::getInstance().isMetaData(key, value))
     {
-      if (!_caseSensitive)
+      if (!caseSensitive)
       {
         key = key.toUpper();
         value = value.toUpper();
@@ -450,7 +441,7 @@ bool TagComparator::nonNameTagsExactlyMatch(const Tags& t1, const Tags& t2)
     if (!Tags::getNameKeys().contains(key, caseSensitivity) &&
         !OsmSchema::getInstance().isMetaData(key, value))
     {
-      if (!_caseSensitive)
+      if (!caseSensitive)
       {
         key = key.toUpper();
         value = value.toUpper();
@@ -464,26 +455,25 @@ bool TagComparator::nonNameTagsExactlyMatch(const Tags& t1, const Tags& t2)
 
 TagComparator& TagComparator::getInstance()
 {
-  if (_theInstance == NULL)
-  {
-    _theInstance.reset(new TagComparator());
-  }
-  return *_theInstance;
+  //  Local static singleton instance
+  static TagComparator instance;
+  return instance;
 }
 
-// NOTE: I'm not using const references b/c I'd have to copy anyways.
-Tags TagComparator::generalize(Tags t1, Tags t2, bool overwriteUnrecognizedTags)
+Tags TagComparator::generalize(Tags t1, Tags t2, bool overwriteUnrecognizedTags, bool caseSensitive)
 {
+  // NOTE: Not using const references on the inputs b/c we'd have to copy anyway.
+
   Tags result;
 
   // Names are merged using _mergeNames.
-  mergeNames(t1, t2, result);
+  mergeNames(t1, t2, result, QStringList()/*FIXEME*/, caseSensitive);
 
   // Exact matches are unchanged
   _mergeExactMatches(t1, t2, result);
 
   // Merge any text fields by adding to a list.
-  mergeText(t1, t2, result);
+  mergeText(t1, t2, result, QStringList()/*FIXEME*/, caseSensitive);
 
   // Unrecognized tags are concatenated in a list.
   if (overwriteUnrecognizedTags)
@@ -543,7 +533,7 @@ void TagComparator::_mergeExactMatches(Tags& t1, Tags& t2, Tags& result)
 }
 
 void TagComparator::mergeNames(Tags& t1, Tags& t2, Tags& result,
-                               const QStringList& overwriteExcludeTagKeys)
+                               const QStringList& overwriteExcludeTagKeys, bool caseSensitive)
 {
   LOG_TRACE("Merging names...");
   LOG_VART(t1);
@@ -554,15 +544,15 @@ void TagComparator::mergeNames(Tags& t1, Tags& t2, Tags& result,
   set<QString> altNames, nonAltNames;
   set<QString> toRemove;
   const Qt::CaseSensitivity caseSensitivity =
-    _caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive;
-  LOG_VART(_caseSensitive);
+    caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive;
+  LOG_VART(caseSensitive);
 
   toRemove.insert("alt_name");
 
   for (Tags::const_iterator it1 = t1.begin(); it1 != t1.end(); ++it1)
   {
-    LOG_VART(it1.key());
-    LOG_VART(it1.value());
+    //LOG_VART(it1.key());
+    //LOG_VART(it1.value());
     if (it1.key() == "alt_name" && !overwriteExcludeTagKeys.contains("alt_name"))
     {
       QStringList sl = Tags::split(it1.value());
@@ -578,15 +568,15 @@ void TagComparator::mergeNames(Tags& t1, Tags& t2, Tags& result,
       toRemove.insert(it1.key());
     }
   }
-  LOG_VART(altNames);
-  LOG_VART(nonAltNames);
-  LOG_VART(toRemove);
-  LOG_VART(result);
+//  LOG_VART(altNames);
+//  LOG_VART(nonAltNames);
+//  LOG_VART(toRemove);
+//  LOG_VART(result);
 
   for (Tags::const_iterator it2 = t2.begin(); it2 != t2.end(); ++it2)
   {
-    LOG_VART(it2.key());
-    LOG_VART(it2.value());
+    //LOG_VART(it2.key());
+    //LOG_VART(it2.value());
     if (it2.key() == "alt_name")
     {
       QStringList sl = Tags::split(it2.value());
@@ -608,18 +598,18 @@ void TagComparator::mergeNames(Tags& t1, Tags& t2, Tags& result,
       toRemove.insert(it2.key());
     }
   }
-  LOG_VART(altNames);
-  LOG_VART(nonAltNames);
-  LOG_VART(toRemove);
-  LOG_VART(result);
+//  LOG_VART(altNames);
+//  LOG_VART(nonAltNames);
+//  LOG_VART(toRemove);
+//  LOG_VART(result);
 
   for (set<QString>::const_iterator it = toRemove.begin(); it != toRemove.end(); ++it)
   {
     t1.remove(*it);
     t2.remove(*it);
   }
-  LOG_VART(t1);
-  LOG_VART(t2);
+//  LOG_VART(t1);
+//  LOG_VART(t2);
 
   // add all the altNames that don't exist in nonAltNames
   QStringList l;
@@ -630,7 +620,7 @@ void TagComparator::mergeNames(Tags& t1, Tags& t2, Tags& result,
       l.append(*it);
     }
   }
-  LOG_VART(l);
+  //LOG_VART(l);
 
   if (l.size() > 0)
   {
@@ -640,7 +630,8 @@ void TagComparator::mergeNames(Tags& t1, Tags& t2, Tags& result,
 }
 
 void TagComparator::mergeText(Tags& t1, Tags& t2, Tags& result,
-                              const QStringList& overwriteExcludeTagKeys)
+                              const QStringList& overwriteExcludeTagKeys,
+                              bool caseSensitive)
 {
   LOG_TRACE("Merging text...");
   LOG_VART(t1);
@@ -657,32 +648,32 @@ void TagComparator::mergeText(Tags& t1, Tags& t2, Tags& result,
     {
       // only keep the unique text fields
       QStringList values1 = t1.getList(it1.key());
-      LOG_VART(values1);
+      //LOG_VART(values1);
       QStringList values2 = t2.getList(it1.key());
-      LOG_VART(values2);
+      //LOG_VART(values2);
 
       // append all unique values in the existing order; don't overwrite tags in t2 that are in the
       // exclude list
       const Qt::CaseSensitivity caseSensitivity =
-        _caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive;
+        caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive;
       for (int i = 0; i < values1.size(); i++)
       {
-        LOG_VART(values1[i]);
+        //LOG_VART(values1[i]);
         if (values1[i].isEmpty() == false &&
             (!t2.contains(it1.key()) ||
              !overwriteExcludeTagKeys.contains(it1.key(), caseSensitivity)))
         {
           result.appendValueIfUnique(it1.key(), values1[i]);
-          LOG_VART(result);
+          //LOG_VART(result);
         }
       }
       for (int i = 0; i < values2.size(); i++)
       {
-        LOG_VART(values2[i]);
+        //LOG_VART(values2[i]);
         if (values2[i].isEmpty() == false)
         {
           result.appendValueIfUnique(it1.key(), values2[i]);
-          LOG_VART(result);
+          //LOG_VART(result);
         }
       }
 
@@ -741,24 +732,53 @@ void TagComparator::_mergeUnrecognizedTags(Tags& t1, Tags& t2, Tags& result)
   }
 }
 
-Tags TagComparator::overwriteMerge(Tags t1, Tags t2, const QStringList& overwriteExcludeTagKeys)
+Tags TagComparator::overwriteMerge(Tags t1, Tags t2, const QStringList& overwriteExcludeTagKeys, bool caseSensitive)
 { 
   Tags result;
 
   // Names are merged using _mergeNames.
-  mergeNames(t1, t2, result, overwriteExcludeTagKeys);
+  mergeNames(t1, t2, result, overwriteExcludeTagKeys, caseSensitive);
 
   // concatenate the known text fields (e.g. note)
-  mergeText(t1, t2, result, overwriteExcludeTagKeys);
+  mergeText(t1, t2, result, overwriteExcludeTagKeys, caseSensitive);
 
   // use the tags in t1 first, then fall back to tags in t2
-  _overwriteRemainingTags(t1, t2, result, overwriteExcludeTagKeys);
+  _overwriteRemainingTags(t1, t2, result, overwriteExcludeTagKeys, caseSensitive);
+
+  return result;
+}
+
+Tags TagComparator::replaceMerge(const Tags& t1, const Tags& t2,
+                                 const QStringList& overwriteExcludeTagKeys,
+                                 bool caseSensitive)
+{
+  Tags result;
+
+  // We're keeping t1, so start with them as the result.
+  result = t1;
+
+  // Now see if there are any configurd exclusions we should keep from t2.
+  if (overwriteExcludeTagKeys.size() > 0)
+  {
+    const Qt::CaseSensitivity caseSensitivity =
+      caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive;
+    for (Tags::ConstIterator it = t2.constBegin(); it != t2.constEnd(); ++it)
+    {
+      if (!it.value().isEmpty() &&
+          (result.contains(it.key()) &&
+           overwriteExcludeTagKeys.contains(it.key(), caseSensitivity)))
+      {
+        result[it.key()] = it.value();
+      }
+    }
+  }
 
   return result;
 }
 
 void TagComparator::_overwriteRemainingTags(Tags& t1, Tags& t2, Tags& result,
-                                            const QStringList& overwriteExcludeTagKeys)
+                                            const QStringList& overwriteExcludeTagKeys,
+                                            bool caseSensitive)
 {
   LOG_TRACE("Overwriting remaining tags...");
   LOG_VART(t1);
@@ -772,17 +792,17 @@ void TagComparator::_overwriteRemainingTags(Tags& t1, Tags& t2, Tags& result,
       result[it2.key()] = it2.value();
     }
   }
-  LOG_VART(result);
+  //LOG_VART(result);
 
   // Add t1 tags overwriting any t2 tags in the process (except those in the optional exclude list).
   const Qt::CaseSensitivity caseSensitivity =
-    _caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive;
+    caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive;
   for (Tags::ConstIterator it1 = t1.constBegin(); it1 != t1.constEnd(); ++it1)
   {
-    LOG_VART(it1.key());
-    LOG_VART(it1.value());
-    LOG_VART(overwriteExcludeTagKeys.contains(it1.key(), caseSensitivity));
-    LOG_VART(result.contains(it1.key()));
+    //LOG_VART(it1.key());
+    //LOG_VART(it1.value());
+    //LOG_VART(overwriteExcludeTagKeys.contains(it1.key(), caseSensitivity));
+    //LOG_VART(result.contains(it1.key()));
     if (it1.value().isEmpty() == false &&
         (!result.contains(it1.key()) ||
          !overwriteExcludeTagKeys.contains(it1.key(), caseSensitivity)))
Clone this wiki locally